ProtoCore v0.0.2
Deterministic, zero-heap network stack for embedded targets
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 PC_ENABLE_DOCSTORE
12
14#include <string.h>
15
16void pc_docstore_open(pc_doc_store *ds, pc_dbm *db)
17{
18 ds->db = db;
19}
20
21bool pc_docstore_put(pc_doc_store *ds, const char *id, uint16_t id_len, const uint8_t *json, uint32_t json_len)
22{
23 return pc_dbm_put(ds->db, id, id_len, json, json_len);
24}
25
26long pc_docstore_get(pc_doc_store *ds, const char *id, uint16_t id_len, uint8_t *buf, size_t cap)
27{
28 return pc_dbm_get(ds->db, id, id_len, buf, cap);
29}
30
31bool pc_docstore_del(pc_doc_store *ds, const char *id, uint16_t id_len)
32{
33 return pc_dbm_del(ds->db, id, id_len);
34}
35
36bool pc_docstore_contains(const pc_doc_store *ds, const char *id, uint16_t id_len)
37{
38 return pc_dbm_contains(ds->db, id, id_len);
39}
40
41uint32_t pc_docstore_count(const pc_doc_store *ds)
42{
43 return pc_dbm_count(ds->db);
44}
45
46bool pc_docstore_sync(pc_doc_store *ds)
47{
48 return pc_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 pc_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 pc_dbm *db;
65 const char *field;
66 FindKind kind;
67 const char *sval;
68 long ival;
69 bool bval;
70 pc_doc_match_cb user_cb;
71 void *user_ctx;
72 uint32_t matches;
73 uint8_t doc[PC_DBM_VAL_MAX + 1];
74 char fieldtmp[PC_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 = pc_dbm_get(f->db, key, key_len, f->doc, PC_DBM_VAL_MAX);
81 if (n < 0)
82 {
83 return true; // unreadable (shouldn't happen mid-iteration) - skip
84 }
85 f->doc[n] = 0; // the JSON reader wants a NUL-terminated body
86 const char *json = (const char *)f->doc;
87
88 bool match = false;
89 if (f->kind == FindKind::FIND_STR)
90 {
91 if (json_get_str(json, f->field, f->fieldtmp, sizeof(f->fieldtmp)))
92 {
93 match = (strcmp(f->fieldtmp, f->sval) == 0);
94 }
95 }
96 else if (f->kind == FindKind::FIND_INT)
97 {
98 long v = 0;
99 if (json_get_int(json, f->field, &v))
100 {
101 match = (v == f->ival);
102 }
103 }
104 else
105 {
106 bool b = false;
107 if (json_get_bool(json, f->field, &b))
108 {
109 match = (b == f->bval);
110 }
111 }
112
113 if (match)
114 {
115 f->matches++;
116 if (f->user_cb && !f->user_cb(key, key_len, f->doc, (uint32_t)n, f->user_ctx))
117 {
118 return false; // caller asked to stop
119 }
120 }
121 return true;
122}
123
124uint32_t run_find(FindCtx *f)
125{
126 f->matches = 0;
127 pc_dbm_iterate(f->db, find_cb, f);
128 return f->matches;
129}
130} // namespace
131
132uint32_t pc_docstore_find_str(pc_doc_store *ds, const char *field, const char *value, pc_doc_match_cb cb, void *ctx)
133{
134 FindCtx f;
135 f.db = ds->db;
136 f.field = field;
137 f.kind = FindKind::FIND_STR;
138 f.sval = value;
139 f.user_cb = cb;
140 f.user_ctx = ctx;
141 return run_find(&f);
142}
143
144uint32_t pc_docstore_find_int(pc_doc_store *ds, const char *field, long value, pc_doc_match_cb cb, void *ctx)
145{
146 FindCtx f;
147 f.db = ds->db;
148 f.field = field;
149 f.kind = FindKind::FIND_INT;
150 f.ival = value;
151 f.user_cb = cb;
152 f.user_ctx = ctx;
153 return run_find(&f);
154}
155
156uint32_t pc_docstore_find_bool(pc_doc_store *ds, const char *field, bool value, pc_doc_match_cb cb, void *ctx)
157{
158 FindCtx f;
159 f.db = ds->db;
160 f.field = field;
161 f.kind = FindKind::FIND_BOOL;
162 f.bval = value;
163 f.user_cb = cb;
164 f.user_ctx = ctx;
165 return run_find(&f);
166}
167
168#endif // PC_ENABLE_DOCSTORE
Local JSON document store on the WAL (PC_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:577
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:644
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:623
Layer 6 (Presentation) - zero-heap JSON: a bounded writer and top-level reader.
#define PC_DOCSTORE_FIELD_MAX
#define PC_DBM_VAL_MAX