11cb0ef41Sopenharmony_ci/* MIT License
21cb0ef41Sopenharmony_ci *
31cb0ef41Sopenharmony_ci * Copyright (c) 2023 Brad House
41cb0ef41Sopenharmony_ci *
51cb0ef41Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy
61cb0ef41Sopenharmony_ci * of this software and associated documentation files (the "Software"), to deal
71cb0ef41Sopenharmony_ci * in the Software without restriction, including without limitation the rights
81cb0ef41Sopenharmony_ci * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
91cb0ef41Sopenharmony_ci * copies of the Software, and to permit persons to whom the Software is
101cb0ef41Sopenharmony_ci * furnished to do so, subject to the following conditions:
111cb0ef41Sopenharmony_ci *
121cb0ef41Sopenharmony_ci * The above copyright notice and this permission notice (including the next
131cb0ef41Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
141cb0ef41Sopenharmony_ci * Software.
151cb0ef41Sopenharmony_ci *
161cb0ef41Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
171cb0ef41Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
181cb0ef41Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
191cb0ef41Sopenharmony_ci * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
201cb0ef41Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
211cb0ef41Sopenharmony_ci * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
221cb0ef41Sopenharmony_ci * SOFTWARE.
231cb0ef41Sopenharmony_ci *
241cb0ef41Sopenharmony_ci * SPDX-License-Identifier: MIT
251cb0ef41Sopenharmony_ci */
261cb0ef41Sopenharmony_ci#ifndef __ARES__BUF_H
271cb0ef41Sopenharmony_ci#define __ARES__BUF_H
281cb0ef41Sopenharmony_ci
291cb0ef41Sopenharmony_ci/*! \addtogroup ares__buf Safe Data Builder and buffer
301cb0ef41Sopenharmony_ci *
311cb0ef41Sopenharmony_ci * This is a buffer building and parsing framework with a focus on security over
321cb0ef41Sopenharmony_ci * performance. All data to be read from the buffer will perform explicit length
331cb0ef41Sopenharmony_ci * validation and return a success/fail result.  There are also various helpers
341cb0ef41Sopenharmony_ci * for writing data to the buffer which dynamically grows.
351cb0ef41Sopenharmony_ci *
361cb0ef41Sopenharmony_ci * All operations that fetch or consume data from the buffer will move forward
371cb0ef41Sopenharmony_ci * the internal pointer, thus marking the data as processed which may no longer
381cb0ef41Sopenharmony_ci * be accessible after certain operations (such as append).
391cb0ef41Sopenharmony_ci *
401cb0ef41Sopenharmony_ci * The helpers for this object are meant to be added as needed.  If you can't
411cb0ef41Sopenharmony_ci * find it, write it!
421cb0ef41Sopenharmony_ci *
431cb0ef41Sopenharmony_ci * @{
441cb0ef41Sopenharmony_ci */
451cb0ef41Sopenharmony_cistruct ares__buf;
461cb0ef41Sopenharmony_ci
471cb0ef41Sopenharmony_ci/*! Opaque data type for generic hash table implementation */
481cb0ef41Sopenharmony_citypedef struct ares__buf ares__buf_t;
491cb0ef41Sopenharmony_ci
501cb0ef41Sopenharmony_ci/*! Create a new buffer object that dynamically allocates buffers for data.
511cb0ef41Sopenharmony_ci *
521cb0ef41Sopenharmony_ci *  \return initialized buffer object or NULL if out of memory.
531cb0ef41Sopenharmony_ci */
541cb0ef41Sopenharmony_ciares__buf_t             *ares__buf_create(void);
551cb0ef41Sopenharmony_ci
561cb0ef41Sopenharmony_ci/*! Create a new buffer object that uses a user-provided data pointer.  The
571cb0ef41Sopenharmony_ci *  data provided will not be manipulated, and cannot be appended to.  This
581cb0ef41Sopenharmony_ci *  is strictly used for parsing.
591cb0ef41Sopenharmony_ci *
601cb0ef41Sopenharmony_ci *  \param[in] data     Data to provide to buffer, must not be NULL.
611cb0ef41Sopenharmony_ci *  \param[in] data_len Size of buffer provided, must be > 0
621cb0ef41Sopenharmony_ci *
631cb0ef41Sopenharmony_ci *  \return initialized buffer object or NULL if out of memory or misuse.
641cb0ef41Sopenharmony_ci */
651cb0ef41Sopenharmony_ciares__buf_t *ares__buf_create_const(const unsigned char *data, size_t data_len);
661cb0ef41Sopenharmony_ci
671cb0ef41Sopenharmony_ci
681cb0ef41Sopenharmony_ci/*! Destroy an initialized buffer object.
691cb0ef41Sopenharmony_ci *
701cb0ef41Sopenharmony_ci *  \param[in] buf  Initialized buf object
711cb0ef41Sopenharmony_ci */
721cb0ef41Sopenharmony_civoid         ares__buf_destroy(ares__buf_t *buf);
731cb0ef41Sopenharmony_ci
741cb0ef41Sopenharmony_ci
751cb0ef41Sopenharmony_ci/*! Append multiple bytes to a dynamic buffer object
761cb0ef41Sopenharmony_ci *
771cb0ef41Sopenharmony_ci *  \param[in] buf      Initialized buffer object
781cb0ef41Sopenharmony_ci *  \param[in] data     Data to copy to buffer object
791cb0ef41Sopenharmony_ci *  \param[in] data_len Length of data to copy to buffer object.
801cb0ef41Sopenharmony_ci *  \return ARES_SUCCESS or one of the c-ares error codes
811cb0ef41Sopenharmony_ci */
821cb0ef41Sopenharmony_ciares_status_t  ares__buf_append(ares__buf_t *buf, const unsigned char *data,
831cb0ef41Sopenharmony_ci                                size_t data_len);
841cb0ef41Sopenharmony_ci
851cb0ef41Sopenharmony_ci/*! Append a single byte to the dynamic buffer object
861cb0ef41Sopenharmony_ci *
871cb0ef41Sopenharmony_ci *  \param[in] buf      Initialized buffer object
881cb0ef41Sopenharmony_ci *  \param[in] byte     Single byte to append to buffer object.
891cb0ef41Sopenharmony_ci *  \return ARES_SUCCESS or one of the c-ares error codes
901cb0ef41Sopenharmony_ci */
911cb0ef41Sopenharmony_ciares_status_t  ares__buf_append_byte(ares__buf_t *buf, unsigned char byte);
921cb0ef41Sopenharmony_ci
931cb0ef41Sopenharmony_ci/*! Append a null-terminated string to the dynamic buffer object
941cb0ef41Sopenharmony_ci *
951cb0ef41Sopenharmony_ci *  \param[in] buf      Initialized buffer object
961cb0ef41Sopenharmony_ci *  \param[in] str      String to append to buffer object.
971cb0ef41Sopenharmony_ci *  \return ARES_SUCCESS or one of the c-ares error codes
981cb0ef41Sopenharmony_ci */
991cb0ef41Sopenharmony_ciares_status_t  ares__buf_append_str(ares__buf_t *buf, const char *str);
1001cb0ef41Sopenharmony_ci
1011cb0ef41Sopenharmony_ci/*! Append a 16bit Big Endian number to the buffer.
1021cb0ef41Sopenharmony_ci *
1031cb0ef41Sopenharmony_ci *  \param[in]  buf     Initialized buffer object
1041cb0ef41Sopenharmony_ci *  \param[out] u16     16bit integer
1051cb0ef41Sopenharmony_ci *  \return ARES_SUCCESS or one of the c-ares error codes
1061cb0ef41Sopenharmony_ci */
1071cb0ef41Sopenharmony_ciares_status_t  ares__buf_append_be16(ares__buf_t *buf, unsigned short u16);
1081cb0ef41Sopenharmony_ci
1091cb0ef41Sopenharmony_ci/*! Append a 32bit Big Endian number to the buffer.
1101cb0ef41Sopenharmony_ci *
1111cb0ef41Sopenharmony_ci *  \param[in]  buf     Initialized buffer object
1121cb0ef41Sopenharmony_ci *  \param[out] u32     32bit integer
1131cb0ef41Sopenharmony_ci *  \return ARES_SUCCESS or one of the c-ares error codes
1141cb0ef41Sopenharmony_ci */
1151cb0ef41Sopenharmony_ciares_status_t  ares__buf_append_be32(ares__buf_t *buf, unsigned int u32);
1161cb0ef41Sopenharmony_ci
1171cb0ef41Sopenharmony_ci/*! Append a number in ASCII decimal form.
1181cb0ef41Sopenharmony_ci *
1191cb0ef41Sopenharmony_ci *  \param[in] buf  Initialized buffer object
1201cb0ef41Sopenharmony_ci *  \param[in] num  Number to print
1211cb0ef41Sopenharmony_ci *  \param[in] len  Length to output, use 0 for no padding
1221cb0ef41Sopenharmony_ci *  \return ARES_SUCCESS on success
1231cb0ef41Sopenharmony_ci */
1241cb0ef41Sopenharmony_ciares_status_t  ares__buf_append_num_dec(ares__buf_t *buf, size_t num,
1251cb0ef41Sopenharmony_ci                                        size_t len);
1261cb0ef41Sopenharmony_ci
1271cb0ef41Sopenharmony_ci/*! Append a number in ASCII hexadecimal form.
1281cb0ef41Sopenharmony_ci *
1291cb0ef41Sopenharmony_ci *  \param[in] buf  Initialized buffer object
1301cb0ef41Sopenharmony_ci *  \param[in] num  Number to print
1311cb0ef41Sopenharmony_ci *  \param[in] len  Length to output, use 0 for no padding
1321cb0ef41Sopenharmony_ci *  \return ARES_SUCCESS on success
1331cb0ef41Sopenharmony_ci */
1341cb0ef41Sopenharmony_ciares_status_t  ares__buf_append_num_hex(ares__buf_t *buf, size_t num,
1351cb0ef41Sopenharmony_ci                                        size_t len);
1361cb0ef41Sopenharmony_ci
1371cb0ef41Sopenharmony_ci/*! Sets the current buffer length.  This *may* be used if there is a need to
1381cb0ef41Sopenharmony_ci *  override a prior position in the buffer, such as if there is a length
1391cb0ef41Sopenharmony_ci *  prefix that isn't easily predictable, and you must go back and overwrite
1401cb0ef41Sopenharmony_ci *  that position.
1411cb0ef41Sopenharmony_ci *
1421cb0ef41Sopenharmony_ci *  Only valid on non-const buffers.  Length provided must not exceed current
1431cb0ef41Sopenharmony_ci *  allocated buffer size, but otherwise there are very few protections on
1441cb0ef41Sopenharmony_ci *  this function.  Use cautiously.
1451cb0ef41Sopenharmony_ci *
1461cb0ef41Sopenharmony_ci *  \param[in]  buf  Initialized buffer object
1471cb0ef41Sopenharmony_ci *  \param[in]  len  Length to set
1481cb0ef41Sopenharmony_ci *  \return ARES_SUCCESS or one of the c-ares error codes
1491cb0ef41Sopenharmony_ci */
1501cb0ef41Sopenharmony_ciares_status_t  ares__buf_set_length(ares__buf_t *buf, size_t len);
1511cb0ef41Sopenharmony_ci
1521cb0ef41Sopenharmony_ci
1531cb0ef41Sopenharmony_ci/*! Start a dynamic append operation that returns a buffer suitable for
1541cb0ef41Sopenharmony_ci *  writing.  A desired minimum length is passed in, and the actual allocated
1551cb0ef41Sopenharmony_ci *  buffer size is returned which may be greater than the requested size.
1561cb0ef41Sopenharmony_ci *  No operation other than ares__buf_append_finish() is allowed on the
1571cb0ef41Sopenharmony_ci *  buffer after this request.
1581cb0ef41Sopenharmony_ci *
1591cb0ef41Sopenharmony_ci *  \param[in]     buf     Initialized buffer object
1601cb0ef41Sopenharmony_ci *  \param[in,out] len     Desired non-zero length passed in, actual buffer size
1611cb0ef41Sopenharmony_ci *                         returned.
1621cb0ef41Sopenharmony_ci *  \return Pointer to writable buffer or NULL on failure (usage, out of mem)
1631cb0ef41Sopenharmony_ci */
1641cb0ef41Sopenharmony_ciunsigned char *ares__buf_append_start(ares__buf_t *buf, size_t *len);
1651cb0ef41Sopenharmony_ci
1661cb0ef41Sopenharmony_ci/*! Finish a dynamic append operation.  Called after
1671cb0ef41Sopenharmony_ci *  ares__buf_append_start() once desired data is written.
1681cb0ef41Sopenharmony_ci *
1691cb0ef41Sopenharmony_ci *  \param[in] buf    Initialized buffer object.
1701cb0ef41Sopenharmony_ci *  \param[in] len    Length of data written.  May be zero to terminate
1711cb0ef41Sopenharmony_ci *                    operation. Must not be greater than returned from
1721cb0ef41Sopenharmony_ci *                    ares__buf_append_start().
1731cb0ef41Sopenharmony_ci */
1741cb0ef41Sopenharmony_civoid           ares__buf_append_finish(ares__buf_t *buf, size_t len);
1751cb0ef41Sopenharmony_ci
1761cb0ef41Sopenharmony_ci/*! Write the data provided to the buffer in a hexdump format.
1771cb0ef41Sopenharmony_ci *
1781cb0ef41Sopenharmony_ci *  \param[in] buf      Initialized buffer object.
1791cb0ef41Sopenharmony_ci *  \param[in] data     Data to hex dump
1801cb0ef41Sopenharmony_ci *  \param[in] data_len Length of data to hexdump
1811cb0ef41Sopenharmony_ci *  \return ARES_SUCCESS on success.
1821cb0ef41Sopenharmony_ci */
1831cb0ef41Sopenharmony_ciares_status_t  ares__buf_hexdump(ares__buf_t *buf, const unsigned char *data,
1841cb0ef41Sopenharmony_ci                                 size_t len);
1851cb0ef41Sopenharmony_ci
1861cb0ef41Sopenharmony_ci/*! Clean up ares__buf_t and return allocated pointer to unprocessed data.  It
1871cb0ef41Sopenharmony_ci *  is the responsibility of the  caller to ares_free() the returned buffer.
1881cb0ef41Sopenharmony_ci *  The passed in buf parameter is invalidated by this call.
1891cb0ef41Sopenharmony_ci *
1901cb0ef41Sopenharmony_ci * \param[in]  buf    Initialized buffer object. Can not be a "const" buffer.
1911cb0ef41Sopenharmony_ci * \param[out] len    Length of data returned
1921cb0ef41Sopenharmony_ci * \return pointer to unprocessed data (may be zero length) or NULL on error.
1931cb0ef41Sopenharmony_ci */
1941cb0ef41Sopenharmony_ciunsigned char *ares__buf_finish_bin(ares__buf_t *buf, size_t *len);
1951cb0ef41Sopenharmony_ci
1961cb0ef41Sopenharmony_ci/*! Clean up ares__buf_t and return allocated pointer to unprocessed data and
1971cb0ef41Sopenharmony_ci *  return it as a string (null terminated).  It is the responsibility of the
1981cb0ef41Sopenharmony_ci *  caller to ares_free() the returned buffer. The passed in buf parameter is
1991cb0ef41Sopenharmony_ci *  invalidated by this call.
2001cb0ef41Sopenharmony_ci *
2011cb0ef41Sopenharmony_ci *  This function in no way validates the data in this buffer is actually
2021cb0ef41Sopenharmony_ci *  a string, that characters are printable, or that there aren't multiple
2031cb0ef41Sopenharmony_ci *  NULL terminators.  It is assumed that the caller will either validate that
2041cb0ef41Sopenharmony_ci *  themselves or has built this buffer with only a valid character set.
2051cb0ef41Sopenharmony_ci *
2061cb0ef41Sopenharmony_ci * \param[in]  buf    Initialized buffer object. Can not be a "const" buffer.
2071cb0ef41Sopenharmony_ci * \param[out] len    Optional. Length of data returned, or NULL if not needed.
2081cb0ef41Sopenharmony_ci * \return pointer to unprocessed data or NULL on error.
2091cb0ef41Sopenharmony_ci */
2101cb0ef41Sopenharmony_cichar          *ares__buf_finish_str(ares__buf_t *buf, size_t *len);
2111cb0ef41Sopenharmony_ci
2121cb0ef41Sopenharmony_ci/*! Tag a position to save in the buffer in case parsing needs to rollback,
2131cb0ef41Sopenharmony_ci *  such as if insufficient data is available, but more data may be added in
2141cb0ef41Sopenharmony_ci *  the future.  Only a single tag can be set per buffer object.  Setting a
2151cb0ef41Sopenharmony_ci *  tag will override any pre-existing tag.
2161cb0ef41Sopenharmony_ci *
2171cb0ef41Sopenharmony_ci *  \param[in] buf Initialized buffer object
2181cb0ef41Sopenharmony_ci */
2191cb0ef41Sopenharmony_civoid           ares__buf_tag(ares__buf_t *buf);
2201cb0ef41Sopenharmony_ci
2211cb0ef41Sopenharmony_ci/*! Rollback to a tagged position.  Will automatically clear the tag.
2221cb0ef41Sopenharmony_ci *
2231cb0ef41Sopenharmony_ci *  \param[in] buf Initialized buffer object
2241cb0ef41Sopenharmony_ci *  \return ARES_SUCCESS or one of the c-ares error codes
2251cb0ef41Sopenharmony_ci */
2261cb0ef41Sopenharmony_ciares_status_t  ares__buf_tag_rollback(ares__buf_t *buf);
2271cb0ef41Sopenharmony_ci
2281cb0ef41Sopenharmony_ci/*! Clear the tagged position without rolling back.  You should do this any
2291cb0ef41Sopenharmony_ci *  time a tag is no longer needed as future append operations can reclaim
2301cb0ef41Sopenharmony_ci *  buffer space.
2311cb0ef41Sopenharmony_ci *
2321cb0ef41Sopenharmony_ci *  \param[in] buf Initialized buffer object
2331cb0ef41Sopenharmony_ci *  \return ARES_SUCCESS or one of the c-ares error codes
2341cb0ef41Sopenharmony_ci */
2351cb0ef41Sopenharmony_ciares_status_t  ares__buf_tag_clear(ares__buf_t *buf);
2361cb0ef41Sopenharmony_ci
2371cb0ef41Sopenharmony_ci/*! Fetch the buffer and length of data starting from the tagged position up
2381cb0ef41Sopenharmony_ci *  to the _current_ position.  It will not unset the tagged position.  The
2391cb0ef41Sopenharmony_ci *  data may be invalidated by any future ares__buf_*() calls.
2401cb0ef41Sopenharmony_ci *
2411cb0ef41Sopenharmony_ci *  \param[in]  buf    Initialized buffer object
2421cb0ef41Sopenharmony_ci *  \param[out] len    Length between tag and current offset in buffer
2431cb0ef41Sopenharmony_ci *  \return NULL on failure (such as no tag), otherwise pointer to start of
2441cb0ef41Sopenharmony_ci *          buffer
2451cb0ef41Sopenharmony_ci */
2461cb0ef41Sopenharmony_ciconst unsigned char *ares__buf_tag_fetch(const ares__buf_t *buf, size_t *len);
2471cb0ef41Sopenharmony_ci
2481cb0ef41Sopenharmony_ci/*! Get the length of the current tag offset to the current position.
2491cb0ef41Sopenharmony_ci *
2501cb0ef41Sopenharmony_ci *  \param[in]  buf    Initialized buffer object
2511cb0ef41Sopenharmony_ci *  \return length
2521cb0ef41Sopenharmony_ci */
2531cb0ef41Sopenharmony_cisize_t               ares__buf_tag_length(const ares__buf_t *buf);
2541cb0ef41Sopenharmony_ci
2551cb0ef41Sopenharmony_ci/*! Fetch the bytes starting from the tagged position up to the _current_
2561cb0ef41Sopenharmony_ci *  position using the provided buffer.  It will not unset the tagged position.
2571cb0ef41Sopenharmony_ci *
2581cb0ef41Sopenharmony_ci *  \param[in]     buf    Initialized buffer object
2591cb0ef41Sopenharmony_ci *  \param[in,out] bytes  Buffer to hold data
2601cb0ef41Sopenharmony_ci *  \param[in,out] len    On input, buffer size, on output, bytes place in
2611cb0ef41Sopenharmony_ci *                        buffer.
2621cb0ef41Sopenharmony_ci *  \return ARES_SUCCESS if fetched, ARES_EFORMERR if insufficient buffer size
2631cb0ef41Sopenharmony_ci */
2641cb0ef41Sopenharmony_ciares_status_t        ares__buf_tag_fetch_bytes(const ares__buf_t *buf,
2651cb0ef41Sopenharmony_ci                                               unsigned char *bytes, size_t *len);
2661cb0ef41Sopenharmony_ci
2671cb0ef41Sopenharmony_ci/*! Fetch the bytes starting from the tagged position up to the _current_
2681cb0ef41Sopenharmony_ci *  position as a NULL-terminated string using the provided buffer.  The data
2691cb0ef41Sopenharmony_ci *  is validated to be ASCII-printable data.  It will not unset the tagged
2701cb0ef41Sopenharmony_ci *  poition.
2711cb0ef41Sopenharmony_ci *
2721cb0ef41Sopenharmony_ci *  \param[in]     buf    Initialized buffer object
2731cb0ef41Sopenharmony_ci *  \param[in,out] str    Buffer to hold data
2741cb0ef41Sopenharmony_ci *  \param[in]     len    On input, buffer size, on output, bytes place in
2751cb0ef41Sopenharmony_ci *                        buffer.
2761cb0ef41Sopenharmony_ci *  \return ARES_SUCCESS if fetched, ARES_EFORMERR if insufficient buffer size,
2771cb0ef41Sopenharmony_ci *          ARES_EBADSTR if not printable ASCII
2781cb0ef41Sopenharmony_ci */
2791cb0ef41Sopenharmony_ciares_status_t ares__buf_tag_fetch_string(const ares__buf_t *buf, char *str,
2801cb0ef41Sopenharmony_ci                                         size_t len);
2811cb0ef41Sopenharmony_ci
2821cb0ef41Sopenharmony_ci/*! Consume the given number of bytes without reading them.
2831cb0ef41Sopenharmony_ci *
2841cb0ef41Sopenharmony_ci *  \param[in] buf    Initialized buffer object
2851cb0ef41Sopenharmony_ci *  \param[in] len    Length to consume
2861cb0ef41Sopenharmony_ci *  \return ARES_SUCCESS or one of the c-ares error codes
2871cb0ef41Sopenharmony_ci */
2881cb0ef41Sopenharmony_ciares_status_t ares__buf_consume(ares__buf_t *buf, size_t len);
2891cb0ef41Sopenharmony_ci
2901cb0ef41Sopenharmony_ci/*! Fetch a 16bit Big Endian number from the buffer.
2911cb0ef41Sopenharmony_ci *
2921cb0ef41Sopenharmony_ci *  \param[in]  buf     Initialized buffer object
2931cb0ef41Sopenharmony_ci *  \param[out] u16     Buffer to hold 16bit integer
2941cb0ef41Sopenharmony_ci *  \return ARES_SUCCESS or one of the c-ares error codes
2951cb0ef41Sopenharmony_ci */
2961cb0ef41Sopenharmony_ciares_status_t ares__buf_fetch_be16(ares__buf_t *buf, unsigned short *u16);
2971cb0ef41Sopenharmony_ci
2981cb0ef41Sopenharmony_ci/*! Fetch a 32bit Big Endian number from the buffer.
2991cb0ef41Sopenharmony_ci *
3001cb0ef41Sopenharmony_ci *  \param[in]  buf     Initialized buffer object
3011cb0ef41Sopenharmony_ci *  \param[out] u32     Buffer to hold 32bit integer
3021cb0ef41Sopenharmony_ci *  \return ARES_SUCCESS or one of the c-ares error codes
3031cb0ef41Sopenharmony_ci */
3041cb0ef41Sopenharmony_ciares_status_t ares__buf_fetch_be32(ares__buf_t *buf, unsigned int *u32);
3051cb0ef41Sopenharmony_ci
3061cb0ef41Sopenharmony_ci
3071cb0ef41Sopenharmony_ci/*! Fetch the requested number of bytes into the provided buffer
3081cb0ef41Sopenharmony_ci *
3091cb0ef41Sopenharmony_ci *  \param[in]  buf     Initialized buffer object
3101cb0ef41Sopenharmony_ci *  \param[out] bytes   Buffer to hold data
3111cb0ef41Sopenharmony_ci *  \param[in]  len     Requested number of bytes (must be > 0)
3121cb0ef41Sopenharmony_ci *  \return ARES_SUCCESS or one of the c-ares error codes
3131cb0ef41Sopenharmony_ci */
3141cb0ef41Sopenharmony_ciares_status_t ares__buf_fetch_bytes(ares__buf_t *buf, unsigned char *bytes,
3151cb0ef41Sopenharmony_ci                                    size_t len);
3161cb0ef41Sopenharmony_ci
3171cb0ef41Sopenharmony_ci
3181cb0ef41Sopenharmony_ci/*! Fetch the requested number of bytes and return a new buffer that must be
3191cb0ef41Sopenharmony_ci *  ares_free()'d by the caller.
3201cb0ef41Sopenharmony_ci *
3211cb0ef41Sopenharmony_ci *  \param[in]  buf       Initialized buffer object
3221cb0ef41Sopenharmony_ci *  \param[in]  len       Requested number of bytes (must be > 0)
3231cb0ef41Sopenharmony_ci *  \param[in]  null_term Even though this is considered binary data, the user
3241cb0ef41Sopenharmony_ci *                        knows it may be a vald string, so add a null
3251cb0ef41Sopenharmony_ci *                        terminator.
3261cb0ef41Sopenharmony_ci *  \param[out] bytes     Pointer passed by reference. Will be allocated.
3271cb0ef41Sopenharmony_ci *  \return ARES_SUCCESS or one of the c-ares error codes
3281cb0ef41Sopenharmony_ci */
3291cb0ef41Sopenharmony_ciares_status_t ares__buf_fetch_bytes_dup(ares__buf_t *buf, size_t len,
3301cb0ef41Sopenharmony_ci                                        ares_bool_t     null_term,
3311cb0ef41Sopenharmony_ci                                        unsigned char **bytes);
3321cb0ef41Sopenharmony_ci
3331cb0ef41Sopenharmony_ci/*! Fetch the requested number of bytes and place them into the provided
3341cb0ef41Sopenharmony_ci *  dest buffer object.
3351cb0ef41Sopenharmony_ci *
3361cb0ef41Sopenharmony_ci *  \param[in]  buf     Initialized buffer object
3371cb0ef41Sopenharmony_ci *  \param[out] dest    Buffer object to append bytes.
3381cb0ef41Sopenharmony_ci *  \param[in]  len     Requested number of bytes (must be > 0)
3391cb0ef41Sopenharmony_ci *  \return ARES_SUCCESS or one of the c-ares error codes
3401cb0ef41Sopenharmony_ci */
3411cb0ef41Sopenharmony_ciares_status_t ares__buf_fetch_bytes_into_buf(ares__buf_t *buf,
3421cb0ef41Sopenharmony_ci                                             ares__buf_t *dest, size_t len);
3431cb0ef41Sopenharmony_ci
3441cb0ef41Sopenharmony_ci/*! Fetch the requested number of bytes and return a new buffer that must be
3451cb0ef41Sopenharmony_ci *  ares_free()'d by the caller.  The returned buffer is a null terminated
3461cb0ef41Sopenharmony_ci *  string.
3471cb0ef41Sopenharmony_ci *
3481cb0ef41Sopenharmony_ci *  \param[in]  buf     Initialized buffer object
3491cb0ef41Sopenharmony_ci *  \param[in]  len     Requested number of bytes (must be > 0)
3501cb0ef41Sopenharmony_ci *  \param[out] str     Pointer passed by reference. Will be allocated.
3511cb0ef41Sopenharmony_ci *  \return ARES_SUCCESS or one of the c-ares error codes
3521cb0ef41Sopenharmony_ci */
3531cb0ef41Sopenharmony_ciares_status_t ares__buf_fetch_str_dup(ares__buf_t *buf, size_t len, char **str);
3541cb0ef41Sopenharmony_ci
3551cb0ef41Sopenharmony_ci/*! Consume whitespace characters (0x09, 0x0B, 0x0C, 0x0D, 0x20, and optionally
3561cb0ef41Sopenharmony_ci *  0x0A).
3571cb0ef41Sopenharmony_ci *
3581cb0ef41Sopenharmony_ci *  \param[in]  buf               Initialized buffer object
3591cb0ef41Sopenharmony_ci *  \param[in]  include_linefeed  ARES_TRUE to include consuming 0x0A,
3601cb0ef41Sopenharmony_ci *                                ARES_FALSE otherwise.
3611cb0ef41Sopenharmony_ci *  \return number of whitespace characters consumed
3621cb0ef41Sopenharmony_ci */
3631cb0ef41Sopenharmony_cisize_t        ares__buf_consume_whitespace(ares__buf_t *buf,
3641cb0ef41Sopenharmony_ci                                           ares_bool_t  include_linefeed);
3651cb0ef41Sopenharmony_ci
3661cb0ef41Sopenharmony_ci
3671cb0ef41Sopenharmony_ci/*! Consume any non-whitespace character (anything other than 0x09, 0x0B, 0x0C,
3681cb0ef41Sopenharmony_ci *  0x0D, 0x20, and 0x0A).
3691cb0ef41Sopenharmony_ci *
3701cb0ef41Sopenharmony_ci *  \param[in]  buf               Initialized buffer object
3711cb0ef41Sopenharmony_ci *  \return number of characters consumed
3721cb0ef41Sopenharmony_ci */
3731cb0ef41Sopenharmony_cisize_t        ares__buf_consume_nonwhitespace(ares__buf_t *buf);
3741cb0ef41Sopenharmony_ci
3751cb0ef41Sopenharmony_ci
3761cb0ef41Sopenharmony_ci/*! Consume until a character in the character set provided is reached
3771cb0ef41Sopenharmony_ci *
3781cb0ef41Sopenharmony_ci *  \param[in] buf                Initialized buffer object
3791cb0ef41Sopenharmony_ci *  \param[in] charset            character set
3801cb0ef41Sopenharmony_ci *  \param[in] len                length of character set
3811cb0ef41Sopenharmony_ci *  \param[in] require_charset    require we find a character from the charset.
3821cb0ef41Sopenharmony_ci *                                if ARES_FALSE it will simply consume the
3831cb0ef41Sopenharmony_ci *                                rest of the buffer.  If ARES_TRUE will return
3841cb0ef41Sopenharmony_ci *                                0 if not found.
3851cb0ef41Sopenharmony_ci *  \return number of characters consumed
3861cb0ef41Sopenharmony_ci */
3871cb0ef41Sopenharmony_cisize_t        ares__buf_consume_until_charset(ares__buf_t         *buf,
3881cb0ef41Sopenharmony_ci                                              const unsigned char *charset, size_t len,
3891cb0ef41Sopenharmony_ci                                              ares_bool_t require_charset);
3901cb0ef41Sopenharmony_ci
3911cb0ef41Sopenharmony_ci
3921cb0ef41Sopenharmony_ci/*! Consume while the characters match the characters in the provided set.
3931cb0ef41Sopenharmony_ci *
3941cb0ef41Sopenharmony_ci *  \param[in] buf                Initialized buffer object
3951cb0ef41Sopenharmony_ci *  \param[in] charset            character set
3961cb0ef41Sopenharmony_ci *  \param[in] len                length of character set
3971cb0ef41Sopenharmony_ci *  \return number of characters consumed
3981cb0ef41Sopenharmony_ci */
3991cb0ef41Sopenharmony_cisize_t ares__buf_consume_charset(ares__buf_t *buf, const unsigned char *charset,
4001cb0ef41Sopenharmony_ci                                 size_t len);
4011cb0ef41Sopenharmony_ci
4021cb0ef41Sopenharmony_ci
4031cb0ef41Sopenharmony_ci/*! Consume from the current position until the end of the line, and optionally
4041cb0ef41Sopenharmony_ci *  the end of line character (0x0A) itself.
4051cb0ef41Sopenharmony_ci *
4061cb0ef41Sopenharmony_ci *  \param[in]  buf               Initialized buffer object
4071cb0ef41Sopenharmony_ci *  \param[in]  include_linefeed  ARES_TRUE to include consuming 0x0A,
4081cb0ef41Sopenharmony_ci *                                ARES_FALSE otherwise.
4091cb0ef41Sopenharmony_ci *  \return number of characters consumed
4101cb0ef41Sopenharmony_ci */
4111cb0ef41Sopenharmony_cisize_t ares__buf_consume_line(ares__buf_t *buf, ares_bool_t include_linefeed);
4121cb0ef41Sopenharmony_ci
4131cb0ef41Sopenharmony_citypedef enum {
4141cb0ef41Sopenharmony_ci  /*! No flags */
4151cb0ef41Sopenharmony_ci  ARES_BUF_SPLIT_NONE = 0,
4161cb0ef41Sopenharmony_ci  /*! The delimiter will be the first character in the buffer, except the
4171cb0ef41Sopenharmony_ci   *  first buffer since the start doesn't have a delimiter
4181cb0ef41Sopenharmony_ci   */
4191cb0ef41Sopenharmony_ci  ARES_BUF_SPLIT_DONT_CONSUME_DELIMS = 1 << 0,
4201cb0ef41Sopenharmony_ci  /*! Allow blank sections, by default blank sections are not emitted.  If using
4211cb0ef41Sopenharmony_ci   *  ARES_BUF_SPLIT_DONT_CONSUME_DELIMS, the delimiter is not counted as part
4221cb0ef41Sopenharmony_ci   *  of the section */
4231cb0ef41Sopenharmony_ci  ARES_BUF_SPLIT_ALLOW_BLANK = 1 << 1,
4241cb0ef41Sopenharmony_ci  /*! Remove duplicate entries */
4251cb0ef41Sopenharmony_ci  ARES_BUF_SPLIT_NO_DUPLICATES = 1 << 2,
4261cb0ef41Sopenharmony_ci  /*! Perform case-insensitive matching when comparing values */
4271cb0ef41Sopenharmony_ci  ARES_BUF_SPLIT_CASE_INSENSITIVE = 1 << 3
4281cb0ef41Sopenharmony_ci} ares__buf_split_t;
4291cb0ef41Sopenharmony_ci
4301cb0ef41Sopenharmony_ci/*! Split the provided buffer into multiple sub-buffers stored in the variable
4311cb0ef41Sopenharmony_ci *  pointed to by the linked list.  The sub buffers are const buffers pointing
4321cb0ef41Sopenharmony_ci *  into the buf provided.
4331cb0ef41Sopenharmony_ci *
4341cb0ef41Sopenharmony_ci *  \param[in]  buf               Initialized buffer object
4351cb0ef41Sopenharmony_ci *  \param[in]  delims            Possible delimiters
4361cb0ef41Sopenharmony_ci *  \param[in]  delims_len        Length of possible delimiters
4371cb0ef41Sopenharmony_ci *  \param[in]  flags             One more more flags
4381cb0ef41Sopenharmony_ci *  \param[out] list              Result. Depending on flags, this may be a
4391cb0ef41Sopenharmony_ci *                                valid list with no elements.  Use
4401cb0ef41Sopenharmony_ci *                                ares__llist_destroy() to free the memory which
4411cb0ef41Sopenharmony_ci *                                will also free the contained ares__buf_t
4421cb0ef41Sopenharmony_ci *                                objects.
4431cb0ef41Sopenharmony_ci *  \return ARES_SUCCESS on success, or error like ARES_ENOMEM.
4441cb0ef41Sopenharmony_ci */
4451cb0ef41Sopenharmony_ciares_status_t ares__buf_split(ares__buf_t *buf, const unsigned char *delims,
4461cb0ef41Sopenharmony_ci                              size_t delims_len, ares__buf_split_t flags,
4471cb0ef41Sopenharmony_ci                              ares__llist_t **list);
4481cb0ef41Sopenharmony_ci
4491cb0ef41Sopenharmony_ci
4501cb0ef41Sopenharmony_ci/*! Check the unprocessed buffer to see if it begins with the sequence of
4511cb0ef41Sopenharmony_ci *  characters provided.
4521cb0ef41Sopenharmony_ci *
4531cb0ef41Sopenharmony_ci *  \param[in] buf          Initialized buffer object
4541cb0ef41Sopenharmony_ci *  \param[in] data         Bytes of data to compare.
4551cb0ef41Sopenharmony_ci *  \param[in] data_len     Length of data to compare.
4561cb0ef41Sopenharmony_ci *  \return ARES_TRUE on match, ARES_FALSE otherwise.
4571cb0ef41Sopenharmony_ci */
4581cb0ef41Sopenharmony_ciares_bool_t   ares__buf_begins_with(const ares__buf_t   *buf,
4591cb0ef41Sopenharmony_ci                                    const unsigned char *data, size_t data_len);
4601cb0ef41Sopenharmony_ci
4611cb0ef41Sopenharmony_ci
4621cb0ef41Sopenharmony_ci/*! Size of unprocessed remaining data length
4631cb0ef41Sopenharmony_ci *
4641cb0ef41Sopenharmony_ci *  \param[in] buf Initialized buffer object
4651cb0ef41Sopenharmony_ci *  \return length remaining
4661cb0ef41Sopenharmony_ci */
4671cb0ef41Sopenharmony_cisize_t        ares__buf_len(const ares__buf_t *buf);
4681cb0ef41Sopenharmony_ci
4691cb0ef41Sopenharmony_ci/*! Retrieve a pointer to the currently unprocessed data.  Generally this isn't
4701cb0ef41Sopenharmony_ci *  recommended to be used in practice.  The returned pointer may be invalidated
4711cb0ef41Sopenharmony_ci *  by any future ares__buf_*() calls.
4721cb0ef41Sopenharmony_ci *
4731cb0ef41Sopenharmony_ci *  \param[in]  buf    Initialized buffer object
4741cb0ef41Sopenharmony_ci *  \param[out] len    Length of available data
4751cb0ef41Sopenharmony_ci *  \return Pointer to buffer of unprocessed data
4761cb0ef41Sopenharmony_ci */
4771cb0ef41Sopenharmony_ciconst unsigned char *ares__buf_peek(const ares__buf_t *buf, size_t *len);
4781cb0ef41Sopenharmony_ci
4791cb0ef41Sopenharmony_ci
4801cb0ef41Sopenharmony_ci/*! Wipe any processed data from the beginning of the buffer.  This will
4811cb0ef41Sopenharmony_ci *  move any remaining data to the front of the internally allocated buffer.
4821cb0ef41Sopenharmony_ci *
4831cb0ef41Sopenharmony_ci *  Can not be used on const buffer objects.
4841cb0ef41Sopenharmony_ci *
4851cb0ef41Sopenharmony_ci *  Typically not needed to call, as any new append operation will automatically
4861cb0ef41Sopenharmony_ci *  call this function if there is insufficient space to append the data in
4871cb0ef41Sopenharmony_ci *  order to try to avoid another memory allocation.
4881cb0ef41Sopenharmony_ci *
4891cb0ef41Sopenharmony_ci *  It may be useful to call in order to ensure the current message being
4901cb0ef41Sopenharmony_ci *  processed is in the beginning of the buffer if there is an intent to use
4911cb0ef41Sopenharmony_ci *  ares__buf_set_position() and ares__buf_get_position() as may be necessary
4921cb0ef41Sopenharmony_ci *  when processing DNS compressed names.
4931cb0ef41Sopenharmony_ci *
4941cb0ef41Sopenharmony_ci *  If there is an active tag, it will NOT clear the tag, it will use the tag
4951cb0ef41Sopenharmony_ci *  as the start of the unprocessed data rather than the current offset.  If
4961cb0ef41Sopenharmony_ci *  a prior tag is no longer needed, may be wise to call ares__buf_tag_clear().
4971cb0ef41Sopenharmony_ci *
4981cb0ef41Sopenharmony_ci *  \param[in]  buf    Initialized buffer object
4991cb0ef41Sopenharmony_ci */
5001cb0ef41Sopenharmony_civoid                 ares__buf_reclaim(ares__buf_t *buf);
5011cb0ef41Sopenharmony_ci
5021cb0ef41Sopenharmony_ci/*! Set the current offset within the internal buffer.
5031cb0ef41Sopenharmony_ci *
5041cb0ef41Sopenharmony_ci *  Typically this should not be used, if possible, use the ares__buf_tag*()
5051cb0ef41Sopenharmony_ci *  operations instead.
5061cb0ef41Sopenharmony_ci *
5071cb0ef41Sopenharmony_ci *  One exception is DNS name compression which may backwards reference to
5081cb0ef41Sopenharmony_ci *  an index in the message.  It may be necessary in such a case to call
5091cb0ef41Sopenharmony_ci *  ares__buf_reclaim() if using a dynamic (non-const) buffer before processing
5101cb0ef41Sopenharmony_ci *  such a message.
5111cb0ef41Sopenharmony_ci *
5121cb0ef41Sopenharmony_ci *  \param[in] buf  Initialized buffer object
5131cb0ef41Sopenharmony_ci *  \param[in] idx  Index to set position
5141cb0ef41Sopenharmony_ci *  \return ARES_SUCCESS if valid index
5151cb0ef41Sopenharmony_ci */
5161cb0ef41Sopenharmony_ciares_status_t        ares__buf_set_position(ares__buf_t *buf, size_t idx);
5171cb0ef41Sopenharmony_ci
5181cb0ef41Sopenharmony_ci/*! Get the current offset within the internal buffer.
5191cb0ef41Sopenharmony_ci *
5201cb0ef41Sopenharmony_ci *  Typically this should not be used, if possible, use the ares__buf_tag*()
5211cb0ef41Sopenharmony_ci *  operations instead.
5221cb0ef41Sopenharmony_ci *
5231cb0ef41Sopenharmony_ci *  This can be used to get the current position, useful for saving if a
5241cb0ef41Sopenharmony_ci *  jump via ares__buf_set_position() is performed and need to restore the
5251cb0ef41Sopenharmony_ci *  current position for future operations.
5261cb0ef41Sopenharmony_ci *
5271cb0ef41Sopenharmony_ci *  \param[in] buf Initialized buffer object
5281cb0ef41Sopenharmony_ci *  \return index of current position
5291cb0ef41Sopenharmony_ci */
5301cb0ef41Sopenharmony_cisize_t               ares__buf_get_position(const ares__buf_t *buf);
5311cb0ef41Sopenharmony_ci
5321cb0ef41Sopenharmony_ci/*! Parse a character-string as defined in RFC1035, as a null-terminated
5331cb0ef41Sopenharmony_ci *  string.
5341cb0ef41Sopenharmony_ci *
5351cb0ef41Sopenharmony_ci *  \param[in]  buf            initialized buffer object
5361cb0ef41Sopenharmony_ci *  \param[in]  remaining_len  maximum length that should be used for parsing
5371cb0ef41Sopenharmony_ci *                             the string, this is often less than the remaining
5381cb0ef41Sopenharmony_ci *                             buffer and is based on the RR record length.
5391cb0ef41Sopenharmony_ci *  \param[out] str            Pointer passed by reference to be filled in with
5401cb0ef41Sopenharmony_ci *                             allocated string of the parsed that must be
5411cb0ef41Sopenharmony_ci *                             ares_free()'d by the caller.
5421cb0ef41Sopenharmony_ci *  \param[in]  allow_multiple ARES_TRUE if it should attempt to parse multiple
5431cb0ef41Sopenharmony_ci *                             strings back to back, and will concatenate in
5441cb0ef41Sopenharmony_ci *                             the returned str.
5451cb0ef41Sopenharmony_ci *  \return ARES_SUCCESS on success
5461cb0ef41Sopenharmony_ci */
5471cb0ef41Sopenharmony_ciares_status_t ares__buf_parse_dns_str(ares__buf_t *buf, size_t remaining_len,
5481cb0ef41Sopenharmony_ci                                      char **name, ares_bool_t allow_multiple);
5491cb0ef41Sopenharmony_ci
5501cb0ef41Sopenharmony_ci/*! Parse a character-string as defined in RFC1035, as binary, however for
5511cb0ef41Sopenharmony_ci *  convenience this does guarantee a NULL terminator (that is not included
5521cb0ef41Sopenharmony_ci *  in the returned length).
5531cb0ef41Sopenharmony_ci *
5541cb0ef41Sopenharmony_ci *  \param[in]  buf            initialized buffer object
5551cb0ef41Sopenharmony_ci *  \param[in]  remaining_len  maximum length that should be used for parsing
5561cb0ef41Sopenharmony_ci *                             the string, this is often less than the remaining
5571cb0ef41Sopenharmony_ci *                             buffer and is based on the RR record length.
5581cb0ef41Sopenharmony_ci *  \param[out] bin            Pointer passed by reference to be filled in with
5591cb0ef41Sopenharmony_ci *                             allocated string of the parsed that must be
5601cb0ef41Sopenharmony_ci *                             ares_free()'d by the caller.
5611cb0ef41Sopenharmony_ci *  \param[out] bin_len        Length of returned string.
5621cb0ef41Sopenharmony_ci *  \param[in]  allow_multiple ARES_TRUE if it should attempt to parse multiple
5631cb0ef41Sopenharmony_ci *                             strings back to back, and will concatenate in
5641cb0ef41Sopenharmony_ci *                             the returned str.
5651cb0ef41Sopenharmony_ci *  \return ARES_SUCCESS on success
5661cb0ef41Sopenharmony_ci */
5671cb0ef41Sopenharmony_ciares_status_t ares__buf_parse_dns_binstr(ares__buf_t *buf, size_t remaining_len,
5681cb0ef41Sopenharmony_ci                                         unsigned char **bin, size_t *bin_len,
5691cb0ef41Sopenharmony_ci                                         ares_bool_t allow_multiple);
5701cb0ef41Sopenharmony_ci/*! @} */
5711cb0ef41Sopenharmony_ci
5721cb0ef41Sopenharmony_ci#endif /* __ARES__BUF_H */
573