]> git.ozlabs.org Git - ccan/commitdiff
ccan/rune: simplify check helper interfaces, allow explicit string lengths.
authorRusty Russell <rusty@rustcorp.com.au>
Sat, 2 Jul 2022 05:36:14 +0000 (15:06 +0930)
committerRusty Russell <rusty@rustcorp.com.au>
Sat, 2 Jul 2022 05:36:14 +0000 (15:06 +0930)
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
ccan/rune/_info
ccan/rune/rune.c
ccan/rune/rune.h
ccan/rune/test/run-alt-lexicographic-order.c [new file with mode: 0644]
ccan/rune/test/run.c

index aaed15d871eb21ea37b521c94e8943a1a2c14ad8..2b2e2e8b98e8cbb686c20520e22090813c5a5f67 100644 (file)
  *     // 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");
index 19d55c5490fb60a28f05d1819ec0acb9b32ff4bb..0ff7968b4aa9b093f42bb5febdd6fb4b455b8e25 100644 (file)
@@ -5,6 +5,7 @@
 #include <inttypes.h>
 #include <stdio.h>
 #include <ccan/endian/endian.h>
+#include <ccan/mem/mem.h>
 #include <ccan/tal/str/str.h>
 #include <ccan/rune/rune.h>
 #include <ccan/rune/internal.h>
@@ -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,
index 59406db3637754032f365ae31d37cbcf4e730305..b67b78281edad3ba2659b1a54798f932e78840f6 100644 (file)
@@ -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 (file)
index 0000000..a37ee58
--- /dev/null
@@ -0,0 +1,33 @@
+#include <ccan/rune/rune.c>
+#include <ccan/rune/coding.c>
+#include <ccan/tal/str/str.h>
+#include <ccan/tap/tap.h>
+
+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();
+}
index 6cf33a3dceefce6114f55a70e5354f7f5e211dc0..86737b86be11d2d338a8dd62674ec7ae99c0dc78 100644 (file)
@@ -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)