resolve cyclic dependency with zstd
[platform/upstream/cmake.git] / Source / cmXMLSafe.cxx
1 /* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
2    file Copyright.txt or https://cmake.org/licensing for details.  */
3 #include "cmXMLSafe.h"
4
5 #include <cstdio>
6 #include <cstring>
7 #include <sstream>
8
9 #include "cm_utf8.h"
10
11 cmXMLSafe::cmXMLSafe(const char* s)
12   : Data(s)
13   , Size(static_cast<unsigned long>(strlen(s)))
14   , DoQuotes(true)
15 {
16 }
17
18 cmXMLSafe::cmXMLSafe(std::string const& s)
19   : Data(s.c_str())
20   , Size(static_cast<unsigned long>(s.length()))
21   , DoQuotes(true)
22 {
23 }
24
25 cmXMLSafe& cmXMLSafe::Quotes(bool b)
26 {
27   this->DoQuotes = b;
28   return *this;
29 }
30
31 std::string cmXMLSafe::str() const
32 {
33   std::ostringstream ss;
34   ss << *this;
35   return ss.str();
36 }
37
38 std::ostream& operator<<(std::ostream& os, cmXMLSafe const& self)
39 {
40   char const* first = self.Data;
41   char const* last = self.Data + self.Size;
42   while (first != last) {
43     unsigned int ch;
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 ||
48           ch == 0xD) {
49         switch (ch) {
50           // Escape XML control characters.
51           case '&':
52             os << "&amp;";
53             break;
54           case '<':
55             os << "&lt;";
56             break;
57           case '>':
58             os << "&gt;";
59             break;
60           case '"':
61             os << (self.DoQuotes ? "&quot;" : "\"");
62             break;
63           case '\'':
64             os << (self.DoQuotes ? "&apos;" : "'");
65             break;
66           case '\r':
67             break; // Ignore CR
68           // Print the UTF-8 character.
69           default:
70             os.write(first, next - first);
71             break;
72         }
73       } else {
74         // Use a human-readable hex value for this invalid character.
75         char buf[16];
76         snprintf(buf, sizeof(buf), "%X", ch);
77         os << "[NON-XML-CHAR-0x" << buf << "]";
78       }
79
80       first = next;
81     } else {
82       ch = static_cast<unsigned char>(*first++);
83       // Use a human-readable hex value for this invalid byte.
84       char buf[16];
85       snprintf(buf, sizeof(buf), "%X", ch);
86       os << "[NON-UTF-8-BYTE-0x" << buf << "]";
87     }
88   }
89   return os;
90 }