rune: add helpers for users doing DIY parsing. master
authorRusty Russell <rusty@rustcorp.com.au>
Thu, 18 Aug 2022 03:32:16 +0000 (13:02 +0930)
committerRusty Russell <rusty@rustcorp.com.au>
Thu, 18 Aug 2022 03:32:16 +0000 (13:02 +0930)
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
ccan/rune/coding.c
ccan/rune/rune.h

index 380a225c948319c66dbb5e004383e8bd07dc28f5..f4d110283245cfa5db4e486f283cfdb7bd709c90 100644 (file)
@@ -184,7 +184,7 @@ static bool pull_char(const char **data, size_t *len, char *c)
        return true;
 }
 
-static bool is_valid_cond(enum rune_condition cond)
+bool rune_condition_is_valid(enum rune_condition cond)
 {
        switch (cond) {
        case RUNE_COND_IF_MISSING:
@@ -203,31 +203,35 @@ static bool is_valid_cond(enum rune_condition cond)
        return false;
 }
 
+size_t rune_altern_fieldname_len(const char *alternstr, size_t alternstrlen)
+{
+       for (size_t i = 0; i < alternstrlen; i++) {
+               if (cispunct(alternstr[i]))
+                       return i;
+       }
+       return alternstrlen;
+}
+
 /* Sets *more on success: true if another altern follows */
 static struct rune_altern *rune_altern_decode(const tal_t *ctx,
                                              const char **data, size_t *len,
                                              bool *more)
 {
        struct rune_altern *alt = tal(ctx, struct rune_altern);
-       const char *strstart = *data;
        char *value;
-       size_t strlen = 0;
+       size_t strlen;
        char c;
 
-        /* Swallow field up to conditional */
-       for (;;) {
-               if (!pull_char(data, len, &c))
-                       return tal_free(alt);
-               if (cispunct(c))
-                       break;
-               strlen++;
-       }
+        /* Swallow field up to possible conditional */
+       strlen = rune_altern_fieldname_len(*data, *len);
+       alt->fieldname = tal_strndup(alt, *data, strlen);
+       *data += strlen;
+       *len -= strlen;
 
-       alt->fieldname = tal_strndup(alt, strstart, strlen);
-       if (!is_valid_cond(c)) {
-               pull_invalid(data, len);
+       /* Grab conditional */
+       if (!pull_char(data, len, &c) || !rune_condition_is_valid(c))
                return tal_free(alt);
-       }
+
        alt->condition = c;
 
        /* Assign worst case. */
index b67b78281edad3ba2659b1a54798f932e78840f6..c373269aa0c90fcf4372b8b67a7097da71c43418 100644 (file)
@@ -376,4 +376,25 @@ char *rune_to_string(const tal_t *ctx, const struct rune *rune);
 struct rune_restr *rune_restr_from_string(const tal_t *ctx,
                                          const char *str,
                                          size_t len);
+
+/**
+ * rune_condition_is_valid: is this a valid condition?
+ * @cond: potential condition character.
+ *
+ * Returns true if it's one of enum rune_condition.
+ */
+bool rune_condition_is_valid(enum rune_condition cond);
+
+/**
+ * rune_altern_fieldname_len: how much of this string is condition?
+ * @alternstr: potential alternative string
+ * @alternstrlen: length
+ *
+ * This helps parsing your own runes.
+ *
+ * Returns the first possible condition (check with rune_condition_is_valid)
+ * or alternstrlen if none found.
+ */
+size_t rune_altern_fieldname_len(const char *alternstr, size_t alternstrlen);
+
 #endif /* CCAN_RUNE_RUNE_H */