[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