Write number of bytes read to error position on successful decode

Closes #49.
This commit is contained in:
Petri Lehtinen 2012-01-23 21:18:04 +02:00
parent bb24697d9b
commit f471e63bb3
3 changed files with 57 additions and 19 deletions

View 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,15 +821,6 @@ macros can be ORed together to obtain *flags*.
.. versionadded:: 2.1
``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
the otherwise valid JSON input. With this flag enabled, the decoder
stops after decoding a valid JSON array or object, and thus allows
extra data after the JSON text.
.. 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.
@ -839,6 +832,36 @@ macros can be ORed together to obtain *flags*.
.. 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
the otherwise valid JSON input. With this flag enabled, the decoder
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
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.
.. versionadded:: 2.3
Number of bytes of input read is written to the ``position`` field
of the :type:`json_error_t` structure.
If no error or position information is needed, you can pass *NULL*.
The following functions perform the actual JSON decoding.
.. function:: json_t *json_loads(const char *input, size_t flags, json_error_t *error)
@ -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

View 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;
}

View 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();
}