1#ifndef ZSERIO_ARRAY_H_INC
2#define ZSERIO_ARRAY_H_INC
33template <
typename T,
typename ARRAY_TRAITS = ArrayTraits<std::remove_cv_t<T>>>
54 using OwnerType = detail::array_owner_type_t<Traits>;
62 std::enable_if_t<detail::is_dummy_array_owner_v<OWNER_TYPE_>,
int> = 0>
74 std::enable_if_t<!detail::is_dummy_array_owner_v<OWNER_TYPE_>,
int> = 0>
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));
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);
495template <ArrayType ARRAY_TYPE,
typename T,
typename ARRAY_TRAITS>
496void 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);
515template <ArrayType ARRAY_TYPE,
typename T,
typename ARRAY_TRAITS>
516BitSize 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;
538struct DummyOffsetSetter
540 static void setOffset(
size_t ,
BitSize )
544template <ArrayType ARRAY_TYPE,
typename T,
typename ARRAY_TRAITS,
typename OFFSET_SETTER = DummyOffsetSetter>
545BitSize 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;
579template <ArrayType ARRAY_TYPE,
typename ARRAY_TRAITS>
580size_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();
597template <ArrayType ARRAY_TYPE,
typename T,
typename ALLOC,
typename ARRAY_TRAITS = ArrayTraits<T>>
598void 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);
631template <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>
633void read(BitStreamReader& reader, Vector<T, ALLOC>& rawArray,
size_t arrayLength = 0)
635 DummyArrayOwner owner;
636 read<ARRAY_TYPE, T, ALLOC>(reader, rawArray, owner, arrayLength);
639template <ArrayType ARRAY_TYPE,
typename ARRAY_TRAITS,
typename T,
typename ALLOC>
640void 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);
646template <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>
648void 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);
654template <ArrayType ARRAY_TYPE,
typename T,
typename ARRAY_TRAITS>
655void 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]);
673template <ArrayType ARRAY_TYPE,
typename T,
typename ARRAY_TRAITS>
674BitSize 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);
718template <ArrayType ARRAY_TYPE,
typename T,
typename ARRAY_TRAITS,
typename OFFSET_SETTER = DummyOffsetSetter>
719BitSize 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);
774template <ArrayType ARRAY_TYPE,
typename T,
typename ARRAY_TRAITS>
775void 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);
815template <ArrayType ARRAY_TYPE,
typename T,
typename ALLOC,
typename ARRAY_TRAITS = ArrayTraits<T>>
816void 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);
855template <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>
858void 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);
864template <ArrayType ARRAY_TYPE,
typename ARRAY_TRAITS,
typename T,
typename ALLOC>
865void 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);
871template <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>
873void 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);
881template <
typename T,
typename ARRAY_TRAITS>
885 for (
size_t i = 0;
i <
array.size(); ++
i)
bool operator<=(const ConstIterator &other) const
bool operator==(const ConstIterator &other) const
std::ptrdiff_t difference_type
ConstIterator & operator--()
ConstIterator operator++(int)
ConstIterator(const ArrayView *array, size_t index)
ConstIterator operator-(difference_type offset) const
value_type operator[](difference_type offset) const
friend ConstIterator operator+(difference_type offset, const ConstIterator &other)
bool operator>(const ConstIterator &other) const
ConstIterator & operator+=(difference_type offset)
ArrowHelper operator->() const
bool operator<(const ConstIterator &other) const
ConstIterator & operator++()
ConstIterator & operator-=(difference_type offset)
ConstIterator operator--(int)
difference_type operator-(const ConstIterator &other) const
value_type operator*() const
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
ArrayView & operator=(ArrayView &&other)=default
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=(const ArrayView &other)=default
bool operator>(const ArrayView &other) const
decltype(auto) back() const
ArrayView(const ArrayView &other)=default
ConstIterator end() const noexcept
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->()