26#include <freeradius-devel/util/sbuff.h>
38#define TEST_SBUFF_LEN(_sbuff, _num) \
41 _len = talloc_array_length((_sbuff)->buff); \
42 TEST_CHECK(_len == (size_t)_num); \
43 TEST_MSG("Expected length : %zu", (size_t)_num); \
44 TEST_MSG("Got length : %zu", _len); \
47#define TEST_SBUFF_USED(_sbuff, _num) \
50 _len = fr_sbuff_used(_sbuff); \
51 TEST_CHECK(_len == (size_t)_num); \
52 TEST_MSG("Expected length : %zu", (size_t)_num); \
53 TEST_MSG("Got length : %zu", _len); \
58 char const in[] =
"i am a test string";
85 char const in[] =
"i am a test string";
99 fr_sbuff_marker(&marker, &sbuff);
114 char const in[] =
"i am a test string";
115 char const in_long[] =
"i am a longer test string";
116 char out[18 + 1] =
"";
117 char out_long[32 + 1] =
"";
143 TEST_CASE(
"Copy would overrun input part way through");
159 TEST_CASE(
"SIZE_MAX copies the whole input");
160 fr_sbuff_set_to_start(&sbuff);
167 fr_sbuff_set_to_start(&sbuff);
175 fr_sbuff_set_to_start(&sbuff);
185 char const in[] =
"i am a test string";
186 char const in_long[] =
"i am a longer test string";
187 char out[18 + 1] =
"";
215 TEST_CASE(
"Copy would overrun output (and SIZE_MAX special value)");
225 fr_sbuff_set_to_start(&sbuff);
234 fr_sbuff_set_to_start(&sbuff);
243 fr_sbuff_set_to_start(&sbuff);
250 [
'a'] =
true, [
'b'] =
true, [
'c'] =
true, [
'd'] =
true, [
'e'] =
true,
251 [
'f'] =
true, [
'g'] =
true, [
'h'] =
true, [
'i'] =
true, [
'j'] =
true,
252 [
'k'] =
true, [
'l'] =
true, [
'm'] =
true, [
'n'] =
true, [
'o'] =
true,
253 [
'p'] =
true, [
'q'] =
true, [
'r'] =
true, [
's'] =
true, [
't'] =
true,
254 [
'u'] =
true, [
'v'] =
true, [
'w'] =
true, [
'x'] =
true, [
'y'] =
true,
255 [
'z'] =
true, [
' '] =
true
259 [
'a'] =
true, [
'b'] =
true, [
'c'] =
true, [
'd'] =
true, [
'e'] =
true,
260 [
'f'] =
true, [
'g'] =
true, [
'h'] =
true, [
'i'] =
true, [
'j'] =
true,
261 [
'k'] =
true, [
'l'] =
true, [
'm'] =
true, [
'n'] =
true, [
'o'] =
true,
262 [
'p'] =
true, [
'q'] =
true, [
'r'] =
true, [
's'] =
true, [
't'] =
false,
263 [
'u'] =
true, [
'v'] =
true, [
'w'] =
true, [
'x'] =
true, [
'y'] =
true,
264 [
'z'] =
true, [
' '] =
true
269 char const in[] =
"i am a test string";
270 char const in_long[] =
"i am a longer test string";
271 char out[18 + 1] =
"";
304 TEST_CASE(
"Copy would overrun output (and SIZE_MAX special value)");
313 fr_sbuff_set_to_start(&sbuff);
322 fr_sbuff_set_to_start(&sbuff);
334 fr_sbuff_set_to_start(&sbuff);
341 TEST_CASE(
"Copy until first t with length constraint (same len as token)");
342 fr_sbuff_set_to_start(&sbuff);
349 TEST_CASE(
"Copy until first t with length constraint (one shorter than token)");
350 fr_sbuff_set_to_start(&sbuff);
357 TEST_CASE(
"Zero length token (should still be terminated)");
358 fr_sbuff_set_to_start(&sbuff);
368 char const in[] =
"i am a test string";
369 char const in_long[] =
"i am a longer test string";
370 char out[18 + 1] =
"";
404 fr_sbuff_set_to_start(&sbuff);
412 TEST_CASE(
"Copy would overrun output (and SIZE_MAX special value)");
421 fr_sbuff_set_to_start(&sbuff);
430 fr_sbuff_set_to_start(&sbuff);
442 fr_sbuff_set_to_start(&sbuff);
448 TEST_CASE(
"Copy until first t with length constraint (same len as token)");
449 fr_sbuff_set_to_start(&sbuff);
455 TEST_CASE(
"Copy until first t with length constraint (one shorter than token)");
456 fr_sbuff_set_to_start(&sbuff);
462 TEST_CASE(
"Zero length token (should still be terminated)");
463 fr_sbuff_set_to_start(&sbuff);
472 char const in[] =
"i am a test string";
473 char const in_long[] =
"i am a longer test string";
474 char const in_escapes[] =
"i am a |t|est strin|g";
475 char const in_escapes_seq[] =
"i |x|0am a |t|est strin|g|x20|040";
476 char out[18 + 1] =
"";
477 char escape_out[20 + 1];
489 .subs = { [
'g'] =
'g', [
'|'] =
'|' }
493 .
chr =
'|', .subs = { [
'g'] =
'h', [
'|'] =
'|' }
498 .subs = { [
'g'] =
'h', [
'|'] =
'|' },
504 .subs = { [
'g'] =
'h', [
'|'] =
'|' },
510 .subs = { [
'g'] =
'h', [
'|'] =
'|' },
542 TEST_CASE(
"Copy would overrun output (and SIZE_MAX special value)");
552 fr_sbuff_set_to_start(&sbuff);
561 fr_sbuff_set_to_start(&sbuff);
573 fr_sbuff_set_to_start(&sbuff);
580 TEST_CASE(
"Copy until first t with length constraint (same len as token)");
581 fr_sbuff_set_to_start(&sbuff);
588 TEST_CASE(
"Copy until first t with length constraint (one shorter than token)");
589 fr_sbuff_set_to_start(&sbuff);
596 TEST_CASE(
"Zero length token (should still be terminated)");
597 fr_sbuff_set_to_start(&sbuff);
607 TEST_CASE(
"Escape with substitution to same char");
616 TEST_CASE(
"Escape with substitution to different char");
626 char tmp_out[24 + 1];
628 TEST_CASE(
"Escape with hex substitutions (insufficient output space)");
639 char tmp_out[25 + 1];
645 TEST_CASE(
"Escape with hex substitutions (sufficient output space for the hex escape)");
656 char tmp_out[28 + 1];
658 TEST_CASE(
"Escape with oct substitutions (insufficient output space)");
669 char tmp_out[29 + 1];
671 TEST_CASE(
"Escape with oct substitutions (sufficient output space)");
682 char tmp_out[26 + 1];
684 TEST_CASE(
"Escape with hex and oct substitutions (sufficient output space)");
696 char const in_escapes_collapse[] =
"||";
699 fr_sbuff_init_in(&sbuff, in_escapes_collapse,
sizeof(in_escapes_collapse) - 1);
701 &sbuff, SIZE_MAX, NULL, &pipe_rules);
709 char in_escapes_collapse[] =
"||foo||";
711 TEST_CASE(
"Collapse double escapes overlapping");
712 fr_sbuff_init_in(&sbuff, in_escapes_collapse,
sizeof(in_escapes_collapse) - 1);
714 &sbuff, SIZE_MAX, NULL, &pipe_rules);
722 char tmp_out[30 + 1];
741 char const in_escapes_unit[] =
750 char const expected[] = {
751 '0',
'x',
'0',
'1',
'\001',
752 '0',
'x',
'0',
'7',
'\007',
753 '0',
'x',
'0',
'A',
'\n',
754 '0',
'x',
'0',
'D',
'\r',
760 TEST_CASE(
"Check unit test test strings");
763 NULL, &double_quote_rules);
775 char const in_zero[] =
"";
777 ret = fr_sbuff_out_aunescape_until(NULL, &
buff, &
len, &
FR_SBUFF_IN(in_zero,
sizeof(in_zero) - 1), SIZE_MAX,
781 talloc_get_type_abort(
buff,
char);
800 char out[24 + 1] =
"";
805 char const in_hex[] =
"|x41|x42|x43";
806 char const in_oct[] =
"|101|102|103";
810 .subs = { [
'|'] =
'|' },
816 .subs = { [
'|'] =
'|' },
828 TEST_CASE(
"Hex, limit falls on the end of an escape sequence");
836 TEST_CASE(
"Hex, limit falls on the escape char");
847 TEST_CASE(
"Hex, limit leaves no room for either hex digit");
859 TEST_CASE(
"Hex, limit leaves room for only one hex digit");
876 TEST_CASE(
"Octal, limit falls on the end of an escape sequence");
887 TEST_CASE(
"Octal, limit leaves room for only two octal digits");
902 TEST_CASE(
"No limit is ever exceeded, hex");
903 for (
size_t i = 0; i <=
sizeof(in_hex); i++) {
911 TEST_CASE(
"No limit is ever exceeded, octal");
912 for (
size_t i = 0; i <=
sizeof(in_oct); i++) {
923 char const in[] =
"foo, bar, baz```";
962 char const in[] =
"foo, bar";
1009 char const in[] =
"abc}xyz";
1039 size_t const len = 4;
1121 for (i = 0; i < result->
len; i++) {
1130 char const *
in =
"i am a test string";
1131 char out[18 + 1] =
"";
1136 TEST_CASE(
"Copy 5 bytes to out - no advance");
1149 MEM(fr_sbuff_init_talloc(NULL, &sbuff, &tctx, 32, 50));
1158 TEST_CASE(
"Print string - Should realloc to init");
1168 TEST_CASE(
"Print string - Should realloc to init");
1178 TEST_CASE(
"Print string - Should realloc to double buffer len");
1184 TEST_CASE(
"Print string - Should only add a single char, should not extend the buffer");
1190 TEST_CASE(
"Print string - Use all available buffer data");
1196 TEST_CASE(
"Print string - Add single char, should trigger doubling constrained by max");
1202 TEST_CASE(
"Print string - Add data to take us up to max");
1208 TEST_CASE(
"Print string - Add single char, should fail");
1214 TEST_CASE(
"Trim to strlen (should be noop)");
1229 MEM(fr_sbuff_init_talloc(NULL, &sbuff, &tctx, 0, 50));
1233 TEST_CASE(
"Print string - Should alloc one byte");
1239 TEST_CASE(
"Print string - Should alloc two bytes");
1245 TEST_CASE(
"Print string - Should alloc three bytes");
1260 MEM(fr_sbuff_init_talloc(NULL, &sbuff_0, &tctx, 0, 50));
1265 TEST_CASE(
"Check sbuff_1 has extend fields set");
1266 TEST_CHECK(sbuff_0.extend == sbuff_1.extend);
1272 TEST_CASE(
"Print string - Should alloc one byte");
1294 MEM(fr_sbuff_init_talloc(NULL, &sbuff_0, &tctx, 0, 50));
1298 TEST_CASE(
"Print string - Should alloc one byte");
1304 fr_sbuff_marker(&marker_0, &sbuff_0);
1305 TEST_CHECK((marker_0.p - sbuff_0.start) == 1);
1307 TEST_CASE(
"Print string - Ensure marker is updated");
1312 TEST_CHECK((marker_0.p - sbuff_0.start) == 1);
1317 fr_sbuff_marker(&marker_1, &sbuff_1);
1319 TEST_CHECK((marker_1.p - sbuff_1.start) == 0);
1320 TEST_CHECK((marker_1.p - sbuff_0.start) == 2);
1323 TEST_CASE(
"Print string - Trigger re-alloc, ensure all pointers are updated");
1328 TEST_CHECK((marker_1.p - sbuff_1.start) == 0);
1329 TEST_CHECK((marker_1.p - sbuff_0.start) == 2);
1342 MEM(fr_sbuff_init_talloc(NULL, &sbuff, &tctx, 4, 8));
1366 TEST_CASE(
"Before any shift, used() and used_total() agree");
1367 MEM(fr_sbuff_init_talloc(NULL, &sbuff, &tctx, 8, 32));
1374 TEST_CASE(
"A shift moves data out of the buffer");
1386 TEST_CASE(
"used() forgets the shifted data");
1389 TEST_CASE(
"used_total() remembers it, and is unchanged by the shift");
1393 TEST_CASE(
"used_total() stays whole across a second shift");
1404 TEST_CASE(
"used() plus shifted() equals used_total()");
1423 TEST_CASE(
"SIZE_MAX means no constraint, so the marker sits at the end");
1425 fr_sbuff_marker(&end, &sbuff);
1427 fr_sbuff_marker_release(&end);
1429 TEST_CASE(
"A budget smaller than the buffer stops the marker short");
1431 fr_sbuff_marker(&end, &sbuff);
1433 fr_sbuff_marker_release(&end);
1435 TEST_CASE(
"Data already consumed comes off the budget");
1438 fr_sbuff_marker(&end, &sbuff);
1445 fr_sbuff_marker_release(&end);
1447 TEST_CASE(
"A budget which exactly matches what was consumed leaves nothing");
1450 fr_sbuff_marker(&end, &sbuff);
1452 fr_sbuff_marker_release(&end);
1464 TEST_CASE(
"An overspent budget allows nothing more");
1467 fr_sbuff_marker(&end, &sbuff);
1470 TEST_MSG(
"marker is %zu past the current position, expected 0",
1473 fr_sbuff_marker_release(&end);
1475 TEST_CASE(
"A budget overspent by a single byte allows nothing more");
1478 fr_sbuff_marker(&end, &sbuff);
1480 fr_sbuff_marker_release(&end);
1482 TEST_CASE(
"A zero budget allows nothing, whether or not anything was used");
1484 fr_sbuff_marker(&end, &sbuff);
1486 fr_sbuff_marker_release(&end);
1490 fr_sbuff_marker(&end, &sbuff);
1492 fr_sbuff_marker_release(&end);
1499 TEST_CASE(
"Repeated updates on an overspent budget stay put");
1502 fr_sbuff_marker(&end, &sbuff);
1506 fr_sbuff_marker_release(&end);
1514 TEST_CASE(
"An overspent budget at the end of the buffer");
1517 fr_sbuff_marker(&end, &sbuff);
1521 fr_sbuff_marker_release(&end);
1550 size_t used, used_total;
1558 TEST_CASE(
"Set up a buffer which has shifted, and which has room left");
1559 MEM(fr_sbuff_init_talloc(NULL, &sbuff, &tctx, 16, 32));
1575 TEST_CASE(
"A budget between used and used_total is already overspent");
1576 fr_sbuff_marker(&end, &sbuff);
1578 TEST_MSG(
"marker is %zu past the current position, expected 0. "
1579 "Measuring the budget with fr_sbuff_used() would give 2, "
1580 "and not clamping the overspend would give %zu",
1583 fr_sbuff_marker_release(&end);
1589 TEST_CASE(
"A budget larger than used_total leaves used_total's worth of room");
1596 fr_sbuff_marker(&end, &sbuff);
1598 TEST_MSG(
"marker is %zu past the current position, expected 1. "
1599 "Measuring the budget with fr_sbuff_used() would give 5",
1601 fr_sbuff_marker_release(&end);
1613 char out[24] =
"not written";
1615 const char PATTERN[] =
"xyzzy";
1616#define PATTERN_LEN (sizeof(PATTERN) - 1)
1621 static_assert(
sizeof(
buff) >=
PATTERN_LEN,
"Buffer must be sufficiently large to hold the pattern");
1622 static_assert((
sizeof(fbuff) %
sizeof(
buff)) > 0,
"sizeof buff must not be a multiple of fbuff");
1623 static_assert((
sizeof(fbuff) %
sizeof(
buff)) <
PATTERN_LEN,
"remainder of sizeof(fbuff)/sizeof(buff) must be less than sizeof pattern");
1626 memset(fbuff,
' ',
sizeof(fbuff));
1629 fp = fmemopen(fbuff,
sizeof(fbuff),
"r");
1630#ifdef __clang_analyzer__
1631 if (fp == NULL)
return;
1635 TEST_CHECK(fr_sbuff_init_file(&sbuff, &fctx,
buff,
sizeof(
buff), fp, 128) == &sbuff);
1638 TEST_CASE(
"Advance past whitespace, which will require shift/extend");
1640 TEST_CASE(
"Verify extend on unused child buffer");
1641 child_sbuff =
FR_SBUFF(&our_sbuff);
1644 TEST_CASE(
"Verify that we passed all and only whitespace");
1651 TEST_CASE(
"Verify that we do not read shifted buffer past eof");
1663 TEST_CASE(
"Verify fr_sbuff_out_bstrncpy_until() extends from file properly");
1664 fp = fmemopen(fbuff,
sizeof(fbuff),
"r");
1665#ifdef __clang_analyzer__
1666 if (fp == NULL)
return;
1670 TEST_CHECK(fr_sbuff_init_file(&sbuff, &fctx,
buff,
sizeof(
buff), fp, 128) == &sbuff);
1684 char fbuff[] =
" xyzzy";
1689 fp = fmemopen(fbuff,
sizeof(fbuff) - 1,
"r");
1690#ifdef __clang_analyzer__
1691 if (fp == NULL)
return;
1694 TEST_CHECK(fr_sbuff_init_file(&sbuff, &fctx,
buff,
sizeof(
buff), fp,
sizeof(fbuff) - 8) == &sbuff);
1696 TEST_CASE(
"Confirm that max stops us from seeing xyzzy");
1716 char out[16] =
"not written";
1720 fp = fopen(
"/dev/null",
"w");
1721#ifdef __clang_analyzer__
1722 if (fp == NULL)
return;
1725 TEST_CHECK(fr_sbuff_init_file(&sbuff, &fctx,
buff,
sizeof(
buff), fp, SIZE_MAX) == &sbuff);
1727 TEST_CASE(
"Copy reports the read error");
1732 TEST_CASE(
"Copy until reports the read error");
1737 TEST_CASE(
"Exact copy reports the read error");
1748 TEST_CASE(
"In range, input advanced past the number");
1754 TEST_CASE(
"Overflow, out is the maximum and input is not advanced");
1760 TEST_CASE(
"Underflow, out is the minimum");
1787 TEST_CASE(
"Leading minus is underflow");
1792 TEST_CASE(
"Hex, more digits than the type can hold is trailing data");
1798 TEST_CASE(
"Hex, trailing digits allowed, input advanced past the two consumed");
1831 TEST_CASE(
"True, input advanced past the value");
1843 TEST_CASE(
"Not a truth value, out is false and input is not advanced");
1858 char const in[] =
"i am a test string";
1860 TEST_CASE(
"Check for token at beginning of string");
1865 TEST_CASE(
"Check for token not at beginning of string");
1870 TEST_CASE(
"Check for token larger than the string");
1875 TEST_CASE(
"Check for token with zero length string");
1879 TEST_CASE(
"Check for token that is the string");
1889 char const in[] =
"i am a test string";
1891 TEST_CASE(
"Check for token at beginning of string");
1896 TEST_CASE(
"Check for token not at beginning of string");
1901 TEST_CASE(
"Check for token larger than the string");
1906 TEST_CASE(
"Check for token with zero length string");
1910 TEST_CASE(
"Check for token that is the string");
1920 char const in[] =
" i am a test string";
1921 char const in_ns[] =
"i am a test string";
1922 char const in_ws[] =
" ";
1924 TEST_CASE(
"Check for token at beginning of string");
1929 TEST_CASE(
"Check for token not at beginning of string");
1934 TEST_CASE(
"Check for token with zero length string");
1938 TEST_CASE(
"Check for token that is the string");
1942 TEST_CASE(
"Length constraint with token match");
1947 TEST_CASE(
"Length constraint without token match");
1956 char const in[] =
" i am a test string";
1957 char const in_ns[] =
"i am a test string";
1958 char const in_ws[] =
" ";
1960 TEST_CASE(
"Check for token at beginning of string");
1965 TEST_CASE(
"Check for token not at beginning of string");
1970 TEST_CASE(
"Check for token with zero length string");
1975 TEST_CASE(
"Check for token at the end of the string");
1980 TEST_CASE(
"Length constraint with token match");
1985 TEST_CASE(
"Length constraint with token match");
1994 char const in[] =
" abcdefgh ijklmnopp";
1996 TEST_CASE(
"Check for token at beginning of string");
2001 TEST_CASE(
"Check for token not at beginning of string");
2006 TEST_CASE(
"Check for token with zero length string");
2011 TEST_CASE(
"Check for token that is not in the string");
2021 TEST_CASE(
"Check for token that is not in the string with length constraint");
2030 char const in[] =
"🥺🥺🥺🥺🍪😀";
2033 TEST_CASE(
"Check for token at beginning of string");
2039 TEST_CASE(
"Check for token not at beginning of string");
2042 TEST_CHECK(p == (sbuff.start + (
sizeof(
"🥺🥺🥺🥺") - 1)));
2045 TEST_CASE(
"Check for token with zero length string");
2051 TEST_CASE(
"Check for token at the end of the string");
2054 TEST_CHECK(p == sbuff.start + (
sizeof(
"🥺🥺🥺🥺🍪") - 1));
2056 TEST_CASE(
"Check for token not in the string");
2061 TEST_CASE(
"Check for token at the end of the string within len constraints");
2064 TEST_CHECK(p == sbuff.start + (
sizeof(
"🥺🥺🥺🥺🍪") - 1));
2066 TEST_CASE(
"Check for token at the end of the string outside len constraints #1");
2071 TEST_CASE(
"Check for token at the end of the string outside len constraints #2");
2076 TEST_CASE(
"Check for token at the end of the string outside len constraints #3");
2081 TEST_CASE(
"Check for token at the end of the string outside len constraints #4");
2090 char const in[] =
"AAAAbC";
2093 TEST_CASE(
"Check for token at beginning of string");
2099 TEST_CASE(
"Check for token not at beginning of string");
2102 TEST_CHECK(p == (sbuff.start + (
sizeof(
"AAAA") - 1)));
2105 TEST_CASE(
"Check for token with zero length string");
2110 TEST_CASE(
"Check for token at the end of the string");
2113 TEST_CHECK(p == sbuff.start + (
sizeof(
"AAAAb") - 1));
2115 TEST_CASE(
"Check for token not in the string");
2120 TEST_CASE(
"Check for token not at beginning of string within length constraints");
2123 TEST_CHECK(p == (sbuff.start + (
sizeof(
"AAAA") - 1)));
2126 TEST_CASE(
"Check for token not at beginning of string outside length constraints");
2135 char const in[] =
"i am a test string";
2138 TEST_CASE(
"Check for token at beginning of string");
2144 TEST_CASE(
"Check for token not at beginning of string");
2150 TEST_CASE(
"Check for token at the end of string");
2156 TEST_CASE(
"Check for token larger than the string");
2162 TEST_CASE(
"Check for token shorter than string, not in the string");
2168 TEST_CASE(
"Check for token with zero length string");
2174 TEST_CASE(
"Check for token that is the string");
2181 TEST_CASE(
"Check for token not at beginning of string within length constraints");
2187 TEST_CASE(
"Check for token not at beginning of string outside length constraints");
2196 char const in[] =
"i am a test string";
2199 TEST_CASE(
"Check for token at beginning of string");
2205 TEST_CASE(
"Check for token not at beginning of string");
2211 TEST_CASE(
"Check for token at the end of string");
2217 TEST_CASE(
"Check for token larger than the string");
2223 TEST_CASE(
"Check for token shorter than string, not in the string");
2229 TEST_CASE(
"Check for token with zero length string");
2235 TEST_CASE(
"Check for token that is the string");
2242 TEST_CASE(
"Check for token not at beginning of string within length constraints");
2248 TEST_CASE(
"Check for token not at beginning of string outside length constraints");
2257 char const in[] =
"i ";
2259 TEST_CASE(
"Check for advancement on match");
2264 TEST_CASE(
"Check for non-advancement on non-match");
2268 TEST_CASE(
"Check for advancement at end");
2272 TEST_CASE(
"Check we can't advance off the end of the buffer");
2280 char const in[] =
"i ";
2282 TEST_CASE(
"Check for advancement on non-match");
2287 TEST_CASE(
"Check for non-advancement on match");
2291 TEST_CASE(
"Check for advancement at end");
2295 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_LEN(_got, _exp)
#define TEST_CHECK_RET(_got, _exp)
#define TEST_CHECK_STRCMP(_got, _exp)
#define L(_str)
Helper for initialising arrays of string literals.
fr_sbuff_err_t fr_sbuff_out_bstrncpy_exact(fr_sbuff_t *out, fr_sbuff_t *in, size_t len)
fr_sbuff_err_t fr_sbuff_out_bstrncpy_allowed(size_t *len, fr_sbuff_t *out, fr_sbuff_t *in, size_t max, bool const allowed[static SBUFF_CHAR_CLASS])
@ FR_SBUFF_ERR_INPUT_EMPTY
@ FR_SBUFF_ERR_INPUT_SHORT
fr_sbuff_err_t fr_sbuff_out_bstrncpy_until(size_t *len, fr_sbuff_t *out, fr_sbuff_t *in, size_t max, fr_sbuff_term_t const *tt, fr_sbuff_unescape_rules_t const *u_rules)
fr_sbuff_err_t fr_sbuff_out_unescape_until(size_t *len, fr_sbuff_t *out, fr_sbuff_t *in, size_t max, fr_sbuff_term_t const *tt, fr_sbuff_unescape_rules_t const *u_rules)
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.
fr_sbuff_err_t fr_sbuff_out_bstrncpy(size_t *len, fr_sbuff_t *out, fr_sbuff_t *in, size_t max)
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_out(_out, _in)
#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_out_int(void)
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_out_bool(void)
static void test_out_uint(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_file_extend_error(void)
A read error on the file backing an sbuff is reported, not treated as the end of the input.
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_out_float(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 fr_sbuff_err_t char size_t fr_sbuff_t * in
static fr_sbuff_err_t char ** out
static fr_sbuff_err_t char size_t * len