1 #ifndef ZSERIO_ZSERIO_TREE_CREATOR_H_INC
2 #define ZSERIO_ZSERIO_TREE_CREATOR_H_INC
27 template <
typename T,
typename ALLOC>
28 BasicAny<ALLOC> makeAnyValue(
const IBasicTypeInfo<ALLOC>&
typeInfo, T&& value,
const ALLOC& allocator);
30 template <
typename T,
typename U, std::enable_if_t<std::is_
integral_v<std::decay_t<U>>,
int> = 0>
31 bool checkArithmeticValueRanges(U value)
33 if constexpr (std::is_unsigned_v<std::decay_t<U>>)
36 return (value <=
static_cast<U
>(std::numeric_limits<T>::max()));
38 else if constexpr (std::is_signed_v<std::decay_t<U>> && std::is_signed_v<std::decay_t<T>>)
41 return (
static_cast<int64_t
>(value) >=
static_cast<int64_t
>(std::numeric_limits<T>::min()) &&
42 static_cast<int64_t
>(value) <=
static_cast<int64_t
>(std::numeric_limits<T>::max()));
44 else if constexpr (std::is_signed_v<std::decay_t<U>> && std::is_unsigned_v<std::decay_t<T>>)
48 static_cast<uint64_t
>(value) <=
static_cast<uint64_t
>(std::numeric_limits<T>::max()));
52 template <
typename T,
typename U, std::enable_if_t<is_numeric_wrapper_v<std::decay_t<U>>,
int> = 0>
53 bool checkArithmeticValueRanges(U value)
55 return checkArithmeticValueRanges<T>(
static_cast<typename U::ValueType
>(value));
58 template <
typename T,
typename ALLOC>
59 BasicAny<ALLOC> makeAnyBoolValue(
bool value,
const ALLOC& allocator)
61 return BasicAny<ALLOC>(
static_cast<T
>(value), allocator);
64 template <
typename T,
typename U,
typename ALLOC>
65 BasicAny<ALLOC> makeAnyBoolValue(
const U& value,
const ALLOC&)
67 throw CppRuntimeException(
"ZserioTreeCreator: Value '") << value <<
"' cannot be converted to bool value!";
70 template <
typename T,
typename ALLOC>
71 BasicAny<ALLOC> makeAnyIntegralValue(
bool value,
const ALLOC&)
73 throw CppRuntimeException(
"ZserioTreeCreator: Bool value '")
74 << value <<
"' cannot be converted to integral type!";
77 template <
typename T,
typename U,
typename ALLOC>
78 BasicAny<ALLOC> makeAnyIntegralValue(U value,
const ALLOC& allocator)
80 using Type = std::decay_t<U>;
81 if constexpr (std::is_integral_v<Type> || is_numeric_wrapper_v<Type>)
84 if (!checkArithmeticValueRanges<T>(value))
86 throw CppRuntimeException(
"ZserioTreeCreator: Integral value '")
87 << value <<
"' overflow (<" << std::numeric_limits<T>::min() <<
", "
88 << std::numeric_limits<T>::max() <<
">)!";
91 return BasicAny<ALLOC>(
static_cast<T
>(value), allocator);
95 throw CppRuntimeException(
"ZserioTreeCreator: Value '")
96 << value <<
"' cannot be converted to integral value!";
100 template <
typename T,
typename ALLOC>
101 BasicAny<ALLOC> makeAnyFloatingValue(
bool value,
const ALLOC&)
103 throw CppRuntimeException(
"ZserioTreeCreator: Bool value '")
104 << value <<
"' cannot be converted to floating type!";
107 template <
typename T,
typename U,
typename ALLOC>
108 BasicAny<ALLOC> makeAnyFloatingValue(U value,
const ALLOC& allocator)
110 using Type = std::decay_t<U>;
111 if constexpr (std::is_arithmetic_v<Type> || is_numeric_wrapper_v<Type>)
114 return BasicAny<ALLOC>(
static_cast<T
>(value), allocator);
118 throw CppRuntimeException(
"ZserioTreeCreator: Value '")
119 << value <<
"' cannot be converted to floating value!";
123 template <
typename ALLOC>
124 BasicAny<ALLOC> makeAnyStringValue(
const BasicString<RebindAlloc<ALLOC, char>>& value,
const ALLOC& allocator)
126 return BasicAny<ALLOC>(value, allocator);
129 template <
typename ALLOC>
130 BasicAny<ALLOC> makeAnyStringValue(
BasicString<RebindAlloc<ALLOC, char>>&& value,
const ALLOC& allocator)
132 return BasicAny<ALLOC>(std::move(value), allocator);
135 template <
typename ALLOC>
136 BasicAny<ALLOC> makeAnyStringValue(std::string_view value,
const ALLOC& allocator)
138 return BasicAny<ALLOC>(
toString(value, allocator), allocator);
141 template <
typename ALLOC>
142 BasicAny<ALLOC> makeAnyStringValue(
const char* value,
const ALLOC& allocator)
144 return makeAnyStringValue(std::string_view(value), allocator);
147 template <
typename T,
typename ALLOC>
148 BasicAny<ALLOC> makeAnyStringValue(
const T&,
const ALLOC&)
150 throw CppRuntimeException(
"ZserioTreeCreator: Trying to make any string value from unsupported type!");
153 template <
typename ALLOC>
154 BasicAny<ALLOC> parseEnumStringValue(
155 std::string_view stringValue,
const IBasicTypeInfo<ALLOC>&
typeInfo,
const ALLOC& allocator)
159 if (itemInfo.schemaName == stringValue)
173 return BasicAny<ALLOC>(allocator);
176 template <
typename ALLOC>
177 BasicAny<ALLOC> makeAnyEnumValue(
178 std::string_view stringValue,
const IBasicTypeInfo<ALLOC>&
typeInfo,
const ALLOC& allocator)
180 if (!stringValue.empty())
182 const char firstChar = stringValue[0];
183 if ((firstChar >=
'A' && firstChar <=
'Z') || (firstChar >=
'a' && firstChar <=
'z') ||
186 BasicAny<ALLOC> anyValue = parseEnumStringValue(stringValue,
typeInfo, allocator);
187 if (anyValue.hasValue())
195 throw CppRuntimeException(
"ZserioTreeCreator: Cannot create enum '")
199 template <
typename ALLOC>
200 BasicAny<ALLOC> makeAnyEnumValue(
const BasicString<RebindAlloc<ALLOC, char>>& stringValue,
201 const IBasicTypeInfo<ALLOC>&
typeInfo,
const ALLOC& allocator)
203 return makeAnyEnumValue(std::string_view(stringValue),
typeInfo, allocator);
206 template <
typename ALLOC>
207 BasicAny<ALLOC> makeAnyEnumValue(
208 const char* stringValue,
const IBasicTypeInfo<ALLOC>&
typeInfo,
const ALLOC& allocator)
210 return makeAnyEnumValue(std::string_view(stringValue),
typeInfo, allocator);
213 template <typename T, typename ALLOC, typename std::enable_if<std::is_enum<T>::value,
int>::type = 0>
214 BasicAny<ALLOC> makeAnyEnumValue(T enumValue,
const IBasicTypeInfo<ALLOC>&,
const ALLOC& allocator)
216 return BasicAny<ALLOC>(enumValue, allocator);
219 template <typename T, typename ALLOC, typename std::enable_if<!std::is_enum<T>::value,
int>::type = 0>
220 BasicAny<ALLOC> makeAnyEnumValue(T enumRawValue,
const IBasicTypeInfo<ALLOC>&
typeInfo,
const ALLOC& allocator)
225 template <
typename ALLOC>
226 BasicAny<ALLOC> parseBitmaskStringValue(
227 std::string_view stringValue,
const IBasicTypeInfo<ALLOC>&
typeInfo,
const ALLOC& allocator)
231 while (pos < stringValue.size())
234 const size_t available = stringValue.size() - pos;
237 if (available >= itemInfo.schemaName.size() &&
238 stringValue.substr(pos, itemInfo.schemaName.size()) == itemInfo.schemaName)
240 const size_t newPos = pos + itemInfo.schemaName.size();
242 if (newPos == stringValue.size() || stringValue[newPos] ==
' ' || stringValue[newPos] ==
'|')
244 value |= itemInfo.value;
245 if (newPos == stringValue.size())
250 pos += itemInfo.schemaName.size();
261 while (pos < stringValue.size() && stringValue[pos] ==
' ')
266 if (pos < stringValue.size() && stringValue[pos] ==
'|')
271 while (pos < stringValue.size() && stringValue[pos] ==
' ')
278 return BasicAny<ALLOC>(allocator);
281 template <
typename ALLOC>
282 BasicAny<ALLOC> parseBitmaskNumericStringValue(
283 const char* stringValue,
const IBasicTypeInfo<ALLOC>&
typeInfo,
const ALLOC& allocator)
285 char* pEnd =
nullptr;
287 uint64_t value = std::strtoull(stringValue, &pEnd, 10);
290 return BasicAny<ALLOC>(allocator);
295 template <
typename ALLOC>
296 BasicAny<ALLOC> makeAnyBitmaskValue(
297 std::string_view stringValue,
const IBasicTypeInfo<ALLOC>&
typeInfo,
const ALLOC& allocator)
299 if (!stringValue.empty())
301 const char firstChar = stringValue[0];
302 if ((firstChar >=
'A' && firstChar <=
'Z') || (firstChar >=
'a' && firstChar <=
'z') ||
305 BasicAny<ALLOC> anyValue = parseBitmaskStringValue(stringValue,
typeInfo, allocator);
306 if (anyValue.hasValue())
311 else if (firstChar >=
'0' && firstChar <=
'9')
314 const BasicString<RebindAlloc<ALLOC, char>> numericStringValue =
toString(stringValue, allocator);
315 BasicAny<ALLOC> anyValue =
316 parseBitmaskNumericStringValue(numericStringValue.c_str(),
typeInfo, allocator);
317 if (anyValue.hasValue())
324 throw CppRuntimeException(
"ZserioTreeCreator: Cannot create bitmask '")
328 template <
typename ALLOC>
329 BasicAny<ALLOC> makeAnyBitmaskValue(
const BasicString<RebindAlloc<ALLOC, char>>& stringValue,
330 const IBasicTypeInfo<ALLOC>&
typeInfo,
const ALLOC& allocator)
332 return makeAnyBitmaskValue(std::string_view(stringValue),
typeInfo, allocator);
335 template <
typename ALLOC>
336 BasicAny<ALLOC> makeAnyBitmaskValue(
337 const char* stringValue,
const IBasicTypeInfo<ALLOC>&
typeInfo,
const ALLOC& allocator)
339 return makeAnyBitmaskValue(std::string_view(stringValue),
typeInfo, allocator);
342 template <typename T, typename ALLOC, typename std::enable_if<is_bitmask<T>::value,
int>::type = 0>
343 BasicAny<ALLOC> makeAnyBitmaskValue(T bitmaskValue,
const IBasicTypeInfo<ALLOC>&,
const ALLOC& allocator)
345 return BasicAny<ALLOC>(bitmaskValue, allocator);
348 template <typename T, typename ALLOC, typename std::enable_if<!is_bitmask<T>::value,
int>::type = 0>
349 BasicAny<ALLOC> makeAnyBitmaskValue(
350 T bitmaskRawValue,
const IBasicTypeInfo<ALLOC>&
typeInfo,
const ALLOC& allocator)
355 template <
typename T,
typename ALLOC>
356 BasicAny<ALLOC> makeAnyValue(
const IBasicTypeInfo<ALLOC>&
typeInfo, T&& value,
const ALLOC& allocator)
361 return makeAnyBoolValue<bool>(std::forward<T>(value), allocator);
363 return makeAnyIntegralValue<uint8_t>(std::forward<T>(value), allocator);
365 return makeAnyIntegralValue<uint16_t>(std::forward<T>(value), allocator);
367 return makeAnyIntegralValue<uint32_t>(std::forward<T>(value), allocator);
369 return makeAnyIntegralValue<uint64_t>(std::forward<T>(value), allocator);
371 return makeAnyIntegralValue<int8_t>(std::forward<T>(value), allocator);
373 return makeAnyIntegralValue<int16_t>(std::forward<T>(value), allocator);
375 return makeAnyIntegralValue<int32_t>(std::forward<T>(value), allocator);
377 return makeAnyIntegralValue<int64_t>(std::forward<T>(value), allocator);
379 return makeAnyFloatingValue<float>(std::forward<T>(value), allocator);
381 return makeAnyFloatingValue<double>(std::forward<T>(value), allocator);
383 return makeAnyStringValue(std::forward<T>(value), allocator);
385 return makeAnyEnumValue(std::forward<T>(value),
typeInfo, allocator);
387 return makeAnyBitmaskValue(std::forward<T>(value),
typeInfo, allocator);
389 return BasicAny<ALLOC>(std::forward<T>(value), allocator);
394 template <
typename ALLOC>
395 BasicAny<ALLOC> makeAnyValue(
const IBasicTypeInfo<ALLOC>&, BasicAny<ALLOC>&& anyValue,
const ALLOC&)
397 return std::move(anyValue);
400 enum class CreatorState : uint8_t
417 CppRuntimeException&
operator<<(CppRuntimeException& exception, detail::CreatorState state);
422 template <
typename ALLOC>
487 template <
typename T>
534 template <
typename T>
549 using BasicFieldInfoRef = std::reference_wrapper<const BasicFieldInfo<ALLOC>>;
555 template <
typename T>
561 detail::CreatorState m_state = detail::CreatorState::BEFORE_ROOT;
567 template <
typename ALLOC>
572 m_fieldInfoStack(allocator),
573 m_valueStack(allocator)
576 template <
typename ALLOC>
579 if (m_state != detail::CreatorState::BEFORE_ROOT)
581 throw CppRuntimeException(
"ZserioTreeCreator: Cannot begin root in state '") << m_state <<
"'!";
584 m_valueStack.push_back(m_typeInfo.createInstance(get_allocator()));
585 m_state = detail::CreatorState::IN_COMPOUND;
588 template <
typename ALLOC>
591 if (m_state != detail::CreatorState::IN_COMPOUND || m_valueStack.size() != 1)
593 throw CppRuntimeException(
"ZserioTreeCreator: Cannot end root in state '") << m_state <<
"'!";
596 m_state = detail::CreatorState::BEFORE_ROOT;
597 auto value = m_valueStack.back();
598 m_valueStack.pop_back();
602 template <
typename ALLOC>
605 if (m_state != detail::CreatorState::IN_COMPOUND)
607 throw CppRuntimeException(
"ZserioTreeCreator: Cannot begin array in state '") << m_state <<
"'!";
610 const auto& parentTypeInfo = getTypeInfo();
611 const auto& fieldInfo = findFieldInfo(parentTypeInfo, name);
612 if (!fieldInfo.isArray)
615 << fieldInfo.schemaName <<
"' is not an array!";
618 m_fieldInfoStack.push_back(fieldInfo);
626 m_valueStack.push_back(m_valueStack.back()->createField(name));
628 m_state = detail::CreatorState::IN_ARRAY;
631 template <
typename ALLOC>
634 if (m_state != detail::CreatorState::IN_ARRAY)
636 throw CppRuntimeException(
"ZserioTreeCreator: Cannot end array in state '") << m_state <<
"'!";
639 m_fieldInfoStack.pop_back();
640 m_valueStack.pop_back();
641 m_state = detail::CreatorState::IN_COMPOUND;
644 template <
typename ALLOC>
647 if (m_state != detail::CreatorState::IN_COMPOUND)
649 throw CppRuntimeException(
"ZserioTreeCreator: Cannot begin compound in state '") << m_state <<
"'!";
652 const auto& parentTypeInfo = getTypeInfo();
653 const auto& fieldInfo = findFieldInfo(parentTypeInfo, name);
654 if (fieldInfo.isArray)
656 throw CppRuntimeException(
"ZserioTreeCreator: Member '") << fieldInfo.schemaName <<
"' is an array!";
662 << fieldInfo.schemaName <<
"' is not a compound!";
665 m_fieldInfoStack.push_back(fieldInfo);
669 m_valueStack.push_back(m_valueStack.back()->createField(name));
673 m_valueStack.push_back(m_valueStack.back()->getField(name));
676 m_state = detail::CreatorState::IN_COMPOUND;
679 template <
typename ALLOC>
682 if (m_state != detail::CreatorState::IN_COMPOUND || m_fieldInfoStack.empty())
685 << m_state <<
"'" << (m_fieldInfoStack.empty() ?
", expecting endRoot!" :
"!'");
691 throw CppRuntimeException(
"ZserioTreeCreator: Cannot end compound, it's an array element!");
694 m_fieldInfoStack.pop_back();
695 m_valueStack.pop_back();
698 template <
typename ALLOC>
699 template <
typename T>
702 if (m_state != detail::CreatorState::IN_COMPOUND)
704 throw CppRuntimeException(
"ZserioTreeCreator: Cannot set value in state '") << m_state <<
"'!";
714 m_valueStack.back()->setField(
718 template <
typename ALLOC>
722 if (m_state != detail::CreatorState::IN_COMPOUND)
724 throw CppRuntimeException(
"ZserioTreeCreator: Cannot set value (null) in state '") << m_state <<
"'!";
737 m_valueStack.back()->createField(fieldInfo.
schemaName);
741 template <
typename ALLOC>
745 if (m_state != detail::CreatorState::IN_COMPOUND)
747 throw CppRuntimeException(
"ZserioTreeCreator: Cannot get field type in state '") << m_state <<
"'!";
750 return findFieldInfo(getTypeInfo(), name).typeInfo;
753 template <
typename ALLOC>
756 if (m_state != detail::CreatorState::IN_ARRAY)
766 << fieldInfo.
schemaName <<
"' is not a compound!";
769 auto compoundArray = m_valueStack.back();
770 compoundArray->resize(compoundArray->size() + 1);
771 m_valueStack.push_back(compoundArray->at(compoundArray->size() - 1));
772 m_state = detail::CreatorState::IN_COMPOUND;
775 template <
typename ALLOC>
778 if (m_state != detail::CreatorState::IN_COMPOUND || m_fieldInfoStack.empty())
781 << m_state << (m_fieldInfoStack.empty() ?
", expecting endRoot!" :
"'!");
787 throw CppRuntimeException(
"ZserioTreeCreator: Cannot end compound element, not in array!");
790 m_valueStack.pop_back();
791 m_state = detail::CreatorState::IN_ARRAY;
794 template <
typename ALLOC>
795 template <
typename T>
798 if (m_state != detail::CreatorState::IN_ARRAY)
800 throw CppRuntimeException(
"ZserioTreeCreator: Cannot add value element in state '") << m_state <<
"'!";
804 m_valueStack.back()->append(makeAnyValue(fieldInfo.
typeInfo, std::forward<T>(value)));
807 template <
typename ALLOC>
810 if (m_state != detail::CreatorState::IN_ARRAY)
812 throw CppRuntimeException(
"ZserioTreeCreator: Cannot get element type in state '") << m_state <<
"'!";
815 return m_fieldInfoStack.back().get().typeInfo;
818 template <
typename ALLOC>
821 return m_fieldInfoStack.empty() ? m_typeInfo : m_fieldInfoStack.back().get().typeInfo;
824 template <
typename ALLOC>
825 const BasicFieldInfo<ALLOC>& BasicZserioTreeCreator<ALLOC>::findFieldInfo(
826 const IBasicTypeInfo<ALLOC>&
typeInfo, std::string_view name)
const
829 auto found_it = std::find_if(fields.begin(), fields.end(), [name](
const BasicFieldInfo<ALLOC>& field) {
830 return field.schemaName == name;
832 if (found_it == fields.end())
834 throw CppRuntimeException(
"ZserioTreeCreator: Member '")
841 template <
typename ALLOC>
842 template <
typename T>
843 BasicAny<ALLOC> BasicZserioTreeCreator<ALLOC>::makeAnyValue(
844 const IBasicTypeInfo<ALLOC>&
typeInfo, T&& value)
const
846 return detail::makeAnyValue(
typeInfo, std::forward<T>(value), get_allocator());
const IBasicTypeInfo< ALLOC > & getFieldType(const BasicString< RebindAlloc< ALLOC, char >> &name) const
const IBasicTypeInfo< ALLOC > & getElementType() const
void beginCompoundElement()
BasicZserioTreeCreator(const IBasicTypeInfo< ALLOC > &typeInfo, const ALLOC &allocator=ALLOC())
void setValue(const BasicString< RebindAlloc< ALLOC, char >> &name, T &&value)
void beginCompound(const BasicString< RebindAlloc< ALLOC, char >> &name)
void addValueElement(T &&value)
void beginArray(const BasicString< RebindAlloc< ALLOC, char >> &name)
void endCompoundElement()
IBasicReflectableDataPtr< ALLOC > endRoot()
virtual Span< const BasicFieldInfo< ALLOC > > getFields() const =0
virtual const IBasicTypeInfo< ALLOC > & getUnderlyingType() const =0
virtual CppType getCppType() const =0
virtual Span< const ItemInfo > getEnumItems() const =0
virtual Span< const ItemInfo > getBitmaskValues() const =0
virtual std::string_view getSchemaName() const =0
typename IBasicReflectableData< ALLOC >::Ptr IBasicReflectableDataPtr
std::basic_string< char, std::char_traits< char >, ALLOC > BasicString
std::vector< T, ALLOC > Vector
typename std::allocator_traits< ALLOC >::template rebind_alloc< T > RebindAlloc
const IBasicTypeInfo< ALLOC > & typeInfo()
BasicString< RebindAlloc< ALLOC, char > > toString(T value, const ALLOC &allocator=ALLOC())
CppRuntimeException & operator<<(CppRuntimeException &exception, const BasicBitBuffer< ALLOC > &bitBuffer)
std::string_view schemaName
const IBasicTypeInfo< ALLOC > & typeInfo
static bool hasChoice(SchemaType schemaType)
static bool isCompound(SchemaType schemaType)
static bool isSigned(SchemaType schemaType)