static size_t tmpl_rule_func_table_len = NUM_ELEMENTS(tmpl_rule_func_table);
while (fr_sbuff_extend(&sbuff)) {
- fr_sbuff_adv_past_whitespace(&sbuff, SIZE_MAX);
+ fr_sbuff_adv_past_whitespace(&sbuff, SIZE_MAX, NULL);
fr_sbuff_out_by_longest_prefix(&slen, &func, tmpl_rule_func_table, &sbuff, NULL);
if (func == NULL) {
RETURN_COMMAND_ERROR();
}
- fr_sbuff_adv_past_whitespace(&sbuff, SIZE_MAX);
+ fr_sbuff_adv_past_whitespace(&sbuff, SIZE_MAX, NULL);
if (!fr_sbuff_next_if_char(&sbuff, '=')) {
fr_strerror_printf("Expected '=' after rule identifier, got \"%pV\"",
RETURN_COMMAND_ERROR();
}
- fr_sbuff_adv_past_whitespace(&sbuff, SIZE_MAX);
+ fr_sbuff_adv_past_whitespace(&sbuff, SIZE_MAX, NULL);
if (func(&cc->tmpl_rules, &sbuff) <= 0) RETURN_COMMAND_ERROR();
}
fr_sbuff_parse_error_t err;
while (fr_sbuff_extend(in)) {
- fr_sbuff_adv_past_whitespace(in, SIZE_MAX);
+ fr_sbuff_adv_past_whitespace(in, SIZE_MAX, NULL);
MEM(lr = talloc_zero(ctx, command_line_range_t));
fr_dlist_insert_tail(out, lr);
max = lr->start;
}
lr->end = lr->start; /* Default to a single line */
- fr_sbuff_adv_past_whitespace(in, SIZE_MAX);
+ fr_sbuff_adv_past_whitespace(in, SIZE_MAX, NULL);
again:
if (!fr_sbuff_extend(in)) break;
*/
case ',':
fr_sbuff_next(in);
- fr_sbuff_adv_past_whitespace(in, SIZE_MAX);
+ fr_sbuff_adv_past_whitespace(in, SIZE_MAX, NULL);
continue;
/*
case '-':
{
fr_sbuff_next(in);
- fr_sbuff_adv_past_whitespace(in, SIZE_MAX);
+ fr_sbuff_adv_past_whitespace(in, SIZE_MAX, NULL);
/*
* A bare '-' with no number means
} else {
max = lr->end;
}
- fr_sbuff_adv_past_whitespace(in, SIZE_MAX);
+ fr_sbuff_adv_past_whitespace(in, SIZE_MAX, NULL);
}
goto again;
}
talloc_free(text);
goto error;
}
- fr_sbuff_adv_past_whitespace(&sbuff, SIZE_MAX);
+ fr_sbuff_adv_past_whitespace(&sbuff, SIZE_MAX, NULL);
} else if (attribute) {
cf_log_err(cp, "Invalid quoting. Unquoted attribute reference is required");
goto error;
slen = tmpl_cast_from_substr(&cast, &our_in);
if (slen < 0) return slen;
- fr_sbuff_adv_past_whitespace(&our_in, SIZE_MAX);
+ fr_sbuff_adv_past_whitespace(&our_in, SIZE_MAX, NULL);
fr_sbuff_marker(&m, &our_in);
/*
MEM(c = talloc_zero(ctx, fr_cond_t));
- fr_sbuff_adv_past_whitespace(&our_in, SIZE_MAX);
+ fr_sbuff_adv_past_whitespace(&our_in, SIZE_MAX, NULL);
if (!fr_sbuff_extend(&our_in)) {
fr_strerror_const("Empty condition is invalid");
error:
*/
if (fr_sbuff_next_if_char(&our_in, '!')) {
c->negate = true;
- fr_sbuff_adv_past_whitespace(&our_in, SIZE_MAX);
+ fr_sbuff_adv_past_whitespace(&our_in, SIZE_MAX, NULL);
/*
* Just for stupidity
goto error;
}
- fr_sbuff_adv_past_whitespace(&our_in, SIZE_MAX);
+ fr_sbuff_adv_past_whitespace(&our_in, SIZE_MAX, NULL);
goto closing_brace;
}
/*
* We may (or not) have an operator
*/
- fr_sbuff_adv_past_whitespace(&our_in, SIZE_MAX);
+ fr_sbuff_adv_past_whitespace(&our_in, SIZE_MAX, NULL);
/*
* What's found directly after the LHS token determines
fr_strerror_const("Invalid operator");
goto error;
}
- fr_sbuff_adv_past_whitespace(&our_in, SIZE_MAX);
+ fr_sbuff_adv_past_whitespace(&our_in, SIZE_MAX, NULL);
{
map_t *map;
goto error;
}
- fr_sbuff_adv_past_whitespace(&our_in, SIZE_MAX);
+ fr_sbuff_adv_past_whitespace(&our_in, SIZE_MAX, NULL);
/*
* Check cast type. We can have the RHS
goto error;
}
fr_sbuff_advance(&our_in, 1);
- fr_sbuff_adv_past_whitespace(&our_in, SIZE_MAX);
+ fr_sbuff_adv_past_whitespace(&our_in, SIZE_MAX, NULL);
goto done;
}
fr_strerror_const("Unterminated cast");
FR_SBUFF_ERROR_RETURN(&our_in);
}
- fr_sbuff_adv_past_whitespace(&our_in, SIZE_MAX);
+ fr_sbuff_adv_past_whitespace(&our_in, SIZE_MAX, NULL);
}
if (out) *out = cast;
* don't want them to become a whitespace
* literal.
*/
- fr_sbuff_adv_past_whitespace(in, SIZE_MAX);
+ fr_sbuff_adv_past_whitespace(in, SIZE_MAX, NULL);
fr_sbuff_marker(&m, &our_in);
fr_cursor_init(&cursor, head);
* then error.
*/
fr_sbuff_set(&m, &our_in);
- len = fr_sbuff_adv_past_whitespace(&our_in, SIZE_MAX);
+ len = fr_sbuff_adv_past_whitespace(&our_in, SIZE_MAX, NULL);
/*
* Check to see if we have a terminal char
* @param[in] idx Fastpath index, populated by
* fr_sbuff_terminal_idx_init.
* @param[in] term terminals to search in.
+ * @param[in] needle_len Length of the longest needle.
* @return
* - true if found.
* - false if not.
*/
static inline bool fr_sbuff_terminal_search(fr_sbuff_t *in, char const *p,
uint8_t idx[static UINT8_MAX + 1],
- fr_sbuff_term_t const *term)
+ fr_sbuff_term_t const *term, size_t needle_len)
{
uint8_t term_idx;
/*
* Special case for EOFlike states
*/
- remaining = fr_sbuff_extend_lowat(&status, in, 1);
+ remaining = fr_sbuff_extend_lowat(&status, in, needle_len);
if (remaining == 0) {
if (status & FR_SBUFF_EXTEND_ERROR) return false;
return (idx['\0'] != 0);
end = CONSTRAINED_END(&our_in, len, fr_sbuff_used_total(&our_in));
if (escape_chr == '\0') {
- while ((p < end) && !fr_sbuff_terminal_search(in, p, idx, tt)) p++;
+ while ((p < end) && !fr_sbuff_terminal_search(in, p, idx, tt, needle_len)) p++;
} else {
while (p < end) {
if (do_escape) {
do_escape = false;
} else if (*p == escape_chr) {
do_escape = true;
- } else if (fr_sbuff_terminal_search(in, p, idx, tt)) {
+ } else if (fr_sbuff_terminal_search(in, p, idx, tt, needle_len)) {
break;
}
p++;
}
next:
- if (tt && fr_sbuff_terminal_search(in, fr_sbuff_current(&our_in), idx, tt)) break;
+ if (tt && fr_sbuff_terminal_search(in, fr_sbuff_current(&our_in), idx, tt, needle_len)) break;
fr_sbuff_advance(&our_in, 1);
};
*
* @param[in] sbuff sbuff to search in.
* @param[in] len Maximum amount to advance by. Unconstrained if SIZE_MAX.
+ * @param[in] tt If not NULL, stop if we find a terminal sequence.
* @return how many bytes we advanced.
*/
-size_t fr_sbuff_adv_past_whitespace(fr_sbuff_t *sbuff, size_t len)
+size_t fr_sbuff_adv_past_whitespace(fr_sbuff_t *sbuff, size_t len, fr_sbuff_term_t const *tt)
{
size_t total = 0;
char const *p;
+ uint8_t idx[UINT8_MAX + 1]; /* Fast path index */
+ size_t needle_len = 0;
CHECK_SBUFF_INIT(sbuff);
+ if (tt) fr_sbuff_terminal_idx_init(&needle_len, idx, tt);
+
while (total < len) {
char *end;
end = CONSTRAINED_END(sbuff, len, total);
p = sbuff->p;
- while ((p < end) && isspace(*p)) p++;
+ while ((p < end) && isspace(*p) &&
+ ((needle_len == 0) || !fr_sbuff_terminal_search(sbuff, p, idx, tt, needle_len))) p++;
total += fr_sbuff_set(sbuff, p);
if (p != end) break; /* stopped early, break */
p = sbuff->p;
if (escape_chr == '\0') {
- while ((p < end) && !fr_sbuff_terminal_search(sbuff, p, idx, tt)) p++;
+ while ((p < end) && !fr_sbuff_terminal_search(sbuff, p, idx, tt, needle_len)) p++;
} else {
while (p < end) {
if (do_escape) {
do_escape = false;
} else if (*p == escape_chr) {
do_escape = true;
- } else if (fr_sbuff_terminal_search(sbuff, p, idx, tt)) {
+ } else if (fr_sbuff_terminal_search(sbuff, p, idx, tt, needle_len)) {
break;
}
p++;
*/
fr_sbuff_terminal_idx_init(&needle_len, idx, tt);
- return fr_sbuff_terminal_search(in, in->p, idx, tt);
+ return fr_sbuff_terminal_search(in, in->p, idx, tt, needle_len);
}
#define fr_sbuff_adv_past_strcase_literal(_sbuff, _needle) fr_sbuff_adv_past_strcase(_sbuff, _needle, sizeof(_needle) - 1)
-size_t fr_sbuff_adv_past_whitespace(fr_sbuff_t *sbuff, size_t len);
+size_t fr_sbuff_adv_past_whitespace(fr_sbuff_t *sbuff, size_t len, fr_sbuff_term_t const *tt);
size_t fr_sbuff_adv_past_allowed(fr_sbuff_t *sbuff, size_t len, bool const allowed[static UINT8_MAX + 1]);
TEST_CHECK(fr_sbuff_init_file(&sbuff, &fctx, buff, sizeof(buff), fp, 128) == &sbuff);
TEST_CASE("Advance past whitespace, which will require shift/extend");
- TEST_CHECK_LEN(sizeof(fbuff) - 6, fr_sbuff_adv_past_whitespace(&sbuff, SIZE_MAX));
+ TEST_CHECK_LEN(sizeof(fbuff) - 6, fr_sbuff_adv_past_whitespace(&sbuff, SIZE_MAX, NULL));
TEST_CASE("Verify that we passed all and only whitespace");
(void) fr_sbuff_out_abstrncpy(NULL, &post_ws, &sbuff, 24);
TEST_CHECK_STRCMP(post_ws, "xyzzy");
TEST_CASE("Check for token at beginning of string");
fr_sbuff_init(&sbuff, in, sizeof(in));
- TEST_CHECK_LEN(fr_sbuff_adv_past_whitespace(&sbuff, SIZE_MAX), 5);
+ TEST_CHECK_LEN(fr_sbuff_adv_past_whitespace(&sbuff, SIZE_MAX, NULL), 5);
TEST_CHECK_STRCMP(sbuff.p, "i am a test string");
TEST_CASE("Check for token not at beginning of string");
fr_sbuff_init(&sbuff, in_ns, sizeof(in_ns));
- TEST_CHECK_LEN(fr_sbuff_adv_past_whitespace(&sbuff, SIZE_MAX), 0);
+ TEST_CHECK_LEN(fr_sbuff_adv_past_whitespace(&sbuff, SIZE_MAX, NULL), 0);
TEST_CHECK_STRCMP(sbuff.p, "i am a test string");
TEST_CASE("Check for token with zero length string");
fr_sbuff_init(&sbuff, in, 0 + 1);
- TEST_CHECK_LEN(fr_sbuff_adv_past_whitespace(&sbuff, SIZE_MAX), 0);
+ TEST_CHECK_LEN(fr_sbuff_adv_past_whitespace(&sbuff, SIZE_MAX, NULL), 0);
TEST_CASE("Check for token that is the string");
fr_sbuff_init(&sbuff, in_ws, sizeof(in_ws));
- TEST_CHECK_LEN(fr_sbuff_adv_past_whitespace(&sbuff, SIZE_MAX), 5);
+ TEST_CHECK_LEN(fr_sbuff_adv_past_whitespace(&sbuff, SIZE_MAX, NULL), 5);
TEST_CASE("Length constraint with token match");
fr_sbuff_init(&sbuff, in, sizeof(in));
- TEST_CHECK_LEN(fr_sbuff_adv_past_whitespace(&sbuff, 2), 2);
+ TEST_CHECK_LEN(fr_sbuff_adv_past_whitespace(&sbuff, 2, NULL), 2);
TEST_CHECK_STRCMP(sbuff.p, " i am a test string");
TEST_CASE("Length constraint without token match");
fr_sbuff_init(&sbuff, in_ns, sizeof(in_ns));
- TEST_CHECK_LEN(fr_sbuff_adv_past_whitespace(&sbuff, 2), 0);
+ TEST_CHECK_LEN(fr_sbuff_adv_past_whitespace(&sbuff, 2, NULL), 0);
TEST_CHECK_STRCMP(sbuff.p, "i am a test string");
}
}
sbuff = FR_SBUFF_IN((*in)->vb_strvalue, (*in)->vb_length);
- fr_sbuff_adv_past_whitespace(&sbuff, SIZE_MAX);
+ fr_sbuff_adv_past_whitespace(&sbuff, SIZE_MAX, NULL);
/*
* Iterate through the list of attribute templates in the xlat. For each
TALLOC_FREE(vpt);
/* Jump forward to next attr */
- fr_sbuff_adv_past_whitespace(&sbuff, SIZE_MAX);
+ fr_sbuff_adv_past_whitespace(&sbuff, SIZE_MAX, NULL);
}
/*