Sane C++ Libraries
C++ Platform Abstraction Libraries
Loading...
Searching...
No Matches
SerializationJson.h
1// Copyright (c) Stefano Cristiano
2// SPDX-License-Identifier: MIT
3#pragma once
4#include "../Common/CompilerMacrosExport.h"
5#ifndef SC_EXPORT_LIBRARY_SERIALIZATION_TEXT
6#define SC_EXPORT_LIBRARY_SERIALIZATION_TEXT 0
7#endif
8#define SC_SERIALIZATION_TEXT_EXPORT SC_COMPILER_LIBRARY_EXPORT(SC_EXPORT_LIBRARY_SERIALIZATION_TEXT)
9
10#include "Internal/JsonTokenizer.h"
11#include "Internal/SerializationTextOutput.h"
12#include "Internal/SerializationTextReadVersioned.h"
13#include "Internal/SerializationTextReadWriteExact.h"
14
15namespace SC
16{
17struct SC_SERIALIZATION_TEXT_EXPORT SerializationJson;
18} // namespace SC
19
25
28
51{
53 struct SC_SERIALIZATION_TEXT_EXPORT Options
54 {
55 uint8_t floatDigits;
56 Options() { floatDigits = 2; }
57 };
58
68 template <typename T, typename B>
69 [[nodiscard]] static bool write(T& object, B& buffer, Options options = Options())
70 {
71 GrowableBuffer<B> gb = {buffer};
72 SerializationTextOutput output(gb);
73
74 Writer stream(output, options);
75 if (not stream.onSerializationStart())
76 {
77 output.onFormatFailed();
78 return false;
79 }
80 if (not Serialization::SerializationTextReadWriteExact<Writer, T>::serialize(0, object, stream))
81 {
82 output.onFormatFailed();
83 return false;
84 }
85 return stream.onSerializationEnd();
86 }
87
97 template <typename T>
98 [[nodiscard]] static bool loadExact(T& object, StringSpan text)
99 {
100 Reader stream(text);
101 return Serialization::SerializationTextReadWriteExact<Reader, T>::serialize(0, object, stream);
102 }
103
110 template <typename T>
111 [[nodiscard]] static bool loadVersioned(T& object, StringSpan text)
112 {
113 Reader stream(text);
114 return Serialization::SerializationTextReadVersioned<Reader, T, void>::loadVersioned(0, object, stream);
115 }
116
117 private:
120 struct SC_SERIALIZATION_TEXT_EXPORT Writer
121 {
122 SerializationTextOutput& output;
123
124 Writer(SerializationTextOutput& output, Options options) : output(output), options(options) {}
125
126 [[nodiscard]] bool onSerializationStart();
127 [[nodiscard]] bool onSerializationEnd();
128
129 [[nodiscard]] bool setOptions(Options opt);
130
131 [[nodiscard]] bool startObject(uint32_t index);
132 [[nodiscard]] bool endObject();
133
134 [[nodiscard]] bool startArray(uint32_t index);
135 [[nodiscard]] bool endArray();
136
137 template <typename Container>
138 [[nodiscard]] bool startArray(uint32_t index, Container& container, uint32_t& size)
139 {
140 if (not eventuallyAddComma(index))
141 return false;
142 size = static_cast<uint32_t>(container.size());
143 return output.append("[");
144 }
145
146 template <typename Container>
147 [[nodiscard]] bool endArrayItem(Container&, uint32_t&)
148 {
149 return true;
150 }
151
152 [[nodiscard]] bool startObjectField(uint32_t index, StringSpan text);
153
154 template <typename T>
155 [[nodiscard]]
156 typename TypeTraits::EnableIf<not Serialization::SerializationTextIsBaseOf<StringSpan, T>::value,
157 bool>::type serialize(uint32_t index, T& text)
158 {
159 return serializeStringSpan(index, text.view());
160 }
161
162 [[nodiscard]] bool serialize(uint32_t index, StringSpan text);
163 [[nodiscard]] bool serialize(uint32_t index, float value);
164 [[nodiscard]] bool serialize(uint32_t index, double value);
165 [[nodiscard]] bool serialize(uint32_t index, int value);
166
167 private:
168 [[nodiscard]] bool serializeStringSpan(uint32_t index, StringSpan text);
169
170 bool eventuallyAddComma(uint32_t index);
171
172 Options options;
173 };
174
177 struct SC_SERIALIZATION_TEXT_EXPORT Reader
178 {
179 Reader(StringSpan text) : iteratorText(text), iterator(text) {}
180
181 [[nodiscard]] bool onSerializationStart() { return true; }
182 [[nodiscard]] bool onSerializationEnd() { return true; }
183
184 [[nodiscard]] bool startObject(uint32_t index);
185 [[nodiscard]] bool endObject();
186
187 [[nodiscard]] bool startArray(uint32_t index);
188 [[nodiscard]] bool endArray();
189
190 template <typename Container>
191 [[nodiscard]] bool startArray(uint32_t index, Container& container, uint32_t& size)
192 {
193 if (not tokenizeArrayStart(index))
194 return false;
195 return endArrayItem(container, size);
196 }
197
198 template <typename Container>
199 [[nodiscard]] bool endArrayItem(Container& container, uint32_t& size)
200 {
201 auto oldSize = size;
202 if (not tokenizeArrayEnd(size))
203 return false;
204 if (oldSize != size)
205 return Reflection::ExtendedTypeInfo<Container>::resize(container, size);
206 return true;
207 }
208
209 [[nodiscard]] bool startObjectField(uint32_t index, StringSpan text);
210 [[nodiscard]] bool getNextField(uint32_t index, StringSpan& text, bool& hasMore);
211
212 [[nodiscard]] bool serialize(uint32_t index, bool& value);
213 [[nodiscard]] bool serialize(uint32_t index, float& value);
214 [[nodiscard]] bool serialize(uint32_t index, int32_t& value);
215 [[nodiscard]] bool serialize(uint32_t index, StringSpan& value);
216
217 template <typename T>
218 [[nodiscard]]
219 typename TypeTraits::EnableIf<not Serialization::SerializationTextIsBaseOf<StringSpan, T>::value,
220 bool>::type serialize(uint32_t index, T& text)
221 {
222 bool succeeded;
223 auto escaped = serializeInternal(index, succeeded);
224 if (not succeeded)
225 return false;
226
227 GrowableBuffer<T> gb = {text};
228 SerializationTextOutput output(gb);
229 gb.clear();
230 output.onFormatBegin();
231 if (not appendJSONStringUnescaped(escaped, output))
232 {
233 output.onFormatFailed();
234 return false;
235 }
236 return output.onFormatSucceeded();
237 }
238
239 private:
240 [[nodiscard]] static bool appendJSONStringUnescaped(StringSpan escaped, SerializationTextOutput& output);
241 [[nodiscard]] StringSpan serializeInternal(uint32_t index, bool& succeeded);
242
243 [[nodiscard]] bool tokenizeArrayStart(uint32_t index);
244 [[nodiscard]] bool tokenizeArrayEnd(uint32_t& size);
245 [[nodiscard]] bool eventuallyExpectComma(uint32_t index);
246
247 StringSpan iteratorText;
248 JsonTokenizer::Cursor iterator;
249 };
250};
Formatting options.
Definition SerializationJson.h:54
uint8_t floatDigits
How many digits should be used when printing floating points.
Definition SerializationJson.h:55
SC::SerializationJson reads or writes C++ structures to / from json using Reflection information.
Definition SerializationJson.h:51
static bool loadExact(T &object, StringSpan text)
Parses a JSON produced by SerializationJson::write loading its values into a C++ object Read a JSON b...
Definition SerializationJson.h:98
static bool write(T &object, B &buffer, Options options=Options())
Writes a C++ object to JSON using Reflection.
Definition SerializationJson.h:69
static bool loadVersioned(T &object, StringSpan text)
Parses a JSON buffer and writes C++ objects supporting reordered or missing fields.
Definition SerializationJson.h:111