1 ////////////////////////////////////////////////////////////////////////////////
3 // Copyright 2006 - 2017, Paul Beckingham, Federico Hernandez.
5 // Permission is hereby granted, free of charge, to any person obtaining a copy
6 // of this software and associated documentation files (the "Software"), to deal
7 // in the Software without restriction, including without limitation the rights
8 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 // copies of the Software, and to permit persons to whom the Software is
10 // furnished to do so, subject to the following conditions:
12 // The above copyright notice and this permission notice shall be included
13 // in all copies or substantial portions of the Software.
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 // http://www.opensource.org/licenses/mit-license.php
25 ////////////////////////////////////////////////////////////////////////////////
33 const char *json_encode[] = {
34 "\x00", "\x01", "\x02", "\x03", "\x04", "\x05", "\x06", "\x07",
35 "\\b", "\\t", "\\n", "\x0b", "\\f", "\\r", "\x0e", "\x0f",
36 "\x10", "\x11", "\x12", "\x13", "\x14", "\x15", "\x16", "\x17",
37 "\x18", "\x19", "\x1a", "\x1b", "\x1c", "\x1d", "\x1e", "\x1f",
38 "\x20", "\x21", "\\\"", "\x23", "\x24", "\x25", "\x26", "\x27",
39 "\x28", "\x29", "\x2a", "\x2b", "\x2c", "\x2d", "\x2e", "\\/",
40 "\x30", "\x31", "\x32", "\x33", "\x34", "\x35", "\x36", "\x37",
41 "\x38", "\x39", "\x3a", "\x3b", "\x3c", "\x3d", "\x3e", "\x3f",
42 "\x40", "\x41", "\x42", "\x43", "\x44", "\x45", "\x46", "\x47",
43 "\x48", "\x49", "\x4a", "\x4b", "\x4c", "\x4d", "\x4e", "\x4f",
44 "\x50", "\x51", "\x52", "\x53", "\x54", "\x55", "\x56", "\x57",
45 "\x58", "\x59", "\x5a", "\x5b", "\\\\", "\x5d", "\x5e", "\x5f",
46 "\x60", "\x61", "\x62", "\x63", "\x64", "\x65", "\x66", "\x67",
47 "\x68", "\x69", "\x6a", "\x6b", "\x6c", "\x6d", "\x6e", "\x6f",
48 "\x70", "\x71", "\x72", "\x73", "\x74", "\x75", "\x76", "\x77",
49 "\x78", "\x79", "\x7a", "\x7b", "\x7c", "\x7d", "\x7e", "\x7f",
50 "\x80", "\x81", "\x82", "\x83", "\x84", "\x85", "\x86", "\x87",
51 "\x88", "\x89", "\x8a", "\x8b", "\x8c", "\x8d", "\x8e", "\x8f",
52 "\x90", "\x91", "\x92", "\x93", "\x94", "\x95", "\x96", "\x97",
53 "\x98", "\x99", "\x9a", "\x9b", "\x9c", "\x9d", "\x9e", "\x9f",
54 "\xa0", "\xa1", "\xa2", "\xa3", "\xa4", "\xa5", "\xa6", "\xa7",
55 "\xa8", "\xa9", "\xaa", "\xab", "\xac", "\xad", "\xae", "\xaf",
56 "\xb0", "\xb1", "\xb2", "\xb3", "\xb4", "\xb5", "\xb6", "\xb7",
57 "\xb8", "\xb9", "\xba", "\xbb", "\xbc", "\xbd", "\xbe", "\xbf",
58 "\xc0", "\xc1", "\xc2", "\xc3", "\xc4", "\xc5", "\xc6", "\xc7",
59 "\xc8", "\xc9", "\xca", "\xcb", "\xcc", "\xcd", "\xce", "\xcf",
60 "\xd0", "\xd1", "\xd2", "\xd3", "\xd4", "\xd5", "\xd6", "\xd7",
61 "\xd8", "\xd9", "\xda", "\xdb", "\xdc", "\xdd", "\xde", "\xdf",
62 "\xe0", "\xe1", "\xe2", "\xe3", "\xe4", "\xe5", "\xe6", "\xe7",
63 "\xe8", "\xe9", "\xea", "\xeb", "\xec", "\xed", "\xee", "\xef",
64 "\xf0", "\xf1", "\xf2", "\xf3", "\xf4", "\xf5", "\xf6", "\xf7",
65 "\xf8", "\xf9", "\xfa", "\xfb", "\xfc", "\xfd", "\xfe", "\xff"
68 ////////////////////////////////////////////////////////////////////////////////
69 json::value* json::value::parse (Pig& pig)
72 if ((v = json::object::parse (pig)) ||
73 (v = json::array::parse (pig)) ||
74 (v = json::string::parse (pig)) ||
75 (v = json::number::parse (pig)) ||
76 (v = json::literal::parse (pig)))
82 ////////////////////////////////////////////////////////////////////////////////
83 json::jtype json::value::type ()
88 ////////////////////////////////////////////////////////////////////////////////
89 std::string json::value::dump () const
94 ////////////////////////////////////////////////////////////////////////////////
95 json::string::string (const std::string& other)
100 ////////////////////////////////////////////////////////////////////////////////
101 json::string* json::string::parse (Pig& pig)
104 if (pig.getQuoted ('"', value))
106 json::string* s = new json::string ();
114 ////////////////////////////////////////////////////////////////////////////////
115 json::jtype json::string::type ()
117 return json::j_string;
120 ////////////////////////////////////////////////////////////////////////////////
121 std::string json::string::dump () const
123 return std::string ("\"") + _data + '"';
126 ////////////////////////////////////////////////////////////////////////////////
127 json::number* json::number::parse (Pig& pig)
130 if (pig.getNumber (d))
132 json::number* s = new json::number ();
140 ////////////////////////////////////////////////////////////////////////////////
141 json::jtype json::number::type ()
143 return json::j_number;
146 ////////////////////////////////////////////////////////////////////////////////
147 std::string json::number::dump () const
149 return format (_dvalue);
152 ////////////////////////////////////////////////////////////////////////////////
153 json::number::operator double () const
158 ////////////////////////////////////////////////////////////////////////////////
159 json::literal* json::literal::parse (Pig& pig)
161 if (pig.skipLiteral ("null"))
163 json::literal* s = new json::literal ();
164 s->_lvalue = nullvalue;
167 else if (pig.skipLiteral ("false"))
169 json::literal* s = new json::literal ();
170 s->_lvalue = falsevalue;
173 else if (pig.skipLiteral ("true"))
175 json::literal* s = new json::literal ();
176 s->_lvalue = truevalue;
183 ////////////////////////////////////////////////////////////////////////////////
184 json::jtype json::literal::type ()
186 return json::j_literal;
189 ////////////////////////////////////////////////////////////////////////////////
190 std::string json::literal::dump () const
192 if (_lvalue == nullvalue) return "null";
193 else if (_lvalue == falsevalue) return "false";
197 ////////////////////////////////////////////////////////////////////////////////
198 json::array::~array ()
200 for (auto& i : _data)
204 ////////////////////////////////////////////////////////////////////////////////
205 json::array* json::array::parse (Pig& pig)
207 auto checkpoint = pig.cursor ();
214 json::array* arr = new json::array ();
217 if ((value = json::value::parse (pig)))
219 arr->_data.push_back (value);
220 value = NULL; // Not a leak. Looks like a leak.
222 while (pig.skip (','))
226 if ((value = json::value::parse (pig)))
228 arr->_data.push_back (value);
234 throw format ("Error: missing value after ',' at position {1}", (int) pig.cursor ());
242 throw format ("Error: missing ']' at position {1}", (int) pig.cursor ());
247 pig.restoreTo (checkpoint);
251 ////////////////////////////////////////////////////////////////////////////////
252 json::jtype json::array::type ()
254 return json::j_array;
257 ////////////////////////////////////////////////////////////////////////////////
258 std::string json::array::dump () const
263 for (auto i = _data.begin (); i != _data.end (); ++i)
265 if (i != _data.begin ())
268 output += (*i)->dump ();
275 ////////////////////////////////////////////////////////////////////////////////
276 json::object::~object ()
278 for (auto& i : _data)
282 ////////////////////////////////////////////////////////////////////////////////
283 json::object* json::object::parse (Pig& pig)
285 auto checkpoint = pig.cursor ();
292 json::object* obj = new json::object ();
296 if (json::object::parse_pair (pig, name, value))
298 obj->_data.insert (std::pair <std::string, json::value*> (name, value));
299 value = NULL; // Not a leak. Looks like a leak.
302 while (pig.skip (','))
306 if (json::object::parse_pair (pig, name, value))
308 obj->_data.insert (std::pair <std::string, json::value*> (name, value));
314 throw format ("Error: missing value after ',' at position {1}", (int) pig.cursor ());
322 throw format ("Error: missing '}' at position {1}", (int) pig.cursor ());
327 pig.restoreTo (checkpoint);
331 ////////////////////////////////////////////////////////////////////////////////
332 bool json::object::parse_pair (
337 auto checkpoint = pig.cursor ();
339 if (pig.getQuoted ('"', name))
345 if ((val = json::value::parse (pig)))
348 throw format ("Error: missing value at position {1}", (int) pig.cursor ());
351 throw format ("Error: missing ':' at position {1}", (int) pig.cursor ());
354 pig.restoreTo (checkpoint);
358 ////////////////////////////////////////////////////////////////////////////////
359 json::jtype json::object::type ()
361 return json::j_object;
364 ////////////////////////////////////////////////////////////////////////////////
365 std::string json::object::dump () const
370 for (auto i = _data.begin (); i != _data.end (); ++i)
372 if (i != _data.begin ())
375 output += '"' + i->first + "\":";
376 output += i->second->dump ();
383 ////////////////////////////////////////////////////////////////////////////////
384 json::value* json::parse (const std::string& input)
386 json::value* root = NULL;
391 if (n.peek () == '{') root = json::object::parse (n);
392 else if (n.peek () == '[') root = json::array::parse (n);
394 throw format ("Error: expected '{' or '[' at position {1}", (int) n.cursor ());
396 // Check for end condition.
401 throw format ("Error: extra characters found at position {1}", (int) n.cursor ());
407 ////////////////////////////////////////////////////////////////////////////////
408 std::string json::encode (const std::string& input)
411 output.reserve ((input.size () * 6) / 5); // 20% increase.
413 auto last = input.begin ();
414 for (auto i = input.begin (); i != input.end (); ++i)
418 // Simple translations.
427 output.append (last, i);
428 output += json_encode[(unsigned char)(*i)];
435 output.append (last, input.end ());
440 ////////////////////////////////////////////////////////////////////////////////
441 std::string json::decode (const std::string& input)
444 output.reserve (input.size ()); // Same size.
448 while (pos < input.length ())
450 if (input[pos] == '\\')
455 // Simple translations.
456 case '"': output += '"'; break;
457 case '\\': output += '\\'; break;
458 case '/': output += '/'; break;
459 case 'b': output += '\b'; break;
460 case 'f': output += '\f'; break;
461 case 'n': output += '\n'; break;
462 case 'r': output += '\r'; break;
463 case 't': output += '\t'; break;
465 // Compose a UTF8 unicode character.
467 output += utf8_character (utf8_codepoint (input.substr (++pos)));
471 // If it is an unrecognized sequence, do nothing.
474 output += input[pos];
481 size_t next_backslash = input.find ('\\', pos);
482 output.append (input, pos, next_backslash - pos);
483 pos = next_backslash;
490 ////////////////////////////////////////////////////////////////////////////////