|
3 | 3 | * @file Simple.hpp |
4 | 4 | * @author Gaspard Kirira |
5 | 5 | * |
6 | | - * Copyright 2025, Gaspard Kirira. All rights reserved. |
| 6 | + * Copyright 2025, Gaspard Kirira. |
| 7 | + * All rights reserved. |
7 | 8 | * https://github.com/vixcpp/vix |
| 9 | + * |
8 | 10 | * Use of this source code is governed by a MIT license |
9 | 11 | * that can be found in the License file. |
10 | 12 | * |
11 | 13 | * Vix.cpp |
| 14 | + * |
12 | 15 | */ |
13 | 16 | #ifndef VIX_JSON_SIMPLE_HPP |
14 | 17 | #define VIX_JSON_SIMPLE_HPP |
|
18 | 21 | * @brief Minimal JSON-like data model for lightweight Vix internal APIs. |
19 | 22 | * |
20 | 23 | * @details |
21 | | - * `vix::json::Simple` provides a self-contained JSON representation for internal |
22 | | - * use, independent from `nlohmann::json`. It is designed to be header-only and |
23 | | - * trivially embeddable in performance-sensitive modules or plugins. |
| 24 | + * vix::json::Simple provides a self-contained JSON representation for internal |
| 25 | + * use, independent from nlohmann::json. It is designed to be header-only and |
| 26 | + * easily embeddable in performance-sensitive modules or plugins. |
24 | 27 | * |
25 | 28 | * Features: |
26 | | - * - `token`: a tagged variant supporting scalars, arrays, and objects. |
27 | | - * - `array_t`: a flat sequence of tokens. |
28 | | - * - `kvs`: a flattened key/value list representing JSON objects. |
29 | | - * - Helper functions (`obj()` and `array()`) for quick construction. |
30 | | - * - Implicit constructors for nesting (tokens can wrap `array_t` or `kvs`). |
| 29 | + * - token: a tagged variant supporting scalars, arrays, and objects. |
| 30 | + * - array_t: a flat sequence of tokens representing JSON arrays. |
| 31 | + * - kvs: a flattened key/value list representing JSON objects. |
| 32 | + * - Helper functions (obj() and array()) for quick construction. |
| 33 | + * - Implicit constructors for nesting (token can wrap array_t or kvs). |
31 | 34 | * |
32 | 35 | * Example: |
33 | | - * ```cpp |
| 36 | + * @code |
| 37 | + * #include <vix/json/Simple.hpp> |
| 38 | + * |
34 | 39 | * using namespace vix::json; |
35 | 40 | * |
36 | 41 | * kvs user = obj({ |
37 | | - * "name", "Alice", |
38 | | - * "age", 30, |
39 | | - * "skills", array({"C++", "Networking", "Systems"}) |
| 42 | + * "name", "Alice", |
| 43 | + * "age", 30, |
| 44 | + * "skills", array({"C++", "Networking", "Systems"}) |
40 | 45 | * }); |
41 | 46 | * |
42 | 47 | * token t = user; // convertible to token |
43 | | - * ``` |
| 48 | + * @endcode |
44 | 49 | * |
45 | | - * ### Design notes |
46 | | - * - This type avoids dynamic JSON parsing/serialization overhead when |
47 | | - * interoperating between different internal JSON adapters. |
48 | | - * - Recursive types are handled using shared_ptr wrappers. |
| 50 | + * Design notes: |
| 51 | + * - This type avoids JSON parsing and serialization overhead when moving data |
| 52 | + * between internal adapters. |
| 53 | + * - Recursive types are represented using shared_ptr wrappers to keep token |
| 54 | + * trivially copyable. |
49 | 55 | */ |
50 | 56 |
|
51 | 57 | #include <string> |
|
57 | 63 |
|
58 | 64 | namespace vix::json |
59 | 65 | { |
60 | | - |
| 66 | + /** |
| 67 | + * @brief Forward declaration for JSON array representation. |
| 68 | + */ |
61 | 69 | struct array_t; |
| 70 | + |
| 71 | + /** |
| 72 | + * @brief Forward declaration for JSON object representation (flattened kv pairs). |
| 73 | + */ |
62 | 74 | struct kvs; |
63 | 75 |
|
| 76 | + /** |
| 77 | + * @struct token |
| 78 | + * @brief A tagged variant representing a JSON-like value. |
| 79 | + * |
| 80 | + * Supported types: |
| 81 | + * - null (std::monostate) |
| 82 | + * - bool |
| 83 | + * - integer (long long) |
| 84 | + * - floating point (double) |
| 85 | + * - string (std::string) |
| 86 | + * - array (std::shared_ptr<array_t>) |
| 87 | + * - object (std::shared_ptr<kvs>) |
| 88 | + * |
| 89 | + * Arrays and objects are stored via shared_ptr to allow recursion while |
| 90 | + * keeping token copyable and lightweight. |
| 91 | + */ |
64 | 92 | struct token |
65 | 93 | { |
| 94 | + /** |
| 95 | + * @brief Underlying variant type for the token. |
| 96 | + */ |
66 | 97 | using value_t = std::variant< |
67 | | - std::monostate, // null |
| 98 | + std::monostate, |
68 | 99 | bool, |
69 | | - long long, // integer (64-bit) |
| 100 | + long long, |
70 | 101 | double, |
71 | 102 | std::string, |
72 | | - std::shared_ptr<array_t>, // array |
73 | | - std::shared_ptr<kvs> // object |
74 | | - >; |
| 103 | + std::shared_ptr<array_t>, |
| 104 | + std::shared_ptr<kvs>>; |
75 | 105 |
|
| 106 | + /** |
| 107 | + * @brief Stored value. |
| 108 | + */ |
76 | 109 | value_t v{std::monostate{}}; |
77 | 110 |
|
| 111 | + /// @brief Default constructs a null token. |
78 | 112 | token() = default; |
| 113 | + |
| 114 | + /// @brief Construct a null token. |
79 | 115 | token(std::nullptr_t) : v(std::monostate{}) {} |
| 116 | + |
| 117 | + /// @brief Construct a boolean token. |
80 | 118 | token(bool b) : v(b) {} |
| 119 | + |
| 120 | + /// @brief Construct an integer token (int promoted to 64-bit). |
81 | 121 | token(int i) : v(static_cast<long long>(i)) {} |
| 122 | + |
| 123 | + /// @brief Construct an integer token (64-bit). |
82 | 124 | token(long long i) : v(i) {} |
| 125 | + |
| 126 | + /// @brief Construct a floating point token. |
83 | 127 | token(double d) : v(d) {} |
| 128 | + |
| 129 | + /// @brief Construct a string token from a C-string. |
84 | 130 | token(const char *s) : v(std::string(s)) {} |
| 131 | + |
| 132 | + /// @brief Construct a string token by value (moved into storage). |
85 | 133 | token(std::string s) : v(std::move(s)) {} |
86 | 134 |
|
| 135 | + /** |
| 136 | + * @brief Construct an object token from kvs. |
| 137 | + * |
| 138 | + * @param obj Object representation. |
| 139 | + */ |
87 | 140 | token(const kvs &obj); |
| 141 | + |
| 142 | + /** |
| 143 | + * @brief Construct an array token from array_t. |
| 144 | + * |
| 145 | + * @param arr Array representation. |
| 146 | + */ |
88 | 147 | token(const array_t &arr); |
89 | 148 | }; |
90 | 149 |
|
| 150 | + /** |
| 151 | + * @struct kvs |
| 152 | + * @brief Flattened key/value list representing a JSON object. |
| 153 | + * |
| 154 | + * The vector is expected to contain alternating tokens: |
| 155 | + * key0, value0, key1, value1, ... |
| 156 | + * Keys are typically string tokens. |
| 157 | + */ |
91 | 158 | struct kvs |
92 | 159 | { |
| 160 | + /** |
| 161 | + * @brief Flat key/value token list. |
| 162 | + */ |
93 | 163 | std::vector<token> flat{}; |
94 | 164 |
|
| 165 | + /// @brief Default construct an empty object. |
95 | 166 | kvs() = default; |
| 167 | + |
| 168 | + /** |
| 169 | + * @brief Construct from an initializer list. |
| 170 | + * |
| 171 | + * @param list Tokens in flattened key/value order. |
| 172 | + */ |
96 | 173 | kvs(std::initializer_list<token> list) : flat(list) {} |
| 174 | + |
| 175 | + /** |
| 176 | + * @brief Construct from a vector (copy). |
| 177 | + * |
| 178 | + * @param v Token vector. |
| 179 | + */ |
97 | 180 | explicit kvs(const std::vector<token> &v) : flat(v) {} |
| 181 | + |
| 182 | + /** |
| 183 | + * @brief Construct from a vector (move). |
| 184 | + * |
| 185 | + * @param v Token vector. |
| 186 | + */ |
98 | 187 | explicit kvs(std::vector<token> &&v) : flat(std::move(v)) {} |
99 | 188 | }; |
100 | 189 |
|
| 190 | + /** |
| 191 | + * @struct array_t |
| 192 | + * @brief Token list representing a JSON array. |
| 193 | + */ |
101 | 194 | struct array_t |
102 | 195 | { |
| 196 | + /** |
| 197 | + * @brief Array elements. |
| 198 | + */ |
103 | 199 | std::vector<token> elems; |
104 | 200 |
|
| 201 | + /// @brief Default construct an empty array. |
105 | 202 | array_t() = default; |
| 203 | + |
| 204 | + /** |
| 205 | + * @brief Construct from an initializer list. |
| 206 | + * |
| 207 | + * @param l List of elements. |
| 208 | + */ |
106 | 209 | array_t(std::initializer_list<token> l) : elems(l) {} |
| 210 | + |
| 211 | + /** |
| 212 | + * @brief Construct from a vector (copy). |
| 213 | + * |
| 214 | + * @param v Element vector. |
| 215 | + */ |
107 | 216 | explicit array_t(const std::vector<token> &v) : elems(v) {} |
| 217 | + |
| 218 | + /** |
| 219 | + * @brief Construct from a vector (move). |
| 220 | + * |
| 221 | + * @param v Element vector. |
| 222 | + */ |
108 | 223 | explicit array_t(std::vector<token> &&v) : elems(std::move(v)) {} |
109 | 224 | }; |
110 | 225 |
|
| 226 | + /** |
| 227 | + * @brief Create an object token by storing a shared_ptr to a kvs copy. |
| 228 | + */ |
111 | 229 | inline token::token(const kvs &obj) : v(std::make_shared<kvs>(obj)) {} |
| 230 | + |
| 231 | + /** |
| 232 | + * @brief Create an array token by storing a shared_ptr to an array_t copy. |
| 233 | + */ |
112 | 234 | inline token::token(const array_t &arr) : v(std::make_shared<array_t>(arr)) {} |
| 235 | + |
| 236 | + /** |
| 237 | + * @brief Helper to create an array_t from an initializer list. |
| 238 | + * |
| 239 | + * @param l Elements. |
| 240 | + * @return array_t |
| 241 | + */ |
113 | 242 | inline array_t array(std::initializer_list<token> l) { return array_t{l}; } |
| 243 | + |
| 244 | + /** |
| 245 | + * @brief Helper to create a kvs from an initializer list. |
| 246 | + * |
| 247 | + * Tokens must be passed in flattened key/value order. |
| 248 | + * |
| 249 | + * @param l Tokens. |
| 250 | + * @return kvs |
| 251 | + */ |
114 | 252 | inline kvs obj(std::initializer_list<token> l) { return kvs{l}; } |
| 253 | + |
| 254 | + /** |
| 255 | + * @brief Helper to create an array_t from a vector (copy). |
| 256 | + * |
| 257 | + * @param v Elements. |
| 258 | + * @return array_t |
| 259 | + */ |
115 | 260 | inline array_t array(const std::vector<token> &v) { return array_t{v}; } |
| 261 | + |
| 262 | + /** |
| 263 | + * @brief Helper to create an array_t from a vector (move). |
| 264 | + * |
| 265 | + * @param v Elements. |
| 266 | + * @return array_t |
| 267 | + */ |
116 | 268 | inline array_t array(std::vector<token> &&v) { return array_t{std::move(v)}; } |
| 269 | + |
| 270 | + /** |
| 271 | + * @brief Helper to create a kvs from a vector (copy). |
| 272 | + * |
| 273 | + * @param v Tokens. |
| 274 | + * @return kvs |
| 275 | + */ |
117 | 276 | inline kvs obj(const std::vector<token> &v) { return kvs{v}; } |
| 277 | + |
| 278 | + /** |
| 279 | + * @brief Helper to create a kvs from a vector (move). |
| 280 | + * |
| 281 | + * @param v Tokens. |
| 282 | + * @return kvs |
| 283 | + */ |
118 | 284 | inline kvs obj(std::vector<token> &&v) { return kvs{std::move(v)}; } |
119 | 285 |
|
120 | 286 | } // namespace vix::json |
|
0 commit comments