diff options
Diffstat (limited to 'Source/cmXMLSafe.cxx')
-rw-r--r-- | Source/cmXMLSafe.cxx | 102 |
1 files changed, 102 insertions, 0 deletions
diff --git a/Source/cmXMLSafe.cxx b/Source/cmXMLSafe.cxx new file mode 100644 index 000000000..72fdc3466 --- /dev/null +++ b/Source/cmXMLSafe.cxx @@ -0,0 +1,102 @@ +/*============================================================================ + 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 <cmsys/ios/iostream> +#include <cmsys/ios/sstream> + +#include <string.h> +#include <stdio.h> + +//---------------------------------------------------------------------------- +cmXMLSafe::cmXMLSafe(const char* s): + Data(s), + Size(static_cast<unsigned long>(strlen(s))), + DoQuotes(true) +{ +} + +//---------------------------------------------------------------------------- +cmXMLSafe::cmXMLSafe(cmsys_stl::string const& s): + Data(s.c_str()), + Size(static_cast<unsigned long>(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<unsigned char>(*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; +} |