DeterministicESPAsyncWebServer v6.27.1
Zero-allocation, bounded-execution async HTTP server for ESP32
Loading...
Searching...
No Matches
docstore.cpp
Go to the documentation of this file.
1// Copyright (C) 2026 Douglas Quigg (dstroy0) <dquigg123@gmail.com>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4/**
5 * @file docstore.cpp
6 * @brief Local JSON document store on the WAL: dbm + top-level JSON field queries (see docstore.h).
7 */
8
10
11#if DETWS_ENABLE_DOCSTORE
12
14#include <string.h>
15
16void detws_docstore_open(DetwsDocStore *ds, DetwsDbm *db)
17{
18 ds->db = db;
19}
20
21bool detws_docstore_put(DetwsDocStore *ds, const char *id, uint16_t id_len, const uint8_t *json, uint32_t json_len)
22{
23 return detws_dbm_put(ds->db, id, id_len, json, json_len);
24}
25
26long detws_docstore_get(DetwsDocStore *ds, const char *id, uint16_t id_len, uint8_t *buf, size_t cap)
27{
28 return detws_dbm_get(ds->db, id, id_len, buf, cap);
29}
30
31bool detws_docstore_del(DetwsDocStore *ds, const char *id, uint16_t id_len)
32{
33 return detws_dbm_del(ds->db, id, id_len);
34}
35
36bool detws_docstore_contains(DetwsDocStore *ds, const char *id, uint16_t id_len)
37{
38 return detws_dbm_contains(ds->db, id, id_len);
39}
40
41uint32_t detws_docstore_count(DetwsDocStore *ds)
42{
43 return detws_dbm_count(ds->db);
44}
45
46bool detws_docstore_sync(DetwsDocStore *ds)
47{
48 return detws_dbm_sync(ds->db);
49}
50
51namespace
52{
53enum class FindKind : uint8_t
54{
55 FIND_STR,
56 FIND_INT,
57 FIND_BOOL
58};
59
60// Per-scan state carried through detws_dbm_iterate. `doc` reads each document's JSON body (NUL-terminated
61// for the reader); `fieldtmp` extracts a string field for comparison. Both are bounded (no heap).
62struct FindCtx
63{
64 DetwsDbm *db;
65 const char *field;
66 FindKind kind;
67 const char *sval;
68 long ival;
69 bool bval;
70 DetwsDocMatchCb user_cb;
71 void *user_ctx;
72 uint32_t matches;
73 uint8_t doc[DETWS_DBM_VAL_MAX + 1];
74 char fieldtmp[DETWS_DOCSTORE_FIELD_MAX + 1];
75};
76
77bool find_cb(const char *key, uint16_t key_len, void *vctx)
78{
79 FindCtx *f = (FindCtx *)vctx;
80 long n = detws_dbm_get(f->db, key, key_len, f->doc, DETWS_DBM_VAL_MAX);
81 if (n < 0)
82 return true; // unreadable (shouldn't happen mid-iteration) - skip
83 f->doc[n] = 0; // the JSON reader wants a NUL-terminated body
84 const char *json = (const char *)f->doc;
85
86 bool match = false;
87 if (f->kind == FindKind::FIND_STR)
88 {
89 if (json_get_str(json, f->field, f->fieldtmp, sizeof(f->fieldtmp)))
90 match = (strcmp(f->fieldtmp, f->sval) == 0);
91 }
92 else if (f->kind == FindKind::FIND_INT)
93 {
94 long v = 0;
95 if (json_get_int(json, f->field, &v))
96 match = (v == f->ival);
97 }
98 else
99 {
100 bool b = false;
101 if (json_get_bool(json, f->field, &b))
102 match = (b == f->bval);
103 }
104
105 if (match)
106 {
107 f->matches++;
108 if (f->user_cb && !f->user_cb(key, key_len, f->doc, (uint32_t)n, f->user_ctx))
109 return false; // caller asked to stop
110 }
111 return true;
112}
113
114uint32_t run_find(FindCtx *f)
115{
116 f->matches = 0;
117 detws_dbm_iterate(f->db, find_cb, f);
118 return f->matches;
119}
120} // namespace
121
122uint32_t detws_docstore_find_str(DetwsDocStore *ds, const char *field, const char *value, DetwsDocMatchCb cb, void *ctx)
123{
124 FindCtx f;
125 f.db = ds->db;
126 f.field = field;
127 f.kind = FindKind::FIND_STR;
128 f.sval = value;
129 f.user_cb = cb;
130 f.user_ctx = ctx;
131 return run_find(&f);
132}
133
134uint32_t detws_docstore_find_int(DetwsDocStore *ds, const char *field, long value, DetwsDocMatchCb cb, void *ctx)
135{
136 FindCtx f;
137 f.db = ds->db;
138 f.field = field;
139 f.kind = FindKind::FIND_INT;
140 f.ival = value;
141 f.user_cb = cb;
142 f.user_ctx = ctx;
143 return run_find(&f);
144}
145
146uint32_t detws_docstore_find_bool(DetwsDocStore *ds, const char *field, bool value, DetwsDocMatchCb cb, void *ctx)
147{
148 FindCtx f;
149 f.db = ds->db;
150 f.field = field;
151 f.kind = FindKind::FIND_BOOL;
152 f.bval = value;
153 f.user_cb = cb;
154 f.user_ctx = ctx;
155 return run_find(&f);
156}
157
158#endif // DETWS_ENABLE_DOCSTORE
#define DETWS_DBM_VAL_MAX
#define DETWS_DOCSTORE_FIELD_MAX
Local JSON document store on the WAL (DETWS_ENABLE_DOCSTORE, requires DBM + WAL).
bool json_get_str(const char *json, const char *key, char *out, size_t out_cap)
Read a top-level string member from a JSON object body.
Definition json.cpp:512
bool json_get_bool(const char *json, const char *key, bool *out)
Read a top-level boolean member (true/false) from a JSON object body.
Definition json.cpp:567
bool json_get_int(const char *json, const char *key, long *out)
Read a top-level integer member from a JSON object body.
Definition json.cpp:552
Layer 6 (Presentation) - zero-heap JSON: a bounded writer and top-level reader.