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,
40 bool checkArithmeticValueRanges(U value)
43 return (
static_cast<int64_t
>(value) >=
static_cast<int64_t
>(std::numeric_limits<T>::min()) &&
44 static_cast<int64_t
>(value) <=
static_cast<int64_t
>(std::numeric_limits<T>::max()));
47 template <
typename T,
typename U,
48 typename std::enable_if<std::is_signed<typename std::decay<U>::type>::value &&
49 std::is_unsigned<typename std::decay<T>::type>::value,
51 bool checkArithmeticValueRanges(U value)
54 return (value >= 0 &&
static_cast<uint64_t
>(value) <=
static_cast<uint64_t
>(std::numeric_limits<T>::max()));
57 template <
typename T,
typename ALLOC>
58 AnyHolder<ALLOC> makeAnyBoolValue(
bool value,
const ALLOC& allocator)
60 return AnyHolder<ALLOC>(
static_cast<T
>(value), allocator);
63 template <
typename T,
typename U,
typename ALLOC>
64 AnyHolder<ALLOC> makeAnyBoolValue(
const U& value,
const ALLOC&)
66 throw CppRuntimeException(
"ZserioTreeCreator: Value '") << value <<
"' cannot be converted to bool value!";
69 template <
typename T,
typename ALLOC>
70 AnyHolder<ALLOC> makeAnyIntegralValue(
bool value,
const ALLOC&)
72 throw CppRuntimeException(
"ZserioTreeCreator: Bool value '")
73 << value <<
"' cannot be converted to integral type!";
76 template <
typename T,
typename U,
typename ALLOC,
77 typename std::enable_if<std::is_integral<typename std::decay<U>::type>::value,
int>::type = 0>
78 AnyHolder<ALLOC> makeAnyIntegralValue(U value,
const ALLOC& allocator)
81 if (!checkArithmeticValueRanges<T>(value))
83 throw CppRuntimeException(
"ZserioTreeCreator: Integral value '")
84 << value <<
"' overflow (<" << std::numeric_limits<T>::min() <<
", "
85 << std::numeric_limits<T>::max() <<
">)!";
88 return AnyHolder<ALLOC>(
static_cast<T
>(value), allocator);
91 template <
typename T,
typename U,
typename ALLOC,
92 typename std::enable_if<!std::is_integral<typename std::decay<U>::type>::value,
int>::type = 0>
93 AnyHolder<ALLOC> makeAnyIntegralValue(
const U& value,
const ALLOC&)
95 throw CppRuntimeException(
"ZserioTreeCreator: Value '")
96 << value <<
"' cannot be converted to integral value!";
99 template <
typename T,
typename ALLOC>
100 AnyHolder<ALLOC> makeAnyFloatingValue(
bool value,
const ALLOC&)
102 throw CppRuntimeException(
"ZserioTreeCreator: Bool value '")
103 << value <<
"' cannot be converted to floating type!";
106 template <
typename T,
typename U,
typename ALLOC,
107 typename std::enable_if<std::is_arithmetic<typename std::decay<U>::type>::value,
int>::type = 0>
108 AnyHolder<ALLOC> makeAnyFloatingValue(U value,
const ALLOC& allocator)
111 return AnyHolder<ALLOC>(
static_cast<T
>(value), allocator);
114 template <
typename T,
typename U,
typename ALLOC,
115 typename std::enable_if<!std::is_arithmetic<typename std::decay<U>::type>::value,
int>::type = 0>
116 AnyHolder<ALLOC> makeAnyFloatingValue(
const U& value,
const ALLOC&)
118 throw CppRuntimeException(
"ZserioTreeCreator: Value '")
119 << value <<
"' cannot be converted to floating value!";
122 template <
typename ALLOC>
123 AnyHolder<ALLOC> makeAnyStringValue(
const string<ALLOC>& value,
const ALLOC& allocator)
125 return AnyHolder<ALLOC>(value, allocator);
128 template <
typename ALLOC>
129 AnyHolder<ALLOC> makeAnyStringValue(string<ALLOC>&& value,
const ALLOC& allocator)
131 return AnyHolder<ALLOC>(std::move(value), allocator);
134 template <
typename ALLOC>
135 AnyHolder<ALLOC> makeAnyStringValue(
StringView value,
const ALLOC& allocator)
137 return AnyHolder<ALLOC>(
toString(value, allocator), allocator);
140 template <
typename ALLOC>
141 AnyHolder<ALLOC> makeAnyStringValue(
const char* value,
const ALLOC& allocator)
143 return makeAnyStringValue(
StringView(value), allocator);
146 template <
typename T,
typename ALLOC>
147 AnyHolder<ALLOC> makeAnyStringValue(
const T&,
const ALLOC&)
149 throw CppRuntimeException(
"ZserioTreeCreator: Trying to make any string value from unsupported type!");
152 template <
typename ALLOC>
153 AnyHolder<ALLOC> parseEnumStringValue(
154 StringView stringValue,
const IBasicTypeInfo<ALLOC>& typeInfo,
const ALLOC& allocator)
156 for (
const auto& itemInfo : typeInfo.getEnumItems())
158 if (itemInfo.schemaName == stringValue)
163 typeInfo.getUnderlyingType(),
static_cast<int64_t
>(itemInfo.value), allocator);
167 return makeAnyValue(typeInfo.getUnderlyingType(), itemInfo.value, allocator);
172 return AnyHolder<ALLOC>(allocator);
175 template <
typename ALLOC>
176 AnyHolder<ALLOC> makeAnyEnumValue(
177 StringView stringValue,
const IBasicTypeInfo<ALLOC>& typeInfo,
const ALLOC& allocator)
179 if (!stringValue.empty())
181 const char firstChar = stringValue[0];
182 if ((firstChar >=
'A' && firstChar <=
'Z') || (firstChar >=
'a' && firstChar <=
'z') ||
185 AnyHolder<ALLOC> anyValue = parseEnumStringValue(stringValue, typeInfo, allocator);
186 if (anyValue.hasValue())
192 throw CppRuntimeException(
"ZserioTreeCreator: Cannot create enum '")
193 << typeInfo.getSchemaName() <<
"' from string value '" << stringValue <<
"'!";
196 template <
typename ALLOC>
197 AnyHolder<ALLOC> makeAnyEnumValue(
198 const string<ALLOC>& stringValue,
const IBasicTypeInfo<ALLOC>& typeInfo,
const ALLOC& allocator)
200 return makeAnyEnumValue(
StringView(stringValue), typeInfo, allocator);
203 template <
typename ALLOC>
204 AnyHolder<ALLOC> makeAnyEnumValue(
205 const char* stringValue,
const IBasicTypeInfo<ALLOC>& typeInfo,
const ALLOC& allocator)
207 return makeAnyEnumValue(
StringView(stringValue), typeInfo, allocator);
210 template <typename T, typename ALLOC, typename std::enable_if<std::is_enum<T>::value,
int>::type = 0>
211 AnyHolder<ALLOC> makeAnyEnumValue(T enumValue,
const IBasicTypeInfo<ALLOC>&,
const ALLOC& allocator)
213 return AnyHolder<ALLOC>(enumValue, allocator);
216 template <typename T, typename ALLOC, typename std::enable_if<!std::is_enum<T>::value,
int>::type = 0>
217 AnyHolder<ALLOC> makeAnyEnumValue(T enumRawValue,
const IBasicTypeInfo<ALLOC>& typeInfo,
const ALLOC& allocator)
219 return makeAnyValue(typeInfo.getUnderlyingType(), enumRawValue, allocator);
222 template <
typename ALLOC>
223 AnyHolder<ALLOC> parseBitmaskStringValue(
224 StringView stringValue,
const IBasicTypeInfo<ALLOC>& typeInfo,
const ALLOC& allocator)
228 while (pos < stringValue.size())
231 const size_t available = stringValue.size() - pos;
232 for (
const auto& itemInfo : typeInfo.getBitmaskValues())
234 if (available >= itemInfo.schemaName.size() &&
235 stringValue.substr(pos, itemInfo.schemaName.size()) == itemInfo.schemaName)
237 const size_t newPos = pos + itemInfo.schemaName.size();
239 if (newPos == stringValue.size() || stringValue[newPos] ==
' ' || stringValue[newPos] ==
'|')
241 value |= itemInfo.value;
242 if (newPos == stringValue.size())
243 return makeAnyValue(typeInfo.getUnderlyingType(), value, allocator);
245 pos += itemInfo.schemaName.size();
254 while (pos < stringValue.size() && stringValue[pos] ==
' ')
257 if (pos < stringValue.size() && stringValue[pos] ==
'|')
260 while (pos < stringValue.size() && stringValue[pos] ==
' ')
265 return AnyHolder<ALLOC>(allocator);
268 template <
typename ALLOC>
269 AnyHolder<ALLOC> parseBitmaskNumericStringValue(
270 const char* stringValue,
const IBasicTypeInfo<ALLOC>& typeInfo,
const ALLOC& allocator)
272 char* pEnd =
nullptr;
274 uint64_t value = std::strtoull(stringValue, &pEnd, 10);
276 return AnyHolder<ALLOC>(allocator);
277 return makeAnyValue(typeInfo.getUnderlyingType(), value, allocator);
280 template <
typename ALLOC>
281 AnyHolder<ALLOC> makeAnyBitmaskValue(
282 StringView stringValue,
const IBasicTypeInfo<ALLOC>& typeInfo,
const ALLOC& allocator)
284 if (!stringValue.empty())
286 const char firstChar = stringValue[0];
287 if ((firstChar >=
'A' && firstChar <=
'Z') || (firstChar >=
'a' && firstChar <=
'z') ||
290 AnyHolder<ALLOC> anyValue = parseBitmaskStringValue(stringValue, typeInfo, allocator);
291 if (anyValue.hasValue())
294 else if (firstChar >=
'0' && firstChar <=
'9')
297 const string<ALLOC> numericStringValue =
toString(stringValue, allocator);
298 AnyHolder<ALLOC> anyValue =
299 parseBitmaskNumericStringValue(numericStringValue.c_str(), typeInfo, allocator);
300 if (anyValue.hasValue())
305 throw CppRuntimeException(
"ZserioTreeCreator: Cannot create bitmask '")
306 << typeInfo.getSchemaName() <<
"' from string value '" << stringValue <<
"'!";
309 template <
typename ALLOC>
310 AnyHolder<ALLOC> makeAnyBitmaskValue(
311 const string<ALLOC>& stringValue,
const IBasicTypeInfo<ALLOC>& typeInfo,
const ALLOC& allocator)
313 return makeAnyBitmaskValue(
StringView(stringValue), typeInfo, allocator);
316 template <
typename ALLOC>
317 AnyHolder<ALLOC> makeAnyBitmaskValue(
318 const char* stringValue,
const IBasicTypeInfo<ALLOC>& typeInfo,
const ALLOC& allocator)
320 return makeAnyBitmaskValue(
StringView(stringValue), typeInfo, allocator);
323 template <typename T, typename ALLOC, typename std::enable_if<is_bitmask<T>::value,
int>::type = 0>
324 AnyHolder<ALLOC> makeAnyBitmaskValue(T bitmaskValue,
const IBasicTypeInfo<ALLOC>&,
const ALLOC& allocator)
326 return AnyHolder<ALLOC>(bitmaskValue, allocator);
329 template <typename T, typename ALLOC, typename std::enable_if<!is_bitmask<T>::value,
int>::type = 0>
330 AnyHolder<ALLOC> makeAnyBitmaskValue(
331 T bitmaskRawValue,
const IBasicTypeInfo<ALLOC>& typeInfo,
const ALLOC& allocator)
333 return makeAnyValue(typeInfo.getUnderlyingType(), bitmaskRawValue, allocator);
336 template <
typename T,
typename ALLOC>
337 AnyHolder<ALLOC> makeAnyValue(
const IBasicTypeInfo<ALLOC>& typeInfo, T&& value,
const ALLOC& allocator)
339 switch (typeInfo.getCppType())
342 return makeAnyBoolValue<bool>(std::forward<T>(value), allocator);
344 return makeAnyIntegralValue<uint8_t>(std::forward<T>(value), allocator);
346 return makeAnyIntegralValue<uint16_t>(std::forward<T>(value), allocator);
348 return makeAnyIntegralValue<uint32_t>(std::forward<T>(value), allocator);
350 return makeAnyIntegralValue<uint64_t>(std::forward<T>(value), allocator);
352 return makeAnyIntegralValue<int8_t>(std::forward<T>(value), allocator);
354 return makeAnyIntegralValue<int16_t>(std::forward<T>(value), allocator);
356 return makeAnyIntegralValue<int32_t>(std::forward<T>(value), allocator);
358 return makeAnyIntegralValue<int64_t>(std::forward<T>(value), allocator);
360 return makeAnyFloatingValue<float>(std::forward<T>(value), allocator);
362 return makeAnyFloatingValue<double>(std::forward<T>(value), allocator);
364 return makeAnyStringValue(std::forward<T>(value), allocator);
366 return makeAnyEnumValue(std::forward<T>(value), typeInfo, allocator);
368 return makeAnyBitmaskValue(std::forward<T>(value), typeInfo, allocator);
370 return AnyHolder<ALLOC>(std::forward<T>(value), allocator);
375 template <
typename ALLOC>
376 AnyHolder<ALLOC> makeAnyValue(
const IBasicTypeInfo<ALLOC>&, AnyHolder<ALLOC>&& anyValue,
const ALLOC&)
378 return std::move(anyValue);
381 enum class CreatorState : uint8_t
398 CppRuntimeException&
operator<<(CppRuntimeException& exception, detail::CreatorState state);
403 template <
typename ALLOC>
468 template <
typename T>
515 template <
typename T>
533 template <
typename T>
539 detail::CreatorState m_state = detail::CreatorState::BEFORE_ROOT;
545 template <
typename ALLOC>
549 m_typeInfo(typeInfo),
550 m_fieldInfoStack(allocator),
551 m_valueStack(allocator)
554 template <
typename ALLOC>
557 if (m_state != detail::CreatorState::BEFORE_ROOT)
558 throw CppRuntimeException(
"ZserioTreeCreator: Cannot begin root in state '") << m_state <<
"'!";
560 m_valueStack.push_back(m_typeInfo.createInstance(get_allocator()));
561 m_state = detail::CreatorState::IN_COMPOUND;
564 template <
typename ALLOC>
567 if (m_state != detail::CreatorState::IN_COMPOUND || m_valueStack.size() != 1)
568 throw CppRuntimeException(
"ZserioTreeCreator: Cannot end root in state '") << m_state <<
"'!";
570 m_state = detail::CreatorState::BEFORE_ROOT;
571 auto value = m_valueStack.back();
572 m_valueStack.pop_back();
576 template <
typename ALLOC>
579 if (m_state != detail::CreatorState::IN_COMPOUND)
580 throw CppRuntimeException(
"ZserioTreeCreator: Cannot begin array in state '") << m_state <<
"'!";
582 const auto& parentTypeInfo = getTypeInfo();
583 const auto& fieldInfo = findFieldInfo(parentTypeInfo, name);
584 if (!fieldInfo.isArray)
587 << fieldInfo.schemaName <<
"' is not an array!";
590 m_fieldInfoStack.push_back(fieldInfo);
598 m_valueStack.push_back(m_valueStack.back()->createField(name));
600 m_state = detail::CreatorState::IN_ARRAY;
603 template <
typename ALLOC>
606 if (m_state != detail::CreatorState::IN_ARRAY)
607 throw CppRuntimeException(
"ZserioTreeCreator: Cannot end array in state '") << m_state <<
"'!";
609 m_fieldInfoStack.pop_back();
610 m_valueStack.pop_back();
611 m_state = detail::CreatorState::IN_COMPOUND;
614 template <
typename ALLOC>
617 if (m_state != detail::CreatorState::IN_COMPOUND)
618 throw CppRuntimeException(
"ZserioTreeCreator: Cannot begin compound in state '") << m_state <<
"'!";
620 const auto& parentTypeInfo = getTypeInfo();
621 const auto& fieldInfo = findFieldInfo(parentTypeInfo, name);
622 if (fieldInfo.isArray)
623 throw CppRuntimeException(
"ZserioTreeCreator: Member '") << fieldInfo.schemaName <<
"' is an array!";
628 << fieldInfo.schemaName <<
"' is not a compound!";
631 m_fieldInfoStack.push_back(fieldInfo);
635 m_valueStack.push_back(m_valueStack.back()->createField(name));
639 m_valueStack.push_back(m_valueStack.back()->getField(name));
642 m_state = detail::CreatorState::IN_COMPOUND;
645 template <
typename ALLOC>
648 if (m_state != detail::CreatorState::IN_COMPOUND || m_fieldInfoStack.empty())
651 << m_state <<
"'" << (m_fieldInfoStack.empty() ?
", expecting endRoot!" :
"!'");
656 throw CppRuntimeException(
"ZserioTreeCreator: Cannot end compound, it's an array element!");
658 m_fieldInfoStack.pop_back();
659 m_valueStack.pop_back();
662 template <
typename ALLOC>
663 template <
typename T>
666 if (m_state != detail::CreatorState::IN_COMPOUND)
667 throw CppRuntimeException(
"ZserioTreeCreator: Cannot set value in state '") << m_state <<
"'!";
676 m_valueStack.
back()->setField(
680 template <
typename ALLOC>
683 if (m_state != detail::CreatorState::IN_COMPOUND)
685 throw CppRuntimeException(
"ZserioTreeCreator: Cannot set value (null) in state '") << m_state <<
"'!";
698 m_valueStack.back()->createField(fieldInfo.
schemaName);
702 template <
typename ALLOC>
705 if (m_state != detail::CreatorState::IN_COMPOUND)
706 throw CppRuntimeException(
"ZserioTreeCreator: Cannot get field type in state '") << m_state <<
"'!";
708 return findFieldInfo(getTypeInfo(), name).typeInfo;
711 template <
typename ALLOC>
714 if (m_state != detail::CreatorState::IN_ARRAY)
724 << fieldInfo.
schemaName <<
"' is not a compound!";
727 auto compoundArray = m_valueStack.
back();
728 compoundArray->resize(compoundArray->size() + 1);
729 m_valueStack.push_back(compoundArray->at(compoundArray->size() - 1));
730 m_state = detail::CreatorState::IN_COMPOUND;
733 template <
typename ALLOC>
736 if (m_state != detail::CreatorState::IN_COMPOUND || m_fieldInfoStack.empty())
739 << m_state << (m_fieldInfoStack.empty() ?
", expecting endRoot!" :
"'!");
744 throw CppRuntimeException(
"ZserioTreeCreator: Cannot end compound element, not in array!");
746 m_valueStack.pop_back();
747 m_state = detail::CreatorState::IN_ARRAY;
750 template <
typename ALLOC>
751 template <
typename T>
754 if (m_state != detail::CreatorState::IN_ARRAY)
756 throw CppRuntimeException(
"ZserioTreeCreator: Cannot add value element in state '") << m_state <<
"'!";
760 m_valueStack.back()->append(makeAnyValue(fieldInfo.
typeInfo, std::forward<T>(value)));
763 template <
typename ALLOC>
766 if (m_state != detail::CreatorState::IN_ARRAY)
768 throw CppRuntimeException(
"ZserioTreeCreator: Cannot get element type in state '") << m_state <<
"'!";
771 return m_fieldInfoStack.back().get().typeInfo;
774 template <
typename ALLOC>
777 return m_fieldInfoStack.empty() ? m_typeInfo : m_fieldInfoStack.back().get().typeInfo;
780 template <
typename ALLOC>
781 const BasicFieldInfo<ALLOC>& BasicZserioTreeCreator<ALLOC>::findFieldInfo(
782 const IBasicTypeInfo<ALLOC>& typeInfo,
StringView name)
const
784 Span<const BasicFieldInfo<ALLOC>> fields = typeInfo.getFields();
785 auto found_it = std::find_if(fields.begin(), fields.end(), [name](
const BasicFieldInfo<ALLOC>& field) {
786 return field.schemaName == name;
788 if (found_it == fields.end())
790 throw CppRuntimeException(
"ZserioTreeCreator: Member '")
791 << name <<
"' not found in '" << typeInfo.getSchemaName() <<
"'!";
797 template <
typename ALLOC>
798 template <
typename T>
799 AnyHolder<ALLOC> BasicZserioTreeCreator<ALLOC>::makeAnyValue(
800 const IBasicTypeInfo<ALLOC>& typeInfo, T&& value)
const
802 return detail::makeAnyValue(typeInfo, std::forward<T>(value), get_allocator());
constexpr const_reference back() const noexcept
IBasicReflectablePtr< ALLOC > endRoot()
void beginArray(const string< ALLOC > &name)
const IBasicTypeInfo< ALLOC > & getFieldType(const string< ALLOC > &name) const
const IBasicTypeInfo< ALLOC > & getElementType() const
void setValue(const string< ALLOC > &name, T &&value)
void beginCompound(const string< ALLOC > &name)
void beginCompoundElement()
BasicZserioTreeCreator(const IBasicTypeInfo< ALLOC > &typeInfo, const ALLOC &allocator=ALLOC())
void addValueElement(T &&value)
void endCompoundElement()
virtual CppType getCppType() const =0
BasicStringView< char, std::char_traits< char > > StringView
std::basic_string< char, std::char_traits< char >, RebindAlloc< ALLOC, char > > string
std::vector< T, RebindAlloc< ALLOC, T > > vector
CppRuntimeException & operator<<(CppRuntimeException &exception, const BasicBitBuffer< ALLOC > &bitBuffer)
string< ALLOC > toString(T value, const ALLOC &allocator=ALLOC())
typename IBasicReflectable< ALLOC >::Ptr IBasicReflectablePtr
const IBasicTypeInfo< ALLOC > & typeInfo
static bool hasChoice(SchemaType schemaType)
static bool isCompound(SchemaType schemaType)
static bool isSigned(SchemaType schemaType)