26RCSIDH(sbuff_h, 
"$Id: ed6def0746f3e5441c9e0270701b483786f9b1d7 $")
 
   55#include <freeradius-devel/util/atexit.h> 
   56#include <freeradius-devel/util/strerror.h> 
   57#include <freeradius-devel/util/table.h> 
   58#include <freeradius-devel/util/talloc.h> 
   65typedef enum CC_HINT(flag_enum) {
 
 
  181#define FR_SBUFF_TERM(_str) \ 
  184        .elem = (fr_sbuff_term_elem_t[]){ L(_str) }, \ 
 
  193#define FR_SBUFF_TERMS(...) \ 
  195        .len = (sizeof((fr_sbuff_term_elem_t[]){ __VA_ARGS__ }) / sizeof(fr_sbuff_term_elem_t)), \ 
  196        .elem = (fr_sbuff_term_elem_t[]){ __VA_ARGS__ }, \ 
 
  249} fr_sbuff_parse_rules_t;
 
  277static inline bool fr_sbuff_is_extendable(
fr_sbuff_t *sbuff)
 
  279        return sbuff->extend && (!sbuff->eof || (sbuff->eof(sbuff) == 
false));
 
  282#define fr_sbuff_was_extended(_status)          (_status & FR_SBUFF_FLAG_EXTENDED) 
  298#define SBUFF_CHAR_CLASS_ALPHA \ 
  299        ['a'] = true, ['b'] = true, ['c'] = true, ['d'] = true, ['e'] = true, \ 
  300        ['f'] = true, ['g'] = true, ['h'] = true, ['i'] = true, ['j'] = true, \ 
  301        ['k'] = true, ['l'] = true, ['m'] = true, ['n'] = true, ['o'] = true, \ 
  302        ['p'] = true, ['q'] = true, ['r'] = true, ['s'] = true, ['t'] = true, \ 
  303        ['u'] = true, ['v'] = true, ['w'] = true, ['x'] = true, ['y'] = true, \ 
  305        ['A'] = true, ['B'] = true, ['C'] = true, ['D'] = true, ['E'] = true, \ 
  306        ['F'] = true, ['G'] = true, ['H'] = true, ['I'] = true, ['J'] = true, \ 
  307        ['K'] = true, ['L'] = true, ['M'] = true, ['N'] = true, ['O'] = true, \ 
  308        ['P'] = true, ['Q'] = true, ['R'] = true, ['S'] = true, ['T'] = true, \ 
  309        ['U'] = true, ['V'] = true, ['W'] = true, ['X'] = true, ['Y'] = true, \ 
  314#define SBUFF_CHAR_CLASS_NUM \ 
  315        ['0'] = true, ['1'] = true, ['2'] = true, ['3'] = true, ['4'] = true, \ 
  316        ['5'] = true, ['6'] = true, ['7'] = true, ['8'] = true, ['9'] = true 
  320#define SBUFF_CHAR_CLASS_ALPHA_NUM \ 
  321        SBUFF_CHAR_CLASS_ALPHA, \ 
  326#define SBUFF_CHAR_CLASS_HEX \ 
  327        SBUFF_CHAR_CLASS_NUM, \ 
  328        ['a'] = true, ['b'] = true, ['c'] = true, ['d'] = true, ['e'] = true, \ 
  330        ['A'] = true, ['B'] = true, ['C'] = true, ['D'] = true, ['E'] = true, \ 
  333#define SBUFF_CHAR_CLASS_SYMBOLS \ 
  334        ['!'] = true, ['"'] = true, ['#'] = true, ['$'] = true, ['%'] = true, \ 
  335        ['&'] = true, ['/'] = true, ['('] = true, [')'] = true, ['*'] = true, \ 
  336        ['+'] = true, ['`'] = true, ['-'] = true, ['.'] = true, ['/'] = true, \ 
  337        [':'] = true, [';'] = true, ['<'] = true, ['='] = true, ['>'] = true, \ 
  338        ['?'] = true, ['@'] = true, ['['] = true, ['\''] = true, [']'] = true, \ 
  339        ['^'] = true, ['_'] = true, ['`'] = true, ['{'] = true, ['|'] = true, \ 
  340        ['}'] = true, ['~'] = true \ 
  343 * If the additional tables need to be generated feel free to use this 
  350        int main(int argc, char **argv) 
  353                start = atoi(argv[1]); 
  355                for (i = start; i <= end; i++) { 
  356                        printf("[0x%02x] = true, ", i); 
  357                        if (!(i % 8)) printf("\\\n"); 
  369#define SBUFF_CHAR_UNPRINTABLES_LOW \
 
  371        [0x01] = true, [0x02] = true, [0x03] = true, [0x04] = true, [0x05] = true, [0x06] = true, [0x07] = true, [0x08] = true, \
 
  372        [0x09] = true, [0x0a] = true, [0x0b] = true, [0x0c] = true, [0x0d] = true, [0x0e] = true, [0x0f] = true, [0x10] = true, \
 
  373        [0x11] = true, [0x12] = true, [0x13] = true, [0x14] = true, [0x15] = true, [0x16] = true, [0x17] = true, [0x18] = true, \
 
  374        [0x19] = true, [0x1a] = true, [0x1b] = true, [0x1c] = true, [0x1d] = true, [0x1e] = true, [0x1f] = true, \
 
  382#define SBUFF_CHAR_UNPRINTABLES_EXTENDED \
 
  384        [0x81] = true, [0x82] = true, [0x83] = true, [0x84] = true, [0x85] = true, [0x86] = true, [0x87] = true, [0x88] = true, \
 
  385        [0x89] = true, [0x8a] = true, [0x8b] = true, [0x8c] = true, [0x8d] = true, [0x8e] = true, [0x8f] = true, [0x90] = true, \
 
  386        [0x91] = true, [0x92] = true, [0x93] = true, [0x94] = true, [0x95] = true, [0x96] = true, [0x97] = true, [0x98] = true, \
 
  387        [0x99] = true, [0x9a] = true, [0x9b] = true, [0x9c] = true, [0x9d] = true, [0x9e] = true, [0x9f] = true, [0xa0] = true, \
 
  388        [0xa1] = true, [0xa2] = true, [0xa3] = true, [0xa4] = true, [0xa5] = true, [0xa6] = true, [0xa7] = true, [0xa8] = true, \
 
  389        [0xa9] = true, [0xaa] = true, [0xab] = true, [0xac] = true, [0xad] = true, [0xae] = true, [0xaf] = true, [0xb0] = true, \
 
  390        [0xb1] = true, [0xb2] = true, [0xb3] = true, [0xb4] = true, [0xb5] = true, [0xb6] = true, [0xb7] = true, [0xb8] = true, \
 
  391        [0xb9] = true, [0xba] = true, [0xbb] = true, [0xbc] = true, [0xbd] = true, [0xbe] = true, [0xbf] = true, [0xc0] = true, \
 
  392        [0xc1] = true, [0xc2] = true, [0xc3] = true, [0xc4] = true, [0xc5] = true, [0xc6] = true, [0xc7] = true, [0xc8] = true, \
 
  393        [0xc9] = true, [0xca] = true, [0xcb] = true, [0xcc] = true, [0xcd] = true, [0xce] = true, [0xcf] = true, [0xd0] = true, \
 
  394        [0xd1] = true, [0xd2] = true, [0xd3] = true, [0xd4] = true, [0xd5] = true, [0xd6] = true, [0xd7] = true, [0xd8] = true, \
 
  395        [0xd9] = true, [0xda] = true, [0xdb] = true, [0xdc] = true, [0xdd] = true, [0xde] = true, [0xdf] = true, [0xe0] = true, \
 
  396        [0xe1] = true, [0xe2] = true, [0xe3] = true, [0xe4] = true, [0xe5] = true, [0xe6] = true, [0xe7] = true, [0xe8] = true, \
 
  397        [0xe9] = true, [0xea] = true, [0xeb] = true, [0xec] = true, [0xed] = true, [0xee] = true, [0xef] = true, [0xf0] = true, \
 
  398        [0xf1] = true, [0xf2] = true, [0xf3] = true, [0xf4] = true, [0xf5] = true, [0xf6] = true, [0xf7] = true, [0xf8] = true, \
 
  399        [0xf9] = true, [0xfa] = true, [0xfb] = true, [0xfc] = true, [0xfd] = true, [0xfe] = true, [0xff] = true
 
  404#define FR_SBUFF_RETURN(_func, _sbuff, ...) \
 
  407        _slen = _func(_sbuff, ## __VA_ARGS__ ); \
 
  408        if (_slen < 0) return _slen; \
 
  421#define _FR_SBUFF(_sbuff_or_marker, _start, _current, _end, _extend, _eof, _adv_parent) \
 
  423        .buff           = fr_sbuff_buff(_sbuff_or_marker), \
 
  427        .is_const       = fr_sbuff_ptr(_sbuff_or_marker)->is_const, \
 
  428        .adv_parent     = (_adv_parent), \
 
  430        .extend         = (_extend), \
 
  432        .uctx           = fr_sbuff_ptr(_sbuff_or_marker)->uctx, \
 
  433        .parent         = fr_sbuff_ptr(_sbuff_or_marker) \
 
  444#define FR_SBUFF(_sbuff_or_marker) _FR_SBUFF(_sbuff_or_marker, \
 
  445                                             fr_sbuff_current(_sbuff_or_marker), \
 
  446                                             fr_sbuff_current(_sbuff_or_marker), \
 
  447                                             fr_sbuff_end(_sbuff_or_marker), \
 
  448                                             fr_sbuff_ptr(_sbuff_or_marker)->extend, \
 
  449                                             fr_sbuff_ptr(_sbuff_or_marker)->eof, \
 
  459#define FR_SBUFF_ABS(_sbuff_or_marker) _FR_SBUFF(_sbuff_or_marker, \
 
  460                                                 fr_sbuff_start(_sbuff_or_marker), \
 
  461                                                 fr_sbuff_current(_sbuff_or_marker), \
 
  462                                                 fr_sbuff_end(_sbuff_or_marker), \
 
  463                                                 fr_sbuff_ptr(_sbuff_or_marker)->extend, \
 
  478#define FR_SBUFF_REPARSE(_sbuff_or_marker) _FR_SBUFF(_sbuff_or_marker, \
 
  479                                                     fr_sbuff_start(_sbuff_or_marker), \
 
  480                                                     fr_sbuff_start(_sbuff_or_marker), \
 
  481                                                     fr_sbuff_current(_sbuff_or_marker), \
 
  493#define FR_SBUFF_BIND_CURRENT(_sbuff_or_marker) _FR_SBUFF(_sbuff_or_marker, \
 
  494                                                          fr_sbuff_current(_sbuff_or_marker), \
 
  495                                                          fr_sbuff_current(_sbuff_or_marker), \
 
  496                                                          fr_sbuff_end(_sbuff_or_marker), \
 
  497                                                          fr_sbuff_ptr(_sbuff_or_marker)->extend, \
 
  498                                                          fr_sbuff_ptr(_sbuff_or_marker)->eof, \
 
  508#define FR_SBUFF_BIND_CURRENT_ABS(_sbuff_or_marker) FR_SBUFF_ABS(_sbuff_or_marker, \
 
  509                                                                 fr_sbuff_start(_sbuff_or_marker), \
 
  510                                                                 fr_sbuff_current(_sbuff_or_marker), \
 
  511                                                                 fr_sbuff_end(_sbuff_or_marker), \
 
  512                                                                 fr_sbuff_ptr(_sbuff_or_marker)->extend, \
 
  513                                                                 fr_sbuff_ptr(_sbuff_or_marker)->eof, \
 
  524#define FR_SBUFF_OUT(_start, _len_or_end) \
 
  527        .start_i        = _Generic((_start), \
 
  531        .end_i          = _Generic((_len_or_end), \
 
  532                                size_t          : (char const *)(_start) + ((size_t)(_len_or_end) - 1), \
 
  533                                long            : (char const *)(_start) + ((size_t)(_len_or_end) - 1), \
 
  534                                int             : (char const *)(_start) + ((size_t)(_len_or_end) - 1), \
 
  535                                unsigned int    : (char const *)(_start) + ((size_t)(_len_or_end) - 1), \
 
  536                                char *          : (char const *)(_len_or_end), \
 
  537                                char const *    : (char const *)(_len_or_end) \
 
  551#define FR_SBUFF_IN(_start, _len_or_end) \
 
  554        .start_i        = _Generic((_start), \
 
  556                                char const *    : _start, \
 
  557                                uint8_t *       : _start, \
 
  558                                uint8_t const * : _start \
 
  560        .end_i          = _Generic((_len_or_end), \
 
  561                                size_t          : (char const *)(_start) + (size_t)(_len_or_end), \
 
  562                                long            : (char const *)(_start) + (size_t)(_len_or_end), \
 
  563                                int             : (char const *)(_start) + (size_t)(_len_or_end), \
 
  564                                unsigned int    : (char const *)(_start) + (size_t)(_len_or_end), \
 
  565                                char *          : (char const *)(_len_or_end), \
 
  566                                char const *    : (char const *)(_len_or_end) \
 
  572#define FR_SBUFF_IN_STR(_start) FR_SBUFF_IN(_start, strlen(_start))
 
  578        fr_sbuff_t                      sbuff;          //!< Thread local sbuff.
 
  579        fr_sbuff_uctx_talloc_t          tctx;           //!< Thread local tctx.
 
  580} fr_sbuff_thread_local_t;
 
  582static inline int _sbuff_thread_local_free(void *sbtl)
 
  584        return talloc_free(sbtl);
 
  593#define FR_SBUFF_TALLOC_THREAD_LOCAL(_out, _init, _max) \
 
  595        static _Thread_local fr_sbuff_thread_local_t *_sbuff_t_local; \
 
  596        if (!_sbuff_t_local) { \
 
  597                fr_sbuff_thread_local_t *sbtl = talloc_zero(NULL, fr_sbuff_thread_local_t); \
 
  598                fr_sbuff_init_talloc(sbtl, &sbtl->sbuff, &sbtl->tctx, _init, _max); \
 
  599                fr_atexit_thread_local(_sbuff_t_local, _sbuff_thread_local_free, sbtl); \
 
  600                *(_out) = &_sbuff_t_local->sbuff; \
 
  602                fr_sbuff_reset_talloc(&_sbuff_t_local->sbuff); \
 
  603                *(_out) = &_sbuff_t_local->sbuff; \
 
  607void    fr_sbuff_update(fr_sbuff_t *sbuff, char *new_buff, size_t new_len);
 
  609size_t  fr_sbuff_shift(fr_sbuff_t *sbuff, size_t shift, bool move_end);
 
  611size_t  fr_sbuff_extend_file(fr_sbuff_extend_status_t *status, fr_sbuff_t *sbuff, size_t extension);
 
  613bool    fr_sbuff_eof_file(fr_sbuff_t *sbuff);
 
  615size_t  fr_sbuff_extend_talloc(fr_sbuff_extend_status_t *status, fr_sbuff_t *sbuff, size_t extension);
 
  617int     fr_sbuff_trim_talloc(fr_sbuff_t *sbuff, size_t len);
 
  619int     fr_sbuff_reset_talloc(fr_sbuff_t *sbuff);
 
  621static inline void fr_sbuff_terminate(fr_sbuff_t *sbuff)
 
  626static inline void _fr_sbuff_init(fr_sbuff_t *out, char const *start, char const *end, bool is_const)
 
  628        if (unlikely(end < start)) end = start; /* Could be an assert? */
 
  640 *      GCC is stupid and will warn about output variables
 
  641 *      being unnitialised, even if they're not dereferenced.
 
  643#if defined(__GNUC__) && __GNUC__ >= 11
 
  644DIAG_OFF(maybe-uninitialized)
 
  656#define fr_sbuff_init_out(_out, _start, _len_or_end) \
 
  659  _fr_sbuff_init(_out, _start, \
 
  660  _Generic((_len_or_end), \
 
  661        size_t          : (char const *)(_start) + ((size_t)(_len_or_end) - 1), \
 
  662        long            : (char const *)(_start) + ((size_t)(_len_or_end) - 1), \
 
  663        int             : (char const *)(_start) + ((size_t)(_len_or_end) - 1), \
 
  664        char *          : (char const *)(_len_or_end), \
 
  665        char const *    : (char const *)(_len_or_end) \
 
  670#if defined(__GNUC__) && __GNUC__ >= 11
 
  671DIAG_ON(maybe-uninitialized)
 
  681#define fr_sbuff_init_in(_out, _start, _len_or_end) \
 
  682_fr_sbuff_init(_out, _start, \
 
  683_Generic((_len_or_end), \
 
  684        size_t          : (char const *)(_start) + (size_t)(_len_or_end), \
 
  685        long            : (char const *)(_start) + (size_t)(_len_or_end), \
 
  686        int             : (char const *)(_start) + (size_t)(_len_or_end), \
 
  687        char *          : (char const *)(_len_or_end), \
 
  688        char const *    : (char const *)(_len_or_end) \
 
  690IS_CONST(char *, _start))
 
  704static inline fr_sbuff_t *fr_sbuff_init_file(fr_sbuff_t *sbuff, fr_sbuff_uctx_file_t *fctx,
 
  705                                             char *buff, size_t len, FILE *file, size_t max)
 
  707        *fctx = (fr_sbuff_uctx_file_t){
 
  710                .buff_end = buff + len          //!< Store the real end
 
  713        *sbuff = (fr_sbuff_t){
 
  717                .end = buff,                    //!< Starts with 0 bytes available
 
  718                .extend = fr_sbuff_extend_file,
 
  719                .eof = fr_sbuff_eof_file,
 
  737static inline fr_sbuff_t *fr_sbuff_init_talloc(TALLOC_CTX *ctx,
 
  738                                               fr_sbuff_t *sbuff, fr_sbuff_uctx_talloc_t *tctx,
 
  739                                               size_t init, size_t max)
 
  743        *tctx = (fr_sbuff_uctx_talloc_t){
 
  750         *      Allocate the initial buffer
 
  752         *      We always allocate a buffer so we don't
 
  753         *      trigger ubsan errors by performing
 
  754         *      arithmetic on NULL pointers.
 
  756        buff = talloc_zero_array(ctx, char, init + 1);
 
  758                fr_strerror_printf("Failed allocating buffer of %zu bytes", init + 1);
 
  759                memset(sbuff, 0, sizeof(*sbuff));       /* clang scan */
 
  763        *sbuff = (fr_sbuff_t){
 
  768                .extend = fr_sbuff_extend_talloc,
 
  793#define fr_sbuff_ptr(_sbuff_or_marker) \
 
  794        _Generic((_sbuff_or_marker), \
 
  795                 fr_sbuff_t *                   : ((fr_sbuff_t *)(_sbuff_or_marker)), \
 
  796                 fr_sbuff_marker_t *            : ((fr_sbuff_marker_t *)(_sbuff_or_marker))->parent \
 
  804#define fr_sbuff_buff(_sbuff_or_marker) \
 
  805        _Generic((_sbuff_or_marker), \
 
  806                 fr_sbuff_t *                   : ((fr_sbuff_t const *)(_sbuff_or_marker))->buff, \
 
  807                 fr_sbuff_t const *             : ((fr_sbuff_t const *)(_sbuff_or_marker))->buff, \
 
  808                 fr_sbuff_marker_t *            : ((fr_sbuff_marker_t const *)(_sbuff_or_marker))->parent->buff, \
 
  809                 fr_sbuff_marker_t const *      : ((fr_sbuff_marker_t const *)(_sbuff_or_marker))->parent->buff \
 
  820#define fr_sbuff_start(_sbuff_or_marker) \
 
  821        (_Generic((_sbuff_or_marker), \
 
  822                  fr_sbuff_t *                  : ((fr_sbuff_t const *)(_sbuff_or_marker))->start, \
 
  823                  fr_sbuff_t const *            : ((fr_sbuff_t const *)(_sbuff_or_marker))->start, \
 
  824                  fr_sbuff_marker_t *           : ((fr_sbuff_marker_t const *)(_sbuff_or_marker))->parent->start, \
 
  825                  fr_sbuff_marker_t const *     : ((fr_sbuff_marker_t const *)(_sbuff_or_marker))->parent->start \
 
  836#define fr_sbuff_current(_sbuff_or_marker) \
 
  837        (_Generic((_sbuff_or_marker), \
 
  838                  fr_sbuff_t *                  : ((fr_sbuff_t const *)(_sbuff_or_marker))->p, \
 
  839                  fr_sbuff_t const *            : ((fr_sbuff_t const *)(_sbuff_or_marker))->p, \
 
  840                  fr_sbuff_marker_t *           : ((fr_sbuff_marker_t const *)(_sbuff_or_marker))->p, \
 
  841                  fr_sbuff_marker_t const *     : ((fr_sbuff_marker_t const *)(_sbuff_or_marker))->p \
 
  849#define fr_sbuff_end(_sbuff_or_marker) \
 
  850        (_Generic((_sbuff_or_marker), \
 
  851                  fr_sbuff_t *                  : ((fr_sbuff_t const *)(_sbuff_or_marker))->end, \
 
  852                  fr_sbuff_t const *            : ((fr_sbuff_t const *)(_sbuff_or_marker))->end, \
 
  853                  fr_sbuff_marker_t *           : ((fr_sbuff_marker_t const *)(_sbuff_or_marker))->parent->end, \
 
  854                  fr_sbuff_marker_t const *     : ((fr_sbuff_marker_t const *)(_sbuff_or_marker))->parent->end \
 
  862#define fr_sbuff_shifted(_sbuff_or_marker) \
 
  863        (_Generic((_sbuff_or_marker), \
 
  864                  fr_sbuff_t *                  : ((fr_sbuff_t const *)(_sbuff_or_marker))->shifted, \
 
  865                  fr_sbuff_t const *            : ((fr_sbuff_t const *)(_sbuff_or_marker))->shifted, \
 
  866                  fr_sbuff_marker_t *           : ((fr_sbuff_marker_t const *)(_sbuff_or_marker))->parent->shifted, \
 
  867                  fr_sbuff_marker_t const *     : ((fr_sbuff_marker_t const *)(_sbuff_or_marker))->parent->shifted \
 
  878#define fr_sbuff_char(_sbuff_or_marker, _eob) \
 
  879        (fr_sbuff_current(_sbuff_or_marker) >= fr_sbuff_end(_sbuff_or_marker) ? _eob : *fr_sbuff_current(_sbuff_or_marker))
 
  888#define fr_sbuff_switch(_sbuff_or_marker, _eob) \
 
  889        switch (fr_sbuff_char(_sbuff_or_marker, _eob))
 
  905#define fr_sbuff_diff(_a, _b) \
 
  906        ((ssize_t)(fr_sbuff_current(_a) - fr_sbuff_current(_b)))
 
  921#define fr_sbuff_remaining(_sbuff_or_marker) \
 
  922        ((size_t)(fr_sbuff_end(_sbuff_or_marker) < fr_sbuff_current(_sbuff_or_marker) ? \
 
  923                0 : (fr_sbuff_end(_sbuff_or_marker) - fr_sbuff_current(_sbuff_or_marker))))
 
  932#define fr_sbuff_used(_sbuff_or_marker) \
 
  933        ((size_t)(fr_sbuff_start(_sbuff_or_marker) > fr_sbuff_current(_sbuff_or_marker) ? \
 
  934                0 : (fr_sbuff_current(_sbuff_or_marker) - fr_sbuff_start(_sbuff_or_marker))))
 
  944static inline fr_slen_t _fr_sbuff_error(fr_sbuff_t *sbuff, char const *err)
 
  946        fr_sbuff_t      *parent = sbuff->parent;
 
  949        if (sbuff->err) err = sbuff->err;
 
  950        if (parent) parent->err = err;
 
  952        slen = -((err - fr_sbuff_start(sbuff)) + 1);
 
  954#ifdef __clang_analyzer__
 
  956         *      Convince clang that the return value
 
  957         *      is always negative. It never can be
 
  958         *      else the sbuff code is very broken.
 
  960        if (slen >= 0) return -1;
 
  974#define fr_sbuff_error(_sbuff_or_marker) \
 
  975        _fr_sbuff_error(fr_sbuff_ptr(_sbuff_or_marker), fr_sbuff_current(_sbuff_or_marker))
 
  985#define fr_sbuff_used_total(_sbuff_or_marker) \
 
  986        ((size_t)((fr_sbuff_current(_sbuff_or_marker) + fr_sbuff_shifted(_sbuff_or_marker)) - fr_sbuff_start(_sbuff_or_marker)))
 
  993#define fr_sbuff_len(_sbuff_or_marker) \
 
  994        ((size_t)(fr_sbuff_end(_sbuff_or_marker) - fr_sbuff_buff(_sbuff_or_marker)))
 
 1003#define fr_sbuff_behind(_sbuff_or_marker) \
 
 1004        (fr_sbuff_current(_sbuff_or_marker) > fr_sbuff_current((_sbuff_or_marker)->parent) ? \
 
 1005                0 : fr_sbuff_current((_sbuff_or_marker)->parent) - fr_sbuff_current(_sbuff_or_marker))
 
 1013#define fr_sbuff_ahead(_sbuff_or_marker) \
 
 1014        (fr_sbuff_current((_sbuff_or_marker)->parent) > fr_sbuff_current(_sbuff_or_marker) ? \
 
 1015                0 : fr_sbuff_current(_sbuff_or_marker) - fr_sbuff_current((_sbuff_or_marker)->parent))
 
 1020#define FR_SBUFF_ERROR_RETURN(_sbuff_or_marker) return fr_sbuff_error(_sbuff_or_marker)
 
 1025#define FR_SBUFF_CHECK_REMAINING_RETURN(_sbuff, _len) \
 
 1026        if ((_len) > fr_sbuff_remaining(_sbuff)) return -((_len) - fr_sbuff_remaining(_sbuff))
 
 1028static inline size_t _fr_sbuff_extend_lowat(fr_sbuff_extend_status_t *status, fr_sbuff_t *in, size_t remaining, size_t lowat)
 
 1031        fr_sbuff_extend_status_t our_status = 0;
 
 1033        if (!fr_sbuff_is_extendable(in)) {
 
 1035                if (status) *status = our_status;
 
 1039        /* Still have data remaining, no need to try and extend */
 
 1040        if (remaining >= lowat) goto no_extend;
 
 1042        if (!in->extend || ((extended = in->extend(&our_status, in, lowat - remaining)) == 0)) {
 
 1046        our_status |= FR_SBUFF_FLAG_EXTENDED;
 
 1048        if (status) *status = our_status;
 
 1049        return remaining + extended;
 
 1066#define fr_sbuff_extend_lowat(_status, _sbuff_or_marker, _lowat) \
 
 1067        _fr_sbuff_extend_lowat(_status, \
 
 1068                               fr_sbuff_ptr(_sbuff_or_marker), \
 
 1069                               fr_sbuff_remaining(_sbuff_or_marker), _lowat)
 
 1079#define FR_SBUFF_EXTEND_LOWAT_OR_RETURN(_sbuff, _len) \
 
 1081        size_t _remaining = fr_sbuff_extend_lowat(NULL, _sbuff, _len); \
 
 1082        if (_remaining < _len) return -(_len - _remaining); \
 
 1092#define fr_sbuff_extend(_sbuff_or_marker) fr_sbuff_extend_lowat(NULL, _sbuff_or_marker, 1)
 
 1106static inline void _fr_sbuff_set_recurse(fr_sbuff_t *sbuff, char const *p)
 
 1109        sbuff->err = NULL;      /* Modifying the position of the sbuff clears the error */
 
 1111        if (sbuff->adv_parent && sbuff->parent) _fr_sbuff_set_recurse(sbuff->parent, p);
 
 1114static inline ssize_t _fr_sbuff_marker_set(fr_sbuff_marker_t *m, char const *p)
 
 1116        fr_sbuff_t      *sbuff = m->parent;
 
 1117        char            *current = m->p;
 
 1119        if (unlikely(p > sbuff->end)) return -(p - sbuff->end);
 
 1120        if (unlikely(p < sbuff->start)) return 0;
 
 1122        sbuff->err = NULL;      /* Modifying the position of any markers clears the error, unsure if this is correct? */
 
 1128static inline ssize_t _fr_sbuff_set(fr_sbuff_t *sbuff, char const *p)
 
 1132        if (unlikely(p > sbuff->end)) return -(p - sbuff->end);
 
 1133        if (unlikely(p < sbuff->start)) return 0;
 
 1136        _fr_sbuff_set_recurse(sbuff, p);
 
 1155#define fr_sbuff_set(_dst, _src) \
 
 1157         fr_sbuff_t *                   : _fr_sbuff_set, \
 
 1158         fr_sbuff_marker_t *            : _fr_sbuff_marker_set \
 
 1161        fr_sbuff_t *                    : fr_sbuff_current((fr_sbuff_t const *)(_src)), \
 
 1162        fr_sbuff_t const *              : fr_sbuff_current((fr_sbuff_t const *)(_src)), \
 
 1163        fr_sbuff_marker_t *             : fr_sbuff_current((fr_sbuff_marker_t const *)(_src)), \
 
 1164        fr_sbuff_marker_t const *       : fr_sbuff_current((fr_sbuff_marker_t const *)(_src)), \
 
 1165        char const *                    : (char const *)(_src), \
 
 1166        char *                          : (char const *)(_src), \
 
 1167        size_t                          : (fr_sbuff_start(_dst) + (uintptr_t)(_src)) \
 
 1176#define FR_SBUFF_SET_RETURN(_dst, _src) return fr_sbuff_set(_dst, _src)
 
 1187#define fr_sbuff_advance(_sbuff_or_marker, _len)  fr_sbuff_set(_sbuff_or_marker, (fr_sbuff_current(_sbuff_or_marker) + (_len)))
 
 1188#define FR_SBUFF_ADVANCE_RETURN(_sbuff, _len) FR_SBUFF_RETURN(fr_sbuff_advance, _sbuff, _len)
 
 1193static inline void fr_sbuff_set_to_start(fr_sbuff_t *sbuff)
 
 1195        _fr_sbuff_set_recurse(sbuff, sbuff->start);
 
 1201static inline void fr_sbuff_set_to_end(fr_sbuff_t *sbuff)
 
 1203        _fr_sbuff_set_recurse(sbuff, sbuff->end);
 
 1227static inline char *fr_sbuff_marker(fr_sbuff_marker_t *m, fr_sbuff_t *sbuff)
 
 1229        *m = (fr_sbuff_marker_t){
 
 1230                .next = sbuff->m,       /* Link into the head */
 
 1231                .p = sbuff->p,          /* Set the current position in the sbuff */
 
 1232                .parent = sbuff         /* Record which sbuff this marker was associated with */
 
 1257static inline char *fr_sbuff_marker_update_end(fr_sbuff_marker_t *m, size_t max)
 
 1259        fr_sbuff_t      *sbuff = m->parent;
 
 1260        size_t          used = fr_sbuff_used_total(sbuff);
 
 1262        m->p = (((max) - (used)) > fr_sbuff_remaining(sbuff) ?
 
 1263               fr_sbuff_end(sbuff) :
 
 1264               fr_sbuff_current(sbuff) + ((max) - (used)));
 
 1278static inline void fr_sbuff_marker_release(fr_sbuff_marker_t *m)
 
 1280        m->parent->m = m->next;
 
 1283        memset(m, 0, sizeof(*m));       /* Use after release */
 
 1299static inline size_t fr_sbuff_marker_release_behind(fr_sbuff_marker_t *m)
 
 1301        size_t len = fr_sbuff_behind(m);
 
 1302        fr_sbuff_marker_release(m);
 
 1318static inline size_t fr_sbuff_marker_release_ahead(fr_sbuff_marker_t *m)
 
 1320        size_t len = fr_sbuff_ahead(m);
 
 1321        fr_sbuff_marker_release(m);
 
 1337static inline size_t fr_sbuff_marker_release_reset_behind(fr_sbuff_marker_t *m)
 
 1339        size_t len = fr_sbuff_behind(m);
 
 1340        fr_sbuff_set(m->parent, m);
 
 1341        fr_sbuff_marker_release(m);
 
 1357static inline size_t fr_sbuff_marker_release_reset_ahead(fr_sbuff_marker_t *m)
 
 1359        size_t len = fr_sbuff_ahead(m);
 
 1360        fr_sbuff_set(m->parent, m);
 
 1361        fr_sbuff_marker_release(m);
 
 1372size_t _fr_sbuff_move_sbuff_to_sbuff(fr_sbuff_t *out, fr_sbuff_t *in, size_t len);
 
 1374size_t _fr_sbuff_move_marker_to_sbuff(fr_sbuff_t *out, fr_sbuff_marker_t *in, size_t len);
 
 1376size_t _fr_sbuff_move_marker_to_marker(fr_sbuff_marker_t *out, fr_sbuff_marker_t *in, size_t len);
 
 1378size_t _fr_sbuff_move_sbuff_to_marker(fr_sbuff_marker_t *out, fr_sbuff_t *in, size_t len);
 
 1387#define fr_sbuff_move(_out, _in, _len) \
 
 1391                                fr_sbuff_t *            : _fr_sbuff_move_sbuff_to_sbuff((fr_sbuff_t *)_out, (fr_sbuff_t *)_in, _len), \
 
 1392                                fr_sbuff_marker_t *     : _fr_sbuff_move_marker_to_sbuff((fr_sbuff_t *)_out, (fr_sbuff_marker_t *)_in, _len) \
 
 1394               fr_sbuff_marker_t *      : \
 
 1396                                fr_sbuff_t *            : _fr_sbuff_move_sbuff_to_marker((fr_sbuff_marker_t *)_out, (fr_sbuff_t *)_in, _len), \
 
 1397                                fr_sbuff_marker_t *     : _fr_sbuff_move_marker_to_marker((fr_sbuff_marker_t *)_out, (fr_sbuff_marker_t *)_in, _len) \
 
 1408#define fr_sbuff_in_char(_sbuff, ...) fr_sbuff_in_bstrncpy(_sbuff, ((char []){ __VA_ARGS__ }), sizeof((char []){ __VA_ARGS__ }))
 
 1409#define FR_SBUFF_IN_CHAR_RETURN(_sbuff, ...) FR_SBUFF_RETURN(fr_sbuff_in_bstrncpy, _sbuff, ((char []){ __VA_ARGS__ }), sizeof((char []){ __VA_ARGS__ }))
 
 1411ssize_t fr_sbuff_in_strcpy(fr_sbuff_t *sbuff, char const *str);
 
 1412#define FR_SBUFF_IN_STRCPY_RETURN(...) FR_SBUFF_RETURN(fr_sbuff_in_strcpy, ##__VA_ARGS__)
 
 1414ssize_t fr_sbuff_in_bstrncpy(fr_sbuff_t *sbuff, char const *str, size_t len);
 
 1415#define FR_SBUFF_IN_BSTRNCPY_RETURN(...) FR_SBUFF_RETURN(fr_sbuff_in_bstrncpy, ##__VA_ARGS__)
 
 1417#define fr_sbuff_in_strcpy_literal(_sbuff, _str) fr_sbuff_in_bstrncpy(_sbuff, _str, sizeof(_str) - 1)
 
 1418#define FR_SBUFF_IN_STRCPY_LITERAL_RETURN(_sbuff, _str) FR_SBUFF_RETURN(fr_sbuff_in_bstrncpy, _sbuff, _str, sizeof(_str) - 1)
 
 1420ssize_t fr_sbuff_in_bstrcpy_buffer(fr_sbuff_t *sbuff, char const *str);
 
 1421#define FR_SBUFF_IN_BSTRCPY_BUFFER_RETURN(...) FR_SBUFF_RETURN(fr_sbuff_in_bstrcpy_buffer, ##__VA_ARGS__)
 
 1423ssize_t fr_sbuff_in_vsprintf(fr_sbuff_t *sbuff, char const *fmt, va_list ap);
 
 1424#define FR_SBUFF_IN_VSPRINTF_RETURN(...) FR_SBUFF_RETURN(fr_sbuff_in_vsprintf, ##__VA_ARGS__)
 
 1426ssize_t fr_sbuff_in_sprintf(fr_sbuff_t *sbuff, char const *fmt, ...);
 
 1427#define FR_SBUFF_IN_SPRINTF_RETURN(...) FR_SBUFF_RETURN(fr_sbuff_in_sprintf, ##__VA_ARGS__)
 
 1429ssize_t fr_sbuff_in_escape(fr_sbuff_t *sbuff, char const *in, size_t inlen, fr_sbuff_escape_rules_t const *e_rules);
 
 1430#define FR_SBUFF_IN_ESCAPE_RETURN(...) FR_SBUFF_RETURN(fr_sbuff_in_escape, ##__VA_ARGS__)
 
 1432ssize_t fr_sbuff_in_escape_buffer(fr_sbuff_t *sbuff, char const *in, fr_sbuff_escape_rules_t const *e_rules);
 
 1433#define FR_SBUFF_IN_ESCAPE_BUFFER_RETURN(...)   FR_SBUFF_RETURN(fr_sbuff_in_escape_buffer, ##__VA_ARGS__)
 
 1435ssize_t fr_sbuff_in_array(fr_sbuff_t *sbuff, char const * const *array, char const *sep);
 
 1436#define FR_SBUFF_IN_ARRAY(...) FR_SBUFF_RETURN(fr_sbuff_in_array, ##__VA_ARGS__)
 
 1446#define         fr_sbuff_in_table_str(_slen, _sbuff, _table, _number, _def) \
 
 1447                                      _slen = fr_sbuff_in_strcpy(_sbuff, fr_table_str_by_value(_table, _number, _def))
 
 1448#define         FR_SBUFF_IN_TABLE_STR_RETURN(_sbuff, _table, _number, _def) \
 
 1451        fr_sbuff_in_table_str(_slen, _sbuff, _table, _number, _def); \
 
 1452        if (_slen < 0) return _slen; \
 
 1466static inline void fr_sbuff_allowed_merge(bool out[static UINT8_MAX + 1], bool const in[static UINT8_MAX + 1])
 
 1468        for (size_t i = 0; i <= UINT8_MAX; i++) out[i] = out[i] || in[i];
 
 1471fr_sbuff_term_t *fr_sbuff_terminals_amerge(TALLOC_CTX *ctx,
 
 1472                                           fr_sbuff_term_t const *a, fr_sbuff_term_t const *b);
 
 1474size_t  fr_sbuff_out_bstrncpy(fr_sbuff_t *out, fr_sbuff_t *in, size_t len);
 
 1476ssize_t fr_sbuff_out_bstrncpy_exact(fr_sbuff_t *out, fr_sbuff_t *in, size_t len);
 
 1478size_t  fr_sbuff_out_bstrncpy_allowed(fr_sbuff_t *out, fr_sbuff_t *in, size_t len,
 
 1479                                      bool const allowed[static UINT8_MAX + 1]);
 
 1481size_t  fr_sbuff_out_bstrncpy_until(fr_sbuff_t *out, fr_sbuff_t *in, size_t len,
 
 1482                                    fr_sbuff_term_t const *tt,
 
 1483                                    fr_sbuff_unescape_rules_t const *u_rules);
 
 1485size_t  fr_sbuff_out_unescape_until(fr_sbuff_t *out, fr_sbuff_t *in, size_t len,
 
 1486                                    fr_sbuff_term_t const *tt,
 
 1487                                    fr_sbuff_unescape_rules_t const *u_rules);
 
 1498#define fr_sbuff_out_by_longest_prefix(_match_len, _out, _table, _sbuff, _def) \
 
 1500        size_t          _match_len_tmp; \
 
 1501        fr_sbuff_extend_lowat(NULL, _sbuff, fr_table_max_needle_len(_table)); \
 
 1502        *(_out) = fr_table_value_by_longest_prefix(&_match_len_tmp, _table, \
 
 1503                                                   fr_sbuff_current(_sbuff), fr_sbuff_remaining(_sbuff), \
 
 1505        (void) fr_sbuff_advance(_sbuff, _match_len_tmp); /* can't fail */ \
 
 1506        *(_match_len) = _match_len_tmp; \
 
 1516#define SBUFF_OUT_TALLOC_ERR_FUNC_DEF(_func, _in, _len, ...) \
 
 1519        fr_sbuff_uctx_talloc_t  tctx; \
 
 1520        fr_sbuff_parse_error_t  err; \
 
 1521        fr_slen_t               slen = -1; \
 
 1522        if (unlikely(fr_sbuff_init_talloc(ctx, &sbuff, &tctx, \
 
 1523                                          ((_len) != SIZE_MAX) ? (_len) : 1024, \
 
 1524                                          ((_len) != SIZE_MAX) ? (_len) : SIZE_MAX) == NULL)) { \
 
 1526                TALLOC_FREE(sbuff.buff); \
 
 1530        slen = _func(&err, &sbuff, _in, _len, ##__VA_ARGS__); \
 
 1531        if (slen < 0) goto error; \
 
 1532        if (unlikely(fr_sbuff_trim_talloc(&sbuff, SIZE_MAX) < 0)) { \
 
 1536        *out = sbuff.buff; \
 
 1547#define SBUFF_OUT_TALLOC_FUNC_DEF(_func, _in, _len, ...) \
 
 1550        fr_sbuff_uctx_talloc_t  tctx; \
 
 1551        fr_slen_t               slen = -1; \
 
 1552        if (unlikely(fr_sbuff_init_talloc(ctx, &sbuff, &tctx, \
 
 1553                                          ((_len) != SIZE_MAX) ? (_len) : 1024, \
 
 1554                                          ((_len) != SIZE_MAX) ? (_len) : SIZE_MAX) == NULL)) { \
 
 1556                TALLOC_FREE(sbuff.buff); \
 
 1560        slen = _func(&sbuff, _in, _len, ##__VA_ARGS__); \
 
 1561        if (slen < 0) goto error; \
 
 1562        if (unlikely(fr_sbuff_trim_talloc(&sbuff, SIZE_MAX) < 0)) { \
 
 1566        *out = sbuff.buff; \
 
 1575#define SBUFF_OUT_TALLOC_FUNC_NO_LEN_DEF(_func, ...) \
 
 1578        fr_sbuff_uctx_talloc_t  tctx; \
 
 1579        fr_slen_t               slen = -1; \
 
 1580        if (unlikely(fr_sbuff_init_talloc(ctx, &sbuff, &tctx, 0, SIZE_MAX) == NULL)) { \
 
 1582                TALLOC_FREE(sbuff.buff); \
 
 1586        slen = _func(&sbuff, ##__VA_ARGS__); \
 
 1587        if (slen < 0) goto error; \
 
 1588        if (unlikely(fr_sbuff_trim_talloc(&sbuff, SIZE_MAX) < 0)) { \
 
 1592        *out = sbuff.buff; \
 
 1596static inline fr_slen_t fr_sbuff_out_abstrncpy(TALLOC_CTX *ctx, char **out, fr_sbuff_t *in, size_t len)
 
 1597SBUFF_OUT_TALLOC_FUNC_DEF(fr_sbuff_out_bstrncpy, in, len)
 
 1599static inline fr_slen_t fr_sbuff_out_abstrncpy_exact(TALLOC_CTX *ctx, char **out, fr_sbuff_t *in, size_t len)
 
 1600SBUFF_OUT_TALLOC_FUNC_DEF(fr_sbuff_out_bstrncpy_exact, in, len)
 
 1602static inline fr_slen_t fr_sbuff_out_abstrncpy_allowed(TALLOC_CTX *ctx, char **out, fr_sbuff_t *in, size_t len,
 
 1603                                                       bool const allowed[static UINT8_MAX + 1])
 
 1604SBUFF_OUT_TALLOC_FUNC_DEF(fr_sbuff_out_bstrncpy_allowed, in, len, allowed)
 
 1606static inline fr_slen_t fr_sbuff_out_abstrncpy_until(TALLOC_CTX *ctx, char **out, fr_sbuff_t *in, size_t len,
 
 1607                                                     fr_sbuff_term_t const *tt,
 
 1608                                                     fr_sbuff_unescape_rules_t const *u_rules)
 
 1609SBUFF_OUT_TALLOC_FUNC_DEF(fr_sbuff_out_bstrncpy_until, in, len, tt, u_rules)
 
 1611static inline fr_slen_t fr_sbuff_out_aunescape_until(TALLOC_CTX *ctx, char **out, fr_sbuff_t *in, size_t len,
 
 1612                                                     fr_sbuff_term_t const *tt,
 
 1613                                                     fr_sbuff_unescape_rules_t const *u_rules)
 
 1614SBUFF_OUT_TALLOC_FUNC_DEF(fr_sbuff_out_unescape_until, in, len, tt, u_rules)
 
 1623fr_slen_t fr_sbuff_out_bool(bool *out, fr_sbuff_t *in);
 
 1625fr_slen_t fr_sbuff_out_int8(fr_sbuff_parse_error_t *err, int8_t *out, fr_sbuff_t *sbuff, bool no_trailing);
 
 1626fr_slen_t fr_sbuff_out_int16(fr_sbuff_parse_error_t *err, int16_t *out, fr_sbuff_t *sbuff, bool no_trailing);
 
 1627fr_slen_t fr_sbuff_out_int32(fr_sbuff_parse_error_t *err, int32_t *out, fr_sbuff_t *sbuff, bool no_trailing);
 
 1628fr_slen_t fr_sbuff_out_int64(fr_sbuff_parse_error_t *err, int64_t *out, fr_sbuff_t *sbuff, bool no_trailing);
 
 1629fr_slen_t fr_sbuff_out_ssize(fr_sbuff_parse_error_t *err, ssize_t *out, fr_sbuff_t *sbuff, bool no_trailing);
 
 1630fr_slen_t fr_sbuff_out_uint8(fr_sbuff_parse_error_t *err, uint8_t *out, fr_sbuff_t *sbuff, bool no_trailing);
 
 1631fr_slen_t fr_sbuff_out_uint16(fr_sbuff_parse_error_t *err, uint16_t *out, fr_sbuff_t *sbuff, bool no_trailing);
 
 1632fr_slen_t fr_sbuff_out_uint32(fr_sbuff_parse_error_t *err, uint32_t *out, fr_sbuff_t *sbuff, bool no_trailing);
 
 1633fr_slen_t fr_sbuff_out_uint64(fr_sbuff_parse_error_t *err, uint64_t *out, fr_sbuff_t *sbuff, bool no_trailing);
 
 1634fr_slen_t fr_sbuff_out_size(fr_sbuff_parse_error_t *err, size_t *out, fr_sbuff_t *sbuff, bool no_trailing);
 
 1636fr_slen_t fr_sbuff_out_uint8_dec(fr_sbuff_parse_error_t *err, uint8_t *out, fr_sbuff_t *sbuff, bool no_trailing);
 
 1637fr_slen_t fr_sbuff_out_uint16_dec(fr_sbuff_parse_error_t *err, uint16_t *out, fr_sbuff_t *sbuff, bool no_trailing);
 
 1638fr_slen_t fr_sbuff_out_uint32_dec(fr_sbuff_parse_error_t *err, uint32_t *out, fr_sbuff_t *sbuff, bool no_trailing);
 
 1639fr_slen_t fr_sbuff_out_uint64_dec(fr_sbuff_parse_error_t *err, uint64_t *out, fr_sbuff_t *sbuff, bool no_trailing);
 
 1640fr_slen_t fr_sbuff_out_size_dec(fr_sbuff_parse_error_t *err, size_t *out, fr_sbuff_t *sbuff, bool no_trailing);
 
 1642fr_slen_t fr_sbuff_out_uint8_oct(fr_sbuff_parse_error_t *err, uint8_t *out, fr_sbuff_t *sbuff, bool no_trailing);
 
 1643fr_slen_t fr_sbuff_out_uint16_oct(fr_sbuff_parse_error_t *err, uint16_t *out, fr_sbuff_t *sbuff, bool no_trailing);
 
 1644fr_slen_t fr_sbuff_out_uint32_oct(fr_sbuff_parse_error_t *err, uint32_t *out, fr_sbuff_t *sbuff, bool no_trailing);
 
 1645fr_slen_t fr_sbuff_out_uint64_oct(fr_sbuff_parse_error_t *err, uint64_t *out, fr_sbuff_t *sbuff, bool no_trailing);
 
 1646fr_slen_t fr_sbuff_out_size_oct(fr_sbuff_parse_error_t *err, size_t *out, fr_sbuff_t *sbuff, bool no_trailing);
 
 1648fr_slen_t fr_sbuff_out_uint8_hex(fr_sbuff_parse_error_t *err, uint8_t *out, fr_sbuff_t *sbuff, bool no_trailing);
 
 1649fr_slen_t fr_sbuff_out_uint16_hex(fr_sbuff_parse_error_t *err, uint16_t *out, fr_sbuff_t *sbuff, bool no_trailing);
 
 1650fr_slen_t fr_sbuff_out_uint32_hex(fr_sbuff_parse_error_t *err, uint32_t *out, fr_sbuff_t *sbuff, bool no_trailing);
 
 1651fr_slen_t fr_sbuff_out_uint64_hex(fr_sbuff_parse_error_t *err, uint64_t *out, fr_sbuff_t *sbuff, bool no_trailing);
 
 1652fr_slen_t fr_sbuff_out_size_hex(fr_sbuff_parse_error_t *err, size_t *out, fr_sbuff_t *sbuff, bool no_trailing);
 
 1654fr_slen_t fr_sbuff_out_float32(fr_sbuff_parse_error_t *err, float *out, fr_sbuff_t *sbuff, bool no_trailing);
 
 1655fr_slen_t fr_sbuff_out_float64(fr_sbuff_parse_error_t *err, double *out, fr_sbuff_t *sbuff, bool no_trailing);
 
 1657#ifndef SIZE_SAME_AS_UINT64
 
 1658#  define _fr_sbuff_out_size(_err, _out, _in)   size_t *        : fr_sbuff_out_size(_err, (size_t *)_out, _in, true),
 
 1660#  define _fr_sbuff_out_size(_err, _out, _in)
 
 1663#ifndef SSIZE_SAME_AS_INT64
 
 1664#  define _fr_sbuff_out_ssize(_err, _out, _in)  ssize_t *       : fr_sbuff_out_ssize(_err, (ssize_t *)_out, _in, true),
 
 1666#  define _fr_sbuff_out_ssize(_err, _out, _in)
 
 1677#define fr_sbuff_out(_err, _out, _in) \
 
 1679                 bool *         : fr_sbuff_out_bool((bool *)_out, _in), \
 
 1680                 int8_t *       : fr_sbuff_out_int8(_err, (int8_t *)_out, _in, true), \
 
 1681                 int16_t *      : fr_sbuff_out_int16(_err, (int16_t *)_out, _in, true), \
 
 1682                 int32_t *      : fr_sbuff_out_int32(_err, (int32_t *)_out, _in, true), \
 
 1683                 int64_t *      : fr_sbuff_out_int64(_err, (int64_t *)_out, _in, true), \
 
 1684                 _fr_sbuff_out_ssize(_err, _out, _in) \
 
 1685                 uint8_t *      : fr_sbuff_out_uint8(_err, (uint8_t *)_out, _in, true), \
 
 1686                 uint16_t *     : fr_sbuff_out_uint16(_err, (uint16_t *)_out, _in, true), \
 
 1687                 uint32_t *     : fr_sbuff_out_uint32(_err, (uint32_t *)_out, _in, true), \
 
 1688                 uint64_t *     : fr_sbuff_out_uint64(_err, (uint64_t *)_out, _in, true), \
 
 1689                 _fr_sbuff_out_size(_err, _out, _in) \
 
 1690                 float *        : fr_sbuff_out_float32(_err, (float *)_out, _in, true), \
 
 1691                 double *       : fr_sbuff_out_float64(_err, (double *)_out, _in, true) \
 
 1703size_t  fr_sbuff_adv_past_str(fr_sbuff_t *sbuff, char const *needle, size_t need_len);
 
 1705#define fr_sbuff_adv_past_str_literal(_sbuff, _needle) fr_sbuff_adv_past_str(_sbuff, _needle, sizeof(_needle) - 1)
 
 1707size_t  fr_sbuff_adv_past_strcase(fr_sbuff_t *sbuff, char const *needle, size_t need_len);
 
 1709#define fr_sbuff_adv_past_strcase_literal(_sbuff, _needle) fr_sbuff_adv_past_strcase(_sbuff, _needle, sizeof(_needle) - 1)
 
 1711size_t  fr_sbuff_adv_past_allowed(fr_sbuff_t *sbuff, size_t len,
 
 1712                                  bool const allowed[static UINT8_MAX + 1], fr_sbuff_term_t const *tt);
 
 1714#define fr_sbuff_adv_past_zeros(_sbuff, _len, _tt) fr_sbuff_adv_past_allowed(_sbuff, _len, sbuff_char_class_zero, _tt)
 
 1716#define fr_sbuff_adv_past_whitespace(_sbuff, _len, _tt) fr_sbuff_adv_past_allowed(_sbuff, _len, sbuff_char_whitespace, _tt)
 
 1718#define fr_sbuff_adv_past_blank(_sbuff, _len, _tt) fr_sbuff_adv_past_allowed(_sbuff, _len, sbuff_char_blank, _tt)
 
 1720size_t  fr_sbuff_adv_until(fr_sbuff_t *sbuff, size_t len, fr_sbuff_term_t const *tt, char escape_chr);
 
 1722char    *fr_sbuff_adv_to_chr_utf8(fr_sbuff_t *in, size_t len, char const *chr);
 
 1724char    *fr_sbuff_adv_to_chr(fr_sbuff_t *in, size_t len, char c);
 
 1726char    *fr_sbuff_adv_to_str(fr_sbuff_t *sbuff, size_t len, char const *needle, size_t needle_len);
 
 1728#define fr_sbuff_adv_to_str_literal(_sbuff, _len, _needle) fr_sbuff_adv_to_str(_sbuff, _len, _needle, sizeof(_needle) - 1)
 
 1730char    *fr_sbuff_adv_to_strcase(fr_sbuff_t *sbuff, size_t len, char const *needle, size_t needle_len);
 
 1732#define fr_sbuff_adv_to_strcase_literal(_sbuff, _len, _needle) fr_sbuff_adv_to_strcase(_sbuff, _len, _needle, sizeof(_needle) - 1)
 
 1734bool    fr_sbuff_next_if_char(fr_sbuff_t *sbuff, char c);
 
 1736bool    fr_sbuff_next_unless_char(fr_sbuff_t *sbuff, char c);
 
 1741static inline char fr_sbuff_next(fr_sbuff_t *sbuff)
 
 1743        if (!fr_sbuff_extend(sbuff)) return '\0';
 
 1744        return fr_sbuff_advance(sbuff, 1);
 
 1752size_t fr_sbuff_trim(fr_sbuff_t *sbuff, bool const to_trim[static UINT8_MAX + 1]);
 
 1761bool fr_sbuff_is_terminal(fr_sbuff_t *in, fr_sbuff_term_t const *tt);
 
 1763static inline bool fr_sbuff_is_in_charset(fr_sbuff_t *sbuff, bool const chars[static UINT8_MAX + 1])
 
 1765        if (!fr_sbuff_extend(sbuff)) return false;
 
 1766        return chars[(uint8_t)*sbuff->p];
 
 1769static inline bool fr_sbuff_is_str(fr_sbuff_t *sbuff, char const *str, size_t len)
 
 1771        if (len == SIZE_MAX) len = strlen(str);
 
 1772        if (!fr_sbuff_extend_lowat(NULL, sbuff, len)) return false;
 
 1773        return memcmp(sbuff->p, str, len) == 0;
 
 1775#define fr_sbuff_is_str_literal(_sbuff, _str) fr_sbuff_is_str(_sbuff, _str, sizeof(_str) - 1)
 
 1777#define fr_sbuff_eof(_x) (!fr_sbuff_extend(_x))
 
 1779static inline bool _fr_sbuff_is_char(fr_sbuff_t *sbuff, char *p, char c)
 
 1781        if (!fr_sbuff_extend(sbuff)) return false;
 
 1784static inline bool _fr_marker_is_char(fr_sbuff_marker_t *marker, char *p, char c)
 
 1786        if (!fr_sbuff_extend(marker)) return false;
 
 1789#define fr_sbuff_is_char(_sbuff_or_marker, _c) \
 
 1790        _Generic((_sbuff_or_marker), \
 
 1791                 fr_sbuff_t *           : _fr_sbuff_is_char((fr_sbuff_t *)(_sbuff_or_marker), fr_sbuff_current(_sbuff_or_marker), _c), \
 
 1792                 fr_sbuff_marker_t *    : _fr_marker_is_char((fr_sbuff_marker_t *)(_sbuff_or_marker), fr_sbuff_current(_sbuff_or_marker), _c) \
 
 1795#define SBUFF_IS_FUNC(_name, _test) \
 
 1796        static inline bool _fr_sbuff_is_ ## _name(fr_sbuff_t *sbuff, char *p) \
 
 1798                if (!fr_sbuff_extend(sbuff)) return false; \
 
 1801        static inline bool _fr_marker_is_ ## _name(fr_sbuff_marker_t *marker, char *p) \
 
 1803                if (!fr_sbuff_extend(marker)) return false; \
 
 1807#define SBUFF_IS_GENERIC(_sbuff_or_marker, _name) \
 
 1808        _Generic((_sbuff_or_marker), \
 
 1809                 fr_sbuff_t *           : _fr_sbuff_is_ ## _name((fr_sbuff_t *)(_sbuff_or_marker), fr_sbuff_current(_sbuff_or_marker)), \
 
 1810                 fr_sbuff_marker_t *    : _fr_marker_is_ ## _name((fr_sbuff_marker_t *)(_sbuff_or_marker), fr_sbuff_current(_sbuff_or_marker)) \
 
 1813SBUFF_IS_FUNC(digit, isdigit((uint8_t) *p))
 
 1814#define fr_sbuff_is_digit(_sbuff_or_marker) \
 
 1815        SBUFF_IS_GENERIC(_sbuff_or_marker, digit)
 
 1817SBUFF_IS_FUNC(upper, isupper((uint8_t) *p))
 
 1818#define fr_sbuff_is_upper(_sbuff_or_marker) \
 
 1819        SBUFF_IS_GENERIC(_sbuff_or_marker, upper)
 
 1821SBUFF_IS_FUNC(lower, islower((uint8_t) *p))
 
 1822#define fr_sbuff_is_lower(_sbuff_or_marker) \
 
 1823        SBUFF_IS_GENERIC(_sbuff_or_marker, lower)
 
 1825SBUFF_IS_FUNC(alpha, isalpha((uint8_t) *p))
 
 1826#define fr_sbuff_is_alpha(_sbuff_or_marker) \
 
 1827        SBUFF_IS_GENERIC(_sbuff_or_marker, alpha)
 
 1829SBUFF_IS_FUNC(alnum, isalnum((uint8_t) *p))
 
 1830#define fr_sbuff_is_alnum(_sbuff_or_marker) \
 
 1831        SBUFF_IS_GENERIC(_sbuff_or_marker, alnum)
 
 1833SBUFF_IS_FUNC(space, isspace((uint8_t) *p))
 
 1834#define fr_sbuff_is_space(_sbuff_or_marker) \
 
 1835        SBUFF_IS_GENERIC(_sbuff_or_marker, space)
 
 1837SBUFF_IS_FUNC(hex, isxdigit((uint8_t) *p))
 
 1838#define fr_sbuff_is_hex(_sbuff_or_marker) \
 
 1839        SBUFF_IS_GENERIC(_sbuff_or_marker, hex)
 
 1843void    fr_sbuff_unescape_debug(FILE *fp, fr_sbuff_unescape_rules_t const *escapes);
 
 1845void    fr_sbuff_terminal_debug(FILE *fp, fr_sbuff_term_t const *tt);
 
 1847void    fr_sbuff_parse_rules_debug(FILE *fp, fr_sbuff_parse_rules_t const *p_rules);
 
 1850 *      ...printf("foo %.*s", fr_sbuff_as_percent_s(&sbuff));
 
 1852#define fr_sbuff_as_percent_s(_sbuff) (int) fr_sbuff_remaining(_sbuff), fr_sbuff_current(_sbuff)
 
static const bool escapes[UINT8_MAX+1]
@ FR_SBUFF_PARSE_ERROR_NUM_OVERFLOW
Integer type would overflow.
@ FR_SBUFF_PARSE_ERROR_NUM_UNDERFLOW
Integer type would underflow.
@ FR_SBUFF_PARSE_ERROR_NOT_FOUND
String does not contain a token matching the output type.
@ FR_SBUFF_PARSE_ERROR_FORMAT
Format of data was invalid.
@ FR_SBUFF_PARSE_OK
No error.
@ FR_SBUFF_PARSE_ERROR_OUT_OF_SPACE
No space available in output buffer.
@ FR_SBUFF_PARSE_ERROR_TRAILING
Trailing characters found.
bool const sbuff_char_class_float[UINT8_MAX+1]
bool const sbuff_char_line_endings[UINT8_MAX+1]
bool const sbuff_char_class_hex[UINT8_MAX+1]
bool const sbuff_char_class_uint[UINT8_MAX+1]
size_t sbuff_parse_error_table_len
bool const sbuff_char_class_zero[UINT8_MAX+1]
bool const sbuff_char_class_hostname[UINT8_MAX+1]
bool const sbuff_char_whitespace[UINT8_MAX+1]
bool const sbuff_char_blank[UINT8_MAX+1]
bool const sbuff_char_class_int[UINT8_MAX+1]
fr_table_num_ordered_t const sbuff_parse_error_table[]
bool const sbuff_char_word[UINT8_MAX+1]
bool const sbuff_char_alpha_num[UINT8_MAX+1]
TALLOC_CTX * ctx
Context to alloc new buffers in.
bool(* fr_sbuff_eof_t)(fr_sbuff_t *sbuff)
For a given extension function, returns whether it is at EOF.
size_t shifted
How much we've read from this file.
size_t shifted
How many bytes this sbuff has been shifted since its creation.
fr_sbuff_extend_t extend
Function to re-populate or extend the buffer.
char const  * str
Terminal string.
void * uctx
Extend uctx data.
size_t init
How much to allocate initially.
char chr
Character at the start of an escape sequence.
char const  * name
Name for rule set to aid we debugging.
bool do_oct
Process oct sequences i.e.
fr_sbuff_marker_t * m
Pointers to update if the underlying buffer changes.
size_t len
Length of the list.
char const  * err
Where the last error occurred.
bool do_hex
Process hex sequences i.e.
size_t max
Maximum size of the buffer.
size_t len
Length of string.
char * buff_end
The true end of the buffer.
fr_sbuff_t * parent
sbuff this sbuff was copied from.
uint8_t is_const
Can't be modified.
fr_sbuff_marker_t * next
Next m in the list.
uint8_t adv_parent
If true, advance the parent.
fr_sbuff_term_elem_t * elem
A sorted list of terminal strings.
ssize_t fr_slen_t
Represents number of bytes parsed or location of parse error.
fr_sbuff_t * parent
Owner of the marker.
fr_sbuff_eof_t eof
Function to determine if the buffer is at EOF.
size_t(* fr_sbuff_extend_t)(fr_sbuff_extend_status_t *status, fr_sbuff_t *sbuff, size_t req_extension)
Extension callback.
FILE * file
FILE * we're reading from.
size_t max
Maximum number of bytes to read.
fr_sbuff_extend_status_t
Whether the buffer is currently extendable and whether it was extended.
@ FR_SBUFF_FLAG_EXTEND_ERROR
The last call to an extend function resulted in an error.
@ FR_SBUFF_FLAG_EXTENDED
The last call to extend function actually extended the buffer.
Terminal element with pre-calculated lengths.
Set of terminal elements.
File sbuff extension structure.
Talloc sbuff extension structure.
Set of parsing rules for *unescape_until functions.
static char buff[sizeof("18446744073709551615")+3]
#define fr_table_str_by_value(_table, _number, _def)
Convert an integer to a string.
An element in an arbitrarily ordered array of name to num mappings.
#define fr_strerror_const(_msg)