12c593315Sopenharmony_ci/*
22c593315Sopenharmony_ci * sfparse
32c593315Sopenharmony_ci *
42c593315Sopenharmony_ci * Copyright (c) 2023 sfparse contributors
52c593315Sopenharmony_ci * Copyright (c) 2019 nghttp3 contributors
62c593315Sopenharmony_ci * Copyright (c) 2015 nghttp2 contributors
72c593315Sopenharmony_ci *
82c593315Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining
92c593315Sopenharmony_ci * a copy of this software and associated documentation files (the
102c593315Sopenharmony_ci * "Software"), to deal in the Software without restriction, including
112c593315Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish,
122c593315Sopenharmony_ci * distribute, sublicense, and/or sell copies of the Software, and to
132c593315Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to
142c593315Sopenharmony_ci * the following conditions:
152c593315Sopenharmony_ci *
162c593315Sopenharmony_ci * The above copyright notice and this permission notice shall be
172c593315Sopenharmony_ci * included in all copies or substantial portions of the Software.
182c593315Sopenharmony_ci *
192c593315Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
202c593315Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
212c593315Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
222c593315Sopenharmony_ci * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
232c593315Sopenharmony_ci * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
242c593315Sopenharmony_ci * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
252c593315Sopenharmony_ci * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
262c593315Sopenharmony_ci */
272c593315Sopenharmony_ci#ifndef SFPARSE_H
282c593315Sopenharmony_ci#define SFPARSE_H
292c593315Sopenharmony_ci
302c593315Sopenharmony_ci/* Define WIN32 when build target is Win32 API (borrowed from
312c593315Sopenharmony_ci   libcurl) */
322c593315Sopenharmony_ci#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32)
332c593315Sopenharmony_ci#  define WIN32
342c593315Sopenharmony_ci#endif
352c593315Sopenharmony_ci
362c593315Sopenharmony_ci#ifdef __cplusplus
372c593315Sopenharmony_ciextern "C" {
382c593315Sopenharmony_ci#endif
392c593315Sopenharmony_ci
402c593315Sopenharmony_ci#if defined(_MSC_VER) && (_MSC_VER < 1800)
412c593315Sopenharmony_ci/* MSVC < 2013 does not have inttypes.h because it is not C99
422c593315Sopenharmony_ci   compliant.  See compiler macros and version number in
432c593315Sopenharmony_ci   https://sourceforge.net/p/predef/wiki/Compilers/ */
442c593315Sopenharmony_ci#  include <stdint.h>
452c593315Sopenharmony_ci#else /* !defined(_MSC_VER) || (_MSC_VER >= 1800) */
462c593315Sopenharmony_ci#  include <inttypes.h>
472c593315Sopenharmony_ci#endif /* !defined(_MSC_VER) || (_MSC_VER >= 1800) */
482c593315Sopenharmony_ci#include <sys/types.h>
492c593315Sopenharmony_ci#include <stddef.h>
502c593315Sopenharmony_ci
512c593315Sopenharmony_ci/**
522c593315Sopenharmony_ci * @enum
532c593315Sopenharmony_ci *
542c593315Sopenharmony_ci * :type:`sf_type` defines value type.
552c593315Sopenharmony_ci */
562c593315Sopenharmony_citypedef enum sf_type {
572c593315Sopenharmony_ci  /**
582c593315Sopenharmony_ci   * :enum:`SF_TYPE_BOOLEAN` indicates boolean type.
592c593315Sopenharmony_ci   */
602c593315Sopenharmony_ci  SF_TYPE_BOOLEAN,
612c593315Sopenharmony_ci  /**
622c593315Sopenharmony_ci   * :enum:`SF_TYPE_INTEGER` indicates integer type.
632c593315Sopenharmony_ci   */
642c593315Sopenharmony_ci  SF_TYPE_INTEGER,
652c593315Sopenharmony_ci  /**
662c593315Sopenharmony_ci   * :enum:`SF_TYPE_DECIMAL` indicates decimal type.
672c593315Sopenharmony_ci   */
682c593315Sopenharmony_ci  SF_TYPE_DECIMAL,
692c593315Sopenharmony_ci  /**
702c593315Sopenharmony_ci   * :enum:`SF_TYPE_STRING` indicates string type.
712c593315Sopenharmony_ci   */
722c593315Sopenharmony_ci  SF_TYPE_STRING,
732c593315Sopenharmony_ci  /**
742c593315Sopenharmony_ci   * :enum:`SF_TYPE_TOKEN` indicates token type.
752c593315Sopenharmony_ci   */
762c593315Sopenharmony_ci  SF_TYPE_TOKEN,
772c593315Sopenharmony_ci  /**
782c593315Sopenharmony_ci   * :enum:`SF_TYPE_BYTESEQ` indicates byte sequence type.
792c593315Sopenharmony_ci   */
802c593315Sopenharmony_ci  SF_TYPE_BYTESEQ,
812c593315Sopenharmony_ci  /**
822c593315Sopenharmony_ci   * :enum:`SF_TYPE_INNER_LIST` indicates inner list type.
832c593315Sopenharmony_ci   */
842c593315Sopenharmony_ci  SF_TYPE_INNER_LIST,
852c593315Sopenharmony_ci  /**
862c593315Sopenharmony_ci   * :enum:`SF_TYPE_DATE` indicates date type.
872c593315Sopenharmony_ci   */
882c593315Sopenharmony_ci  SF_TYPE_DATE
892c593315Sopenharmony_ci} sf_type;
902c593315Sopenharmony_ci
912c593315Sopenharmony_ci/**
922c593315Sopenharmony_ci * @macro
932c593315Sopenharmony_ci *
942c593315Sopenharmony_ci * :macro:`SF_ERR_PARSE_ERROR` indicates fatal parse error has
952c593315Sopenharmony_ci * occurred, and it is not possible to continue the processing.
962c593315Sopenharmony_ci */
972c593315Sopenharmony_ci#define SF_ERR_PARSE_ERROR -1
982c593315Sopenharmony_ci
992c593315Sopenharmony_ci/**
1002c593315Sopenharmony_ci * @macro
1012c593315Sopenharmony_ci *
1022c593315Sopenharmony_ci * :macro:`SF_ERR_EOF` indicates that there is nothing left to read.
1032c593315Sopenharmony_ci * The context of this error varies depending on the function that
1042c593315Sopenharmony_ci * returns this error code.
1052c593315Sopenharmony_ci */
1062c593315Sopenharmony_ci#define SF_ERR_EOF -2
1072c593315Sopenharmony_ci
1082c593315Sopenharmony_ci/**
1092c593315Sopenharmony_ci * @struct
1102c593315Sopenharmony_ci *
1112c593315Sopenharmony_ci * :type:`sf_vec` stores sequence of bytes.
1122c593315Sopenharmony_ci */
1132c593315Sopenharmony_citypedef struct sf_vec {
1142c593315Sopenharmony_ci  /**
1152c593315Sopenharmony_ci   * :member:`base` points to the beginning of the sequence of bytes.
1162c593315Sopenharmony_ci   */
1172c593315Sopenharmony_ci  uint8_t *base;
1182c593315Sopenharmony_ci  /**
1192c593315Sopenharmony_ci   * :member:`len` is the number of bytes contained in this sequence.
1202c593315Sopenharmony_ci   */
1212c593315Sopenharmony_ci  size_t len;
1222c593315Sopenharmony_ci} sf_vec;
1232c593315Sopenharmony_ci
1242c593315Sopenharmony_ci/**
1252c593315Sopenharmony_ci * @macro
1262c593315Sopenharmony_ci *
1272c593315Sopenharmony_ci * :macro:`SF_VALUE_FLAG_NONE` indicates no flag set.
1282c593315Sopenharmony_ci */
1292c593315Sopenharmony_ci#define SF_VALUE_FLAG_NONE 0x0u
1302c593315Sopenharmony_ci
1312c593315Sopenharmony_ci/**
1322c593315Sopenharmony_ci * @macro
1332c593315Sopenharmony_ci *
1342c593315Sopenharmony_ci * :macro:`SF_VALUE_FLAG_ESCAPED_STRING` indicates that a string
1352c593315Sopenharmony_ci * contains escaped character(s).
1362c593315Sopenharmony_ci */
1372c593315Sopenharmony_ci#define SF_VALUE_FLAG_ESCAPED_STRING 0x1u
1382c593315Sopenharmony_ci
1392c593315Sopenharmony_ci/**
1402c593315Sopenharmony_ci * @struct
1412c593315Sopenharmony_ci *
1422c593315Sopenharmony_ci * :type:`sf_decimal` contains decimal value.
1432c593315Sopenharmony_ci */
1442c593315Sopenharmony_citypedef struct sf_decimal {
1452c593315Sopenharmony_ci  /**
1462c593315Sopenharmony_ci   * :member:`numer` contains numerator of the decimal value.
1472c593315Sopenharmony_ci   */
1482c593315Sopenharmony_ci  int64_t numer;
1492c593315Sopenharmony_ci  /**
1502c593315Sopenharmony_ci   * :member:`denom` contains denominator of the decimal value.
1512c593315Sopenharmony_ci   */
1522c593315Sopenharmony_ci  int64_t denom;
1532c593315Sopenharmony_ci} sf_decimal;
1542c593315Sopenharmony_ci
1552c593315Sopenharmony_ci/**
1562c593315Sopenharmony_ci * @struct
1572c593315Sopenharmony_ci *
1582c593315Sopenharmony_ci * :type:`sf_value` stores a Structured Field item.  For Inner List,
1592c593315Sopenharmony_ci * only type is set to :enum:`sf_type.SF_TYPE_INNER_LIST`.  In order
1602c593315Sopenharmony_ci * to read the items contained in an inner list, call
1612c593315Sopenharmony_ci * `sf_parser_inner_list`.
1622c593315Sopenharmony_ci */
1632c593315Sopenharmony_citypedef struct sf_value {
1642c593315Sopenharmony_ci  /**
1652c593315Sopenharmony_ci   * :member:`type` is the type of the value contained in this
1662c593315Sopenharmony_ci   * particular object.
1672c593315Sopenharmony_ci   */
1682c593315Sopenharmony_ci  sf_type type;
1692c593315Sopenharmony_ci  /**
1702c593315Sopenharmony_ci   * :member:`flags` is bitwise OR of one or more of
1712c593315Sopenharmony_ci   * :macro:`SF_VALUE_FLAG_* <SF_VALUE_FLAG_NONE>`.
1722c593315Sopenharmony_ci   */
1732c593315Sopenharmony_ci  uint32_t flags;
1742c593315Sopenharmony_ci  /**
1752c593315Sopenharmony_ci   * @anonunion_start
1762c593315Sopenharmony_ci   *
1772c593315Sopenharmony_ci   * @sf_value_value
1782c593315Sopenharmony_ci   */
1792c593315Sopenharmony_ci  union {
1802c593315Sopenharmony_ci    /**
1812c593315Sopenharmony_ci     * :member:`boolean` contains boolean value if :member:`type` ==
1822c593315Sopenharmony_ci     * :enum:`sf_type.SF_TYPE_BOOLEAN`.  1 indicates true, and 0
1832c593315Sopenharmony_ci     * indicates false.
1842c593315Sopenharmony_ci     */
1852c593315Sopenharmony_ci    int boolean;
1862c593315Sopenharmony_ci    /**
1872c593315Sopenharmony_ci     * :member:`integer` contains integer value if :member:`type` is
1882c593315Sopenharmony_ci     * either :enum:`sf_type.SF_TYPE_INTEGER` or
1892c593315Sopenharmony_ci     * :enum:`sf_type.SF_TYPE_DATE`.
1902c593315Sopenharmony_ci     */
1912c593315Sopenharmony_ci    int64_t integer;
1922c593315Sopenharmony_ci    /**
1932c593315Sopenharmony_ci     * :member:`decimal` contains decimal value if :member:`type` ==
1942c593315Sopenharmony_ci     * :enum:`sf_type.SF_TYPE_DECIMAL`.
1952c593315Sopenharmony_ci     */
1962c593315Sopenharmony_ci    sf_decimal decimal;
1972c593315Sopenharmony_ci    /**
1982c593315Sopenharmony_ci     * :member:`vec` contains sequence of bytes if :member:`type` is
1992c593315Sopenharmony_ci     * either :enum:`sf_type.SF_TYPE_STRING`,
2002c593315Sopenharmony_ci     * :enum:`sf_type.SF_TYPE_TOKEN`, or
2012c593315Sopenharmony_ci     * :enum:`sf_type.SF_TYPE_BYTESEQ`.
2022c593315Sopenharmony_ci     *
2032c593315Sopenharmony_ci     * For :enum:`sf_type.SF_TYPE_STRING`, this field contains one or
2042c593315Sopenharmony_ci     * more escaped characters if :member:`flags` has
2052c593315Sopenharmony_ci     * :macro:`SF_VALUE_FLAG_ESCAPED_STRING` set.  To unescape the
2062c593315Sopenharmony_ci     * string, use `sf_unescape`.
2072c593315Sopenharmony_ci     *
2082c593315Sopenharmony_ci     * For :enum:`sf_type.SF_TYPE_BYTESEQ`, this field contains base64
2092c593315Sopenharmony_ci     * encoded string.  To decode this byte string, use
2102c593315Sopenharmony_ci     * `sf_base64decode`.
2112c593315Sopenharmony_ci     *
2122c593315Sopenharmony_ci     * If :member:`vec.len <sf_vec.len>` == 0, :member:`vec.base
2132c593315Sopenharmony_ci     * <sf_vec.base>` is guaranteed to be NULL.
2142c593315Sopenharmony_ci     */
2152c593315Sopenharmony_ci    sf_vec vec;
2162c593315Sopenharmony_ci    /**
2172c593315Sopenharmony_ci     * @anonunion_end
2182c593315Sopenharmony_ci     */
2192c593315Sopenharmony_ci  };
2202c593315Sopenharmony_ci} sf_value;
2212c593315Sopenharmony_ci
2222c593315Sopenharmony_ci/**
2232c593315Sopenharmony_ci * @struct
2242c593315Sopenharmony_ci *
2252c593315Sopenharmony_ci * :type:`sf_parser` is the Structured Field Values parser.  Use
2262c593315Sopenharmony_ci * `sf_parser_init` to initialize it.
2272c593315Sopenharmony_ci */
2282c593315Sopenharmony_citypedef struct sf_parser {
2292c593315Sopenharmony_ci  /* all fields are private */
2302c593315Sopenharmony_ci  const uint8_t *pos;
2312c593315Sopenharmony_ci  const uint8_t *end;
2322c593315Sopenharmony_ci  uint32_t state;
2332c593315Sopenharmony_ci} sf_parser;
2342c593315Sopenharmony_ci
2352c593315Sopenharmony_ci/**
2362c593315Sopenharmony_ci * @function
2372c593315Sopenharmony_ci *
2382c593315Sopenharmony_ci * `sf_parser_init` initializes |sfp| with the given buffer pointed by
2392c593315Sopenharmony_ci * |data| of length |datalen|.
2402c593315Sopenharmony_ci */
2412c593315Sopenharmony_civoid sf_parser_init(sf_parser *sfp, const uint8_t *data, size_t datalen);
2422c593315Sopenharmony_ci
2432c593315Sopenharmony_ci/**
2442c593315Sopenharmony_ci * @function
2452c593315Sopenharmony_ci *
2462c593315Sopenharmony_ci * `sf_parser_param` reads a parameter.  If this function returns 0,
2472c593315Sopenharmony_ci * it stores parameter key and value in |dest_key| and |dest_value|
2482c593315Sopenharmony_ci * respectively, if they are not NULL.
2492c593315Sopenharmony_ci *
2502c593315Sopenharmony_ci * This function does no effort to find duplicated keys.  Same key may
2512c593315Sopenharmony_ci * be reported more than once.
2522c593315Sopenharmony_ci *
2532c593315Sopenharmony_ci * Caller should keep calling this function until it returns negative
2542c593315Sopenharmony_ci * error code.  If it returns :macro:`SF_ERR_EOF`, all parameters have
2552c593315Sopenharmony_ci * read, and caller can continue to read rest of the values.  If it
2562c593315Sopenharmony_ci * returns :macro:`SF_ERR_PARSE_ERROR`, it encountered fatal error
2572c593315Sopenharmony_ci * while parsing field value.
2582c593315Sopenharmony_ci */
2592c593315Sopenharmony_ciint sf_parser_param(sf_parser *sfp, sf_vec *dest_key, sf_value *dest_value);
2602c593315Sopenharmony_ci
2612c593315Sopenharmony_ci/**
2622c593315Sopenharmony_ci * @function
2632c593315Sopenharmony_ci *
2642c593315Sopenharmony_ci * `sf_parser_dict` reads the next dictionary key and value pair.  If
2652c593315Sopenharmony_ci * this function returns 0, it stores the key and value in |dest_key|
2662c593315Sopenharmony_ci * and |dest_value| respectively, if they are not NULL.
2672c593315Sopenharmony_ci *
2682c593315Sopenharmony_ci * Caller can optionally read parameters attached to the pair by
2692c593315Sopenharmony_ci * calling `sf_parser_param`.
2702c593315Sopenharmony_ci *
2712c593315Sopenharmony_ci * This function does no effort to find duplicated keys.  Same key may
2722c593315Sopenharmony_ci * be reported more than once.
2732c593315Sopenharmony_ci *
2742c593315Sopenharmony_ci * Caller should keep calling this function until it returns negative
2752c593315Sopenharmony_ci * error code.  If it returns :macro:`SF_ERR_EOF`, all key and value
2762c593315Sopenharmony_ci * pairs have been read, and there is nothing left to read.
2772c593315Sopenharmony_ci *
2782c593315Sopenharmony_ci * This function returns 0 if it succeeds, or one of the following
2792c593315Sopenharmony_ci * negative error codes:
2802c593315Sopenharmony_ci *
2812c593315Sopenharmony_ci * :macro:`SF_ERR_EOF`
2822c593315Sopenharmony_ci *     All values in the dictionary have read.
2832c593315Sopenharmony_ci * :macro:`SF_ERR_PARSE_ERROR`
2842c593315Sopenharmony_ci *     It encountered fatal error while parsing field value.
2852c593315Sopenharmony_ci */
2862c593315Sopenharmony_ciint sf_parser_dict(sf_parser *sfp, sf_vec *dest_key, sf_value *dest_value);
2872c593315Sopenharmony_ci
2882c593315Sopenharmony_ci/**
2892c593315Sopenharmony_ci * @function
2902c593315Sopenharmony_ci *
2912c593315Sopenharmony_ci * `sf_parser_list` reads the next list item.  If this function
2922c593315Sopenharmony_ci * returns 0, it stores the item in |dest| if it is not NULL.
2932c593315Sopenharmony_ci *
2942c593315Sopenharmony_ci * Caller can optionally read parameters attached to the item by
2952c593315Sopenharmony_ci * calling `sf_parser_param`.
2962c593315Sopenharmony_ci *
2972c593315Sopenharmony_ci * Caller should keep calling this function until it returns negative
2982c593315Sopenharmony_ci * error code.  If it returns :macro:`SF_ERR_EOF`, all values in the
2992c593315Sopenharmony_ci * list have been read, and there is nothing left to read.
3002c593315Sopenharmony_ci *
3012c593315Sopenharmony_ci * This function returns 0 if it succeeds, or one of the following
3022c593315Sopenharmony_ci * negative error codes:
3032c593315Sopenharmony_ci *
3042c593315Sopenharmony_ci * :macro:`SF_ERR_EOF`
3052c593315Sopenharmony_ci *     All values in the list have read.
3062c593315Sopenharmony_ci * :macro:`SF_ERR_PARSE_ERROR`
3072c593315Sopenharmony_ci *     It encountered fatal error while parsing field value.
3082c593315Sopenharmony_ci */
3092c593315Sopenharmony_ciint sf_parser_list(sf_parser *sfp, sf_value *dest);
3102c593315Sopenharmony_ci
3112c593315Sopenharmony_ci/**
3122c593315Sopenharmony_ci * @function
3132c593315Sopenharmony_ci *
3142c593315Sopenharmony_ci * `sf_parser_item` reads a single item.  If this function returns 0,
3152c593315Sopenharmony_ci * it stores the item in |dest| if it is not NULL.
3162c593315Sopenharmony_ci *
3172c593315Sopenharmony_ci * This function is only used for the field value that consists of a
3182c593315Sopenharmony_ci * single item.
3192c593315Sopenharmony_ci *
3202c593315Sopenharmony_ci * Caller can optionally read parameters attached to the item by
3212c593315Sopenharmony_ci * calling `sf_parser_param`.
3222c593315Sopenharmony_ci *
3232c593315Sopenharmony_ci * Caller should call this function again to make sure that there is
3242c593315Sopenharmony_ci * nothing left to read.  If this 2nd function call returns
3252c593315Sopenharmony_ci * :macro:`SF_ERR_EOF`, all data have been processed successfully.
3262c593315Sopenharmony_ci *
3272c593315Sopenharmony_ci * This function returns 0 if it succeeds, or one of the following
3282c593315Sopenharmony_ci * negative error codes:
3292c593315Sopenharmony_ci *
3302c593315Sopenharmony_ci * :macro:`SF_ERR_EOF`
3312c593315Sopenharmony_ci *     There is nothing left to read.
3322c593315Sopenharmony_ci * :macro:`SF_ERR_PARSE_ERROR`
3332c593315Sopenharmony_ci *     It encountered fatal error while parsing field value.
3342c593315Sopenharmony_ci */
3352c593315Sopenharmony_ciint sf_parser_item(sf_parser *sfp, sf_value *dest);
3362c593315Sopenharmony_ci
3372c593315Sopenharmony_ci/**
3382c593315Sopenharmony_ci * @function
3392c593315Sopenharmony_ci *
3402c593315Sopenharmony_ci * `sf_parser_inner_list` reads the next inner list item.  If this
3412c593315Sopenharmony_ci * function returns 0, it stores the item in |dest| if it is not NULL.
3422c593315Sopenharmony_ci *
3432c593315Sopenharmony_ci * Caller can optionally read parameters attached to the item by
3442c593315Sopenharmony_ci * calling `sf_parser_param`.
3452c593315Sopenharmony_ci *
3462c593315Sopenharmony_ci * Caller should keep calling this function until it returns negative
3472c593315Sopenharmony_ci * error code.  If it returns :macro:`SF_ERR_EOF`, all values in this
3482c593315Sopenharmony_ci * inner list have been read, and caller can optionally read
3492c593315Sopenharmony_ci * parameters attached to this inner list by calling
3502c593315Sopenharmony_ci * `sf_parser_param`.  Then caller can continue to read rest of the
3512c593315Sopenharmony_ci * values.
3522c593315Sopenharmony_ci *
3532c593315Sopenharmony_ci * This function returns 0 if it succeeds, or one of the following
3542c593315Sopenharmony_ci * negative error codes:
3552c593315Sopenharmony_ci *
3562c593315Sopenharmony_ci * :macro:`SF_ERR_EOF`
3572c593315Sopenharmony_ci *     All values in the inner list have read.
3582c593315Sopenharmony_ci * :macro:`SF_ERR_PARSE_ERROR`
3592c593315Sopenharmony_ci *     It encountered fatal error while parsing field value.
3602c593315Sopenharmony_ci */
3612c593315Sopenharmony_ciint sf_parser_inner_list(sf_parser *sfp, sf_value *dest);
3622c593315Sopenharmony_ci
3632c593315Sopenharmony_ci/**
3642c593315Sopenharmony_ci * @function
3652c593315Sopenharmony_ci *
3662c593315Sopenharmony_ci * `sf_unescape` copies |src| to |dest| by removing escapes (``\``).
3672c593315Sopenharmony_ci * |src| should be the pointer to :member:`sf_value.vec` of type
3682c593315Sopenharmony_ci * :enum:`sf_type.SF_TYPE_STRING` produced by either `sf_parser_dict`,
3692c593315Sopenharmony_ci * `sf_parser_list`, `sf_parser_inner_list`, `sf_parser_item`, or
3702c593315Sopenharmony_ci * `sf_parser_param`, otherwise the behavior is undefined.
3712c593315Sopenharmony_ci *
3722c593315Sopenharmony_ci * :member:`dest->base <sf_vec.base>` must point to the buffer that
3732c593315Sopenharmony_ci * has sufficient space to store the unescaped string.
3742c593315Sopenharmony_ci *
3752c593315Sopenharmony_ci * If there is no escape character in |src|, |*src| is assigned to
3762c593315Sopenharmony_ci * |*dest|.  This includes the case that :member:`src->len
3772c593315Sopenharmony_ci * <sf_vec.len>` == 0.
3782c593315Sopenharmony_ci *
3792c593315Sopenharmony_ci * This function sets the length of unescaped string to
3802c593315Sopenharmony_ci * :member:`dest->len <sf_vec.len>`.
3812c593315Sopenharmony_ci */
3822c593315Sopenharmony_civoid sf_unescape(sf_vec *dest, const sf_vec *src);
3832c593315Sopenharmony_ci
3842c593315Sopenharmony_ci/**
3852c593315Sopenharmony_ci * @function
3862c593315Sopenharmony_ci *
3872c593315Sopenharmony_ci * `sf_base64decode` decodes Base64 encoded string |src| and writes
3882c593315Sopenharmony_ci * the result into |dest|.  |src| should be the pointer to
3892c593315Sopenharmony_ci * :member:`sf_value.vec` of type :enum:`sf_type.SF_TYPE_BYTESEQ`
3902c593315Sopenharmony_ci * produced by either `sf_parser_dict`, `sf_parser_list`,
3912c593315Sopenharmony_ci * `sf_parser_inner_list`, `sf_parser_item`, or `sf_parser_param`,
3922c593315Sopenharmony_ci * otherwise the behavior is undefined.
3932c593315Sopenharmony_ci *
3942c593315Sopenharmony_ci * :member:`dest->base <sf_vec.base>` must point to the buffer that
3952c593315Sopenharmony_ci * has sufficient space to store the decoded byte string.
3962c593315Sopenharmony_ci *
3972c593315Sopenharmony_ci * If :member:`src->len <sf_vec.len>` == 0, |*src| is assigned to
3982c593315Sopenharmony_ci * |*dest|.
3992c593315Sopenharmony_ci *
4002c593315Sopenharmony_ci * This function sets the length of decoded byte string to
4012c593315Sopenharmony_ci * :member:`dest->len <sf_vec.len>`.
4022c593315Sopenharmony_ci */
4032c593315Sopenharmony_civoid sf_base64decode(sf_vec *dest, const sf_vec *src);
4042c593315Sopenharmony_ci
4052c593315Sopenharmony_ci#ifdef __cplusplus
4062c593315Sopenharmony_ci}
4072c593315Sopenharmony_ci#endif
4082c593315Sopenharmony_ci
4092c593315Sopenharmony_ci#endif /* SFPARSE_H */
410