On Tue, Nov 03, 2009 at 02:50:08PM -0500, Daniel P. Berrange wrote: > Import JSON parsing / formatting helper code based on code from > > http://mjson.sourceforge.net/ Hum http://mjson.sourceforge.net/ -> news: MJSON v0.9 released http://sourceforge.net/projects/mjson/ -> Download now mjson-1.2.tar.gz what version did you based this from ? > with some API changes to better cope with libvirt's needs. I notice no error or debug is emitted directly from this module. > +static int > +lexer (const char *buffer, const char **p, unsigned int *state, rcstring ** text) > +{ > + if (*p == NULL) > + *p = buffer; > + > + while (**p != '\0') > + { > + switch (*state) > + { > + > + case 0: /* Root document */ > + { > + switch (*(*p)++) > + { > + case '\x20': /* space */ > + case '\x09': /* horizontal tab */ > + case '\x0A': /* line feed or new line */ > + case '\x0D': /* Carriage return */ > + break; > + > + case '{': > + return LEX_BEGIN_OBJECT; > + case '}': > + return LEX_END_OBJECT; > + case '[': > + return LEX_BEGIN_ARRAY; > + case ']': > + return LEX_END_ARRAY; > + case ':': > + return LEX_NAME_SEPARATOR; > + case ',': > + return LEX_VALUE_SEPARATOR; > + > + case '\"': > + *text = rcs_create (RSTRING_DEFAULT); > + if (*text == NULL) > + return LEX_MEMORY; > + *state = 1; /* inside a JSON string */ > + break; > + > + case 't': > + *state = 7; /* true: 1 */ > + break; > + > + case 'f': > + *state = 10; /* false: 1 */ > + break; > + > + case 'n': > + *state = 14; /* false: 1 */ > + break; > + > + case '-': > + *text = rcs_create (RSTRING_DEFAULT); > + if (*text == NULL) > + return LEX_MEMORY; > + if (rcs_catc (*text, '-') != RS_OK) > + return LEX_MEMORY; > + *state = 17; /* number: '0' */ > + break; > + > + case '0': > + *text = rcs_create (RSTRING_DEFAULT); > + if (*text == NULL) > + return LEX_MEMORY; > + if (rcs_catc (*text, '0') != RS_OK) > + return LEX_MEMORY; > + *state = 18; /* number: '0' */ > + break; > + > + case '1': > + case '2': > + case '3': > + case '4': > + case '5': > + case '6': > + case '7': > + case '8': > + case '9': > + *text = rcs_create (RSTRING_DEFAULT); > + if (*text == NULL) > + return LEX_MEMORY; > + if (rcs_catc (*text, *(*p - 1)) != RS_OK) > + return LEX_MEMORY; > + *state = 19; /* number: decimal followup */ > + break; > + > + > + default: > + return LEX_INVALID_CHARACTER; > + } > + } > + break; > + > + case 1: /* inside a JSON string */ > + { > + switch (**p) > + { > + case 1: > + case 2: > + case 3: > + case 4: > + case 5: > + case 6: > + case 7: > + case 8: > + case 9: > + case 10: /* line feed */ > + case 11: > + case 12: > + case 13: /* carriage return */ > + case 14: > + case 15: > + case 16: > + case 17: > + case 18: > + case 19: > + case 20: > + case 21: > + case 22: > + case 23: > + case 24: > + case 25: > + case 26: > + case 27: > + case 28: > + case 29: > + case 30: > + case 31: > + /* ASCII control characters can only be present in a JSON string if they are escaped. If not then the document is invalid */ > + return LEX_INVALID_CHARACTER; > + break; > + > + case '\"': /* close JSON string */ > + /* it is expected that, in the routine that calls this function, text is set to NULL */ > + *state = 0; > + ++*p; > + return LEX_STRING; > + break; > + > + case '\\': > + if (rcs_catc (*text, '\\') != RS_OK) > + return LEX_MEMORY; > + *state = 2; /* inside a JSON string: start escape sequence */ > + break; > + > + default: > + if (rcs_catc (*text, **p) != RS_OK) > + return LEX_MEMORY; > + } > + ++*p; > + } > + break; > + > + case 2: /* inside a JSON string: start escape sequence */ > + { > + switch (**p) > + { > + case '\\': > + case '\"': > + case '/': > + case 'b': > + case 'f': > + case 'n': > + case 'r': > + case 't': > + if (rcs_catc (*text, **p) != RS_OK) > + return LEX_MEMORY; > + *state = 1; /* inside a JSON string */ > + break; > + > + case 'u': > + if (rcs_catc (*text, **p) != RS_OK) > + return LEX_MEMORY; > + *state = 3; /* inside a JSON string: escape unicode */ > + break; > + > + default: > + return LEX_INVALID_CHARACTER; > + } > + ++*p; > + } > + break; > + > + case 3: /*inside a JSON string: escape unicode */ > + { > + if ((**p >= 'a') && (**p <= 'f')) > + { > + if (rcs_catc (*text, **p) != RS_OK) > + return LEX_MEMORY; > + *state = 4; /* inside a JSON string: escape unicode */ > + } > + else if ((**p >= 'A') && (**p <= 'F')) > + { > + if (rcs_catc (*text, **p) != RS_OK) > + return LEX_MEMORY; > + *state = 4; /* inside a JSON string: escape unicode */ > + } > + else if ((**p >= '0') && (**p <= '9')) > + { > + if (rcs_catc (*text, **p) != RS_OK) > + return LEX_MEMORY; > + *state = 4; /* inside a JSON string: escape unicode */ > + } > + else > + return LEX_INVALID_CHARACTER; > + ++*p; > + } > + break; > + > + case 4: /* inside a JSON string: escape unicode */ > + { > + if ((**p >= 'a') && (**p <= 'f')) > + { > + if (rcs_catc (*text, **p) != RS_OK) > + return LEX_MEMORY; > + *state = 5; /* inside a JSON string: escape unicode */ > + } > + else if ((**p >= 'A') && (**p <= 'F')) > + { > + if (rcs_catc (*text, **p) != RS_OK) > + return LEX_MEMORY; > + *state = 5; /* inside a JSON string: escape unicode */ > + } > + else if ((**p >= '0') && (**p <= '9')) > + { > + if (rcs_catc (*text, **p) != RS_OK) > + return LEX_MEMORY; > + *state = 5; /* inside a JSON string: escape unicode */ > + } > + else > + return LEX_INVALID_CHARACTER; > + ++*p; > + } > + > + case 5: /* inside a JSON string: escape unicode */ > + { > + if ((**p >= 'a') && (**p <= 'f')) > + { > + if (rcs_catc (*text, **p) != RS_OK) > + return LEX_MEMORY; > + *state = 6; /* inside a JSON string: escape unicode */ > + } > + else if ((**p >= 'A') && (**p <= 'F')) > + { > + if (rcs_catc (*text, **p) != RS_OK) > + return LEX_MEMORY; > + *state = 6; /* inside a JSON string: escape unicode */ > + } > + else if ((**p >= '0') && (**p <= '9')) > + { > + if (rcs_catc (*text, **p) != RS_OK) > + return LEX_MEMORY; > + *state = 6; /* inside a JSON string: escape unicode */ > + } > + else > + return LEX_INVALID_CHARACTER; > + ++*p; > + } > + break; > + > + case 6: /* inside a JSON string: escape unicode */ > + { > + if ((**p >= 'a') && (**p <= 'f')) > + { > + if (rcs_catc (*text, **p) != RS_OK) > + return LEX_MEMORY; > + *state = 1; /* inside a JSON string: escape unicode */ > + } > + else if ((**p >= 'A') && (**p <= 'F')) > + { > + if (rcs_catc (*text, **p) != RS_OK) > + return LEX_MEMORY; > + *state = 1; /* inside a JSON string: escape unicode */ > + } > + else if ((**p >= '0') && (**p <= '9')) > + { > + if (rcs_catc (*text, **p) != RS_OK) > + return LEX_MEMORY; > + *state = 1; /* inside a JSON string: escape unicode */ > + } > + else > + return LEX_INVALID_CHARACTER; > + ++*p; > + } > + break; > + > + case 7: /* true: 1 */ > + { > + switch (*(*p)++) > + { > + case 'r': > + *state = 8; > + break; > + default: > + return LEX_INVALID_CHARACTER; > + break; > + } > + } > + break; > + > + case 8: /* true: 2 */ > + { > + switch (*(*p)++) > + { > + case 'u': > + *state = 9; > + break; > + default: > + return LEX_INVALID_CHARACTER; > + break; > + } > + } > + break; > + > + case 9: /* true: 3 */ > + { > + switch (*(*p)++) > + { > + case 'e': > + *state = 0; > + return LEX_TRUE; > + break; > + default: > + return LEX_INVALID_CHARACTER; > + break; > + } > + } > + break; > + > + case 10: /* false: 1 */ > + { > + switch (*(*p)++) > + { > + case 'a': > + *state = 11; > + break; > + default: > + return LEX_INVALID_CHARACTER; > + break; > + } > + } > + break; > + > + case 11: /* false: 2 */ > + { > + switch (*(*p)++) > + { > + case 'l': > + *state = 12; > + break; > + default: > + return LEX_INVALID_CHARACTER; > + break; > + } > + } > + break; > + > + case 12: /* false: 3 */ > + { > + switch (*(*p)++) > + { > + case 's': > + *state = 13; > + break; > + default: > + return LEX_INVALID_CHARACTER; > + break; > + } > + } > + break; > + > + case 13: /* false: 4 */ > + { > + switch (*(*p)++) > + { > + case 'e': > + *state = 0; > + return LEX_FALSE; > + break; > + default: > + return LEX_INVALID_CHARACTER; > + break; > + } > + } > + break; > + > + case 14: /* null: 1 */ > + { > + switch (*(*p)++) > + { > + case 'u': > + *state = 15; > + break; > + default: > + return LEX_INVALID_CHARACTER; > + break; > + } > + } > + break; > + > + case 15: /* null: 2 */ > + { > + switch (*(*p)++) > + { > + case 'l': > + *state = 16; > + break; > + default: > + return LEX_INVALID_CHARACTER; > + break; > + } > + } > + break; > + > + case 16: /* null: 3 */ > + { > + switch (*(*p)++) > + { > + case 'l': > + *state = 0; > + return LEX_NULL; > + break; > + default: > + return LEX_INVALID_CHARACTER; > + break; > + } > + } > + break; > + > + case 17: /* number: minus sign */ > + { > + switch (**p) > + { > + case '0': > + if (rcs_catc (*text, **p) != RS_OK) > + return LEX_MEMORY; > + ++*p; > + *state = 18; /* number: '0' */ > + break; > + > + case '1': > + case '2': > + case '3': > + case '4': > + case '5': > + case '6': > + case '7': > + case '8': > + case '9': > + if (rcs_catc (*text, **p) != RS_OK) > + return LEX_MEMORY; > + ++*p; > + *state = 19; /* number: decimal followup */ > + break; > + > + default: > + return LEX_INVALID_CHARACTER; > + break; > + } > + } > + break; > + > + case 18: /* number: '0' */ > + { > + switch (**p) > + { > + case '\x20': /* space */ > + case '\x09': /* horizontal tab */ > + case '\x0A': /* line feed or new line */ > + case '\x0D': /* Carriage return */ > + ++*p; > + case ']': > + case '}': > + case ',': > + *state = 0; > + return LEX_NUMBER; > + break; > + > + case '.': > + if (rcs_catc (*text, **p) != RS_OK) > + return LEX_MEMORY; > + ++*p; > + *state = 20; /* number: frac start */ > + break; > + > + case 'e': > + case 'E': > + if (rcs_catc (*text, **p) != RS_OK) > + return LEX_MEMORY; > + ++*p; > + *state = 22; /* number: exp start */ > + break; > + > + default: > + return LEX_INVALID_CHARACTER; > + break; > + } > + } > + break; > + > + case 19: /* number: int followup */ > + { > + switch (**p) > + { > + case '\x20': /* space */ > + case '\x09': /* horizontal tab */ > + case '\x0A': /* line feed or new line */ > + case '\x0D': /* Carriage return */ > + ++*p; > + case ']': > + case '}': > + case ',': > + *state = 0; > + return LEX_NUMBER; > + break; > + > + case '.': > + if (rcs_catc (*text, **p) != RS_OK) > + return LEX_MEMORY; > + ++*p; > + *state = 20; /* number: frac start */ > + break; > + > + case 'e': > + case 'E': > + if (rcs_catc (*text, **p) != RS_OK) > + return LEX_MEMORY; > + ++*p; > + *state = 22; /* number: exp start */ > + break; > + > + case '0': > + case '1': > + case '2': > + case '3': > + case '4': > + case '5': > + case '6': > + case '7': > + case '8': > + case '9': > + if (rcs_catc (*text, **p) != RS_OK) > + return LEX_MEMORY; > + ++*p; > + break; > + > + default: > + return LEX_INVALID_CHARACTER; > + break; > + } > + } > + break; > + > + case 20: /* number: frac start */ > + { > + switch (**p) > + { > + case '0': > + case '1': > + case '2': > + case '3': > + case '4': > + case '5': > + case '6': > + case '7': > + case '8': > + case '9': > + if (rcs_catc (*text, **p) != RS_OK) > + return LEX_MEMORY; > + ++*p; > + *state = 21; /* number: frac continue */ > + break; > + > + default: > + return LEX_INVALID_CHARACTER; > + break; > + } > + } > + break; > + > + case 21: /* number: frac continue */ > + { > + switch (**p) > + { > + case '\x20': /* space */ > + case '\x09': /* horizontal tab */ > + case '\x0A': /* line feed or new line */ > + case '\x0D': /* Carriage return */ > + ++*p; > + case ']': > + case '}': > + case ',': > + *state = 0; > + return LEX_NUMBER; > + break; > + > + case 'e': > + case 'E': > + if (rcs_catc (*text, **p) != RS_OK) > + return LEX_MEMORY; > + ++*p; > + *state = 22; /* number: exp start */ > + break; > + > + case '0': > + case '1': > + case '2': > + case '3': > + case '4': > + case '5': > + case '6': > + case '7': > + case '8': > + case '9': > + if (rcs_catc (*text, **p) != RS_OK) > + return LEX_MEMORY; > + ++*p; > + break; > + > + default: > + return LEX_INVALID_CHARACTER; > + break; > + } > + } > + break; > + > + case 22: /* number: exp start */ > + { > + switch (**p) > + { > + case '-': > + case '+': > + if (rcs_catc (*text, **p) != RS_OK) > + return LEX_MEMORY; > + ++*p; > + *state = 23; /* number: exp continue */ > + break; > + > + case '0': > + case '1': > + case '2': > + case '3': > + case '4': > + case '5': > + case '6': > + case '7': > + case '8': > + case '9': > + if (rcs_catc (*text, **p) != RS_OK) > + return LEX_MEMORY; > + ++*p; > + *state = 24; /* number: exp end */ > + break; > + > + default: > + return LEX_INVALID_CHARACTER; > + break; > + } > + } > + break; > + > + case 23: /* number: exp continue */ > + { > + switch (**p) > + { > + case '0': > + case '1': > + case '2': > + case '3': > + case '4': > + case '5': > + case '6': > + case '7': > + case '8': > + case '9': > + if (rcs_catc (*text, **p) != RS_OK) > + return LEX_MEMORY; > + ++*p; > + *state = 24; /* number: exp end */ > + break; > + > + default: > + return LEX_INVALID_CHARACTER; > + break; > + } > + } > + break; > + > + case 24: /* number: exp end */ > + { > + switch (**p) > + { > + case '\x20': /* space */ > + case '\x09': /* horizontal tab */ > + case '\x0A': /* line feed or new line */ > + case '\x0D': /* Carriage return */ > + ++*p; > + case ']': > + case '}': > + case ',': > + *state = 0; > + return LEX_NUMBER; > + break; > + > + case '0': > + case '1': > + case '2': > + case '3': > + case '4': > + case '5': > + case '6': > + case '7': > + case '8': > + case '9': > + if (rcs_catc (*text, **p) != RS_OK) > + return LEX_MEMORY; > + ++*p; > + break; > + > + default: > + return LEX_INVALID_CHARACTER; > + break; > + } > + } > + break; > + > + default: > + printf ("*state missing: %d\n", *state); > + return LEX_INVALID_CHARACTER; > + } > + > + } > + > + *p = NULL; > + return LEX_MORE; > +} IMHO this is an abomination, but as long as nobody need to fix that code ! Just out of curiosity, what encoding are those character supposed to be into ? It's being checked against ASCII values and there are hints of 'unicode escaping' it's weird. > +enum json_error > +json_parse_fragment (struct json_parsing_info *info, const char *buffer) > +{ > + json_t *temp = NULL; > + > + info->p = buffer; > + while (*info->p != '\0') > + { > + switch (info->state) > + { > + case 0: /* starting point */ > + { > + switch (lexer (buffer, &info->p, &info->lex_state, & info->lex_text)) > + { > + case LEX_BEGIN_OBJECT: > + info->state = 1; /* begin object */ > + break; > + > + case LEX_BEGIN_ARRAY: > + info->state = 7; /* begin array */ > + break; > + > + case LEX_INVALID_CHARACTER: > + return JSON_MALFORMED_DOCUMENT; > + break; > + > + default: > + printf ("state %d: defaulted\n", info->state); > + return JSON_MALFORMED_DOCUMENT; > + break; > + } > + } > + break; > + > + case 1: /* open object */ > + { > + if (info->cursor == NULL) > + { > + if ((info->cursor = json_new_object ()) == NULL) > + { > + return JSON_MEMORY; > + } > + } > + else > + { > + if ((temp = json_new_object ()) == NULL) > + { > + return JSON_MEMORY; > + } > + if (json_insert_child (info->cursor, temp) != JSON_OK) > + { > + return JSON_UNKNOWN_PROBLEM; > + } > + info->cursor = temp; > + temp = NULL; > + } > + info->state = 2; /* just entered an object */ > + } > + break; > + > + case 2: /* opened object */ > + { > + switch (lexer (buffer, &info->p, &info->lex_state, & info->lex_text)) > + { > + case LEX_STRING: > + if ((temp = json_new_value (JSON_STRING)) == NULL) > + return JSON_MEMORY; > + temp->text = rcs_unwrap (info->lex_text), info->lex_text = NULL; > + if (json_insert_child (info->cursor, temp) != JSON_OK) > + { > + /*TODO return value according to the value returned from json_insert_child() */ > + return JSON_UNKNOWN_PROBLEM; > + } > + info->cursor = temp; > + temp = NULL; > + info->state = 5; /* label, pre label:value separator */ > + break; > + > + case LEX_END_OBJECT: > + if (info->cursor->parent == NULL) > + { > + info->state = 99; /* finished document. only accept whitespaces until EOF */ > + } > + else > + { > + info->cursor = info->cursor->parent; > + switch (info->cursor->type) > + { > + case JSON_STRING: > + info->cursor = info->cursor->parent; > + if (info->cursor->type != JSON_OBJECT) > + { > + return JSON_BAD_TREE_STRUCTURE; > + } > + else > + { > + info->state = 3; /* finished adding a field to an object */ > + } > + break; > + > + case JSON_ARRAY: > + info->state = 9; > + break; > + > + default: > + return JSON_BAD_TREE_STRUCTURE; > + } > + } > + break; > + > + case LEX_MORE: > + return JSON_INCOMPLETE_DOCUMENT; > + break; > + > + default: > + printf ("state %d: defaulted\n", info->state); > + return JSON_MALFORMED_DOCUMENT; > + break; > + } > + } > + break; > + > + case 3: /* finished adding a field to an object */ > + { > + switch (lexer (buffer, &info->p, &info->lex_state, & info->lex_text)) > + { > + case LEX_VALUE_SEPARATOR: > + info->state = 4; /* sibling, post-object */ > + break; > + > + case LEX_END_OBJECT: > + if (info->cursor->parent == NULL) > + { > + info->state = 99; /* parse until EOF */ > + } > + else > + { > + info->cursor = info->cursor->parent; > + switch (info->cursor->type) > + { > + case JSON_STRING: > + info->cursor = info->cursor->parent; > + if (info->cursor->type != JSON_OBJECT) > + { > + return JSON_BAD_TREE_STRUCTURE; > + } > + else > + { > + info->state = 3; /* finished adding a field to an object */ > + } > + break; > + > + case JSON_ARRAY: > + info->state = 9; > + break; > + > + default: > + return JSON_BAD_TREE_STRUCTURE; > + } > + } > + break; > + > + case LEX_MORE: > + return JSON_INCOMPLETE_DOCUMENT; > + break; > + > + default: > + printf ("state %d: defaulted\n", info->state); > + return JSON_MALFORMED_DOCUMENT; > + break; > + } > + } > + break; > + > + case 4: /* sibling, post-object */ > + { > + switch (lexer (buffer, &info->p, &info->lex_state, & info->lex_text)) > + { > + case LEX_STRING: > + if ((temp = json_new_value (JSON_STRING)) == NULL) > + return JSON_MEMORY; > + temp->text = rcs_unwrap (info->lex_text), info->lex_text = NULL; > + if (json_insert_child (info->cursor, temp) != JSON_OK) > + { > + return JSON_UNKNOWN_PROBLEM; > + } > + info->cursor = temp; > + temp = NULL; > + info->state = 5; > + break; > + > + case LEX_MORE: > + return JSON_INCOMPLETE_DOCUMENT; > + break; > + > + case LEX_INVALID_CHARACTER: > + return JSON_ILLEGAL_CHARACTER; > + break; > + > + default: > + printf ("state %d: defaulted\n", info->state); > + return JSON_MALFORMED_DOCUMENT; > + break; > + } > + } > + break; > + > + case 5: /* label, pre name separator */ > + { > + switch (lexer (buffer, &info->p, &info->lex_state, & info->lex_text)) > + { > + case LEX_NAME_SEPARATOR: > + info->state = 6; /* label, pos label:value separator */ > + break; > + > + case LEX_MORE: > + return JSON_INCOMPLETE_DOCUMENT; > + break; > + > + default: > + printf ("state %d: defaulted\n", info->state); > + return JSON_MALFORMED_DOCUMENT; > + break; > + } > + } > + break; > + > + case 6: /* label, pos name separator */ > + { > + unsigned int value; /* to avoid redundant code */ > + > + switch (value = lexer (buffer, &info->p, &info->lex_state, & info->lex_text)) > + { > + case LEX_STRING: > + if ((temp = json_new_value (JSON_STRING)) == NULL) > + return JSON_MEMORY; > + temp->text = rcs_unwrap (info->lex_text), info->lex_text = NULL; > + if (json_insert_child (info->cursor, temp) != JSON_OK) > + { > + /*TODO specify the exact error message */ > + return JSON_UNKNOWN_PROBLEM; > + } > + if (info->cursor->parent == NULL) > + { > + info->state = 99; /* finished document. only accepts whitespaces until EOF */ > + } > + else > + { > + info->cursor = info->cursor->parent; > + } > + temp = NULL; > + info->state = 3; /* finished adding a field to an object */ > + break; > + > + case LEX_NUMBER: > + if ((temp = json_new_value (JSON_NUMBER)) == NULL) > + return JSON_MEMORY; > + temp->text = rcs_unwrap (info->lex_text), info->lex_text = NULL; > + if (json_insert_child (info->cursor, temp) != JSON_OK) > + { > + /*TODO specify the exact error message */ > + return JSON_UNKNOWN_PROBLEM; > + } > + if (info->cursor->parent == NULL) > + { > + info->state = 99; /* finished document. only accepts whitespaces until EOF */ > + } > + else > + { > + info->cursor = info->cursor->parent; > + } > + temp = NULL; > + info->state = 3; /* finished adding a field to an object */ > + break; > + > + case LEX_TRUE: > + if ((temp = json_new_value (JSON_TRUE)) == NULL) > + return JSON_MEMORY; > + if (json_insert_child (info->cursor, temp) != JSON_OK) > + { > + /*TODO specify the exact error message */ > + return JSON_UNKNOWN_PROBLEM; > + } > + if (info->cursor->parent == NULL) > + { > + info->state = 99; /* finished document. only accepts whitespaces until EOF */ > + } > + else > + { > + info->cursor = info->cursor->parent; > + } > + temp = NULL; > + info->state = 3; /* finished adding a field to an object */ > + break; > + > + case LEX_FALSE: > + if ((temp = json_new_value (JSON_FALSE)) == NULL) > + return JSON_MEMORY; > + if (json_insert_child (info->cursor, temp) != JSON_OK) > + { > + /*TODO specify the exact error message */ > + return JSON_UNKNOWN_PROBLEM; > + } > + if (info->cursor->parent == NULL) > + { > + info->state = 99; /* finished document. only accepts whitespaces until EOF */ > + } > + else > + { > + info->cursor = info->cursor->parent; > + } > + temp = NULL; > + info->state = 3; /* finished adding a field to an object */ > + break; > + > + case LEX_NULL: > + if ((temp = json_new_value (JSON_NULL)) == NULL) > + return JSON_MEMORY; > + if (json_insert_child (info->cursor, temp) != JSON_OK) > + { > + /*TODO specify the exact error message */ > + return JSON_UNKNOWN_PROBLEM; > + } > + if (info->cursor->parent == NULL) > + { > + info->state = 99; /* finished document. only accepts whitespaces until EOF */ > + } > + else > + { > + info->cursor = info->cursor->parent; > + } > + temp = NULL; > + info->state = 3; /* finished adding a field to an object */ > + break; > + > + case LEX_BEGIN_OBJECT: > + info->state = 1; > + break; > + > + case LEX_BEGIN_ARRAY: > + info->state = 7; > + break; > + > + case LEX_MORE: > + return JSON_INCOMPLETE_DOCUMENT; > + break; > + > + case LEX_MEMORY: > + return JSON_MEMORY; > + break; > + > + case LEX_INVALID_CHARACTER: > + return JSON_ILLEGAL_CHARACTER; > + break; > + > + default: > + printf ("state %d: defaulted\n", info->state); > + return JSON_MALFORMED_DOCUMENT; > + break; > + } > + } > + break; > + > + case 7: /* open array */ > + { > + if (info->cursor == NULL) > + { > + if ((info->cursor = json_new_array ()) == NULL) > + { > + return JSON_MEMORY; > + } > + } > + else > + { > + if ((temp = json_new_array ()) == NULL) > + { > + return JSON_MEMORY; > + } > + if (json_insert_child (info->cursor, temp) != JSON_OK) > + { > + return JSON_UNKNOWN_PROBLEM; > + } > + info->cursor = temp; > + temp = NULL; > + } > + info->state = 8; /* just entered an array */ > + } > + break; > + > + case 8: /* just entered an array */ > + { > + switch (lexer (buffer, &info->p, &info->lex_state, & info->lex_text)) > + { > + case LEX_STRING: > + if ((temp = json_new_value (JSON_STRING)) == NULL) > + return JSON_MEMORY; > + temp->text = rcs_unwrap (info->lex_text), info->lex_text = NULL; > + if (json_insert_child (info->cursor, temp) != JSON_OK) > + { > + return JSON_UNKNOWN_PROBLEM; > + } > + temp = NULL; > + info->state = 9; /* label, pre label:value separator */ > + break; > + > + case LEX_NUMBER: > + if ((temp = json_new_value (JSON_NUMBER)) == NULL) > + return JSON_MEMORY; > + temp->text = rcs_unwrap (info->lex_text), info->lex_text = NULL; > + if (json_insert_child (info->cursor, temp) != JSON_OK) > + { > + return JSON_UNKNOWN_PROBLEM; > + } > + temp = NULL; > + info->state = 9; /* label, pre label:value separator */ > + break; > + > + case LEX_TRUE: > + if ((temp = json_new_value (JSON_TRUE)) == NULL) > + return JSON_MEMORY; > + if (json_insert_child (info->cursor, temp) != JSON_OK) > + { > + return JSON_UNKNOWN_PROBLEM; > + } > + info->state = 9; /* label, pre label:value separator */ > + break; > + > + case LEX_FALSE: > + if ((temp = json_new_value (JSON_FALSE)) == NULL) > + return JSON_MEMORY; > + if (json_insert_child (info->cursor, temp) != JSON_OK) > + { > + return JSON_UNKNOWN_PROBLEM; > + } > + info->state = 9; /* label, pre label:value separator */ > + break; > + > + case LEX_NULL: > + if ((temp = json_new_value (JSON_NULL)) == NULL) > + return JSON_MEMORY; > + if (json_insert_child (info->cursor, temp) != JSON_OK) > + { > + return JSON_UNKNOWN_PROBLEM; > + } > + info->state = 9; /* label, pre label:value separator */ > + break; > + > + case LEX_BEGIN_ARRAY: > + info->state = 7; /* open array */ > + break; > + > + case LEX_END_ARRAY: > + if (info->cursor->parent == NULL) > + { > + /*TODO implement this */ > + info->state = 99; /* finished document. only accept whitespaces until EOF */ > + } > + else > + { > + info->cursor = info->cursor->parent; > + switch (info->cursor->type) > + { > + case JSON_STRING: > + if (info->cursor->parent == NULL) > + return JSON_BAD_TREE_STRUCTURE; > + else > + { > + info->cursor = info->cursor->parent; > + if (info->cursor->type != JSON_OBJECT) > + { > + return JSON_BAD_TREE_STRUCTURE; > + } > + > + info->state = 3; /* followup to adding child to array */ > + } > + break; > + > + case JSON_ARRAY: > + info->state = 9; /* followup to adding child to array */ > + break; > + > + default: > + return JSON_BAD_TREE_STRUCTURE; > + } > + } > + break; > + > + case LEX_BEGIN_OBJECT: > + info->state = 1; /* open object */ > + break; > + > + case LEX_MORE: > + return JSON_INCOMPLETE_DOCUMENT; > + break; > + > + case LEX_INVALID_CHARACTER: > + return JSON_ILLEGAL_CHARACTER; > + break; > + > + default: > + printf ("state %d: defaulted\n", info->state); > + return JSON_MALFORMED_DOCUMENT; > + break; > + } > + } > + break; > + > + case 9: /* followup to adding child to array */ > + { > + switch (lexer (buffer, &info->p, &info->lex_state, & info->lex_text)) > + { > + case LEX_VALUE_SEPARATOR: > + info->state = 8; > + break; > + > + case LEX_END_ARRAY: > + if (info->cursor->parent == NULL) > + { > + info->state = 99; /* finished document. only accept whitespaces until EOF */ > + } > + else > + { > + info->cursor = info->cursor->parent; > + switch (info->cursor->type) > + { > + case JSON_STRING: > + if (info->cursor->parent == NULL) > + { > + info->state = 99; /* finished document. only accept whitespaces until EOF */ > + } > + else > + { > + info->cursor = info->cursor->parent; > + if (info->cursor->type != JSON_OBJECT) > + { > + return JSON_BAD_TREE_STRUCTURE; > + } > + else > + { > + info->state = 3; /* followup to adding child to array */ > + } > + } > + break; > + > + case JSON_ARRAY: > + info->state = 9; /* followup to adding child to array */ > + break; > + > + default: > + return JSON_BAD_TREE_STRUCTURE; > + } > + } > + break; > + > + case LEX_MORE: > + return JSON_INCOMPLETE_DOCUMENT; > + break; > + > + default: > + printf ("state %d: defaulted\n", info->state); > + return JSON_MALFORMED_DOCUMENT; > + break; > + } > + } > + break; > + > + case 99: /* finished document. only accept whitespaces until EOF */ > + { > + switch (lexer (buffer, &info->p, &info->lex_state, & info->lex_text)) > + { > + case LEX_MORE: > + return JSON_WAITING_FOR_EOF; > + break; > + > + case LEX_MEMORY: > + return JSON_MEMORY; > + break; > + > + default: > + return JSON_MALFORMED_DOCUMENT; > + break; > + } > + } > + break; > + > + default: > + printf ("invalid parser state %d: defaulted\n", info->state); > + return JSON_UNKNOWN_PROBLEM; > + } > + } > + info->p = NULL; > + if (info->state == 99) > + return JSON_WAITING_FOR_EOF; > + else > + return JSON_INCOMPLETE_DOCUMENT; > +} > + Another abomination, again hopefully this won't have to be changed ! > +enum json_error > +json_saxy_parse (struct json_saxy_parser_status *jsps, struct json_saxy_functions *jsf, char c) > +{ > + /*TODO handle a string instead of a single char */ > + /* temp variables */ > + rcstring *temp; > + > + temp = NULL; > + > + /* goto where we left off */ > + switch (jsps->state) > + { > + case 0: /* general state. everything goes. */ > + goto state0; > + break; > + case 1: /* parse string */ > + goto state1; > + break; > + case 2: /* parse string: escaped character */ > + goto state2; > + break; > + case 3: /* parse string: escaped unicode 1 */ > + goto state3; > + break; > + case 4: /* parse string: escaped unicode 2 */ > + goto state4; > + break; > + case 5: /* parse string: escaped unicode 3 */ > + goto state5; > + break; > + case 6: /* parse string: escaped unicode 4 */ > + goto state6; > + break; > + case 7: /* parse true: tr */ > + goto state7; > + break; > + case 8: /* parse true: tru */ > + goto state8; > + break; > + case 9: /* parse true: true */ > + goto state9; > + break; > + case 10: /* parse false: fa */ > + goto state10; > + break; > + case 11: /* parse false: fal */ > + goto state11; > + break; > + case 12: /* parse false: fals */ > + goto state12; > + break; > + case 13: /* parse false: false */ > + goto state13; > + break; > + case 14: /* parse null: nu */ > + goto state14; > + break; > + case 15: /* parse null: nul */ > + goto state15; > + break; > + case 16: /* parse null: null */ > + goto state16; > + break; > + case 17: /* parse number: 0 */ > + goto state17; > + break; > + case 18: /* parse number: start fraccional part */ > + goto state18; > + break; > + case 19: /* parse number: fraccional part */ > + goto state19; > + break; > + case 20: /* parse number: start exponent part */ > + goto state20; > + break; > + case 21: /* parse number: exponent part */ > + goto state21; > + break; > + case 22: /* parse number: exponent sign part */ > + goto state22; > + break; > + case 23: /* parse number: start negative */ > + goto state23; > + break; > + case 24: /* parse number: decimal part */ > + goto state24; > + break; > + case 25: /* open object */ > + goto state25; > + break; > + case 26: /* close object/array */ > + goto state26; > + break; > + case 27: /* sibling followup */ > + goto state27; > + break; > + > + default: /* oops... this should never be reached */ > + return JSON_UNKNOWN_PROBLEM; > + } > + > +state0: /* starting point */ > + { > + switch (c) > + { > + case '\x20': > + case '\x09': > + case '\x0A': > + case '\x0D': /* JSON insignificant white spaces */ > + break; > + > + case '\"': /* starting a string */ > + jsps->string_length_limit_reached = 0; > + jsps->state = 1; > + break; > + > + case '{': > + if (jsf->open_object != NULL) > + jsf->open_object (); > + jsps->state = 25; /*open object */ > + break; > + > + case '}': > + if (jsf->close_object != NULL) > + jsf->close_object (); > + jsps->state = 26; /* close object/array */ > + break; > + > + case '[': > + if (jsf->open_array != NULL) > + jsf->open_array (); > +/* jsps->state = 0; // redundant*/ > + break; > + > + case ']': > + if (jsf->close_array != NULL) > + jsf->close_array (); > + jsps->state = 26; /* close object/array */ > + break; > + > + case 't': > + jsps->state = 7; /* parse true: tr */ > + break; > + > + case 'f': > + jsps->state = 10; /* parse false: fa */ > + break; > + > + case 'n': > + jsps->state = 14; /* parse null: nu */ > + break; > + > + case ':': > + if (jsf->label_value_separator != NULL) > + jsf->label_value_separator (); > +/* jsps->state = 0; // redundant*/ > + break; > + > + case ',': > + if (jsf->sibling_separator != NULL) > + jsf->sibling_separator (); > + jsps->state = 27; /* sibling followup */ > + break; > + > + case '0': > + jsps->string_length_limit_reached = 0; > + jsps->state = 17; /* parse number: 0 */ > + if ((jsps->temp = rcs_create (5)) == NULL) > + { > + return JSON_MEMORY; > + } > + if (rcs_catc ((jsps->temp), '0') != RS_OK) > + { > + return JSON_MEMORY; > + } > + break; > + > + case '1': > + case '2': > + case '3': > + case '4': > + case '5': > + case '6': > + case '7': > + case '8': > + case '9': > + jsps->string_length_limit_reached = 0; > + jsps->state = 24; /* parse number: decimal */ > + if ((jsps->temp = rcs_create (5)) == NULL) > + { > + return JSON_MEMORY; > + } > + if (rcs_catc ((jsps->temp), c) != RS_OK) > + { > + return JSON_MEMORY; > + } > + break; > + > + case '-': > + jsps->string_length_limit_reached = 0; > + jsps->state = 23; /* number: */ > + jsps->temp = NULL; > + if ((jsps->temp = rcs_create (5)) == NULL) > + { > + return JSON_MEMORY; > + } > + if (rcs_catc ((jsps->temp), '-') != RS_OK) > + { > + return JSON_MEMORY; > + } > + > + break; > + > + default: > + return JSON_ILLEGAL_CHARACTER; > + break; > + } > + return JSON_OK; > + } > + > +state1: /* parse string */ > + { > + switch (c) > + { > + case '\\': > + if (!jsps->string_length_limit_reached) > + { > + if (rcs_length ((jsps->temp)) < JSON_MAX_STRING_LENGTH - 1) /* check if there is space for a two character escape sequence */ > + { > + if (rcs_catc ((jsps->temp), '\\') != RS_OK) > + { > + return JSON_MEMORY; > + } > + } > + else > + { > + jsps->string_length_limit_reached = 1; > + } > + } > + jsps->state = 2; /* parse string: escaped character */ > + break; > + > + case '\"': /* end of string */ > + if ((jsps->temp) != NULL) > + { > + jsps->state = 0; /* starting point */ > + if (jsf->new_string != NULL) > + jsf->new_string (((jsps->temp))->text); /*copied or integral? */ > + rcs_free (& jsps->temp); > + } > + else > + return JSON_UNKNOWN_PROBLEM; > + break; > + > + default: > + if (!jsps->string_length_limit_reached) > + { > + if (rcs_length ((jsps->temp)) < JSON_MAX_STRING_LENGTH) /* check if there is space for a two character escape sequence */ > + { > + if (rcs_catc ((jsps->temp), c) != RS_OK) > + { > + return JSON_MEMORY; > + } > + } > + else > + { > + jsps->string_length_limit_reached = 1; > + } > + } > + break; > + } > + return JSON_OK; > + } > + > +state2: /* parse string: escaped character */ > + { > + switch (c) > + { > + case '\"': > + case '\\': > + case '/': > + case 'b': > + case 'f': > + case 'n': > + case 'r': > + case 't': > + if (!jsps->string_length_limit_reached) > + { > + if (rcs_length ((jsps->temp)) < JSON_MAX_STRING_LENGTH) > + { > + if (rcs_catc ((jsps->temp), c) != RS_OK) > + { > + return JSON_MEMORY; > + } > + } > + else > + { > + jsps->string_length_limit_reached = 1; > + } > + } > + break; > + > + case 'u': > + if (!jsps->string_length_limit_reached) > + { > + if (rcs_length ((jsps->temp)) < JSON_MAX_STRING_LENGTH - 4) > + { > + if (rcs_catc ((jsps->temp), 'u') != RS_OK) > + { > + return JSON_MEMORY; > + } > + } > + else > + { > + jsps->string_length_limit_reached = 1; > + } > + } > + jsps->state = 3; /* parse string: escaped unicode 1; */ > + break; > + > + default: > + return JSON_ILLEGAL_CHARACTER; > + break; > + } > + return JSON_OK; > + } > + > +state3: /* parse string: escaped unicode 1 */ > + { > + switch (c) > + { > + case '0': > + case '1': > + case '2': > + case '3': > + case '4': > + case '5': > + case '6': > + case '7': > + case '8': > + case '9': > + case 'a': > + case 'b': > + case 'c': > + case 'd': > + case 'e': > + case 'f': > + case 'A': > + case 'B': > + case 'C': > + case 'D': > + case 'E': > + case 'F': > + if (!jsps->string_length_limit_reached) > + { > + if (rcs_length ((jsps->temp)) < JSON_MAX_STRING_LENGTH - 3) > + { > + if (rcs_catc ((jsps->temp), 'u') != RS_OK) > + { > + return JSON_MEMORY; > + } > + } > + else > + { > + jsps->string_length_limit_reached = 1; > + } > + } > + jsps->state = 4; /* parse string. escaped unicode 2 */ > + break; > + > + default: > + return JSON_ILLEGAL_CHARACTER; > + } > + return JSON_OK; > + } > + > +state4: /* parse string: escaped unicode 2 */ > + { > + switch (c) > + { > + case '0': > + case '1': > + case '2': > + case '3': > + case '4': > + case '5': > + case '6': > + case '7': > + case '8': > + case '9': > + case 'a': > + case 'b': > + case 'c': > + case 'd': > + case 'e': > + case 'f': > + case 'A': > + case 'B': > + case 'C': > + case 'D': > + case 'E': > + case 'F': > + if (!jsps->string_length_limit_reached) > + { > + if (rcs_length ((jsps->temp)) < JSON_MAX_STRING_LENGTH - 2) > + { > + if (rcs_catc ((jsps->temp), c) != RS_OK) > + { > + return JSON_MEMORY; > + } > + } > + else > + { > + jsps->string_length_limit_reached = 1; > + } > + } > + jsps->state = 5; /* parse string. escaped unicode 3 */ > + break; > + > + default: > + return JSON_ILLEGAL_CHARACTER; > + } > + return JSON_OK; > + } > + > +state5: /* parse string: escaped unicode 3 */ > + { > + switch (c) > + { > + case '0': > + case '1': > + case '2': > + case '3': > + case '4': > + case '5': > + case '6': > + case '7': > + case '8': > + case '9': > + case 'a': > + case 'b': > + case 'c': > + case 'd': > + case 'e': > + case 'f': > + case 'A': > + case 'B': > + case 'C': > + case 'D': > + case 'E': > + case 'F': > + if (!jsps->string_length_limit_reached) > + { > + if (rcs_length ((jsps->temp)) < JSON_MAX_STRING_LENGTH - 1) > + { > + if (rcs_catc ((jsps->temp), c) != RS_OK) > + { > + return JSON_MEMORY; > + } > + } > + else > + { > + jsps->string_length_limit_reached = 1; > + } > + } > + jsps->state = 6; /* parse string. escaped unicode 4 */ > + break; > + > + default: > + return JSON_ILLEGAL_CHARACTER; > + } > + return JSON_OK; > + } > + > +state6: /* parse string: escaped unicode 4 */ > + { > + switch (c) > + { > + case '0': > + case '1': > + case '2': > + case '3': > + case '4': > + case '5': > + case '6': > + case '7': > + case '8': > + case '9': > + case 'a': > + case 'b': > + case 'c': > + case 'd': > + case 'e': > + case 'f': > + case 'A': > + case 'B': > + case 'C': > + case 'D': > + case 'E': > + case 'F': > + if (!jsps->string_length_limit_reached) > + { > + if (rcs_length ((jsps->temp)) < JSON_MAX_STRING_LENGTH) > + { > + if (rcs_catc ((jsps->temp), c) != RS_OK) > + { > + return JSON_MEMORY; > + } > + } > + else > + { > + jsps->string_length_limit_reached = 1; > + } > + } > + jsps->state = 1; /* parse string */ > + break; > + > + default: > + return JSON_ILLEGAL_CHARACTER; > + } > + return JSON_OK; > + } > + > +state7: /* parse true: tr */ > + { > + if (c != 'r') > + { > + return JSON_ILLEGAL_CHARACTER; > + } > + > + jsps->state = 8; /* parse true: tru */ > + return JSON_OK; > + } > + > +state8: /* parse true: tru */ > + { > + if (c != 'u') > + { > + return JSON_ILLEGAL_CHARACTER; > + } > + > + jsps->state = 9; /* parse true: true */ > + return JSON_OK; > + } > + > +state9: /* parse true: true */ > + { > + if (c != 'e') > + { > + return JSON_ILLEGAL_CHARACTER; > + } > + > + jsps->state = 0; /* back to general state. */ > + if (jsf->new_true != NULL) > + jsf->new_true (); > + return JSON_OK; > + } > + > +state10: /* parse false: fa */ > + { > + if (c != 'a') > + { > + return JSON_ILLEGAL_CHARACTER; > + } > + > + jsps->state = 11; /* parse true: fal */ > + return JSON_OK; > + } > + > +state11: /* parse false: fal */ > + { > + if (c != 'l') > + { > + return JSON_ILLEGAL_CHARACTER; > + } > + > + jsps->state = 12; /* parse true: fals */ > + return JSON_OK; > + } > + > +state12: /* parse false: fals */ > + { > + if (c != 's') > + { > + return JSON_ILLEGAL_CHARACTER; > + } > + > + jsps->state = 13; /* parse true: false */ > + return JSON_OK; > + } > + > +state13: /* parse false: false */ > + { > + if (c != 'e') > + { > + return JSON_ILLEGAL_CHARACTER; > + } > + > + jsps->state = 0; /* general state. everything goes. */ > + if (jsf->new_false != NULL) > + jsf->new_false (); > + return JSON_OK; > + } > + > +state14: /* parse null: nu */ > + { > + if (c != 'u') > + { > + return JSON_ILLEGAL_CHARACTER; > + } > + > + jsps->state = 15; /* parse null: nul */ > + return JSON_OK; > + } > + > +state15: /* parse null: nul */ > + { > + if (c != 'l') > + { > + return JSON_ILLEGAL_CHARACTER; > + } > + > + jsps->state = 16; /* parse null: null */ > + return JSON_OK; > + } > + > +state16: /* parse null: null */ > + { > + if (c != 'l') > + { > + return JSON_ILLEGAL_CHARACTER; > + } > + > + jsps->state = 0; /* general state. everything goes. */ > + if (jsf->new_null != NULL) > + jsf->new_null (); > + return JSON_OK; > + } > + > +state17: /* parse number: 0 */ > + { > + switch (c) > + { > + case '.': > + if ((jsps->temp = rcs_create (5)) == NULL) > + { > + return JSON_MEMORY; > + } > + if (rcs_catc ((jsps->temp), '.') != RS_OK) > + { > + return JSON_MEMORY; > + } > + jsps->state = 18; /* parse number: fraccional part */ > + break; > + > + case '\x20': > + case '\x09': > + case '\x0A': > + case '\x0D': /* JSON insignificant white spaces */ > + if ((jsps->temp) == NULL) > + return JSON_MEMORY; > + if (jsf->new_number != NULL) > + { > + jsf->new_number ((jsps->temp)->text); > + } > + rcs_free (& jsps->temp); > + > + jsps->state = 0; > + break; > + > + case '}': > + if ((jsps->temp) == NULL) > + return JSON_MEMORY; > + if (jsf->new_number != NULL) > + { > + jsf->new_number ((jsps->temp)->text); > + } > + rcs_free (& jsps->temp); > + > + if (jsf->open_object != NULL) > + jsf->close_object (); > + jsps->state = 26; /* close object/array */ > + break; > + > + case ']': > + > + if ((jsps->temp) == NULL) > + return JSON_MEMORY; > + if (jsf->new_number != NULL) > + { > + jsf->new_number ((jsps->temp)->text); > + } > + rcs_free (& jsps->temp); > + > + if (jsf->open_object != NULL) > + jsf->close_array (); > + jsps->state = 26; /* close object/array */ > + break; > + > + case ',': > + > + if ((jsps->temp) == NULL) > + return JSON_MEMORY; > + if (jsf->new_number != NULL) > + { > + jsf->new_number ((jsps->temp)->text); > + } > + rcs_free (& jsps->temp); > + > + if (jsf->open_object != NULL) > + jsf->label_value_separator (); > + jsps->state = 27; /* sibling followup */ > + break; > + > + default: > + return JSON_ILLEGAL_CHARACTER; > + break; > + } > + > + return JSON_OK; > + } > + > +state18: /* parse number: start fraccional part */ > + { > + switch (c) > + { > + case '0': > + case '1': > + case '2': > + case '3': > + case '4': > + case '5': > + case '6': > + case '7': > + case '8': > + case '9': > + if (!jsps->string_length_limit_reached) > + { > + if (rcs_length ((jsps->temp)) < JSON_MAX_STRING_LENGTH / 2) > + { > + if (rcs_catc ((jsps->temp), c) != RS_OK) > + { > + return JSON_MEMORY; > + } > + } > + else > + { > + jsps->string_length_limit_reached = 1; > + } > + } > + jsps->state = 19; /* parse number: fractional part */ > + break; > + > + default: > + return JSON_ILLEGAL_CHARACTER; > + break; > + } > + return JSON_OK; > + } > + > +state19: /* parse number: fraccional part */ > + { > + switch (c) > + { > + case '0': > + case '1': > + case '2': > + case '3': > + case '4': > + case '5': > + case '6': > + case '7': > + case '8': > + case '9': > + if (!jsps->string_length_limit_reached) > + { > + if (rcs_length ((jsps->temp)) < JSON_MAX_STRING_LENGTH / 2) > + { > + if (rcs_catc ((jsps->temp), c) != RS_OK) > + { > + return JSON_MEMORY; > + } > + } > + else > + { > + jsps->string_length_limit_reached = 1; > + } > + } > +/* jsps->state = 19; // parse number: fractional part*/ > + break; > + > + case 'e': > + case 'E': > + if (rcs_catc ((jsps->temp), c) != RS_OK) > + { > + return JSON_MEMORY; > + } > + > + jsps->state = 20; /* parse number: start exponent part */ > + break; > + > + > + case '\x20': > + case '\x09': > + case '\x0A': > + case '\x0D': /* JSON insignificant white spaces */ > + > + if ((jsps->temp) == NULL) > + return JSON_MEMORY; > + if (jsf->new_number != NULL) > + { > + jsf->new_number ((jsps->temp)->text); > + } > + rcs_free (& jsps->temp); > + > + jsps->state = 0; > + break; > + > + case '}': > + > + if ((jsps->temp) == NULL) > + return JSON_MEMORY; > + if (jsf->new_number != NULL) > + { > + jsf->new_number ((jsps->temp)->text); > + } > + rcs_free (& jsps->temp); > + > + if (jsf->open_object != NULL) > + jsf->close_object (); > + jsps->state = 26; /* close object/array */ > + break; > + > + case ']': > + if (jsf->new_number != NULL) > + { > + if ((jsps->temp) == NULL) > + return JSON_MEMORY; > + jsf->new_number ((jsps->temp)->text); > + rcs_free (& jsps->temp); > + } > + else > + { > + rcs_free (& jsps->temp); > + jsps->temp = NULL; > + } > + if (jsf->open_object != NULL) > + jsf->close_array (); > + jsps->state = 26; /* close object/array */ > + break; > + > + case ',': > + > + if ((jsps->temp) == NULL) > + return JSON_MEMORY; > + if (jsf->new_number != NULL) > + { > + jsf->new_number ((jsps->temp)->text); > + } > + rcs_free (& jsps->temp); > + > + if (jsf->label_value_separator != NULL) > + jsf->label_value_separator (); > + jsps->state = 27; /* sibling followup */ > + break; > + > + > + default: > + return JSON_ILLEGAL_CHARACTER; > + break; > + } > + return JSON_OK; > + } > + > +state20: /* parse number: start exponent part */ > + { > + switch (c) > + { > + case '+': > + case '-': > + jsps->string_length_limit_reached = 0; > + if (rcs_catc ((jsps->temp), c) != RS_OK) > + { > + return JSON_MEMORY; > + } > + > + jsps->state = 22; /* parse number: exponent sign part */ > + break; > + > + case '0': > + case '1': > + case '2': > + case '3': > + case '4': > + case '5': > + case '6': > + case '7': > + case '8': > + case '9': > + if (!jsps->string_length_limit_reached) > + { > + if (rcs_length ((jsps->temp)) < JSON_MAX_STRING_LENGTH) > + { > + if (rcs_catc ((jsps->temp), c) != RS_OK) > + { > + return JSON_MEMORY; > + } > + > + } > + else > + { > + jsps->string_length_limit_reached = 1; > + } > + } > + jsps->state = 21; /* parse number: exponent part */ > + break; > + > + default: > + return JSON_ILLEGAL_CHARACTER; > + break; > + } > + return JSON_OK; > + } > + > +state21: /* parse number: exponent part */ > + { > + switch (c) > + { > + case '0': > + case '1': > + case '2': > + case '3': > + case '4': > + case '5': > + case '6': > + case '7': > + case '8': > + case '9': > + if (!jsps->string_length_limit_reached) > + { > + if (rcs_length ((jsps->temp)) < JSON_MAX_STRING_LENGTH) > + { > + if (rcs_catc ((jsps->temp), c) != RS_OK) > + { > + return JSON_MEMORY; > + } > + } > + else > + { > + jsps->string_length_limit_reached = 1; > + } > + } > +/* jsps->state = 21; // parse number: exponent part*/ > + break; > + > + case '\x20': > + case '\x09': > + case '\x0A': > + case '\x0D': /* JSON insignificant white spaces */ > + > + if ((jsps->temp) == NULL) > + return JSON_MEMORY; > + if (jsf->new_number != NULL) > + { > + jsf->new_number ((jsps->temp)->text); > + } > + rcs_free (& jsps->temp); > + > + jsps->state = 0; > + break; > + > + case '}': > + if ((jsps->temp) == NULL) > + return JSON_MEMORY; > + if (jsf->new_number != NULL) > + { > + jsf->new_number ((jsps->temp)->text); > + } > + rcs_free (& jsps->temp); > + > + if (jsf->open_object != NULL) > + jsf->close_object (); > + jsps->state = 26; /* close object */ > + break; > + > + case ']': > + if (jsf->new_number != NULL) > + { > + if ((jsps->temp) == NULL) > + return JSON_MEMORY; > + jsf->new_number ((jsps->temp)->text); > + VIR_FREE(jsps->temp); > + } > + else > + { > + VIR_FREE(jsps->temp); > + jsps->temp = NULL; > + } > + if (jsf->open_object != NULL) > + jsf->close_array (); > + jsps->state = 26; /* close object/array */ > + break; > + > + case ',': > + if (jsf->new_number != NULL) > + { > + if ((jsps->temp) == NULL) > + return JSON_MEMORY; > + jsf->new_number ((jsps->temp)->text); > + VIR_FREE(jsps->temp); > + } > + else > + { > + free (jsps->temp); > + jsps->temp = NULL; > + } > + if (jsf->label_value_separator != NULL) > + jsf->label_value_separator (); > + jsps->state = 27; /* sibling followup */ > + break; > + > + default: > + return JSON_ILLEGAL_CHARACTER; > + break; > + } > + return JSON_OK; > + } > + > +state22: /* parse number: start exponent part */ > + { > + switch (c) > + { > + case '0': > + case '1': > + case '2': > + case '3': > + case '4': > + case '5': > + case '6': > + case '7': > + case '8': > + case '9': > + if (!jsps->string_length_limit_reached) > + { > + if (rcs_length ((jsps->temp)) < JSON_MAX_STRING_LENGTH) > + { > + rcs_catc ((jsps->temp), c); > + } > + else > + { > + jsps->string_length_limit_reached = 1; > + } > + } > + jsps->state = 21; /* parse number: exponent part */ > + break; > + > + default: > + return JSON_ILLEGAL_CHARACTER; > + break; > + } > + return JSON_OK; > + } > + > +state23: /* parse number: start negative */ > + { > + switch (c) > + { > + case '0': > + rcs_catc ((jsps->temp), c); > + jsps->state = 17; /* parse number: 0 */ > + break; > + > + case '1': > + case '2': > + case '3': > + case '4': > + case '5': > + case '6': > + case '7': > + case '8': > + case '9': > + if (!jsps->string_length_limit_reached) > + { > + if (rcs_length ((jsps->temp)) < JSON_MAX_STRING_LENGTH / 2) > + { > + if ((jsps->temp = rcs_create (5)) == NULL) > + { > + return JSON_MEMORY; > + } > + if (rcs_catc ((jsps->temp), c) != RS_OK) > + { > + return JSON_MEMORY; > + } > + else > + { > + jsps->string_length_limit_reached = 1; > + } > + } > + } > + jsps->state = 24; /* parse number: start decimal part */ > + break; > + > + default: > + return JSON_ILLEGAL_CHARACTER; > + break; > + } > + return JSON_OK; > + } > + > +state24: /* parse number: decimal part */ > + { > + switch (c) > + { > + case '0': > + case '1': > + case '2': > + case '3': > + case '4': > + case '5': > + case '6': > + case '7': > + case '8': > + case '9': > + if (!jsps->string_length_limit_reached) > + { > + if (rcs_length ((jsps->temp)) < JSON_MAX_STRING_LENGTH / 2) > + { > + if ((jsps->temp = rcs_create (5)) == NULL) > + { > + return JSON_MEMORY; > + } > + if (rcs_catc ((jsps->temp), c) != RS_OK) > + { > + return JSON_MEMORY; > + } > + } > + else > + { > + jsps->string_length_limit_reached = 1; > + } > + } > +/* jsps->state = 24; // parse number: decimal part*/ > + break; > + > + case '.': > + if ((jsps->temp = rcs_create (5)) == NULL) > + { > + return JSON_MEMORY; > + } > + if (rcs_catc ((jsps->temp), '.') != RS_OK) > + { > + return JSON_MEMORY; > + } > + > + jsps->state = 18; /* parse number: start exponent part */ > + break; > + > + case 'e': > + case 'E': > + if ((jsps->temp = rcs_create (5)) == NULL) > + { > + return JSON_MEMORY; > + } > + if (rcs_catc ((jsps->temp), c) != RS_OK) > + { > + return JSON_MEMORY; > + } > + > + jsps->string_length_limit_reached = 0; /* reset to accept the exponential part */ > + jsps->state = 20; /* parse number: start exponent part */ > + break; > + > + case '\x20': > + case '\x09': > + case '\x0A': > + case '\x0D': /* JSON insignificant white spaces */ > + if ((jsps->temp) == NULL) > + return JSON_MEMORY; > + if (jsf->new_number != NULL) > + { > + jsf->new_number ((jsps->temp)->text); > + } > + rcs_free (& jsps->temp); > + > + jsps->state = 0; > + break; > + > + case '}': > + if ((jsps->temp) == NULL) > + return JSON_MEMORY; > + if (jsf->new_number != NULL) > + { > + jsf->new_number ((jsps->temp)->text); > + } > + rcs_free (& jsps->temp); > + > + if (jsf->open_object != NULL) > + jsf->close_object (); > + jsps->state = 26; /* close object/array */ > + break; > + > + case ']': > + if ((jsps->temp) == NULL) > + return JSON_MEMORY; > + if (jsf->new_number != NULL) > + { > + jsf->new_number ((jsps->temp)->text); > + } > + rcs_free (& jsps->temp); > + > + if (jsf->open_object != NULL) > + jsf->close_array (); > + jsps->state = 26; /* close object/array */ > + break; > + > + case ',': > + if ((jsps->temp) == NULL) > + return JSON_MEMORY; > + if (jsf->new_number != NULL) > + { > + jsf->new_number ((jsps->temp)->text); > + } > + rcs_free (& jsps->temp); > + > + if (jsf->label_value_separator != NULL) > + jsf->label_value_separator (); > + jsps->state = 27; /* sibling followup */ > + break; > + > + default: > + return JSON_ILLEGAL_CHARACTER; > + break; > + } > + return JSON_OK; > + } > + > +state25: /* open object */ > + { > + switch (c) > + { > + case '\x20': > + case '\x09': > + case '\x0A': > + case '\x0D': /* JSON insignificant white spaces */ > + break; > + > + case '\"': > + jsps->temp = NULL; > + jsps->state = 1; > + break; > + > + case '}': > + if (jsf->close_object != NULL) > + jsf->close_object (); > + jsps->state = 26; /* close object */ > + break; > + > + default: > + return JSON_ILLEGAL_CHARACTER; > + break; > + } > + return JSON_OK; > + } > + > +state26: /* close object/array */ > + { > + switch (c) > + { > + case '\x20': > + case '\x09': > + case '\x0A': > + case '\x0D': /* JSON insignificant white spaces */ > + break; > + > + case '}': > + if (jsf->close_object != NULL) > + jsf->close_object (); > +/* jsp->state = 26; // close object*/ > + break; > + > + case ']': > + if (jsf->close_array != NULL) > + jsf->close_array (); > +/* jsps->state = 26; // close object/array*/ > + break; > + > + case ',': > + if (jsf->sibling_separator != NULL) > + jsf->sibling_separator (); > + jsps->state = 27; /* sibling followup */ > + break; > + > + default: > + return JSON_ILLEGAL_CHARACTER; > + break; > + } > + return JSON_OK; > + } > + > +state27: /* sibling followup */ > + { > + switch (c) > + { > + case '\x20': > + case '\x09': > + case '\x0A': > + case '\x0D': /* JSON insignificant white spaces */ > + break; > + > + case '\"': > + jsps->state = 1; > + jsps->temp = NULL; > + break; > + > + case '{': > + if (jsf->open_object != NULL) > + jsf->open_object (); > + jsps->state = 25; /*open object */ > + break; > + > + case '[': > + if (jsf->open_array != NULL) > + jsf->open_array (); > +/* jsps->state = 0; // redundant*/ > + break; > + > + case 't': > + jsps->state = 7; /* parse true: tr */ > + break; > + > + case 'f': > + jsps->state = 10; /* parse false: fa */ > + break; > + > + case 'n': > + jsps->state = 14; /* parse null: nu */ > + break; > + > + case '0': > + jsps->state = 17; /* parse number: 0 */ > + if ((jsps->temp = rcs_create (5)) == NULL) > + { > + return JSON_MEMORY; > + } > + if (rcs_catc ((jsps->temp), '0') != RS_OK) > + { > + return JSON_MEMORY; > + } > + break; > + > + case '1': > + case '2': > + case '3': > + case '4': > + case '5': > + case '6': > + case '7': > + case '8': > + case '9': > + jsps->state = 24; /* parse number: decimal */ > + if ((jsps->temp = rcs_create (5)) == NULL) > + { > + return JSON_MEMORY; > + } > + if (rcs_catc ((jsps->temp), c) != RS_OK) > + { > + return JSON_MEMORY; > + } > + break; > + > + case '-': > + jsps->state = 23; /* number: */ > + if ((jsps->temp = rcs_create (RSTRING_DEFAULT)) == NULL) > + { > + return JSON_MEMORY; > + } > + if (rcs_catc ((jsps->temp), '-') != RS_OK) > + { > + return JSON_MEMORY; > + } > + break; > + > + default: > + return JSON_ILLEGAL_CHARACTER; > + break; > + } > + return JSON_OK; > + } > + > + return JSON_UNKNOWN_PROBLEM; > +} Urgh ... Okay his parsing style and mine don't match ! but come on lex/yacc was invented to avoid having to maintain such code. I'm not objecting, as long as we don't have to fix this code, that's fine. ACK Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@xxxxxxxxxxxx | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/ -- Libvir-list mailing list Libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list