]> git.kaiwu.me - haproxy.git/commitdiff
MINOR: mjson: reintroduce mjson_next()
authorWilliam Lallemand <wlallemand@haproxy.com>
Tue, 14 Apr 2026 08:25:30 +0000 (10:25 +0200)
committerWilliam Lallemand <wlallemand@haproxy.com>
Tue, 14 Apr 2026 08:57:21 +0000 (10:57 +0200)
The lack of mjson_next() prevents to iterate easily and need to hack by
iterating on a loop of snprintf + $.field[XXX] combined with
mjson_find().

This reintroduce mjson_next() so we could iterate without having to
build the string.

The patch does not reintroduce MJSON_ENABLE_NEXT so it could be used
without having to define it.

include/import/mjson.h
src/mjson.c

index 043ca2b699e2614a57e82de88e5a08463cf43ead..4bfdc81d569d70bccacfd016f72bc8762518ccc4 100644 (file)
@@ -54,4 +54,7 @@ int mjson_get_bool(const char *s, int len, const char *path, int *v);
 int mjson_get_string(const char *s, int len, const char *path, char *to, int n);
 int mjson_get_hex(const char *s, int len, const char *path, char *to, int n);
 
+int mjson_next(const char *s, int n, int off, int *koff, int *klen, int *voff,
+               int *vlen, int *vtype);
+
 #endif  // MJSON_H
index 19c204e73ed7604a4c50fb50bf2a963edaba21ea..0012f0c50f2a13b674462c19fee7cbcbcb4de798 100644 (file)
@@ -338,6 +338,76 @@ int mjson_get_hex(const char *s, int len, const char *x, char *to, int n) {
   return j;
 }
 
+struct nextdata {
+  int off, len, depth, t, vo, arrayindex;
+  int *koff, *klen, *voff, *vlen, *vtype;
+};
+
+static int next_cb(int tok, const char *s, int off, int len, void *ud) {
+  struct nextdata *d = (struct nextdata *) ud;
+  // int i;
+  switch (tok) {
+    case '{':
+    case '[':
+      if (d->depth == 0 && tok == '[') d->arrayindex = 0;
+      if (d->depth == 1 && off > d->off) {
+        d->vo = off;
+        d->t = tok == '{' ? MJSON_TOK_OBJECT : MJSON_TOK_ARRAY;
+        if (d->voff) *d->voff = off;
+        if (d->vtype) *d->vtype = d->t;
+      }
+      d->depth++;
+      break;
+    case '}':
+    case ']':
+      d->depth--;
+      if (d->depth == 1 && d->vo) {
+        d->len = off + len;
+        if (d->vlen) *d->vlen = d->len - d->vo;
+        if (d->arrayindex >= 0) {
+          if (d->koff) *d->koff = d->arrayindex;  // koff holds array index
+          if (d->klen) *d->klen = 0;              // klen holds 0
+        }
+        return 1;
+      }
+      if (d->depth == 1 && d->arrayindex >= 0) d->arrayindex++;
+      break;
+    case ',':
+    case ':':
+      break;
+    case MJSON_TOK_KEY:
+      if (d->depth == 1 && d->off < off) {
+        if (d->koff) *d->koff = off;  // And report back to the user
+        if (d->klen) *d->klen = len;  // If we have to
+      }
+      break;
+    default:
+      if (d->depth != 1) break;
+      // If we're iterating over the array
+      if (off > d->off) {
+        d->len = off + len;
+        if (d->vlen) *d->vlen = len;    // value length
+        if (d->voff) *d->voff = off;    // value offset
+        if (d->vtype) *d->vtype = tok;  // value type
+        if (d->arrayindex >= 0) {
+          if (d->koff) *d->koff = d->arrayindex;  // koff holds array index
+          if (d->klen) *d->klen = 0;              // klen holds 0
+        }
+        return 1;
+      }
+      if (d->arrayindex >= 0) d->arrayindex++;
+      break;
+  }
+  (void) s;
+  return 0;
+}
+
+int mjson_next(const char *s, int n, int off, int *koff, int *klen, int *voff,
+               int *vlen, int *vtype) {
+  struct nextdata d = {off, 0, 0, 0, 0, -1, koff, klen, voff, vlen, vtype};
+  mjson(s, n, next_cb, &d);
+  return d.len;
+}
 static int is_digit(int c) {
   return c >= '0' && c <= '9';
 }