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 "../Foundation/Compiler.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 "../Strings/StringFormat.h" //StringFormatOutput
11#include "Internal/SerializationTextReadVersioned.h"
12#include "Internal/SerializationTextReadWriteExact.h"
13
14namespace SC
15{
16struct SC_SERIALIZATION_TEXT_EXPORT SerializationJson;
17} // namespace SC
18
24
27
50{
52 struct SC_SERIALIZATION_TEXT_EXPORT Options
53 {
55 Options() { floatDigits = 2; }
56 };
57
67 template <typename T, typename B>
68 [[nodiscard]] static bool write(T& object, B& buffer, Options options = Options())
69 {
70 GrowableBuffer<B> gb = {buffer};
71 StringFormatOutput output(StringEncoding::Ascii, gb);
72
73 Writer stream(output, options);
74 if (not stream.onSerializationStart())
75 return false;
76 if (not Serialization::SerializationTextReadWriteExact<Writer, T>::serialize(0, object, stream))
77 return false;
78 return stream.onSerializationEnd();
79 }
80
90 template <typename T>
91 [[nodiscard]] static bool loadExact(T& object, StringView text)
92 {
93 Reader stream(text);
94 return Serialization::SerializationTextReadWriteExact<Reader, T>::serialize(0, object, stream);
95 }
96
103 template <typename T>
104 [[nodiscard]] static bool loadVersioned(T& object, StringView text)
105 {
106 Reader stream(text);
107 return Serialization::SerializationTextReadVersioned<Reader, T, void>::loadVersioned(0, object, stream);
108 }
109
110 private:
113 struct SC_SERIALIZATION_TEXT_EXPORT Writer
114 {
115 StringFormatOutput& output;
116
117 Writer(StringFormatOutput& output, Options options) : output(output), options(options) {}
118
119 [[nodiscard]] bool onSerializationStart();
120 [[nodiscard]] bool onSerializationEnd();
121
122 [[nodiscard]] bool setOptions(Options opt);
123
124 [[nodiscard]] bool startObject(uint32_t index);
125 [[nodiscard]] bool endObject();
126
127 [[nodiscard]] bool startArray(uint32_t index);
128 [[nodiscard]] bool endArray();
129
130 template <typename Container>
131 [[nodiscard]] bool startArray(uint32_t index, Container& container, uint32_t& size)
132 {
133 if (not eventuallyAddComma(index))
134 return false;
135 size = static_cast<uint32_t>(container.size());
136 return output.append("["_a8);
137 }
138
139 template <typename Container>
140 [[nodiscard]] bool endArrayItem(Container&, uint32_t&)
141 {
142 return true;
143 }
144
145 [[nodiscard]] bool startObjectField(uint32_t index, StringView text);
146
147 template <typename T>
148 [[nodiscard]] bool serialize(uint32_t index, T& text)
149 {
150 return serializeStringView(index, text.view());
151 }
152
153 [[nodiscard]] bool serialize(uint32_t index, StringSpan text);
154 [[nodiscard]] bool serialize(uint32_t index, StringView text);
155 [[nodiscard]] bool serialize(uint32_t index, float value);
156 [[nodiscard]] bool serialize(uint32_t index, double value);
157 [[nodiscard]] bool serialize(uint32_t index, int value);
158
159 private:
160 [[nodiscard]] bool serializeStringView(uint32_t index, StringView text);
161
162 bool eventuallyAddComma(uint32_t index);
163
164 char floatFormatStorage[5];
165 StringSpan floatFormat;
166 Options options;
167 };
168
171 struct SC_SERIALIZATION_TEXT_EXPORT Reader
172 {
173 Reader(StringView text) : iteratorText(text), iterator(text.getIterator<StringIteratorASCII>()) {}
174
175 [[nodiscard]] bool onSerializationStart() { return true; }
176 [[nodiscard]] bool onSerializationEnd() { return true; }
177
178 [[nodiscard]] bool startObject(uint32_t index);
179 [[nodiscard]] bool endObject();
180
181 [[nodiscard]] bool startArray(uint32_t index);
182 [[nodiscard]] bool endArray();
183
184 template <typename Container>
185 [[nodiscard]] bool startArray(uint32_t index, Container& container, uint32_t& size)
186 {
187 if (not tokenizeArrayStart(index))
188 return false;
189 return endArrayItem(container, size);
190 }
191
192 template <typename Container>
193 [[nodiscard]] bool endArrayItem(Container& container, uint32_t& size)
194 {
195 auto oldSize = size;
196 if (not tokenizeArrayEnd(size))
197 return false;
198 if (oldSize != size)
199 return Reflection::ExtendedTypeInfo<Container>::resize(container, size);
200 return true;
201 }
202
203 [[nodiscard]] bool startObjectField(uint32_t index, StringView text);
204 [[nodiscard]] bool getNextField(uint32_t index, StringSpan& text, bool& hasMore);
205
206 [[nodiscard]] bool serialize(uint32_t index, bool& value);
207 [[nodiscard]] bool serialize(uint32_t index, float& value);
208 [[nodiscard]] bool serialize(uint32_t index, int32_t& value);
209 [[nodiscard]] bool serialize(uint32_t index, StringSpan& value);
210 [[nodiscard]] bool serialize(uint32_t index, StringView& value);
211
212 template <typename T>
213 [[nodiscard]] bool serialize(uint32_t index, T& text)
214 {
215 bool succeeded;
216 auto escaped = serializeInternal(index, succeeded);
217 if (not succeeded)
218 return false;
219
220 GrowableBuffer<T> gb = {text};
221 StringFormatOutput output(StringEncoding::Utf8, gb);
222 gb.clear();
223 output.onFormatBegin();
224 if (not appendJSONStringUnescaped(escaped, output))
225 {
226 output.onFormatFailed();
227 return false;
228 }
229 return output.onFormatSucceeded();
230 }
231
232 private:
233 [[nodiscard]] static bool appendJSONStringUnescaped(StringView escaped, StringFormatOutput& output);
234 [[nodiscard]] StringView serializeInternal(uint32_t index, bool& succeeded);
235
236 [[nodiscard]] bool tokenizeArrayStart(uint32_t index);
237 [[nodiscard]] bool tokenizeArrayEnd(uint32_t& size);
238 [[nodiscard]] bool eventuallyExpectComma(uint32_t index);
239
240 StringView iteratorText;
241 StringIteratorASCII iterator;
242 };
243};
unsigned char uint8_t
Platform independent (1) byte unsigned int.
Definition PrimitiveTypes.h:27
Formatting options.
Definition SerializationJson.h:53
uint8_t floatDigits
How many digits should be used when printing floating points.
Definition SerializationJson.h:54
SC::SerializationJson reads or writes C++ structures to / from json using Reflection information.
Definition SerializationJson.h:50
static bool loadVersioned(T &object, StringView text)
Parses a JSON buffer and writes C++ objects supporting reordered or missing fields.
Definition SerializationJson.h:104
static bool loadExact(T &object, StringView text)
Parses a JSON produced by SerializationJson::write loading its values into a C++ object Read a JSON b...
Definition SerializationJson.h:91
static bool write(T &object, B &buffer, Options options=Options())
Writes a C++ object to JSON using Reflection.
Definition SerializationJson.h:68
Definition StringFormat.h:27
Non-owning view over a range of characters with UTF Encoding.
Definition StringView.h:47