quickjs-tart

quickjs-based runtime for wallet-core logic
Log | Files | Refs | README | LICENSE

ares_buf.h (33593B)


      1 /* MIT License
      2  *
      3  * Copyright (c) 2023 Brad House
      4  *
      5  * Permission is hereby granted, free of charge, to any person obtaining a copy
      6  * of this software and associated documentation files (the "Software"), to deal
      7  * in the Software without restriction, including without limitation the rights
      8  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      9  * copies of the Software, and to permit persons to whom the Software is
     10  * furnished to do so, subject to the following conditions:
     11  *
     12  * The above copyright notice and this permission notice (including the next
     13  * paragraph) shall be included in all copies or substantial portions of the
     14  * Software.
     15  *
     16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     22  * SOFTWARE.
     23  *
     24  * SPDX-License-Identifier: MIT
     25  */
     26 #ifndef __ARES__BUF_H
     27 #define __ARES__BUF_H
     28 
     29 #include "ares.h"
     30 #include "ares_array.h"
     31 
     32 /*! \addtogroup ares_buf Safe Data Builder and buffer
     33  *
     34  * This is a buffer building and parsing framework with a focus on security over
     35  * performance. All data to be read from the buffer will perform explicit length
     36  * validation and return a success/fail result.  There are also various helpers
     37  * for writing data to the buffer which dynamically grows.
     38  *
     39  * All operations that fetch or consume data from the buffer will move forward
     40  * the internal pointer, thus marking the data as processed which may no longer
     41  * be accessible after certain operations (such as append).
     42  *
     43  * The helpers for this object are meant to be added as needed.  If you can't
     44  * find it, write it!
     45  *
     46  * @{
     47  */
     48 struct ares_buf;
     49 
     50 /*! Opaque data type for generic hash table implementation */
     51 typedef struct ares_buf     ares_buf_t;
     52 
     53 /*! Create a new buffer object that dynamically allocates buffers for data.
     54  *
     55  *  \return initialized buffer object or NULL if out of memory.
     56  */
     57 CARES_EXTERN ares_buf_t    *ares_buf_create(void);
     58 
     59 /*! Create a new buffer object that uses a user-provided data pointer.  The
     60  *  data provided will not be manipulated, and cannot be appended to.  This
     61  *  is strictly used for parsing.
     62  *
     63  *  \param[in] data     Data to provide to buffer, must not be NULL.
     64  *  \param[in] data_len Size of buffer provided, must be > 0
     65  *
     66  *  \return initialized buffer object or NULL if out of memory or misuse.
     67  */
     68 CARES_EXTERN ares_buf_t    *ares_buf_create_const(const unsigned char *data,
     69                                                   size_t               data_len);
     70 
     71 
     72 /*! Destroy an initialized buffer object.
     73  *
     74  *  \param[in] buf  Initialized buf object
     75  */
     76 CARES_EXTERN void           ares_buf_destroy(ares_buf_t *buf);
     77 
     78 
     79 /*! Append multiple bytes to a dynamic buffer object
     80  *
     81  *  \param[in] buf      Initialized buffer object
     82  *  \param[in] data     Data to copy to buffer object
     83  *  \param[in] data_len Length of data to copy to buffer object.
     84  *  \return ARES_SUCCESS or one of the c-ares error codes
     85  */
     86 CARES_EXTERN ares_status_t  ares_buf_append(ares_buf_t          *buf,
     87                                             const unsigned char *data,
     88                                             size_t               data_len);
     89 
     90 /*! Append a single byte to the dynamic buffer object
     91  *
     92  *  \param[in] buf      Initialized buffer object
     93  *  \param[in] b        Single byte to append to buffer object.
     94  *  \return ARES_SUCCESS or one of the c-ares error codes
     95  */
     96 CARES_EXTERN ares_status_t  ares_buf_append_byte(ares_buf_t   *buf,
     97                                                  unsigned char b);
     98 
     99 /*! Append a null-terminated string to the dynamic buffer object
    100  *
    101  *  \param[in] buf      Initialized buffer object
    102  *  \param[in] str      String to append to buffer object.
    103  *  \return ARES_SUCCESS or one of the c-ares error codes
    104  */
    105 CARES_EXTERN ares_status_t  ares_buf_append_str(ares_buf_t *buf,
    106                                                 const char *str);
    107 
    108 /*! Append a 16bit Big Endian number to the buffer.
    109  *
    110  *  \param[in]  buf     Initialized buffer object
    111  *  \param[out] u16     16bit integer
    112  *  \return ARES_SUCCESS or one of the c-ares error codes
    113  */
    114 CARES_EXTERN ares_status_t  ares_buf_append_be16(ares_buf_t    *buf,
    115                                                  unsigned short u16);
    116 
    117 /*! Append a 32bit Big Endian number to the buffer.
    118  *
    119  *  \param[in]  buf     Initialized buffer object
    120  *  \param[out] u32     32bit integer
    121  *  \return ARES_SUCCESS or one of the c-ares error codes
    122  */
    123 CARES_EXTERN ares_status_t  ares_buf_append_be32(ares_buf_t  *buf,
    124                                                  unsigned int u32);
    125 
    126 /*! Append a number in ASCII decimal form.
    127  *
    128  *  \param[in] buf  Initialized buffer object
    129  *  \param[in] num  Number to print
    130  *  \param[in] len  Length to output, use 0 for no padding
    131  *  \return ARES_SUCCESS on success
    132  */
    133 CARES_EXTERN ares_status_t  ares_buf_append_num_dec(ares_buf_t *buf, size_t num,
    134                                                     size_t len);
    135 
    136 /*! Append a number in ASCII hexadecimal form.
    137  *
    138  *  \param[in] buf  Initialized buffer object
    139  *  \param[in] num  Number to print
    140  *  \param[in] len  Length to output, use 0 for no padding
    141  *  \return ARES_SUCCESS on success
    142  */
    143 CARES_EXTERN ares_status_t  ares_buf_append_num_hex(ares_buf_t *buf, size_t num,
    144                                                     size_t len);
    145 
    146 /*! Sets the current buffer length.  This *may* be used if there is a need to
    147  *  override a prior position in the buffer, such as if there is a length
    148  *  prefix that isn't easily predictable, and you must go back and overwrite
    149  *  that position.
    150  *
    151  *  Only valid on non-const buffers.  Length provided must not exceed current
    152  *  allocated buffer size, but otherwise there are very few protections on
    153  *  this function.  Use cautiously.
    154  *
    155  *  \param[in]  buf  Initialized buffer object
    156  *  \param[in]  len  Length to set
    157  *  \return ARES_SUCCESS or one of the c-ares error codes
    158  */
    159 CARES_EXTERN ares_status_t  ares_buf_set_length(ares_buf_t *buf, size_t len);
    160 
    161 
    162 /*! Start a dynamic append operation that returns a buffer suitable for
    163  *  writing.  A desired minimum length is passed in, and the actual allocated
    164  *  buffer size is returned which may be greater than the requested size.
    165  *  No operation other than ares_buf_append_finish() is allowed on the
    166  *  buffer after this request.
    167  *
    168  *  \param[in]     buf     Initialized buffer object
    169  *  \param[in,out] len     Desired non-zero length passed in, actual buffer size
    170  *                         returned.
    171  *  \return Pointer to writable buffer or NULL on failure (usage, out of mem)
    172  */
    173 CARES_EXTERN unsigned char *ares_buf_append_start(ares_buf_t *buf, size_t *len);
    174 
    175 /*! Finish a dynamic append operation.  Called after
    176  *  ares_buf_append_start() once desired data is written.
    177  *
    178  *  \param[in] buf    Initialized buffer object.
    179  *  \param[in] len    Length of data written.  May be zero to terminate
    180  *                    operation. Must not be greater than returned from
    181  *                    ares_buf_append_start().
    182  */
    183 CARES_EXTERN void           ares_buf_append_finish(ares_buf_t *buf, size_t len);
    184 
    185 /*! Write the data provided to the buffer in a hexdump format.
    186  *
    187  *  \param[in] buf      Initialized buffer object.
    188  *  \param[in] data     Data to hex dump
    189  *  \param[in] len      Length of data to hexdump
    190  *  \return ARES_SUCCESS on success.
    191  */
    192 CARES_EXTERN ares_status_t  ares_buf_hexdump(ares_buf_t          *buf,
    193                                              const unsigned char *data,
    194                                              size_t               len);
    195 
    196 /*! Clean up ares_buf_t and return allocated pointer to unprocessed data.  It
    197  *  is the responsibility of the  caller to ares_free() the returned buffer.
    198  *  The passed in buf parameter is invalidated by this call.
    199  *
    200  * \param[in]  buf    Initialized buffer object. Can not be a "const" buffer.
    201  * \param[out] len    Length of data returned
    202  * \return pointer to unprocessed data (may be zero length) or NULL on error.
    203  */
    204 CARES_EXTERN unsigned char *ares_buf_finish_bin(ares_buf_t *buf, size_t *len);
    205 
    206 /*! Clean up ares_buf_t and return allocated pointer to unprocessed data and
    207  *  return it as a string (null terminated).  It is the responsibility of the
    208  *  caller to ares_free() the returned buffer. The passed in buf parameter is
    209  *  invalidated by this call.
    210  *
    211  *  This function in no way validates the data in this buffer is actually
    212  *  a string, that characters are printable, or that there aren't multiple
    213  *  NULL terminators.  It is assumed that the caller will either validate that
    214  *  themselves or has built this buffer with only a valid character set.
    215  *
    216  * \param[in]  buf    Initialized buffer object. Can not be a "const" buffer.
    217  * \param[out] len    Optional. Length of data returned, or NULL if not needed.
    218  * \return pointer to unprocessed data or NULL on error.
    219  */
    220 CARES_EXTERN char          *ares_buf_finish_str(ares_buf_t *buf, size_t *len);
    221 
    222 /*! Replace the given search byte sequence with the replacement byte sequence.
    223  *  This is only valid for allocated buffers, not const buffers.  Will replace
    224  *  all byte sequences starting at the current offset to the end of the buffer.
    225  *
    226  *  \param[in]  buf       Initialized buffer object. Can not be a "const" buffer.
    227  *  \param[in]  srch      Search byte sequence, must not be NULL.
    228  *  \param[in]  srch_size Size of byte sequence, must not be zero.
    229  *  \param[in]  rplc      Byte sequence to use as replacement.  May be NULL if
    230  *                        rplc_size is zero.
    231  *  \param[in]  rplc_size Size of replacement byte sequence, may be 0.
    232  *  \return ARES_SUCCESS on success, otherwise on may return failure only on
    233  *          memory allocation failure or misuse.  Will not return indication
    234  *          if any replacements occurred
    235  */
    236 CARES_EXTERN ares_status_t  ares_buf_replace(ares_buf_t *buf,
    237                                              const unsigned char *srch,
    238                                              size_t srch_size,
    239                                              const unsigned char *rplc,
    240                                              size_t rplc_size);
    241 
    242 /*! Tag a position to save in the buffer in case parsing needs to rollback,
    243  *  such as if insufficient data is available, but more data may be added in
    244  *  the future.  Only a single tag can be set per buffer object.  Setting a
    245  *  tag will override any pre-existing tag.
    246  *
    247  *  \param[in] buf Initialized buffer object
    248  */
    249 CARES_EXTERN void           ares_buf_tag(ares_buf_t *buf);
    250 
    251 /*! Rollback to a tagged position.  Will automatically clear the tag.
    252  *
    253  *  \param[in] buf Initialized buffer object
    254  *  \return ARES_SUCCESS or one of the c-ares error codes
    255  */
    256 CARES_EXTERN ares_status_t  ares_buf_tag_rollback(ares_buf_t *buf);
    257 
    258 /*! Clear the tagged position without rolling back.  You should do this any
    259  *  time a tag is no longer needed as future append operations can reclaim
    260  *  buffer space.
    261  *
    262  *  \param[in] buf Initialized buffer object
    263  *  \return ARES_SUCCESS or one of the c-ares error codes
    264  */
    265 CARES_EXTERN ares_status_t  ares_buf_tag_clear(ares_buf_t *buf);
    266 
    267 /*! Fetch the buffer and length of data starting from the tagged position up
    268  *  to the _current_ position.  It will not unset the tagged position.  The
    269  *  data may be invalidated by any future ares_buf_*() calls.
    270  *
    271  *  \param[in]  buf    Initialized buffer object
    272  *  \param[out] len    Length between tag and current offset in buffer
    273  *  \return NULL on failure (such as no tag), otherwise pointer to start of
    274  *          buffer
    275  */
    276 CARES_EXTERN const unsigned char *ares_buf_tag_fetch(const ares_buf_t *buf,
    277                                                      size_t           *len);
    278 
    279 /*! Get the length of the current tag offset to the current position.
    280  *
    281  *  \param[in]  buf    Initialized buffer object
    282  *  \return length
    283  */
    284 CARES_EXTERN size_t               ares_buf_tag_length(const ares_buf_t *buf);
    285 
    286 /*! Fetch the bytes starting from the tagged position up to the _current_
    287  *  position using the provided buffer.  It will not unset the tagged position.
    288  *
    289  *  \param[in]     buf    Initialized buffer object
    290  *  \param[in,out] bytes  Buffer to hold data
    291  *  \param[in,out] len    On input, buffer size, on output, bytes place in
    292  *                        buffer.
    293  *  \return ARES_SUCCESS if fetched, ARES_EFORMERR if insufficient buffer size
    294  */
    295 CARES_EXTERN ares_status_t ares_buf_tag_fetch_bytes(const ares_buf_t *buf,
    296                                                     unsigned char    *bytes,
    297                                                     size_t           *len);
    298 
    299 /*! Fetch the bytes starting from the tagged position up to the _current_
    300  *  position as a NULL-terminated string using the provided buffer.  The data
    301  *  is validated to be ASCII-printable data.  It will not unset the tagged
    302  *  position.
    303  *
    304  *  \param[in]     buf    Initialized buffer object
    305  *  \param[in,out] str    Buffer to hold data
    306  *  \param[in]     len    buffer size
    307  *  \return ARES_SUCCESS if fetched, ARES_EFORMERR if insufficient buffer size,
    308  *          ARES_EBADSTR if not printable ASCII
    309  */
    310 CARES_EXTERN ares_status_t ares_buf_tag_fetch_string(const ares_buf_t *buf,
    311                                                      char *str, size_t len);
    312 
    313 /*! Fetch the bytes starting from the tagged position up to the _current_
    314  *  position as a NULL-terminated string and placed into a newly allocated
    315  *  buffer.  The data is validated to be ASCII-printable data.  It will not
    316  *  unset the tagged position.
    317  *
    318  *  \param[in]  buf    Initialized buffer object
    319  *  \param[out] str    New buffer to hold output, free with ares_free()
    320  *
    321  *  \return ARES_SUCCESS if fetched, ARES_EFORMERR if insufficient buffer size,
    322  *          ARES_EBADSTR if not printable ASCII
    323  */
    324 CARES_EXTERN ares_status_t ares_buf_tag_fetch_strdup(const ares_buf_t *buf,
    325                                                      char            **str);
    326 
    327 /*! Fetch the bytes starting from the tagged position up to the _current_
    328  *  position as const buffer.  Care must be taken to not append or destroy the
    329  *  passed in buffer until the newly fetched buffer is no longer needed since
    330  *  it points to memory inside the passed in buffer which could be invalidated.
    331  *
    332  *  \param[in]     buf    Initialized buffer object
    333  *  \param[out]    newbuf New const buffer object, must be destroyed when done.
    334 
    335  *  \return ARES_SUCCESS if fetched
    336  */
    337 CARES_EXTERN ares_status_t ares_buf_tag_fetch_constbuf(const ares_buf_t *buf,
    338                                                        ares_buf_t **newbuf);
    339 
    340 /*! Consume the given number of bytes without reading them.
    341  *
    342  *  \param[in] buf    Initialized buffer object
    343  *  \param[in] len    Length to consume
    344  *  \return ARES_SUCCESS or one of the c-ares error codes
    345  */
    346 CARES_EXTERN ares_status_t ares_buf_consume(ares_buf_t *buf, size_t len);
    347 
    348 /*! Fetch a 16bit Big Endian number from the buffer.
    349  *
    350  *  \param[in]  buf     Initialized buffer object
    351  *  \param[out] u16     Buffer to hold 16bit integer
    352  *  \return ARES_SUCCESS or one of the c-ares error codes
    353  */
    354 CARES_EXTERN ares_status_t ares_buf_fetch_be16(ares_buf_t     *buf,
    355                                                unsigned short *u16);
    356 
    357 /*! Fetch a 32bit Big Endian number from the buffer.
    358  *
    359  *  \param[in]  buf     Initialized buffer object
    360  *  \param[out] u32     Buffer to hold 32bit integer
    361  *  \return ARES_SUCCESS or one of the c-ares error codes
    362  */
    363 CARES_EXTERN ares_status_t ares_buf_fetch_be32(ares_buf_t   *buf,
    364                                                unsigned int *u32);
    365 
    366 
    367 /*! Fetch the requested number of bytes into the provided buffer
    368  *
    369  *  \param[in]  buf     Initialized buffer object
    370  *  \param[out] bytes   Buffer to hold data
    371  *  \param[in]  len     Requested number of bytes (must be > 0)
    372  *  \return ARES_SUCCESS or one of the c-ares error codes
    373  */
    374 CARES_EXTERN ares_status_t ares_buf_fetch_bytes(ares_buf_t    *buf,
    375                                                 unsigned char *bytes,
    376                                                 size_t         len);
    377 
    378 
    379 /*! Fetch the requested number of bytes and return a new buffer that must be
    380  *  ares_free()'d by the caller.
    381  *
    382  *  \param[in]  buf       Initialized buffer object
    383  *  \param[in]  len       Requested number of bytes (must be > 0)
    384  *  \param[in]  null_term Even though this is considered binary data, the user
    385  *                        knows it may be a vald string, so add a null
    386  *                        terminator.
    387  *  \param[out] bytes     Pointer passed by reference. Will be allocated.
    388  *  \return ARES_SUCCESS or one of the c-ares error codes
    389  */
    390 CARES_EXTERN ares_status_t ares_buf_fetch_bytes_dup(ares_buf_t *buf, size_t len,
    391                                                     ares_bool_t     null_term,
    392                                                     unsigned char **bytes);
    393 
    394 /*! Fetch the requested number of bytes and place them into the provided
    395  *  dest buffer object.
    396  *
    397  *  \param[in]  buf     Initialized buffer object
    398  *  \param[out] dest    Buffer object to append bytes.
    399  *  \param[in]  len     Requested number of bytes (must be > 0)
    400  *  \return ARES_SUCCESS or one of the c-ares error codes
    401  */
    402 CARES_EXTERN ares_status_t ares_buf_fetch_bytes_into_buf(ares_buf_t *buf,
    403                                                          ares_buf_t *dest,
    404                                                          size_t      len);
    405 
    406 /*! Fetch the requested number of bytes and return a new buffer that must be
    407  *  ares_free()'d by the caller.  The returned buffer is a null terminated
    408  *  string.  The data is validated to be ASCII-printable.
    409  *
    410  *  \param[in]  buf     Initialized buffer object
    411  *  \param[in]  len     Requested number of bytes (must be > 0)
    412  *  \param[out] str     Pointer passed by reference. Will be allocated.
    413  *  \return ARES_SUCCESS or one of the c-ares error codes
    414  */
    415 CARES_EXTERN ares_status_t ares_buf_fetch_str_dup(ares_buf_t *buf, size_t len,
    416                                                   char **str);
    417 
    418 /*! Consume whitespace characters (0x09, 0x0B, 0x0C, 0x0D, 0x20, and optionally
    419  *  0x0A).
    420  *
    421  *  \param[in]  buf               Initialized buffer object
    422  *  \param[in]  include_linefeed  ARES_TRUE to include consuming 0x0A,
    423  *                                ARES_FALSE otherwise.
    424  *  \return number of whitespace characters consumed
    425  */
    426 CARES_EXTERN size_t        ares_buf_consume_whitespace(ares_buf_t *buf,
    427                                                        ares_bool_t include_linefeed);
    428 
    429 
    430 /*! Consume any non-whitespace character (anything other than 0x09, 0x0B, 0x0C,
    431  *  0x0D, 0x20, and 0x0A).
    432  *
    433  *  \param[in]  buf               Initialized buffer object
    434  *  \return number of characters consumed
    435  */
    436 CARES_EXTERN size_t        ares_buf_consume_nonwhitespace(ares_buf_t *buf);
    437 
    438 
    439 /*! Consume until a character in the character set provided is reached.  Does
    440  *  not include the character from the charset at the end.
    441  *
    442  *  \param[in] buf                Initialized buffer object
    443  *  \param[in] charset            character set
    444  *  \param[in] len                length of character set
    445  *  \param[in] require_charset    require we find a character from the charset.
    446  *                                if ARES_FALSE it will simply consume the
    447  *                                rest of the buffer.  If ARES_TRUE will return
    448  *                                SIZE_MAX if not found.
    449  *  \return number of characters consumed
    450  */
    451 CARES_EXTERN size_t        ares_buf_consume_until_charset(ares_buf_t          *buf,
    452                                                           const unsigned char *charset,
    453                                                           size_t               len,
    454                                                           ares_bool_t require_charset);
    455 
    456 
    457 /*! Consume until a sequence of bytes is encountered.  Does not include the
    458  *  sequence of characters itself.
    459  *
    460  *  \param[in] buf                Initialized buffer object
    461  *  \param[in] seq                sequence of bytes
    462  *  \param[in] len                length of sequence
    463  *  \param[in] require_charset    require we find the sequence.
    464  *                                if ARES_FALSE it will simply consume the
    465  *                                rest of the buffer.  If ARES_TRUE will return
    466  *                                SIZE_MAX if not found.
    467  *  \return number of characters consumed
    468  */
    469 CARES_EXTERN size_t        ares_buf_consume_until_seq(ares_buf_t          *buf,
    470                                                       const unsigned char *seq,
    471                                                       size_t               len,
    472                                                       ares_bool_t require_seq);
    473 
    474 /*! Consume while the characters match the characters in the provided set.
    475  *
    476  *  \param[in] buf                Initialized buffer object
    477  *  \param[in] charset            character set
    478  *  \param[in] len                length of character set
    479  *  \return number of characters consumed
    480  */
    481 CARES_EXTERN size_t        ares_buf_consume_charset(ares_buf_t          *buf,
    482                                                     const unsigned char *charset,
    483                                                     size_t               len);
    484 
    485 
    486 /*! Consume from the current position until the end of the line, and optionally
    487  *  the end of line character (0x0A) itself.
    488  *
    489  *  \param[in]  buf               Initialized buffer object
    490  *  \param[in]  include_linefeed  ARES_TRUE to include consuming 0x0A,
    491  *                                ARES_FALSE otherwise.
    492  *  \return number of characters consumed
    493  */
    494 CARES_EXTERN size_t        ares_buf_consume_line(ares_buf_t *buf,
    495                                                  ares_bool_t include_linefeed);
    496 
    497 typedef enum {
    498   /*! No flags */
    499   ARES_BUF_SPLIT_NONE = 0,
    500   /*! The delimiter will be the first character in the buffer, except the
    501    *  first buffer since the start doesn't have a delimiter.  This option is
    502    *  incompatible with ARES_BUF_SPLIT_LTRIM since the delimiter is always
    503    *  the first character.
    504    */
    505   ARES_BUF_SPLIT_KEEP_DELIMS = 1 << 0,
    506   /*! Allow blank sections, by default blank sections are not emitted.  If using
    507    *  ARES_BUF_SPLIT_KEEP_DELIMS, the delimiter is not counted as part
    508    *  of the section */
    509   ARES_BUF_SPLIT_ALLOW_BLANK = 1 << 1,
    510   /*! Remove duplicate entries */
    511   ARES_BUF_SPLIT_NO_DUPLICATES = 1 << 2,
    512   /*! Perform case-insensitive matching when comparing values */
    513   ARES_BUF_SPLIT_CASE_INSENSITIVE = 1 << 3,
    514   /*! Trim leading whitespace from buffer */
    515   ARES_BUF_SPLIT_LTRIM = 1 << 4,
    516   /*! Trim trailing whitespace from buffer */
    517   ARES_BUF_SPLIT_RTRIM = 1 << 5,
    518   /*! Trim leading and trailing whitespace from buffer */
    519   ARES_BUF_SPLIT_TRIM = (ARES_BUF_SPLIT_LTRIM | ARES_BUF_SPLIT_RTRIM)
    520 } ares_buf_split_t;
    521 
    522 /*! Split the provided buffer into multiple sub-buffers stored in the variable
    523  *  pointed to by the linked list.  The sub buffers are const buffers pointing
    524  *  into the buf provided.
    525  *
    526  *  \param[in]  buf               Initialized buffer object
    527  *  \param[in]  delims            Possible delimiters
    528  *  \param[in]  delims_len        Length of possible delimiters
    529  *  \param[in]  flags             One more more flags
    530  *  \param[in]  max_sections      Maximum number of sections.  Use 0 for
    531  *                                unlimited. Useful for splitting key/value
    532  *                                pairs where the delimiter may be a valid
    533  *                                character in the value.  A value of 1 would
    534  *                                have little usefulness and would effectively
    535  *                                ignore the delimiter itself.
    536  *  \param[out] arr               Result. Depending on flags, this may be a
    537  *                                valid array with no elements.  Use
    538  *                                ares_array_destroy() to free the memory which
    539  *                                will also free the contained ares_buf_t *
    540  *                                objects. Each buf object returned by
    541  *                                ares_array_at() or similar is a pointer to
    542  *                                an ares_buf_t * object, meaning you need to
    543  *                                accept it as "ares_buf_t **" then dereference.
    544  *  \return ARES_SUCCESS on success, or error like ARES_ENOMEM.
    545  */
    546 CARES_EXTERN ares_status_t ares_buf_split(
    547   ares_buf_t *buf, const unsigned char *delims, size_t delims_len,
    548   ares_buf_split_t flags, size_t max_sections, ares_array_t **arr);
    549 
    550 /*! Split the provided buffer into an ares_array_t of C strings.
    551  *
    552  *  \param[in]  buf               Initialized buffer object
    553  *  \param[in]  delims            Possible delimiters
    554  *  \param[in]  delims_len        Length of possible delimiters
    555  *  \param[in]  flags             One more more flags
    556  *  \param[in]  max_sections      Maximum number of sections.  Use 0 for
    557  *                                unlimited. Useful for splitting key/value
    558  *                                pairs where the delimiter may be a valid
    559  *                                character in the value.  A value of 1 would
    560  *                                have little usefulness and would effectively
    561  *                                ignore the delimiter itself.
    562  *  \param[out] arr               Array of strings. Free using
    563  *                                ares_array_destroy().
    564  *  \return ARES_SUCCESS on success, or error like ARES_ENOMEM.
    565  */
    566 CARES_EXTERN ares_status_t ares_buf_split_str_array(
    567   ares_buf_t *buf, const unsigned char *delims, size_t delims_len,
    568   ares_buf_split_t flags, size_t max_sections, ares_array_t **arr);
    569 
    570 /*! Split the provided buffer into a C array of C strings.
    571  *
    572  *  \param[in]  buf               Initialized buffer object
    573  *  \param[in]  delims            Possible delimiters
    574  *  \param[in]  delims_len        Length of possible delimiters
    575  *  \param[in]  flags             One more more flags
    576  *  \param[in]  max_sections      Maximum number of sections.  Use 0 for
    577  *                                unlimited. Useful for splitting key/value
    578  *                                pairs where the delimiter may be a valid
    579  *                                character in the value.  A value of 1 would
    580  *                                have little usefulness and would effectively
    581  *                                ignore the delimiter itself.
    582  *  \param[out] strs              Array of strings. Free using
    583  *                                ares_free_array(strs, nstrs, ares_free)
    584  *  \param[out] nstrs             Number of elements in the array.
    585  *  \return ARES_SUCCESS on success, or error like ARES_ENOMEM.
    586  */
    587 CARES_EXTERN ares_status_t ares_buf_split_str(
    588   ares_buf_t *buf, const unsigned char *delims, size_t delims_len,
    589   ares_buf_split_t flags, size_t max_sections, char ***strs, size_t *nstrs);
    590 
    591 /*! Check the unprocessed buffer to see if it begins with the sequence of
    592  *  characters provided.
    593  *
    594  *  \param[in] buf          Initialized buffer object
    595  *  \param[in] data         Bytes of data to compare.
    596  *  \param[in] data_len     Length of data to compare.
    597  *  \return ARES_TRUE on match, ARES_FALSE otherwise.
    598  */
    599 CARES_EXTERN ares_bool_t          ares_buf_begins_with(const ares_buf_t    *buf,
    600                                                        const unsigned char *data,
    601                                                        size_t               data_len);
    602 
    603 
    604 /*! Size of unprocessed remaining data length
    605  *
    606  *  \param[in] buf Initialized buffer object
    607  *  \return length remaining
    608  */
    609 CARES_EXTERN size_t               ares_buf_len(const ares_buf_t *buf);
    610 
    611 /*! Retrieve a pointer to the currently unprocessed data.  Generally this isn't
    612  *  recommended to be used in practice.  The returned pointer may be invalidated
    613  *  by any future ares_buf_*() calls.
    614  *
    615  *  \param[in]  buf    Initialized buffer object
    616  *  \param[out] len    Length of available data
    617  *  \return Pointer to buffer of unprocessed data
    618  */
    619 CARES_EXTERN const unsigned char *ares_buf_peek(const ares_buf_t *buf,
    620                                                 size_t           *len);
    621 
    622 /*! Retrieve the next byte in the buffer without moving forward.
    623  *
    624  *  \param[in]  buf  Initialized buffer object
    625  *  \param[out] b    Single byte
    626  *  \return \return ARES_SUCCESS on success, or error
    627  */
    628 CARES_EXTERN ares_status_t        ares_buf_peek_byte(const ares_buf_t *buf,
    629                                                      unsigned char    *b);
    630 
    631 /*! Wipe any processed data from the beginning of the buffer.  This will
    632  *  move any remaining data to the front of the internally allocated buffer.
    633  *
    634  *  Can not be used on const buffer objects.
    635  *
    636  *  Typically not needed to call, as any new append operation will automatically
    637  *  call this function if there is insufficient space to append the data in
    638  *  order to try to avoid another memory allocation.
    639  *
    640  *  It may be useful to call in order to ensure the current message being
    641  *  processed is in the beginning of the buffer if there is an intent to use
    642  *  ares_buf_set_position() and ares_buf_get_position() as may be necessary
    643  *  when processing DNS compressed names.
    644  *
    645  *  If there is an active tag, it will NOT clear the tag, it will use the tag
    646  *  as the start of the unprocessed data rather than the current offset.  If
    647  *  a prior tag is no longer needed, may be wise to call ares_buf_tag_clear().
    648  *
    649  *  \param[in]  buf    Initialized buffer object
    650  */
    651 CARES_EXTERN void                 ares_buf_reclaim(ares_buf_t *buf);
    652 
    653 /*! Set the current offset within the internal buffer.
    654  *
    655  *  Typically this should not be used, if possible, use the ares_buf_tag*()
    656  *  operations instead.
    657  *
    658  *  One exception is DNS name compression which may backwards reference to
    659  *  an index in the message.  It may be necessary in such a case to call
    660  *  ares_buf_reclaim() if using a dynamic (non-const) buffer before processing
    661  *  such a message.
    662  *
    663  *  \param[in] buf  Initialized buffer object
    664  *  \param[in] idx  Index to set position
    665  *  \return ARES_SUCCESS if valid index
    666  */
    667 CARES_EXTERN ares_status_t ares_buf_set_position(ares_buf_t *buf, size_t idx);
    668 
    669 /*! Get the current offset within the internal buffer.
    670  *
    671  *  Typically this should not be used, if possible, use the ares_buf_tag*()
    672  *  operations instead.
    673  *
    674  *  This can be used to get the current position, useful for saving if a
    675  *  jump via ares_buf_set_position() is performed and need to restore the
    676  *  current position for future operations.
    677  *
    678  *  \param[in] buf Initialized buffer object
    679  *  \return index of current position
    680  */
    681 CARES_EXTERN size_t        ares_buf_get_position(const ares_buf_t *buf);
    682 
    683 /*! Parse a character-string as defined in RFC1035, as a null-terminated
    684  *  string.
    685  *
    686  *  \param[in]  buf            initialized buffer object
    687  *  \param[in]  remaining_len  maximum length that should be used for parsing
    688  *                             the string, this is often less than the remaining
    689  *                             buffer and is based on the RR record length.
    690  *  \param[out] name           Pointer passed by reference to be filled in with
    691  *                             allocated string of the parsed that must be
    692  *                             ares_free()'d by the caller.
    693  *  \return ARES_SUCCESS on success
    694  */
    695 CARES_EXTERN ares_status_t ares_buf_parse_dns_str(ares_buf_t *buf,
    696                                                   size_t      remaining_len,
    697                                                   char      **name);
    698 
    699 /*! Parse a character-string as defined in RFC1035, as binary, however for
    700  *  convenience this does guarantee a NULL terminator (that is not included
    701  *  in the returned length).
    702  *
    703  *  \param[in]  buf            initialized buffer object
    704  *  \param[in]  remaining_len  maximum length that should be used for parsing
    705  *                             the string, this is often less than the remaining
    706  *                             buffer and is based on the RR record length.
    707  *  \param[out] bin            Pointer passed by reference to be filled in with
    708  *                             allocated string of the parsed that must be
    709  *                             ares_free()'d by the caller.
    710  *  \param[out] bin_len        Length of returned string.
    711  *  \return ARES_SUCCESS on success
    712  */
    713 CARES_EXTERN ares_status_t ares_buf_parse_dns_binstr(ares_buf_t *buf,
    714                                                      size_t      remaining_len,
    715                                                      unsigned char **bin,
    716                                                      size_t         *bin_len);
    717 
    718 /*! Load data from specified file path into provided buffer.  The entire file
    719  *  is loaded into memory.
    720  *
    721  *  \param[in]     filename complete path to file
    722  *  \param[in,out] buf      Initialized (non-const) buffer object to load data
    723  *                          into
    724  *  \return ARES_ENOTFOUND if file not found, ARES_EFILE if issues reading
    725  *          file, ARES_ENOMEM if out of memory, ARES_SUCCESS on success.
    726  */
    727 CARES_EXTERN ares_status_t ares_buf_load_file(const char *filename,
    728                                               ares_buf_t *buf);
    729 
    730 /*! @} */
    731 
    732 #endif /* __ARES__BUF_H */