Initialize their reference counts to (unsigned int)-1 to disable
reference counting on them. It already was meant to work like this,
but the reference counts were just initialized to 1 instead of -1.
Thanks to Andrew Thompson for reporting this issue.
With this encoding flag, the object key-value pairs in output are in
the same order in which they were first inserted into the object.
To make this possible, a key of an object is now a serial number plus
a string. An object keeps an increasing counter which is used to
assign serial number to the keys. Hashing, comparison and public API
functions were changed to act only on the string part, i.e. the serial
number is ignored everywhere else but in the encoder, where it's used
to order object keys if JSON_PRESERVE_ORDER flag is used.
When the property already exists in the object, we can store an
iterator pointing to that property, instead of duplicating the key.
When the property (key) is not present in the object, we still have to
duplicate the key.
If a user happens to store an ElementProxy or a PropertyProxy
instance, we need to take a reference to the JSON value they point to.
With PropertyProxy, the key needs to be copied as well.
Added functions are:
* json_string_nocheck()
* json_string_set_nocheck()
* json_object_set_nocheck()
* json_object_set_new_nocheck()
These functions don't check that their string argument is valid UTF-8,
but assume that the user has already performed the check.
This patch changes the sprintf format from "%0.17f" to "%.17g", as the
f format specifier doesn't print the exponent at all. This caused
losing precision in all but the most simple cases.
Because the g specifier doesn't print the decimal fraction or exponent
if they're not needed, a ".0" has to be appended by hand in these
cases. Otherwise the value's type changes from real to integer when
decoding again.
Thanks to Philip Grandinetti for reporting this issue.
- Never append newline to output
- By default, add spaces between array and object items for more
readable output
- Introduce the flag JSON_COMPACT to not add the aforementioned spaces
Failing to do this has the effect that the error message is not
returned when the input file cannot be opened (e.g. if it doesn't
exist).
Thanks to Martin Vopatek for reporting.
It's now an error to try to add an object or array to itself. The
encoder checks for circular references and fails with an error status
if one is detected.
Added functions:
json_string_set
json_integer_set
json_real_set
While at it, clarify the documentation and parameter naming of
json_{string,integer,real}_value() a bit.
Some day we will have ANSI C compatibility... This change doesn't make
the API backwards incompatible because uint32_t was only used in flags
to json_dump*() and the flags are meant to be used only by ORing
constants and macro output, and actually currently only JSON_INDENT
can be used.
In stream_get(), EOF never got it to stream->buffer and because of
this, stream_unget() failed on some situations. This patch makes
stream_get() handle EOF just like any other byte.
As a "side effect", lex_scan_string() now needs to unget the EOF, or
otherwise it ends up in error message on premature end of input.
All pointer arguments are now tested for NULL. json_string() now also
tests that strdup() succeeds. This is to ensure that no NULL values
end up in data structures.
Also desribe the different sources of errors in documentation.
Don't alloca() a whitespace buffer and fill it with spaces in each
call to dump_indent. Instead, use a static whitespace buffer.
As a bonus, this saves the use of poorly portable alloca().
Before, only the syntax level (parse_*) was able to set the error
string. This patch fixes the situation so that lexical (lex_*) and
stream (stream_*) levels can report detailed error messages.
Also, instead of 0, EOF is now returned by stream on error.
It's no longer needed to load the whole input into a string and then
parse from the string. Instead, the input is read as needed from
a string or file.
Before, json_loads checked for '[' or '{' at the beginning. Now
there's a dedicated function for that: parse_json(). Also rename
parse() to parse_value().