33 case '\t': s++;
break;
34 case '\n': s++;
break;
35 case '\r': s++;
break;
45 if (c >=
'0' && c <=
'9')
47 if (c >=
'a' && c <=
'f')
49 if (c >=
'A' && c <=
'F')
58 for (
int i=0; i<4; i++) {
64 unicode = unicode*16 + v;
75 if (unicode >= 0 && unicode <= 0x7F) {
77 buf[0] = unicode & 0x7F;
84 if (unicode >= 0x80 && unicode <= 0x7FF) {
86 buf[0] = 0x80|0x40|((unicode>>6)&0x1F);
87 buf[1] = 0x80|((unicode>>0)&0x3F);
92 if (unicode >= 0x800 && unicode <= 0xFFFF) {
94 buf[0] = 0x80|0x40|0x20|((unicode>>12)&0xF);
95 buf[1] = 0x80|((unicode>>6)&0x3F);
96 buf[2] = 0x80|((unicode>>0)&0x3F);
105static std::string
xparse_string(
const char* s,
const char** sout,
bool *error)
117 }
else if (*s ==
'\"') {
121 }
else if (*s ==
'\\') {
136 case '\"': v +=
'\"'; s++;
break;
137 case '\\': v +=
'\\'; s++;
break;
138 case '/': v +=
'/'; s++;
break;
139 case 'b': v +=
'\b'; s++;
break;
140 case 'f': v +=
'\f'; s++;
break;
141 case 'n': v +=
'\n'; s++;
break;
142 case 'r': v +=
'\r'; s++;
break;
143 case 't': v +=
'\t'; s++;
break;
223 return MJsonNode::MakeError(n,
"unexpected char after array element, should be \',\' or \']\'", sin, s);
251 }
else if (*s !=
'\"') {
253 return MJsonNode::MakeError(n,
"unexpected char while parsing object, should be \"\"\"", sin, s);
258 if (error || name.length() < 1) {
267 return MJsonNode::MakeError(n,
"unexpected end of string after name of object element", sin, s);
268 }
else if (*s !=
':') {
270 return MJsonNode::MakeError(n,
"unexpected char after name of object element, should be \":\"", sin, s);
302 return MJsonNode::MakeError(n,
"unexpected char after object element, should be \"}\" or \",\"", sin, s);
345 number = std::strtoll(str, &end, 10);
347 if ((number == LLONG_MAX || number == LLONG_MIN) && errno == ERANGE)
372 printf(
"atoll test failed: [%s] -> %lld (0x%llx) != %lld (0x%llx)\n", s, vv, vv, v, v);
373 assert(!
"mjson self test: my atoll() is broken, bye!");
477 if (*s ==
'e' || *s ==
'E') {
501 if (expsign < 0 || sfrac.length() > 0) {
503 double v1 = atof(sint.c_str());
506 const char* p = sfrac.c_str();
507 for ( ; *p != 0; p++, vm/=10.0) {
513 if (flag && (e < 0 || e > 400)) {
516 printf(
"overflow!\n");
521 double inf =
one/zero;
531 ee = pow(10, (
double)(expsign*e));
532 double v = sign*(v1+v2)*ee;
542 if (flag && (e < 0 || e > 400)) {
549 double inf =
one/zero;
554 for (
int ee=0; ee<e; ee++)
560 std::string sstr = sign == 1 ? sint :
"-" + sint;
570 double vv = atof(sint.c_str());
587 if (s[0] ==
'n' && s[1] ==
'u' && s[2] ==
'l' && s[3] ==
'l') {
598 if (s[0] ==
't' && s[1] ==
'r' && s[2] ==
'u' && s[3] ==
'e') {
609 if (s[0] ==
'f' && s[1] ==
'a' && s[2] ==
'l' && s[3] ==
's' && s[4] ==
'e') {
625 }
else if (*s ==
'{') {
627 }
else if (*s ==
'\"') {
629 }
else if (*s ==
'-') {
631 }
else if (*s >=
'0' && *s <=
'9') {
633 }
else if (*s ==
'n') {
635 }
else if (*s ==
't') {
637 }
else if (*s ==
'f') {
653 for (
unsigned i=0; i<
subnodes.size(); i++)
683 case '\"': v +=
"\\\""; s++;
break;
684 case '\\': v +=
"\\\\"; s++;
break;
686 case '\b': v +=
"\\b"; s++;
break;
687 case '\f': v +=
"\\f"; s++;
break;
688 case '\n': v +=
"\\n"; s++;
break;
689 case '\r': v +=
"\\r"; s++;
break;
690 case '\t': v +=
"\\t"; s++;
break;
713 snprintf(buf,
sizeof(buf),
"%lld", value);
719 if (isfinite(numbervalue)) {
721 snprintf(buf,
sizeof(buf),
"%.16e", numbervalue);
723 }
else if (isnan(numbervalue)) {
725 }
else if (isinf(numbervalue)) {
727 return "\"Infinity\"";
729 return "\"-Infinity\"";
731 assert(!
"this cannot happen!");
742 for (
size_t i=0; i<
subnodes.size(); i++) {
782 return "arraybuffer";
784 return std::string(
"json parse error: ") +
string_value;
786 assert(!
"should not come here");
800 strncpy(sample, serror, 31);
802 int offset = serror-sin;
805 for (
const char* s = sin; s != serror; s++) {
815 snprintf(msg,
sizeof(msg),
" at char \"%c\" file offset %d, line %d position %d, around text \"%s\"", *serror, offset, lineno, lineoff, sample);
889 assert(!
"not an array");
901 assert(!
"not an object");
1050 default:
return "UNKNOWN";
1067 for (
int i=0; i<nest; i++)
1073 printf(
"Node type %d (%s)", type, TypeToString(type));
1075 default: printf(
"\n");
break;
1076 case MJSON_STRING: printf(
", value [%s]\n", string_value.c_str());
break;
1077 case MJSON_INT: printf(
", value %lld\n", ll_value);
break;
1078 case MJSON_NUMBER: printf(
", value %g\n", double_value);
break;
1079 case MJSON_BOOL: printf(
", value %lld\n", ll_value);
break;
1081 case MJSON_JSON: printf(
", json [%s]\n", string_value.c_str());
break;
1082 case MJSON_ARRAYBUFFER: printf(
", arraybuffer size %d\n", (
int)arraybuffer_size);
break;
1085 for (
size_t i=0; i<subnodes.size(); i++) {
1087 printf(
"element %zu: ", i);
1088 subnodes[i]->Dump(nest+1);
1093 for (
size_t i=0; i<object_names.size(); i++) {
1095 printf(
"%s: ", object_names[i].c_str());
1096 subnodes[i]->Dump(nest+1);
1100 printf(
": %s\n", string_value.c_str());
1101 for (
size_t i=0; i<subnodes.size(); i++) {
1103 printf(
"errorelement %zu: ", i);
1104 subnodes[i]->Dump(nest+1);
1115 for (
size_t i=0; i<n->
subnodes.size(); i++) {
std::string GetString() const
find subnode with given name, NULL if not object, NULL is name not found
static MJsonNode * MakeJSON(const char *json)
void Dump(int nest=0) const
return node type as string
#define MJSON_ARRAYBUFFER
static MJsonNode * MakeArray()
MJsonNode * Copy() const
dump the subtree to standard output
const MJsonNodeVector * GetArray() const
get node type: MJSON_xxx
long long GetLL() const
get integer value, 0 if not an integer or value is JSON "null"
MJsonStringVector object_names
int GetType() const
delete a node from an object
void AddToArray(MJsonNode *node)
static MJsonNode * MakeNumber(double value)
static std::string Encode(const char *s)
std::vector< MJsonNode * > MJsonNodeVector
std::vector< std::string > MJsonStringVector
long long GetInt() const
get string value, "" if not string or value is JSON "null"
MJsonNode(int type)
make a copy of the json tree
static MJsonNode * MakeObject()
void AddToObject(const char *name, MJsonNode *node)
add node to an array. the array takes ownership of this node
double GetDouble() const
get 64-bit long long value, 0 if not an integer or value is JSON "null"
const MJsonNodeVector * GetObjectNodes() const
get array of object names, NULL if not object, empty array if value is JSON "null"
static MJsonNode * MakeBool(bool value)
std::string Stringify(int flags=0) const
static MJsonNode * MakeString(const char *value)
void DeleteObjectNode(const char *name)
add node to an object. the object takes ownership of this node
bool GetBool() const
get number or integer value, 0 if not a number or value is JSON "null"
static MJsonNode * MakeInt(long long value)
static std::string EncodeDouble(double v)
void GetArrayBuffer(const char **pptr, size_t *psize) const
get boolean value, false if not a boolean or value is JSON "null"
const MJsonStringVector * GetObjectNames() const
get array value, NULL if not array, empty array if value is JSON "null"
static MJsonNode * MakeError(MJsonNode *errornode, const char *errormessage, const char *sin, const char *serror)
the node takes ownership of the buffer
const MJsonNode * FindObjectNode(const char *name) const
get array of object subnodes, NULL if not object, empty array if value is JSON "null"
static MJsonNode * MakeArrayBuffer(char *ptr, size_t size)
static std::string EncodeLL(long long v)
static MJsonNode * MakeNull()
std::string GetError() const
static MJsonNode * Parse(const char *jsonstring)
static const char * TypeToString(int type)
get error message from MJSON_ERROR nodes
static char toHexChar(int c)
static std::string xoutput_unicode(int unicode, bool *error)
bool atoll_with_overflow(const char *str, long long &number)
static int xparse_unicode(const char *s, const char **sout)
static void test_atoll_with_overflow_value(const char *s, long long v, bool flag)
static MJsonNode * parse_something(const char *sin, const char *s, const char **sout)
static MJsonNode * parse_string(const char *sin, const char *s, const char **sout)
static MJsonNode * parse_false(const char *sin, const char *s, const char **sout)
static MJsonNode * parse_true(const char *sin, const char *s, const char **sout)
static MJsonNode * parse_object(const char *sin, const char *s, const char **sout)
static TestAtollWithOverflow runme
static std::string xparse_string(const char *s, const char **sout, bool *error)
static int hexToInt(char c)
static MJsonNode * parse_null(const char *sin, const char *s, const char **sout)
static void pnest(int nest)
static const char * skip_spaces(const char *s)
static std::string parse_digits(const char *s, const char **sout)
static MJsonNode * parse_number(const char *sin, const char *s, const char **sout)
static void test_atoll_with_overflow()
static MJsonNode * parse_array(const char *sin, const char *s, const char **sout)