spa_json_init assumes that we start in an object and always requires a
key/value pair. If the last part is a key, it returns and error and does
not want to return the key value.
This causes problems when parsing AUX0,AUX1,AUX2 or any relaxed array
withand odd number of elements.
Make a new spa_json_init_relax that takes the type of the container
we're assuming we're in and set the state of the parser to array when we
are parsing a relaxed array.
Fixes#4944
Including C headers inside of `extern "C"` breaks use from C++. Hoist
the includes of standard C headers above the block so we don't try
to mangle the stdlib.
I initially tried to scope this with a targeted change but it's too
hard to do correctly that way. This way, we avoid whack-a-mole.
Firefox is working around this in their e21461b7b8b39cc31ba53c47d4f6f310c673ff2f
commit.
Bug: https://bugzilla.mozilla.org/1953080
Use the helper instead of duplicating the same code.
Also add some helpers to parse a json array of uint32_t
Move some functions to convert between type name and id.
This gets the next key and value from an object. This function is better
because it will skip key/value pairs that don't fit in the array to hold
the key.
The previous code patter would stop parsing the object as soon as a key
larger than the available space was found.
Add spa_json_begin_array/object to replace
spa_json_init+spa_json_begin_array/object
This function is better because it does not waste a useless spa_json
structure as an iterator. The relaxed versions also error out when the
container is mismatched because parsing a mismatched container is not
going to give any results anyway.
Add struct spa_error_location that holds information about some parsing
context such as the line and column number, error and line fragment
with the error.
Make spa_json_get_error() fill in the spa_error_location instead. Add
some error codes to the error state and use this to add a parsing reason
to the location.
Add a debug function to log the error location in a nice way. Also
add a FILE based debug context to log to any FILE.
Replace pw_properties_check_string() with
pw_properties_update_string_checked() and add
pw_properties_new_string_checked(). The check string behaviour can still
be done by setting props to NULL but the main purpose is to be able to
avoid parsing the json file twice in the future.
When using the old pw_properties_update_string(), log a warning to the
log when we fail to parse the complete string.
Use the new checked functions and the debug functions to report about
parsing errors in the tools and conf parsing.
This gives errors like:
```
> pw-loopback --playback-props '{ foo = [ f : g ] }'
error: syntax error in --playback-props: Invalid array separator
line: 1 | { foo = [ f : g ] }
col: 14 | ^
```
Check each object key is associated with value. Disallow object or
array valued keys.
Add flag tracking whether the parser is at global top-level or not, as
there we may either be in object context or in a single-value context.
Save depth=0 array flag bit in state, so that spa_json_next preserves
its complete state across calls. The higher-depth flag bits can be in
temporary stack as they are not needed across calls.
Control characters probably are an error. We also are not validating any
utf8 here, so disallow bare utf8 too --- one likely should use strings
for such content anyway as spaces are not allowed otherwise.
Successful return is always >= 2 since it includes {} or [], so use 0 to
indicate error.
Since there's existing code that doesn't check the return value, it's
better to use 0 for errors as it'll likely to just lead to producing an
empty string if the value is not checked.
Disallow = and : as bare items in [] containers, as that likely is
"[ { foo = bar } ]" mistyped as "[ foo = bar ]".
Disallow nesting errors, eg. "[ foo bar" or "[ foo bar }".
Fix handling of ", \ and # in bare strings.
Fix ignoring trailing comments.
Add a fixed-size stack (128 levels) to the tokenizer, so that it can
check these at levels below its depth.
When the tokenizer encounters an error, make it and its parents enter
error state where no further input will be processed. This allows caller
to check for parse errors later as convenient.
The error state can be queried using spa_json_get_error, which also
looks up the error line/column position.
spa_json_parse_float/int receive non nul-terminated string, so calling
string functions assuming nul-termination is invalid.
Fix by copying data to a buffer before doing parsing.
spa_json_parse_stringn() can be used when the strings source and
destination are overlapping so use memmove instead of strncpy to
avoid corruption of the strings.
added cleanup of unused variables and fix warning about missing initializers
to resolve build warnings in pipewire-rs
Signed-off-by: Dorinda Bassey <dbassey@redhat.com>
We need exactly 4 hex characters, everything else is refused. We
also copy those characters directly to the output string without
assuming any encoding.
See #2337
And use this in spa_json_format_float() where we also avoid invalid
json floats.
Use json float format in some places where we serialize json floats.
Add a unit test.
See #2223
The Doxygen "Modules" page is not very illuminative, as different parts
of the API are mixed together and not all parts are included.
Try to address this:
Put all parts of the public API to some Doxygen group, usually one group
per header file. Use short, systematic names.
Make these groups sub-groups of a few top-level groups, roughly
corresponding to the different logical parts of the API (core, impl,
stream, filter, spa, utilities).
Subdirectories buffer, control, debug, monitor, pod, support and utils, others
are still missing. Headers are grouped either per subdirectory (e.g. buffer/
gets added to group spa_buffer) or per-file (e.g. spa_json is a separate
group), whatever seemed like the most sensible approach.
We can't move past the } or ] or we might miss the end of the
container. Now that we ignore \0 it is not a problem if the \0
is placed at the container boundary.