#pragma once #include #include #include #include #include /** * `TArrayRef` works pretty much like `std::span` with dynamic extent, presenting * an array-like interface into a contiguous sequence of objects. * * It can be used at interface boundaries instead of `TVector` or * pointer-size pairs, and is actually a preferred way to pass contiguous data * into functions. * * Note that `TArrayRef` can be auto-constructed from any contiguous container * (with `size` and `data` members), and thus you don't have to change client code * when switching over from passing `TVector` to `TArrayRef`. * * Note that `TArrayRef` has the same const-semantics as raw pointers: * - `TArrayRef` is a non-const reference to non-const data (like `T*`); * - `TArrayRef` is a non-const reference to const data (like `const T*`); * - `const TArrayRef` is a const reference to non-const data (like `T* const`); * - `const TArrayRef` is a const reference to const data (like `const T* const`). */ template class TArrayRef { public: using iterator = T*; using const_iterator = const T*; using reference = T&; using const_reference = const T&; using value_type = T; using reverse_iterator = std::reverse_iterator; using const_reverse_iterator = std::reverse_iterator; constexpr inline TArrayRef() noexcept : T_(nullptr) , S_(0) { } constexpr inline TArrayRef(T* data Y_LIFETIME_BOUND, size_t len) noexcept : T_(data) , S_(len) { } constexpr inline TArrayRef(T* begin Y_LIFETIME_BOUND, T* end Y_LIFETIME_BOUND) noexcept : T_(begin) , S_(NonNegativeDistance(begin, end)) { } constexpr inline TArrayRef(std::initializer_list list Y_LIFETIME_BOUND) noexcept : T_(list.begin()) , S_(list.size()) { } template constexpr inline TArrayRef(Container&& container, decltype(std::declval() = container.data(), nullptr) = nullptr) noexcept : T_(container.data()) , S_(container.size()) { static_assert( sizeof(decltype(*container.data())) == sizeof(T), "Attempt to create TArrayRef from a container of elements with a different size"); } template constexpr inline TArrayRef(T (&array)[N] Y_LIFETIME_BOUND) noexcept : T_(array) , S_(N) { } template , std::remove_const_t>::value>> bool operator==(const TArrayRef& other) const { return (S_ == other.size()) && std::equal(begin(), end(), other.begin()); } constexpr inline T* data() const noexcept { return T_; } constexpr inline size_t size() const noexcept { return S_; } constexpr size_t size_bytes() const noexcept { return (size() * sizeof(T)); } constexpr inline bool empty() const noexcept { return (S_ == 0); } constexpr inline iterator begin() const noexcept { return T_; } constexpr inline iterator end() const noexcept { return (T_ + S_); } constexpr inline const_iterator cbegin() const noexcept { return T_; } constexpr inline const_iterator cend() const noexcept { return (T_ + S_); } constexpr inline reverse_iterator rbegin() const noexcept { return reverse_iterator(T_ + S_); } constexpr inline reverse_iterator rend() const noexcept { return reverse_iterator(T_); } constexpr inline const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(T_ + S_); } constexpr inline const_reverse_iterator crend() const noexcept { return const_reverse_iterator(T_); } constexpr inline reference front() const noexcept { Y_ASSERT(S_ > 0); return *T_; } inline reference back() const noexcept { Y_ASSERT(S_ > 0); return *(end() - 1); } inline reference operator[](size_t n) const noexcept { Y_ASSERT(n < S_); return *(T_ + n); } inline reference at(size_t n) const { if (n >= S_) { throw std::out_of_range("array ref range error"); } return (*this)[n]; } constexpr inline explicit operator bool() const noexcept { return (S_ > 0); } /** * Obtains a ref that is a view over the first `count` elements of this TArrayRef. * * The behavior is undefined if count > size(). */ TArrayRef first(size_t count) const { Y_ASSERT(count <= size()); return TArrayRef(data(), count); } /** * Obtains a ref that is a view over the last `count` elements of this TArrayRef. * * The behavior is undefined if count > size(). */ TArrayRef last(size_t count) const { Y_ASSERT(count <= size()); return TArrayRef(end() - count, end()); } /** * Obtains a ref that is a view over the `count` elements of this TArrayRef starting at `offset`. * * The behavior is undefined in either offset or count is out of range. */ TArrayRef subspan(size_t offset) const { Y_ASSERT(offset <= size()); return TArrayRef(data() + offset, size() - offset); } TArrayRef subspan(size_t offset, size_t count) const { Y_ASSERT(offset + count <= size()); return TArrayRef(data() + offset, count); } TArrayRef Slice(size_t offset) const { return subspan(offset); } TArrayRef Slice(size_t offset, size_t size) const { return subspan(offset, size); } /* FIXME: * This method is placed here for backward compatibility only and should be removed. * Keep in mind that it's behavior is different from Slice(): * SubRegion() never throws. It returns empty TArrayRef in case of invalid input. * * DEPRECATED. DO NOT USE. */ TArrayRef SubRegion(size_t offset, size_t size) const noexcept { if (size == 0 || offset >= S_) { return TArrayRef(); } if (size > S_ - offset) { size = S_ - offset; } return TArrayRef(T_ + offset, size); } constexpr inline yssize_t ysize() const noexcept { return static_cast(this->size()); } private: T* T_; size_t S_; }; /** * Obtains a view to the object representation of the elements of the TArrayRef arrayRef. * * Named as its std counterparts, std::as_bytes. */ template TArrayRef as_bytes(TArrayRef arrayRef Y_LIFETIME_BOUND) noexcept { return TArrayRef( reinterpret_cast(arrayRef.data()), arrayRef.size_bytes()); } /** * Obtains a view to the writable object representation of the elements of the TArrayRef arrayRef. * * Named as its std counterparts, std::as_writable_bytes. */ template TArrayRef as_writable_bytes(TArrayRef arrayRef Y_LIFETIME_BOUND) noexcept { return TArrayRef( reinterpret_cast(arrayRef.data()), arrayRef.size_bytes()); } template constexpr TArrayRef MakeArrayRef(const Range& range) noexcept { return TArrayRef(range); } template constexpr TArrayRef MakeArrayRef(Range& range) noexcept { return TArrayRef(range); } template constexpr TArrayRef MakeConstArrayRef(const Range& range) noexcept { return TArrayRef(range); } template constexpr TArrayRef MakeConstArrayRef(Range& range) noexcept { return TArrayRef(range); } template constexpr TArrayRef MakeArrayRef(T* data Y_LIFETIME_BOUND, size_t size) noexcept { return TArrayRef(data, size); } template constexpr TArrayRef MakeArrayRef(T* begin Y_LIFETIME_BOUND, T* end Y_LIFETIME_BOUND) noexcept { return TArrayRef(begin, end); }