123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442 |
- /*
- * sfparse
- *
- * Copyright (c) 2023 sfparse contributors
- * Copyright (c) 2019 nghttp3 contributors
- * Copyright (c) 2015 nghttp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
- #ifndef SFPARSE_H
- #define SFPARSE_H
- /* Define WIN32 when build target is Win32 API (borrowed from
- libcurl) */
- #if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32)
- # define WIN32
- #endif /* (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32) */
- #ifdef __cplusplus
- extern "C" {
- #endif /* defined(__cplusplus) */
- #if defined(_MSC_VER) && (_MSC_VER < 1800)
- /* MSVC < 2013 does not have inttypes.h because it is not C99
- compliant. See compiler macros and version number in
- https://sourceforge.net/p/predef/wiki/Compilers/ */
- # include <stdint.h>
- #else /* !(defined(_MSC_VER) && (_MSC_VER < 1800)) */
- # include <inttypes.h>
- #endif /* !(defined(_MSC_VER) && (_MSC_VER < 1800)) */
- #include <sys/types.h>
- #include <stddef.h>
- /**
- * @enum
- *
- * :type:`sfparse_type` defines value type.
- */
- typedef enum sfparse_type {
- /**
- * :enum:`SFPARSE_TYPE_BOOLEAN` indicates boolean type.
- */
- SFPARSE_TYPE_BOOLEAN,
- /**
- * :enum:`SFPARSE_TYPE_INTEGER` indicates integer type.
- */
- SFPARSE_TYPE_INTEGER,
- /**
- * :enum:`SFPARSE_TYPE_DECIMAL` indicates decimal type.
- */
- SFPARSE_TYPE_DECIMAL,
- /**
- * :enum:`SFPARSE_TYPE_STRING` indicates string type.
- */
- SFPARSE_TYPE_STRING,
- /**
- * :enum:`SFPARSE_TYPE_TOKEN` indicates token type.
- */
- SFPARSE_TYPE_TOKEN,
- /**
- * :enum:`SFPARSE_TYPE_BYTESEQ` indicates byte sequence type.
- */
- SFPARSE_TYPE_BYTESEQ,
- /**
- * :enum:`SFPARSE_TYPE_INNER_LIST` indicates inner list type.
- */
- SFPARSE_TYPE_INNER_LIST,
- /**
- * :enum:`SFPARSE_TYPE_DATE` indicates date type.
- */
- SFPARSE_TYPE_DATE,
- /**
- * :enum:`SFPARSE_TYPE_DISPSTRING` indicates display string type.
- */
- SFPARSE_TYPE_DISPSTRING
- } sfparse_type;
- /**
- * @macro
- *
- * :macro:`SFPARSE_ERR_PARSE` indicates fatal parse error has
- * occurred, and it is not possible to continue the processing.
- */
- #define SFPARSE_ERR_PARSE -1
- /**
- * @macro
- *
- * :macro:`SFPARSE_ERR_EOF` indicates that there is nothing left to
- * read. The context of this error varies depending on the function
- * that returns this error code.
- */
- #define SFPARSE_ERR_EOF -2
- /**
- * @struct
- *
- * :type:`sfparse_vec` stores sequence of bytes.
- */
- typedef struct sfparse_vec {
- /**
- * :member:`base` points to the beginning of the sequence of bytes.
- */
- uint8_t *base;
- /**
- * :member:`len` is the number of bytes contained in this sequence.
- */
- size_t len;
- } sfparse_vec;
- /**
- * @macro
- *
- * :macro:`SFPARSE_VALUE_FLAG_NONE` indicates no flag set.
- */
- #define SFPARSE_VALUE_FLAG_NONE 0x0u
- /**
- * @macro
- *
- * :macro:`SFPARSE_VALUE_FLAG_ESCAPED_STRING` indicates that a string
- * contains escaped character(s).
- */
- #define SFPARSE_VALUE_FLAG_ESCAPED_STRING 0x1u
- /**
- * @struct
- *
- * :type:`sfparse_decimal` contains decimal value.
- */
- typedef struct sfparse_decimal {
- /**
- * :member:`numer` contains numerator of the decimal value.
- */
- int64_t numer;
- /**
- * :member:`denom` contains denominator of the decimal value.
- */
- int64_t denom;
- } sfparse_decimal;
- /**
- * @struct
- *
- * :type:`sfparse_value` stores a Structured Field item. For Inner
- * List, only type is set to
- * :enum:`sfparse_type.SFPARSE_TYPE_INNER_LIST`. In order to read the
- * items contained in an inner list, call `sfparse_parser_inner_list`.
- */
- typedef struct sfparse_value {
- /**
- * :member:`type` is the type of the value contained in this
- * particular object.
- */
- sfparse_type type;
- /**
- * :member:`flags` is bitwise OR of one or more of
- * :macro:`SFPARSE_VALUE_FLAG_* <SFPARSE_VALUE_FLAG_NONE>`.
- */
- uint32_t flags;
- /**
- * @anonunion_start
- *
- * @sfparse_value_value
- */
- union {
- /**
- * :member:`boolean` contains boolean value if :member:`type` ==
- * :enum:`sfparse_type.SFPARSE_TYPE_BOOLEAN`. 1 indicates true,
- * and 0 indicates false.
- */
- int boolean;
- /**
- * :member:`integer` contains integer value if :member:`type` is
- * either :enum:`sfparse_type.SFPARSE_TYPE_INTEGER` or
- * :enum:`sfparse_type.SFPARSE_TYPE_DATE`.
- */
- int64_t integer;
- /**
- * :member:`decimal` contains decimal value if :member:`type` ==
- * :enum:`sfparse_type.SFPARSE_TYPE_DECIMAL`.
- */
- sfparse_decimal decimal;
- /**
- * :member:`vec` contains sequence of bytes if :member:`type` is
- * either :enum:`sfparse_type.SFPARSE_TYPE_STRING`,
- * :enum:`sfparse_type.SFPARSE_TYPE_TOKEN`,
- * :enum:`sfparse_type.SFPARSE_TYPE_BYTESEQ`, or
- * :enum:`sfparse_type.SFPARSE_TYPE_DISPSTRING`.
- *
- * For :enum:`sfparse_type.SFPARSE_TYPE_STRING`, this field
- * contains one or more escaped characters if :member:`flags` has
- * :macro:`SFPARSE_VALUE_FLAG_ESCAPED_STRING` set. To unescape
- * the string, use `sfparse_unescape`.
- *
- * For :enum:`sfparse_type.SFPARSE_TYPE_BYTESEQ`, this field
- * contains base64 encoded string. To decode this byte string,
- * use `sfparse_base64decode`.
- *
- * For :enum:`sfparse_type.SFPARSE_TYPE_DISPSTRING`, this field
- * may contain percent-encoded UTF-8 byte sequences. To decode
- * it, use `sfparse_pctdecode`.
- *
- * If :member:`vec.len <sfparse_vec.len>` == 0, :member:`vec.base
- * <sfparse_vec.base>` is guaranteed to be NULL.
- */
- sfparse_vec vec;
- /**
- * @anonunion_end
- */
- };
- } sfparse_value;
- /**
- * @struct
- *
- * :type:`sfparse_parser` is the Structured Field Values parser. Use
- * `sfparse_parser_init` to initialize it.
- */
- typedef struct sfparse_parser {
- /* all fields are private */
- const uint8_t *pos;
- const uint8_t *end;
- uint32_t state;
- } sfparse_parser;
- /**
- * @function
- *
- * `sfparse_parser_init` initializes |sfp| with the given data encoded
- * in Structured Field Values pointed by |data| of length |datalen|.
- */
- void sfparse_parser_init(sfparse_parser *sfp, const uint8_t *data,
- size_t datalen);
- /**
- * @function
- *
- * `sfparse_parser_param` reads a parameter. If this function returns
- * 0, it stores parameter key and value in |dest_key| and |dest_value|
- * respectively, if they are not NULL.
- *
- * This function does no effort to find duplicated keys. Same key may
- * be reported more than once.
- *
- * Caller should keep calling this function until it returns negative
- * error code. If it returns :macro:`SFPARSE_ERR_EOF`, all parameters
- * have read, and caller can continue to read rest of the values. If
- * it returns :macro:`SFPARSE_ERR_PARSE`, it encountered fatal error
- * while parsing field value.
- */
- int sfparse_parser_param(sfparse_parser *sfp, sfparse_vec *dest_key,
- sfparse_value *dest_value);
- /**
- * @function
- *
- * `sfparse_parser_dict` reads the next dictionary key and value pair.
- * If this function returns 0, it stores the key and value in
- * |dest_key| and |dest_value| respectively, if they are not NULL.
- *
- * Caller can optionally read parameters attached to the pair by
- * calling `sfparse_parser_param`.
- *
- * This function does no effort to find duplicated keys. Same key may
- * be reported more than once.
- *
- * Caller should keep calling this function until it returns negative
- * error code. If it returns :macro:`SFPARSE_ERR_EOF`, all key and
- * value pairs have been read, and there is nothing left to read.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * :macro:`SFPARSE_ERR_EOF`
- * All values in the dictionary have read.
- * :macro:`SFPARSE_ERR_PARSE`
- * It encountered fatal error while parsing field value.
- */
- int sfparse_parser_dict(sfparse_parser *sfp, sfparse_vec *dest_key,
- sfparse_value *dest_value);
- /**
- * @function
- *
- * `sfparse_parser_list` reads the next list item. If this function
- * returns 0, it stores the item in |dest| if it is not NULL.
- *
- * Caller can optionally read parameters attached to the item by
- * calling `sfparse_parser_param`.
- *
- * Caller should keep calling this function until it returns negative
- * error code. If it returns :macro:`SFPARSE_ERR_EOF`, all values in
- * the list have been read, and there is nothing left to read.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * :macro:`SFPARSE_ERR_EOF`
- * All values in the list have read.
- * :macro:`SFPARSE_ERR_PARSE`
- * It encountered fatal error while parsing field value.
- */
- int sfparse_parser_list(sfparse_parser *sfp, sfparse_value *dest);
- /**
- * @function
- *
- * `sfparse_parser_item` reads a single item. If this function
- * returns 0, it stores the item in |dest| if it is not NULL.
- *
- * This function is only used for the field value that consists of a
- * single item.
- *
- * Caller can optionally read parameters attached to the item by
- * calling `sfparse_parser_param`.
- *
- * Caller should call this function again to make sure that there is
- * nothing left to read. If this 2nd function call returns
- * :macro:`SFPARSE_ERR_EOF`, all data have been processed
- * successfully.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * :macro:`SFPARSE_ERR_EOF`
- * There is nothing left to read.
- * :macro:`SFPARSE_ERR_PARSE`
- * It encountered fatal error while parsing field value.
- */
- int sfparse_parser_item(sfparse_parser *sfp, sfparse_value *dest);
- /**
- * @function
- *
- * `sfparse_parser_inner_list` reads the next inner list item. If
- * this function returns 0, it stores the item in |dest| if it is not
- * NULL.
- *
- * Caller can optionally read parameters attached to the item by
- * calling `sfparse_parser_param`.
- *
- * Caller should keep calling this function until it returns negative
- * error code. If it returns :macro:`SFPARSE_ERR_EOF`, all values in
- * this inner list have been read, and caller can optionally read
- * parameters attached to this inner list by calling
- * `sfparse_parser_param`. Then caller can continue to read rest of
- * the values.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * :macro:`SFPARSE_ERR_EOF`
- * All values in the inner list have read.
- * :macro:`SFPARSE_ERR_PARSE`
- * It encountered fatal error while parsing field value.
- */
- int sfparse_parser_inner_list(sfparse_parser *sfp, sfparse_value *dest);
- /**
- * @function
- *
- * `sfparse_unescape` copies |src| to |dest| by removing escapes
- * (``\``). |src| should be the pointer to
- * :member:`sfparse_value.vec` of type
- * :enum:`sfparse_type.SFPARSE_TYPE_STRING` produced by either
- * `sfparse_parser_dict`, `sfparse_parser_list`,
- * `sfparse_parser_inner_list`, `sfparse_parser_item`, or
- * `sfparse_parser_param`, otherwise the behavior is undefined.
- *
- * :member:`dest->base <sfparse_vec.base>` must point to the buffer
- * that has sufficient space to store the unescaped string. The
- * memory areas pointed by :member:`dest->base <sfparse_vec.base>` and
- * :member:`src->base <sfparse_vec.base>` must not overlap.
- *
- * This function sets the length of unescaped string to
- * :member:`dest->len <sfparse_vec.len>`.
- */
- void sfparse_unescape(sfparse_vec *dest, const sfparse_vec *src);
- /**
- * @function
- *
- * `sfparse_base64decode` decodes Base64 encoded string |src| and
- * writes the result into |dest|. |src| should be the pointer to
- * :member:`sfparse_value.vec` of type
- * :enum:`sfparse_type.SFPARSE_TYPE_BYTESEQ` produced by either
- * `sfparse_parser_dict`, `sfparse_parser_list`,
- * `sfparse_parser_inner_list`, `sfparse_parser_item`, or
- * `sfparse_parser_param`, otherwise the behavior is undefined.
- *
- * :member:`dest->base <sfparse_vec.base>` must point to the buffer
- * that has sufficient space to store the decoded byte string.
- *
- * This function sets the length of decoded byte string to
- * :member:`dest->len <sfparse_vec.len>`.
- */
- void sfparse_base64decode(sfparse_vec *dest, const sfparse_vec *src);
- /**
- * @function
- *
- * `sfparse_pctdecode` decodes percent-encoded string |src| and writes
- * the result into |dest|. |src| should be the pointer to
- * :member:`sfparse_value.vec` of type
- * :enum:`sfparse_type.SFPARSE_TYPE_DISPSTRING` produced by either
- * `sfparse_parser_dict`, `sfparse_parser_list`,
- * `sfparse_parser_inner_list`, `sfparse_parser_item`, or
- * `sfparse_parser_param`, otherwise the behavior is undefined.
- *
- * :member:`dest->base <sfparse_vec.base>` must point to the buffer
- * that has sufficient space to store the decoded byte string. The
- * memory areas pointed by :member:`dest->base <sfparse_vec.base>` and
- * :member:`src->base <sfparse_vec.base>` must not overlap.
- *
- * This function sets the length of decoded byte string to
- * :member:`dest->len <sfparse_vec.len>`.
- */
- void sfparse_pctdecode(sfparse_vec *dest, const sfparse_vec *src);
- #ifdef __cplusplus
- }
- #endif /* defined(__cplusplus) */
- #endif /* !defined(SFPARSE_H) */
|