@@ -22,81 +22,54 @@ Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md).
22
22
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23
23
THE SOFTWARE.
24
24
25
- A simple wrapper dotnet Utf8JsonWriter like API style of rapidjson
25
+ A simple JsonWriter implementation like dotnet Utf8JsonWriter API.
26
26
27
27
****************************************************************************/
28
28
29
29
#pragma once
30
30
31
31
#include < string_view>
32
32
33
- #include " rapidjson/writer.h "
34
- #include " rapidjson/prettywriter .h"
33
+ #include " yasio/byte_buffer.hpp "
34
+ #include " base/format .h"
35
35
36
36
namespace ax
37
37
{
38
38
struct JsonWriterOptions
39
39
{
40
- char indentChar = ' ' ;
41
- int indentCharCount = 2 ;
42
- rapidjson::PrettyFormatOptions formatOptions = rapidjson::kFormatDefault ;
43
- };
44
-
45
- template <bool _Pretty = true >
46
- struct JsonWriterImpl
47
- {
48
- using type = rapidjson::PrettyWriter<rapidjson::StringBuffer>;
49
- };
50
-
51
- template <>
52
- struct JsonWriterImpl <false >
53
- {
54
- using type = rapidjson::Writer<rapidjson::StringBuffer>;
40
+ char indentChar = ' ' ;
41
+ int indentCharCount = 2 ;
42
+ int initialBufferSize = 128 ;
55
43
};
56
44
57
45
template <bool _Pretty = true >
58
46
class JsonWriter
59
47
{
60
- using writer_type = typename JsonWriterImpl<_Pretty>::type;
61
-
62
48
public:
63
49
JsonWriter ()
64
50
{
65
- new (static_cast <void *>(_writerHold)) writer_type (_buffer);
66
51
setOptions (JsonWriterOptions{});
52
+ _buffer.reserve (_options.initialBufferSize );
67
53
}
68
- ~JsonWriter () { writer (). ~writer_type (); }
54
+ ~JsonWriter () {}
69
55
70
56
explicit JsonWriter (const JsonWriterOptions& options) { setOptions (options); }
71
57
72
- void setOptions (const JsonWriterOptions& options)
73
- {
74
- if constexpr (_Pretty)
75
- {
76
- prettyWriter ().SetIndent (options.indentChar , options.indentCharCount );
77
- prettyWriter ().SetFormatOptions (options.formatOptions );
78
- }
79
- }
58
+ void setOptions (const JsonWriterOptions& options) { _options = options; }
80
59
81
- void writePropertyName (std::string_view propertyName)
82
- {
83
- writer ().Key (propertyName.data (), static_cast <rapidjson::SizeType>(propertyName.length ()), false );
84
- }
60
+ explicit operator std::string_view () const { return std::string_view{_buffer.data (), _buffer.size ()}; }
85
61
86
62
#pragma region write values
87
- void writeBoolValue (bool value) { writer ().Bool (value); }
88
- void writeNumberValue (int value) { writer ().Int (value); }
89
- void writeNumberValue (long long value) { writer ().Int64 (value); }
90
- void writeNumberValue (double value) { writer ().Double (value); }
91
- void writeStringValue (std::string_view value)
92
- {
93
- writer ().String (value.data (), static_cast <rapidjson::SizeType>(value.length ()));
94
- }
63
+ void writeBoolValue (bool value) { writeUnquoteValue (value); }
64
+ void writeNumberValue (int value) { writeUnquoteValue (value); }
65
+ void writeNumberValue (long long value) { writeUnquoteValue (value); }
66
+ void writeNumberValue (double value) { writeUnquoteValue (value); }
67
+ void writeNullValue () { writeUnquoteValue (" null" sv); }
95
68
96
- void writeNullValue ( ) { writer (). Null ( ); }
69
+ void writeStringValue (std::string_view value ) { writeQuoteValue (value ); }
97
70
98
- template <typename Intty , size_t _N>
99
- void writeNumberValues (Intty (&values)[_N])
71
+ template <typename _Nty , size_t _N>
72
+ void writeNumberValues (_Nty (&values)[_N])
100
73
{
101
74
for (auto v : values)
102
75
writeNumberValue (v);
@@ -154,21 +127,108 @@ class JsonWriter
154
127
writePropertyName (propertyName);
155
128
writeStartObject ();
156
129
}
157
- void writeStartArray () { writer ().StartArray (); }
158
- void writeEndArray () { writer ().EndArray (); }
159
- void writeStartObject () { writer ().StartObject (); }
160
- void writeEndObject () { writer ().EndObject (); }
130
+ void writeStartArray () { writeStartCollection (' [' ); }
131
+ void writeEndArray () { writeEndCollection (' ]' ); }
132
+
133
+ void writeStartObject () { writeStartCollection (' {' ); }
134
+ void writeEndObject () { writeEndCollection (' }' ); }
161
135
#pragma endregion
162
136
163
- explicit operator std::string_view () { return std::string_view{_buffer.GetString (), _buffer.GetLength ()}; }
137
+ void writePropertyName (std::string_view propertyName)
138
+ {
139
+ if constexpr (_Pretty)
140
+ {
141
+ fillIndentChars ();
142
+ _pendingValue = true ;
143
+ }
144
+ _buffer += ' "' ;
145
+ _buffer += propertyName;
146
+ _buffer += " \" :" sv;
147
+ if constexpr (_Pretty)
148
+ _buffer += _options.indentChar ;
149
+ }
164
150
165
151
protected:
166
- inline writer_type& writer () { return *reinterpret_cast <writer_type*>(&_writerHold[0 ]); }
167
- inline JsonWriterImpl<true >::type& prettyWriter ()
152
+ void writeQuoteValue (const std::string_view& value)
168
153
{
169
- return *reinterpret_cast <JsonWriterImpl<true >::type*>(&_writerHold[0 ]);
154
+ if constexpr (_Pretty)
155
+ if (!_pendingValue)
156
+ fillIndentChars ();
157
+
158
+ _buffer += ' "' ;
159
+ _buffer += value;
160
+ _buffer += " \" ," sv;
161
+ if constexpr (_Pretty)
162
+ _buffer += ' \n ' ;
163
+
164
+ _pendingValue = false ;
170
165
}
171
- rapidjson::StringBuffer _buffer;
172
- uint8_t _writerHold[sizeof (writer_type)];
166
+ template <typename _Ty>
167
+ void writeUnquoteValue (const _Ty& value)
168
+ {
169
+ if constexpr (_Pretty)
170
+ if (!_pendingValue)
171
+ fillIndentChars ();
172
+
173
+ fmt::vformat_to (std::back_inserter (_buffer), " {}," , fmt::make_format_args (value));
174
+ if constexpr (_Pretty)
175
+ _buffer += ' \n ' ;
176
+
177
+ _pendingValue = false ;
178
+ }
179
+
180
+ void writeStartCollection (const char startChar)
181
+ {
182
+ if constexpr (_Pretty)
183
+ if (!_pendingValue)
184
+ fillIndentChars ();
185
+
186
+ ++_level;
187
+
188
+ _buffer += startChar;
189
+ if constexpr (_Pretty)
190
+ _buffer += ' \n ' ;
191
+
192
+ _pendingValue = false ;
193
+ }
194
+
195
+ void writeEndCollection (const char termChar)
196
+ {
197
+ if (_buffer.empty ())
198
+ return ;
199
+
200
+ --_level;
201
+
202
+ if constexpr (_Pretty)
203
+ {
204
+ if (_buffer.back () == ' \n ' )
205
+ _buffer.pop_back (); // pop '\n'
206
+ }
207
+ if (_buffer.back () == ' ,' )
208
+ _buffer.pop_back ();
209
+ if constexpr (_Pretty)
210
+ {
211
+ _buffer += ' \n ' ;
212
+ fillIndentChars ();
213
+ }
214
+ _buffer += termChar;
215
+
216
+ if (_level != 0 )
217
+ _buffer += ' ,' ;
218
+ if constexpr (_Pretty)
219
+ _buffer += ' \n ' ;
220
+ }
221
+
222
+ void fillIndentChars ()
223
+ {
224
+ if constexpr (_Pretty)
225
+ if (_level)
226
+ _buffer.expand (_level * _options.indentCharCount , _options.indentChar );
227
+ }
228
+
229
+ yasio::sbyte_buffer _buffer;
230
+ uint16_t _level{0 };
231
+ bool _pendingValue{false };
232
+ JsonWriterOptions _options;
173
233
};
174
234
} // namespace ax
0 commit comments