]> thyrsus.com Git - microjson.git/commitdiff
Set the end pointer when erroring out.
authorEric S. Raymond <esr@thyrsus.com>
Fri, 26 Sep 2014 21:01:31 +0000 (17:01 -0400)
committerEric S. Raymond <esr@thyrsus.com>
Fri, 26 Sep 2014 21:01:31 +0000 (17:01 -0400)
mjson.asc
mjson.c

index 04790008fbe29a07db303a0abed43f690d97b7f4..0826f22c64d310f66ead051c5cda46351166c1cb 100644 (file)
--- a/mjson.asc
+++ b/mjson.asc
@@ -47,6 +47,9 @@ The two main functions return 0 for success, a nonzero error code for
 failure.  The function +json_error_string()+ maps error codes to
 explanatory messages.
 
+When an error is returned and the end pointer argument
+is non-null, it is filled with the value of the buffer
+pointer at the time the error was thrown. 
 == BUGS ==
 A backslash escape of "\0000" in a string value will drop a NUL in the 
 string that is likely to confuse C code looking at the storage.  In
diff --git a/mjson.c b/mjson.c
index 799fa34f985575f7be06efe5b12d6b190af6bd2f..25fd00b1bd8e8434c2bff8da4dbf806f8171db99 100644 (file)
--- a/mjson.c
+++ b/mjson.c
@@ -237,6 +237,8 @@ static int json_internal_read_object(const char *cp,
            else {
                json_debug_trace((1,
                                  "Non-WS when expecting object start.\n"));
+               if (end)
+                   *end = cp;
                return JSON_ERR_OBSTART;
            }
            break;
@@ -250,12 +252,17 @@ static int json_internal_read_object(const char *cp,
                break;
            else {
                json_debug_trace((1, "Non-WS when expecting attribute.\n"));
+               if (end)
+                   *end = cp;
                return JSON_ERR_ATTRSTART;
            }
            break;
        case in_attr:
-           if (pattr == NULL)
+           if (pattr == NULL) {
+               if (end)
+                   *end = cp;
                return JSON_ERR_NULLPTR;
+           }
            if (*cp == '"') {
                *pattr++ = '\0';
                json_debug_trace((1, "Collected attribute name %s\n",
@@ -284,6 +291,8 @@ static int json_internal_read_object(const char *cp,
                pval = valbuf;
            } else if (pattr >= attrbuf + JSON_ATTR_MAX - 1) {
                json_debug_trace((1, "Attribute name too long.\n"));
+               if (end)
+                   *end = cp;
                return JSON_ERR_ATTRLEN;
            } else
                *pattr++ = *cp;
@@ -295,6 +304,8 @@ static int json_internal_read_object(const char *cp,
                if (cursor->type != t_array) {
                    json_debug_trace((1,
                                      "Saw [ when not expecting array.\n"));
+                   if (end)
+                       *end = cp;
                    return JSON_ERR_NOARRAY;
                }
                substatus = json_read_array(cp, &cursor->addr.array, &cp);
@@ -304,6 +315,8 @@ static int json_internal_read_object(const char *cp,
            } else if (cursor->type == t_array) {
                json_debug_trace((1,
                                  "Array element was specified, but no [.\n"));
+               if (end)
+                   *end = cp;
                return JSON_ERR_NOBRAK;
            } else if (*cp == '"') {
                value_quoted = true;
@@ -317,8 +330,11 @@ static int json_internal_read_object(const char *cp,
            }
            break;
        case in_val_string:
-           if (pval == NULL)
+           if (pval == NULL) {
+               if (end)
+                   *end = cp;
                return JSON_ERR_NULLPTR;
+           }
            if (*cp == '\\')
                state = in_escape;
            else if (*cp == '"') {
@@ -328,13 +344,18 @@ static int json_internal_read_object(const char *cp,
            } else if (pval > valbuf + JSON_VAL_MAX - 1
                       || pval > valbuf + maxlen) {
                json_debug_trace((1, "String value too long.\n"));
+               if (end)
+                   *end = cp;
                return JSON_ERR_STRLONG;        /*  */
            } else
                *pval++ = *cp;
            break;
        case in_escape:
-           if (pval == NULL)
+           if (pval == NULL) {
+               if (end)
+                   *end = cp;
                return JSON_ERR_NULLPTR;
+           }
            switch (*cp) {
            case 'b':
                *pval++ = '\b';
@@ -365,8 +386,11 @@ static int json_internal_read_object(const char *cp,
            state = in_val_string;
            break;
        case in_val_token:
-           if (pval == NULL)
+           if (pval == NULL) {
+               if (end)
+                   *end = cp;
                return JSON_ERR_NULLPTR;
+           }
            if (isspace((unsigned char) *cp) || *cp == ',' || *cp == '}') {
                *pval = '\0';
                json_debug_trace((1, "Collected token value %s.\n", valbuf));
@@ -375,6 +399,8 @@ static int json_internal_read_object(const char *cp,
                    --cp;
            } else if (pval > valbuf + JSON_VAL_MAX - 1) {
                json_debug_trace((1, "Token value too long.\n"));
+               if (end)
+                   *end = cp;
                return JSON_ERR_TOKLONG;
            } else
                *pval++ = *cp;
@@ -414,6 +440,8 @@ static int json_internal_read_object(const char *cp,
                    && cursor->type != t_ignore && cursor->map == 0)) {
                json_debug_trace((1,
                                  "Saw quoted value when expecting non-string.\n"));
+               if (end)
+                   *end = cp;
                return JSON_ERR_QNONSTRING;
            }
            if (!value_quoted
@@ -421,6 +449,8 @@ static int json_internal_read_object(const char *cp,
                    || cursor->map != 0)) {
                json_debug_trace((1,
                                  "Didn't see quoted value when expecting string.\n"));
+               if (end)
+                   *end = cp;
                return JSON_ERR_NONQSTRING;
            }
            if (cursor->map != 0) {
@@ -430,6 +460,8 @@ static int json_internal_read_object(const char *cp,
                    }
                json_debug_trace((1, "Invalid enumerated value string %s.\n",
                                  valbuf));
+               if (end)
+                   *end = cp;
                return JSON_ERR_BADENUM;
              foundit:
                (void)snprintf(valbuf, sizeof(valbuf), "%d", mp->value);
@@ -470,8 +502,11 @@ static int json_internal_read_object(const char *cp,
                    }
                    break;
                case t_character:
-                   if (strlen(valbuf) > 1)
+                   if (strlen(valbuf) > 1) {
+                       if (end)
+                           *end = cp;
                        return JSON_ERR_STRLONG;
+                   }
                    else
                        lptr[0] = valbuf[0];
                    break;
@@ -485,6 +520,8 @@ static int json_internal_read_object(const char *cp,
                        json_debug_trace((1,
                                          "Required attribute value %s not present.\n",
                                          cursor->dflt.check));
+                       if (end)
+                           *end = cp;
                        return JSON_ERR_CHECKFAIL;
                    }
                    break;
@@ -500,6 +537,8 @@ static int json_internal_read_object(const char *cp,
                goto good_parse;
            } else {
                json_debug_trace((1, "Garbage while expecting comma or }\n"));
+               if (end)
+                   *end = cp;
                return JSON_ERR_BADTRAIL;
            }
            break;