openMSX
XMLEscape.hh
Go to the documentation of this file.
1 #ifndef XMLESCAPE_HH
2 #define XMLESCAPE_HH
3 
4 #include <string>
5 #include <string_view>
6 
7 // The following routines do the following substitutions:
8 // & -> &amp; must always be done
9 // < -> &lt; must always be done
10 // > -> &gt; always allowed, but must be done when it appears as ]]>
11 // ' -> &apos; always allowed, but must be done inside quoted attribute
12 // " -> &quot; always allowed, but must be done inside quoted attribute
13 // all chars less than 32 -> &#xnn;
14 // So to simplify things we always do these 5+32 substitutions.
15 
16 // This is a low-level version. It takes an input string and an output-functor.
17 // That functor is called (possibly) multiple times, each with a (small) chunk
18 // for the final output (chunk are either parts of the input or xml escape
19 // sequences).
20 template<typename Output>
21 inline void XMLEscape(std::string_view s, Output output)
22 {
23  auto normal = [&](auto f, auto l) {
24  // c++20 std::string_view(f, l);
25  return std::string_view(&*f, l - f);
26  };
27 
28  auto chunk = s.begin();
29  auto last = s.end();
30  auto it = chunk;
31  while (it != last) {
32  char c = *it;
33  if (auto uc = static_cast<unsigned char>(c); uc < 32) {
34  output(normal(chunk, it));
35  char buf[6] = {'&', '#', 'x', '0', '0', ';'};
36  auto hex = [](unsigned x) { return (x < 10) ? char(x + '0') : char(x - 10 + 'a'); };
37  buf[3] = hex(uc / 16);
38  buf[4] = hex(uc % 16);
39  output(std::string_view(buf, sizeof(buf)));
40  chunk = ++it;
41  } else if (c == '<') {
42  output(normal(chunk, it));
43  output("&lt;");
44  chunk = ++it;
45  } else if (c == '>') {
46  output(normal(chunk, it));
47  output("&gt;");
48  chunk = ++it;
49  } else if (c == '&') {
50  output(normal(chunk, it));
51  output("&amp;");
52  chunk = ++it;
53  } else if (c == '"') {
54  output(normal(chunk, it));
55  output("&quot;");
56  chunk = ++it;
57  } else if (c == '\'') {
58  output(normal(chunk, it));
59  output("&apos;");
60  chunk = ++it;
61  } else {
62  // no output yet
63  ++it;
64  }
65  }
66  output(normal(chunk, last));
67 }
68 
69 // Like above, but produces the output as a (single) std::string.
70 inline std::string XMLEscape(std::string_view s)
71 {
72  std::string result;
73  XMLEscape(s, [&](std::string_view chunk) { result += chunk; });
74  return result;
75 }
76 
77 #endif
void XMLEscape(std::string_view s, Output output)
Definition: XMLEscape.hh:21
constexpr KeyMatrixPosition x
Keyboard bindings.
Definition: Keyboard.cc:118