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
-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.
@@ -819,6 +821,17 @@ macros can be ORed together to obtain *flags*.
 
    .. 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
@@ -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.
 
+   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
 
-``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.
 
@@ -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.
 
-   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
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);
-            result = NULL;
+            return NULL;
         }
     }
 
+    if(error) {
+        /* Save the position even though there was no error */
+        error->position = lex->stream.position;
+    }
+
     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");
 }
 
+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();
@@ -105,4 +122,5 @@ static void run_tests()
     disable_eof_check();
     decode_any();
     load_wrong_args();
+    position();
 }