Write number of bytes read to error position on successful decode
authorPetri Lehtinen <petri@digip.org>
Mon, 23 Jan 2012 19:18:04 +0000 (21:18 +0200)
committerPetri Lehtinen <petri@digip.org>
Mon, 23 Jan 2012 19:18:04 +0000 (21:18 +0200)
Closes #49.

doc/apiref.rst
src/load.c
test/suites/api/test_load.c

index d6b89e3..5003a04 100644 (file)
@@ -675,7 +675,9 @@ and pass a pointer to a function. Example::
    }
 
 Also note that if the call succeeded (``json != NULL`` in the above
    }
 
 Also note that if the call succeeded (``json != NULL`` in the above
-example), the contents of ``error`` are unspecified.
+example), the contents of ``error`` are generally left unspecified.
+The decoding functions write to the ``position`` member also on
+success. See :ref:`apiref-decoding` for more info.
 
 All functions also accept *NULL* as the :type:`json_error_t` pointer,
 in which case no error information is returned to the caller.
 
 All functions also accept *NULL* as the :type:`json_error_t` pointer,
 in which case no error information is returned to the caller.
@@ -819,6 +821,17 @@ macros can be ORed together to obtain *flags*.
 
    .. versionadded:: 2.1
 
 
    .. versionadded:: 2.1
 
+``JSON_DECODE_ANY``
+   By default, the decoder expects an array or object as the input.
+   With this flag enabled, the decoder accepts any valid JSON value.
+
+   **Note:** Decoding any value may be useful in some scenarios, but
+   it's generally discouraged as it violates strict compatiblity with
+   :rfc:`4627`. If you use this flag, don't expect interoperatibility
+   with other JSON systems.
+
+   .. versionadded:: 2.3
+
 ``JSON_DISABLE_EOF_CHECK``
    By default, the decoder expects that its whole input constitutes a
    valid JSON text, and issues an error if there's extra data after
 ``JSON_DISABLE_EOF_CHECK``
    By default, the decoder expects that its whole input constitutes a
    valid JSON text, and issues an error if there's extra data after
@@ -826,18 +839,28 @@ macros can be ORed together to obtain *flags*.
    stops after decoding a valid JSON array or object, and thus allows
    extra data after the JSON text.
 
    stops after decoding a valid JSON array or object, and thus allows
    extra data after the JSON text.
 
+   Normally, reading will stop when the last ``]`` or ``}`` in the
+   JSON input is encountered. If both ``JSON_DISABLE_EOF_CHECK`` and
+   ``JSON_DECODE_ANY`` flags are used, the decoder may read one extra
+   UTF-8 code unit (up to 4 bytes of input). For example, decoding
+   ``4true`` correctly decodes the integer 4, but also reads the
+   ``t``. For this reason, if reading multiple consecutive values that
+   are not arrays or objects, they should be separated by at least one
+   whitespace character.
+
    .. versionadded:: 2.1
 
    .. versionadded:: 2.1
 
-``JSON_DECODE_ANY``
-   By default, the decoder expects an array or object as the input.
-   With this flag enabled, the decoder accepts any valid JSON value.
+Each function also takes an optional :type:`json_error_t` parameter
+that is filled with error information if decoding fails. It's also
+updated on success; the number of bytes of input read is written to
+its ``position`` field. This is especially useful when using
+``JSON_DISABLE_EOF_CHECK`` to read multiple consecutive JSON texts.
 
 
-   **Note:** Decoding any value may be useful in some scenarios, but
-   it's generally discouraged as it violates strict compatiblity with
-   :rfc:`4627`. If you use this flag, don't expect interoperatibility
-   with other JSON systems.
+.. versionadded:: 2.3
+   Number of bytes of input read is written to the ``position`` field
+   of the :type:`json_error_t` structure.
 
 
-   .. versionadded:: 2.3
+If no error or position information is needed, you can pass *NULL*.
 
 The following functions perform the actual JSON decoding.
 
 
 The following functions perform the actual JSON decoding.
 
@@ -880,14 +903,6 @@ The following functions perform the actual JSON decoding.
    multiple times, if the input consists of consecutive JSON texts,
    possibly separated by whitespace.
 
    multiple times, if the input consists of consecutive JSON texts,
    possibly separated by whitespace.
 
-   If both ``JSON_DISABLE_EOF_CHECK`` and ``JSON_DECODE_ANY`` flags
-   are used, the decoder may read one extra UTF-8 code unit (up to 4
-   bytes of input). For example, decoding ``4true`` correctly decodes
-   the integer 4, but leaves the file position pointing at ``r``
-   instead of ``t``. For this reason, if reading multiple consecutive
-   values that are not arrays and objects, they should be separated by
-   at least one whitespace character.
-
 .. function:: json_t *json_load_file(const char *path, size_t flags, json_error_t *error)
 
    .. refcounting:: new
 .. function:: json_t *json_load_file(const char *path, size_t flags, json_error_t *error)
 
    .. refcounting:: new
index f5cbf68..193db45 100644 (file)
@@ -836,10 +836,15 @@ static json_t *parse_json(lex_t *lex, size_t flags, json_error_t *error)
         if(lex->token != TOKEN_EOF) {
             error_set(error, lex, "end of file expected");
             json_decref(result);
         if(lex->token != TOKEN_EOF) {
             error_set(error, lex, "end of file expected");
             json_decref(result);
-            result = NULL;
+            return NULL;
         }
     }
 
         }
     }
 
+    if(error) {
+        /* Save the position even though there was no error */
+        error->position = lex->stream.position;
+    }
+
     return result;
 }
 
     return result;
 }
 
index 8143d46..d8cb912 100644 (file)
@@ -98,6 +98,23 @@ static void load_wrong_args()
         fail("json_loadf should return NULL if the first argument is NULL");
 }
 
         fail("json_loadf should return NULL if the first argument is NULL");
 }
 
+static void position()
+{
+    json_t *json;
+    size_t flags = JSON_DISABLE_EOF_CHECK;
+    json_error_t error;
+
+    json = json_loads("{\"foo\": \"bar\"}", 0, &error);
+    if(error.position != 14)
+        fail("json_loads returned a wrong position");
+    json_decref(json);
+
+    json = json_loads("{\"foo\": \"bar\"} baz quux", flags, &error);
+    if(error.position != 14)
+        fail("json_loads returned a wrong position");
+    json_decref(json);
+}
+
 static void run_tests()
 {
     file_not_found();
 static void run_tests()
 {
     file_not_found();
@@ -105,4 +122,5 @@ static void run_tests()
     disable_eof_check();
     decode_any();
     load_wrong_args();
     disable_eof_check();
     decode_any();
     load_wrong_args();
+    position();
 }
 }