
On Tue, Nov 03, 2009 at 02:50:08PM -0500, Daniel P. Berrange wrote:
Import JSON parsing / formatting helper code based on code from
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@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/