From: Rusty Russell Date: Sat, 2 Jul 2022 05:36:14 +0000 (+0930) Subject: ccan/rune: simplify check helper interfaces, allow explicit string lengths. X-Git-Url: http://git.ozlabs.org/?p=ccan;a=commitdiff_plain;h=7343770f9760cf95311ae0a835171ad8d3057f13 ccan/rune: simplify check helper interfaces, allow explicit string lengths. Signed-off-by: Rusty Russell --- diff --git a/ccan/rune/_info b/ccan/rune/_info index aaed15d8..2b2e2e8b 100644 --- a/ccan/rune/_info +++ b/ccan/rune/_info @@ -40,16 +40,14 @@ * // t= means current time, in seconds, as integer * if (streq(alt->fieldname, "t")) { * struct timeval now; - * s64 t; * gettimeofday(&now, NULL); - * t = now.tv_sec; - * return rune_alt_single(ctx, alt, NULL, &t); + * return rune_alt_single_int(ctx, alt, now.tv_sec); * } * if (streq(alt->fieldname, "uid")) { - * return rune_alt_single(ctx, alt, uid, NULL); + * return rune_alt_single_str(ctx, alt, uid, strlen(uid)); * } * // Otherwise, field is missing - * return rune_alt_single(ctx, alt, NULL, NULL); + * return rune_alt_single_missing(ctx, alt); * } * * int main(int argc, char *argv[]) @@ -115,6 +113,7 @@ int main(int argc, char *argv[]) printf("ccan/base64\n"); printf("ccan/crypto/sha256\n"); printf("ccan/endian\n"); + printf("ccan/mem\n"); printf("ccan/short_types\n"); printf("ccan/str/hex\n"); printf("ccan/tal/str\n"); diff --git a/ccan/rune/rune.c b/ccan/rune/rune.c index 19d55c54..0ff7968b 100644 --- a/ccan/rune/rune.c +++ b/ccan/rune/rune.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -282,20 +283,34 @@ static const char *integer_compare_valid(const tal_t *ctx, return NULL; } -const char *rune_alt_single(const tal_t *ctx, - const struct rune_altern *alt, - const char *fieldval_str, - const s64 *fieldval_int) +static int lexo_order(const char *fieldval_str, + size_t fieldval_strlen, + const char *alt) +{ + int ret = strncmp(fieldval_str, alt, fieldval_strlen); + + /* If alt is same but longer, fieldval is < */ + if (ret == 0 && strlen(alt) > fieldval_strlen) + ret = -1; + return ret; +} + +static const char *rune_alt_single(const tal_t *ctx, + const struct rune_altern *alt, + const char *fieldval_str, + size_t fieldval_strlen, + const s64 *fieldval_int) { char strfield[STR_MAX_CHARS(s64) + 1]; s64 runeval_int; const char *err; - + /* Caller can't set both! */ if (fieldval_int) { assert(!fieldval_str); sprintf(strfield, "%"PRIi64, *fieldval_int); fieldval_str = strfield; + fieldval_strlen = strlen(strfield); } switch (alt->condition) { @@ -307,27 +322,28 @@ const char *rune_alt_single(const tal_t *ctx, if (!fieldval_str) return tal_fmt(ctx, "%s not present", alt->fieldname); return cond_test(ctx, alt, "is not equal to", - streq(fieldval_str, alt->value)); + memeqstr(fieldval_str, fieldval_strlen, alt->value)); case RUNE_COND_NOT_EQUAL: if (!fieldval_str) return tal_fmt(ctx, "%s not present", alt->fieldname); return cond_test(ctx, alt, "is equal to", - !streq(fieldval_str, alt->value)); + !memeqstr(fieldval_str, fieldval_strlen, alt->value)); case RUNE_COND_BEGINS: if (!fieldval_str) return tal_fmt(ctx, "%s not present", alt->fieldname); return cond_test(ctx, alt, "does not start with", - strstarts(fieldval_str, alt->value)); + memstarts_str(fieldval_str, fieldval_strlen, alt->value)); case RUNE_COND_ENDS: if (!fieldval_str) return tal_fmt(ctx, "%s not present", alt->fieldname); return cond_test(ctx, alt, "does not end with", - strends(fieldval_str, alt->value)); + memends_str(fieldval_str, fieldval_strlen, alt->value)); case RUNE_COND_CONTAINS: if (!fieldval_str) return tal_fmt(ctx, "%s not present", alt->fieldname); return cond_test(ctx, alt, "does not contain", - strstr(fieldval_str, alt->value)); + memmem(fieldval_str, fieldval_strlen, + alt->value, strlen(alt->value))); case RUNE_COND_INT_LESS: err = integer_compare_valid(ctx, fieldval_int, alt, &runeval_int); @@ -346,12 +362,12 @@ const char *rune_alt_single(const tal_t *ctx, if (!fieldval_str) return tal_fmt(ctx, "%s not present", alt->fieldname); return cond_test(ctx, alt, "is equal to or ordered after", - strcmp(fieldval_str, alt->value) < 0); + lexo_order(fieldval_str, fieldval_strlen, alt->value) < 0); case RUNE_COND_LEXO_AFTER: if (!fieldval_str) return tal_fmt(ctx, "%s not present", alt->fieldname); return cond_test(ctx, alt, "is equal to or ordered before", - strcmp(fieldval_str, alt->value) > 0); + lexo_order(fieldval_str, fieldval_strlen, alt->value) > 0); case RUNE_COND_COMMENT: return NULL; } @@ -359,6 +375,27 @@ const char *rune_alt_single(const tal_t *ctx, abort(); } +const char *rune_alt_single_str(const tal_t *ctx, + const struct rune_altern *alt, + const char *fieldval_str, + size_t fieldval_strlen) +{ + return rune_alt_single(ctx, alt, fieldval_str, fieldval_strlen, NULL); +} + +const char *rune_alt_single_int(const tal_t *ctx, + const struct rune_altern *alt, + s64 fieldval_int) +{ + return rune_alt_single(ctx, alt, NULL, 0, &fieldval_int); +} + +const char *rune_alt_single_missing(const tal_t *ctx, + const struct rune_altern *alt) +{ + return rune_alt_single(ctx, alt, NULL, 0, NULL); +} + const char *rune_meets_criteria_(const tal_t *ctx, const struct rune *rune, const char *(*check)(const tal_t *ctx, diff --git a/ccan/rune/rune.h b/ccan/rune/rune.h index 59406db3..b67b7828 100644 --- a/ccan/rune/rune.h +++ b/ccan/rune/rune.h @@ -215,19 +215,38 @@ bool rune_restr_eq(const struct rune_restr *rest1, bool rune_eq(const struct rune *rune1, const struct rune *rune2); /** - * rune_alt_single - helper to implement check(). + * rune_alt_single_str - helper to implement check(). * @ctx: context to allocate any error return from. * @alt: alternative to test. * @fieldval_str: field value as a string. + * @fieldval_strlen: length of @fieldval_str + */ +const char *rune_alt_single_str(const tal_t *ctx, + const struct rune_altern *alt, + const char *fieldval_str, + size_t fieldval_strlen); + +/** + * rune_alt_single_int - helper to implement check(). + * @ctx: context to allocate any error return from. + * @alt: alternative to test. * @fieldval_int: field value as an integer. + */ +const char *rune_alt_single_int(const tal_t *ctx, + const struct rune_altern *alt, + s64 fieldval_int); + +/** + * rune_alt_single_missing - helper to implement check(). + * @ctx: context to allocate any error return from. + * @alt: alternative to test. * - * If the field value is missing, set neither fieldval_str nor fieldval_int, - * otherwise you must set exactly one. + * Use this if alt->fieldname is unknown (it could still pass, if + * the test is that the fieldname is missing). */ -const char *rune_alt_single(const tal_t *ctx, - const struct rune_altern *alt, - const char *fieldval_str, - const s64 *fieldval_int); +const char *rune_alt_single_missing(const tal_t *ctx, + const struct rune_altern *alt); + /** * rune_is_derived - is a rune derived from this other rune? diff --git a/ccan/rune/test/run-alt-lexicographic-order.c b/ccan/rune/test/run-alt-lexicographic-order.c new file mode 100644 index 00000000..a37ee581 --- /dev/null +++ b/ccan/rune/test/run-alt-lexicographic-order.c @@ -0,0 +1,33 @@ +#include +#include +#include +#include + +int main(void) +{ + const char *str = "test string"; + plan_tests(strlen(str) * strlen(str)); + + for (size_t i = 0; str[i]; i++) { + char *stra = strdup(str); + stra[i] = '\0'; + for (size_t j = 0; str[j]; j++) { + char *strb = strdup(str); + strb[j] = '\0'; + int lexo, strc; + + lexo = lexo_order(str, i, strb); + strc = strcmp(stra, strb); + if (strc > 0) + ok1(lexo > 0); + else if (strc < 0) + ok1(lexo < 0); + else + ok1(lexo == 0); + free(strb); + } + free(stra); + } + /* This exits depending on whether all tests passed */ + return exit_status(); +} diff --git a/ccan/rune/test/run.c b/ccan/rune/test/run.c index 6cf33a3d..86737b86 100644 --- a/ccan/rune/test/run.c +++ b/ccan/rune/test/run.c @@ -22,10 +22,10 @@ static const char *check(const tal_t *ctx, char *endp; s64 v = strtol(val, &endp, 10); if (*endp == '\0' && endp != val) - return rune_alt_single(ctx, alt, NULL, &v); + return rune_alt_single_int(ctx, alt, v); + return rune_alt_single_str(ctx, alt, val, strlen(val)); } - - return rune_alt_single(ctx, alt, val, NULL); + return rune_alt_single_missing(ctx, alt); } int main(void)