GMP 0.4.0
Generative Metaprogramming library for C++
Loading...
Searching...
No Matches
value_archive.hpp
Go to the documentation of this file.
1// ___ __ __ ___
2// / __| \/ | _ \ GMP(Generative Metaprogramming)
3// | (_ | |\/| | _/ version 0.4.0
4// \___|_| |_|_| https://github.com/lkimuk/gmp
5//
6// SPDX-FileCopyrightText: 2023-2026 Miles Li <https://www.cppmore.com/>
7// SPDX-License-Identifier: MIT
8//
9// This file is part of the GMP (Generative Metaprogramming) library.
10// Full project source: https://github.com/lkimuk/gmp
11
12#ifndef GMP_SERIALIZATION_VALUE_ARCHIVE_HPP_
13#define GMP_SERIALIZATION_VALUE_ARCHIVE_HPP_
14
15#include <cstdint>
16#include <optional>
17#include <string>
18#include <string_view>
19#include <vector>
20
23
24namespace gmp {
25
27public:
31
35
37 return put(serialization_value(v));
38 }
39
41 return put(serialization_value(v));
42 }
43
47
49 return put(serialization_value(std::string(v)));
50 }
51
54 value.reserve(size);
55 return begin(serialization_kind::array, serialization_value(std::move(value)));
56 }
57
61
64 value.reserve(size);
65 return begin(serialization_kind::object, serialization_value(std::move(value)));
66 }
67
68 serialization_result<void> write_key(std::string_view key) {
69 if (finished_) {
71 "value archive is already finished");
72 }
73 if (stack_.empty() || stack_.back().kind != serialization_kind::object) {
75 "object key outside object");
76 }
77 if (stack_.back().has_key) {
79 "object key requires a value");
80 }
81 stack_.back().key = std::string(key);
82 stack_.back().has_key = true;
83 return {};
84 }
85
89
91 if (finished_) {
93 "value archive is already finished");
94 }
95 if (!stack_.empty() || !root_) {
97 }
98 auto result = std::move(*root_);
99 root_.reset();
100 finished_ = true;
101 return result;
102 }
103
104private:
105 struct frame {
108 std::string key;
109 bool has_key = false;
110 };
111
112 serialization_result<void> put(serialization_value v) {
113 if (finished_) {
115 "value archive is already finished");
116 }
117 auto status = validate_value_position();
118 if (!status) {
119 return status;
120 }
121 if (stack_.empty()) {
122 root_ = std::move(v);
123 return {};
124 }
125 auto &f = stack_.back();
126 if (f.kind == serialization_kind::array) {
127 f.value.get<serialization_value::array>().push_back(std::move(v));
128 return {};
129 }
130 f.value.get<serialization_value::object>().emplace_back(std::move(f.key), std::move(v));
131 f.key.clear();
132 f.has_key = false;
133 return {};
134 }
135
136 serialization_result<void> begin(serialization_kind kind, serialization_value v) {
137 if (finished_) {
139 "value archive is already finished");
140 }
141 auto status = validate_value_position();
142 if (!status) {
143 return status;
144 }
145 stack_.push_back({kind, std::move(v), {}});
146 return {};
147 }
148
149 serialization_result<void> validate_value_position() const {
150 if (stack_.empty()) {
151 if (root_) {
152 return make_serialization_error(serialization_errc::custom_error, "multiple root values");
153 }
154 return {};
155 }
156 if (stack_.back().kind == serialization_kind::object && !stack_.back().has_key) {
157 return make_serialization_error(serialization_errc::custom_error, "object value without key");
158 }
159 return {};
160 }
161
162 serialization_result<void> end(serialization_kind expected) {
163 if (finished_) {
165 "value archive is already finished");
166 }
167 if (stack_.empty()) {
169 "archive end without begin");
170 }
171 if (stack_.back().kind != expected) {
172 return make_serialization_error(serialization_errc::custom_error, "mismatched archive end");
173 }
174 if (stack_.back().kind == serialization_kind::object && stack_.back().has_key) {
176 "object ended with missing value");
177 }
178 auto v = std::move(stack_.back().value);
179 stack_.pop_back();
180 return put(std::move(v));
181 }
182
183 std::optional<serialization_value> root_;
184 std::vector<frame> stack_;
185 bool finished_ = false;
186};
187
189public:
190 struct member_view;
191
192 explicit value_reader(const serialization_value &value) : value_(&value) {}
193
195 if (value_->is<serialization_value::null_t>()) {
197 }
198 if (value_->is<bool>()) {
200 }
201 if (value_->is<std::int64_t>()) {
203 }
204 if (value_->is<std::uint64_t>()) {
206 }
207 if (value_->is<double>()) {
209 }
210 if (value_->is<std::string>()) {
212 }
213 if (value_->is<serialization_value::array>()) {
215 }
217 }
218
219 std::size_t size() const noexcept {
220 if (value_->is<serialization_value::array>()) {
221 return value_->get<serialization_value::array>().size();
222 }
223 if (value_->is<serialization_value::object>()) {
224 return value_->get<serialization_value::object>().size();
225 }
226 return 0;
227 }
228
229 bool read_bool() const {
230 return value_->get<bool>();
231 }
232
233 std::int64_t read_signed() const {
234 return value_->get<std::int64_t>();
235 }
236
237 std::uint64_t read_unsigned() const {
238 return value_->get<std::uint64_t>();
239 }
240
241 double read_floating() const {
242 return value_->get<double>();
243 }
244
245 std::string_view read_string() const {
246 return value_->get<std::string>();
247 }
248
249 value_reader element(std::size_t i) const {
250 return value_reader(value_->get<serialization_value::array>().at(i));
251 }
252
253 member_view member(std::size_t i) const;
254
256 return *value_;
257 }
258
259private:
260 const serialization_value *value_;
261};
262
267
269 const auto &p = value_->get<serialization_value::object>().at(i);
270 return {p.first, value_reader(p.second)};
271}
272
273} // namespace gmp
274
275#endif // GMP_SERIALIZATION_VALUE_ARCHIVE_HPP_
std::vector< std::pair< std::string, serialization_value > > object
Definition value.hpp:32
std::vector< serialization_value > array
Definition value.hpp:31
std::monostate null_t
Definition value.hpp:30
bool is() const noexcept
Definition value.hpp:68
std::uint64_t read_unsigned() const
std::int64_t read_signed() const
member_view member(std::size_t i) const
bool read_bool() const
value_reader(const serialization_value &value)
std::string_view read_string() const
const serialization_value & value() const noexcept
value_reader element(std::size_t i) const
serialization_kind kind() const noexcept
double read_floating() const
std::size_t size() const noexcept
serialization_result< void > end_object()
serialization_result< void > write_null()
serialization_result< void > begin_object(std::size_t size)
serialization_result< void > write_unsigned(std::uint64_t v)
serialization_result< void > write_bool(bool v)
serialization_result< serialization_value > finish()
serialization_result< void > end_array()
serialization_result< void > write_string(std::string_view v)
serialization_result< void > write_signed(std::int64_t v)
serialization_result< void > write_key(std::string_view key)
serialization_result< void > begin_array(std::size_t size)
serialization_result< void > write_floating(double v)
consteval auto enum_values()
Get all enumerator values of an enumeration type at compile-time.
Definition meta.hpp:193
Definition lock.hpp:21
serialization_kind
Definition archive.hpp:26
serialization_error make_serialization_error(serialization_errc code, std::string message, std::string path={}, std::size_t offset=serialization_error::unknown_offset)
Definition error.hpp:160