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(a)veillard.com | Rpmfind RPM search engine
http://rpmfind.net/
http://veillard.com/ | virtualization library
http://libvirt.org/