[libvirt] [PATCH 14/15] Import basic JSON parsing / formatting helper code
Daniel Veillard
veillard at redhat.com
Wed Nov 4 17:51:37 UTC 2009
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 at veillard.com | Rpmfind RPM search engine http://rpmfind.net/
http://veillard.com/ | virtualization library http://libvirt.org/
More information about the libvir-list
mailing list