/** * @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 #include /** 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