JsonWriter.cpp
Go to the documentation of this file.
1/*
2* This file is part of ArmarX.
3*
4* ArmarX is free software; you can redistribute it and/or modify
5* it under the terms of the GNU General Public License version 2 as
6* published by the Free Software Foundation.
7*
8* ArmarX is distributed in the hope that it will be useful, but
9* WITHOUT ANY WARRANTY; without even the implied warranty of
10* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11* GNU General Public License for more details.
12*
13* You should have received a copy of the GNU General Public License
14* along with this program. If not, see <http://www.gnu.org/licenses/>.
15*
16* @author Simon Ottenhaus (simon dot ottenhaus at kit dot edu)
17* @copyright http://www.gnu.org/licenses/gpl-2.0.txt
18* GNU General Public License
19*/
20
21#include "JsonWriter.h"
22
23#include <iomanip>
24
25#include <boost/regex.hpp>
26
28
29namespace armarx
30{
31 JsonWriter::JsonWriter(int indenting, const std::string& indentChars, bool jsStyleKeys) :
32 indenting(indenting), nesting(0), indentChars(indentChars), jsStyleKeys(jsStyleKeys)
33 {
34 }
35
36 void
38 {
39 beginValue();
40
41 stack.push(eEmptyObject);
42 ss << "{";
43 nesting++;
44 }
45
46 void
48 {
49 if (stack.size() == 0)
50 {
51 throw LocalException("Stack is empty");
52 }
53
54 if (stack.top() != eEmptyObject && stack.top() != eObject)
55 {
56 throw LocalException("Wrong type");
57 }
58
59 nesting--;
60 endArrayOrObject();
61 stack.pop();
62 ss << "}";
63 endValue();
64 }
65
66 void
67 JsonWriter::writeKey(const std::string& key)
68 {
69 beginKey();
70 if (jsStyleKeys && isId(key))
71 {
72 ss << key << (indenting == 2 ? ": " : ":");
73 }
74 else
75 {
76 ss << EscapeQuote(key) << (indenting == 2 ? ": " : ":");
77 }
78 endKey();
79 }
80
81 void
83 {
84 beginValue();
85 stack.push(eEmptyArray);
86 ss << "[";
87 nesting++;
88 }
89
90 void
92 {
93 if (stack.size() == 0)
94 {
95 throw LocalException("Stack is empty");
96 }
97
98 if (stack.top() != eEmptyArray && stack.top() != eArray)
99 {
100 throw LocalException("Wrong type");
101 }
102
103 nesting--;
104 endArrayOrObject();
105 stack.pop();
106 ss << "]";
107 endValue();
108 }
109
110 void
111 JsonWriter::writeRawValue(const std::string& value)
112 {
113 beginValue();
114 ss << value;
115 endValue();
116 }
117
118 std::string
120 {
121 return ss.str();
122 }
123
124 bool
125 JsonWriter::isId(const std::string& str)
126 {
127 boost::cmatch result;
128 return boost::regex_search(str.c_str(),
129 result,
130 boost::regex("^[_A-Za-z]\\w*$"),
131 boost::regex_constants::match_default);
132 }
133
134 std::string
135 JsonWriter::EscapeQuote(const std::string& str)
136 {
137 return "\"" + Escape(str) + "\"";
138 }
139
140 std::string
141 JsonWriter::Escape(const std::string& str)
142 {
143 std::ostringstream ss;
144
145 for (auto iter = str.cbegin(); iter != str.cend(); iter++)
146 {
147 switch (*iter)
148 {
149 case '\\':
150 ss << "\\\\";
151 break;
152
153 case '"':
154 ss << "\\\"";
155 break;
156
157 case '\b':
158 ss << "\\b";
159 break;
160
161 case '\f':
162 ss << "\\f";
163 break;
164
165 case '\n':
166 ss << "\\n";
167 break;
168
169 case '\r':
170 ss << "\\r";
171 break;
172
173 case '\t':
174 ss << "\\t";
175 break;
176
177 default:
178 if (IsControlChar(*iter))
179 {
180 ss << "\\u" << std::hex << std::uppercase << std::setfill('0')
181 << std::setw(4) << static_cast<int>(*iter);
182 }
183 else
184 {
185 ss << *iter;
186 }
187
188 break;
189 }
190 }
191
192 return ss.str();
193 }
194
195 void
196 JsonWriter::writeNewLine()
197 {
198 if (indenting == 2)
199 {
200 ss << "\n";
201
202 for (int i = 0; i < nesting; i++)
203 {
204 ss << indentChars;
205 }
206 }
207 }
208
209 void
210 JsonWriter::beginValue()
211 {
212 if (stack.size() == 0)
213 {
214 return;
215 }
216
217 if (stack.top() == eArray)
218 {
219 ss << (indenting == 1 ? ", " : ",");
220 }
221
222 if (stack.top() != eObjectKey)
223 {
224 writeNewLine();
225 }
226
227 if (stack.top() != eEmptyArray && stack.top() != eArray && stack.top() != eObjectKey)
228 {
229 throw LocalException("Wrong type");
230 }
231 }
232
233 void
234 JsonWriter::beginKey()
235 {
236 if (stack.size() == 0)
237 {
238 throw LocalException("Stack is empty");
239 }
240
241 if (stack.top() != eEmptyObject && stack.top() != eObject)
242 {
243 throw LocalException("Wrong type");
244 }
245
246 if (stack.top() == eObject)
247 {
248 ss << (indenting == 1 ? ", " : ",");
249 }
250
251 writeNewLine();
252 }
253
254 void
255 JsonWriter::endKey()
256 {
257 stack.pop();
258 stack.push(eObjectKey);
259 }
260
261 void
262 JsonWriter::endValue()
263 {
264 if (stack.size() == 0)
265 {
266 stack.push(eFinal);
267 }
268 else if (stack.top() == eEmptyArray)
269 {
270 stack.top() = eArray;
271 }
272 else if (stack.top() == eObjectKey)
273 {
274 stack.top() = eObject;
275 }
276 }
277
278 void
279 JsonWriter::endArrayOrObject()
280 {
281 if (stack.top() == eArray || stack.top() == eObject)
282 {
283 writeNewLine();
284 }
285 }
286} // namespace armarx
std::string str(const T &t)
bool isId(const std::string &str)
void writeKey(const std::string &key)
static std::string Escape(const std::string &str)
static bool IsControlChar(char c)
Definition JsonWriter.h:99
static std::string EscapeQuote(const std::string &str)
std::string toString()
void writeRawValue(const std::string &value)
JsonWriter(int indenting=0, const std::string &indentChars=" ", bool jsStyleKeys=false)
This file offers overloads of toIce() and fromIce() functions for STL container types.