1 /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
2 file Copyright.txt or https://cmake.org/licensing for details. */
11 cmXMLSafe::cmXMLSafe(const char* s)
13 , Size(static_cast<unsigned long>(strlen(s)))
18 cmXMLSafe::cmXMLSafe(std::string const& s)
20 , Size(static_cast<unsigned long>(s.length()))
25 cmXMLSafe& cmXMLSafe::Quotes(bool b)
31 std::string cmXMLSafe::str() const
33 std::ostringstream ss;
38 std::ostream& operator<<(std::ostream& os, cmXMLSafe const& self)
40 char const* first = self.Data;
41 char const* last = self.Data + self.Size;
42 while (first != last) {
44 if (const char* next = cm_utf8_decode_character(first, last, &ch)) {
45 // http://www.w3.org/TR/REC-xml/#NT-Char
46 if ((ch >= 0x20 && ch <= 0xD7FF) || (ch >= 0xE000 && ch <= 0xFFFD) ||
47 (ch >= 0x10000 && ch <= 0x10FFFF) || ch == 0x9 || ch == 0xA ||
50 // Escape XML control characters.
61 os << (self.DoQuotes ? """ : "\"");
64 os << (self.DoQuotes ? "'" : "'");
68 // Print the UTF-8 character.
70 os.write(first, next - first);
74 // Use a human-readable hex value for this invalid character.
76 snprintf(buf, sizeof(buf), "%X", ch);
77 os << "[NON-XML-CHAR-0x" << buf << "]";
82 ch = static_cast<unsigned char>(*first++);
83 // Use a human-readable hex value for this invalid byte.
85 snprintf(buf, sizeof(buf), "%X", ch);
86 os << "[NON-UTF-8-BYTE-0x" << buf << "]";