GCC Code Coverage Report | |||||||||||||||||||||
|
|||||||||||||||||||||
Line | Branch | Exec | Source |
1 |
#ifndef ZSERIO_JSON_WRITER_H_INC |
||
2 |
#define ZSERIO_JSON_WRITER_H_INC |
||
3 |
|||
4 |
#include <ostream> |
||
5 |
|||
6 |
#include "zserio/AllocatorHolder.h" |
||
7 |
#include "zserio/IWalkObserver.h" |
||
8 |
#include "zserio/JsonEncoder.h" |
||
9 |
#include "zserio/OptionalHolder.h" |
||
10 |
#include "zserio/TypeInfoUtil.h" |
||
11 |
|||
12 |
namespace zserio |
||
13 |
{ |
||
14 |
|||
15 |
/** |
||
16 |
* Walker observer which dumps zserio objects to JSON format. |
||
17 |
*/ |
||
18 |
template <typename ALLOC = std::allocator<uint8_t>> |
||
19 |
class BasicJsonWriter : public IBasicWalkObserver<ALLOC>, public AllocatorHolder<ALLOC> |
||
20 |
{ |
||
21 |
public: |
||
22 |
using AllocatorHolder<ALLOC>::get_allocator; |
||
23 |
|||
24 |
/** |
||
25 |
* Default item separator used when indent is not set. |
||
26 |
*/ |
||
27 |
static constexpr const char* DEFAULT_ITEM_SEPARATOR = ", "; |
||
28 |
|||
29 |
/** |
||
30 |
* Default item separator used when indent is set. |
||
31 |
*/ |
||
32 |
static constexpr const char* DEFAULT_ITEM_SEPARATOR_WITH_INDENT = ","; |
||
33 |
|||
34 |
/** |
||
35 |
* Default key separator. |
||
36 |
*/ |
||
37 |
static constexpr const char* DEFAULT_KEY_SEPARATOR = ": "; |
||
38 |
|||
39 |
/** |
||
40 |
* Configuration for writing of enumerable types. |
||
41 |
*/ |
||
42 |
enum class EnumerableFormat |
||
43 |
{ |
||
44 |
/** Print as JSON integral value. */ |
||
45 |
NUMBER, |
||
46 |
/** |
||
47 |
* Print as JSON string according to the following rules: |
||
48 |
* |
||
49 |
* 1. Enums |
||
50 |
* * when an exact match with an enumerable item is found, the item name is used - e.g. "FIRST", |
||
51 |
* * when no exact match is found, it's an invalid value, the integral value is converted to string |
||
52 |
* and an appropriate comment is included - e.g. \"10 /<span>*</span> no match <span>*</span>/\". |
||
53 |
* |
||
54 |
* 2. Bitmasks |
||
55 |
* * when an exact mach with or-ed bitmask values is found, it's used - e.g. "READ | WRITE", |
||
56 |
* * when no exact match is found, but some or-ed values match, the integral value is converted |
||
57 |
* to string and the or-ed values are included in a comment - e.g. |
||
58 |
* \"127 /<span>*</span> READ | CREATE <span>*</span>/\", |
||
59 |
* * when no match is found at all, the integral value is converted to string and an appropriate |
||
60 |
* comment is included - e.g. \"13 /<span>*</span> no match <span>*</span>/\". |
||
61 |
*/ |
||
62 |
STRING |
||
63 |
}; |
||
64 |
/** |
||
65 |
* Default configuration for enumerable types. |
||
66 |
*/ |
||
67 |
static constexpr EnumerableFormat DEFAULT_ENUMERABLE_FORMAT = EnumerableFormat::STRING; |
||
68 |
|||
69 |
/** |
||
70 |
* Constructor. |
||
71 |
* |
||
72 |
* \param out Stream to use for writing. |
||
73 |
* \param allocator Allocator to use. |
||
74 |
*/ |
||
75 |
explicit BasicJsonWriter(std::ostream& out, const ALLOC& allocator = ALLOC()); |
||
76 |
|||
77 |
/** |
||
78 |
* Constructor. |
||
79 |
* |
||
80 |
* \param out Stream to use for writing. |
||
81 |
* \param indent Indent as a number of ' ' to be used for indentation. |
||
82 |
* \param allocator Allocator to use. |
||
83 |
*/ |
||
84 |
BasicJsonWriter(std::ostream& out, uint8_t indent, const ALLOC& allocator = ALLOC()); |
||
85 |
|||
86 |
/** |
||
87 |
* Constructor. |
||
88 |
* |
||
89 |
* \param out Stream to use for writing. |
||
90 |
* \param indent Indent as a string to be used for indentation. |
||
91 |
* \param allocator Allocator to use. |
||
92 |
*/ |
||
93 |
BasicJsonWriter(std::ostream& out, const string<ALLOC>& indent, const ALLOC& allocator = ALLOC()); |
||
94 |
|||
95 |
/** |
||
96 |
* Method generated by default. |
||
97 |
*/ |
||
98 |
✗✓✗✗ ✓ |
68 |
~BasicJsonWriter() override = default; |
99 |
|||
100 |
/** |
||
101 |
* Copying and moving is disallowed! |
||
102 |
* \{ |
||
103 |
*/ |
||
104 |
BasicJsonWriter(const BasicJsonWriter& other) = delete; |
||
105 |
BasicJsonWriter& operator=(const BasicJsonWriter& other) = delete; |
||
106 |
|||
107 |
BasicJsonWriter(BasicJsonWriter&& other) = delete; |
||
108 |
BasicJsonWriter& operator=(BasicJsonWriter&& other) = delete; |
||
109 |
/** |
||
110 |
* \} |
||
111 |
*/ |
||
112 |
|||
113 |
/** |
||
114 |
* Sets custom item separator. |
||
115 |
* |
||
116 |
* Use with caution since setting of a wrong separator can lead to invalid JSON output. |
||
117 |
* |
||
118 |
* \param itemSeparator Item separator to set. |
||
119 |
*/ |
||
120 |
void setItemSeparator(const string<ALLOC>& itemSeparator); |
||
121 |
|||
122 |
/** |
||
123 |
* Sets custom key separator. |
||
124 |
* |
||
125 |
* Use with caution since setting of a wrong separator can lead to invalid JSON output. |
||
126 |
* |
||
127 |
* \param keySeparator Key separator to set. |
||
128 |
*/ |
||
129 |
void setKeySeparator(const string<ALLOC>& keySeparator); |
||
130 |
|||
131 |
/** |
||
132 |
* Sets preferred formatting for enumerable types. |
||
133 |
* |
||
134 |
* @param enumerableFormat Enumerable format to use. |
||
135 |
*/ |
||
136 |
void setEnumerableFormat(EnumerableFormat enumerableFormat); |
||
137 |
|||
138 |
void beginRoot(const IBasicReflectableConstPtr<ALLOC>& compound) override; |
||
139 |
void endRoot(const IBasicReflectableConstPtr<ALLOC>& compound) override; |
||
140 |
|||
141 |
void beginArray(const IBasicReflectableConstPtr<ALLOC>& array, |
||
142 |
const BasicFieldInfo<ALLOC>& fieldInfo) override; |
||
143 |
void endArray(const IBasicReflectableConstPtr<ALLOC>& array, |
||
144 |
const BasicFieldInfo<ALLOC>& fieldInfo) override; |
||
145 |
|||
146 |
void beginCompound(const IBasicReflectableConstPtr<ALLOC>& compound, |
||
147 |
const BasicFieldInfo<ALLOC>& fieldInfo, size_t elementIndex) override; |
||
148 |
void endCompound(const IBasicReflectableConstPtr<ALLOC>& compound, |
||
149 |
const BasicFieldInfo<ALLOC>& fieldInfo, size_t elementIndex) override; |
||
150 |
|||
151 |
void visitValue(const IBasicReflectableConstPtr<ALLOC>& value, |
||
152 |
const BasicFieldInfo<ALLOC>& fieldInfo, size_t elementIndex) override; |
||
153 |
|||
154 |
private: |
||
155 |
BasicJsonWriter(std::ostream& out, InplaceOptionalHolder<string<ALLOC>>&& optionalIndent, |
||
156 |
const ALLOC& allocator = ALLOC()); |
||
157 |
|||
158 |
void beginItem(); |
||
159 |
void endItem(); |
||
160 |
void beginObject(); |
||
161 |
void endObject(); |
||
162 |
void beginArray(); |
||
163 |
void endArray(); |
||
164 |
|||
165 |
void writeIndent(); |
||
166 |
void writeKey(StringView key); |
||
167 |
void writeValue(const IBasicReflectableConstPtr<ALLOC>& reflectable); |
||
168 |
void writeBitBuffer(const BasicBitBuffer<ALLOC>& bitBuffer); |
||
169 |
void writeBytes(Span<const uint8_t> value); |
||
170 |
void writeStringifiedEnum(const IBasicReflectableConstPtr<ALLOC>& reflectable); |
||
171 |
void writeStringifiedBitmask(const IBasicReflectableConstPtr<ALLOC>& reflectable); |
||
172 |
|||
173 |
std::ostream& m_out; |
||
174 |
InplaceOptionalHolder<string<ALLOC>> m_indent; |
||
175 |
string<ALLOC> m_itemSeparator; |
||
176 |
string<ALLOC> m_keySeparator; |
||
177 |
EnumerableFormat m_enumerableFormat = DEFAULT_ENUMERABLE_FORMAT; |
||
178 |
|||
179 |
bool m_isFirst = true; |
||
180 |
size_t m_level = 0; |
||
181 |
}; |
||
182 |
|||
183 |
/** Typedef to JsonWriter provided for convenience - using default std::allocator<uint8_t>. */ |
||
184 |
/** \{ */ |
||
185 |
using JsonWriter = BasicJsonWriter<>; |
||
186 |
/** \} */ |
||
187 |
|||
188 |
template <typename ALLOC> |
||
189 |
28 |
BasicJsonWriter<ALLOC>::BasicJsonWriter(std::ostream& out, const ALLOC& allocator) : |
|
190 |
✓✗ | 28 |
BasicJsonWriter(out, NullOpt, allocator) |
191 |
28 |
{} |
|
192 |
|||
193 |
template <typename ALLOC> |
||
194 |
38 |
BasicJsonWriter<ALLOC>::BasicJsonWriter(std::ostream& out, uint8_t indent, const ALLOC& allocator) : |
|
195 |
✓✗✓✗ ✓✗✓✗ |
38 |
BasicJsonWriter(out, string<ALLOC>(indent, ' ', allocator), allocator) |
196 |
38 |
{} |
|
197 |
|||
198 |
template <typename ALLOC> |
||
199 |
40 |
BasicJsonWriter<ALLOC>::BasicJsonWriter(std::ostream& out, const string<ALLOC>& indent, |
|
200 |
const ALLOC& allocator) : |
||
201 |
✓✗✓✗ |
40 |
BasicJsonWriter(out, InplaceOptionalHolder<string<ALLOC>>(indent), allocator) |
202 |
40 |
{} |
|
203 |
|||
204 |
template <typename ALLOC> |
||
205 |
68 |
BasicJsonWriter<ALLOC>::BasicJsonWriter(std::ostream& out, |
|
206 |
InplaceOptionalHolder<string<ALLOC>>&& optionalIndent, const ALLOC& allocator) : |
||
207 |
AllocatorHolder<ALLOC>(allocator), |
||
208 |
m_out(out), m_indent(optionalIndent), |
||
209 |
68 |
m_itemSeparator(m_indent.hasValue() ? DEFAULT_ITEM_SEPARATOR_WITH_INDENT : DEFAULT_ITEM_SEPARATOR, |
|
210 |
allocator), |
||
211 |
✓✗✓✗ ✓✗✓✗ ✗✓✗✓ ✓✓✗✓ ✗ |
136 |
m_keySeparator(DEFAULT_KEY_SEPARATOR, allocator) |
212 |
68 |
{} |
|
213 |
|||
214 |
template <typename ALLOC> |
||
215 |
1 |
void BasicJsonWriter<ALLOC>::setItemSeparator(const string<ALLOC>& itemSeparator) |
|
216 |
{ |
||
217 |
1 |
m_itemSeparator = itemSeparator; |
|
218 |
1 |
} |
|
219 |
|||
220 |
template <typename ALLOC> |
||
221 |
1 |
void BasicJsonWriter<ALLOC>::setKeySeparator(const string<ALLOC>& keySeparator) |
|
222 |
{ |
||
223 |
1 |
m_keySeparator = keySeparator; |
|
224 |
1 |
} |
|
225 |
|||
226 |
template <typename ALLOC> |
||
227 |
3 |
void BasicJsonWriter<ALLOC>::setEnumerableFormat(EnumerableFormat enumerableFormat) |
|
228 |
{ |
||
229 |
3 |
m_enumerableFormat = enumerableFormat; |
|
230 |
3 |
} |
|
231 |
|||
232 |
template <typename ALLOC> |
||
233 |
45 |
void BasicJsonWriter<ALLOC>::beginRoot(const IBasicReflectableConstPtr<ALLOC>&) |
|
234 |
{ |
||
235 |
45 |
beginObject(); |
|
236 |
45 |
} |
|
237 |
|||
238 |
template <typename ALLOC> |
||
239 |
45 |
void BasicJsonWriter<ALLOC>::endRoot(const IBasicReflectableConstPtr<ALLOC>&) |
|
240 |
{ |
||
241 |
45 |
endObject(); |
|
242 |
45 |
m_out.flush(); |
|
243 |
45 |
} |
|
244 |
|||
245 |
template <typename ALLOC> |
||
246 |
3 |
void BasicJsonWriter<ALLOC>::beginArray(const IBasicReflectableConstPtr<ALLOC>&, |
|
247 |
const BasicFieldInfo<ALLOC>& fieldInfo) |
||
248 |
{ |
||
249 |
3 |
beginItem(); |
|
250 |
|||
251 |
3 |
writeKey(fieldInfo.schemaName); |
|
252 |
|||
253 |
3 |
beginArray(); |
|
254 |
3 |
} |
|
255 |
|||
256 |
template <typename ALLOC> |
||
257 |
3 |
void BasicJsonWriter<ALLOC>::endArray(const IBasicReflectableConstPtr<ALLOC>&, const BasicFieldInfo<ALLOC>&) |
|
258 |
{ |
||
259 |
3 |
endArray(); |
|
260 |
|||
261 |
3 |
endItem(); |
|
262 |
3 |
} |
|
263 |
|||
264 |
template <typename ALLOC> |
||
265 |
6 |
void BasicJsonWriter<ALLOC>::beginCompound(const IBasicReflectableConstPtr<ALLOC>&, |
|
266 |
const BasicFieldInfo<ALLOC>& fieldInfo, size_t elementIndex) |
||
267 |
{ |
||
268 |
6 |
beginItem(); |
|
269 |
|||
270 |
✓✓✗✗ |
6 |
if (elementIndex == WALKER_NOT_ELEMENT) |
271 |
5 |
writeKey(fieldInfo.schemaName); |
|
272 |
|||
273 |
6 |
beginObject(); |
|
274 |
6 |
} |
|
275 |
|||
276 |
template <typename ALLOC> |
||
277 |
6 |
void BasicJsonWriter<ALLOC>::endCompound(const IBasicReflectableConstPtr<ALLOC>&, |
|
278 |
const BasicFieldInfo<ALLOC>&, size_t) |
||
279 |
{ |
||
280 |
6 |
endObject(); |
|
281 |
|||
282 |
6 |
endItem(); |
|
283 |
6 |
} |
|
284 |
|||
285 |
template <typename ALLOC> |
||
286 |
85 |
void BasicJsonWriter<ALLOC>::visitValue(const IBasicReflectableConstPtr<ALLOC>& value, |
|
287 |
const BasicFieldInfo<ALLOC>& fieldInfo, size_t elementIndex) |
||
288 |
{ |
||
289 |
85 |
beginItem(); |
|
290 |
|||
291 |
✓✓✓✗ |
85 |
if (elementIndex == WALKER_NOT_ELEMENT) |
292 |
81 |
writeKey(fieldInfo.schemaName); |
|
293 |
|||
294 |
85 |
writeValue(value); |
|
295 |
|||
296 |
84 |
endItem(); |
|
297 |
84 |
} |
|
298 |
|||
299 |
template <typename ALLOC> |
||
300 |
108 |
void BasicJsonWriter<ALLOC>::beginItem() |
|
301 |
{ |
||
302 |
✓✓✗✓ |
108 |
if (!m_isFirst) |
303 |
29 |
m_out.write(m_itemSeparator.data(), static_cast<std::streamsize>(m_itemSeparator.size())); |
|
304 |
|||
305 |
✓✓✓✗ |
108 |
if (m_indent.hasValue()) |
306 |
43 |
m_out.put('\n'); |
|
307 |
|||
308 |
108 |
writeIndent(); |
|
309 |
108 |
} |
|
310 |
|||
311 |
template <typename ALLOC> |
||
312 |
107 |
void BasicJsonWriter<ALLOC>::endItem() |
|
313 |
{ |
||
314 |
107 |
m_isFirst = false; |
|
315 |
107 |
} |
|
316 |
|||
317 |
template <typename ALLOC> |
||
318 |
55 |
void BasicJsonWriter<ALLOC>::beginObject() |
|
319 |
{ |
||
320 |
55 |
m_out.put('{'); |
|
321 |
|||
322 |
55 |
m_isFirst = true; |
|
323 |
55 |
m_level += 1; |
|
324 |
55 |
} |
|
325 |
|||
326 |
template <typename ALLOC> |
||
327 |
55 |
void BasicJsonWriter<ALLOC>::endObject() |
|
328 |
{ |
||
329 |
✓✓✓✗ |
55 |
if (m_indent.hasValue()) |
330 |
43 |
m_out.put('\n'); |
|
331 |
|||
332 |
55 |
m_level -= 1; |
|
333 |
|||
334 |
55 |
writeIndent(); |
|
335 |
|||
336 |
55 |
m_out.put('}'); |
|
337 |
55 |
} |
|
338 |
|||
339 |
template <typename ALLOC> |
||
340 |
7 |
void BasicJsonWriter<ALLOC>::beginArray() |
|
341 |
{ |
||
342 |
7 |
m_out.put('['); |
|
343 |
|||
344 |
7 |
m_isFirst = true; |
|
345 |
7 |
m_level += 1; |
|
346 |
7 |
} |
|
347 |
|||
348 |
template <typename ALLOC> |
||
349 |
7 |
void BasicJsonWriter<ALLOC>::endArray() |
|
350 |
{ |
||
351 |
✓✓✗✗ |
7 |
if (m_indent.hasValue()) |
352 |
1 |
m_out.put('\n'); |
|
353 |
|||
354 |
7 |
m_level -= 1; |
|
355 |
|||
356 |
7 |
writeIndent(); |
|
357 |
|||
358 |
7 |
m_out.put(']'); |
|
359 |
7 |
} |
|
360 |
|||
361 |
template <typename ALLOC> |
||
362 |
170 |
void BasicJsonWriter<ALLOC>::writeIndent() |
|
363 |
{ |
||
364 |
✓✓✓✗ |
170 |
if (m_indent.hasValue()) |
365 |
{ |
||
366 |
87 |
const auto& indent = m_indent.value(); |
|
367 |
✓✓✓✗ |
87 |
if (!indent.empty()) |
368 |
{ |
||
369 |
✓✓✓✓ |
129 |
for (size_t i = 0; i < m_level; ++i) |
370 |
47 |
m_out.write(indent.data(), static_cast<std::streamsize>(indent.size())); |
|
371 |
} |
||
372 |
} |
||
373 |
170 |
} |
|
374 |
|||
375 |
template <typename ALLOC> |
||
376 |
95 |
void BasicJsonWriter<ALLOC>::writeKey(StringView key) |
|
377 |
{ |
||
378 |
95 |
JsonEncoder::encodeString(m_out, key); |
|
379 |
95 |
m_out.write(m_keySeparator.data(), static_cast<std::streamsize>(m_keySeparator.size())); |
|
380 |
95 |
m_out.flush(); |
|
381 |
95 |
} |
|
382 |
|||
383 |
template <typename ALLOC> |
||
384 |
85 |
void BasicJsonWriter<ALLOC>::writeValue(const IBasicReflectableConstPtr<ALLOC>& reflectable) |
|
385 |
{ |
||
386 |
✓✓✗✓ |
85 |
if (!reflectable) |
387 |
{ |
||
388 |
1 |
JsonEncoder::encodeNull(m_out); |
|
389 |
1 |
return; |
|
390 |
} |
||
391 |
|||
392 |
84 |
const IBasicTypeInfo<ALLOC>& typeInfo = reflectable->getTypeInfo(); |
|
393 |
✓✓✓✓ ✓✓✓✓ ✓✓✓✗ ✗✗✗✗ ✗✓✗✗ ✗✗ |
84 |
switch (typeInfo.getCppType()) |
394 |
{ |
||
395 |
case CppType::BOOL: |
||
396 |
1 |
JsonEncoder::encodeBool(m_out, reflectable->getBool()); |
|
397 |
1 |
break; |
|
398 |
case CppType::INT8: |
||
399 |
case CppType::INT16: |
||
400 |
case CppType::INT32: |
||
401 |
case CppType::INT64: |
||
402 |
4 |
JsonEncoder::encodeIntegral(m_out, reflectable->toInt()); |
|
403 |
4 |
break; |
|
404 |
case CppType::UINT8: |
||
405 |
case CppType::UINT16: |
||
406 |
case CppType::UINT32: |
||
407 |
case CppType::UINT64: |
||
408 |
14 |
JsonEncoder::encodeIntegral(m_out, reflectable->toUInt()); |
|
409 |
14 |
break; |
|
410 |
case CppType::FLOAT: |
||
411 |
1 |
JsonEncoder::encodeFloatingPoint(m_out, static_cast<double>(reflectable->getFloat())); |
|
412 |
1 |
break; |
|
413 |
case CppType::DOUBLE: |
||
414 |
1 |
JsonEncoder::encodeFloatingPoint(m_out, reflectable->getDouble()); |
|
415 |
1 |
break; |
|
416 |
case CppType::BYTES: |
||
417 |
2 |
writeBytes(reflectable->getBytes()); |
|
418 |
2 |
break; |
|
419 |
case CppType::STRING: |
||
420 |
39 |
JsonEncoder::encodeString(m_out, reflectable->getStringView()); |
|
421 |
39 |
break; |
|
422 |
case CppType::BIT_BUFFER: |
||
423 |
2 |
writeBitBuffer(reflectable->getBitBuffer()); |
|
424 |
2 |
break; |
|
425 |
case CppType::ENUM: |
||
426 |
✓✓✗✗ |
12 |
if (m_enumerableFormat == EnumerableFormat::STRING) |
427 |
7 |
writeStringifiedEnum(reflectable); |
|
428 |
✓✓✗✗ |
5 |
else if (TypeInfoUtil::isSigned(typeInfo.getUnderlyingType().getCppType())) |
429 |
3 |
JsonEncoder::encodeIntegral(m_out, reflectable->toInt()); |
|
430 |
else |
||
431 |
2 |
JsonEncoder::encodeIntegral(m_out, reflectable->toUInt()); |
|
432 |
12 |
break; |
|
433 |
case CppType::BITMASK: |
||
434 |
✓✓✗✗ |
7 |
if (m_enumerableFormat == EnumerableFormat::STRING) |
435 |
5 |
writeStringifiedBitmask(reflectable); |
|
436 |
else |
||
437 |
2 |
JsonEncoder::encodeIntegral(m_out, reflectable->toUInt()); |
|
438 |
7 |
break; |
|
439 |
default: |
||
440 |
✓✗✓✗ ✓✗✗✗ ✗✗✗✗ |
2 |
throw CppRuntimeException("JsonWriter: Unexpected not-null value of type '") << |
441 |
✓✗✗✗ |
2 |
typeInfo.getSchemaName() << "'!"; |
442 |
} |
||
443 |
|||
444 |
83 |
m_out.flush(); |
|
445 |
} |
||
446 |
|||
447 |
template <typename ALLOC> |
||
448 |
2 |
void BasicJsonWriter<ALLOC>::writeBitBuffer(const BasicBitBuffer<ALLOC>& bitBuffer) |
|
449 |
{ |
||
450 |
✓✗✗✗ |
2 |
beginObject(); |
451 |
✓✗✗✗ |
2 |
beginItem(); |
452 |
✓✗✗✗ |
2 |
writeKey("buffer"_sv); |
453 |
✓✗✗✗ |
2 |
beginArray(); |
454 |
✓✗✗✗ |
2 |
Span<const uint8_t> buffer = bitBuffer.getData(); |
455 |
✓✓✗✗ |
6 |
for (uint8_t element : buffer) |
456 |
{ |
||
457 |
✓✗✗✗ |
4 |
beginItem(); |
458 |
✓✗✗✗ |
4 |
JsonEncoder::encodeIntegral(m_out, element); |
459 |
4 |
endItem(); |
|
460 |
} |
||
461 |
✓✗✗✗ |
2 |
endArray(); |
462 |
2 |
endItem(); |
|
463 |
✓✗✗✗ |
2 |
beginItem(); |
464 |
✓✗✗✗ |
2 |
writeKey("bitSize"_sv); |
465 |
✓✗✗✗ |
2 |
JsonEncoder::encodeIntegral(m_out, bitBuffer.getBitSize()); |
466 |
2 |
endItem(); |
|
467 |
✓✗✗✗ |
2 |
endObject(); |
468 |
2 |
} |
|
469 |
|||
470 |
template <typename ALLOC> |
||
471 |
2 |
void BasicJsonWriter<ALLOC>::writeBytes(Span<const uint8_t> value) |
|
472 |
{ |
||
473 |
2 |
beginObject(); |
|
474 |
2 |
beginItem(); |
|
475 |
2 |
writeKey("buffer"_sv); |
|
476 |
2 |
beginArray(); |
|
477 |
✓✓✗✗ |
6 |
for (uint8_t byte : value) |
478 |
{ |
||
479 |
4 |
beginItem(); |
|
480 |
4 |
JsonEncoder::encodeIntegral(m_out, byte); |
|
481 |
4 |
endItem(); |
|
482 |
} |
||
483 |
2 |
endArray(); |
|
484 |
2 |
endItem(); |
|
485 |
2 |
endObject(); |
|
486 |
2 |
} |
|
487 |
|||
488 |
template <typename ALLOC> |
||
489 |
7 |
void BasicJsonWriter<ALLOC>::writeStringifiedEnum(const IBasicReflectableConstPtr<ALLOC>& reflectable) |
|
490 |
{ |
||
491 |
✓✗✗✗ |
7 |
const auto& typeInfo = reflectable->getTypeInfo(); |
492 |
✓✗✓✗ ✓✗✓✗ ✗✗✗✗ ✗✗✗✗ |
14 |
const uint64_t enumValue = TypeInfoUtil::isSigned(typeInfo.getUnderlyingType().getCppType()) ? |
493 |
✓✓✓✗ ✗✗✗✗ |
14 |
static_cast<uint64_t>(reflectable->toInt()) : reflectable->toUInt(); |
494 |
✓✗✓✓ ✗✗✗✗ |
16 |
for (const auto& itemInfo : typeInfo.getEnumItems()) |
495 |
{ |
||
496 |
✓✓✗✗ |
14 |
if (itemInfo.value == enumValue) |
497 |
{ |
||
498 |
// exact match |
||
499 |
✓✗✗✗ |
5 |
JsonEncoder::encodeString(m_out, itemInfo.schemaName); |
500 |
10 |
return; |
|
501 |
} |
||
502 |
} |
||
503 |
|||
504 |
// no match |
||
505 |
✓✗✓✗ ✓✗✗✗ ✗✗✗✗ |
2 |
string<ALLOC> stringValue = TypeInfoUtil::isSigned(typeInfo.getUnderlyingType().getCppType()) |
506 |
1 |
? toString(reflectable->toInt(), get_allocator()) |
|
507 |
✓✓✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✓ ✓✓✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ |
5 |
: toString(reflectable->toUInt(), get_allocator()); |
508 |
✓✗✗✗ |
2 |
stringValue.append(" /* no match */"); |
509 |
✓✗✗✗ |
2 |
JsonEncoder::encodeString(m_out, stringValue); |
510 |
} |
||
511 |
|||
512 |
template <typename ALLOC> |
||
513 |
5 |
void BasicJsonWriter<ALLOC>::writeStringifiedBitmask(const IBasicReflectableConstPtr<ALLOC>& reflectable) |
|
514 |
{ |
||
515 |
✓✗✓✗ ✗✗ |
10 |
string<ALLOC> stringValue(get_allocator()); |
516 |
✓✗✗✗ |
5 |
const auto& typeInfo = reflectable->getTypeInfo(); |
517 |
✓✗✗✗ |
5 |
const uint64_t bitmaskValue = reflectable->toUInt(); |
518 |
5 |
uint64_t valueCheck = 0; |
|
519 |
✓✗✓✓ ✗✗✗✗ |
20 |
for (const auto& itemInfo : typeInfo.getBitmaskValues()) |
520 |
{ |
||
521 |
✓✓✓✓ ✓✓✓✓ ✗✗✗✗ ✗✗✗✗ |
25 |
if ((itemInfo.value != 0 && (bitmaskValue & itemInfo.value) == itemInfo.value) || |
522 |
10 |
(itemInfo.value == 0 && bitmaskValue == 0)) |
|
523 |
{ |
||
524 |
6 |
valueCheck |= itemInfo.value; |
|
525 |
✓✓✗✗ |
6 |
if (!stringValue.empty()) |
526 |
✓✗✗✗ |
2 |
stringValue += " | "; |
527 |
✓✗✓✗ ✓✗✗✗ ✗✗✗✗ |
6 |
stringValue += toString(itemInfo.schemaName, get_allocator()); |
528 |
} |
||
529 |
} |
||
530 |
|||
531 |
✓✓✗✗ |
5 |
if (stringValue.empty()) |
532 |
{ |
||
533 |
// no match |
||
534 |
✓✗✓✗ ✓✗✗✗ ✗✗✗✗ |
1 |
stringValue.append(toString(bitmaskValue, get_allocator())); |
535 |
✓✗✗✗ |
1 |
stringValue.append(" /* no match */"); |
536 |
} |
||
537 |
✓✓✗✗ |
4 |
else if (bitmaskValue != valueCheck) |
538 |
{ |
||
539 |
// partial match |
||
540 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ |
1 |
stringValue = toString(bitmaskValue, get_allocator()) |
541 |
.append(" /* partial match: ") |
||
542 |
.append(stringValue) |
||
543 |
.append(" */"); |
||
544 |
} |
||
545 |
// else exact match |
||
546 |
|||
547 |
✓✗✗✗ |
5 |
JsonEncoder::encodeString(m_out, stringValue); |
548 |
5 |
} |
|
549 |
|||
550 |
} // namespace zserio |
||
551 |
|||
552 |
#endif // ZSERIO_JSON_WRITER_H_INC |
Generated by: GCOVR (Version 4.2) |