1
2
3
4
5
6 #include <soulng/lexer/XmlParsingLog.hpp>
7 #include <soulng/util/Unicode.hpp>
8 #include <algorithm>
9 #include <sstream>
10 #include <cctype>
11
12 namespace soulng { namespace lexer {
13
14 using namespace soulng::unicode;
15
16 std::u32string XmlHexEscape(char32_t c)
17 {
18 std::stringstream s;
19 s << "&#x" << std::hex << (unsigned int)c << ";";
20 return ToUtf32(s.str());
21 }
22
23 std::u32string XmlCharStr(char32_t c)
24 {
25 switch (c)
26 {
27 case '&': return U"&";
28 case '<': return U"<";
29 case '>': return U">";
30 case '\a': return U"\\a";
31 case '\b': return U"\\b";
32 case '\f': return U"\\f";
33 case '\n': return U"\\n";
34 case '\r': return U"\\r";
35 case '\t': return U"\\t";
36 case '\v': return U"\\v";
37 default:
38 {
39 if (((int)c >= 32 && (int)c <= 126))
40 {
41 return std::u32string(1, c);
42 }
43 else
44 {
45 return XmlHexEscape(c);
46 }
47 }
48 }
49 return std::u32string();
50 }
51
52 std::u32string XmlEscape(const std::u32string& s)
53 {
54 std::u32string result;
55 result.reserve(2 * s.length());
56 std::u32string::const_iterator e = s.end();
57 for (std::u32string::const_iterator i = s.begin(); i != e; ++i)
58 {
59 result.append(XmlCharStr(*i));
60 }
61 return result;
62 }
63
64 XmlParsingLog::XmlParsingLog(std::ostream& stream_) : ParsingLog(), formatter(stream_)
65 {
66 formatter.SetIndentSize(1);
67 }
68
69 XmlParsingLog::XmlParsingLog(std::ostream& stream_, int maxLineLength_) : ParsingLog(maxLineLength_), formatter(stream_)
70 {
71 formatter.SetIndentSize(1);
72 }
73
74 void XmlParsingLog::IncIndent()
75 {
76 formatter.IncIndent();
77 }
78
79 void XmlParsingLog::DecIndent()
80 {
81 formatter.DecIndent();
82 }
83
84 void XmlParsingLog::WriteBeginRule(const std::u32string& ruleName)
85 {
86 Write(U"<" + ruleName + U">");
87 }
88
89 void XmlParsingLog::WriteEndRule(const std::u32string& ruleName)
90 {
91 Write(U"</" + ruleName + U">");
92 }
93
94 void XmlParsingLog::WriteTry(const std::u32string& s)
95 {
96 WriteElement(U"try", s);
97 }
98
99 void XmlParsingLog::WriteSuccess(const std::u32string& match)
100 {
101 WriteElement(U"success", match);
102 }
103
104 void XmlParsingLog::WriteFail()
105 {
106 Write(U"<fail/>");
107 }
108
109 void XmlParsingLog::WriteElement(const std::u32string& elementName, const std::u32string& elementContent)
110 {
111 std::u32string converted = XmlEscape(elementContent);
112 int convertedLength = static_cast<int>(converted.length());
113 int lineLength = 2 * static_cast<int>(elementName.length()) + 5 + convertedLength;
114 std::u32string s = converted;
115 if (lineLength > MaxLineLength())
116 {
117 lineLength += 3;
118 s = converted.substr(0, std::max(0, convertedLength - (lineLength - MaxLineLength()))) + U"...";
119 }
120 Write(U"<" + elementName + U">" + s + U"</" + elementName + U">");
121 }
122
123 void XmlParsingLog::Write(const std::u32string& s)
124 {
125 formatter.WriteLine(ToUtf8(s));
126 }
127
128 } }