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())
194 throw CppRuntimeException(
"ZserioTreeCreator: Cannot create enum '")
195 << typeInfo.getSchemaName() <<
"' from string value '" << stringValue <<
"'!";
198 template <
typename ALLOC>
199 AnyHolder<ALLOC> makeAnyEnumValue(
200 const string<ALLOC>& stringValue,
const IBasicTypeInfo<ALLOC>& typeInfo,
const ALLOC& allocator)
202 return makeAnyEnumValue(
StringView(stringValue), typeInfo, allocator);
205 template <
typename ALLOC>
206 AnyHolder<ALLOC> makeAnyEnumValue(
207 const char* stringValue,
const IBasicTypeInfo<ALLOC>& typeInfo,
const ALLOC& allocator)
209 return makeAnyEnumValue(
StringView(stringValue), typeInfo, allocator);
212 template <typename T, typename ALLOC, typename std::enable_if<std::is_enum<T>::value,
int>::type = 0>
213 AnyHolder<ALLOC> makeAnyEnumValue(T enumValue,
const IBasicTypeInfo<ALLOC>&,
const ALLOC& allocator)
215 return AnyHolder<ALLOC>(enumValue, allocator);
218 template <typename T, typename ALLOC, typename std::enable_if<!std::is_enum<T>::value,
int>::type = 0>
219 AnyHolder<ALLOC> makeAnyEnumValue(T enumRawValue,
const IBasicTypeInfo<ALLOC>& typeInfo,
const ALLOC& allocator)
221 return makeAnyValue(typeInfo.getUnderlyingType(), enumRawValue, allocator);
224 template <
typename ALLOC>
225 AnyHolder<ALLOC> parseBitmaskStringValue(
226 StringView stringValue,
const IBasicTypeInfo<ALLOC>& typeInfo,
const ALLOC& allocator)
230 while (pos < stringValue.size())
233 const size_t available = stringValue.size() - pos;
234 for (
const auto& itemInfo : typeInfo.getBitmaskValues())
236 if (available >= itemInfo.schemaName.size() &&
237 stringValue.substr(pos, itemInfo.schemaName.size()) == itemInfo.schemaName)
239 const size_t newPos = pos + itemInfo.schemaName.size();
241 if (newPos == stringValue.size() || stringValue[newPos] ==
' ' || stringValue[newPos] ==
'|')
243 value |= itemInfo.value;
244 if (newPos == stringValue.size())
246 return makeAnyValue(typeInfo.getUnderlyingType(), value, allocator);
249 pos += itemInfo.schemaName.size();
260 while (pos < stringValue.size() && stringValue[pos] ==
' ')
265 if (pos < stringValue.size() && stringValue[pos] ==
'|')
270 while (pos < stringValue.size() && stringValue[pos] ==
' ')
277 return AnyHolder<ALLOC>(allocator);
280 template <
typename ALLOC>
281 AnyHolder<ALLOC> parseBitmaskNumericStringValue(
282 const char* stringValue,
const IBasicTypeInfo<ALLOC>& typeInfo,
const ALLOC& allocator)
284 char* pEnd =
nullptr;
286 uint64_t value = std::strtoull(stringValue, &pEnd, 10);
289 return AnyHolder<ALLOC>(allocator);
291 return makeAnyValue(typeInfo.getUnderlyingType(), value, allocator);
294 template <
typename ALLOC>
295 AnyHolder<ALLOC> makeAnyBitmaskValue(
296 StringView stringValue,
const IBasicTypeInfo<ALLOC>& typeInfo,
const ALLOC& allocator)
298 if (!stringValue.empty())
300 const char firstChar = stringValue[0];
301 if ((firstChar >=
'A' && firstChar <=
'Z') || (firstChar >=
'a' && firstChar <=
'z') ||
304 AnyHolder<ALLOC> anyValue = parseBitmaskStringValue(stringValue, typeInfo, allocator);
305 if (anyValue.hasValue())
310 else if (firstChar >=
'0' && firstChar <=
'9')
313 const string<ALLOC> numericStringValue =
toString(stringValue, allocator);
314 AnyHolder<ALLOC> anyValue =
315 parseBitmaskNumericStringValue(numericStringValue.c_str(), typeInfo, allocator);
316 if (anyValue.hasValue())
323 throw CppRuntimeException(
"ZserioTreeCreator: Cannot create bitmask '")
324 << typeInfo.getSchemaName() <<
"' from string value '" << stringValue <<
"'!";
327 template <
typename ALLOC>
328 AnyHolder<ALLOC> makeAnyBitmaskValue(
329 const string<ALLOC>& stringValue,
const IBasicTypeInfo<ALLOC>& typeInfo,
const ALLOC& allocator)
331 return makeAnyBitmaskValue(
StringView(stringValue), typeInfo, allocator);
334 template <
typename ALLOC>
335 AnyHolder<ALLOC> makeAnyBitmaskValue(
336 const char* stringValue,
const IBasicTypeInfo<ALLOC>& typeInfo,
const ALLOC& allocator)
338 return makeAnyBitmaskValue(
StringView(stringValue), typeInfo, allocator);
341 template <typename T, typename ALLOC, typename std::enable_if<is_bitmask<T>::value,
int>::type = 0>
342 AnyHolder<ALLOC> makeAnyBitmaskValue(T bitmaskValue,
const IBasicTypeInfo<ALLOC>&,
const ALLOC& allocator)
344 return AnyHolder<ALLOC>(bitmaskValue, allocator);
347 template <typename T, typename ALLOC, typename std::enable_if<!is_bitmask<T>::value,
int>::type = 0>
348 AnyHolder<ALLOC> makeAnyBitmaskValue(
349 T bitmaskRawValue,
const IBasicTypeInfo<ALLOC>& typeInfo,
const ALLOC& allocator)
351 return makeAnyValue(typeInfo.getUnderlyingType(), bitmaskRawValue, allocator);
354 template <
typename T,
typename ALLOC>
355 AnyHolder<ALLOC> makeAnyValue(
const IBasicTypeInfo<ALLOC>& typeInfo, T&& value,
const ALLOC& allocator)
357 switch (typeInfo.getCppType())
360 return makeAnyBoolValue<bool>(std::forward<T>(value), allocator);
362 return makeAnyIntegralValue<uint8_t>(std::forward<T>(value), allocator);
364 return makeAnyIntegralValue<uint16_t>(std::forward<T>(value), allocator);
366 return makeAnyIntegralValue<uint32_t>(std::forward<T>(value), allocator);
368 return makeAnyIntegralValue<uint64_t>(std::forward<T>(value), allocator);
370 return makeAnyIntegralValue<int8_t>(std::forward<T>(value), allocator);
372 return makeAnyIntegralValue<int16_t>(std::forward<T>(value), allocator);
374 return makeAnyIntegralValue<int32_t>(std::forward<T>(value), allocator);
376 return makeAnyIntegralValue<int64_t>(std::forward<T>(value), allocator);
378 return makeAnyFloatingValue<float>(std::forward<T>(value), allocator);
380 return makeAnyFloatingValue<double>(std::forward<T>(value), allocator);
382 return makeAnyStringValue(std::forward<T>(value), allocator);
384 return makeAnyEnumValue(std::forward<T>(value), typeInfo, allocator);
386 return makeAnyBitmaskValue(std::forward<T>(value), typeInfo, allocator);
388 return AnyHolder<ALLOC>(std::forward<T>(value), allocator);
393 template <
typename ALLOC>
394 AnyHolder<ALLOC> makeAnyValue(
const IBasicTypeInfo<ALLOC>&, AnyHolder<ALLOC>&& anyValue,
const ALLOC&)
396 return std::move(anyValue);
399 enum class CreatorState : uint8_t
416 CppRuntimeException&
operator<<(CppRuntimeException& exception, detail::CreatorState state);
421 template <
typename ALLOC>
486 template <
typename T>
533 template <
typename T>
551 template <
typename T>
557 detail::CreatorState m_state = detail::CreatorState::BEFORE_ROOT;
563 template <
typename ALLOC>
567 m_typeInfo(typeInfo),
568 m_fieldInfoStack(allocator),
569 m_valueStack(allocator)
572 template <
typename ALLOC>
575 if (m_state != detail::CreatorState::BEFORE_ROOT)
577 throw CppRuntimeException(
"ZserioTreeCreator: Cannot begin root in state '") << m_state <<
"'!";
580 m_valueStack.push_back(m_typeInfo.createInstance(get_allocator()));
581 m_state = detail::CreatorState::IN_COMPOUND;
584 template <
typename ALLOC>
587 if (m_state != detail::CreatorState::IN_COMPOUND || m_valueStack.size() != 1)
589 throw CppRuntimeException(
"ZserioTreeCreator: Cannot end root in state '") << m_state <<
"'!";
592 m_state = detail::CreatorState::BEFORE_ROOT;
593 auto value = m_valueStack.back();
594 m_valueStack.pop_back();
598 template <
typename ALLOC>
601 if (m_state != detail::CreatorState::IN_COMPOUND)
603 throw CppRuntimeException(
"ZserioTreeCreator: Cannot begin array in state '") << m_state <<
"'!";
606 const auto& parentTypeInfo = getTypeInfo();
607 const auto& fieldInfo = findFieldInfo(parentTypeInfo, name);
608 if (!fieldInfo.isArray)
611 << fieldInfo.schemaName <<
"' is not an array!";
614 m_fieldInfoStack.push_back(fieldInfo);
622 m_valueStack.push_back(m_valueStack.back()->createField(name));
624 m_state = detail::CreatorState::IN_ARRAY;
627 template <
typename ALLOC>
630 if (m_state != detail::CreatorState::IN_ARRAY)
632 throw CppRuntimeException(
"ZserioTreeCreator: Cannot end array in state '") << m_state <<
"'!";
635 m_fieldInfoStack.pop_back();
636 m_valueStack.pop_back();
637 m_state = detail::CreatorState::IN_COMPOUND;
640 template <
typename ALLOC>
643 if (m_state != detail::CreatorState::IN_COMPOUND)
645 throw CppRuntimeException(
"ZserioTreeCreator: Cannot begin compound in state '") << m_state <<
"'!";
648 const auto& parentTypeInfo = getTypeInfo();
649 const auto& fieldInfo = findFieldInfo(parentTypeInfo, name);
650 if (fieldInfo.isArray)
652 throw CppRuntimeException(
"ZserioTreeCreator: Member '") << fieldInfo.schemaName <<
"' is an array!";
658 << fieldInfo.schemaName <<
"' is not a compound!";
661 m_fieldInfoStack.push_back(fieldInfo);
665 m_valueStack.push_back(m_valueStack.back()->createField(name));
669 m_valueStack.push_back(m_valueStack.back()->getField(name));
672 m_state = detail::CreatorState::IN_COMPOUND;
675 template <
typename ALLOC>
678 if (m_state != detail::CreatorState::IN_COMPOUND || m_fieldInfoStack.empty())
681 << m_state <<
"'" << (m_fieldInfoStack.empty() ?
", expecting endRoot!" :
"!'");
687 throw CppRuntimeException(
"ZserioTreeCreator: Cannot end compound, it's an array element!");
690 m_fieldInfoStack.pop_back();
691 m_valueStack.pop_back();
694 template <
typename ALLOC>
695 template <
typename T>
698 if (m_state != detail::CreatorState::IN_COMPOUND)
700 throw CppRuntimeException(
"ZserioTreeCreator: Cannot set value in state '") << m_state <<
"'!";
710 m_valueStack.
back()->setField(
714 template <
typename ALLOC>
717 if (m_state != detail::CreatorState::IN_COMPOUND)
719 throw CppRuntimeException(
"ZserioTreeCreator: Cannot set value (null) in state '") << m_state <<
"'!";
732 m_valueStack.back()->createField(fieldInfo.
schemaName);
736 template <
typename ALLOC>
739 if (m_state != detail::CreatorState::IN_COMPOUND)
741 throw CppRuntimeException(
"ZserioTreeCreator: Cannot get field type in state '") << m_state <<
"'!";
744 return findFieldInfo(getTypeInfo(), name).typeInfo;
747 template <
typename ALLOC>
750 if (m_state != detail::CreatorState::IN_ARRAY)
760 << fieldInfo.
schemaName <<
"' is not a compound!";
763 auto compoundArray = m_valueStack.
back();
764 compoundArray->resize(compoundArray->size() + 1);
765 m_valueStack.push_back(compoundArray->at(compoundArray->size() - 1));
766 m_state = detail::CreatorState::IN_COMPOUND;
769 template <
typename ALLOC>
772 if (m_state != detail::CreatorState::IN_COMPOUND || m_fieldInfoStack.empty())
775 << m_state << (m_fieldInfoStack.empty() ?
", expecting endRoot!" :
"'!");
781 throw CppRuntimeException(
"ZserioTreeCreator: Cannot end compound element, not in array!");
784 m_valueStack.pop_back();
785 m_state = detail::CreatorState::IN_ARRAY;
788 template <
typename ALLOC>
789 template <
typename T>
792 if (m_state != detail::CreatorState::IN_ARRAY)
794 throw CppRuntimeException(
"ZserioTreeCreator: Cannot add value element in state '") << m_state <<
"'!";
798 m_valueStack.back()->append(makeAnyValue(fieldInfo.
typeInfo, std::forward<T>(value)));
801 template <
typename ALLOC>
804 if (m_state != detail::CreatorState::IN_ARRAY)
806 throw CppRuntimeException(
"ZserioTreeCreator: Cannot get element type in state '") << m_state <<
"'!";
809 return m_fieldInfoStack.back().get().typeInfo;
812 template <
typename ALLOC>
815 return m_fieldInfoStack.empty() ? m_typeInfo : m_fieldInfoStack.back().get().typeInfo;
818 template <
typename ALLOC>
819 const BasicFieldInfo<ALLOC>& BasicZserioTreeCreator<ALLOC>::findFieldInfo(
820 const IBasicTypeInfo<ALLOC>& typeInfo,
StringView name)
const
822 Span<const BasicFieldInfo<ALLOC>> fields = typeInfo.getFields();
823 auto found_it = std::find_if(fields.begin(), fields.end(), [name](
const BasicFieldInfo<ALLOC>& field) {
824 return field.schemaName == name;
826 if (found_it == fields.end())
828 throw CppRuntimeException(
"ZserioTreeCreator: Member '")
829 << name <<
"' not found in '" << typeInfo.getSchemaName() <<
"'!";
835 template <
typename ALLOC>
836 template <
typename T>
837 AnyHolder<ALLOC> BasicZserioTreeCreator<ALLOC>::makeAnyValue(
838 const IBasicTypeInfo<ALLOC>& typeInfo, T&& value)
const
840 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)