blob: b0776551e3d3b5bc542d47c0d1f46696b5aedd80 [file] [log] [blame]
/* 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 */