Design

Interruptible

the interruptible parser permits the user to incrementally parse data. each time new data is passed to the parser, the parser potentially emits call back to the caller to give a found value, and every time update its internal state machine. this state machine will returns an error when the data passed doesn't end up beeing a JSON compliant stream.

Because of the interruptibility of the parser, the caller is in charge of feeding data to the parser, which give the flexibility to the caller to channel the data to the parser in its own ways. for example, embedded stream of json in another stream, can dynamically and without extra allocation, be passed to the parser. this effectively decoupled the parser from the stream of data.

This also reduce the API related to parser's input to only one function, instead of specific functions to parse a string in memory, a C FILE handler, a unix file descriptor, etc.

No Object Model

There's no object model embedded in the library. This way the object model is left to the caller wants and needs. like a SAX API, the parser callback on opening and closing structures, and also for every data values.

The caller is free to represent a json object as a GLIB hashtable, an handmade chained list, etc. The same is true for any JSON types. This cut down the usual rewritting of the library object tree to the native object tree after parsing that takes memory and cpu time.

Callback without native conversion

Float and int are passed to the caller directly as a string. Since JSON integer and float are not limited to a specific size, this is up to the caller to specify how to read the string. for example one implementation can choose to represent the json int as very big int (GMP), but some other implementation can choose 64 bits int and truncate data.

If the callback return a non null value, the parser will return failure, so that you can stop the parsing.

Security aspects

The design of the library is to emphasis security. the event based parser, the carefully secure crafted code, and the optional limits in place means that the parser can be put on the front line and will behave in front of DoS and huge data.

The parser supports maximum size in the data buffer for string/float/int and supports a maximum nesting level.

If the data limit is set to 0, the buffer will double when necessary.

If the nestimg limit is set to 0, the stack will double when necessary.

All string data are passed to the caller with an explicit size; NULL bytes can be handled properly.