33 |
33 |
34 std::string keyValueSeparator = " = "; |
34 std::string keyValueSeparator = " = "; |
35 std::string commentSeparatorForSections = " ; "; |
35 std::string commentSeparatorForSections = " ; "; |
36 std::string commentSeparatorForEntries = " ; "; |
36 std::string commentSeparatorForEntries = " ; "; |
37 std::string commentSeparatorStandalone = "; "; |
37 std::string commentSeparatorStandalone = "; "; |
|
38 |
|
39 bool hasContent = false; |
38 |
40 |
39 enum class TokenType { |
41 enum class TokenType { |
40 SectionName, |
42 SectionName, |
41 SectionTag, |
43 SectionTag, |
42 SectionComment, |
44 SectionComment, |
115 void endDocument() { |
117 void endDocument() { |
116 output.flush(); |
118 output.flush(); |
117 } |
119 } |
118 |
120 |
119 void startSection(const SectionStartEvent& event) { |
121 void startSection(const SectionStartEvent& event) { |
|
122 if (hasContent) output << std::endl; |
120 output << "[" << escape(TokenType::SectionName, event.name) << "]"; |
123 output << "[" << escape(TokenType::SectionName, event.name) << "]"; |
121 if (event.tag.size()) output << "[" << escape(TokenType::SectionTag, event.tag) << "]"; |
124 if (event.tag.size()) output << "[" << escape(TokenType::SectionTag, event.tag) << "]"; |
122 if (event.comment.size()) output << commentSeparatorForSections << escape(TokenType::SectionComment, event.comment); |
125 if (event.comment.size()) output << commentSeparatorForSections << escape(TokenType::SectionComment, event.comment); |
123 output << std::endl; |
126 output << std::endl; |
|
127 hasContent = true; |
124 } |
128 } |
125 |
129 |
126 void endSection() { |
130 void endSection() { |
127 output << std::endl; |
|
128 output.flush(); |
131 output.flush(); |
129 } |
132 } |
130 |
133 |
131 void entry(const EntryEvent& event) { |
134 void entry(const EntryEvent& event) { |
132 output << escape(TokenType::EntryKey, event.key); |
135 output << escape(TokenType::EntryKey, event.key); |
133 if (event.subKey.size()) output << "[" << escape(TokenType::EntrySubKey, event.subKey) << "]"; |
136 if (event.subKey.size()) output << "[" << escape(TokenType::EntrySubKey, event.subKey) << "]"; |
134 output << keyValueSeparator << escape(TokenType::EntryValue, event.value); |
137 output << keyValueSeparator << escape(TokenType::EntryValue, event.value); |
135 if (event.comment.size()) output << commentSeparatorForEntries << escape(TokenType::EntryComment, event.comment); |
138 if (event.comment.size()) output << commentSeparatorForEntries << escape(TokenType::EntryComment, event.comment); |
136 output << std::endl; |
139 output << std::endl; |
|
140 hasContent = true; |
137 } |
141 } |
138 |
142 |
139 void comment(const CommentEvent& event) { |
143 void comment(const CommentEvent& event) { |
140 output << commentSeparatorStandalone << escape(TokenType::StandaloneComment, event.comment); |
144 output << commentSeparatorStandalone << escape(TokenType::StandaloneComment, event.comment); |
|
145 output << std::endl; |
|
146 hasContent = true; |
141 } |
147 } |
142 |
148 |
143 void whitespace(const WhitespaceEvent& event) { |
149 void whitespace(const WhitespaceEvent& event) { |
144 for (wchar_t ch : event.whitespace) { |
150 for (wchar_t ch : event.whitespace) { |
145 if (ch == L' ') output << " "; |
151 if (ch == L' ') output << " "; |
146 else if (ch == L'\t') output << "\t"; |
152 else if (ch == L'\t') output << "\t"; |
147 else if (ch == L'\n') output << "\n"; |
153 else if (ch == L'\n') output << "\n"; |
148 else if (ch == L'\r'); // TODO: keep CR? |
154 else if (ch == L'\r'); // TODO: keep CR? |
149 else; // TODO: throw exception if whitespace contains unexpected data? (should not happen) |
155 else; // TODO: throw exception if whitespace contains unexpected data? (should not happen) |
150 } |
156 } |
|
157 hasContent = true; |
151 } |
158 } |
152 |
159 |
153 |
160 |
154 |
161 |
155 }; |
162 }; |