25 static double json_epsilon = std::numeric_limits<double>::epsilon();
43 std::string getValidatedUTF8String(
const std::string &src) {
45 utf8::replace_invalid(src.begin(), src.end(), back_inserter(out));
49 std::string itos(
int i)
56 void SkipWhiteSpace(std::istream &in)
62 }
while ((c >= 0) && isspace(c));
67 void WriteEscapedString(
const std::string &s, std::ostream &out,
bool enclosingQuotes =
true)
72 for (
unsigned i = 0; i < s.length(); ++i)
74 if (s[i] >= 0x0000 && s[i] <= 0x001f)
78 char temphex[5] = {0};
97 sprintf(temphex,
"%04x", s[i]);
98 out<<std::string(temphex);
120 bool isNumberStart(
int ch) {
121 if (ch ==
'-' || isdigit(ch))
126 bool isNullStart(
int ch) {
130 bool isStringStart(
int ch) {
134 bool isBooleanStart(
int ch) {
135 return (ch ==
't' || ch ==
'f');
138 bool isArrayStart(
int ch) {
142 bool isObjectStart(
int ch) {
155 bool isValidJsonNumber(
const std::string &s) {
156 unsigned len = s.length();
162 unsigned start = (s[0] ==
'-') ? 1 : 0;
163 if (!isdigit(s[start]))
166 if (start + 1 == len)
169 if (s[start] ==
'0' && isdigit(s[start + 1]))
172 for (
unsigned i = start + 1; i < len; ++i) {
187 if (s[i + 1] ==
'+' || s[i + 1] ==
'-') {
201 Value* ReadNumberValue(std::istream &in) {
202 Value *toReturn = NULL;
203 std::string toParse =
"";
205 bool isDouble =
false;
213 if (isdigit(ch) || ch ==
'+' || ch ==
'-')
216 if (ch ==
'.' || ch ==
'e' || ch ==
'E') {
231 if (!isValidJsonNumber(toParse))
232 throw JSONException(
"Invalid JSON number: \"" + toParse +
"\". Unable to parse");
234 std::stringstream stream(toParse);
236 Real *r =
new Real();
238 toReturn =
dynamic_cast<Value*
>(r);
241 Integer *i =
new Integer();
243 toReturn =
dynamic_cast<Value*
>(i);
245 assert(toReturn != NULL);
249 void ReadJSONValue(std::istream &in,
JSON &j,
bool topLevel =
false) {
251 JSON_Utility::SkipWhiteSpace(in);
258 if (isObjectStart(ch))
259 j.
val =
new Object();
261 if (isArrayStart(ch))
265 if (topLevel && j.
val == NULL)
266 throw JSONException(
"JSON::read() - Expected top level JSON to be an Object OR Array");
268 if (isStringStart(ch))
269 j.
val =
new String();
271 if (isBooleanStart(ch))
272 j.
val =
new Boolean();
281 if (isNumberStart(ch))
282 j.
val = JSON_Utility::ReadNumberValue(in);
284 throw JSONException(
"Illegal JSON value. Cannot start with : " + std::string(1,
char(ch)));
298 inline int32_t hexdigit_to_num(
char ch) {
299 if (ch >=
'0' && ch <=
'9')
300 return uint32_t(ch -
'0');
302 if (ch >=
'A' && ch <=
'F')
303 return uint32_t(ch -
'A' + 10);
304 throw JSONException(
"Invalid Hex digit in unicode escape \\uxxxx: " + std::string(1,ch));
307 inline int32_t string4_to_hex(
char str[]) {
309 return ( (hexdigit_to_num(str[0]) << 12) +
310 (hexdigit_to_num(str[1]) << 8) +
311 (hexdigit_to_num(str[2]) << 4) +
312 (hexdigit_to_num(str[3])) );
322 std::string parseUtf8JsonString(
const std::string &inp) {
323 std::string out =
"";
326 size_t inplength = inp.length();
328 for (
unsigned i = 0; i < inplength; i++) {
329 if (inp[i] !=
'\\') {
333 if ( (i + 1) >= inplength)
337 int32_t first16bit, second16bit;
340 case '"': out +=
'"';
break;
341 case '\\': out +=
'\\';
break;
342 case '/': out +=
'/';
break;
343 case 'b': out +=
'\b';
break;
344 case 'f': out +=
'\f';
break;
345 case 'n': out +=
'\n';
break;
346 case 'r': out +=
'\r';
break;
347 case 't': out +=
'\t';
break;
350 if (i + 4 >= inplength)
351 throw JSONException(
"Expected exactly 4 hex digits after \\u");
352 copy(inp.begin() + i + 1, inp.begin() + i + 1 + 5, hex);
354 first16bit = string4_to_hex(hex);
355 codepoint = first16bit;
356 if (0xD800 <= first16bit && first16bit <= 0xDBFF) {
360 if ( (i + 6) >= inplength || inp[i + 1] !=
'\\' || inp[i + 2] !=
'u')
361 throw JSONException(
"Missing surrogate pair in unicode sequence");
363 copy(inp.begin() + i + 1, inp.begin() + i + 1 + 5, hex);
365 second16bit = string4_to_hex(hex);
367 if (0xDC00 <= second16bit && second16bit <= 0xDFFF) {
369 codepoint = ((first16bit - 0xD800) << 10) + (second16bit - 0xDC00) + 0x10000;
373 throw JSONException(
"Invalid second 16 bit value in surrogate pair: first 16 bit = " + JSON_Utility::itos(first16bit) +
" and second 16 bit = " + JSON_Utility::itos(second16bit));
377 utf8::append(codepoint, back_inserter(out));
379 catch(utf8::invalid_code_point &e) {
380 throw JSONException(
"Invalid UTF-8 code point found in text. Value = " + itos(codepoint) +
". Location = " + inp +
"\nInternal message = " + e.what());
384 throw JSONException(
"Illegal escape sequence:" + std::string(1, inp[i]));
388 return getValidatedUTF8String(out);
391 std::string ReadString(std::istream &in) {
392 std::string out =
"";
399 if (in.eof() || in.fail())
401 if (ch ==
'"' && prev !=
'\\')
404 prev = (prev ==
'\\') ? 0 : ch;
406 return parseUtf8JsonString(str);
410 void String::write(std::ostream &out)
const {
411 JSON_Utility::WriteEscapedString(this->
val, out,
true);
414 void Object::write(std::ostream &out)
const {
416 bool firstElem =
true;
418 for (std::map<std::string, JSON>::const_iterator it =
val.begin(); it !=
val.end(); ++it, firstElem =
false) {
421 JSON_Utility::WriteEscapedString((*it).first, out,
true);
423 (*it).second.write(out);
428 void Array::write(std::ostream &out)
const {
430 bool firstElem =
true;
431 for (
unsigned i = 0; i <
val.size(); ++i, firstElem =
false) {
439 const JSON& Array::jsonAtIndex(
size_t i)
const {
440 if (
val.size() == 0u || i >=
val.size())
441 throw JSONException(
"Illegal: Out of bound JSON_ARRAY access");
446 const JSON& Object::jsonAtKey(
const std::string &s)
const {
447 std::map<std::string, JSON>::const_iterator it = this->
val.find(s);
449 throw JSONException(
"Cannot add new key to a constant JSON_OBJECT");
453 JSON& Object::jsonAtKey(
const std::string &s) {
458 if (this->
type() == JSON_UNDEFINED) {
459 throw JSONException(
"Cannot call write() method on uninitialized json object");
461 out.precision(std::numeric_limits<double>::digits10);
467 std::stringstream inp(jstr);
472 if (this->
type() != JSON_OBJECT)
473 throw JSONException(
"Cannot use string to index value of a non-JSON_OBJECT using [] operator");
477 const Object *o =
static_cast<Object*
>(
val);
478 return o->jsonAtKey(s);
483 if (this->
type() != JSON_OBJECT)
484 throw JSONException(
"Cannot use string to index value of a non-JSON_OBJECT using [] operator");
488 Object *o =
static_cast<Object*
>(
val);
489 return o->jsonAtKey(s);
502 if (this->
type() != JSON_ARRAY)
503 throw JSONException(
"Cannot use integer to index value of non-JSON_ARRAY using [] operator");
504 Array *a =
static_cast<Array*
>(
val);
505 return a->jsonAtIndex(indx);
509 if (this->
type() == JSON_ARRAY) {
510 return (*
this)[size_t(j)];
512 if (this->
type() == JSON_OBJECT) {
513 if (j.
type() != JSON_STRING)
514 throw JSONException(
"Cannot use a non-string value to index JSON_OBJECT using []");
516 String *ptr =
static_cast<String*
>(j.
val);
517 return (*
this)[ptr->val];
519 throw JSONException(
"Only JSON_OBJECT and JSON_ARRAY can be indexed using []");
523 if (this->
type() == JSON_ARRAY) {
524 return (*
this)[size_t(j)];
526 if (this->
type() == JSON_OBJECT) {
527 if (j.
type() != JSON_STRING)
528 throw JSONException(
"Cannot use a non-string value to index JSON_OBJECT using []");
530 String *ptr =
static_cast<String*
>(j.
val);
531 return (*
this)[ptr->val];
533 throw JSONException(
"Only JSON_OBJECT and JSON_ARRAY can be indexed using []");
548 if (rhs.
type() != JSON_UNDEFINED)
549 val = rhs.
val->returnMyNewCopy();
557 case JSON_ARRAY:
val =
new Array();
break;
558 case JSON_OBJECT:
val =
new Object();
break;
559 case JSON_INTEGER:
val =
new Integer();
break;
560 case JSON_REAL:
val =
new Real();
break;
561 case JSON_STRING:
val =
new String();
break;
562 case JSON_BOOLEAN:
val =
new Boolean();
break;
563 case JSON_NULL:
val =
new Null();
break;
564 default:
throw JSONException(
"Illegal JSONValue value for JSON initialization");
575 if (rhs.
type() != JSON_UNDEFINED)
576 val = rhs.
val->returnMyNewCopy();
595 val =
new Boolean(x);
616 if (t != JSON_ARRAY && t != JSON_OBJECT && t != JSON_STRING)
617 throw JSONException(
"size()/length() can only be called for JSON_ARRAY/JSON_OBJECT/JSON_STRING");
618 if (t == JSON_ARRAY) {
619 Array *tmp =
static_cast<Array*
>(this->
val);
620 return tmp->val.size();
623 if (t == JSON_OBJECT) {
624 Object *tmp =
static_cast<Object*
>(this->
val);
625 return tmp->val.size();
628 String *tmp =
static_cast<String*
>(this->
val);
629 return tmp->val.size();
633 if (this->
type() != JSON_ARRAY)
635 Array *tmp =
static_cast<Array*
>(this->
val);
641 if (onlyTopLevel && this->
type() != JSON_OBJECT && this->
type() != JSON_ARRAY)
642 throw JSONException(
"Only a JSON_OBJECT/JSON_ARRAY can call toString() with onlyTopLevel flag set to true");
643 std::stringstream in;
649 if (this->
type() != JSON_ARRAY)
650 throw JSONException(
"Illegal call to has(size_t) for non JSON_ARRAY object");
651 size_t size = ((Array*)(this->
val))->
val.size();
652 return (indx < size);
656 if (this->
type() != JSON_OBJECT)
657 throw JSONException(
"Illegal call to has(size_t) for non JSON_OBJECT object");
658 return (((Object*)(this->
val))->
val.count(key) > 0u);
662 return has(std::string(x));
667 switch(this->
type()) {
668 case JSON_ARRAY:
return has((
const size_t)j);
670 if (j.type() != JSON_STRING)
671 throw JSONException(
"For a JSON_OBJECT, has(JSON &j) requires j to be JSON_STRING");
672 return has( ((String*)(j.val))->val);
674 default:
throw JSONException(
"Illegal json object as input to has(const JSON &j)");
679 JSON_Utility::ReadJSONValue(in, *
this,
false);
683 if (this->
type() != JSON_ARRAY)
684 throw JSONException(
"erase(size_t) can only be called for a JSON_ARRAY");
685 (
static_cast<Array*
>(this->
val))->erase(indx);
689 if (this->
type() != JSON_OBJECT)
690 throw JSONException(
"erase(string) can only be called for a JSON_OBJECT");
691 (
static_cast<Object*
>(this->
val))->erase(indx);
694 void String::read(std::istream &in) {
695 val = JSON_Utility::ReadString(in);
698 void Boolean::read(std::istream &in) {
712 in.read(&str[1], size);
713 fail = (in.gcount() ==
size) ?
false :
true;
714 if (!fail && size == 3u && (strcmp(str,
"true") == 0))
717 if (!fail && size == 4u && (strcmp(str,
"false") == 0))
723 throw JSONException(
"Invalid Boolean value, expected exactly one of : 'true' or 'false'");
726 void Null::read(std::istream &in) {
729 if (in.gcount() !=4 || (strcmp(str,
"null") != 0))
730 throw JSONException(
"Invalid JSON null, expected exactly: null");
733 void Object::read(std::istream &in) {
736 JSON_Utility::SkipWhiteSpace(in);
740 bool firstKey =
true;
742 JSON_Utility::SkipWhiteSpace(in);
744 if (in.eof() || in.fail())
745 throw JSONException(
"Unexpected EOF while parsing object. ch = " + std::string(1, ch));
752 if (!firstKey && ch !=
',')
753 throw JSONException(
"Expected , while parsing object. Got : " + std::string(1, ch));
756 JSON_Utility::SkipWhiteSpace(in);
760 if (!JSON_Utility::isStringStart(ch))
761 throw JSONException(
"Expected start of a valid object key (string) at this location");
766 std::string key = JSON_Utility::ReadString(in);
767 JSON_Utility::SkipWhiteSpace(in);
770 throw JSONException(
"Expected :, got : " + std::string(1, ch));
771 JSON_Utility::SkipWhiteSpace(in);
772 JSON_Utility::ReadJSONValue(in,
val[key],
false);
777 void Array::read(std::istream &in) {
780 JSON_Utility::SkipWhiteSpace(in);
784 bool firstKey =
true;
786 JSON_Utility::SkipWhiteSpace(in);
788 if (in.eof() || in.fail())
795 if (!firstKey && ch !=
',')
796 throw JSONException(
"Expected ,(comma) GOT: " + std::string(1, ch));
799 JSON_Utility::SkipWhiteSpace(in);
804 JSON_Utility::SkipWhiteSpace(in);
806 val.push_back(tmpValue);
807 JSON_Utility::ReadJSONValue(in,
val[
val.size() - 1u],
false);
812 void Object::erase(
const std::string &key) {
813 if (
val.erase(key) == 0)
814 throw JSONException(
"Cannot erase non-existent key from a JSON_OBJECT. Key supplied = " + key);
817 void Array::erase(
const size_t &indx) {
818 if (indx >=
val.size())
819 throw JSONException(
"Cannot erase out of bound element in a JSON_ARRAY. indx supplied = " + boost::lexical_cast<std::string>(indx));
820 val.erase(
val.begin() + indx);
823 bool Integer::isEqual(
const Value *other)
const {
824 const Integer *p =
dynamic_cast<const Integer*
>(other);
825 return (p != NULL && this->
val == p->val);
828 bool Real::isEqual(
const Value* other)
const {
829 const Real *p =
dynamic_cast<const Real*
>(other);
838 double diff = fabs(this->
val - p->val);
847 double absA = fabs(this->
val);
848 double absB = fabs(p->val);
849 double largest = (absA > absB) ? absA : absB;
852 return diff <= (largest * eps);
855 bool String::isEqual(
const Value* other)
const {
856 const String *p =
dynamic_cast<const String*
>(other);
857 return (p != NULL && this->
val == p->val);
860 bool Boolean::isEqual(
const Value* other)
const {
861 const Boolean *p =
dynamic_cast<const Boolean*
>(other);
862 return (p != NULL && this->
val == p->val);
865 bool Null::isEqual(
const Value* other)
const {
866 const Null *p =
dynamic_cast<const Null*
>(other);
870 bool Array::isEqual(
const Value* other)
const {
871 const Array *p =
dynamic_cast<const Array*
>(other);
872 return (p != NULL && this->
val.size() == p->val.size() && equal(this->
val.begin(), this->
val.end(), p->val.begin()));
875 bool Object::isEqual(
const Value* other)
const {
876 const Object *p =
dynamic_cast<const Object*
>(other);
877 if (p == NULL || this->
val.size() != p->val.size())
879 std::map<std::string, JSON>::const_iterator it1,it2;
880 for (it1 = this->
val.begin(), it2 = p->val.begin(); it1 != this->
val.end() && it2 != p->val.end(); ++it1, ++it2) {
881 if (it1->first != it2->first || it1->second != it2->second)
884 return (it1 == this->
val.end() && it2 == p->val.end());
889 if (this->
type() != other.
type() || this->
type() == JSON_UNDEFINED)
891 return (this->
val->isEqual(other.
val));
895 if (this->
type() != JSON_OBJECT)
896 throw JSONException(
"Cannot get JSON::object_iterator for a non-JSON_OBJECT");
897 return (static_cast<Object*>(this->
val))->val.begin();
901 if (this->
type() != JSON_ARRAY)
902 throw JSONException(
"Cannot get JSON::array_iterator for a non-JSON_ARRAY");
903 return (static_cast<Array*>(this->
val))->val.begin();
907 if (this->
type() != JSON_OBJECT)
908 throw JSONException(
"Cannot get JSON::object_iterator for a non-JSON_OBJECT");
909 return (static_cast<Object*>(this->
val))->val.begin();
913 if (this->
type() != JSON_ARRAY)
914 throw JSONException(
"Cannot get JSON::array_iterator for a non-JSON_ARRAY");
915 return (static_cast<Array*>(this->
val))->val.begin();
919 if (this->
type() != JSON_OBJECT)
920 throw JSONException(
"Cannot get JSON::object_iterator for a non-JSON_OBJECT");
921 return (static_cast<Object*>(this->
val))->val.end();
925 if (this->
type() != JSON_ARRAY)
926 throw JSONException(
"Cannot get JSON::array_iterator for a non-JSON_ARRAY");
927 return (static_cast<Array*>(this->
val))->val.end();
931 if (this->
type() != JSON_OBJECT)
932 throw JSONException(
"Cannot get JSON::object_iterator for a non-JSON_OBJECT");
933 return (static_cast<Object*>(this->
val))->val.end();
937 if (this->
type() != JSON_ARRAY)
938 throw JSONException(
"Cannot get JSON::array_iterator for a non-JSON_ARRAY");
939 return (static_cast<Array*>(this->
val))->val.end();
950 if (this->
type() != JSON_ARRAY)
951 throw JSONException(
"Cannot get JSON::array_reverse_iterator for a non-JSON_ARRAY");
952 return (static_cast<Array*>(this->
val))->val.rbegin();
962 if (this->
type() != JSON_ARRAY)
963 throw JSONException(
"Cannot get JSON::array_reverse_iterator for a non-JSON_ARRAY");
964 return (static_cast<Array*>(this->
val))->val.rbegin();
974 if (this->
type() != JSON_ARRAY)
975 throw JSONException(
"Cannot get JSON::array_reverse_iterator for a non-JSON_ARRAY");
976 return (static_cast<Array*>(this->
val))->val.rend();
986 if (this->
type() != JSON_ARRAY)
987 throw JSONException(
"Cannot get JSON::array_reverse_iterator for a non-JSON_ARRAY");
988 return (static_cast<Array*>(this->
val))->val.rend();
992 if (this->
type() != JSON_ARRAY)
993 throw JSONException(
"Cannot call resize_array() on a non JSON_ARRAY object");
994 (
static_cast<Array*
>(this->
val))->val.resize(desired_size);
const_object_iterator object_end() const
void write(std::ostream &out) const
std::string toString(bool onlyTopLevel=false) const
const_array_reverse_iterator array_rend() const
JSON & operator=(const T &rhs)
void erase(const size_t &indx)
bool operator==(const JSON &other) const
const_array_iterator array_begin() const
static double getEpsilon()
const_array_iterator array_end() const
bool has(const T &indx) const
void read(std::istream &in)
const_object_iterator object_begin() const
const JSON & operator[](const size_t &indx) const
void readFromString(const std::string &jstr)
void push_back(const JSON &j)
void resize_array(size_t desired_size)
const_array_reverse_iterator array_rbegin() const