GCC Code Coverage Report | |||||||||||||||||||||
|
|||||||||||||||||||||
Line | Branch | Exec | Source |
1 |
#ifndef ZSERIO_ZSERIO_TREE_CREATOR_H_INC |
||
2 |
#define ZSERIO_ZSERIO_TREE_CREATOR_H_INC |
||
3 |
|||
4 |
#include <limits> |
||
5 |
#include <type_traits> |
||
6 |
#include <cerrno> |
||
7 |
#include <cstdlib> |
||
8 |
|||
9 |
#include "zserio/BitBuffer.h" |
||
10 |
#include "zserio/CppRuntimeException.h" |
||
11 |
#include "zserio/IReflectable.h" |
||
12 |
#include "zserio/ITypeInfo.h" |
||
13 |
#include "zserio/StringView.h" |
||
14 |
#include "zserio/TypeInfoUtil.h" |
||
15 |
#include "zserio/Traits.h" |
||
16 |
#include "zserio/Vector.h" |
||
17 |
#include "zserio/Types.h" |
||
18 |
|||
19 |
namespace zserio |
||
20 |
{ |
||
21 |
|||
22 |
namespace detail |
||
23 |
{ |
||
24 |
|||
25 |
template <typename T, typename ALLOC> |
||
26 |
AnyHolder<ALLOC> makeAnyValue(const IBasicTypeInfo<ALLOC>& typeInfo, T&& value, const ALLOC& allocator); |
||
27 |
|||
28 |
template <typename T, typename U, |
||
29 |
typename std::enable_if<std::is_unsigned<typename std::decay<U>::type>::value, int>::type = 0> |
||
30 |
53 |
bool checkArithmeticValueRanges(U value) |
|
31 |
{ |
||
32 |
// value is unsigned |
||
33 |
53 |
return (value <= static_cast<U>(std::numeric_limits<T>::max())); |
|
34 |
} |
||
35 |
|||
36 |
template <typename T, typename U, |
||
37 |
typename std::enable_if<std::is_signed<typename std::decay<U>::type>::value && |
||
38 |
std::is_signed<typename std::decay<T>::type>::value, int>::type = 0> |
||
39 |
17 |
bool checkArithmeticValueRanges(U value) |
|
40 |
{ |
||
41 |
// value is signed and it is converted to signed value |
||
42 |
17 |
return (static_cast<int64_t>(value) >= static_cast<int64_t>(std::numeric_limits<T>::min()) && |
|
43 |
✗✗✗✗ ✓✓✗✓ ✗✗✗✗ ✓✗✓✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✓✗✓✗ ✓✗✓✗ ✓✓✓✓ ✓✓✓✓ |
18 |
static_cast<int64_t>(value) <= static_cast<int64_t>(std::numeric_limits<T>::max())); |
44 |
} |
||
45 |
|||
46 |
template <typename T, typename U, |
||
47 |
typename std::enable_if<std::is_signed<typename std::decay<U>::type>::value && |
||
48 |
std::is_unsigned<typename std::decay<T>::type>::value, int>::type = 0> |
||
49 |
18 |
bool checkArithmeticValueRanges(U value) |
|
50 |
{ |
||
51 |
// value is signed and it is converted to unsigned value |
||
52 |
✗✗✗✗ ✓✗✗✓ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✓✓✓✗ ✓✓✓✗ ✓✓✓✓ ✓✓✓✓ |
18 |
return (value >= 0 && static_cast<uint64_t>(value) <= static_cast<uint64_t>(std::numeric_limits<T>::max())); |
53 |
} |
||
54 |
|||
55 |
template <typename T, typename ALLOC> |
||
56 |
3 |
AnyHolder<ALLOC> makeAnyBoolValue(bool value, const ALLOC& allocator) |
|
57 |
{ |
||
58 |
✓✗✗✗ |
3 |
return AnyHolder<ALLOC>(static_cast<T>(value), allocator); |
59 |
} |
||
60 |
|||
61 |
template <typename T, typename U, typename ALLOC> |
||
62 |
4 |
AnyHolder<ALLOC> makeAnyBoolValue(const U& value, const ALLOC&) |
|
63 |
{ |
||
64 |
✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗ |
8 |
throw CppRuntimeException("ZserioTreeCreator: Value '") << value << |
65 |
8 |
"' cannot be converted to bool value!"; |
|
66 |
} |
||
67 |
|||
68 |
template <typename T, typename ALLOC> |
||
69 |
8 |
AnyHolder<ALLOC> makeAnyIntegralValue(bool value, const ALLOC&) |
|
70 |
{ |
||
71 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ |
16 |
throw CppRuntimeException("ZserioTreeCreator: Bool value '") << value << |
72 |
16 |
"' cannot be converted to integral type!"; |
|
73 |
} |
||
74 |
|||
75 |
template <typename T, typename U, typename ALLOC, |
||
76 |
typename std::enable_if<std::is_integral<typename std::decay<U>::type>::value, int>::type = 0> |
||
77 |
88 |
AnyHolder<ALLOC> makeAnyIntegralValue(U value, const ALLOC& allocator) |
|
78 |
{ |
||
79 |
// check ranges of integers |
||
80 |
✗✗✗✗ ✗✗✗✓ ✗✗✓✓ ✗✗✗✓ ✓✗✗✗ ✗✗✗✓ ✗✗✓✗ ✗✗✗✗ ✗✗✓✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✓✗✓ ✓✓✓✓ ✓✓✓✓ ✓✓✓✓ |
88 |
if (!checkArithmeticValueRanges<T>(value)) |
81 |
{ |
||
82 |
✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✓✗✓✗ ✓✗✓✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✓✗✓✗ ✓✗✓✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✓✗✓✗ ✓✗✓✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✓✗✓✗ ✓✗✓✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ |
45 |
throw CppRuntimeException("ZserioTreeCreator: Integral value '") << value << "' overflow (<" << |
83 |
✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✓✗ ✓✗✓✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✓✗✓✗ ✓✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✓✗ ✓✗✓✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✓✗ ✓✗✓✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ |
45 |
std::numeric_limits<T>::min() << ", " << std::numeric_limits<T>::max() << ">)!"; |
84 |
} |
||
85 |
|||
86 |
✗✗✗✗ ✗✗✓✗ ✗✗✓✗ ✗✗✓✗ ✗✗✗✗ ✗✗✓✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ |
73 |
return AnyHolder<ALLOC>(static_cast<T>(value), allocator); |
87 |
} |
||
88 |
|||
89 |
template <typename T, typename U, typename ALLOC, |
||
90 |
typename std::enable_if<!std::is_integral<typename std::decay<U>::type>::value, int>::type = 0> |
||
91 |
27 |
AnyHolder<ALLOC> makeAnyIntegralValue(const U& value, const ALLOC&) |
|
92 |
{ |
||
93 |
✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✓✗ ✓✗✓✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✓✗ ✓✗✓✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✓✗ ✓✗✓✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ |
54 |
throw CppRuntimeException("ZserioTreeCreator: Value '") << value << |
94 |
54 |
"' cannot be converted to integral value!"; |
|
95 |
} |
||
96 |
|||
97 |
template <typename T, typename ALLOC> |
||
98 |
2 |
AnyHolder<ALLOC> makeAnyFloatingValue(bool value, const ALLOC&) |
|
99 |
{ |
||
100 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ |
4 |
throw CppRuntimeException("ZserioTreeCreator: Bool value '") << value << |
101 |
4 |
"' cannot be converted to floating type!"; |
|
102 |
} |
||
103 |
|||
104 |
template <typename T, typename U, typename ALLOC, |
||
105 |
typename std::enable_if<std::is_arithmetic<typename std::decay<U>::type>::value, int>::type = 0> |
||
106 |
6 |
AnyHolder<ALLOC> makeAnyFloatingValue(U value, const ALLOC& allocator) |
|
107 |
{ |
||
108 |
// allow conversion integers to floats |
||
109 |
✓✗✓✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✓✗✓✗ ✓✗✓✗ |
6 |
return AnyHolder<ALLOC>(static_cast<T>(value), allocator); |
110 |
} |
||
111 |
|||
112 |
template <typename T, typename U, typename ALLOC, |
||
113 |
typename std::enable_if<!std::is_arithmetic<typename std::decay<U>::type>::value, int>::type = 0> |
||
114 |
4 |
AnyHolder<ALLOC> makeAnyFloatingValue(const U& value, const ALLOC&) |
|
115 |
{ |
||
116 |
✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ |
8 |
throw CppRuntimeException("ZserioTreeCreator: Value '") << value << |
117 |
8 |
"' cannot be converted to floating value!"; |
|
118 |
} |
||
119 |
|||
120 |
template <typename ALLOC> |
||
121 |
2 |
AnyHolder<ALLOC> makeAnyStringValue(const string<ALLOC>& value, const ALLOC& allocator) |
|
122 |
{ |
||
123 |
2 |
return AnyHolder<ALLOC>(value, allocator); |
|
124 |
} |
||
125 |
|||
126 |
template <typename ALLOC> |
||
127 |
2 |
AnyHolder<ALLOC> makeAnyStringValue(string<ALLOC>&& value, const ALLOC& allocator) |
|
128 |
{ |
||
129 |
2 |
return AnyHolder<ALLOC>(std::move(value), allocator); |
|
130 |
} |
||
131 |
|||
132 |
template <typename ALLOC> |
||
133 |
62 |
AnyHolder<ALLOC> makeAnyStringValue(StringView value, const ALLOC& allocator) |
|
134 |
{ |
||
135 |
✓✗✓✗ |
62 |
return AnyHolder<ALLOC>(toString(value, allocator), allocator); |
136 |
} |
||
137 |
|||
138 |
template <typename ALLOC> |
||
139 |
7 |
AnyHolder<ALLOC> makeAnyStringValue(const char* value, const ALLOC& allocator) |
|
140 |
{ |
||
141 |
✓✗ | 7 |
return makeAnyStringValue(StringView(value), allocator); |
142 |
} |
||
143 |
|||
144 |
template <typename T, typename ALLOC> |
||
145 |
5 |
AnyHolder<ALLOC> makeAnyStringValue(const T&, const ALLOC&) |
|
146 |
{ |
||
147 |
✗✗✗✗ ✗✗✓✗ ✗✗✗✗ ✗✗✗✗ ✗✗✓✗ ✓✗✓✗ ✗✗ |
5 |
throw CppRuntimeException("ZserioTreeCreator: Trying to make any string value from unsupported type!"); |
148 |
} |
||
149 |
|||
150 |
template <typename ALLOC> |
||
151 |
11 |
AnyHolder<ALLOC> parseEnumStringValue(StringView stringValue, const IBasicTypeInfo<ALLOC>& typeInfo, |
|
152 |
const ALLOC& allocator) |
||
153 |
{ |
||
154 |
✓✓✗✗ |
30 |
for (const auto& itemInfo : typeInfo.getEnumItems()) |
155 |
{ |
||
156 |
✓✓✗✗ |
26 |
if (itemInfo.schemaName == stringValue) |
157 |
{ |
||
158 |
✓✓✗✗ |
7 |
if (TypeInfoUtil::isSigned(typeInfo.getUnderlyingType().getCppType())) |
159 |
{ |
||
160 |
✓✗✗✗ |
10 |
return makeAnyValue(typeInfo.getUnderlyingType(), static_cast<int64_t>(itemInfo.value), |
161 |
✓✗✗✗ |
10 |
allocator); |
162 |
} |
||
163 |
else |
||
164 |
{ |
||
165 |
2 |
return makeAnyValue(typeInfo.getUnderlyingType(), itemInfo.value, allocator); |
|
166 |
} |
||
167 |
} |
||
168 |
} |
||
169 |
|||
170 |
4 |
return AnyHolder<ALLOC>(allocator); |
|
171 |
} |
||
172 |
|||
173 |
template <typename ALLOC> |
||
174 |
24 |
AnyHolder<ALLOC> makeAnyEnumValue(StringView stringValue, const IBasicTypeInfo<ALLOC>& typeInfo, |
|
175 |
const ALLOC& allocator) |
||
176 |
{ |
||
177 |
✓✓✗✗ |
24 |
if (!stringValue.empty()) |
178 |
{ |
||
179 |
22 |
const char firstChar = stringValue[0]; |
|
180 |
✓✓✓✓ ✓✓✓✓ ✓✓✗✗ ✗✗✗✗ ✗✗✗✗ |
22 |
if ((firstChar >= 'A' && firstChar <= 'Z') || (firstChar >= 'a' && firstChar <= 'z') || |
181 |
firstChar == '_') |
||
182 |
{ |
||
183 |
✓✗✗✗ |
15 |
AnyHolder<ALLOC> anyValue = parseEnumStringValue(stringValue, typeInfo, allocator); |
184 |
✓✓✗✗ ✗ |
11 |
if (anyValue.hasValue()) |
185 |
✓✓✗✗ |
14 |
return anyValue; |
186 |
} |
||
187 |
// else it's a no match |
||
188 |
} |
||
189 |
|||
190 |
✓✗✓✗ ✓✗✓✗ ✗✗✗✗ ✗✗✗✗ |
34 |
throw CppRuntimeException("ZserioTreeCreator: Cannot create enum '") << typeInfo.getSchemaName() << |
191 |
✓✗✓✗ ✗✗✗✗ |
34 |
"' from string value '" << stringValue << "'!"; |
192 |
} |
||
193 |
|||
194 |
template <typename ALLOC> |
||
195 |
2 |
AnyHolder<ALLOC> makeAnyEnumValue(const string<ALLOC>& stringValue, const IBasicTypeInfo<ALLOC>& typeInfo, |
|
196 |
const ALLOC& allocator) |
||
197 |
{ |
||
198 |
✗✓ | 2 |
return makeAnyEnumValue(StringView(stringValue), typeInfo, allocator); |
199 |
} |
||
200 |
|||
201 |
template <typename ALLOC> |
||
202 |
3 |
AnyHolder<ALLOC> makeAnyEnumValue(const char* stringValue, const IBasicTypeInfo<ALLOC>& typeInfo, |
|
203 |
const ALLOC& allocator) |
||
204 |
{ |
||
205 |
✓✓ | 3 |
return makeAnyEnumValue(StringView(stringValue), typeInfo, allocator); |
206 |
} |
||
207 |
|||
208 |
template <typename T, typename ALLOC, |
||
209 |
typename std::enable_if<std::is_enum<T>::value, int>::type = 0> |
||
210 |
3 |
AnyHolder<ALLOC> makeAnyEnumValue(T enumValue, const IBasicTypeInfo<ALLOC>&, const ALLOC& allocator) |
|
211 |
{ |
||
212 |
3 |
return AnyHolder<ALLOC>(enumValue, allocator); |
|
213 |
} |
||
214 |
|||
215 |
template <typename T, typename ALLOC, |
||
216 |
typename std::enable_if<!std::is_enum<T>::value, int>::type = 0> |
||
217 |
8 |
AnyHolder<ALLOC> makeAnyEnumValue(T enumRawValue, const IBasicTypeInfo<ALLOC>& typeInfo, |
|
218 |
const ALLOC& allocator) |
||
219 |
{ |
||
220 |
8 |
return makeAnyValue(typeInfo.getUnderlyingType(), enumRawValue, allocator); |
|
221 |
} |
||
222 |
|||
223 |
template <typename ALLOC> |
||
224 |
26 |
AnyHolder<ALLOC> parseBitmaskStringValue(StringView stringValue, const IBasicTypeInfo<ALLOC>& typeInfo, |
|
225 |
const ALLOC& allocator) |
||
226 |
{ |
||
227 |
26 |
uint64_t value = 0; |
|
228 |
26 |
size_t pos = 0; |
|
229 |
✓✓✗✗ |
62 |
while (pos < stringValue.size()) |
230 |
{ |
||
231 |
38 |
bool match = false; |
|
232 |
38 |
const size_t available = stringValue.size() - pos; |
|
233 |
✓✗✓✓ ✗✗✗✗ |
73 |
for (const auto& itemInfo : typeInfo.getBitmaskValues()) |
234 |
{ |
||
235 |
✓✓✓✓ ✓✓✗✗ ✗✗✗✗ |
127 |
if (available >= itemInfo.schemaName.size() && |
236 |
✓✗✗✗ |
63 |
stringValue.substr(pos, itemInfo.schemaName.size()) == itemInfo.schemaName) |
237 |
{ |
||
238 |
44 |
const size_t newPos = pos + itemInfo.schemaName.size(); |
|
239 |
// check that the identifier really ends here |
||
240 |
✓✓✓✓ ✓✓✓✓ ✗✗✗✗ ✗✗✗✗ |
44 |
if (newPos == stringValue.size() || stringValue[newPos] == ' ' || stringValue[newPos] == '|' ) |
241 |
{ |
||
242 |
29 |
value |= itemInfo.value; |
|
243 |
✓✓✗✗ |
29 |
if (newPos == stringValue.size()) |
244 |
✓✗✓✗ ✗✗✗✗ |
11 |
return makeAnyValue(typeInfo.getUnderlyingType(), value, allocator); // end of string |
245 |
18 |
match = true; |
|
246 |
18 |
pos += itemInfo.schemaName.size(); |
|
247 |
18 |
break; |
|
248 |
} |
||
249 |
} |
||
250 |
} |
||
251 |
|||
252 |
✓✓✗✗ |
27 |
if (!match) |
253 |
9 |
break; |
|
254 |
|||
255 |
✓✓✓✓ ✓✓✗✗ ✗✗✗✗ |
48 |
while (pos < stringValue.size() && stringValue[pos] == ' ') |
256 |
15 |
++pos; |
|
257 |
|||
258 |
✓✓✓✓ ✓✓✗✗ ✗✗✗✗ |
18 |
if (pos < stringValue.size() && stringValue[pos] == '|') |
259 |
15 |
++pos; |
|
260 |
|||
261 |
✓✓✓✓ ✓✓✗✗ ✗✗✗✗ |
40 |
while (pos < stringValue.size() && stringValue[pos] == ' ') |
262 |
11 |
++pos; |
|
263 |
} |
||
264 |
|||
265 |
// invalid format or identifier |
||
266 |
✗✗ | 15 |
return AnyHolder<ALLOC>(allocator); |
267 |
} |
||
268 |
|||
269 |
template <typename ALLOC> |
||
270 |
10 |
AnyHolder<ALLOC> parseBitmaskNumericStringValue(const char* stringValue, const IBasicTypeInfo<ALLOC>& typeInfo, |
|
271 |
const ALLOC& allocator) |
||
272 |
{ |
||
273 |
10 |
char *pEnd = nullptr; |
|
274 |
10 |
errno = 0; |
|
275 |
10 |
uint64_t value = std::strtoull(stringValue, &pEnd, 10); |
|
276 |
✓✓✗✗ |
10 |
if (errno == ERANGE) |
277 |
✗✗ | 1 |
return AnyHolder<ALLOC>(allocator); |
278 |
✓✗✓✗ ✗✗✗✗ |
9 |
return makeAnyValue(typeInfo.getUnderlyingType(), value, allocator); |
279 |
} |
||
280 |
|||
281 |
template <typename ALLOC> |
||
282 |
32 |
AnyHolder<ALLOC> makeAnyBitmaskValue(StringView stringValue, const IBasicTypeInfo<ALLOC>& typeInfo, |
|
283 |
const ALLOC& allocator) |
||
284 |
{ |
||
285 |
✓✓✗✗ |
32 |
if (!stringValue.empty()) |
286 |
{ |
||
287 |
30 |
const char firstChar = stringValue[0]; |
|
288 |
✓✓✓✓ ✓✓✓✓ ✓✓✗✗ ✗✗✗✗ ✗✗✗✗ |
30 |
if ((firstChar >= 'A' && firstChar <= 'Z') || (firstChar >= 'a' && firstChar <= 'z') || |
289 |
firstChar == '_') |
||
290 |
{ |
||
291 |
✓✗✗✗ |
25 |
AnyHolder<ALLOC> anyValue = parseBitmaskStringValue(stringValue, typeInfo, allocator); |
292 |
✓✓✗✗ ✗ |
15 |
if (anyValue.hasValue()) |
293 |
✓✓✗✗ |
15 |
return anyValue; |
294 |
} |
||
295 |
✓✓✓✓ ✗✗✗✗ |
15 |
else if (firstChar >= '0' && firstChar <= '9') // bitmask can be only unsigned |
296 |
{ |
||
297 |
// ensure zero-terminated string |
||
298 |
✓✗✗✗ |
11 |
const string<ALLOC> numericStringValue = toString(stringValue, allocator); |
299 |
AnyHolder<ALLOC> anyValue = parseBitmaskNumericStringValue(numericStringValue.c_str(), typeInfo, |
||
300 |
✓✗✓✓ ✗✗✗✗ |
11 |
allocator); |
301 |
✓✓✗✗ ✗ |
10 |
if (anyValue.hasValue()) |
302 |
✓✓✗✗ |
9 |
return anyValue; |
303 |
} |
||
304 |
} |
||
305 |
|||
306 |
✓✗✓✗ ✓✗✓✗ ✗✗✗✗ ✗✗✗✗ |
36 |
throw CppRuntimeException("ZserioTreeCreator: Cannot create bitmask '") << typeInfo.getSchemaName() << |
307 |
✓✗✓✗ ✗✗✗✗ |
36 |
"' from string value '" << stringValue << "'!"; |
308 |
} |
||
309 |
|||
310 |
template <typename ALLOC> |
||
311 |
2 |
AnyHolder<ALLOC> makeAnyBitmaskValue(const string<ALLOC>& stringValue, const IBasicTypeInfo<ALLOC>& typeInfo, |
|
312 |
const ALLOC& allocator) |
||
313 |
{ |
||
314 |
✓✗ | 2 |
return makeAnyBitmaskValue(StringView(stringValue), typeInfo, allocator); |
315 |
} |
||
316 |
|||
317 |
template <typename ALLOC> |
||
318 |
1 |
AnyHolder<ALLOC> makeAnyBitmaskValue(const char* stringValue, const IBasicTypeInfo<ALLOC>& typeInfo, |
|
319 |
const ALLOC& allocator) |
||
320 |
{ |
||
321 |
✓✗ | 1 |
return makeAnyBitmaskValue(StringView(stringValue), typeInfo, allocator); |
322 |
} |
||
323 |
|||
324 |
template <typename T, typename ALLOC, |
||
325 |
typename std::enable_if<is_bitmask<T>::value, int>::type = 0> |
||
326 |
3 |
AnyHolder<ALLOC> makeAnyBitmaskValue(T bitmaskValue, const IBasicTypeInfo<ALLOC>&, const ALLOC& allocator) |
|
327 |
{ |
||
328 |
3 |
return AnyHolder<ALLOC>(bitmaskValue, allocator); |
|
329 |
} |
||
330 |
|||
331 |
template <typename T, typename ALLOC, |
||
332 |
typename std::enable_if<!is_bitmask<T>::value, int>::type = 0> |
||
333 |
7 |
AnyHolder<ALLOC> makeAnyBitmaskValue(T bitmaskRawValue, const IBasicTypeInfo<ALLOC>& typeInfo, |
|
334 |
const ALLOC& allocator) |
||
335 |
{ |
||
336 |
7 |
return makeAnyValue(typeInfo.getUnderlyingType(), bitmaskRawValue, allocator); |
|
337 |
} |
||
338 |
|||
339 |
template <typename T, typename ALLOC> |
||
340 |
295 |
AnyHolder<ALLOC> makeAnyValue(const IBasicTypeInfo<ALLOC>& typeInfo, T&& value, const ALLOC& allocator) |
|
341 |
{ |
||
342 |
✗✓✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✓✗ ✓✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✓✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✓✗✗✗ ✗✗✗✓ ✗✗✗✗ ✗✗✗✓ ✓✓✗✗ ✗✗✓✗ ✗✗✗✗ ✗✗✗✓ ✗✗✗✓ ✗✓✗✓ ✗✗✗✗ ✗✗✓✓ ✓✗✗✗ ✗✗✓✗ ✗✗✗✗ ✗✓✗✗ ✓✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✓✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✓✗✗ ✗✓✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✓✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✓✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✓ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✓✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✓✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✓✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✓✓ ✓✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✓✓✓ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✓✓✓✗ ✗✗✗✓ ✗✗✗✗ ✗✗✗✓ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✓✓✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✓✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✓✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✓ ✓✓✓✓ ✓✓✓✓ ✓✓✓✗ ✗✓✓✓ ✓✓✓✓ ✓✓✓✓ ✓✗✗✗ ✗✓✓✓ ✓✓✓✓ ✓✓✓✓ ✓✗✗✗ ✓✓✓✓ ✓✓✓✓ ✓✓✓✓ ✓✓✓✓ ✓✓✓✓ ✓✓✓✓ ✓✓✓✗ ✗✗ |
295 |
switch (typeInfo.getCppType()) |
343 |
{ |
||
344 |
case CppType::BOOL: |
||
345 |
7 |
return makeAnyBoolValue<bool>(std::forward<T>(value), allocator); |
|
346 |
case CppType::UINT8: |
||
347 |
37 |
return makeAnyIntegralValue<uint8_t>(std::forward<T>(value), allocator); |
|
348 |
case CppType::UINT16: |
||
349 |
7 |
return makeAnyIntegralValue<uint16_t>(std::forward<T>(value), allocator); |
|
350 |
case CppType::UINT32: |
||
351 |
34 |
return makeAnyIntegralValue<uint32_t>(std::forward<T>(value), allocator); |
|
352 |
case CppType::UINT64: |
||
353 |
6 |
return makeAnyIntegralValue<uint64_t>(std::forward<T>(value), allocator); |
|
354 |
case CppType::INT8: |
||
355 |
19 |
return makeAnyIntegralValue<int8_t>(std::forward<T>(value), allocator); |
|
356 |
case CppType::INT16: |
||
357 |
7 |
return makeAnyIntegralValue<int16_t>(std::forward<T>(value), allocator); |
|
358 |
case CppType::INT32: |
||
359 |
7 |
return makeAnyIntegralValue<int32_t>(std::forward<T>(value), allocator); |
|
360 |
case CppType::INT64: |
||
361 |
6 |
return makeAnyIntegralValue<int64_t>(std::forward<T>(value), allocator); |
|
362 |
case CppType::FLOAT: |
||
363 |
6 |
return makeAnyFloatingValue<float>(std::forward<T>(value), allocator); |
|
364 |
case CppType::DOUBLE: |
||
365 |
6 |
return makeAnyFloatingValue<double>(std::forward<T>(value), allocator); |
|
366 |
case CppType::STRING: |
||
367 |
71 |
return makeAnyStringValue(std::forward<T>(value), allocator); |
|
368 |
case CppType::ENUM: |
||
369 |
✗✗✗✗ ✗✗✗✗ |
35 |
return makeAnyEnumValue(std::forward<T>(value), typeInfo, allocator); |
370 |
case CppType::BITMASK: |
||
371 |
✗✗✗✗ ✗✗✗✗ |
42 |
return makeAnyBitmaskValue(std::forward<T>(value), typeInfo, allocator); |
372 |
default: |
||
373 |
5 |
return AnyHolder<ALLOC>(std::forward<T>(value), allocator); |
|
374 |
} |
||
375 |
} |
||
376 |
|||
377 |
// overload for values which are already in AnyHolder |
||
378 |
template <typename ALLOC> |
||
379 |
17 |
AnyHolder<ALLOC> makeAnyValue(const IBasicTypeInfo<ALLOC>&, AnyHolder<ALLOC>&& anyValue, const ALLOC&) |
|
380 |
{ |
||
381 |
17 |
return std::move(anyValue); |
|
382 |
} |
||
383 |
|||
384 |
enum class CreatorState : uint8_t |
||
385 |
{ |
||
386 |
BEFORE_ROOT, |
||
387 |
IN_COMPOUND, |
||
388 |
IN_ARRAY |
||
389 |
}; |
||
390 |
|||
391 |
} // namespace detail |
||
392 |
|||
393 |
/** |
||
394 |
* Allows to append detail::CreatorState to CppRuntimeException. |
||
395 |
* |
||
396 |
* \param exception Exception to modify. |
||
397 |
* \param state Creator state to append. |
||
398 |
* |
||
399 |
* \return Reference to the exception to allow operator chaining. |
||
400 |
*/ |
||
401 |
CppRuntimeException& operator<<(CppRuntimeException& exception, detail::CreatorState state); |
||
402 |
|||
403 |
/** |
||
404 |
* Allows to build zserio object tree defined by the given type info. |
||
405 |
*/ |
||
406 |
template <typename ALLOC> |
||
407 |
235 |
class BasicZserioTreeCreator : AllocatorHolder<ALLOC> |
|
408 |
{ |
||
409 |
public: |
||
410 |
/** |
||
411 |
* Constructor. |
||
412 |
* |
||
413 |
* \param typeInfo Type info defining the tree. |
||
414 |
*/ |
||
415 |
explicit BasicZserioTreeCreator(const IBasicTypeInfo<ALLOC>& typeInfo, const ALLOC& allocator = ALLOC()); |
||
416 |
|||
417 |
/** |
||
418 |
* Creates the top level compound element and move to state of building its children. |
||
419 |
*/ |
||
420 |
void beginRoot(); |
||
421 |
|||
422 |
/** |
||
423 |
* Finishes building and returns the created tree. |
||
424 |
* |
||
425 |
* \return Zserio object tree. |
||
426 |
* |
||
427 |
* \throw CppRuntimeException When the creator is not in state of building the root object. |
||
428 |
*/ |
||
429 |
IBasicReflectablePtr<ALLOC> endRoot(); |
||
430 |
|||
431 |
/** |
||
432 |
* Creates an array field within the current compound. |
||
433 |
* |
||
434 |
* \param name Name of the array field. |
||
435 |
* |
||
436 |
* \throw CppRuntimeException When the field doesn't exist or when the creator is not in a compound. |
||
437 |
*/ |
||
438 |
void beginArray(const string<ALLOC>& name); |
||
439 |
|||
440 |
/** |
||
441 |
* Finishes the array field. |
||
442 |
* |
||
443 |
* \throw CppRuntimeException When the creator is not in an array field. |
||
444 |
*/ |
||
445 |
void endArray(); |
||
446 |
|||
447 |
/** |
||
448 |
* Creates a compound field within the current compound. |
||
449 |
* |
||
450 |
* \param name Name of the compound field. |
||
451 |
* |
||
452 |
* \throw CppRuntimeException When the field doesn't exist or when the creator is not in a compound. |
||
453 |
*/ |
||
454 |
void beginCompound(const string<ALLOC>& name); |
||
455 |
|||
456 |
/** |
||
457 |
* Finishes the compound. |
||
458 |
* |
||
459 |
* \throw CppRuntimeException When the creator is not in a compound. |
||
460 |
*/ |
||
461 |
void endCompound(); |
||
462 |
|||
463 |
/** |
||
464 |
* Sets field value within the current compound. |
||
465 |
* |
||
466 |
* \param name Name of the field. |
||
467 |
* \param value Value to set. |
||
468 |
* |
||
469 |
* \throw CppRuntimeException When the field doesn't exist or when the creator is not in a compound. |
||
470 |
*/ |
||
471 |
template <typename T> |
||
472 |
void setValue(const string<ALLOC>& name, T&& value); |
||
473 |
|||
474 |
/** |
||
475 |
* Overload for setting of a null value. |
||
476 |
* |
||
477 |
* Note that this does nothing in C++ since non-optional fields are always present (default initialized). |
||
478 |
* |
||
479 |
* \param name Name of the field. |
||
480 |
* \param nullValue Null value. |
||
481 |
* |
||
482 |
* \throw CppRuntimeException When the field doesn't exist or when the creator is not in a compound. |
||
483 |
*/ |
||
484 |
void setValue(const string<ALLOC>& name, std::nullptr_t nullValue); |
||
485 |
|||
486 |
/** |
||
487 |
* Gets type info of the expected field. |
||
488 |
* |
||
489 |
* \param name Field name. |
||
490 |
* |
||
491 |
* \return Type info of the expected field. |
||
492 |
* |
||
493 |
* \throw CppRuntimeException When the creator is not in a compound. |
||
494 |
*/ |
||
495 |
const IBasicTypeInfo<ALLOC>& getFieldType(const string<ALLOC>& name) const; |
||
496 |
|||
497 |
/** |
||
498 |
* Creates compound array element within the current array. |
||
499 |
* |
||
500 |
* \throw CppRuntimeException When the creator is not in an array of compounds. |
||
501 |
*/ |
||
502 |
void beginCompoundElement(); |
||
503 |
|||
504 |
/** |
||
505 |
* Finishes the compound element. |
||
506 |
* |
||
507 |
* \throw CppRuntimeException When the creator is not in a compound element. |
||
508 |
*/ |
||
509 |
void endCompoundElement(); |
||
510 |
|||
511 |
/** |
||
512 |
* Adds the value to the array. |
||
513 |
* |
||
514 |
* \param value Value to add. |
||
515 |
* |
||
516 |
* \throw CppRuntimeException When the creator is not in an array of simple values. |
||
517 |
*/ |
||
518 |
template <typename T> |
||
519 |
void addValueElement(T&& value); |
||
520 |
|||
521 |
/** |
||
522 |
* Gets type info of the expected array element. |
||
523 |
* |
||
524 |
* \return Type info of the expected array element. |
||
525 |
* |
||
526 |
* \throw CppRuntimeException When the creator is not in an array. |
||
527 |
*/ |
||
528 |
const IBasicTypeInfo<ALLOC>& getElementType() const; |
||
529 |
|||
530 |
private: |
||
531 |
using AllocatorHolder<ALLOC>::get_allocator; |
||
532 |
|||
533 |
const IBasicTypeInfo<ALLOC>& getTypeInfo() const; |
||
534 |
const BasicFieldInfo<ALLOC>& findFieldInfo(const IBasicTypeInfo<ALLOC>& typeInfo, StringView name) const; |
||
535 |
|||
536 |
template <typename T> |
||
537 |
AnyHolder<ALLOC> makeAnyValue(const IBasicTypeInfo<ALLOC>& typeInfo, T&& value) const; |
||
538 |
|||
539 |
const IBasicTypeInfo<ALLOC>& m_typeInfo; |
||
540 |
vector<std::reference_wrapper<const BasicFieldInfo<ALLOC>>, ALLOC> m_fieldInfoStack; |
||
541 |
vector<IBasicReflectablePtr<ALLOC>, ALLOC> m_valueStack; |
||
542 |
detail::CreatorState m_state = detail::CreatorState::BEFORE_ROOT; |
||
543 |
}; |
||
544 |
|||
545 |
/** Typedef provided for convenience - using default std::allocator<uint8_t>. */ |
||
546 |
using ZserioTreeCreator = BasicZserioTreeCreator<std::allocator<uint8_t>>; |
||
547 |
|||
548 |
template <typename ALLOC> |
||
549 |
85 |
BasicZserioTreeCreator<ALLOC>::BasicZserioTreeCreator(const IBasicTypeInfo<ALLOC>& typeInfo, |
|
550 |
const ALLOC& allocator) : |
||
551 |
AllocatorHolder<ALLOC>(allocator), |
||
552 |
85 |
m_typeInfo(typeInfo), m_fieldInfoStack(allocator), m_valueStack(allocator) |
|
553 |
85 |
{} |
|
554 |
|||
555 |
template <typename ALLOC> |
||
556 |
87 |
void BasicZserioTreeCreator<ALLOC>::beginRoot() |
|
557 |
{ |
||
558 |
✓✓✗✓ |
87 |
if (m_state != detail::CreatorState::BEFORE_ROOT) |
559 |
✓✗✓✗ ✓✗✗✗ ✗✗✗✗ |
5 |
throw CppRuntimeException("ZserioTreeCreator: Cannot begin root in state '") << m_state << "'!"; |
560 |
|||
561 |
✓✗✓✗ ✓✗✓✗ |
82 |
m_valueStack.push_back(m_typeInfo.createInstance(get_allocator())); |
562 |
82 |
m_state = detail::CreatorState::IN_COMPOUND; |
|
563 |
82 |
} |
|
564 |
|||
565 |
template <typename ALLOC> |
||
566 |
54 |
IBasicReflectablePtr<ALLOC> BasicZserioTreeCreator<ALLOC>::endRoot() |
|
567 |
{ |
||
568 |
✓✓✓✓ ✓✓✓✗ ✗✓✗✓ |
54 |
if (m_state != detail::CreatorState::IN_COMPOUND || m_valueStack.size() != 1) |
569 |
✓✗✓✗ ✓✗✗✗ ✗✗✗✗ |
5 |
throw CppRuntimeException("ZserioTreeCreator: Cannot end root in state '") << m_state << "'!"; |
570 |
|||
571 |
49 |
m_state = detail::CreatorState::BEFORE_ROOT; |
|
572 |
49 |
auto value = m_valueStack.back(); |
|
573 |
49 |
m_valueStack.pop_back(); |
|
574 |
49 |
return value; |
|
575 |
} |
||
576 |
|||
577 |
template <typename ALLOC> |
||
578 |
23 |
void BasicZserioTreeCreator<ALLOC>::beginArray(const string<ALLOC>& name) |
|
579 |
{ |
||
580 |
✓✓✗✗ |
23 |
if (m_state != detail::CreatorState::IN_COMPOUND) |
581 |
✓✗✓✗ ✓✗✗✗ ✗✗✗✗ |
3 |
throw CppRuntimeException("ZserioTreeCreator: Cannot begin array in state '") << m_state << "'!"; |
582 |
|||
583 |
20 |
const auto& parentTypeInfo = getTypeInfo(); |
|
584 |
✓✓✗✗ |
23 |
const auto& fieldInfo = findFieldInfo(parentTypeInfo, name); |
585 |
✓✓✗✗ |
17 |
if (!fieldInfo.isArray) |
586 |
{ |
||
587 |
✓✗✓✗ ✓✗✗✗ ✗✗✗✗ |
4 |
throw CppRuntimeException("ZserioTreeCreator: Member '") << fieldInfo.schemaName << |
588 |
4 |
"' is not an array!"; |
|
589 |
} |
||
590 |
|||
591 |
✓✗✗✗ |
15 |
m_fieldInfoStack.push_back(fieldInfo); |
592 |
|||
593 |
// note that we cannot just call getField() in case that the array is not optional like we do it in |
||
594 |
// setValue() and beginCompound() methods because in case of arrays we would join multiple arrays together |
||
595 |
// when this method is called multiple times with the same name - thus we will just create a new array |
||
596 |
// |
||
597 |
// moreover we need to properly initialize arrays of dynamic bit fields |
||
598 |
// see https://github.com/ndsev/zserio/issues/414 |
||
599 |
✓✗✓✗ ✗✗✗✗ |
15 |
m_valueStack.push_back(m_valueStack.back()->createField(name)); |
600 |
|||
601 |
15 |
m_state = detail::CreatorState::IN_ARRAY; |
|
602 |
15 |
} |
|
603 |
|||
604 |
template <typename ALLOC> |
||
605 |
16 |
void BasicZserioTreeCreator<ALLOC>::endArray() |
|
606 |
{ |
||
607 |
✓✓✗✗ |
16 |
if (m_state != detail::CreatorState::IN_ARRAY) |
608 |
✓✗✓✗ ✓✗✗✗ ✗✗✗✗ |
4 |
throw CppRuntimeException("ZserioTreeCreator: Cannot end array in state '") << m_state << "'!"; |
609 |
|||
610 |
12 |
m_fieldInfoStack.pop_back(); |
|
611 |
12 |
m_valueStack.pop_back(); |
|
612 |
12 |
m_state = detail::CreatorState::IN_COMPOUND; |
|
613 |
12 |
} |
|
614 |
|||
615 |
template <typename ALLOC> |
||
616 |
44 |
void BasicZserioTreeCreator<ALLOC>::beginCompound(const string<ALLOC>& name) |
|
617 |
{ |
||
618 |
✓✓✗✗ |
44 |
if (m_state != detail::CreatorState::IN_COMPOUND) |
619 |
✓✗✓✗ ✓✗✗✗ ✗✗✗✗ |
3 |
throw CppRuntimeException("ZserioTreeCreator: Cannot begin compound in state '") << m_state << "'!"; |
620 |
|||
621 |
41 |
const auto& parentTypeInfo = getTypeInfo(); |
|
622 |
✓✓✗✗ |
44 |
const auto& fieldInfo = findFieldInfo(parentTypeInfo, name); |
623 |
✓✓✗✗ |
38 |
if (fieldInfo.isArray) |
624 |
✓✗✓✗ ✓✗✗✗ ✗✗✗✗ |
1 |
throw CppRuntimeException("ZserioTreeCreator: Member '") << fieldInfo.schemaName << "' is an array!"; |
625 |
|||
626 |
✓✓✗✗ |
37 |
if (!TypeInfoUtil::isCompound(fieldInfo.typeInfo.getCppType())) |
627 |
{ |
||
628 |
✓✗✓✗ ✓✗✗✗ ✗✗✗✗ |
2 |
throw CppRuntimeException("ZserioTreeCreator: Member '") << fieldInfo.schemaName << |
629 |
2 |
"' is not a compound!"; |
|
630 |
} |
||
631 |
|||
632 |
✓✗✗✗ |
36 |
m_fieldInfoStack.push_back(fieldInfo); |
633 |
✓✗✓✓ ✓✓✗✗ ✗✗✗✗ |
36 |
if (TypeInfoUtil::hasChoice(parentTypeInfo.getCppType()) || fieldInfo.isOptional) |
634 |
{ |
||
635 |
// optional field, or field within choice or union -> create the new compound |
||
636 |
✓✗✓✗ ✗✗✗✗ |
1 |
m_valueStack.push_back(m_valueStack.back()->createField(name)); |
637 |
} |
||
638 |
else |
||
639 |
{ |
||
640 |
✓✗✓✗ ✗✗✗✗ |
35 |
m_valueStack.push_back(m_valueStack.back()->getField(name)); |
641 |
} |
||
642 |
|||
643 |
36 |
m_state = detail::CreatorState::IN_COMPOUND; |
|
644 |
36 |
} |
|
645 |
|||
646 |
template <typename ALLOC> |
||
647 |
17 |
void BasicZserioTreeCreator<ALLOC>::endCompound() |
|
648 |
{ |
||
649 |
✓✓✓✓ ✓✓✗✗ ✗✗✗✗ |
17 |
if (m_state != detail::CreatorState::IN_COMPOUND || m_fieldInfoStack.empty()) |
650 |
{ |
||
651 |
✓✗✓✗ ✓✗✗✗ ✗✗✗✗ |
12 |
throw CppRuntimeException("ZserioTreeCreator: Cannot end compound in state '") << m_state << |
652 |
✓✓✓✗ ✗✗✗✗ |
12 |
"'" << (m_fieldInfoStack.empty() ? ", expecting endRoot!" : "!'"); |
653 |
} |
||
654 |
|||
655 |
13 |
const BasicFieldInfo<ALLOC>& fieldInfo = m_fieldInfoStack.back(); |
|
656 |
✓✓✗✗ |
13 |
if (fieldInfo.isArray) |
657 |
✓✗✗✗ |
1 |
throw CppRuntimeException("ZserioTreeCreator: Cannot end compound, it's an array element!"); |
658 |
|||
659 |
12 |
m_fieldInfoStack.pop_back(); |
|
660 |
12 |
m_valueStack.pop_back(); |
|
661 |
12 |
} |
|
662 |
|||
663 |
template <typename ALLOC> |
||
664 |
template <typename T> |
||
665 |
136 |
void BasicZserioTreeCreator<ALLOC>::setValue(const string<ALLOC>& name, T&& value) |
|
666 |
{ |
||
667 |
✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✓✓ |
136 |
if (m_state != detail::CreatorState::IN_COMPOUND) |
668 |
✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✓✗ ✓✗✓✗ |
3 |
throw CppRuntimeException("ZserioTreeCreator: Cannot set value in state '") << m_state << "'!"; |
669 |
|||
670 |
✓✗✓✗ ✓✓✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✓✓✓ |
137 |
const BasicFieldInfo<ALLOC>& fieldInfo = findFieldInfo(getTypeInfo(), name); |
671 |
✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✓✓ |
129 |
if (fieldInfo.isArray) |
672 |
{ |
||
673 |
✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✓✗✓✗ |
2 |
throw CppRuntimeException("ZserioTreeCreator: Expecting array in member '") << |
674 |
✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✓✗ |
2 |
fieldInfo.schemaName << "'!"; |
675 |
} |
||
676 |
|||
677 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ |
256 |
m_valueStack.back()->setField(fieldInfo.schemaName, |
678 |
128 |
makeAnyValue(fieldInfo.typeInfo, std::forward<T>(value))); |
|
679 |
113 |
} |
|
680 |
|||
681 |
template <typename ALLOC> |
||
682 |
3 |
void BasicZserioTreeCreator<ALLOC>::setValue(const string<ALLOC>& name, std::nullptr_t nullValue) |
|
683 |
{ |
||
684 |
✓✓✗✗ |
3 |
if (m_state != detail::CreatorState::IN_COMPOUND) |
685 |
{ |
||
686 |
✓✗✓✗ ✓✗✗✗ ✗✗✗✗ |
2 |
throw CppRuntimeException("ZserioTreeCreator: Cannot set value (null) in state '") << m_state << |
687 |
2 |
"'!"; |
|
688 |
} |
||
689 |
|||
690 |
✓✗✗✗ |
2 |
const BasicFieldInfo<ALLOC>& fieldInfo = findFieldInfo(getTypeInfo(), name); |
691 |
✓✓✗✗ |
2 |
if (fieldInfo.isOptional) |
692 |
{ |
||
693 |
// reset an optional field |
||
694 |
✓✗✓✗ ✗✗✗✗ |
1 |
m_valueStack.back()->setField(fieldInfo.schemaName, AnyHolder<ALLOC>(nullValue, get_allocator())); |
695 |
} |
||
696 |
else |
||
697 |
{ |
||
698 |
// reset non-optional field with default-constructed value |
||
699 |
// (classes generated in C++ do not support null values) |
||
700 |
1 |
m_valueStack.back()->createField(fieldInfo.schemaName); |
|
701 |
} |
||
702 |
2 |
} |
|
703 |
|||
704 |
template <typename ALLOC> |
||
705 |
59 |
const IBasicTypeInfo<ALLOC>& BasicZserioTreeCreator<ALLOC>::getFieldType(const string<ALLOC>& name) const |
|
706 |
{ |
||
707 |
✓✓✗✗ |
59 |
if (m_state != detail::CreatorState::IN_COMPOUND) |
708 |
✓✗✓✗ ✓✗✗✗ ✗✗✗✗ |
1 |
throw CppRuntimeException("ZserioTreeCreator: Cannot get field type in state '") << m_state << "'!"; |
709 |
|||
710 |
✓✗✗✗ |
58 |
return findFieldInfo(getTypeInfo(), name).typeInfo; |
711 |
} |
||
712 |
|||
713 |
template <typename ALLOC> |
||
714 |
9 |
void BasicZserioTreeCreator<ALLOC>::beginCompoundElement() |
|
715 |
{ |
||
716 |
✓✓✗✗ |
9 |
if (m_state != detail::CreatorState::IN_ARRAY) |
717 |
{ |
||
718 |
✓✗✓✗ ✗✗✗✗ |
8 |
throw CppRuntimeException("ZserioTreeCreator: Cannot begin compound element in state '") << |
719 |
✓✗✗✗ |
8 |
m_state << "'!"; |
720 |
} |
||
721 |
|||
722 |
5 |
const BasicFieldInfo<ALLOC>& fieldInfo = m_fieldInfoStack.back(); |
|
723 |
✓✗✓✗ ✓✓✗✗ ✗✗✗✗ |
5 |
if (!TypeInfoUtil::isCompound(fieldInfo.typeInfo.getCppType())) |
724 |
{ |
||
725 |
✓✗✓✗ ✓✗✗✗ ✗✗✗✗ |
2 |
throw CppRuntimeException("ZserioTreeCreator: Member '") << fieldInfo.schemaName << |
726 |
2 |
"' is not a compound!"; |
|
727 |
} |
||
728 |
|||
729 |
8 |
auto compoundArray = m_valueStack.back(); |
|
730 |
✓✗✓✗ ✗✗✗✗ |
4 |
compoundArray->resize(compoundArray->size() + 1); |
731 |
✓✗✓✗ ✓✗✗✗ ✗✗✗✗ |
4 |
m_valueStack.push_back(compoundArray->at(compoundArray->size() - 1)); |
732 |
4 |
m_state = detail::CreatorState::IN_COMPOUND; |
|
733 |
4 |
} |
|
734 |
|||
735 |
template <typename ALLOC> |
||
736 |
8 |
void BasicZserioTreeCreator<ALLOC>::endCompoundElement() |
|
737 |
{ |
||
738 |
✓✓✓✓ ✓✓✗✗ ✗✗✗✗ |
8 |
if (m_state != detail::CreatorState::IN_COMPOUND || m_fieldInfoStack.empty()) |
739 |
{ |
||
740 |
✓✗✓✗ ✗✗✗✗ |
12 |
throw CppRuntimeException("ZserioTreeCreator: Cannot end compound element in state '") << |
741 |
✓✓✓✗ ✗✗✗✗ |
12 |
m_state << (m_fieldInfoStack.empty() ? ", expecting endRoot!" : "'!"); |
742 |
} |
||
743 |
|||
744 |
4 |
const BasicFieldInfo<ALLOC>& fieldInfo = m_fieldInfoStack.back(); |
|
745 |
✓✓✗✗ |
4 |
if (!fieldInfo.isArray) |
746 |
✓✗✗✗ |
1 |
throw CppRuntimeException("ZserioTreeCreator: Cannot end compound element, not in array!"); |
747 |
|||
748 |
3 |
m_valueStack.pop_back(); |
|
749 |
3 |
m_state = detail::CreatorState::IN_ARRAY; |
|
750 |
3 |
} |
|
751 |
|||
752 |
template <typename ALLOC> |
||
753 |
template <typename T> |
||
754 |
24 |
void BasicZserioTreeCreator<ALLOC>::addValueElement(T&& value) |
|
755 |
{ |
||
756 |
✓✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ |
24 |
if (m_state != detail::CreatorState::IN_ARRAY) |
757 |
{ |
||
758 |
✓✗✓✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ |
8 |
throw CppRuntimeException("ZserioTreeCreator: Cannot add value element in state '") << |
759 |
✓✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ |
8 |
m_state << "'!"; |
760 |
} |
||
761 |
|||
762 |
20 |
const BasicFieldInfo<ALLOC>& fieldInfo = m_fieldInfoStack.back(); |
|
763 |
✓✓✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ |
21 |
m_valueStack.back()->append(makeAnyValue(fieldInfo.typeInfo, std::forward<T>(value))); |
764 |
18 |
} |
|
765 |
|||
766 |
template <typename ALLOC> |
||
767 |
7 |
const IBasicTypeInfo<ALLOC>& BasicZserioTreeCreator<ALLOC>::getElementType() const |
|
768 |
{ |
||
769 |
✓✓✗✗ |
7 |
if (m_state != detail::CreatorState::IN_ARRAY) |
770 |
{ |
||
771 |
✓✗✓✗ ✓✗✗✗ ✗✗✗✗ |
2 |
throw CppRuntimeException("ZserioTreeCreator: Cannot get element type in state '") << m_state << |
772 |
2 |
"'!"; |
|
773 |
} |
||
774 |
|||
775 |
6 |
return m_fieldInfoStack.back().get().typeInfo; |
|
776 |
} |
||
777 |
|||
778 |
template <typename ALLOC> |
||
779 |
254 |
const IBasicTypeInfo<ALLOC>& BasicZserioTreeCreator<ALLOC>::getTypeInfo() const |
|
780 |
{ |
||
781 |
✓✓✓✗ |
254 |
return m_fieldInfoStack.empty() ? m_typeInfo : m_fieldInfoStack.back().get().typeInfo; |
782 |
} |
||
783 |
|||
784 |
template <typename ALLOC> |
||
785 |
254 |
const BasicFieldInfo<ALLOC>& BasicZserioTreeCreator<ALLOC>::findFieldInfo( |
|
786 |
const IBasicTypeInfo<ALLOC>& typeInfo, StringView name) const |
||
787 |
{ |
||
788 |
✓✗✓✗ |
254 |
Span<const BasicFieldInfo<ALLOC>> fields = typeInfo.getFields(); |
789 |
254 |
auto found_it = std::find_if(fields.begin(), fields.end(), |
|
790 |
✓✗✓✗ |
1016 |
[name](const BasicFieldInfo<ALLOC>& field){ return field.schemaName == name; }); |
791 |
✓✓✗✓ |
254 |
if (found_it == fields.end()) |
792 |
{ |
||
793 |
✓✗✓✗ ✓✗✓✗ ✓✗✗✗ ✗✗✗✗ ✗✗✗✗ |
20 |
throw CppRuntimeException("ZserioTreeCreator: Member '") << name << "' not found in '" << |
794 |
✓✗✗✗ |
20 |
typeInfo.getSchemaName() << "'!"; |
795 |
} |
||
796 |
|||
797 |
244 |
return *found_it; |
|
798 |
} |
||
799 |
|||
800 |
template <typename ALLOC> |
||
801 |
template <typename T> |
||
802 |
148 |
AnyHolder<ALLOC> BasicZserioTreeCreator<ALLOC>::makeAnyValue( |
|
803 |
const IBasicTypeInfo<ALLOC>& typeInfo, T&& value) const |
||
804 |
{ |
||
805 |
✓✓✓✓ ✓✓✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✗✗ ✓✗✗✗ ✓✗✗✗ ✓✗✗✓ ✗✓✓✓ ✓ |
148 |
return detail::makeAnyValue(typeInfo, std::forward<T>(value), get_allocator()); |
806 |
} |
||
807 |
|||
808 |
} // namespace zserio |
||
809 |
|||
810 |
#endif // ZSERIO_ZSERIO_TREE_CREATOR_H_INC |
Generated by: GCOVR (Version 4.2) |