/*============================================================================ CMake - Cross Platform Makefile Generator Copyright 2000-2009 Kitware, Inc., Insight Software Consortium 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 "cmXMLSafe.h" #include "cm_utf8.h" #include #include #include #include //---------------------------------------------------------------------------- cmXMLSafe::cmXMLSafe(const char* s): Data(s), Size(static_cast(strlen(s))), DoQuotes(true) { } //---------------------------------------------------------------------------- cmXMLSafe::cmXMLSafe(cmsys_stl::string const& s): Data(s.c_str()), Size(static_cast(s.length())), DoQuotes(true) { } //---------------------------------------------------------------------------- cmXMLSafe& cmXMLSafe::Quotes(bool b) { this->DoQuotes = b; return *this; } //---------------------------------------------------------------------------- cmsys_stl::string cmXMLSafe::str() { cmsys_ios::ostringstream ss; ss << *this; return ss.str(); } //---------------------------------------------------------------------------- cmsys_ios::ostream& operator<<(cmsys_ios::ostream& os, cmXMLSafe const& self) { char const* first = self.Data; char const* last = self.Data + self.Size; while(first != last) { unsigned int ch; if(const char* next = cm_utf8_decode_character(first, last, &ch)) { // http://www.w3.org/TR/REC-xml/#NT-Char if((ch >= 0x20 && ch <= 0xD7FF) || (ch >= 0xE000 && ch <= 0xFFFD) || (ch >= 0x10000 && ch <= 0x10FFFF) || ch == 0x9 || ch == 0xA || ch == 0xD) { switch(ch) { // Escape XML control characters. case '&': os << "&"; break; case '<': os << "<"; break; case '>': os << ">"; break; case '"': os << (self.DoQuotes? """ : "\""); break; case '\'': os << (self.DoQuotes? "'" : "'"); break; case '\r': break; // Ignore CR // Print the UTF-8 character. default: os.write(first, next-first); break; } } else { // Use a human-readable hex value for this invalid character. char buf[16]; sprintf(buf, "%X", ch); os << "[NON-XML-CHAR-0x" << buf << "]"; } first = next; } else { ch = static_cast(*first++); // Use a human-readable hex value for this invalid byte. char buf[16]; sprintf(buf, "%X", ch); os << "[NON-UTF-8-BYTE-0x" << buf << "]"; } } return os; }