26#include <freeradius-devel/util/sbuff.h>
28#define TEST_SBUFF_LEN(_sbuff, _num) \
31 _len = talloc_array_length((_sbuff)->buff); \
32 TEST_CHECK(_len == (size_t)_num); \
33 TEST_MSG("Expected length : %zu", (size_t)_num); \
34 TEST_MSG("Got length : %zu", _len); \
37#define TEST_SBUFF_USED(_sbuff, _num) \
40 _len = fr_sbuff_used(_sbuff); \
41 TEST_CHECK(_len == (size_t)_num); \
42 TEST_MSG("Expected length : %zu", (size_t)_num); \
43 TEST_MSG("Got length : %zu", _len); \
48 char const in[] =
"i am a test string";
75 char const in[] =
"i am a test string";
89 fr_sbuff_marker(&marker, &sbuff);
104 char const in[] =
"i am a test string";
105 char const in_long[] =
"i am a longer test string";
106 char out[18 + 1] =
"";
130 TEST_CASE(
"Copy would overrun output (and SIZE_MAX special value)");
138 fr_sbuff_set_to_start(&sbuff);
146 fr_sbuff_set_to_start(&sbuff);
156 char const in[] =
"i am a test string";
157 char const in_long[] =
"i am a longer test string";
158 char out[18 + 1] =
"";
182 TEST_CASE(
"Copy would overrun output (and SIZE_MAX special value)");
190 fr_sbuff_set_to_start(&sbuff);
198 fr_sbuff_set_to_start(&sbuff);
207 [
'a'] =
true, [
'b'] =
true, [
'c'] =
true, [
'd'] =
true, [
'e'] =
true,
208 [
'f'] =
true, [
'g'] =
true, [
'h'] =
true, [
'i'] =
true, [
'j'] =
true,
209 [
'k'] =
true, [
'l'] =
true, [
'm'] =
true, [
'n'] =
true, [
'o'] =
true,
210 [
'p'] =
true, [
'q'] =
true, [
'r'] =
true, [
's'] =
true, [
't'] =
true,
211 [
'u'] =
true, [
'v'] =
true, [
'w'] =
true, [
'x'] =
true, [
'y'] =
true,
212 [
'z'] =
true, [
' '] =
true
216 [
'a'] =
true, [
'b'] =
true, [
'c'] =
true, [
'd'] =
true, [
'e'] =
true,
217 [
'f'] =
true, [
'g'] =
true, [
'h'] =
true, [
'i'] =
true, [
'j'] =
true,
218 [
'k'] =
true, [
'l'] =
true, [
'm'] =
true, [
'n'] =
true, [
'o'] =
true,
219 [
'p'] =
true, [
'q'] =
true, [
'r'] =
true, [
's'] =
true, [
't'] =
false,
220 [
'u'] =
true, [
'v'] =
true, [
'w'] =
true, [
'x'] =
true, [
'y'] =
true,
221 [
'z'] =
true, [
' '] =
true
226 char const in[] =
"i am a test string";
227 char const in_long[] =
"i am a longer test string";
228 char out[18 + 1] =
"";
257 TEST_CASE(
"Copy would overrun output (and SIZE_MAX special value)");
265 fr_sbuff_set_to_start(&sbuff);
273 fr_sbuff_set_to_start(&sbuff);
284 fr_sbuff_set_to_start(&sbuff);
290 TEST_CASE(
"Copy until first t with length constraint (same len as token)");
291 fr_sbuff_set_to_start(&sbuff);
297 TEST_CASE(
"Copy until first t with length constraint (one shorter than token)");
298 fr_sbuff_set_to_start(&sbuff);
304 TEST_CASE(
"Zero length token (should still be terminated)");
305 fr_sbuff_set_to_start(&sbuff);
314 char const in[] =
"i am a test string";
315 char const in_long[] =
"i am a longer test string";
346 fr_sbuff_set_to_start(&sbuff);
353 TEST_CASE(
"Copy would overrun output (and SIZE_MAX special value)");
361 fr_sbuff_set_to_start(&sbuff);
369 fr_sbuff_set_to_start(&sbuff);
380 fr_sbuff_set_to_start(&sbuff);
385 TEST_CASE(
"Copy until first t with length constraint (same len as token)");
386 fr_sbuff_set_to_start(&sbuff);
391 TEST_CASE(
"Copy until first t with length constraint (one shorter than token)");
392 fr_sbuff_set_to_start(&sbuff);
397 TEST_CASE(
"Zero length token (should still be terminated)");
398 fr_sbuff_set_to_start(&sbuff);
406 char const in[] =
"i am a test string";
407 char const in_long[] =
"i am a longer test string";
408 char const in_escapes[] =
"i am a |t|est strin|g";
409 char const in_escapes_seq[] =
"i |x|0am a |t|est strin|g|x20|040";
410 char out[18 + 1] =
"";
411 char escape_out[20 + 1];
422 .subs = { [
'g'] =
'g', [
'|'] =
'|' }
426 .
chr =
'|', .subs = { [
'g'] =
'h', [
'|'] =
'|' }
431 .subs = { [
'g'] =
'h', [
'|'] =
'|' },
437 .subs = { [
'g'] =
'h', [
'|'] =
'|' },
443 .subs = { [
'g'] =
'h', [
'|'] =
'|' },
472 TEST_CASE(
"Copy would overrun output (and SIZE_MAX special value)");
480 fr_sbuff_set_to_start(&sbuff);
488 fr_sbuff_set_to_start(&sbuff);
499 fr_sbuff_set_to_start(&sbuff);
505 TEST_CASE(
"Copy until first t with length constraint (same len as token)");
506 fr_sbuff_set_to_start(&sbuff);
512 TEST_CASE(
"Copy until first t with length constraint (one shorter than token)");
513 fr_sbuff_set_to_start(&sbuff);
519 TEST_CASE(
"Zero length token (should still be terminated)");
520 fr_sbuff_set_to_start(&sbuff);
529 TEST_CASE(
"Escape with substitution to same char");
537 TEST_CASE(
"Escape with substitution to different char");
546 char tmp_out[24 + 1];
548 TEST_CASE(
"Escape with hex substitutions (insufficient output space)");
558 char tmp_out[25 + 1];
560 TEST_CASE(
"Escape with hex substitutions (sufficient output space)");
570 char tmp_out[28 + 1];
572 TEST_CASE(
"Escape with oct substitutions (insufficient output space)");
582 char tmp_out[29 + 1];
584 TEST_CASE(
"Escape with oct substitutions (sufficient output space)");
594 char tmp_out[26 + 1];
596 TEST_CASE(
"Escape with hex and oct substitutions (sufficient output space)");
607 char const in_escapes_collapse[] =
"||";
610 fr_sbuff_init_in(&sbuff, in_escapes_collapse,
sizeof(in_escapes_collapse) - 1);
612 &sbuff, SIZE_MAX, NULL, &pipe_rules);
619 char in_escapes_collapse[] =
"||foo||";
621 TEST_CASE(
"Collapse double escapes overlapping");
622 fr_sbuff_init_in(&sbuff, in_escapes_collapse,
sizeof(in_escapes_collapse) - 1);
624 &sbuff, SIZE_MAX, NULL, &pipe_rules);
631 char tmp_out[30 + 1];
650 char const in_escapes_unit[] =
659 char const expected[] = {
660 '0',
'x',
'0',
'1',
'\001',
661 '0',
'x',
'0',
'7',
'\007',
662 '0',
'x',
'0',
'A',
'\n',
663 '0',
'x',
'0',
'D',
'\r',
669 TEST_CASE(
"Check unit test test strings");
672 NULL, &double_quote_rules);
684 char const in_zero[] =
"";
686 len = fr_sbuff_out_aunescape_until(NULL, &
buff, &
FR_SBUFF_IN(in_zero,
sizeof(in_zero) - 1), SIZE_MAX,
689 talloc_get_type_abort(
buff,
char);
708 char out[24 + 1] =
"";
712 char const in_hex[] =
"|x41|x42|x43";
713 char const in_oct[] =
"|101|102|103";
717 .subs = { [
'|'] =
'|' },
723 .subs = { [
'|'] =
'|' },
734 TEST_CASE(
"Hex, limit falls on the end of an escape sequence");
741 TEST_CASE(
"Hex, limit falls on the escape char");
751 TEST_CASE(
"Hex, limit leaves no room for either hex digit");
762 TEST_CASE(
"Hex, limit leaves room for only one hex digit");
777 TEST_CASE(
"Octal, limit falls on the end of an escape sequence");
787 TEST_CASE(
"Octal, limit leaves room for only two octal digits");
801 TEST_CASE(
"No limit is ever exceeded, hex");
802 for (
size_t i = 0; i <=
sizeof(in_hex); i++) {
810 TEST_CASE(
"No limit is ever exceeded, octal");
811 for (
size_t i = 0; i <=
sizeof(in_oct); i++) {
822 char const in[] =
"foo, bar, baz```";
857 char const in[] =
"foo, bar";
901 char const in[] =
"abc}xyz";
930 size_t const len = 4;
940 memcpy(
buff,
"abcd", len);
1012 for (i = 0; i < result->
len; i++) {
1021 char const *
in =
"i am a test string";
1022 char out[18 + 1] =
"";
1028 TEST_CASE(
"Copy 5 bytes to out - no advance");
1042 TEST_CHECK(fr_sbuff_init_talloc(NULL, &sbuff, &tctx, 32, 50) == &sbuff);
1051 TEST_CASE(
"Print string - Should realloc to init");
1061 TEST_CASE(
"Print string - Should realloc to init");
1071 TEST_CASE(
"Print string - Should realloc to double buffer len");
1077 TEST_CASE(
"Print string - Should only add a single char, should not extend the buffer");
1083 TEST_CASE(
"Print string - Use all available buffer data");
1089 TEST_CASE(
"Print string - Add single char, should trigger doubling constrained by max");
1095 TEST_CASE(
"Print string - Add data to take us up to max");
1101 TEST_CASE(
"Print string - Add single char, should fail");
1107 TEST_CASE(
"Trim to strlen (should be noop)");
1122 TEST_CHECK(fr_sbuff_init_talloc(NULL, &sbuff, &tctx, 0, 50) == &sbuff);
1126 TEST_CASE(
"Print string - Should alloc one byte");
1132 TEST_CASE(
"Print string - Should alloc two bytes");
1138 TEST_CASE(
"Print string - Should alloc three bytes");
1153 TEST_CHECK(fr_sbuff_init_talloc(NULL, &sbuff_0, &tctx, 0, 50) == &sbuff_0);
1158 TEST_CASE(
"Check sbuff_1 has extend fields set");
1159 TEST_CHECK(sbuff_0.extend == sbuff_1.extend);
1165 TEST_CASE(
"Print string - Should alloc one byte");
1187 TEST_CHECK(fr_sbuff_init_talloc(NULL, &sbuff_0, &tctx, 0, 50) == &sbuff_0);
1191 TEST_CASE(
"Print string - Should alloc one byte");
1197 fr_sbuff_marker(&marker_0, &sbuff_0);
1198 TEST_CHECK((marker_0.p - sbuff_0.start) == 1);
1200 TEST_CASE(
"Print string - Ensure marker is updated");
1205 TEST_CHECK((marker_0.p - sbuff_0.start) == 1);
1210 fr_sbuff_marker(&marker_1, &sbuff_1);
1212 TEST_CHECK((marker_1.p - sbuff_1.start) == 0);
1213 TEST_CHECK((marker_1.p - sbuff_0.start) == 2);
1216 TEST_CASE(
"Print string - Trigger re-alloc, ensure all pointers are updated");
1221 TEST_CHECK((marker_1.p - sbuff_1.start) == 0);
1222 TEST_CHECK((marker_1.p - sbuff_0.start) == 2);
1235 TEST_CHECK(fr_sbuff_init_talloc(NULL, &sbuff, &tctx, 4, 8) == &sbuff);
1259 TEST_CASE(
"Before any shift, used() and used_total() agree");
1260 TEST_CHECK(fr_sbuff_init_talloc(NULL, &sbuff, &tctx, 8, 32) == &sbuff);
1267 TEST_CASE(
"A shift moves data out of the buffer");
1279 TEST_CASE(
"used() forgets the shifted data");
1282 TEST_CASE(
"used_total() remembers it, and is unchanged by the shift");
1286 TEST_CASE(
"used_total() stays whole across a second shift");
1297 TEST_CASE(
"used() plus shifted() equals used_total()");
1316 TEST_CASE(
"SIZE_MAX means no constraint, so the marker sits at the end");
1318 fr_sbuff_marker(&end, &sbuff);
1320 fr_sbuff_marker_release(&end);
1322 TEST_CASE(
"A budget smaller than the buffer stops the marker short");
1324 fr_sbuff_marker(&end, &sbuff);
1326 fr_sbuff_marker_release(&end);
1328 TEST_CASE(
"Data already consumed comes off the budget");
1331 fr_sbuff_marker(&end, &sbuff);
1338 fr_sbuff_marker_release(&end);
1340 TEST_CASE(
"A budget which exactly matches what was consumed leaves nothing");
1343 fr_sbuff_marker(&end, &sbuff);
1345 fr_sbuff_marker_release(&end);
1357 TEST_CASE(
"An overspent budget allows nothing more");
1360 fr_sbuff_marker(&end, &sbuff);
1363 TEST_MSG(
"marker is %zu past the current position, expected 0",
1366 fr_sbuff_marker_release(&end);
1368 TEST_CASE(
"A budget overspent by a single byte allows nothing more");
1371 fr_sbuff_marker(&end, &sbuff);
1373 fr_sbuff_marker_release(&end);
1375 TEST_CASE(
"A zero budget allows nothing, whether or not anything was used");
1377 fr_sbuff_marker(&end, &sbuff);
1379 fr_sbuff_marker_release(&end);
1383 fr_sbuff_marker(&end, &sbuff);
1385 fr_sbuff_marker_release(&end);
1392 TEST_CASE(
"Repeated updates on an overspent budget stay put");
1395 fr_sbuff_marker(&end, &sbuff);
1399 fr_sbuff_marker_release(&end);
1407 TEST_CASE(
"An overspent budget at the end of the buffer");
1410 fr_sbuff_marker(&end, &sbuff);
1414 fr_sbuff_marker_release(&end);
1443 size_t used, used_total;
1451 TEST_CASE(
"Set up a buffer which has shifted, and which has room left");
1452 TEST_CHECK(fr_sbuff_init_talloc(NULL, &sbuff, &tctx, 16, 32) == &sbuff);
1468 TEST_CASE(
"A budget between used and used_total is already overspent");
1469 fr_sbuff_marker(&end, &sbuff);
1471 TEST_MSG(
"marker is %zu past the current position, expected 0. "
1472 "Measuring the budget with fr_sbuff_used() would give 2, "
1473 "and not clamping the overspend would give %zu",
1476 fr_sbuff_marker_release(&end);
1482 TEST_CASE(
"A budget larger than used_total leaves used_total's worth of room");
1489 fr_sbuff_marker(&end, &sbuff);
1491 TEST_MSG(
"marker is %zu past the current position, expected 1. "
1492 "Measuring the budget with fr_sbuff_used() would give 5",
1494 fr_sbuff_marker_release(&end);
1508 const char PATTERN[] =
"xyzzy";
1509#define PATTERN_LEN (sizeof(PATTERN) - 1)
1513 static_assert(
sizeof(
buff) >=
PATTERN_LEN,
"Buffer must be sufficiently large to hold the pattern");
1514 static_assert((
sizeof(fbuff) %
sizeof(
buff)) > 0,
"sizeof buff must not be a multiple of fbuff");
1515 static_assert((
sizeof(fbuff) %
sizeof(
buff)) <
PATTERN_LEN,
"remainder of sizeof(fbuff)/sizeof(buff) must be less than sizeof pattern");
1518 memset(fbuff,
' ',
sizeof(fbuff));
1521 fp = fmemopen(fbuff,
sizeof(fbuff),
"r");
1522#ifdef __clang_analyzer__
1523 if (fp == NULL)
return;
1527 TEST_CHECK(fr_sbuff_init_file(&sbuff, &fctx,
buff,
sizeof(
buff), fp, 128) == &sbuff);
1530 TEST_CASE(
"Advance past whitespace, which will require shift/extend");
1532 TEST_CASE(
"Verify extend on unused child buffer");
1533 child_sbuff =
FR_SBUFF(&our_sbuff);
1536 TEST_CASE(
"Verify that we passed all and only whitespace");
1537 (void) fr_sbuff_out_abstrncpy(NULL, &post_ws, &our_sbuff, 24);
1543 TEST_CASE(
"Verify that we do not read shifted buffer past eof");
1555 TEST_CASE(
"Verify fr_sbuff_out_bstrncpy_until() extends from file properly");
1556 fp = fmemopen(fbuff,
sizeof(fbuff),
"r");
1557#ifdef __clang_analyzer__
1558 if (fp == NULL)
return;
1562 TEST_CHECK(fr_sbuff_init_file(&sbuff, &fctx,
buff,
sizeof(
buff), fp, 128) == &sbuff);
1576 char fbuff[] =
" xyzzy";
1580 fp = fmemopen(fbuff,
sizeof(fbuff) - 1,
"r");
1581#ifdef __clang_analyzer__
1582 if (fp == NULL)
return;
1585 TEST_CHECK(fr_sbuff_init_file(&sbuff, &fctx,
buff,
sizeof(
buff), fp,
sizeof(fbuff) - 8) == &sbuff);
1587 TEST_CASE(
"Confirm that max stops us from seeing xyzzy");
1589 TEST_CHECK_SLEN(fr_sbuff_out_abstrncpy(NULL, &post_ws, &sbuff, 24), 0);
1598 char const in[] =
"i am a test string";
1600 TEST_CASE(
"Check for token at beginning of string");
1605 TEST_CASE(
"Check for token not at beginning of string");
1610 TEST_CASE(
"Check for token larger than the string");
1615 TEST_CASE(
"Check for token with zero length string");
1619 TEST_CASE(
"Check for token that is the string");
1629 char const in[] =
"i am a test string";
1631 TEST_CASE(
"Check for token at beginning of string");
1636 TEST_CASE(
"Check for token not at beginning of string");
1641 TEST_CASE(
"Check for token larger than the string");
1646 TEST_CASE(
"Check for token with zero length string");
1650 TEST_CASE(
"Check for token that is the string");
1660 char const in[] =
" i am a test string";
1661 char const in_ns[] =
"i am a test string";
1662 char const in_ws[] =
" ";
1664 TEST_CASE(
"Check for token at beginning of string");
1669 TEST_CASE(
"Check for token not at beginning of string");
1674 TEST_CASE(
"Check for token with zero length string");
1678 TEST_CASE(
"Check for token that is the string");
1682 TEST_CASE(
"Length constraint with token match");
1687 TEST_CASE(
"Length constraint without token match");
1696 char const in[] =
" i am a test string";
1697 char const in_ns[] =
"i am a test string";
1698 char const in_ws[] =
" ";
1700 TEST_CASE(
"Check for token at beginning of string");
1705 TEST_CASE(
"Check for token not at beginning of string");
1710 TEST_CASE(
"Check for token with zero length string");
1715 TEST_CASE(
"Check for token at the end of the string");
1720 TEST_CASE(
"Length constraint with token match");
1725 TEST_CASE(
"Length constraint with token match");
1734 char const in[] =
" abcdefgh ijklmnopp";
1736 TEST_CASE(
"Check for token at beginning of string");
1741 TEST_CASE(
"Check for token not at beginning of string");
1746 TEST_CASE(
"Check for token with zero length string");
1751 TEST_CASE(
"Check for token that is not in the string");
1761 TEST_CASE(
"Check for token that is not in the string with length constraint");
1770 char const in[] =
"🥺🥺🥺🥺🍪😀";
1773 TEST_CASE(
"Check for token at beginning of string");
1779 TEST_CASE(
"Check for token not at beginning of string");
1782 TEST_CHECK(p == (sbuff.start + (
sizeof(
"🥺🥺🥺🥺") - 1)));
1785 TEST_CASE(
"Check for token with zero length string");
1791 TEST_CASE(
"Check for token at the end of the string");
1794 TEST_CHECK(p == sbuff.start + (
sizeof(
"🥺🥺🥺🥺🍪") - 1));
1796 TEST_CASE(
"Check for token not in the string");
1801 TEST_CASE(
"Check for token at the end of the string within len constraints");
1804 TEST_CHECK(p == sbuff.start + (
sizeof(
"🥺🥺🥺🥺🍪") - 1));
1806 TEST_CASE(
"Check for token at the end of the string outside len constraints #1");
1811 TEST_CASE(
"Check for token at the end of the string outside len constraints #2");
1816 TEST_CASE(
"Check for token at the end of the string outside len constraints #3");
1821 TEST_CASE(
"Check for token at the end of the string outside len constraints #4");
1830 char const in[] =
"AAAAbC";
1833 TEST_CASE(
"Check for token at beginning of string");
1839 TEST_CASE(
"Check for token not at beginning of string");
1842 TEST_CHECK(p == (sbuff.start + (
sizeof(
"AAAA") - 1)));
1845 TEST_CASE(
"Check for token with zero length string");
1850 TEST_CASE(
"Check for token at the end of the string");
1853 TEST_CHECK(p == sbuff.start + (
sizeof(
"AAAAb") - 1));
1855 TEST_CASE(
"Check for token not in the string");
1860 TEST_CASE(
"Check for token not at beginning of string within length constraints");
1863 TEST_CHECK(p == (sbuff.start + (
sizeof(
"AAAA") - 1)));
1866 TEST_CASE(
"Check for token not at beginning of string outside length constraints");
1875 char const in[] =
"i am a test string";
1878 TEST_CASE(
"Check for token at beginning of string");
1884 TEST_CASE(
"Check for token not at beginning of string");
1890 TEST_CASE(
"Check for token at the end of string");
1896 TEST_CASE(
"Check for token larger than the string");
1902 TEST_CASE(
"Check for token shorter than string, not in the string");
1908 TEST_CASE(
"Check for token with zero length string");
1914 TEST_CASE(
"Check for token that is the string");
1921 TEST_CASE(
"Check for token not at beginning of string within length constraints");
1927 TEST_CASE(
"Check for token not at beginning of string outside length constraints");
1936 char const in[] =
"i am a test string";
1939 TEST_CASE(
"Check for token at beginning of string");
1945 TEST_CASE(
"Check for token not at beginning of string");
1951 TEST_CASE(
"Check for token at the end of string");
1957 TEST_CASE(
"Check for token larger than the string");
1963 TEST_CASE(
"Check for token shorter than string, not in the string");
1969 TEST_CASE(
"Check for token with zero length string");
1975 TEST_CASE(
"Check for token that is the string");
1982 TEST_CASE(
"Check for token not at beginning of string within length constraints");
1988 TEST_CASE(
"Check for token not at beginning of string outside length constraints");
1997 char const in[] =
"i ";
1999 TEST_CASE(
"Check for advancement on match");
2004 TEST_CASE(
"Check for non-advancement on non-match");
2008 TEST_CASE(
"Check for advancement at end");
2012 TEST_CASE(
"Check we can't advance off the end of the buffer");
2020 char const in[] =
"i ";
2022 TEST_CASE(
"Check for advancement on non-match");
2027 TEST_CASE(
"Check for non-advancement on match");
2031 TEST_CASE(
"Check for advancement at end");
2035 TEST_CASE(
"Check we can't advance off the end of the buffer");
Common initialisation for acutest binaries.
#define TEST_CHECK_SLEN(_got, _exp)
#define TEST_CHECK_SLEN_RETURN(_got, _exp)
#define TEST_CHECK_LEN(_got, _exp)
#define TEST_CHECK_STRCMP(_got, _exp)
#define L(_str)
Helper for initialising arrays of string literals.
size_t fr_sbuff_out_unescape_until(fr_sbuff_t *out, fr_sbuff_t *in, size_t len, fr_sbuff_term_t const *tt, fr_sbuff_unescape_rules_t const *u_rules)
ssize_t fr_sbuff_out_bstrncpy_exact(fr_sbuff_t *out, fr_sbuff_t *in, size_t len)
size_t fr_sbuff_out_bstrncpy_until(fr_sbuff_t *out, fr_sbuff_t *in, size_t len, fr_sbuff_term_t const *tt, fr_sbuff_unescape_rules_t const *u_rules)
size_t fr_sbuff_out_bstrncpy_allowed(fr_sbuff_t *out, fr_sbuff_t *in, size_t len, bool const allowed[static SBUFF_CHAR_CLASS])
size_t fr_sbuff_adv_past_allowed(fr_sbuff_t *sbuff, size_t len, bool const allowed[static SBUFF_CHAR_CLASS], fr_sbuff_term_t const *tt)
Wind position past characters in the allowed set.
int fr_sbuff_trim_talloc(fr_sbuff_t *sbuff, size_t len)
Trim a talloced sbuff to the minimum length required to represent the contained string.
ssize_t fr_sbuff_in_strcpy(fr_sbuff_t *sbuff, char const *str)
Copy bytes into the sbuff up to the first \0.
char * fr_sbuff_adv_to_chr_utf8(fr_sbuff_t *sbuff, size_t len, char const *chr)
Wind position to first instance of specified multibyte utf8 char.
char * fr_sbuff_adv_to_str(fr_sbuff_t *sbuff, size_t len, char const *needle, size_t needle_len)
Wind position to the first instance of the specified needle.
char * fr_sbuff_adv_to_strcase(fr_sbuff_t *sbuff, size_t len, char const *needle, size_t needle_len)
Wind position to the first instance of the specified needle.
size_t fr_sbuff_extend_file(fr_sbuff_extend_status_t *status, fr_sbuff_t *sbuff, size_t extension)
Refresh the buffer with more data from the file.
size_t fr_sbuff_adv_past_str(fr_sbuff_t *sbuff, char const *needle, size_t needle_len)
Return true and advance past the end of the needle if needle occurs next in the sbuff.
size_t fr_sbuff_shift(fr_sbuff_t *sbuff, size_t shift, bool move_end)
Shift the contents of the sbuff, returning the number of bytes we managed to shift.
char * fr_sbuff_adv_to_chr(fr_sbuff_t *sbuff, size_t len, char c)
Wind position to first instance of specified char.
bool fr_sbuff_is_terminal(fr_sbuff_t *in, fr_sbuff_term_t const *tt)
Efficient terminal string search.
size_t fr_sbuff_adv_past_strcase(fr_sbuff_t *sbuff, char const *needle, size_t needle_len)
Return true and advance past the end of the needle if needle occurs next in the sbuff.
bool fr_sbuff_next_unless_char(fr_sbuff_t *sbuff, char c)
Return true and advance if the next char does not match.
size_t fr_sbuff_adv_until(fr_sbuff_t *sbuff, size_t len, fr_sbuff_term_t const *tt, char escape_chr)
Wind position until we hit a character in the terminal set.
size_t fr_sbuff_out_bstrncpy(fr_sbuff_t *out, fr_sbuff_t *in, size_t len)
Copy as many bytes as possible from a sbuff to a sbuff.
fr_sbuff_term_t * fr_sbuff_terminals_amerge(TALLOC_CTX *ctx, fr_sbuff_term_t const *a, fr_sbuff_term_t const *b)
Merge two sets of terminal strings.
bool fr_sbuff_next_if_char(fr_sbuff_t *sbuff, char c)
Return true if the current char matches, and if it does, advance.
#define fr_sbuff_start(_sbuff_or_marker)
#define fr_sbuff_shifted(_sbuff_or_marker)
#define FR_SBUFF_IN(_start, _len_or_end)
#define FR_SBUFF_BIND_CURRENT(_sbuff_or_marker)
#define fr_sbuff_adv_past_whitespace(_sbuff, _len, _tt)
char const * str
Terminal string.
#define fr_sbuff_current(_sbuff_or_marker)
char chr
Character at the start of an escape sequence.
#define FR_SBUFF_TERMS(...)
Initialise a terminal structure with a list of sorted strings.
#define fr_sbuff_used_total(_sbuff_or_marker)
#define fr_sbuff_init_out(_out, _start, _len_or_end)
size_t len
Length of the list.
#define fr_sbuff_is_char(_sbuff_or_marker, _c)
#define fr_sbuff_end(_sbuff_or_marker)
#define FR_SBUFF(_sbuff_or_marker)
#define fr_sbuff_advance(_sbuff_or_marker, _len)
#define fr_sbuff_init_in(_out, _start, _len_or_end)
#define fr_sbuff_remaining(_sbuff_or_marker)
#define FR_SBUFF_OUT(_start, _len_or_end)
#define fr_sbuff_used(_sbuff_or_marker)
fr_sbuff_term_elem_t * elem
A sorted list of terminal strings.
#define FR_SBUFF_TERM(_str)
Initialise a terminal structure with a single string.
Set of terminal elements.
File sbuff extension structure.
Talloc sbuff extension structure.
Set of parsing rules for *unescape_until functions.
static void test_adv_past_allowed(void)
static void test_terminal_search_past_visible_end(void)
static void test_no_advance(void)
static void test_marker_update_end(void)
static void test_file_extend_max(void)
static void test_talloc_extend_multi_level(void)
static void test_adv_past_strcase(void)
static void test_shift_used_accounting(void)
static void test_adv_to_strcase(void)
static void test_talloc_extend(void)
static void test_bstrncpy_until(void)
static void test_bstrncpy_allowed(void)
static bool allow_lowercase_and_space_no_t[SBUFF_CHAR_CLASS]
#define TEST_SBUFF_USED(_sbuff, _num)
static void test_adv_until(void)
static void test_is_char(void)
static void test_bstrncpy(void)
static void test_bstrncpy_exact(void)
static void test_adv_to_utf8(void)
static void test_marker_update_end_after_shift(void)
Check that the budget is measured with fr_sbuff_used_total(), not fr_sbuff_used()
static void test_adv_to_chr(void)
static void test_eof_terminal(void)
static void test_next_unless_char(void)
static void test_adv_past_whitespace(void)
static void test_next_if_char(void)
static void test_terminal_search_at_end_no_overrun(void)
static void test_unescape_until(void)
static void test_adv_past_str(void)
static void test_talloc_extend_with_shift(void)
static void test_unescape_multi_char_terminals(void)
#define TEST_SBUFF_LEN(_sbuff, _num)
static void test_file_extend(void)
static void test_terminal_merge(void)
static void test_parse_init(void)
static bool allow_lowercase_and_space[SBUFF_CHAR_CLASS]
static void test_adv_to_str(void)
static void test_talloc_extend_init_zero(void)
static void test_talloc_extend_with_marker(void)
static void test_unescape_until_escape_bounds(void)
Check that a hex or octal escape sequence cannot consume more input than "len" allows.
static char buff[sizeof("18446744073709551615")+3]
static size_t char ** out