aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/yt/memory/range.h
diff options
context:
space:
mode:
Diffstat (limited to 'library/cpp/yt/memory/range.h')
-rw-r--r--library/cpp/yt/memory/range.h556
1 files changed, 556 insertions, 0 deletions
diff --git a/library/cpp/yt/memory/range.h b/library/cpp/yt/memory/range.h
new file mode 100644
index 0000000000..6c71aa9496
--- /dev/null
+++ b/library/cpp/yt/memory/range.h
@@ -0,0 +1,556 @@
+#pragma once
+
+#include <library/cpp/yt/assert/assert.h>
+
+#include <library/cpp/yt/misc/hash.h>
+
+#include <vector>
+#include <array>
+#include <optional>
+#include <initializer_list>
+
+// For size_t.
+#include <stddef.h>
+
+namespace google::protobuf {
+
+////////////////////////////////////////////////////////////////////////////////
+// Forward declarations
+
+template <class T>
+class RepeatedField;
+
+template <class T>
+class RepeatedPtrField;
+
+////////////////////////////////////////////////////////////////////////////////
+
+} // namespace google::protobuf
+
+namespace NYT {
+
+////////////////////////////////////////////////////////////////////////////////
+// Forward declarations
+
+template <class T, size_t N>
+class TCompactVector;
+
+////////////////////////////////////////////////////////////////////////////////
+
+//! TRange (inspired by TArrayRef from LLVM)
+/*!
+ * Represents a constant reference to an array (zero or more elements
+ * consecutively in memory), i. e. a start pointer and a length. It allows
+ * various APIs to take consecutive elements easily and conveniently.
+ *
+ * This class does not own the underlying data, it is expected to be used in
+ * situations where the data resides in some other buffer, whose lifetime
+ * extends past that of the TRange. For this reason, it is not in general
+ * safe to store an TRange.
+ *
+ * This is intended to be trivially copyable, so it should be passed by
+ * value.
+ */
+template <class T>
+class TRange
+{
+public:
+ typedef const T* iterator;
+ typedef const T* const_iterator;
+ typedef size_t size_type;
+
+ //! Constructs a null TRange.
+ TRange()
+ : Data_(nullptr)
+ , Length_(0)
+ { }
+
+ //! Constructs a TRange from a pointer and length.
+ TRange(const T* data, size_t length)
+ : Data_(data)
+ , Length_(length)
+ { }
+
+ //! Constructs a TRange from a range.
+ TRange(const T* begin, const T* end)
+ : Data_(begin)
+ , Length_(end - begin)
+ { }
+
+ //! Constructs a TRange from a TCompactVector.
+ template <size_t N>
+ TRange(const TCompactVector<T, N>& elements)
+ : Data_(elements.data())
+ , Length_(elements.size())
+ { }
+
+ //! Constructs a TRange from an std::vector.
+ template <class A>
+ TRange(const std::vector<T, A>& elements)
+ : Data_(elements.empty() ? nullptr : elements.data())
+ , Length_(elements.size())
+ { }
+
+ //! Constructs a TRange from a C array.
+ template <size_t N>
+ TRange(const T (&elements)[N])
+ : Data_(elements)
+ , Length_(N)
+ { }
+
+ //! Constructs a TRange from std::initializer_list.
+ TRange(std::initializer_list<T> elements)
+ : Data_(elements.begin())
+ , Length_(elements.size())
+ { }
+
+ //! Constructs a TRange from std::array.
+ template <size_t N>
+ TRange(const std::array<T, N>& elements)
+ : Data_(elements.data())
+ , Length_(N)
+ { }
+
+ //! Constructs a TRange from std::optional.
+ //! Range will contain 0-1 elements.
+ explicit TRange(const std::optional<T>& element)
+ : Data_(element ? &*element : nullptr)
+ , Length_(element ? 1 : 0)
+ { }
+
+ const_iterator Begin() const
+ {
+ return Data_;
+ }
+
+ // STL interop, for gcc.
+ const_iterator begin() const
+ {
+ return Begin();
+ }
+
+ const_iterator End() const
+ {
+ return Data_ + Length_;
+ }
+
+ // STL interop, for gcc.
+ const_iterator end() const
+ {
+ return End();
+ }
+
+ bool Empty() const
+ {
+ return Length_ == 0;
+ }
+
+ bool empty() const
+ {
+ return Empty();
+ }
+
+ explicit operator bool() const
+ {
+ return Data_ != nullptr;
+ }
+
+ size_t Size() const
+ {
+ return Length_;
+ }
+
+ size_t size() const
+ {
+ return Size();
+ }
+
+ const T& operator[](size_t index) const
+ {
+ YT_ASSERT(index < Size());
+ return Data_[index];
+ }
+
+
+ const T& Front() const
+ {
+ YT_ASSERT(Length_ > 0);
+ return Data_[0];
+ }
+
+ const T& Back() const
+ {
+ YT_ASSERT(Length_ > 0);
+ return Data_[Length_ - 1];
+ }
+
+
+ TRange<T> Slice(size_t startOffset, size_t endOffset) const
+ {
+ YT_ASSERT(startOffset <= endOffset && endOffset <= Size());
+ return TRange<T>(Begin() + startOffset, endOffset - startOffset);
+ }
+
+ std::vector<T> ToVector() const
+ {
+ return std::vector<T>(Data_, Data_ + Length_);
+ }
+
+protected:
+ //! The start of the array, in an external buffer.
+ const T* Data_;
+
+ //! The number of elements.
+ size_t Length_;
+
+};
+
+// STL interop.
+template <class T>
+typename TRange<T>::const_iterator begin(TRange<T> ref)
+{
+ return ref.Begin();
+}
+
+template <class T>
+typename TRange<T>::const_iterator end(TRange<T> ref)
+{
+ return ref.End();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+//! Constructs a TRange from a pointer and length.
+template <class T>
+TRange<T> MakeRange(const T* data, size_t length)
+{
+ return TRange<T>(data, length);
+}
+
+//! Constructs a TRange from a native range.
+template <class T>
+TRange<T> MakeRange(const T* begin, const T* end)
+{
+ return TRange<T>(begin, end);
+}
+
+//! Constructs a TRange from a TCompactVector.
+template <class T, size_t N>
+TRange<T> MakeRange(const TCompactVector<T, N>& elements)
+{
+ return elements;
+}
+
+//! "Copy-constructor".
+template <class T>
+TRange<T> MakeRange(TRange<T> range)
+{
+ return range;
+}
+
+//! Constructs a TRange from an std::vector.
+template <class T>
+TRange<T> MakeRange(const std::vector<T>& elements)
+{
+ return elements;
+}
+
+//! Constructs a TRange from an std::array.
+template <class T, size_t N>
+TRange<T> MakeRange(const std::array<T, N>& elements)
+{
+ return elements;
+}
+
+//! Constructs a TRange from a C array.
+template <class T, size_t N>
+TRange<T> MakeRange(const T (& elements)[N])
+{
+ return TRange<T>(elements);
+}
+
+//! Constructs a TRange from RepeatedField.
+template <class T>
+TRange<T> MakeRange(const google::protobuf::RepeatedField<T>& elements)
+{
+ return TRange<T>(elements.data(), elements.size());
+}
+
+//! Constructs a TRange from RepeatedPtrField.
+template <class T>
+TRange<const T*> MakeRange(const google::protobuf::RepeatedPtrField<T>& elements)
+{
+ return TRange<const T*>(elements.data(), elements.size());
+}
+
+template <class U, class T>
+TRange<U> ReinterpretCastRange(TRange<T> range)
+{
+ static_assert(sizeof(T) == sizeof(U), "T and U must have equal sizes.");
+ return TRange<U>(reinterpret_cast<const U*>(range.Begin()), range.Size());
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+// TMutableRange (inspired by TMutableArrayRef from LLVM)
+/*
+ * Represents a mutable reference to an array (zero or more elements
+ * consecutively in memory), i. e. a start pointer and a length.
+ * It allows various APIs to take and modify consecutive elements easily and
+ * conveniently.
+ *
+ * This class does not own the underlying data, it is expected to be used in
+ * situations where the data resides in some other buffer, whose lifetime
+ * extends past that of the TMutableRange. For this reason, it is not in
+ * general safe to store a TMutableRange.
+ *
+ * This is intended to be trivially copyable, so it should be passed by value.
+ */
+template <class T>
+class TMutableRange
+ : public TRange<T>
+{
+public:
+ typedef T* iterator;
+
+ //! Constructs a null TMutableRange.
+ TMutableRange()
+ { }
+
+ //! Constructs a TMutableRange from a pointer and length.
+ TMutableRange(T* data, size_t length)
+ : TRange<T>(data, length)
+ { }
+
+ //! Constructs a TMutableRange from a range.
+ TMutableRange(T* begin, T* end)
+ : TRange<T>(begin, end)
+ { }
+
+ //! Constructs a TMutableRange from a TCompactVector.
+ template <size_t N>
+ TMutableRange(TCompactVector<T, N>& elements)
+ : TRange<T>(elements)
+ { }
+
+ //! Constructs a TMutableRange from an std::vector.
+ TMutableRange(std::vector<T>& elements)
+ : TRange<T>(elements)
+ { }
+
+ //! Constructs a TMutableRange from std::array.
+ template <size_t N>
+ TMutableRange(std::array<T, N>& elements)
+ : TRange<T>(elements.data(), N)
+ { }
+
+ //! Construct a TMutableRange from an std::optional
+ //! Range will contain 0-1 elements.
+ explicit TMutableRange(std::optional<T>& optional)
+ : TRange<T>(optional)
+ { }
+
+ //! Constructs a TMutableRange from a C array.
+ template <size_t N>
+ TMutableRange(T (& elements)[N])
+ : TRange<T>(elements)
+ { }
+
+ using TRange<T>::Begin;
+ using TRange<T>::End;
+ using TRange<T>::Front;
+ using TRange<T>::Back;
+ using TRange<T>::operator[];
+
+ iterator Begin() const
+ {
+ return const_cast<T*>(this->Data_);
+ }
+
+ // STL interop, for gcc.
+ iterator begin() const
+ {
+ return Begin();
+ }
+
+ iterator End() const
+ {
+ return this->Begin() + this->Size();
+ }
+
+ // STL interop, for gcc.
+ iterator end() const
+ {
+ return End();
+ }
+
+ T& operator[](size_t index)
+ {
+ YT_ASSERT(index <= this->Size());
+ return Begin()[index];
+ }
+
+ T& Front()
+ {
+ YT_ASSERT(this->Length_ > 0);
+ return Begin()[0];
+ }
+
+ T& Back()
+ {
+ YT_ASSERT(this->Length_ > 0);
+ return Begin()[this->Length_ - 1];
+ }
+
+ TMutableRange<T> Slice(size_t startOffset, size_t endOffset) const
+ {
+ YT_ASSERT(startOffset <= endOffset && endOffset <= this->Size());
+ return TMutableRange<T>(Begin() + startOffset, endOffset - startOffset);
+ }
+
+ TMutableRange<T> Slice(T* begin, T* end) const
+ {
+ YT_ASSERT(begin >= Begin());
+ YT_ASSERT(end <= End());
+ return TMutableRange<T>(begin, end);
+ }
+};
+
+// STL interop.
+template <class T>
+typename TMutableRange<T>::iterator begin(TMutableRange<T> ref)
+{
+ return ref.Begin();
+}
+
+template <class T>
+typename TMutableRange<T>::iterator end(TMutableRange<T> ref)
+{
+ return ref.End();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+//! Constructs a TMutableRange from a pointer and length.
+template <class T>
+TMutableRange<T> MakeMutableRange(T* data, size_t length)
+{
+ return TMutableRange<T>(data, length);
+}
+
+//! Constructs a TMutableRange from a native range.
+template <class T>
+TMutableRange<T> MakeMutableRange(T* begin, T* end)
+{
+ return TMutableRange<T>(begin, end);
+}
+
+//! Constructs a TMutableRange from a TCompactVector.
+template <class T, size_t N>
+TMutableRange<T> MakeMutableRange(TCompactVector<T, N>& elements)
+{
+ return elements;
+}
+
+//! "Copy-constructor".
+template <class T>
+TMutableRange<T> MakeMutableRange(TMutableRange<T> range)
+{
+ return range;
+}
+
+//! Constructs a TMutableRange from an std::vector.
+template <class T>
+TMutableRange<T> MakeMutableRange(std::vector<T>& elements)
+{
+ return elements;
+}
+
+//! Constructs a TMutableRange from an std::array.
+template <class T, size_t N>
+TMutableRange<T> MakeMutableRange(std::array<T, N>& elements)
+{
+ return elements;
+}
+
+//! Constructs a TMutableRange from a C array.
+template <class T, size_t N>
+TMutableRange<T> MakeMutableRange(T (& elements)[N])
+{
+ return TMutableRange<T>(elements);
+}
+
+//! Constructs a TMutableRange from RepeatedField.
+template <class T>
+TMutableRange<T> MakeMutableRange(google::protobuf::RepeatedField<T>& elements)
+{
+ return TMutableRange<T>(elements.data(), elements.size());
+}
+
+//! Constructs a TMutableRange from RepeatedPtrField.
+template <class T>
+TMutableRange<T*> MakeMutableRange(google::protobuf::RepeatedPtrField<T>& elements)
+{
+ return TMutableRange<const T*>(elements.data(), elements.size());
+}
+
+template <class U, class T>
+TMutableRange<U> ReinterpretCastMutableRange(TMutableRange<T> range)
+{
+ static_assert(sizeof(T) == sizeof(U), "T and U must have equal sizes.");
+ return TMutableRange<U>(reinterpret_cast<U*>(range.Begin()), range.Size());
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+// Mark TMutableRange and TMutableRange as PODs.
+namespace NMpl {
+
+template <class T>
+struct TIsPod;
+
+template <class T>
+struct TIsPod<TRange<T>>
+{
+ static const bool Value = true;
+};
+
+template <class T>
+struct TIsPod<TMutableRange<T>>
+{
+ static const bool Value = true;
+};
+
+} // namespace NMpl
+
+////////////////////////////////////////////////////////////////////////////////
+
+} // namespace NYT
+
+template <class T>
+struct hash<NYT::TRange<T>>
+{
+ size_t operator()(const NYT::TRange<T>& range) const
+ {
+ size_t result = 0;
+ for (const auto& element : range) {
+ NYT::HashCombine(result, element);
+ }
+ return result;
+ }
+};
+
+template <class T>
+struct hash<NYT::TMutableRange<T>>
+{
+ size_t operator()(const NYT::TMutableRange<T>& range) const
+ {
+ size_t result = 0;
+ for (const auto& element : range) {
+ NYT::HashCombine(result, element);
+ }
+ return result;
+ }
+};
+
+