1 #ifndef ZSERIO_ZSERIO_TREE_CREATOR_H_INC 2 #define ZSERIO_ZSERIO_TREE_CREATOR_H_INC 25 template <
typename T,
typename ALLOC>
26 AnyHolder<ALLOC> makeAnyValue(
const IBasicTypeInfo<ALLOC>& typeInfo, T&& value,
const ALLOC& allocator);
28 template <
typename T,
typename U,
29 typename std::enable_if<std::is_unsigned<typename std::decay<U>::type>::value,
int>::type = 0>
30 bool checkArithmeticValueRanges(U value)
33 return (value <= static_cast<U>(std::numeric_limits<T>::max()));
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 bool checkArithmeticValueRanges(U value)
42 return (static_cast<int64_t>(value) >= static_cast<int64_t>(std::numeric_limits<T>::min()) &&
43 static_cast<int64_t>(value) <= static_cast<int64_t>(std::numeric_limits<T>::max()));
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 bool checkArithmeticValueRanges(U value)
52 return (value >= 0 && static_cast<uint64_t>(value) <= static_cast<uint64_t>(std::numeric_limits<T>::max()));
55 template <
typename T,
typename ALLOC>
56 AnyHolder<ALLOC> makeAnyBoolValue(
bool value,
const ALLOC& allocator)
58 return AnyHolder<ALLOC>(
static_cast<T
>(value), allocator);
61 template <
typename T,
typename U,
typename ALLOC>
62 AnyHolder<ALLOC> makeAnyBoolValue(
const U& value,
const ALLOC&)
64 throw CppRuntimeException(
"ZserioTreeCreator: Value '") << value <<
65 "' cannot be converted to bool value!";
68 template <
typename T,
typename ALLOC>
69 AnyHolder<ALLOC> makeAnyIntegralValue(
bool value,
const ALLOC&)
71 throw CppRuntimeException(
"ZserioTreeCreator: Bool value '") << value <<
72 "' cannot be converted to integral type!";
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 AnyHolder<ALLOC> makeAnyIntegralValue(U value,
const ALLOC& allocator)
80 if (!checkArithmeticValueRanges<T>(value))
82 throw CppRuntimeException(
"ZserioTreeCreator: Integral value '") << value <<
"' overflow (<" <<
83 std::numeric_limits<T>::min() <<
", " << std::numeric_limits<T>::max() <<
">)!";
86 return AnyHolder<ALLOC>(
static_cast<T
>(value), allocator);
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 AnyHolder<ALLOC> makeAnyIntegralValue(
const U& value,
const ALLOC&)
93 throw CppRuntimeException(
"ZserioTreeCreator: Value '") << value <<
94 "' cannot be converted to integral value!";
97 template <
typename T,
typename ALLOC>
98 AnyHolder<ALLOC> makeAnyFloatingValue(
bool value,
const ALLOC&)
100 throw CppRuntimeException(
"ZserioTreeCreator: Bool value '") << value <<
101 "' cannot be converted to floating type!";
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 AnyHolder<ALLOC> makeAnyFloatingValue(U value,
const ALLOC& allocator)
109 return AnyHolder<ALLOC>(
static_cast<T
>(value), allocator);
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 AnyHolder<ALLOC> makeAnyFloatingValue(
const U& value,
const ALLOC&)
116 throw CppRuntimeException(
"ZserioTreeCreator: Value '") << value <<
117 "' cannot be converted to floating value!";
120 template <
typename ALLOC>
121 AnyHolder<ALLOC> makeAnyStringValue(
const string<ALLOC>& value,
const ALLOC& allocator)
123 return AnyHolder<ALLOC>(value, allocator);
126 template <
typename ALLOC>
127 AnyHolder<ALLOC> makeAnyStringValue(string<ALLOC>&& value,
const ALLOC& allocator)
129 return AnyHolder<ALLOC>(std::move(value), allocator);
132 template <
typename ALLOC>
133 AnyHolder<ALLOC> makeAnyStringValue(
StringView value,
const ALLOC& allocator)
135 return AnyHolder<ALLOC>(
toString(value, allocator), allocator);
138 template <
typename ALLOC>
139 AnyHolder<ALLOC> makeAnyStringValue(
const char* value,
const ALLOC& allocator)
141 return makeAnyStringValue(
StringView(value), allocator);
144 template <
typename T,
typename ALLOC>
145 AnyHolder<ALLOC> makeAnyStringValue(
const T&,
const ALLOC&)
147 throw CppRuntimeException(
"ZserioTreeCreator: Trying to make any string value from unsupported type!");
150 template <
typename ALLOC>
151 AnyHolder<ALLOC> parseEnumStringValue(
StringView stringValue,
const IBasicTypeInfo<ALLOC>& typeInfo,
152 const ALLOC& allocator)
154 for (
const auto& itemInfo : typeInfo.getEnumItems())
156 if (itemInfo.schemaName == stringValue)
160 return makeAnyValue(typeInfo.getUnderlyingType(),
static_cast<int64_t
>(itemInfo.value),
165 return makeAnyValue(typeInfo.getUnderlyingType(), itemInfo.value, allocator);
170 return AnyHolder<ALLOC>(allocator);
173 template <
typename ALLOC>
174 AnyHolder<ALLOC> makeAnyEnumValue(
StringView stringValue,
const IBasicTypeInfo<ALLOC>& typeInfo,
175 const ALLOC& allocator)
177 if (!stringValue.empty())
179 const char firstChar = stringValue[0];
180 if ((firstChar >=
'A' && firstChar <=
'Z') || (firstChar >=
'a' && firstChar <=
'z') ||
183 AnyHolder<ALLOC> anyValue = parseEnumStringValue(stringValue, typeInfo, allocator);
184 if (anyValue.hasValue())
190 throw CppRuntimeException(
"ZserioTreeCreator: Cannot create enum '") << typeInfo.getSchemaName() <<
191 "' from string value '" << stringValue <<
"'!";
194 template <
typename ALLOC>
195 AnyHolder<ALLOC> makeAnyEnumValue(
const string<ALLOC>& stringValue,
const IBasicTypeInfo<ALLOC>& typeInfo,
196 const ALLOC& allocator)
198 return makeAnyEnumValue(
StringView(stringValue), typeInfo, allocator);
201 template <
typename ALLOC>
202 AnyHolder<ALLOC> makeAnyEnumValue(
const char* stringValue,
const IBasicTypeInfo<ALLOC>& typeInfo,
203 const ALLOC& allocator)
205 return makeAnyEnumValue(
StringView(stringValue), typeInfo, allocator);
208 template <
typename T,
typename ALLOC,
209 typename std::enable_if<std::is_enum<T>::value,
int>::type = 0>
210 AnyHolder<ALLOC> makeAnyEnumValue(T enumValue,
const IBasicTypeInfo<ALLOC>&,
const ALLOC& allocator)
212 return AnyHolder<ALLOC>(enumValue, allocator);
215 template <
typename T,
typename ALLOC,
216 typename std::enable_if<!std::is_enum<T>::value,
int>::type = 0>
217 AnyHolder<ALLOC> makeAnyEnumValue(T enumRawValue,
const IBasicTypeInfo<ALLOC>& typeInfo,
218 const ALLOC& allocator)
220 return makeAnyValue(typeInfo.getUnderlyingType(), enumRawValue, allocator);
223 template <
typename ALLOC>
224 AnyHolder<ALLOC> parseBitmaskStringValue(
StringView stringValue,
const IBasicTypeInfo<ALLOC>& typeInfo,
225 const ALLOC& allocator)
229 while (pos < stringValue.size())
232 const size_t available = stringValue.size() - pos;
233 for (
const auto& itemInfo : typeInfo.getBitmaskValues())
235 if (available >= itemInfo.schemaName.size() &&
236 stringValue.substr(pos, itemInfo.schemaName.size()) == itemInfo.schemaName)
238 const size_t newPos = pos + itemInfo.schemaName.size();
240 if (newPos == stringValue.size() || stringValue[newPos] ==
' ' || stringValue[newPos] ==
'|' )
242 value |= itemInfo.value;
243 if (newPos == stringValue.size())
244 return makeAnyValue(typeInfo.getUnderlyingType(), value, allocator);
246 pos += itemInfo.schemaName.size();
255 while (pos < stringValue.size() && stringValue[pos] ==
' ')
258 if (pos < stringValue.size() && stringValue[pos] ==
'|')
261 while (pos < stringValue.size() && stringValue[pos] ==
' ')
266 return AnyHolder<ALLOC>(allocator);
269 template <
typename ALLOC>
270 AnyHolder<ALLOC> parseBitmaskNumericStringValue(
const char* stringValue,
const IBasicTypeInfo<ALLOC>& typeInfo,
271 const ALLOC& allocator)
273 char *pEnd =
nullptr;
275 uint64_t value = std::strtoull(stringValue, &pEnd, 10);
277 return AnyHolder<ALLOC>(allocator);
278 return makeAnyValue(typeInfo.getUnderlyingType(), value, allocator);
281 template <
typename ALLOC>
282 AnyHolder<ALLOC> makeAnyBitmaskValue(
StringView stringValue,
const IBasicTypeInfo<ALLOC>& typeInfo,
283 const ALLOC& allocator)
285 if (!stringValue.empty())
287 const char firstChar = stringValue[0];
288 if ((firstChar >=
'A' && firstChar <=
'Z') || (firstChar >=
'a' && firstChar <=
'z') ||
291 AnyHolder<ALLOC> anyValue = parseBitmaskStringValue(stringValue, typeInfo, allocator);
292 if (anyValue.hasValue())
295 else if (firstChar >=
'0' && firstChar <=
'9')
298 const string<ALLOC> numericStringValue =
toString(stringValue, allocator);
299 AnyHolder<ALLOC> anyValue = parseBitmaskNumericStringValue(numericStringValue.c_str(), typeInfo,
301 if (anyValue.hasValue())
306 throw CppRuntimeException(
"ZserioTreeCreator: Cannot create bitmask '") << typeInfo.getSchemaName() <<
307 "' from string value '" << stringValue <<
"'!";
310 template <
typename ALLOC>
311 AnyHolder<ALLOC> makeAnyBitmaskValue(
const string<ALLOC>& stringValue,
const IBasicTypeInfo<ALLOC>& typeInfo,
312 const ALLOC& allocator)
314 return makeAnyBitmaskValue(
StringView(stringValue), typeInfo, allocator);
317 template <
typename ALLOC>
318 AnyHolder<ALLOC> makeAnyBitmaskValue(
const char* stringValue,
const IBasicTypeInfo<ALLOC>& typeInfo,
319 const ALLOC& allocator)
321 return makeAnyBitmaskValue(
StringView(stringValue), typeInfo, allocator);
324 template <
typename T,
typename ALLOC,
325 typename std::enable_if<is_bitmask<T>::value,
int>::type = 0>
326 AnyHolder<ALLOC> makeAnyBitmaskValue(T bitmaskValue,
const IBasicTypeInfo<ALLOC>&,
const ALLOC& allocator)
328 return AnyHolder<ALLOC>(bitmaskValue, allocator);
331 template <
typename T,
typename ALLOC,
332 typename std::enable_if<!is_bitmask<T>::value,
int>::type = 0>
333 AnyHolder<ALLOC> makeAnyBitmaskValue(T bitmaskRawValue,
const IBasicTypeInfo<ALLOC>& typeInfo,
334 const ALLOC& allocator)
336 return makeAnyValue(typeInfo.getUnderlyingType(), bitmaskRawValue, allocator);
339 template <
typename T,
typename ALLOC>
340 AnyHolder<ALLOC> makeAnyValue(
const IBasicTypeInfo<ALLOC>& typeInfo, T&& value,
const ALLOC& allocator)
342 switch (typeInfo.getCppType())
345 return makeAnyBoolValue<bool>(std::forward<T>(value), allocator);
347 return makeAnyIntegralValue<uint8_t>(std::forward<T>(value), allocator);
349 return makeAnyIntegralValue<uint16_t>(std::forward<T>(value), allocator);
351 return makeAnyIntegralValue<uint32_t>(std::forward<T>(value), allocator);
353 return makeAnyIntegralValue<uint64_t>(std::forward<T>(value), allocator);
355 return makeAnyIntegralValue<int8_t>(std::forward<T>(value), allocator);
357 return makeAnyIntegralValue<int16_t>(std::forward<T>(value), allocator);
359 return makeAnyIntegralValue<int32_t>(std::forward<T>(value), allocator);
361 return makeAnyIntegralValue<int64_t>(std::forward<T>(value), allocator);
363 return makeAnyFloatingValue<float>(std::forward<T>(value), allocator);
365 return makeAnyFloatingValue<double>(std::forward<T>(value), allocator);
367 return makeAnyStringValue(std::forward<T>(value), allocator);
369 return makeAnyEnumValue(std::forward<T>(value), typeInfo, allocator);
371 return makeAnyBitmaskValue(std::forward<T>(value), typeInfo, allocator);
373 return AnyHolder<ALLOC>(std::forward<T>(value), allocator);
378 template <
typename ALLOC>
379 AnyHolder<ALLOC> makeAnyValue(
const IBasicTypeInfo<ALLOC>&, AnyHolder<ALLOC>&& anyValue,
const ALLOC&)
381 return std::move(anyValue);
384 enum class CreatorState : uint8_t
401 CppRuntimeException&
operator<<(CppRuntimeException& exception, detail::CreatorState state);
406 template <
typename ALLOC>
471 template <
typename T>
484 void setValue(
const string<ALLOC>& name, std::nullptr_t nullValue);
502 void beginCompoundElement();
509 void endCompoundElement();
518 template <
typename T>
519 void addValueElement(T&& value);
536 template <
typename T>
542 detail::CreatorState m_state = detail::CreatorState::BEFORE_ROOT;
548 template <
typename ALLOC>
550 const ALLOC& allocator) :
552 m_typeInfo(typeInfo), m_fieldInfoStack(allocator), m_valueStack(allocator)
555 template <
typename ALLOC>
558 if (m_state != detail::CreatorState::BEFORE_ROOT)
559 throw CppRuntimeException(
"ZserioTreeCreator: Cannot begin root in state '") << m_state <<
"'!";
561 m_valueStack.push_back(m_typeInfo.createInstance(
get_allocator()));
562 m_state = detail::CreatorState::IN_COMPOUND;
565 template <
typename ALLOC>
568 if (m_state != detail::CreatorState::IN_COMPOUND || m_valueStack.size() != 1)
569 throw CppRuntimeException(
"ZserioTreeCreator: Cannot end root in state '") << m_state <<
"'!";
571 m_state = detail::CreatorState::BEFORE_ROOT;
572 auto value = m_valueStack.back();
573 m_valueStack.pop_back();
577 template <
typename ALLOC>
580 if (m_state != detail::CreatorState::IN_COMPOUND)
581 throw CppRuntimeException(
"ZserioTreeCreator: Cannot begin array in state '") << m_state <<
"'!";
583 const auto& parentTypeInfo = getTypeInfo();
584 const auto& fieldInfo = findFieldInfo(parentTypeInfo, name);
585 if (!fieldInfo.isArray)
588 "' is not an array!";
591 m_fieldInfoStack.push_back(fieldInfo);
599 m_valueStack.push_back(m_valueStack.back()->createField(name));
601 m_state = detail::CreatorState::IN_ARRAY;
604 template <
typename ALLOC>
607 if (m_state != detail::CreatorState::IN_ARRAY)
608 throw CppRuntimeException(
"ZserioTreeCreator: Cannot end array in state '") << m_state <<
"'!";
610 m_fieldInfoStack.pop_back();
611 m_valueStack.pop_back();
612 m_state = detail::CreatorState::IN_COMPOUND;
615 template <
typename ALLOC>
618 if (m_state != detail::CreatorState::IN_COMPOUND)
619 throw CppRuntimeException(
"ZserioTreeCreator: Cannot begin compound in state '") << m_state <<
"'!";
621 const auto& parentTypeInfo = getTypeInfo();
622 const auto& fieldInfo = findFieldInfo(parentTypeInfo, name);
623 if (fieldInfo.isArray)
624 throw CppRuntimeException(
"ZserioTreeCreator: Member '") << fieldInfo.schemaName <<
"' is an array!";
629 "' is not a compound!";
632 m_fieldInfoStack.push_back(fieldInfo);
636 m_valueStack.push_back(m_valueStack.back()->createField(name));
640 m_valueStack.push_back(m_valueStack.back()->getField(name));
643 m_state = detail::CreatorState::IN_COMPOUND;
646 template <
typename ALLOC>
649 if (m_state != detail::CreatorState::IN_COMPOUND || m_fieldInfoStack.empty())
651 throw CppRuntimeException(
"ZserioTreeCreator: Cannot end compound in state '") << m_state <<
652 "'" << (m_fieldInfoStack.empty() ?
", expecting endRoot!" :
"!'");
656 if (fieldInfo.isArray)
657 throw CppRuntimeException(
"ZserioTreeCreator: Cannot end compound, it's an array element!");
659 m_fieldInfoStack.pop_back();
660 m_valueStack.pop_back();
663 template <
typename ALLOC>
664 template <
typename T>
667 if (m_state != detail::CreatorState::IN_COMPOUND)
668 throw CppRuntimeException(
"ZserioTreeCreator: Cannot set value in state '") << m_state <<
"'!";
677 m_valueStack.back()->setField(fieldInfo.
schemaName,
678 makeAnyValue(fieldInfo.
typeInfo, std::forward<T>(value)));
681 template <
typename ALLOC>
684 if (m_state != detail::CreatorState::IN_COMPOUND)
686 throw CppRuntimeException(
"ZserioTreeCreator: Cannot set value (null) in state '") << m_state <<
700 m_valueStack.back()->createField(fieldInfo.
schemaName);
704 template <
typename ALLOC>
707 if (m_state != detail::CreatorState::IN_COMPOUND)
708 throw CppRuntimeException(
"ZserioTreeCreator: Cannot get field type in state '") << m_state <<
"'!";
710 return findFieldInfo(getTypeInfo(), name).typeInfo;
713 template <
typename ALLOC>
716 if (m_state != detail::CreatorState::IN_ARRAY)
718 throw CppRuntimeException(
"ZserioTreeCreator: Cannot begin compound element in state '") <<
726 "' is not a compound!";
729 auto compoundArray = m_valueStack.back();
730 compoundArray->resize(compoundArray->size() + 1);
731 m_valueStack.push_back(compoundArray->at(compoundArray->size() - 1));
732 m_state = detail::CreatorState::IN_COMPOUND;
735 template <
typename ALLOC>
738 if (m_state != detail::CreatorState::IN_COMPOUND || m_fieldInfoStack.empty())
741 m_state << (m_fieldInfoStack.empty() ?
", expecting endRoot!" :
"'!");
745 if (!fieldInfo.isArray)
746 throw CppRuntimeException(
"ZserioTreeCreator: Cannot end compound element, not in array!");
748 m_valueStack.pop_back();
749 m_state = detail::CreatorState::IN_ARRAY;
752 template <
typename ALLOC>
753 template <
typename T>
756 if (m_state != detail::CreatorState::IN_ARRAY)
763 m_valueStack.back()->append(makeAnyValue(fieldInfo.
typeInfo, std::forward<T>(value)));
766 template <
typename ALLOC>
769 if (m_state != detail::CreatorState::IN_ARRAY)
771 throw CppRuntimeException(
"ZserioTreeCreator: Cannot get element type in state '") << m_state <<
775 return m_fieldInfoStack.back().get().typeInfo;
778 template <
typename ALLOC>
781 return m_fieldInfoStack.empty() ? m_typeInfo : m_fieldInfoStack.back().get().typeInfo;
784 template <
typename ALLOC>
789 auto found_it = std::find_if(fields.
begin(), fields.
end(),
791 if (found_it == fields.
end())
800 template <
typename ALLOC>
801 template <
typename T>
805 return detail::makeAnyValue(typeInfo, std::forward<T>(value),
get_allocator());
810 #endif // ZSERIO_ZSERIO_TREE_CREATOR_H_INC
typename IBasicReflectable< ALLOC >::Ptr IBasicReflectablePtr
void endCompoundElement()
void addValueElement(T &&value)
string< ALLOC > toString(T value, const ALLOC &allocator=ALLOC())
IBasicReflectablePtr< ALLOC > endRoot()
virtual Span< const BasicFieldInfo< ALLOC > > getFields() const =0
void setValue(const string< ALLOC > &name, T &&value)
BasicZserioTreeCreator(const IBasicTypeInfo< ALLOC > &typeInfo, const ALLOC &allocator=ALLOC())
static bool isSigned(SchemaType schemaType)
void beginArray(const string< ALLOC > &name)
virtual StringView getSchemaName() const =0
static bool isCompound(SchemaType schemaType)
const IBasicTypeInfo< ALLOC > & getFieldType(const string< ALLOC > &name) const
allocator_type get_allocator() const
std::vector< T, RebindAlloc< ALLOC, T >> vector
static bool hasChoice(SchemaType schemaType)
BasicStringView< char, std::char_traits< char >> StringView
constexpr iterator begin() const noexcept
std::basic_string< char, std::char_traits< char >, RebindAlloc< ALLOC, char >> string
constexpr iterator end() const noexcept
void beginCompound(const string< ALLOC > &name)
void beginCompoundElement()
const IBasicTypeInfo< ALLOC > & typeInfo
CppRuntimeException & operator<<(CppRuntimeException &exception, const BasicBitBuffer< ALLOC > &bitBuffer)
const IBasicTypeInfo< ALLOC > & getElementType() const