Line | Count | Source (jump to first uncovered line) |
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( |
142 | | const IBasicReflectableConstPtr<ALLOC>& array, const BasicFieldInfo<ALLOC>& fieldInfo) override; |
143 | | void endArray( |
144 | | const IBasicReflectableConstPtr<ALLOC>& array, const BasicFieldInfo<ALLOC>& fieldInfo) override; |
145 | | |
146 | | void beginCompound(const IBasicReflectableConstPtr<ALLOC>& compound, const BasicFieldInfo<ALLOC>& fieldInfo, |
147 | | size_t elementIndex) override; |
148 | | void endCompound(const IBasicReflectableConstPtr<ALLOC>& compound, const BasicFieldInfo<ALLOC>& fieldInfo, |
149 | | size_t elementIndex) override; |
150 | | |
151 | | void visitValue(const IBasicReflectableConstPtr<ALLOC>& value, const BasicFieldInfo<ALLOC>& fieldInfo, |
152 | | 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 | | BasicJsonWriter<ALLOC>::BasicJsonWriter(std::ostream& out, const ALLOC& allocator) : |
190 | | BasicJsonWriter(out, NullOpt, allocator) |
191 | 28 | {} |
192 | | |
193 | | template <typename ALLOC> |
194 | | BasicJsonWriter<ALLOC>::BasicJsonWriter(std::ostream& out, uint8_t indent, const ALLOC& allocator) : |
195 | | BasicJsonWriter(out, string<ALLOC>(indent, ' ', allocator), allocator) |
196 | 38 | {} |
197 | | |
198 | | template <typename ALLOC> |
199 | | BasicJsonWriter<ALLOC>::BasicJsonWriter( |
200 | | std::ostream& out, const string<ALLOC>& indent, const ALLOC& allocator) : |
201 | | BasicJsonWriter(out, InplaceOptionalHolder<string<ALLOC>>(indent), allocator) |
202 | 40 | {} |
203 | | |
204 | | template <typename ALLOC> |
205 | | BasicJsonWriter<ALLOC>::BasicJsonWriter( |
206 | | std::ostream& out, InplaceOptionalHolder<string<ALLOC>>&& optionalIndent, const ALLOC& allocator) : |
207 | | AllocatorHolder<ALLOC>(allocator), |
208 | | m_out(out), |
209 | | m_indent(optionalIndent), |
210 | | m_itemSeparator( |
211 | | m_indent.hasValue() ? DEFAULT_ITEM_SEPARATOR_WITH_INDENT : DEFAULT_ITEM_SEPARATOR, allocator), |
212 | | m_keySeparator(DEFAULT_KEY_SEPARATOR, allocator) |
213 | 68 | {} |
214 | | |
215 | | template <typename ALLOC> |
216 | | void BasicJsonWriter<ALLOC>::setItemSeparator(const string<ALLOC>& itemSeparator) |
217 | 1 | { |
218 | 1 | m_itemSeparator = itemSeparator; |
219 | 1 | } |
220 | | |
221 | | template <typename ALLOC> |
222 | | void BasicJsonWriter<ALLOC>::setKeySeparator(const string<ALLOC>& keySeparator) |
223 | 1 | { |
224 | 1 | m_keySeparator = keySeparator; |
225 | 1 | } |
226 | | |
227 | | template <typename ALLOC> |
228 | | void BasicJsonWriter<ALLOC>::setEnumerableFormat(EnumerableFormat enumerableFormat) |
229 | 3 | { |
230 | 3 | m_enumerableFormat = enumerableFormat; |
231 | 3 | } |
232 | | |
233 | | template <typename ALLOC> |
234 | | void BasicJsonWriter<ALLOC>::beginRoot(const IBasicReflectableConstPtr<ALLOC>&) |
235 | 45 | { |
236 | 45 | beginObject(); |
237 | 45 | } |
238 | | |
239 | | template <typename ALLOC> |
240 | | void BasicJsonWriter<ALLOC>::endRoot(const IBasicReflectableConstPtr<ALLOC>&) |
241 | 45 | { |
242 | 45 | endObject(); |
243 | 45 | m_out.flush(); |
244 | 45 | } |
245 | | |
246 | | template <typename ALLOC> |
247 | | void BasicJsonWriter<ALLOC>::beginArray( |
248 | | const IBasicReflectableConstPtr<ALLOC>&, const BasicFieldInfo<ALLOC>& fieldInfo) |
249 | 3 | { |
250 | 3 | beginItem(); |
251 | | |
252 | 3 | writeKey(fieldInfo.schemaName); |
253 | | |
254 | 3 | beginArray(); |
255 | 3 | } |
256 | | |
257 | | template <typename ALLOC> |
258 | | void BasicJsonWriter<ALLOC>::endArray(const IBasicReflectableConstPtr<ALLOC>&, const BasicFieldInfo<ALLOC>&) |
259 | 3 | { |
260 | 3 | endArray(); |
261 | | |
262 | 3 | endItem(); |
263 | 3 | } |
264 | | |
265 | | template <typename ALLOC> |
266 | | void BasicJsonWriter<ALLOC>::beginCompound( |
267 | | const IBasicReflectableConstPtr<ALLOC>&, const BasicFieldInfo<ALLOC>& fieldInfo, size_t elementIndex) |
268 | 6 | { |
269 | 6 | beginItem(); |
270 | | |
271 | 6 | if (elementIndex == WALKER_NOT_ELEMENT) |
272 | 5 | writeKey(fieldInfo.schemaName); |
273 | | |
274 | 6 | beginObject(); |
275 | 6 | } |
276 | | |
277 | | template <typename ALLOC> |
278 | | void BasicJsonWriter<ALLOC>::endCompound( |
279 | | const IBasicReflectableConstPtr<ALLOC>&, const BasicFieldInfo<ALLOC>&, size_t) |
280 | 6 | { |
281 | 6 | endObject(); |
282 | | |
283 | 6 | endItem(); |
284 | 6 | } |
285 | | |
286 | | template <typename ALLOC> |
287 | | void BasicJsonWriter<ALLOC>::visitValue(const IBasicReflectableConstPtr<ALLOC>& value, |
288 | | const BasicFieldInfo<ALLOC>& fieldInfo, size_t elementIndex) |
289 | 85 | { |
290 | 85 | beginItem(); |
291 | | |
292 | 85 | if (elementIndex == WALKER_NOT_ELEMENT) |
293 | 81 | writeKey(fieldInfo.schemaName); |
294 | | |
295 | 85 | writeValue(value); |
296 | | |
297 | 85 | endItem(); |
298 | 85 | } |
299 | | |
300 | | template <typename ALLOC> |
301 | | void BasicJsonWriter<ALLOC>::beginItem() |
302 | 108 | { |
303 | 108 | if (!m_isFirst) |
304 | 29 | m_out.write(m_itemSeparator.data(), static_cast<std::streamsize>(m_itemSeparator.size())); |
305 | | |
306 | 108 | if (m_indent.hasValue()) |
307 | 43 | m_out.put('\n'); |
308 | | |
309 | 108 | writeIndent(); |
310 | 108 | } |
311 | | |
312 | | template <typename ALLOC> |
313 | | void BasicJsonWriter<ALLOC>::endItem() |
314 | 107 | { |
315 | 107 | m_isFirst = false; |
316 | 107 | } |
317 | | |
318 | | template <typename ALLOC> |
319 | | void BasicJsonWriter<ALLOC>::beginObject() |
320 | 55 | { |
321 | 55 | m_out.put('{'); |
322 | | |
323 | 55 | m_isFirst = true; |
324 | 55 | m_level += 1; |
325 | 55 | } |
326 | | |
327 | | template <typename ALLOC> |
328 | | void BasicJsonWriter<ALLOC>::endObject() |
329 | 55 | { |
330 | 55 | if (m_indent.hasValue()) |
331 | 43 | m_out.put('\n'); |
332 | | |
333 | 55 | m_level -= 1; |
334 | | |
335 | 55 | writeIndent(); |
336 | | |
337 | 55 | m_out.put('}'); |
338 | 55 | } |
339 | | |
340 | | template <typename ALLOC> |
341 | | void BasicJsonWriter<ALLOC>::beginArray() |
342 | 7 | { |
343 | 7 | m_out.put('['); |
344 | | |
345 | 7 | m_isFirst = true; |
346 | 7 | m_level += 1; |
347 | 7 | } |
348 | | |
349 | | template <typename ALLOC> |
350 | | void BasicJsonWriter<ALLOC>::endArray() |
351 | 7 | { |
352 | 7 | if (m_indent.hasValue()) |
353 | 1 | m_out.put('\n'); |
354 | | |
355 | 7 | m_level -= 1; |
356 | | |
357 | 7 | writeIndent(); |
358 | | |
359 | 7 | m_out.put(']'); |
360 | 7 | } |
361 | | |
362 | | template <typename ALLOC> |
363 | | void BasicJsonWriter<ALLOC>::writeIndent() |
364 | 170 | { |
365 | 170 | if (m_indent.hasValue()) |
366 | 87 | { |
367 | 87 | const auto& indent = m_indent.value(); |
368 | 87 | if (!indent.empty()) |
369 | 82 | { |
370 | 129 | for (size_t i = 0; i < m_level; ++i47 ) |
371 | 47 | m_out.write(indent.data(), static_cast<std::streamsize>(indent.size())); |
372 | 82 | } |
373 | 87 | } |
374 | 170 | } |
375 | | |
376 | | template <typename ALLOC> |
377 | | void BasicJsonWriter<ALLOC>::writeKey(StringView key) |
378 | 95 | { |
379 | 95 | JsonEncoder::encodeString(m_out, key); |
380 | 95 | m_out.write(m_keySeparator.data(), static_cast<std::streamsize>(m_keySeparator.size())); |
381 | 95 | m_out.flush(); |
382 | 95 | } |
383 | | |
384 | | template <typename ALLOC> |
385 | | void BasicJsonWriter<ALLOC>::writeValue(const IBasicReflectableConstPtr<ALLOC>& reflectable) |
386 | 85 | { |
387 | 85 | if (!reflectable) |
388 | 1 | { |
389 | 1 | JsonEncoder::encodeNull(m_out); |
390 | 1 | return; |
391 | 1 | } |
392 | | |
393 | 84 | const IBasicTypeInfo<ALLOC>& typeInfo = reflectable->getTypeInfo(); |
394 | 84 | switch (typeInfo.getCppType()) |
395 | 84 | { |
396 | 1 | case CppType::BOOL: |
397 | 1 | JsonEncoder::encodeBool(m_out, reflectable->getBool()); |
398 | 1 | break; |
399 | 1 | case CppType::INT8: |
400 | 2 | case CppType::INT16: |
401 | 3 | case CppType::INT32: |
402 | 4 | case CppType::INT64: |
403 | 4 | JsonEncoder::encodeIntegral(m_out, reflectable->toInt()); |
404 | 4 | break; |
405 | 1 | case CppType::UINT8: |
406 | 2 | case CppType::UINT16: |
407 | 13 | case CppType::UINT32: |
408 | 14 | case CppType::UINT64: |
409 | 14 | JsonEncoder::encodeIntegral(m_out, reflectable->toUInt()); |
410 | 14 | break; |
411 | 1 | case CppType::FLOAT: |
412 | 1 | JsonEncoder::encodeFloatingPoint(m_out, static_cast<double>(reflectable->getFloat())); |
413 | 1 | break; |
414 | 1 | case CppType::DOUBLE: |
415 | 1 | JsonEncoder::encodeFloatingPoint(m_out, reflectable->getDouble()); |
416 | 1 | break; |
417 | 2 | case CppType::BYTES: |
418 | 2 | writeBytes(reflectable->getBytes()); |
419 | 2 | break; |
420 | 39 | case CppType::STRING: |
421 | 39 | JsonEncoder::encodeString(m_out, reflectable->getStringView()); |
422 | 39 | break; |
423 | 2 | case CppType::BIT_BUFFER: |
424 | 2 | writeBitBuffer(reflectable->getBitBuffer()); |
425 | 2 | break; |
426 | 12 | case CppType::ENUM: |
427 | 12 | if (m_enumerableFormat == EnumerableFormat::STRING) |
428 | 7 | writeStringifiedEnum(reflectable); |
429 | 5 | else if (TypeInfoUtil::isSigned(typeInfo.getUnderlyingType().getCppType())) |
430 | 3 | JsonEncoder::encodeIntegral(m_out, reflectable->toInt()); |
431 | 2 | else |
432 | 2 | JsonEncoder::encodeIntegral(m_out, reflectable->toUInt()); |
433 | 12 | break; |
434 | 7 | case CppType::BITMASK: |
435 | 7 | if (m_enumerableFormat == EnumerableFormat::STRING) |
436 | 5 | writeStringifiedBitmask(reflectable); |
437 | 2 | else |
438 | 2 | JsonEncoder::encodeIntegral(m_out, reflectable->toUInt()); |
439 | 7 | break; |
440 | 1 | default: |
441 | 1 | throw CppRuntimeException("JsonWriter: Unexpected not-null value of type '") |
442 | 1 | << typeInfo.getSchemaName() << "'!"; |
443 | 84 | } |
444 | | |
445 | 83 | m_out.flush(); |
446 | 83 | } |
447 | | |
448 | | template <typename ALLOC> |
449 | | void BasicJsonWriter<ALLOC>::writeBitBuffer(const BasicBitBuffer<ALLOC>& bitBuffer) |
450 | 2 | { |
451 | 2 | beginObject(); |
452 | 2 | beginItem(); |
453 | 2 | writeKey("buffer"_sv); |
454 | 2 | beginArray(); |
455 | 2 | Span<const uint8_t> buffer = bitBuffer.getData(); |
456 | 2 | for (uint8_t element : buffer) |
457 | 4 | { |
458 | 4 | beginItem(); |
459 | 4 | JsonEncoder::encodeIntegral(m_out, element); |
460 | 4 | endItem(); |
461 | 4 | } |
462 | 2 | endArray(); |
463 | 2 | endItem(); |
464 | 2 | beginItem(); |
465 | 2 | writeKey("bitSize"_sv); |
466 | 2 | JsonEncoder::encodeIntegral(m_out, bitBuffer.getBitSize()); |
467 | 2 | endItem(); |
468 | 2 | endObject(); |
469 | 2 | } |
470 | | |
471 | | template <typename ALLOC> |
472 | | void BasicJsonWriter<ALLOC>::writeBytes(Span<const uint8_t> value) |
473 | 2 | { |
474 | 2 | beginObject(); |
475 | 2 | beginItem(); |
476 | 2 | writeKey("buffer"_sv); |
477 | 2 | beginArray(); |
478 | 2 | for (uint8_t byte : value) |
479 | 4 | { |
480 | 4 | beginItem(); |
481 | 4 | JsonEncoder::encodeIntegral(m_out, byte); |
482 | 4 | endItem(); |
483 | 4 | } |
484 | 2 | endArray(); |
485 | 2 | endItem(); |
486 | 2 | endObject(); |
487 | 2 | } |
488 | | |
489 | | template <typename ALLOC> |
490 | | void BasicJsonWriter<ALLOC>::writeStringifiedEnum(const IBasicReflectableConstPtr<ALLOC>& reflectable) |
491 | 7 | { |
492 | 7 | const auto& typeInfo = reflectable->getTypeInfo(); |
493 | 7 | const uint64_t enumValue = TypeInfoUtil::isSigned(typeInfo.getUnderlyingType().getCppType()) |
494 | 7 | ? static_cast<uint64_t>(reflectable->toInt())4 |
495 | 7 | : reflectable->toUInt()3 ; |
496 | 7 | for (const auto& itemInfo : typeInfo.getEnumItems()) |
497 | 14 | { |
498 | 14 | if (itemInfo.value == enumValue) |
499 | 5 | { |
500 | | // exact match |
501 | 5 | JsonEncoder::encodeString(m_out, itemInfo.schemaName); |
502 | 5 | return; |
503 | 5 | } |
504 | 14 | } |
505 | | |
506 | | // no match |
507 | 2 | string<ALLOC> stringValue = TypeInfoUtil::isSigned(typeInfo.getUnderlyingType().getCppType()) |
508 | 2 | ? toString(reflectable->toInt(), get_allocator())1 |
509 | 2 | : toString(reflectable->toUInt(), get_allocator())1 ; |
510 | 2 | stringValue.append(" /* no match */"); |
511 | 2 | JsonEncoder::encodeString(m_out, stringValue); |
512 | 2 | } |
513 | | |
514 | | template <typename ALLOC> |
515 | | void BasicJsonWriter<ALLOC>::writeStringifiedBitmask(const IBasicReflectableConstPtr<ALLOC>& reflectable) |
516 | 5 | { |
517 | 5 | string<ALLOC> stringValue(get_allocator()); |
518 | 5 | const auto& typeInfo = reflectable->getTypeInfo(); |
519 | 5 | const uint64_t bitmaskValue = reflectable->toUInt(); |
520 | 5 | uint64_t valueCheck = 0; |
521 | 5 | for (const auto& itemInfo : typeInfo.getBitmaskValues()) |
522 | 15 | { |
523 | 15 | if ((itemInfo.value != 0 && (bitmaskValue & itemInfo.value) == itemInfo.value10 ) || |
524 | 15 | (10 itemInfo.value == 010 && bitmaskValue == 05 )) |
525 | 6 | { |
526 | 6 | valueCheck |= itemInfo.value; |
527 | 6 | if (!stringValue.empty()) |
528 | 2 | stringValue += " | "; |
529 | 6 | stringValue += toString(itemInfo.schemaName, get_allocator()); |
530 | 6 | } |
531 | 15 | } |
532 | | |
533 | 5 | if (stringValue.empty()) |
534 | 1 | { |
535 | | // no match |
536 | 1 | stringValue.append(toString(bitmaskValue, get_allocator())); |
537 | 1 | stringValue.append(" /* no match */"); |
538 | 1 | } |
539 | 4 | else if (bitmaskValue != valueCheck) |
540 | 1 | { |
541 | | // partial match |
542 | 1 | stringValue = |
543 | 1 | toString(bitmaskValue, get_allocator()) |
544 | 1 | .append(" /* partial match: ") |
545 | 1 | .append(stringValue) |
546 | 1 | .append(" */"); |
547 | 1 | } |
548 | | // else exact match |
549 | | |
550 | 5 | JsonEncoder::encodeString(m_out, stringValue); |
551 | 5 | } |
552 | | |
553 | | } // namespace zserio |
554 | | |
555 | | #endif // ZSERIO_JSON_WRITER_H_INC |