26 RCSIDH(sbuff_h,
"$Id: 7ee0f8296e8f06cee9bcedc895a551b8633d9114 $")
39 #include <sys/types.h>
56 #include <freeradius-devel/util/atexit.h>
57 #include <freeradius-devel/util/strerror.h>
58 #include <freeradius-devel/util/table.h>
59 #include <freeradius-devel/util/talloc.h>
155 #define FR_SBUFF_TERM(_str) \
158 .elem = (fr_sbuff_term_elem_t[]){ L(_str) }, \
167 #define FR_SBUFF_TERMS(...) \
169 .len = (sizeof((fr_sbuff_term_elem_t[]){ __VA_ARGS__ }) / sizeof(fr_sbuff_term_elem_t)), \
170 .elem = (fr_sbuff_term_elem_t[]){ __VA_ARGS__ }, \
223 } fr_sbuff_parse_rules_t;
249 #define FR_SBUFF_FLAG_EXTENDABLE 0x01
250 #define FR_SBUFF_FLAG_EXTENDED 0x02
251 #define FR_SBUFF_FLAG_EXTEND_ERROR 0x04
257 FR_SBUFF_NOT_EXTENDABLE = 0x00,
262 } fr_sbuff_extend_status_t;
264 #define fr_sbuff_is_extendable(_status) ((_status) & FR_SBUFF_FLAG_EXTENDABLE)
265 #define fr_sbuff_was_extended(_status) ((_status) & FR_SBUFF_FLAG_EXTENDED)
281 #define SBUFF_CHAR_CLASS_ALPHA \
282 ['a'] = true, ['b'] = true, ['c'] = true, ['d'] = true, ['e'] = true, \
283 ['f'] = true, ['g'] = true, ['h'] = true, ['i'] = true, ['j'] = true, \
284 ['k'] = true, ['l'] = true, ['m'] = true, ['n'] = true, ['o'] = true, \
285 ['p'] = true, ['q'] = true, ['r'] = true, ['s'] = true, ['t'] = true, \
286 ['u'] = true, ['v'] = true, ['w'] = true, ['x'] = true, ['y'] = true, \
288 ['A'] = true, ['B'] = true, ['C'] = true, ['D'] = true, ['E'] = true, \
289 ['F'] = true, ['G'] = true, ['H'] = true, ['I'] = true, ['J'] = true, \
290 ['K'] = true, ['L'] = true, ['M'] = true, ['N'] = true, ['O'] = true, \
291 ['P'] = true, ['Q'] = true, ['R'] = true, ['S'] = true, ['T'] = true, \
292 ['U'] = true, ['V'] = true, ['W'] = true, ['X'] = true, ['Y'] = true, \
297 #define SBUFF_CHAR_CLASS_NUM \
298 ['0'] = true, ['1'] = true, ['2'] = true, ['3'] = true, ['4'] = true, \
299 ['5'] = true, ['6'] = true, ['7'] = true, ['8'] = true, ['9'] = true
303 #define SBUFF_CHAR_CLASS_ALPHA_NUM \
304 SBUFF_CHAR_CLASS_ALPHA, \
309 #define SBUFF_CHAR_CLASS_HEX \
310 SBUFF_CHAR_CLASS_NUM, \
311 ['a'] = true, ['b'] = true, ['c'] = true, ['d'] = true, ['e'] = true, \
313 ['A'] = true, ['B'] = true, ['C'] = true, ['D'] = true, ['E'] = true, \
316 #define SBUFF_CHAR_CLASS_SYMBOLS \
317 ['!'] = true, ['"'] = true, ['#'] = true, ['$'] = true, ['%'] = true, \
318 ['&'] = true, ['/'] = true, ['('] = true, [')'] = true, ['*'] = true, \
319 ['+'] = true, ['`'] = true, ['-'] = true, ['.'] = true, ['/'] = true, \
320 [':'] = true, [';'] = true, ['<'] = true, ['='] = true, ['>'] = true, \
321 ['?'] = true, ['@'] = true, ['['] = true, ['\''] = true, [']'] = true, \
322 ['^'] = true, ['_'] = true, ['`'] = true, ['{'] = true, ['|'] = true, \
323 ['}'] = true, ['~'] = true \
326 * If the additional tables need to be generated feel free to use this
333 int main(int argc, char **argv)
336 start = atoi(argv[1]);
338 for (i = start; i <= end; i++) {
339 printf("[0x%02x] = true, ", i);
340 if (!(i % 8)) printf("\\\n");
352 #define SBUFF_CHAR_UNPRINTABLES_LOW \
354 [0x01] = true, [0x02] = true, [0x03] = true, [0x04] = true, [0x05] = true, [0x06] = true, [0x07] = true, [0x08] = true, \
355 [0x09] = true, [0x0a] = true, [0x0b] = true, [0x0c] = true, [0x0d] = true, [0x0e] = true, [0x0f] = true, [0x10] = true, \
356 [0x11] = true, [0x12] = true, [0x13] = true, [0x14] = true, [0x15] = true, [0x16] = true, [0x17] = true, [0x18] = true, \
357 [0x19] = true, [0x1a] = true, [0x1b] = true, [0x1c] = true, [0x1d] = true, [0x1e] = true, [0x1f] = true, \
365 #define SBUFF_CHAR_UNPRINTABLES_EXTENDED \
367 [0x81] = true, [0x82] = true, [0x83] = true, [0x84] = true, [0x85] = true, [0x86] = true, [0x87] = true, [0x88] = true, \
368 [0x89] = true, [0x8a] = true, [0x8b] = true, [0x8c] = true, [0x8d] = true, [0x8e] = true, [0x8f] = true, [0x90] = true, \
369 [0x91] = true, [0x92] = true, [0x93] = true, [0x94] = true, [0x95] = true, [0x96] = true, [0x97] = true, [0x98] = true, \
370 [0x99] = true, [0x9a] = true, [0x9b] = true, [0x9c] = true, [0x9d] = true, [0x9e] = true, [0x9f] = true, [0xa0] = true, \
371 [0xa1] = true, [0xa2] = true, [0xa3] = true, [0xa4] = true, [0xa5] = true, [0xa6] = true, [0xa7] = true, [0xa8] = true, \
372 [0xa9] = true, [0xaa] = true, [0xab] = true, [0xac] = true, [0xad] = true, [0xae] = true, [0xaf] = true, [0xb0] = true, \
373 [0xb1] = true, [0xb2] = true, [0xb3] = true, [0xb4] = true, [0xb5] = true, [0xb6] = true, [0xb7] = true, [0xb8] = true, \
374 [0xb9] = true, [0xba] = true, [0xbb] = true, [0xbc] = true, [0xbd] = true, [0xbe] = true, [0xbf] = true, [0xc0] = true, \
375 [0xc1] = true, [0xc2] = true, [0xc3] = true, [0xc4] = true, [0xc5] = true, [0xc6] = true, [0xc7] = true, [0xc8] = true, \
376 [0xc9] = true, [0xca] = true, [0xcb] = true, [0xcc] = true, [0xcd] = true, [0xce] = true, [0xcf] = true, [0xd0] = true, \
377 [0xd1] = true, [0xd2] = true, [0xd3] = true, [0xd4] = true, [0xd5] = true, [0xd6] = true, [0xd7] = true, [0xd8] = true, \
378 [0xd9] = true, [0xda] = true, [0xdb] = true, [0xdc] = true, [0xdd] = true, [0xde] = true, [0xdf] = true, [0xe0] = true, \
379 [0xe1] = true, [0xe2] = true, [0xe3] = true, [0xe4] = true, [0xe5] = true, [0xe6] = true, [0xe7] = true, [0xe8] = true, \
380 [0xe9] = true, [0xea] = true, [0xeb] = true, [0xec] = true, [0xed] = true, [0xee] = true, [0xef] = true, [0xf0] = true, \
381 [0xf1] = true, [0xf2] = true, [0xf3] = true, [0xf4] = true, [0xf5] = true, [0xf6] = true, [0xf7] = true, [0xf8] = true, \
382 [0xf9] = true, [0xfa] = true, [0xfb] = true, [0xfc] = true, [0xfd] = true, [0xfe] = true, [0xff] = true
387 #define FR_SBUFF_RETURN(_func, _sbuff, ...) \
390 _slen = _func(_sbuff, ## __VA_ARGS__ ); \
391 if (_slen < 0) return _slen; \
404 #define _FR_SBUFF(_sbuff_or_marker, _start, _current, _end, _extend, _adv_parent) \
406 .buff = fr_sbuff_buff(_sbuff_or_marker), \
410 .is_const = fr_sbuff_ptr(_sbuff_or_marker)->is_const, \
411 .adv_parent = (_adv_parent), \
413 .extend = (_extend), \
414 .uctx = fr_sbuff_ptr(_sbuff_or_marker)->uctx, \
415 .parent = fr_sbuff_ptr(_sbuff_or_marker) \
426 #define FR_SBUFF(_sbuff_or_marker) _FR_SBUFF(_sbuff_or_marker, \
427 fr_sbuff_current(_sbuff_or_marker), \
428 fr_sbuff_current(_sbuff_or_marker), \
429 fr_sbuff_end(_sbuff_or_marker), \
430 fr_sbuff_ptr(_sbuff_or_marker)->extend, \
440 #define FR_SBUFF_ABS(_sbuff_or_marker) _FR_SBUFF(_sbuff_or_marker, \
441 fr_sbuff_start(_sbuff_or_marker), \
442 fr_sbuff_current(_sbuff_or_marker), \
443 fr_sbuff_end(_sbuff_or_marker), \
444 fr_sbuff_ptr(_sbuff_or_marker)->extend, \
459 #define FR_SBUFF_REPARSE(_sbuff_or_marker) _FR_SBUFF(_sbuff_or_marker, \
460 fr_sbuff_start(_sbuff_or_marker), \
461 fr_sbuff_start(_sbuff_or_marker), \
462 fr_sbuff_current(_sbuff_or_marker), \
473 #define FR_SBUFF_BIND_CURRENT(_sbuff_or_marker) _FR_SBUFF(_sbuff_or_marker, \
474 fr_sbuff_current(_sbuff_or_marker), \
475 fr_sbuff_current(_sbuff_or_marker), \
476 fr_sbuff_end(_sbuff_or_marker), \
477 fr_sbuff_ptr(_sbuff_or_marker)->extend, \
487 #define FR_SBUFF_BIND_CURRENT_ABS(_sbuff_or_marker) FR_SBUFF_ABS(_sbuff_or_marker, \
488 fr_sbuff_start(_sbuff_or_marker), \
489 fr_sbuff_current(_sbuff_or_marker), \
490 fr_sbuff_end(_sbuff_or_marker), \
491 fr_sbuff_ptr(_sbuff_or_marker)->extend, \
502 #define FR_SBUFF_OUT(_start, _len_or_end) \
506 .end_i = _Generic((_len_or_end), \
507 size_t : (char const *)(_start) + ((size_t)(_len_or_end) - 1), \
508 long : (char const *)(_start) + ((size_t)(_len_or_end) - 1), \
509 int : (char const *)(_start) + ((size_t)(_len_or_end) - 1), \
510 unsigned int : (char const *)(_start) + ((size_t)(_len_or_end) - 1), \
511 char * : (char const *)(_len_or_end), \
512 char const * : (char const *)(_len_or_end) \
515 .is_const = IS_CONST(char *, _start) \
526 #define FR_SBUFF_IN(_start, _len_or_end) \
530 .end_i = _Generic((_len_or_end), \
531 size_t : (char const *)(_start) + (size_t)(_len_or_end), \
532 long : (char const *)(_start) + (size_t)(_len_or_end), \
533 int : (char const *)(_start) + (size_t)(_len_or_end), \
534 unsigned int : (char const *)(_start) + (size_t)(_len_or_end), \
535 char * : (char const *)(_len_or_end), \
536 char const * : (char const *)(_len_or_end) \
539 .is_const = IS_CONST(char *, _start) \
546 fr_sbuff_t sbuff; //!< Thread local sbuff.
547 fr_sbuff_uctx_talloc_t tctx; //!< Thread local tctx.
548 } fr_sbuff_thread_local_t;
550 static inline int _sbuff_thread_local_free(void *sbtl)
552 return talloc_free(sbtl);
561 #define FR_SBUFF_TALLOC_THREAD_LOCAL(_out, _init, _max) \
563 static _Thread_local fr_sbuff_thread_local_t *_sbuff_t_local; \
564 if (!_sbuff_t_local) { \
565 fr_sbuff_thread_local_t *sbtl = talloc_zero(NULL, fr_sbuff_thread_local_t); \
566 fr_sbuff_init_talloc(sbtl, &sbtl->sbuff, &sbtl->tctx, _init, _max); \
567 fr_atexit_thread_local(_sbuff_t_local, _sbuff_thread_local_free, sbtl); \
568 *(_out) = &_sbuff_t_local->sbuff; \
570 fr_sbuff_reset_talloc(&_sbuff_t_local->sbuff); \
571 *(_out) = &_sbuff_t_local->sbuff; \
575 void fr_sbuff_update(fr_sbuff_t *sbuff, char *new_buff, size_t new_len);
577 size_t fr_sbuff_shift(fr_sbuff_t *sbuff, size_t shift);
579 size_t fr_sbuff_extend_file(fr_sbuff_t *sbuff, size_t extension);
581 size_t fr_sbuff_extend_talloc(fr_sbuff_t *sbuff, size_t extension);
583 int fr_sbuff_trim_talloc(fr_sbuff_t *sbuff, size_t len);
585 int fr_sbuff_reset_talloc(fr_sbuff_t *sbuff);
587 static inline void fr_sbuff_terminate(fr_sbuff_t *sbuff)
592 static inline void _fr_sbuff_init(fr_sbuff_t *out, char const *start, char const *end, bool is_const, bool nul_term)
594 if (unlikely(end < start)) end = start; /* Could be an assert? */
604 if (nul_term) *out->start = '\0';
608 * GCC is stupid and will warn about output variables
609 * being unnitialised, even if they're not dereferenced.
611 #if defined(__GNUC__) && __GNUC__ >= 11
612 DIAG_OFF(maybe-uninitialized)
624 #define fr_sbuff_init_out(_out, _start, _len_or_end) \
625 _fr_sbuff_init(_out, _start, \
626 _Generic((_len_or_end), \
627 size_t : (char const *)(_start) + ((size_t)(_len_or_end) - 1), \
628 long : (char const *)(_start) + ((size_t)(_len_or_end) - 1), \
629 int : (char const *)(_start) + ((size_t)(_len_or_end) - 1), \
630 char * : (char const *)(_len_or_end), \
631 char const * : (char const *)(_len_or_end) \
633 IS_CONST(char *, _start), true)
635 #if defined(__GNUC__) && __GNUC__ >= 11
636 DIAG_ON(maybe-uninitialized)
646 #define fr_sbuff_init_in(_out, _start, _len_or_end) \
647 _fr_sbuff_init(_out, _start, \
648 _Generic((_len_or_end), \
649 size_t : (char const *)(_start) + (size_t)(_len_or_end), \
650 long : (char const *)(_start) + (size_t)(_len_or_end), \
651 int : (char const *)(_start) + (size_t)(_len_or_end), \
652 char * : (char const *)(_len_or_end), \
653 char const * : (char const *)(_len_or_end) \
655 IS_CONST(char *, _start), false)
669 static inline fr_sbuff_t *fr_sbuff_init_file(fr_sbuff_t *sbuff, fr_sbuff_uctx_file_t *fctx,
670 char *buff, size_t len, FILE *file, size_t max)
672 *fctx = (fr_sbuff_uctx_file_t){
675 .buff_end = buff + len //!< Store the real end
678 *sbuff = (fr_sbuff_t){
682 .end = buff, //!< Starts with 0 bytes available
683 .extend = fr_sbuff_extend_file,
701 static inline fr_sbuff_t *fr_sbuff_init_talloc(TALLOC_CTX *ctx,
702 fr_sbuff_t *sbuff, fr_sbuff_uctx_talloc_t *tctx,
703 size_t init, size_t max)
707 *tctx = (fr_sbuff_uctx_talloc_t){
714 * Allocate the initial buffer
716 * We always allocate a buffer so we don't
717 * trigger ubsan errors by performing
718 * arithmetic on NULL pointers.
720 buff = talloc_zero_array(ctx, char, init + 1);
722 fr_strerror_printf("Failed allocating buffer of %zu bytes", init + 1);
723 memset(sbuff, 0, sizeof(*sbuff)); /* clang scan */
727 *sbuff = (fr_sbuff_t){
732 .extend = fr_sbuff_extend_talloc,
757 #define fr_sbuff_ptr(_sbuff_or_marker) \
758 _Generic((_sbuff_or_marker), \
759 fr_sbuff_t * : ((fr_sbuff_t *)(_sbuff_or_marker)), \
760 fr_sbuff_marker_t * : ((fr_sbuff_marker_t *)(_sbuff_or_marker))->parent \
768 #define fr_sbuff_buff(_sbuff_or_marker) \
769 _Generic((_sbuff_or_marker), \
770 fr_sbuff_t * : ((fr_sbuff_t const *)(_sbuff_or_marker))->buff, \
771 fr_sbuff_t const * : ((fr_sbuff_t const *)(_sbuff_or_marker))->buff, \
772 fr_sbuff_marker_t * : ((fr_sbuff_marker_t const *)(_sbuff_or_marker))->parent->buff, \
773 fr_sbuff_marker_t const * : ((fr_sbuff_marker_t const *)(_sbuff_or_marker))->parent->buff \
784 #define fr_sbuff_start(_sbuff_or_marker) \
785 (_Generic((_sbuff_or_marker), \
786 fr_sbuff_t * : ((fr_sbuff_t const *)(_sbuff_or_marker))->start, \
787 fr_sbuff_t const * : ((fr_sbuff_t const *)(_sbuff_or_marker))->start, \
788 fr_sbuff_marker_t * : ((fr_sbuff_marker_t const *)(_sbuff_or_marker))->parent->start, \
789 fr_sbuff_marker_t const * : ((fr_sbuff_marker_t const *)(_sbuff_or_marker))->parent->start \
800 #define fr_sbuff_current(_sbuff_or_marker) \
801 (_Generic((_sbuff_or_marker), \
802 fr_sbuff_t * : ((fr_sbuff_t const *)(_sbuff_or_marker))->p, \
803 fr_sbuff_t const * : ((fr_sbuff_t const *)(_sbuff_or_marker))->p, \
804 fr_sbuff_marker_t * : ((fr_sbuff_marker_t const *)(_sbuff_or_marker))->p, \
805 fr_sbuff_marker_t const * : ((fr_sbuff_marker_t const *)(_sbuff_or_marker))->p \
813 #define fr_sbuff_end(_sbuff_or_marker) \
814 (_Generic((_sbuff_or_marker), \
815 fr_sbuff_t * : ((fr_sbuff_t const *)(_sbuff_or_marker))->end, \
816 fr_sbuff_t const * : ((fr_sbuff_t const *)(_sbuff_or_marker))->end, \
817 fr_sbuff_marker_t * : ((fr_sbuff_marker_t const *)(_sbuff_or_marker))->parent->end, \
818 fr_sbuff_marker_t const * : ((fr_sbuff_marker_t const *)(_sbuff_or_marker))->parent->end \
826 #define fr_sbuff_shifted(_sbuff_or_marker) \
827 (_Generic((_sbuff_or_marker), \
828 fr_sbuff_t * : ((fr_sbuff_t const *)(_sbuff_or_marker))->shifted, \
829 fr_sbuff_t const * : ((fr_sbuff_t const *)(_sbuff_or_marker))->shifted, \
830 fr_sbuff_marker_t * : ((fr_sbuff_marker_t const *)(_sbuff_or_marker))->parent->shifted, \
831 fr_sbuff_marker_t const * : ((fr_sbuff_marker_t const *)(_sbuff_or_marker))->parent->shifted \
842 #define fr_sbuff_char(_sbuff_or_marker, _eob) \
843 (fr_sbuff_current(_sbuff_or_marker) >= fr_sbuff_end(_sbuff_or_marker) ? _eob : *fr_sbuff_current(_sbuff_or_marker))
852 #define fr_sbuff_switch(_sbuff_or_marker, _eob) \
853 switch (fr_sbuff_char(_sbuff_or_marker, _eob))
869 #define fr_sbuff_diff(_a, _b) \
870 ((ssize_t)(fr_sbuff_current(_a) - fr_sbuff_current(_b)))
885 #define fr_sbuff_remaining(_sbuff_or_marker) \
886 ((size_t)(fr_sbuff_end(_sbuff_or_marker) < fr_sbuff_current(_sbuff_or_marker) ? \
887 0 : (fr_sbuff_end(_sbuff_or_marker) - fr_sbuff_current(_sbuff_or_marker))))
896 #define fr_sbuff_used(_sbuff_or_marker) \
897 ((size_t)(fr_sbuff_start(_sbuff_or_marker) > fr_sbuff_current(_sbuff_or_marker) ? \
898 0 : (fr_sbuff_current(_sbuff_or_marker) - fr_sbuff_start(_sbuff_or_marker))))
908 static inline fr_slen_t _fr_sbuff_error(fr_sbuff_t *sbuff, char const *err)
910 fr_sbuff_t *parent = sbuff->parent;
913 if (sbuff->err) err = sbuff->err;
914 if (parent) parent->err = err;
916 slen = -((err - fr_sbuff_start(sbuff)) + 1);
918 #ifdef __clang_analyzer__
920 * Convince clang that the return value
921 * is always negative. It never can be
922 * else the sbuff code is very broken.
924 if (slen >= 0) return -1;
938 #define fr_sbuff_error(_sbuff_or_marker) \
939 _fr_sbuff_error(fr_sbuff_ptr(_sbuff_or_marker), fr_sbuff_current(_sbuff_or_marker))
949 #define fr_sbuff_used_total(_sbuff_or_marker) \
950 ((size_t)((fr_sbuff_current(_sbuff_or_marker) + fr_sbuff_shifted(_sbuff_or_marker)) - fr_sbuff_start(_sbuff_or_marker)))
957 #define fr_sbuff_len(_sbuff_or_marker) \
958 ((size_t)(fr_sbuff_end(_sbuff_or_marker) - fr_sbuff_buff(_sbuff_or_marker)))
967 #define fr_sbuff_behind(_sbuff_or_marker) \
968 (fr_sbuff_current(_sbuff_or_marker) > fr_sbuff_current((_sbuff_or_marker)->parent) ? \
969 0 : fr_sbuff_current((_sbuff_or_marker)->parent) - fr_sbuff_current(_sbuff_or_marker))
977 #define fr_sbuff_ahead(_sbuff_or_marker) \
978 (fr_sbuff_current((_sbuff_or_marker)->parent) > fr_sbuff_current(_sbuff_or_marker) ? \
979 0 : fr_sbuff_current(_sbuff_or_marker) - fr_sbuff_current((_sbuff_or_marker)->parent))
984 #define FR_SBUFF_ERROR_RETURN(_sbuff_or_marker) return fr_sbuff_error(_sbuff_or_marker)
989 #define FR_SBUFF_CHECK_REMAINING_RETURN(_sbuff, _len) \
990 if ((_len) > fr_sbuff_remaining(_sbuff)) return -((_len) - fr_sbuff_remaining(_sbuff))
992 static inline size_t _fr_sbuff_extend_lowat(fr_sbuff_extend_status_t *status, fr_sbuff_t *in,
993 size_t remaining, size_t lowat)
997 if (status && !(*status & FR_SBUFF_EXTENDABLE)) {
999 if (status) *status = FR_SBUFF_NOT_EXTENDABLE;
1003 if (remaining >= lowat) {
1004 if (status) *status = FR_SBUFF_EXTENDABLE;
1008 if (!in->extend || !(extended = in->extend(in, lowat - remaining))) goto not_extendable;
1010 if (status) *status = FR_SBUFF_EXTENDABLE_EXTENDED;
1012 return remaining + extended;
1029 #define fr_sbuff_extend_lowat(_status, _sbuff_or_marker, _lowat) \
1030 _fr_sbuff_extend_lowat(_status, \
1031 fr_sbuff_ptr(_sbuff_or_marker), \
1032 fr_sbuff_remaining(_sbuff_or_marker), _lowat)
1042 #define FR_SBUFF_EXTEND_LOWAT_OR_RETURN(_sbuff, _len) \
1044 size_t _remaining = fr_sbuff_extend_lowat(NULL, _sbuff, _len); \
1045 if (_remaining < _len) return -(_len - _remaining); \
1055 #define fr_sbuff_extend(_sbuff_or_marker) fr_sbuff_extend_lowat(NULL, _sbuff_or_marker, 1)
1069 static inline void _fr_sbuff_set_recurse(fr_sbuff_t *sbuff, char const *p)
1072 sbuff->err = NULL; /* Modifying the position of the sbuff clears the error */
1074 if (sbuff->adv_parent && sbuff->parent) _fr_sbuff_set_recurse(sbuff->parent, p);
1077 static inline ssize_t _fr_sbuff_marker_set(fr_sbuff_marker_t *m, char const *p)
1079 fr_sbuff_t *sbuff = m->parent;
1080 char *current = m->p;
1082 if (unlikely(p > sbuff->end)) return -(p - sbuff->end);
1083 if (unlikely(p < sbuff->start)) return 0;
1085 sbuff->err = NULL; /* Modifying the position of any markers clears the error, unsure if this is correct? */
1091 static inline ssize_t _fr_sbuff_set(fr_sbuff_t *sbuff, char const *p)
1095 if (unlikely(p > sbuff->end)) return -(p - sbuff->end);
1096 if (unlikely(p < sbuff->start)) return 0;
1099 _fr_sbuff_set_recurse(sbuff, p);
1118 #define fr_sbuff_set(_dst, _src) \
1120 fr_sbuff_t * : _fr_sbuff_set, \
1121 fr_sbuff_marker_t * : _fr_sbuff_marker_set \
1124 fr_sbuff_t * : fr_sbuff_current((fr_sbuff_t const *)(_src)), \
1125 fr_sbuff_t const * : fr_sbuff_current((fr_sbuff_t const *)(_src)), \
1126 fr_sbuff_marker_t * : fr_sbuff_current((fr_sbuff_marker_t const *)(_src)), \
1127 fr_sbuff_marker_t const * : fr_sbuff_current((fr_sbuff_marker_t const *)(_src)), \
1128 char const * : (char const *)(_src), \
1129 char * : (char const *)(_src), \
1130 size_t : (fr_sbuff_start(_dst) + (uintptr_t)(_src)) \
1139 #define FR_SBUFF_SET_RETURN(_dst, _src) return fr_sbuff_set(_dst, _src)
1150 #define fr_sbuff_advance(_sbuff_or_marker, _len) fr_sbuff_set(_sbuff_or_marker, (fr_sbuff_current(_sbuff_or_marker) + (_len)))
1151 #define FR_SBUFF_ADVANCE_RETURN(_sbuff, _len) FR_SBUFF_RETURN(fr_sbuff_advance, _sbuff, _len)
1156 static inline void fr_sbuff_set_to_start(fr_sbuff_t *sbuff)
1158 _fr_sbuff_set_recurse(sbuff, sbuff->start);
1164 static inline void fr_sbuff_set_to_end(fr_sbuff_t *sbuff)
1166 _fr_sbuff_set_recurse(sbuff, sbuff->end);
1190 static inline char *fr_sbuff_marker(fr_sbuff_marker_t *m, fr_sbuff_t *sbuff)
1192 *m = (fr_sbuff_marker_t){
1193 .next = sbuff->m, /* Link into the head */
1194 .p = sbuff->p, /* Set the current position in the sbuff */
1195 .parent = sbuff /* Record which sbuff this marker was associated with */
1220 static inline char *fr_sbuff_marker_update_end(fr_sbuff_marker_t *m, size_t max)
1222 fr_sbuff_t *sbuff = m->parent;
1223 size_t used = fr_sbuff_used_total(sbuff);
1225 m->p = (((max) - (used)) > fr_sbuff_remaining(sbuff) ?
1226 fr_sbuff_end(sbuff) :
1227 fr_sbuff_current(sbuff) + ((max) - (used)));
1241 static inline void fr_sbuff_marker_release(fr_sbuff_marker_t *m)
1243 m->parent->m = m->next;
1246 memset(m, 0, sizeof(*m)); /* Use after release */
1262 static inline size_t fr_sbuff_marker_release_behind(fr_sbuff_marker_t *m)
1264 size_t len = fr_sbuff_behind(m);
1265 fr_sbuff_marker_release(m);
1281 static inline size_t fr_sbuff_marker_release_ahead(fr_sbuff_marker_t *m)
1283 size_t len = fr_sbuff_ahead(m);
1284 fr_sbuff_marker_release(m);
1300 static inline size_t fr_sbuff_marker_release_reset_behind(fr_sbuff_marker_t *m)
1302 size_t len = fr_sbuff_behind(m);
1303 fr_sbuff_set(m->parent, m);
1304 fr_sbuff_marker_release(m);
1320 static inline size_t fr_sbuff_marker_release_reset_ahead(fr_sbuff_marker_t *m)
1322 size_t len = fr_sbuff_ahead(m);
1323 fr_sbuff_set(m->parent, m);
1324 fr_sbuff_marker_release(m);
1335 size_t _fr_sbuff_move_sbuff_to_sbuff(fr_sbuff_t *out, fr_sbuff_t *in, size_t len);
1337 size_t _fr_sbuff_move_marker_to_sbuff(fr_sbuff_t *out, fr_sbuff_marker_t *in, size_t len);
1339 size_t _fr_sbuff_move_marker_to_marker(fr_sbuff_marker_t *out, fr_sbuff_marker_t *in, size_t len);
1341 size_t _fr_sbuff_move_sbuff_to_marker(fr_sbuff_marker_t *out, fr_sbuff_t *in, size_t len);
1350 #define fr_sbuff_move(_out, _in, _len) \
1354 fr_sbuff_t * : _fr_sbuff_move_sbuff_to_sbuff((fr_sbuff_t *)_out, (fr_sbuff_t *)_in, _len), \
1355 fr_sbuff_marker_t * : _fr_sbuff_move_marker_to_sbuff((fr_sbuff_t *)_out, (fr_sbuff_marker_t *)_in, _len) \
1357 fr_sbuff_marker_t * : \
1359 fr_sbuff_t * : _fr_sbuff_move_sbuff_to_marker((fr_sbuff_marker_t *)_out, (fr_sbuff_t *)_in, _len), \
1360 fr_sbuff_marker_t * : _fr_sbuff_move_marker_to_marker((fr_sbuff_marker_t *)_out, (fr_sbuff_marker_t *)_in, _len) \
1371 #define fr_sbuff_in_char(_sbuff, ...) fr_sbuff_in_bstrncpy(_sbuff, ((char []){ __VA_ARGS__ }), sizeof((char []){ __VA_ARGS__ }))
1372 #define FR_SBUFF_IN_CHAR_RETURN(_sbuff, ...) FR_SBUFF_RETURN(fr_sbuff_in_bstrncpy, _sbuff, ((char []){ __VA_ARGS__ }), sizeof((char []){ __VA_ARGS__ }))
1374 ssize_t fr_sbuff_in_strcpy(fr_sbuff_t *sbuff, char const *str);
1375 #define FR_SBUFF_IN_STRCPY_RETURN(...) FR_SBUFF_RETURN(fr_sbuff_in_strcpy, ##__VA_ARGS__)
1377 ssize_t fr_sbuff_in_bstrncpy(fr_sbuff_t *sbuff, char const *str, size_t len);
1378 #define FR_SBUFF_IN_BSTRNCPY_RETURN(...) FR_SBUFF_RETURN(fr_sbuff_in_bstrncpy, ##__VA_ARGS__)
1380 #define fr_sbuff_in_strcpy_literal(_sbuff, _str) fr_sbuff_in_bstrncpy(_sbuff, _str, sizeof(_str) - 1)
1381 #define FR_SBUFF_IN_STRCPY_LITERAL_RETURN(_sbuff, _str) FR_SBUFF_RETURN(fr_sbuff_in_bstrncpy, _sbuff, _str, sizeof(_str) - 1)
1383 ssize_t fr_sbuff_in_bstrcpy_buffer(fr_sbuff_t *sbuff, char const *str);
1384 #define FR_SBUFF_IN_BSTRCPY_BUFFER_RETURN(...) FR_SBUFF_RETURN(fr_sbuff_in_bstrcpy_buffer, ##__VA_ARGS__)
1386 ssize_t fr_sbuff_in_vsprintf(fr_sbuff_t *sbuff, char const *fmt, va_list ap);
1387 #define FR_SBUFF_IN_VSPRINTF_RETURN(...) FR_SBUFF_RETURN(fr_sbuff_in_vsprintf, ##__VA_ARGS__)
1389 ssize_t fr_sbuff_in_sprintf(fr_sbuff_t *sbuff, char const *fmt, ...);
1390 #define FR_SBUFF_IN_SPRINTF_RETURN(...) FR_SBUFF_RETURN(fr_sbuff_in_sprintf, ##__VA_ARGS__)
1392 ssize_t fr_sbuff_in_escape(fr_sbuff_t *sbuff, char const *in, size_t inlen, fr_sbuff_escape_rules_t const *e_rules);
1393 #define FR_SBUFF_IN_ESCAPE_RETURN(...) FR_SBUFF_RETURN(fr_sbuff_in_escape, ##__VA_ARGS__)
1395 ssize_t fr_sbuff_in_escape_buffer(fr_sbuff_t *sbuff, char const *in, fr_sbuff_escape_rules_t const *e_rules);
1396 #define FR_SBUFF_IN_ESCAPE_BUFFER_RETURN(...) FR_SBUFF_RETURN(fr_sbuff_in_escape_buffer, ##__VA_ARGS__)
1406 #define fr_sbuff_in_table_str(_slen, _sbuff, _table, _number, _def) \
1407 _slen = fr_sbuff_in_strcpy(_sbuff, fr_table_str_by_value(_table, _number, _def))
1408 #define FR_SBUFF_IN_TABLE_STR_RETURN(_sbuff, _table, _number, _def) \
1411 fr_sbuff_in_table_str(_slen, _sbuff, _table, _number, _def); \
1412 if (_slen < 0) return _slen; \
1426 static inline void fr_sbuff_allowed_merge(bool out[static UINT8_MAX + 1], bool const in[static UINT8_MAX + 1])
1428 for (size_t i = 0; i <= UINT8_MAX; i++) out[i] = out[i] || in[i];
1431 fr_sbuff_term_t *fr_sbuff_terminals_amerge(TALLOC_CTX *ctx,
1432 fr_sbuff_term_t const *a, fr_sbuff_term_t const *b);
1434 size_t fr_sbuff_out_bstrncpy(fr_sbuff_t *out, fr_sbuff_t *in, size_t len);
1436 ssize_t fr_sbuff_out_bstrncpy_exact(fr_sbuff_t *out, fr_sbuff_t *in, size_t len);
1438 size_t fr_sbuff_out_bstrncpy_allowed(fr_sbuff_t *out, fr_sbuff_t *in, size_t len,
1439 bool const allowed[static UINT8_MAX + 1]);
1441 size_t fr_sbuff_out_bstrncpy_until(fr_sbuff_t *out, fr_sbuff_t *in, size_t len,
1442 fr_sbuff_term_t const *tt,
1443 fr_sbuff_unescape_rules_t const *u_rules);
1445 size_t fr_sbuff_out_unescape_until(fr_sbuff_t *out, fr_sbuff_t *in, size_t len,
1446 fr_sbuff_term_t const *tt,
1447 fr_sbuff_unescape_rules_t const *u_rules);
1458 #define fr_sbuff_out_by_longest_prefix(_match_len, _out, _table, _sbuff, _def) \
1460 size_t _match_len_tmp; \
1461 fr_sbuff_extend_lowat(NULL, _sbuff, fr_table_max_needle_len(_table)); \
1462 *(_out) = fr_table_value_by_longest_prefix(&_match_len_tmp, _table, \
1463 fr_sbuff_current(_sbuff), fr_sbuff_remaining(_sbuff), \
1465 (void) fr_sbuff_advance(_sbuff, _match_len_tmp); /* can't fail */ \
1466 *(_match_len) = _match_len_tmp; \
1476 #define SBUFF_OUT_TALLOC_ERR_FUNC_DEF(_func, _in, _len, ...) \
1479 fr_sbuff_uctx_talloc_t tctx; \
1480 fr_sbuff_parse_error_t err; \
1481 fr_slen_t slen = -1; \
1482 if (unlikely(fr_sbuff_init_talloc(ctx, &sbuff, &tctx, \
1483 ((_len) != SIZE_MAX) ? (_len) : 1024, \
1484 ((_len) != SIZE_MAX) ? (_len) : SIZE_MAX) == NULL)) { \
1486 TALLOC_FREE(sbuff.buff); \
1490 slen = _func(&err, &sbuff, _in, _len, ##__VA_ARGS__); \
1491 if (slen < 0) goto error; \
1492 if (unlikely(fr_sbuff_trim_talloc(&sbuff, SIZE_MAX) < 0)) { \
1496 *out = sbuff.buff; \
1507 #define SBUFF_OUT_TALLOC_FUNC_DEF(_func, _in, _len, ...) \
1510 fr_sbuff_uctx_talloc_t tctx; \
1511 fr_slen_t slen = -1; \
1512 if (unlikely(fr_sbuff_init_talloc(ctx, &sbuff, &tctx, \
1513 ((_len) != SIZE_MAX) ? (_len) : 1024, \
1514 ((_len) != SIZE_MAX) ? (_len) : SIZE_MAX) == NULL)) { \
1516 TALLOC_FREE(sbuff.buff); \
1520 slen = _func(&sbuff, _in, _len, ##__VA_ARGS__); \
1521 if (slen < 0) goto error; \
1522 if (unlikely(fr_sbuff_trim_talloc(&sbuff, SIZE_MAX) < 0)) { \
1526 *out = sbuff.buff; \
1535 #define SBUFF_OUT_TALLOC_FUNC_NO_LEN_DEF(_func, ...) \
1538 fr_sbuff_uctx_talloc_t tctx; \
1539 fr_slen_t slen = -1; \
1540 if (unlikely(fr_sbuff_init_talloc(ctx, &sbuff, &tctx, 0, SIZE_MAX) == NULL)) { \
1542 TALLOC_FREE(sbuff.buff); \
1546 slen = _func(&sbuff, ##__VA_ARGS__); \
1547 if (slen < 0) goto error; \
1548 if (unlikely(fr_sbuff_trim_talloc(&sbuff, SIZE_MAX) < 0)) { \
1552 *out = sbuff.buff; \
1556 static inline fr_slen_t fr_sbuff_out_abstrncpy(TALLOC_CTX *ctx, char **out, fr_sbuff_t *in, size_t len)
1557 SBUFF_OUT_TALLOC_FUNC_DEF(fr_sbuff_out_bstrncpy, in, len)
1559 static inline fr_slen_t fr_sbuff_out_abstrncpy_exact(TALLOC_CTX *ctx, char **out, fr_sbuff_t *in, size_t len)
1560 SBUFF_OUT_TALLOC_FUNC_DEF(fr_sbuff_out_bstrncpy_exact, in, len)
1562 static inline fr_slen_t fr_sbuff_out_abstrncpy_allowed(TALLOC_CTX *ctx, char **out, fr_sbuff_t *in, size_t len,
1563 bool const allowed[static UINT8_MAX + 1])
1564 SBUFF_OUT_TALLOC_FUNC_DEF(fr_sbuff_out_bstrncpy_allowed, in, len, allowed)
1566 static inline fr_slen_t fr_sbuff_out_abstrncpy_until(TALLOC_CTX *ctx, char **out, fr_sbuff_t *in, size_t len,
1567 fr_sbuff_term_t const *tt,
1568 fr_sbuff_unescape_rules_t const *u_rules)
1569 SBUFF_OUT_TALLOC_FUNC_DEF(fr_sbuff_out_bstrncpy_until, in, len, tt, u_rules)
1571 static inline fr_slen_t fr_sbuff_out_aunescape_until(TALLOC_CTX *ctx, char **out, fr_sbuff_t *in, size_t len,
1572 fr_sbuff_term_t const *tt,
1573 fr_sbuff_unescape_rules_t const *u_rules)
1574 SBUFF_OUT_TALLOC_FUNC_DEF(fr_sbuff_out_unescape_until, in, len, tt, u_rules)
1583 fr_slen_t fr_sbuff_out_bool(bool *out, fr_sbuff_t *in);
1585 fr_slen_t fr_sbuff_out_int8(fr_sbuff_parse_error_t *err, int8_t *out, fr_sbuff_t *sbuff, bool no_trailing);
1586 fr_slen_t fr_sbuff_out_int16(fr_sbuff_parse_error_t *err, int16_t *out, fr_sbuff_t *sbuff, bool no_trailing);
1587 fr_slen_t fr_sbuff_out_int32(fr_sbuff_parse_error_t *err, int32_t *out, fr_sbuff_t *sbuff, bool no_trailing);
1588 fr_slen_t fr_sbuff_out_int64(fr_sbuff_parse_error_t *err, int64_t *out, fr_sbuff_t *sbuff, bool no_trailing);
1589 fr_slen_t fr_sbuff_out_ssize(fr_sbuff_parse_error_t *err, ssize_t *out, fr_sbuff_t *sbuff, bool no_trailing);
1590 fr_slen_t fr_sbuff_out_uint8(fr_sbuff_parse_error_t *err, uint8_t *out, fr_sbuff_t *sbuff, bool no_trailing);
1591 fr_slen_t fr_sbuff_out_uint16(fr_sbuff_parse_error_t *err, uint16_t *out, fr_sbuff_t *sbuff, bool no_trailing);
1592 fr_slen_t fr_sbuff_out_uint32(fr_sbuff_parse_error_t *err, uint32_t *out, fr_sbuff_t *sbuff, bool no_trailing);
1593 fr_slen_t fr_sbuff_out_uint64(fr_sbuff_parse_error_t *err, uint64_t *out, fr_sbuff_t *sbuff, bool no_trailing);
1594 fr_slen_t fr_sbuff_out_size(fr_sbuff_parse_error_t *err, size_t *out, fr_sbuff_t *sbuff, bool no_trailing);
1596 fr_slen_t fr_sbuff_out_uint8_dec(fr_sbuff_parse_error_t *err, uint8_t *out, fr_sbuff_t *sbuff, bool no_trailing);
1597 fr_slen_t fr_sbuff_out_uint16_dec(fr_sbuff_parse_error_t *err, uint16_t *out, fr_sbuff_t *sbuff, bool no_trailing);
1598 fr_slen_t fr_sbuff_out_uint32_dec(fr_sbuff_parse_error_t *err, uint32_t *out, fr_sbuff_t *sbuff, bool no_trailing);
1599 fr_slen_t fr_sbuff_out_uint64_dec(fr_sbuff_parse_error_t *err, uint64_t *out, fr_sbuff_t *sbuff, bool no_trailing);
1600 fr_slen_t fr_sbuff_out_size_dec(fr_sbuff_parse_error_t *err, size_t *out, fr_sbuff_t *sbuff, bool no_trailing);
1602 fr_slen_t fr_sbuff_out_uint8_oct(fr_sbuff_parse_error_t *err, uint8_t *out, fr_sbuff_t *sbuff, bool no_trailing);
1603 fr_slen_t fr_sbuff_out_uint16_oct(fr_sbuff_parse_error_t *err, uint16_t *out, fr_sbuff_t *sbuff, bool no_trailing);
1604 fr_slen_t fr_sbuff_out_uint32_oct(fr_sbuff_parse_error_t *err, uint32_t *out, fr_sbuff_t *sbuff, bool no_trailing);
1605 fr_slen_t fr_sbuff_out_uint64_oct(fr_sbuff_parse_error_t *err, uint64_t *out, fr_sbuff_t *sbuff, bool no_trailing);
1606 fr_slen_t fr_sbuff_out_size_oct(fr_sbuff_parse_error_t *err, size_t *out, fr_sbuff_t *sbuff, bool no_trailing);
1608 fr_slen_t fr_sbuff_out_uint8_hex(fr_sbuff_parse_error_t *err, uint8_t *out, fr_sbuff_t *sbuff, bool no_trailing);
1609 fr_slen_t fr_sbuff_out_uint16_hex(fr_sbuff_parse_error_t *err, uint16_t *out, fr_sbuff_t *sbuff, bool no_trailing);
1610 fr_slen_t fr_sbuff_out_uint32_hex(fr_sbuff_parse_error_t *err, uint32_t *out, fr_sbuff_t *sbuff, bool no_trailing);
1611 fr_slen_t fr_sbuff_out_uint64_hex(fr_sbuff_parse_error_t *err, uint64_t *out, fr_sbuff_t *sbuff, bool no_trailing);
1612 fr_slen_t fr_sbuff_out_size_hex(fr_sbuff_parse_error_t *err, size_t *out, fr_sbuff_t *sbuff, bool no_trailing);
1614 fr_slen_t fr_sbuff_out_float32(fr_sbuff_parse_error_t *err, float *out, fr_sbuff_t *sbuff, bool no_trailing);
1615 fr_slen_t fr_sbuff_out_float64(fr_sbuff_parse_error_t *err, double *out, fr_sbuff_t *sbuff, bool no_trailing);
1617 #ifndef SIZE_SAME_AS_UINT64
1618 # define _fr_sbuff_out_size(_err, _out, _in) size_t * : fr_sbuff_out_size(_err, (size_t *)_out, _in, true),
1620 # define _fr_sbuff_out_size(_err, _out, _in)
1623 #ifndef SSIZE_SAME_AS_INT64
1624 # define _fr_sbuff_out_ssize(_err, _out, _in) ssize_t * : fr_sbuff_out_ssize(_err, (ssize_t *)_out, _in, true),
1626 # define _fr_sbuff_out_ssize(_err, _out, _in)
1637 #define fr_sbuff_out(_err, _out, _in) \
1639 bool * : fr_sbuff_out_bool((bool *)_out, _in), \
1640 int8_t * : fr_sbuff_out_int8(_err, (int8_t *)_out, _in, true), \
1641 int16_t * : fr_sbuff_out_int16(_err, (int16_t *)_out, _in, true), \
1642 int32_t * : fr_sbuff_out_int32(_err, (int32_t *)_out, _in, true), \
1643 int64_t * : fr_sbuff_out_int64(_err, (int64_t *)_out, _in, true), \
1644 _fr_sbuff_out_ssize(_err, _out, _in) \
1645 uint8_t * : fr_sbuff_out_uint8(_err, (uint8_t *)_out, _in, true), \
1646 uint16_t * : fr_sbuff_out_uint16(_err, (uint16_t *)_out, _in, true), \
1647 uint32_t * : fr_sbuff_out_uint32(_err, (uint32_t *)_out, _in, true), \
1648 uint64_t * : fr_sbuff_out_uint64(_err, (uint64_t *)_out, _in, true), \
1649 _fr_sbuff_out_size(_err, _out, _in) \
1650 float * : fr_sbuff_out_float32(_err, (float *)_out, _in, true), \
1651 double * : fr_sbuff_out_float64(_err, (double *)_out, _in, true) \
1663 size_t fr_sbuff_adv_past_str(fr_sbuff_t *sbuff, char const *needle, size_t need_len);
1665 #define fr_sbuff_adv_past_str_literal(_sbuff, _needle) fr_sbuff_adv_past_str(_sbuff, _needle, sizeof(_needle) - 1)
1667 size_t fr_sbuff_adv_past_strcase(fr_sbuff_t *sbuff, char const *needle, size_t need_len);
1669 #define fr_sbuff_adv_past_strcase_literal(_sbuff, _needle) fr_sbuff_adv_past_strcase(_sbuff, _needle, sizeof(_needle) - 1)
1671 size_t fr_sbuff_adv_past_allowed(fr_sbuff_t *sbuff, size_t len,
1672 bool const allowed[static UINT8_MAX + 1], fr_sbuff_term_t const *tt);
1674 #define fr_sbuff_adv_past_zeros(_sbuff, _len, _tt) fr_sbuff_adv_past_allowed(_sbuff, _len, sbuff_char_class_zero, _tt)
1676 #define fr_sbuff_adv_past_whitespace(_sbuff, _len, _tt) fr_sbuff_adv_past_allowed(_sbuff, _len, sbuff_char_whitespace, _tt)
1678 #define fr_sbuff_adv_past_blank(_sbuff, _len, _tt) fr_sbuff_adv_past_allowed(_sbuff, _len, sbuff_char_blank, _tt)
1680 size_t fr_sbuff_adv_until(fr_sbuff_t *sbuff, size_t len, fr_sbuff_term_t const *tt, char escape_chr);
1682 char *fr_sbuff_adv_to_chr_utf8(fr_sbuff_t *in, size_t len, char const *chr);
1684 char *fr_sbuff_adv_to_chr(fr_sbuff_t *in, size_t len, char c);
1686 char *fr_sbuff_adv_to_str(fr_sbuff_t *sbuff, size_t len, char const *needle, size_t needle_len);
1688 #define fr_sbuff_adv_to_str_literal(_sbuff, _len, _needle) fr_sbuff_adv_to_str(_sbuff, _len, _needle, sizeof(_needle) - 1)
1690 char *fr_sbuff_adv_to_strcase(fr_sbuff_t *sbuff, size_t len, char const *needle, size_t needle_len);
1692 #define fr_sbuff_adv_to_strcase_literal(_sbuff, _len, _needle) fr_sbuff_adv_to_strcase(_sbuff, _len, _needle, sizeof(_needle) - 1)
1694 bool fr_sbuff_next_if_char(fr_sbuff_t *sbuff, char c);
1696 bool fr_sbuff_next_unless_char(fr_sbuff_t *sbuff, char c);
1701 static inline char fr_sbuff_next(fr_sbuff_t *sbuff)
1703 if (!fr_sbuff_extend(sbuff)) return '\0';
1704 return fr_sbuff_advance(sbuff, 1);
1712 size_t fr_sbuff_trim(fr_sbuff_t *sbuff, bool const to_trim[static UINT8_MAX + 1]);
1721 bool fr_sbuff_is_terminal(fr_sbuff_t *in, fr_sbuff_term_t const *tt);
1723 static inline bool fr_sbuff_is_in_charset(fr_sbuff_t *sbuff, bool const chars[static UINT8_MAX + 1])
1725 if (!fr_sbuff_extend(sbuff)) return false;
1726 return chars[(uint8_t)*sbuff->p];
1729 static inline bool fr_sbuff_is_str(fr_sbuff_t *sbuff, char const *str, size_t len)
1731 if (len == SIZE_MAX) len = strlen(str);
1732 if (!fr_sbuff_extend_lowat(NULL, sbuff, len)) return false;
1733 return memcmp(sbuff->p, str, len) == 0;
1735 #define fr_sbuff_is_str_literal(_sbuff, _str) fr_sbuff_is_str(_sbuff, _str, sizeof(_str) - 1)
1737 static inline bool _fr_sbuff_is_char(fr_sbuff_t *sbuff, char *p, char c)
1739 if (!fr_sbuff_extend(sbuff)) return false;
1742 static inline bool _fr_marker_is_char(fr_sbuff_marker_t *marker, char *p, char c)
1744 if (!fr_sbuff_extend(marker)) return false;
1747 #define fr_sbuff_is_char(_sbuff_or_marker, _c) \
1748 _Generic((_sbuff_or_marker), \
1749 fr_sbuff_t * : _fr_sbuff_is_char((fr_sbuff_t *)(_sbuff_or_marker), fr_sbuff_current(_sbuff_or_marker), _c), \
1750 fr_sbuff_marker_t * : _fr_marker_is_char((fr_sbuff_marker_t *)(_sbuff_or_marker), fr_sbuff_current(_sbuff_or_marker), _c) \
1753 #define SBUFF_IS_FUNC(_name, _test) \
1754 static inline bool _fr_sbuff_is_ ## _name(fr_sbuff_t *sbuff, char *p) \
1756 if (!fr_sbuff_extend(sbuff)) return false; \
1759 static inline bool _fr_marker_is_ ## _name(fr_sbuff_marker_t *marker, char *p) \
1761 if (!fr_sbuff_extend(marker)) return false; \
1765 #define SBUFF_IS_GENERIC(_sbuff_or_marker, _name) \
1766 _Generic((_sbuff_or_marker), \
1767 fr_sbuff_t * : _fr_sbuff_is_ ## _name((fr_sbuff_t *)(_sbuff_or_marker), fr_sbuff_current(_sbuff_or_marker)), \
1768 fr_sbuff_marker_t * : _fr_marker_is_ ## _name((fr_sbuff_marker_t *)(_sbuff_or_marker), fr_sbuff_current(_sbuff_or_marker)) \
1771 SBUFF_IS_FUNC(digit, isdigit((uint8_t) *p))
1772 #define fr_sbuff_is_digit(_sbuff_or_marker) \
1773 SBUFF_IS_GENERIC(_sbuff_or_marker, digit)
1775 SBUFF_IS_FUNC(upper, isupper((uint8_t) *p))
1776 #define fr_sbuff_is_upper(_sbuff_or_marker) \
1777 SBUFF_IS_GENERIC(_sbuff_or_marker, upper)
1779 SBUFF_IS_FUNC(lower, islower((uint8_t) *p))
1780 #define fr_sbuff_is_lower(_sbuff_or_marker) \
1781 SBUFF_IS_GENERIC(_sbuff_or_marker, lower)
1783 SBUFF_IS_FUNC(alpha, isalpha((uint8_t) *p))
1784 #define fr_sbuff_is_alpha(_sbuff_or_marker) \
1785 SBUFF_IS_GENERIC(_sbuff_or_marker, alpha)
1787 SBUFF_IS_FUNC(alnum, isalnum((uint8_t) *p))
1788 #define fr_sbuff_is_alnum(_sbuff_or_marker) \
1789 SBUFF_IS_GENERIC(_sbuff_or_marker, alnum)
1791 SBUFF_IS_FUNC(space, isspace((uint8_t) *p))
1792 #define fr_sbuff_is_space(_sbuff_or_marker) \
1793 SBUFF_IS_GENERIC(_sbuff_or_marker, space)
1795 SBUFF_IS_FUNC(hex, isxdigit((uint8_t) *p))
1796 #define fr_sbuff_is_hex(_sbuff_or_marker) \
1797 SBUFF_IS_GENERIC(_sbuff_or_marker, hex)
1801 void fr_sbuff_unescape_debug(fr_sbuff_unescape_rules_t const *escapes);
1803 void fr_sbuff_terminal_debug(fr_sbuff_term_t const *tt);
1805 void fr_sbuff_parse_rules_debug(fr_sbuff_parse_rules_t const *p_rules);
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]
size_t(* fr_sbuff_extend_t)(fr_sbuff_t *sbuff, size_t req_extension)
TALLOC_CTX * ctx
Context to alloc new buffers in.
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.
#define FR_SBUFF_FLAG_EXTENDABLE
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.
#define FR_SBUFF_FLAG_EXTEND_ERROR
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.
#define FR_SBUFF_FLAG_EXTENDED
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.
FILE * file
FILE * we're reading from.
size_t max
Maximum number of bytes to read.
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)