diff options
Diffstat (limited to 'src/json.h')
| -rw-r--r-- | src/json.h | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/src/json.h b/src/json.h new file mode 100644 index 0000000..4d41714 --- /dev/null +++ b/src/json.h @@ -0,0 +1,82 @@ +/** + * @file json.h + * @brief Minimal JSON reader, internal to this library. + * + * Read-only, allocation-per-node, no streaming and no writer. It is here + * because C ships no JSON parser and the shapes this client has to read are + * small and fixed. It handles the whole grammar it is fed: UTF-8 throughout, + * `\uXXXX` escapes with surrogate pairs, and the full number syntax. + */ +#ifndef CEPIS_JSON_H +#define CEPIS_JSON_H + +#include <stdbool.h> +#include <stddef.h> + +/** Deepest nesting accepted, so a hostile body cannot exhaust the stack. */ +#define JSON_MAX_DEPTH 64 + +/** Kind of a ::json_value_t. */ +typedef enum json_type { + JSON_NULL, + JSON_BOOL, + JSON_NUMBER, + JSON_STRING, + JSON_ARRAY, + JSON_OBJECT +} json_type_t; + +typedef struct json_value json_value_t; + +/** A parsed JSON value. Owns everything it points at. */ +struct json_value { + json_type_t type; + union { + bool boolean; + double number; + /** NUL-terminated UTF-8, escapes already decoded. */ + char *string; + struct { + json_value_t **items; + size_t count; + } array; + struct { + char **keys; + json_value_t **values; + size_t count; + } object; + } as; +}; + +/** + * @brief Parse @p len bytes of JSON. + * @return The root value, owned by the caller, or `NULL` when @p text is not + * one complete JSON value followed only by whitespace. + */ +json_value_t *json_parse(const char *text, size_t len); + +/** @brief Release a value and everything below it. `NULL` is ignored. */ +void json_free(json_value_t *value); + +/** + * @brief Look a key up in an object. + * @return The member, borrowed from @p object, or `NULL` when @p object is not + * an object or has no such key. The first match wins. + */ +const json_value_t *json_object_get(const json_value_t *object, + const char *key); + +/** @brief The string a value holds, or `NULL` when it is not a string. */ +const char *json_as_string(const json_value_t *value); + +/** + * @brief Read a value as a number, accepting a numeric string. + * @return `false` when the value is absent or cannot be read as a number, in + * which case @p out is untouched. + */ +bool json_as_double(const json_value_t *value, double *out); + +/** @brief Like ::json_as_double, truncating towards zero. */ +bool json_as_llong(const json_value_t *value, long long *out); + +#endif |