ProtoCore v1.0.16
Deterministic, zero-heap network stack for embedded targets
Loading...
Searching...
No Matches
config_io.h
Go to the documentation of this file.
1// ProtoCore v1.0.16 - Copyright (C) 2026 Douglas Quigg (dstroy0) <dquigg123@gmail.com>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4/**
5 * @file config_io.h
6 * @brief Schema-driven config export / restore (PROTOCORE_ENABLE_CONFIG_IO).
7 *
8 * The app declares a fixed schema - an array of {key, type} fields - and this
9 * service serializes their current values from the config store to a portable
10 * `key=value` text blob (one field per line) for backup / migration, and parses
11 * such a blob back into the store for restore / bulk provisioning. Schema-driven
12 * (rather than enumerating NVS) keeps it deterministic and zero-heap; the
13 * serialize / parse round-trip is host-tested against the in-memory config store.
14 *
15 * @author Douglas Quigg (dstroy0)
16 * @date 2026
17 */
18
19#ifndef PROTOCORE_CONFIG_IO_H
20#define PROTOCORE_CONFIG_IO_H
21
22#include "protocore_config.h" // the entry point: protocore_types.h for the widths
23
24#if PROTOCORE_ENABLE_CONFIG_IO
25
27
28// This module holds nothing between calls, so it carves no borrow and states none. An entry
29// takes one all the same, and never reads it, so every namespace in the tree is invoked the
30// same way.
31
32/** @brief Type of a config field (selects the typed get/set used). */
33typedef enum PROTO_ENUM_PACKED
34{
35 PROTOCORE_CFG_STR = 0, ///< null-terminated string.
36 PROTOCORE_CFG_U32 = 1, ///< unsigned 32-bit integer (serialized as decimal).
37} protocore_cfg_type;
38
39/** @brief One field in an export/restore schema. */
40typedef struct
41{
42 const char *key; ///< config-store key (<= 15 chars).
43 protocore_cfg_type type; ///< the field's value type.
44} protocore_cfg_field;
45
46/** @brief What export takes: ns, fields, n, out, cap. */
47typedef struct
48{
49 const char *ns;
50 const protocore_cfg_field *fields;
51 size_t n;
52 char *out;
53 size_t cap;
54} ConfigIoExportArgs;
55
56/** @brief What import takes: ns, fields, n, text, len. */
57typedef struct
58{
59 const char *ns;
60 const protocore_cfg_field *fields;
61 size_t n;
62 const char *text;
63 size_t len;
64} ConfigIoImportArgs;
65
66/**
67 * @brief Schema-driven config export / restore (PROTOCORE_ENABLE_CONFIG_IO). The app declares a fixed schema - an ...
68 *
69 * A caller sets the members a call takes, invokes it through ::ConfigIo with the bytes it runs
70 * out of, and reads the outcome off the same handle.
71 *
72 * ConfigIo.export_args.ns = ...;
73 * ConfigIo.export_args.fields = ...;
74 * ConfigIo.export_args.n = ...;
75 * ConfigIo.export_args.out = ...;
76 * ConfigIo.export_args.cap = ...;
77 * ConfigIo.export(work);
78 * // ConfigIo.n is what the call reports
79 *
80 * @var ConfigIoNs::export_args what export takes: ns, fields, n, out, cap
81 * @var ConfigIoNs::import_args what import takes: ns, fields, n, text, len
82 * @var ConfigIoNs::ok a call's true/false outcome
83 * @var ConfigIoNs::n characters written, or 0 on a too-small buffer / failure ...
84 * @var ConfigIoNs::export export the schema's current values from namespace ns as `key=value` ...
85 * @var ConfigIoNs::import import `key=value` lines from text into namespace ns, writing each ...
86 *
87 * @c work is bytes the CALLER holds. This module reads none of them: it carries nothing
88 * between calls, so there is no state to keep and nothing to wipe. The parameter is there so
89 * a caller drives every namespace the same way.
90 */
91typedef struct
92{
93 ConfigIoExportArgs export_args;
94 ConfigIoImportArgs import_args;
95 proto_bool ok;
96 int n;
97} ConfigIoVars;
98
99/** @brief The operands and the outcome. */
100extern ConfigIoVars ConfigIoV;
101
102/** @brief The entries. */
103typedef struct
104{
105 void (*const export)(uint8_t *work);
106 void (*const import)(uint8_t *work);
107} ConfigIoNs;
108
109// What the table binds, defined once in the .c and taking one parameter each: everything
110// else an entry needs is an operand in ConfigIoV or a region of the borrow at a fixed offset.
111void protocore_config_io_export(uint8_t *work);
112void protocore_config_io_import(uint8_t *work);
113
114// `static const`, initialised HERE rather than `extern` against a definition in the .c: a
115// const object whose initializer every translation unit can see is a COMPILE-TIME FACT, so
116// `ConfigIo.export(work)` resolves to a named function and becomes a DIRECT call. An extern table
117// leaves the call indirect and the symbol live at every level, -O2 -flto included.
118static const ConfigIoNs ConfigIo __attribute__((unused)) = {
119 .export = protocore_config_io_export,
120 .import = protocore_config_io_import,
121};
122
124
125#endif // PROTOCORE_ENABLE_CONFIG_IO
126
127#endif // PROTOCORE_CONFIG_IO_H
PROTO_ENUM_PACKED
Application protocol spoken on a listener port or connection slot.
#define PROTOCORE_BEGIN_DECLS
Give a header's declarations C linkage, so their symbol names carry no parameter types.
Definition types.h:96
_Bool proto_bool
The truth value.
Definition types.h:64
#define PROTOCORE_END_DECLS
Definition types.h:97