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 rawArray.reserve(readLength);
604 for (
size_t i = 0; i < readLength; ++i)
606 if constexpr (ARRAY_TYPE == ArrayType::ALIGNED || ARRAY_TYPE == ArrayType::ALIGNED_AUTO)
610 rawArray.emplace_back();
611 ARRAY_TRAITS::read(reader, owner, rawArray.back(), i);
615 template <ArrayType ARRAY_TYPE,
typename T,
typename ALLOC,
616 std::enable_if_t<is_dummy_array_owner_v<detail::array_owner_type_t<ArrayTraits<T>>>,
int> = 0>
617 void read(BitStreamReader& reader, Vector<T, ALLOC>& rawArray,
size_t arrayLength = 0)
619 DummyArrayOwner owner;
620 read<ARRAY_TYPE, T, ALLOC>(reader, rawArray, owner, arrayLength);
623 template <ArrayType ARRAY_TYPE,
typename ARRAY_TRAITS,
typename T,
typename ALLOC>
624 void readWithTraits(BitStreamReader& reader, Vector<T, ALLOC>& rawArray,
625 detail::array_owner_type_t<ARRAY_TRAITS>& owner,
size_t arrayLength = 0)
627 read<ARRAY_TYPE, T, ALLOC, ARRAY_TRAITS>(reader, rawArray, owner, arrayLength);
630 template <ArrayType ARRAY_TYPE,
typename ARRAY_TRAITS,
typename T,
typename ALLOC,
631 std::enable_if_t<is_dummy_array_owner_v<detail::array_owner_type_t<ARRAY_TRAITS>>,
int> = 0>
632 void readWithTraits(BitStreamReader& reader, Vector<T, ALLOC>& rawArray,
size_t arrayLength = 0)
634 DummyArrayOwner owner;
635 readWithTraits<ARRAY_TYPE, ARRAY_TRAITS, T, ALLOC>(reader, rawArray, owner, arrayLength);
638 template <ArrayType ARRAY_TYPE,
typename T,
typename ARRAY_TRAITS>
639 void write(BitStreamWriter& writer,
const ArrayView<T, ARRAY_TRAITS>& array)
641 if constexpr (ARRAY_TYPE == ArrayType::AUTO || ARRAY_TYPE == ArrayType::ALIGNED_AUTO)
646 for (
size_t i = 0; i < array.size(); ++i)
648 if constexpr (ARRAY_TYPE == ArrayType::ALIGNED || ARRAY_TYPE == ArrayType::ALIGNED_AUTO)
653 write(writer, array[i]);
657 template <ArrayType ARRAY_TYPE,
typename T,
typename ARRAY_TRAITS>
658 BitSize bitSizeOfPacked(
const ArrayView<T, ARRAY_TRAITS>& array,
BitSize bitPosition = 0)
660 if constexpr (is_packable_v<T>)
664 static_assert(ARRAY_TYPE != ArrayType::IMPLICIT,
"Implicit array cannot be packed!");
666 BitSize endBitPosition = bitPosition;
668 const size_t arrayLength = array.size();
669 if constexpr (ARRAY_TYPE == ArrayType::AUTO || ARRAY_TYPE == ArrayType::ALIGNED_AUTO)
676 detail::packing_context_type_t<ValueType> context;
678 for (
size_t i = 0; i < arrayLength; ++i)
680 initContext(context, array[i]);
683 for (
size_t i = 0; i < arrayLength; ++i)
685 if constexpr (ARRAY_TYPE == ArrayType::ALIGNED || ARRAY_TYPE == ArrayType::ALIGNED_AUTO)
687 endBitPosition =
alignTo(8, endBitPosition);
690 endBitPosition += bitSizeOf(context, array[i], endBitPosition);
694 return endBitPosition - bitPosition;
698 return bitSizeOf<ARRAY_TYPE>(array, bitPosition);
702 template <ArrayType ARRAY_TYPE,
typename T,
typename ARRAY_TRAITS,
typename OFFSET_SETTER = DummyOffsetSetter>
703 BitSize initializeOffsetsPacked(
const ArrayView<T, ARRAY_TRAITS>& array,
BitSize bitPosition,
704 const OFFSET_SETTER& offsetSetter = OFFSET_SETTER())
706 if constexpr (is_packable_v<T>)
710 static_assert(ARRAY_TYPE != ArrayType::IMPLICIT,
"Implicit array cannot be packed!");
712 BitSize endBitPosition = bitPosition;
714 const size_t arrayLength = array.size();
715 if constexpr (ARRAY_TYPE == ArrayType::AUTO || ARRAY_TYPE == ArrayType::ALIGNED_AUTO)
722 detail::packing_context_type_t<ValueType> context;
724 for (
size_t i = 0; i < arrayLength; ++i)
726 initContext(context, array[i]);
729 for (
size_t i = 0; i < arrayLength; ++i)
731 if constexpr (ARRAY_TYPE == ArrayType::ALIGNED || ARRAY_TYPE == ArrayType::ALIGNED_AUTO)
733 endBitPosition =
alignTo(8, endBitPosition);
734 offsetSetter.setOffset(i, endBitPosition / 8);
738 decltype(std::declval<
const ArrayView<T, ARRAY_TRAITS>&>().at(std::declval<size_t>()));
739 if constexpr (std::is_same_v<View<ValueType>, AtResult>)
741 endBitPosition += initializeOffsets(context, array[i], endBitPosition);
745 endBitPosition += bitSizeOf(context, array[i], endBitPosition);
750 return endBitPosition - bitPosition;
754 return initializeOffsets<ARRAY_TYPE>(array, bitPosition, offsetSetter);
758 template <ArrayType ARRAY_TYPE,
typename T,
typename ARRAY_TRAITS>
759 void writePacked(BitStreamWriter& writer,
const ArrayView<T, ARRAY_TRAITS>& array)
761 if constexpr (is_packable_v<T>)
765 static_assert(ARRAY_TYPE != ArrayType::IMPLICIT,
"Implicit array cannot be packed!");
767 const size_t arrayLength = array.size();
768 if constexpr (ARRAY_TYPE == ArrayType::AUTO || ARRAY_TYPE == ArrayType::ALIGNED_AUTO)
775 detail::packing_context_type_t<ValueType> context;
777 for (
size_t i = 0; i < arrayLength; ++i)
779 initContext(context, array[i]);
782 for (
size_t i = 0; i < arrayLength; ++i)
784 if constexpr (ARRAY_TYPE == ArrayType::ALIGNED || ARRAY_TYPE == ArrayType::ALIGNED_AUTO)
789 write(context, writer, array[i]);
795 write<ARRAY_TYPE>(writer, array);
799 template <ArrayType ARRAY_TYPE,
typename T,
typename ALLOC,
typename ARRAY_TRAITS = ArrayTraits<T>>
800 void readPacked(BitStreamReader& reader, Vector<T, ALLOC>& rawArray,
801 detail::array_owner_type_t<ARRAY_TRAITS>& owner,
size_t arrayLength = 0)
803 if constexpr (is_packable_v<T>)
807 const size_t readLength = readArrayLength<ARRAY_TYPE, ARRAY_TRAITS>(reader, arrayLength);
812 rawArray.reserve(readLength);
814 detail::packing_context_type_t<ValueType> context;
816 for (
size_t i = 0; i < readLength; ++i)
818 if constexpr (ARRAY_TYPE == ArrayType::ALIGNED || ARRAY_TYPE == ArrayType::ALIGNED_AUTO)
822 rawArray.emplace_back();
823 ARRAY_TRAITS::read(context, reader, owner, rawArray.back(), i);
829 read<ARRAY_TYPE, T, ALLOC, ARRAY_TRAITS>(reader, rawArray, owner, arrayLength);
833 template <ArrayType ARRAY_TYPE,
typename T,
typename ALLOC,
834 typename ARRAY_TRAITS = ArrayTraits<std::remove_cv_t<T>>,
835 std::enable_if_t<is_dummy_array_owner_v<detail::array_owner_type_t<ARRAY_TRAITS>>,
int> = 0>
836 void readPacked(BitStreamReader& reader, Vector<T, ALLOC>& rawArray,
size_t arrayLength = 0)
838 DummyArrayOwner owner;
839 readPacked<ARRAY_TYPE, T, ALLOC, ARRAY_TRAITS>(reader, rawArray, owner, arrayLength);
842 template <ArrayType ARRAY_TYPE,
typename ARRAY_TRAITS,
typename T,
typename ALLOC>
843 void readPackedWithTraits(BitStreamReader& reader, Vector<T, ALLOC>& rawArray,
844 detail::array_owner_type_t<ARRAY_TRAITS>& owner,
size_t arrayLength = 0)
846 readPacked<ARRAY_TYPE, T, ALLOC, ARRAY_TRAITS>(reader, rawArray, owner, arrayLength);
849 template <ArrayType ARRAY_TYPE,
typename ARRAY_TRAITS,
typename T,
typename ALLOC,
850 std::enable_if_t<is_dummy_array_owner_v<detail::array_owner_type_t<ARRAY_TRAITS>>,
int> = 0>
851 void readPackedWithTraits(BitStreamReader& reader, Vector<T, ALLOC>& rawArray,
size_t arrayLength = 0)
853 DummyArrayOwner owner;
854 readPackedWithTraits<ARRAY_TYPE, ARRAY_TRAITS, T, ALLOC>(reader, rawArray, owner, arrayLength);
859 template <
typename T,
typename ARRAY_TRAITS>
862 uint32_t result = seedValue;
863 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->()