1 #ifndef ZSERIO_ARRAY_H_INC
2 #define ZSERIO_ARRAY_H_INC
33 template <
typename T,
typename ARRAY_TRAITS = ArrayTraits<std::remove_cv_t<T>>>
54 using OwnerType = detail::array_owner_type_t<Traits>;
61 template <
typename OWNER_TYPE_ =
OwnerType,
62 std::enable_if_t<detail::is_dummy_array_owner_v<OWNER_TYPE_>,
int> = 0>
73 template <
typename OWNER_TYPE_ =
OwnerType,
74 std::enable_if_t<!detail::is_dummy_array_owner_v<OWNER_TYPE_>,
int> = 0>
115 const size_t thisSize =
size();
116 const size_t otherSize = other.
size();
117 if (thisSize != otherSize)
122 for (
size_t i = 0; i < thisSize; ++i)
124 if ((*
this)[i] != other[i])
142 const size_t thisSize =
size();
143 const size_t otherSize = other.
size();
144 const size_t minSize = std::min(thisSize, otherSize);
146 for (
size_t i = 0; i < minSize; ++i)
148 if ((*
this)[i] < other[i])
152 if (other[i] < (*
this)[i])
158 return thisSize < otherSize;
182 return other.operator<(*this);
194 return !other.operator<(*this);
216 return m_data.size();
226 return m_data.empty();
235 decltype(
auto)
at(
size_t index)
const
237 if (index >= m_data.size())
240 << index <<
" is out of bounds (" << m_data.size() <<
")!";
243 return Traits::at(m_owner, m_data[index], index);
253 decltype(
auto) operator[](
size_t index)
const
255 return Traits::at(m_owner, m_data[index], index);
353 using value_type = decltype(std::declval<ArrayView>().
at(std::declval<size_t>()));
363 return std::addressof(
value);
376 return m_array->
at(m_index);
386 return m_array->
at(m_index +
static_cast<size_t>(offset));
417 m_index +=
static_cast<size_t>(offset);
423 return ConstIterator(m_array, m_index +
static_cast<size_t>(offset));
428 return ConstIterator(other.m_array, other.m_index +
static_cast<size_t>(offset));
433 m_index -=
static_cast<size_t>(offset);
439 return ConstIterator(m_array, m_index -
static_cast<size_t>(offset));
449 return m_index == other.m_index;
454 return !(*
this == other);
459 if (m_index != other.m_index)
461 return m_index < other.m_index;
469 return other < *
this;
474 return !(other < *
this);
479 return !(*
this < other);
495 template <ArrayType ARRAY_TYPE,
typename T,
typename ARRAY_TRAITS>
496 void validate(
const ArrayView<T, ARRAY_TRAITS>& array, std::string_view fieldName,
size_t schemaSize = 0)
498 if constexpr (ARRAY_TYPE == ArrayType::NORMAL || ARRAY_TYPE == ArrayType::ALIGNED)
500 if (array.size() != schemaSize)
502 throw ArrayLengthException(
"Wrong array length for field '")
503 << fieldName <<
"' (" << array.size() <<
" != " << schemaSize <<
")!";
509 for (
size_t i = 0; i < array.size(); ++i)
511 validate(array[i], fieldName);
515 template <ArrayType ARRAY_TYPE,
typename T,
typename ARRAY_TRAITS>
516 BitSize bitSizeOf(
const ArrayView<T, ARRAY_TRAITS>& array,
BitSize bitPosition = 0)
518 BitSize endBitPosition = bitPosition;
520 if constexpr (ARRAY_TYPE == ArrayType::AUTO || ARRAY_TYPE == ArrayType::ALIGNED_AUTO)
525 for (
size_t i = 0; i < array.size(); ++i)
527 if constexpr (ARRAY_TYPE == ArrayType::ALIGNED || ARRAY_TYPE == ArrayType::ALIGNED_AUTO)
529 endBitPosition =
alignTo(8, endBitPosition);
532 endBitPosition += bitSizeOf(array[i], endBitPosition);
535 return endBitPosition - bitPosition;
538 struct DummyOffsetSetter
540 static void setOffset(
size_t ,
BitSize )
544 template <ArrayType ARRAY_TYPE,
typename T,
typename ARRAY_TRAITS,
typename OFFSET_SETTER = DummyOffsetSetter>
545 BitSize initializeOffsets(
const ArrayView<T, ARRAY_TRAITS>& array,
BitSize bitPosition,
546 const OFFSET_SETTER& offsetSetter = OFFSET_SETTER())
550 BitSize endBitPosition = bitPosition;
552 if constexpr (ARRAY_TYPE == ArrayType::AUTO || ARRAY_TYPE == ArrayType::ALIGNED_AUTO)
557 for (
size_t i = 0; i < array.size(); ++i)
559 if constexpr (ARRAY_TYPE == ArrayType::ALIGNED || ARRAY_TYPE == ArrayType::ALIGNED_AUTO)
561 endBitPosition =
alignTo(8, endBitPosition);
562 offsetSetter.setOffset(i, endBitPosition / 8);
565 using AtResult = decltype(std::declval<
const ArrayView<T, ARRAY_TRAITS>&>().at(std::declval<size_t>()));
566 if constexpr (std::is_same_v<View<ValueType>, AtResult>)
568 endBitPosition += initializeOffsets(array[i], endBitPosition);
572 endBitPosition += bitSizeOf(array[i], endBitPosition);
576 return endBitPosition - bitPosition;
579 template <ArrayType ARRAY_TYPE,
typename ARRAY_TRAITS>
580 size_t readArrayLength(BitStreamReader& reader,
size_t arrayLength)
582 if constexpr (ARRAY_TYPE == ArrayType::NORMAL || ARRAY_TYPE == ArrayType::ALIGNED)
586 else if constexpr (ARRAY_TYPE == ArrayType::AUTO || ARRAY_TYPE == ArrayType::ALIGNED_AUTO)
588 return reader.readVarSize();
592 const size_t remainingBits = reader.getBufferBitSize() - reader.getBitPosition();
593 return remainingBits / ARRAY_TRAITS::bitSizeOf();
597 template <ArrayType ARRAY_TYPE,
typename T,
typename ALLOC,
typename ARRAY_TRAITS = ArrayTraits<T>>
598 void read(BitStreamReader& reader, Vector<T, ALLOC>& rawArray, detail::array_owner_type_t<ARRAY_TRAITS>& owner,
599 size_t arrayLength = 0)
601 const size_t readLength = readArrayLength<ARRAY_TYPE, ARRAY_TRAITS>(reader, arrayLength);
603 if constexpr (std::is_base_of_v<NumericArrayTraits<T>, ARRAY_TRAITS>)
605 const size_t elementSize = ARRAY_TRAITS::bitSizeOf();
606 if (reader.getBitPosition() + readLength *
static_cast<uint64_t
>(elementSize) >
607 reader.getBufferBitSize())
609 throw CppRuntimeException(
"ArrayView: Array size exceeds available buffer!");
613 size_t reserve = readLength;
614 if (reserve *
static_cast<uint64_t
>(
sizeof(T)) > reader.getMaxArrayPreallocation())
616 reserve = reader.getMaxArrayPreallocation() /
sizeof(T);
619 rawArray.reserve(reserve);
620 for (
size_t i = 0; i < readLength; ++i)
622 if constexpr (ARRAY_TYPE == ArrayType::ALIGNED || ARRAY_TYPE == ArrayType::ALIGNED_AUTO)
626 rawArray.emplace_back();
627 ARRAY_TRAITS::read(reader, owner, rawArray.back(), i);
631 template <ArrayType ARRAY_TYPE,
typename T,
typename ALLOC,
632 std::enable_if_t<is_dummy_array_owner_v<detail::array_owner_type_t<ArrayTraits<T>>>,
int> = 0>
633 void read(BitStreamReader& reader, Vector<T, ALLOC>& rawArray,
size_t arrayLength = 0)
635 DummyArrayOwner owner;
636 read<ARRAY_TYPE, T, ALLOC>(reader, rawArray, owner, arrayLength);
639 template <ArrayType ARRAY_TYPE,
typename ARRAY_TRAITS,
typename T,
typename ALLOC>
640 void readWithTraits(BitStreamReader& reader, Vector<T, ALLOC>& rawArray,
641 detail::array_owner_type_t<ARRAY_TRAITS>& owner,
size_t arrayLength = 0)
643 read<ARRAY_TYPE, T, ALLOC, ARRAY_TRAITS>(reader, rawArray, owner, arrayLength);
646 template <ArrayType ARRAY_TYPE,
typename ARRAY_TRAITS,
typename T,
typename ALLOC,
647 std::enable_if_t<is_dummy_array_owner_v<detail::array_owner_type_t<ARRAY_TRAITS>>,
int> = 0>
648 void readWithTraits(BitStreamReader& reader, Vector<T, ALLOC>& rawArray,
size_t arrayLength = 0)
650 DummyArrayOwner owner;
651 readWithTraits<ARRAY_TYPE, ARRAY_TRAITS, T, ALLOC>(reader, rawArray, owner, arrayLength);
654 template <ArrayType ARRAY_TYPE,
typename T,
typename ARRAY_TRAITS>
655 void write(BitStreamWriter& writer,
const ArrayView<T, ARRAY_TRAITS>& array)
657 if constexpr (ARRAY_TYPE == ArrayType::AUTO || ARRAY_TYPE == ArrayType::ALIGNED_AUTO)
662 for (
size_t i = 0; i < array.size(); ++i)
664 if constexpr (ARRAY_TYPE == ArrayType::ALIGNED || ARRAY_TYPE == ArrayType::ALIGNED_AUTO)
669 write(writer, array[i]);
673 template <ArrayType ARRAY_TYPE,
typename T,
typename ARRAY_TRAITS>
674 BitSize bitSizeOfPacked(
const ArrayView<T, ARRAY_TRAITS>& array,
BitSize bitPosition = 0)
676 if constexpr (is_packable_v<T>)
680 static_assert(ARRAY_TYPE != ArrayType::IMPLICIT,
"Implicit array cannot be packed!");
682 BitSize endBitPosition = bitPosition;
684 const size_t arrayLength = array.size();
685 if constexpr (ARRAY_TYPE == ArrayType::AUTO || ARRAY_TYPE == ArrayType::ALIGNED_AUTO)
692 detail::packing_context_type_t<ValueType> context;
694 for (
size_t i = 0; i < arrayLength; ++i)
696 initContext(context, array[i]);
699 for (
size_t i = 0; i < arrayLength; ++i)
701 if constexpr (ARRAY_TYPE == ArrayType::ALIGNED || ARRAY_TYPE == ArrayType::ALIGNED_AUTO)
703 endBitPosition =
alignTo(8, endBitPosition);
706 endBitPosition += bitSizeOf(context, array[i], endBitPosition);
710 return endBitPosition - bitPosition;
714 return bitSizeOf<ARRAY_TYPE>(array, bitPosition);
718 template <ArrayType ARRAY_TYPE,
typename T,
typename ARRAY_TRAITS,
typename OFFSET_SETTER = DummyOffsetSetter>
719 BitSize initializeOffsetsPacked(
const ArrayView<T, ARRAY_TRAITS>& array,
BitSize bitPosition,
720 const OFFSET_SETTER& offsetSetter = OFFSET_SETTER())
722 if constexpr (is_packable_v<T>)
726 static_assert(ARRAY_TYPE != ArrayType::IMPLICIT,
"Implicit array cannot be packed!");
728 BitSize endBitPosition = bitPosition;
730 const size_t arrayLength = array.size();
731 if constexpr (ARRAY_TYPE == ArrayType::AUTO || ARRAY_TYPE == ArrayType::ALIGNED_AUTO)
738 detail::packing_context_type_t<ValueType> context;
740 for (
size_t i = 0; i < arrayLength; ++i)
742 initContext(context, array[i]);
745 for (
size_t i = 0; i < arrayLength; ++i)
747 if constexpr (ARRAY_TYPE == ArrayType::ALIGNED || ARRAY_TYPE == ArrayType::ALIGNED_AUTO)
749 endBitPosition =
alignTo(8, endBitPosition);
750 offsetSetter.setOffset(i, endBitPosition / 8);
754 decltype(std::declval<
const ArrayView<T, ARRAY_TRAITS>&>().at(std::declval<size_t>()));
755 if constexpr (std::is_same_v<View<ValueType>, AtResult>)
757 endBitPosition += initializeOffsets(context, array[i], endBitPosition);
761 endBitPosition += bitSizeOf(context, array[i], endBitPosition);
766 return endBitPosition - bitPosition;
770 return initializeOffsets<ARRAY_TYPE>(array, bitPosition, offsetSetter);
774 template <ArrayType ARRAY_TYPE,
typename T,
typename ARRAY_TRAITS>
775 void writePacked(BitStreamWriter& writer,
const ArrayView<T, ARRAY_TRAITS>& array)
777 if constexpr (is_packable_v<T>)
781 static_assert(ARRAY_TYPE != ArrayType::IMPLICIT,
"Implicit array cannot be packed!");
783 const size_t arrayLength = array.size();
784 if constexpr (ARRAY_TYPE == ArrayType::AUTO || ARRAY_TYPE == ArrayType::ALIGNED_AUTO)
791 detail::packing_context_type_t<ValueType> context;
793 for (
size_t i = 0; i < arrayLength; ++i)
795 initContext(context, array[i]);
798 for (
size_t i = 0; i < arrayLength; ++i)
800 if constexpr (ARRAY_TYPE == ArrayType::ALIGNED || ARRAY_TYPE == ArrayType::ALIGNED_AUTO)
805 write(context, writer, array[i]);
811 write<ARRAY_TYPE>(writer, array);
815 template <ArrayType ARRAY_TYPE,
typename T,
typename ALLOC,
typename ARRAY_TRAITS = ArrayTraits<T>>
816 void readPacked(BitStreamReader& reader, Vector<T, ALLOC>& rawArray,
817 detail::array_owner_type_t<ARRAY_TRAITS>& owner,
size_t arrayLength = 0)
819 if constexpr (is_packable_v<T>)
823 const size_t readLength = readArrayLength<ARRAY_TYPE, ARRAY_TRAITS>(reader, arrayLength);
826 size_t reserve = readLength;
827 if (reserve *
static_cast<uint64_t
>(
sizeof(T)) > reader.getMaxArrayPreallocation())
829 reserve = reader.getMaxArrayPreallocation() /
sizeof(T);
834 rawArray.reserve(reserve);
836 detail::packing_context_type_t<ValueType> context;
838 for (
size_t i = 0; i < readLength; ++i)
840 if constexpr (ARRAY_TYPE == ArrayType::ALIGNED || ARRAY_TYPE == ArrayType::ALIGNED_AUTO)
844 rawArray.emplace_back();
845 ARRAY_TRAITS::read(context, reader, owner, rawArray.back(), i);
851 read<ARRAY_TYPE, T, ALLOC, ARRAY_TRAITS>(reader, rawArray, owner, arrayLength);
855 template <ArrayType ARRAY_TYPE,
typename T,
typename ALLOC,
856 typename ARRAY_TRAITS = ArrayTraits<std::remove_cv_t<T>>,
857 std::enable_if_t<is_dummy_array_owner_v<detail::array_owner_type_t<ARRAY_TRAITS>>,
int> = 0>
858 void readPacked(BitStreamReader& reader, Vector<T, ALLOC>& rawArray,
size_t arrayLength = 0)
860 DummyArrayOwner owner;
861 readPacked<ARRAY_TYPE, T, ALLOC, ARRAY_TRAITS>(reader, rawArray, owner, arrayLength);
864 template <ArrayType ARRAY_TYPE,
typename ARRAY_TRAITS,
typename T,
typename ALLOC>
865 void readPackedWithTraits(BitStreamReader& reader, Vector<T, ALLOC>& rawArray,
866 detail::array_owner_type_t<ARRAY_TRAITS>& owner,
size_t arrayLength = 0)
868 readPacked<ARRAY_TYPE, T, ALLOC, ARRAY_TRAITS>(reader, rawArray, owner, arrayLength);
871 template <ArrayType ARRAY_TYPE,
typename ARRAY_TRAITS,
typename T,
typename ALLOC,
872 std::enable_if_t<is_dummy_array_owner_v<detail::array_owner_type_t<ARRAY_TRAITS>>,
int> = 0>
873 void readPackedWithTraits(BitStreamReader& reader, Vector<T, ALLOC>& rawArray,
size_t arrayLength = 0)
875 DummyArrayOwner owner;
876 readPackedWithTraits<ARRAY_TYPE, ARRAY_TRAITS, T, ALLOC>(reader, rawArray, owner, arrayLength);
881 template <
typename T,
typename ARRAY_TRAITS>
884 uint32_t result = seedValue;
885 for (
size_t i = 0; i < array.
size(); ++i)
bool operator<=(const ConstIterator &other) const
bool operator==(const ConstIterator &other) const
ConstIterator & operator++()
std::ptrdiff_t difference_type
ConstIterator operator++(int)
ConstIterator(const ArrayView *array, size_t index)
ConstIterator operator-(difference_type offset) const
value_type operator[](difference_type offset) const
ConstIterator & operator+=(difference_type offset)
friend ConstIterator operator+(difference_type offset, const ConstIterator &other)
bool operator>(const ConstIterator &other) const
ArrowHelper operator->() const
bool operator<(const ConstIterator &other) const
ConstIterator & operator--()
ConstIterator operator--(int)
difference_type operator-(const ConstIterator &other) const
value_type operator*() const
ConstIterator & operator-=(difference_type offset)
bool operator>=(const ConstIterator &other) const
decltype(std::declval< ArrayView >().at(std::declval< size_t >())) value_type
std::random_access_iterator_tag iterator_category
bool operator!=(const ConstIterator &other) const
ConstIterator operator+(difference_type offset) const
std::remove_cv_t< T > ValueType
ConstIterator begin() const noexcept
Span< T > zserioData() const
ArrayView(Span< T > data)
ConstReverseIterator crend() const noexcept
ConstIterator cend() const noexcept
bool operator>=(const ArrayView &other) const
ConstReverseIterator rend() const noexcept
std::reverse_iterator< ConstIterator > ConstReverseIterator
ConstIterator cbegin() const noexcept
ConstReverseIterator rbegin() const noexcept
bool operator==(const ArrayView &other) const
decltype(auto) front() const
ArrayView & operator=(ArrayView &&other)=default
bool operator>(const ArrayView &other) const
decltype(auto) back() const
ArrayView(const ArrayView &other)=default
ConstIterator end() const noexcept
ArrayView & operator=(const ArrayView &other)=default
bool operator<(const ArrayView &other) const
ArrayView(Span< T > data, const OwnerType &owner)
bool operator<=(const ArrayView &other) const
decltype(auto) at(size_t index) const
bool operator!=(const ArrayView &other) const
ConstReverseIterator crbegin() const noexcept
ArrayView(ArrayView &&other)=default
detail::array_owner_type_t< Traits > OwnerType
constexpr BitSize alignTo(BitSize alignmentValue, BitSize bitPosition)
uint32_t calcHashCode(uint32_t seedValue, const ArrayView< T, ARRAY_TRAITS > &array)
uint32_t convertSizeToUInt32(size_t value)
detail::VarIntWrapper< uint32_t, detail::VarIntType::VARSIZE > VarSize
value_type * operator->()