/*============================================================================ CMake - Cross Platform Makefile Generator Copyright 2012 Kitware, Inc. Distributed under the OSI-approved BSD License (the "License"); see accompanying file Copyright.txt for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the License for more information. ============================================================================*/ #include "cmWIXSourceWriter.h" #include #include cmWIXSourceWriter::cmWIXSourceWriter(cmCPackLog* logger, const std::string& filename, bool isIncludeFile): Logger(logger), file(filename.c_str()), state(DEFAULT), sourceFilename(filename) { WriteXMLDeclaration(); if(isIncludeFile) { BeginElement("Include"); } else { BeginElement("Wix"); } AddAttribute("xmlns", "http://schemas.microsoft.com/wix/2006/wi"); } cmWIXSourceWriter::~cmWIXSourceWriter() { if(elements.size() > 1) { cmCPackLogger(cmCPackLog::LOG_ERROR, elements.size() - 1 << " WiX elements were still open when closing '" << sourceFilename << "'" << std::endl); return; } EndElement(elements.back()); } void cmWIXSourceWriter::BeginElement(const std::string& name) { if(state == BEGIN) { file << ">"; } file << "\n"; Indent(elements.size()); file << "<" << name; elements.push_back(name); state = BEGIN; } void cmWIXSourceWriter::EndElement(std::string const& name) { if(elements.empty()) { cmCPackLogger(cmCPackLog::LOG_ERROR, "can not end WiX element with no open elements in '" << sourceFilename << "'" << std::endl); return; } if(elements.back() != name) { cmCPackLogger(cmCPackLog::LOG_ERROR, "WiX element <" << elements.back() << "> can not be closed by in '" << sourceFilename << "'" << std::endl); return; } if(state == DEFAULT) { file << "\n"; Indent(elements.size()-1); file << ""; } else { file << "/>"; } elements.pop_back(); state = DEFAULT; } void cmWIXSourceWriter::AddProcessingInstruction( const std::string& target, const std::string& content) { if(state == BEGIN) { file << ">"; } file << "\n"; Indent(elements.size()); file << ""; state = DEFAULT; } void cmWIXSourceWriter::AddAttribute( const std::string& key, const std::string& value) { std::string utf8 = WindowsCodepageToUtf8(value); file << " " << key << "=\"" << EscapeAttributeValue(utf8) << '"'; } void cmWIXSourceWriter::AddAttributeUnlessEmpty( const std::string& key, const std::string& value) { if(value.size()) { AddAttribute(key, value); } } std::string cmWIXSourceWriter::WindowsCodepageToUtf8(const std::string& value) { if(value.empty()) { return std::string(); } int characterCount = MultiByteToWideChar( CP_ACP, 0, value.c_str(), static_cast(value.size()), 0, 0); if(characterCount == 0) { return std::string(); } std::vector utf16(characterCount); MultiByteToWideChar( CP_ACP, 0, value.c_str(), static_cast(value.size()), &utf16[0], static_cast(utf16.size())); int utf8ByteCount = WideCharToMultiByte( CP_UTF8, 0, &utf16[0], static_cast(utf16.size()), 0, 0, 0, 0); if(utf8ByteCount == 0) { return std::string(); } std::vector utf8(utf8ByteCount); WideCharToMultiByte(CP_UTF8, 0, &utf16[0], static_cast(utf16.size()), &utf8[0], static_cast(utf8.size()), 0, 0); return std::string(&utf8[0], utf8.size()); } void cmWIXSourceWriter::WriteXMLDeclaration() { file << "" << std::endl; } void cmWIXSourceWriter::Indent(size_t count) { for(size_t i = 0; i < count; ++i) { file << " "; } } std::string cmWIXSourceWriter::EscapeAttributeValue( const std::string& value) { std::string result; result.reserve(value.size()); char c = 0; for(size_t i = 0 ; i < value.size(); ++i) { c = value[i]; switch(c) { case '<': result += "<"; break; case '>': result += ">"; break; case '&': result +="&"; break; case '"': result += """; break; default: result += c; break; } } return result; }