/* Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * @file apr_json.h * @brief APR-UTIL JSON Library */ #ifndef APR_JSON_H #define APR_JSON_H /** * @defgroup APR_Util_JSON JSON Encoding and Decoding * @ingroup APR_Util * @{ */ #include "apr.h" #include "apr_pools.h" #include "apr_tables.h" #include "apr_hash.h" #include "apr_strings.h" #include "apr_buckets.h" #ifdef __cplusplus extern "C" { #endif /** * @package Apache JSON library * * RFC8259 compliant JSON encoding and decoding library. * * https://tools.ietf.org/html/rfc8259 * * This API generates UTF-8 encoded JSON, and writes it to the * bucket brigade specified. All strings are verified as valid UTF-8 * before processing, with invalid UTF-8 characters replaced. * * This API parses UTF-8 encoded JSON, and returns the result as * a set of structures. All JSON strings are unescaped. Any bad * characters or formatting will cause parsing to be terminated * and an error returned, along with the offset of the error. * * Whitespace may be optionally preserved or ignored as required * during generation and parsing. * * The ordering of object keys is preserved, allowing the decode and * encode process to reproduce an identical result. This maintains * stable behaviour during unit tests. */ /** * When passing a string to one of the encode functions, this value can be * passed to indicate a string-valued key, and have the length computed * automatically. */ #define APR_JSON_VALUE_STRING (-1) /** * Flag indicating no special processing. */ #define APR_JSON_FLAGS_NONE 0 /** * Flag indicating include whitespace. */ #define APR_JSON_FLAGS_WHITESPACE 1 /** * Flag indicating strict overlay. */ #define APR_JSON_FLAGS_STRICT 2 /** * A structure to hold a JSON object. */ typedef struct apr_json_object_t apr_json_object_t; /** * A structure to hold a JSON array. */ typedef struct apr_json_array_t apr_json_array_t; /** * Enum that represents the type of the given JSON value. */ typedef enum apr_json_type_e { APR_JSON_OBJECT, APR_JSON_ARRAY, APR_JSON_STRING, APR_JSON_LONG, APR_JSON_DOUBLE, APR_JSON_BOOLEAN, APR_JSON_NULL } apr_json_type_e; /** * A structure to hold a UTF-8 encoded JSON string. */ typedef struct apr_json_string_t { /** pointer to the string */ const char *p; /** string length, or APR_JSON_VALUE_STRING to compute length automatically */ apr_ssize_t len; } apr_json_string_t; /** * A structure that holds a JSON value. * * Use apr_json_value_create() to allocate. */ typedef struct apr_json_value_t { /** Links to the rest of the values if in an array */ APR_RING_ENTRY(apr_json_value_t) link; /** preceding whitespace, if any */ const char *pre; /** trailing whitespace, if any */ const char *post; /** type of the value */ apr_json_type_e type; /** actual value. which member is valid depends on type. */ union { /** JSON object */ apr_json_object_t *object; /** JSON array */ apr_json_array_t *array; /** JSON floating point value */ double dnumber; /** JSON long integer value */ apr_int64_t lnumber; /** JSON UTF-8 encoded string value */ apr_json_string_t string; /** JSON boolean value */ int boolean; } value; } apr_json_value_t; /** * A structure to hold a JSON object key value pair. * * Use apr_json_object_set() to allocate. */ typedef struct apr_json_kv_t { /** Links to the rest of the kv pairs */ APR_RING_ENTRY(apr_json_kv_t) link; /** the key */ apr_json_value_t *k; /** the value */ apr_json_value_t *v; } apr_json_kv_t; /** * A structure to hold a JSON object. * * Use apr_json_object_create() to allocate. */ struct apr_json_object_t { /** The key value pairs in the object are in this list */ APR_RING_HEAD(apr_json_object_list_t, apr_json_kv_t) list; /** JSON object */ apr_hash_t *hash; }; /** * A structure to hold a JSON array. * * Use apr_json_array_create() to allocate. */ struct apr_json_array_t { /** The key value pairs in the object are in this list */ APR_RING_HEAD(apr_json_array_list_t, apr_json_value_t) list; /** Array of JSON objects */ apr_array_header_t *array; }; /** * Allocate and return a apr_json_value_t structure. * * @param pool The pool to allocate from. * @return The apr_json_value_t structure. */ APR_DECLARE(apr_json_value_t *) apr_json_value_create(apr_pool_t *pool) __attribute__((nonnull(1))); /** * Allocate and return a JSON string with the given value. * * @param pool The pool to allocate from. * @param val The UTF-8 encoded string value. * @param len The length of the string, or APR_JSON_VALUE_STRING. * @return The apr_json_value_t structure. */ APR_DECLARE(apr_json_value_t *) apr_json_string_create(apr_pool_t *pool, const char *val, apr_ssize_t len) __attribute__((nonnull(1))); /** * Allocate and return a JSON array. * * @param pool The pool to allocate from. * @param nelts the number of elements in the initial array * @return The apr_json_value_t structure. */ APR_DECLARE(apr_json_value_t *) apr_json_array_create(apr_pool_t *pool, int nelts) __attribute__((nonnull(1))); /** * Allocate and return a JSON object. * * @param pool The pool to allocate from. * @return The apr_json_value_t structure. */ APR_DECLARE(apr_json_value_t *) apr_json_object_create(apr_pool_t *pool) __attribute__((nonnull(1))); /** * Allocate and return a JSON long. * * @param pool The pool to allocate from. * @param lnumber The long value. * @return The apr_json_value_t structure. */ APR_DECLARE(apr_json_value_t *) apr_json_long_create(apr_pool_t *pool, apr_int64_t lnumber) __attribute__((nonnull(1))); /** * Allocate and return a JSON double. * * @param pool The pool to allocate from. * @param dnumber The double value. * @return The apr_json_value_t structure. */ APR_DECLARE(apr_json_value_t *) apr_json_double_create(apr_pool_t *pool, double dnumber) __attribute__((nonnull(1))); /** * Allocate and return a JSON boolean. * * @param pool The pool to allocate from. * @param boolean The boolean value. * @return The apr_json_value_t structure. */ APR_DECLARE(apr_json_value_t *) apr_json_boolean_create(apr_pool_t *pool, int boolean) __attribute__((nonnull(1))); /** * Allocate and return a JSON null. * * @param pool The pool to allocate from. * @return The apr_json_value_t structure. */ APR_DECLARE(apr_json_value_t *) apr_json_null_create(apr_pool_t *pool) __attribute__((nonnull(1))); /** * Associate a value with a key in a JSON object. * @param obj The JSON object. * @param key Pointer to the key string. * @param klen Length of the key, or APR_JSON_VALUE_STRING if NUL * terminated. * @param val Value to associate with the key. * @param pool Pool to use. * @return APR_SUCCESS on success, APR_EINVAL if the key is * NULL or not a string, or the object is not an APR_JSON_OBJECT. * @remark If the value is NULL the key value pair is deleted. */ APR_DECLARE(apr_status_t) apr_json_object_set(apr_json_value_t *obj, const char *key, apr_ssize_t klen, apr_json_value_t *val, apr_pool_t *pool) __attribute__((nonnull(1, 2, 5))); /** * Associate a value with a key in a JSON object, preserving whitespace. * @param obj The JSON object. * @param key Pointer to the key string, including any whitespace * required. * @param val Value to associate with the key. * @param pool Pool to use. * @return APR_SUCCESS on success, APR_EINVAL if the key is * NULL or not a string, or the object is not an APR_JSON_OBJECT. * @remark If the value is NULL the key value pair is deleted. */ APR_DECLARE(apr_status_t) apr_json_object_set_ex(apr_json_value_t *obj, apr_json_value_t *key, apr_json_value_t *val, apr_pool_t *pool) __attribute__((nonnull(1, 2, 4))); /** * Look up the value associated with a key in a JSON object. * @param obj The JSON object. * @param key Pointer to the key. * @param klen Length of the key, or APR_JSON_VALUE_STRING if NUL * terminated. * @return Returns NULL if the key is not present. */ APR_DECLARE(apr_json_kv_t *) apr_json_object_get(apr_json_value_t *obj, const char *key, apr_ssize_t klen) __attribute__((nonnull(1, 2))); /** * Get the first value associated with an object. * * If the value is an object, this function returns the first key value pair. * @param obj The JSON object. * @return Returns the first value, or NULL if not an object, or the object is * empty. */ APR_DECLARE(apr_json_kv_t *) apr_json_object_first(apr_json_value_t *obj) __attribute__((nonnull(1)));; /** * Get the next value associated with an object. * * This function returns the next key value pair, or NULL if no more pairs * are present. * @param obj The JSON object. * @param kv The previous JSON key value pair. * @return Returns the next key value pair, or NULL if not an object, or * the object is empty. */ APR_DECLARE(apr_json_kv_t *) apr_json_object_next(apr_json_value_t *obj, apr_json_kv_t *kv) __attribute__((nonnull(1, 2)));; /** * Add the value to the end of this array. * @param arr The JSON array. * @param val Value to add to the array. * @return APR_SUCCESS on success, APR_EINVAL if the array value is not * an APR_JSON_ARRAY. */ APR_DECLARE(apr_status_t) apr_json_array_add(apr_json_value_t *arr, apr_json_value_t *val) __attribute__((nonnull(1, 2))); /** * Look up the value associated with a key in a JSON object. * @param arr The JSON array. * @param index The index of the element in the array. * @return Returns NULL if the element is out of bounds. */ APR_DECLARE(apr_json_value_t *) apr_json_array_get(apr_json_value_t *arr, int index) __attribute__((nonnull(1))); /** * Get the first value associated with an array. * * If the value is an array, this function returns the first value. * @param arr The JSON array. * @return Returns the first value, or NULL if not an array, or the array is * empty. */ APR_DECLARE(apr_json_value_t *) apr_json_array_first(const apr_json_value_t *arr) __attribute__((nonnull(1)));; /** * Get the next value associated with an array. * * This function returns the next value in the array, or NULL if no more * values are present. * @param arr The JSON array. * @param val The previous element of the array. * @return Returns the next value in the array, or NULL if not an array, or * we have reached the end of the array. */ APR_DECLARE(apr_json_value_t *) apr_json_array_next(const apr_json_value_t *arr, const apr_json_value_t *val) __attribute__((nonnull(1, 2)));; /** * Decode utf8-encoded JSON string into apr_json_value_t. * @param retval the result * @param injson utf8-encoded JSON string. * @param size length of the input string. * @param offset number of characters processed. * @param flags set to APR_JSON_FLAGS_WHITESPACE to preserve whitespace, * or APR_JSON_FLAGS_NONE to filter whitespace. * @param level maximum nesting level we are prepared to decode. * @param pool pool used to allocate the result from. * @return APR_SUCCESS on success, APR_EOF if the JSON text is truncated. * APR_BADCH when a decoding error has occurred (the location of the error * is at offset), APR_EINVAL if the level has been exceeded, or * APR_ENOTIMPL on platforms where not implemented. */ APR_DECLARE(apr_status_t) apr_json_decode(apr_json_value_t ** retval, const char *injson, apr_ssize_t size, apr_off_t * offset, int flags, int level, apr_pool_t * pool) __attribute__((nonnull(1, 2, 7))); /** * Encode data represented as apr_json_value_t to utf8-encoded JSON string * and append it to the specified brigade. * * All JSON strings are checked for invalid UTF-8 character sequences, * and if found invalid sequences are replaced with the replacement * character "�" (U+FFFD). * * @param brigade brigade the result will be appended to. * @param flush optional flush function for the brigade. Can be NULL. * @param ctx optional contaxt for the flush function. Can be NULL. * @param json the JSON data. * @param flags set to APR_JSON_FLAGS_WHITESPACE to preserve whitespace, * or APR_JSON_FLAGS_NONE to filter whitespace. * @param pool pool used to allocate the buckets from. * @return APR_SUCCESS on success, or APR_ENOTIMPL on platforms where not * implemented. */ APR_DECLARE(apr_status_t) apr_json_encode(apr_bucket_brigade * brigade, apr_brigade_flush flush, void *ctx, const apr_json_value_t * json, int flags, apr_pool_t * pool) __attribute__((nonnull(1, 4, 6))); /** * Overlay one JSON value over a second JSON value. * * If the values are objects, a new object will be returned containing * all keys from the overlay superimposed on the base. * * Keys that appear in the overlay will replace keys in the base, unless * APR_JSON_FLAGS_STRICT is specified, in which case NULL will be returned. * * If either the base or the overlay are not objects, overlay will be * returned. * @param p pool to use * @param overlay the JSON object to overlay on top of base. If NULL, the * base will be returned. * @param base the base JSON object. If NULL, the overlay will be returned. * @param flags set to APR_JSON_FLAGS_STRICT to fail if object keys are not * unique, or APR_JSON_FLAGS_NONE to replace keys in base with overlay. * @return A new object containing the result. If APR_JSON_FLAGS_STRICT was * specified and a key was present in overlay that was also present in base, * NULL will be returned. */ APR_DECLARE(apr_json_value_t *) apr_json_overlay(apr_pool_t *p, apr_json_value_t *overlay, apr_json_value_t *base, int flags) __attribute__((nonnull(1)));; #ifdef __cplusplus } #endif /** @} */ #endif /* APR_JSON_H */