Browse Source

File this idea away.

Adam Ierymenko 5 years ago
parent
commit
afa01074c5
1 changed files with 176 additions and 0 deletions
  1. 176 0
      attic/BP.hpp

+ 176 - 0
attic/BP.hpp

@@ -0,0 +1,176 @@
+/*
+ * Copyright (c)2013-2020 ZeroTier, Inc.
+ *
+ * Use of this software is governed by the Business Source License included
+ * in the LICENSE.TXT file in the project's root directory.
+ *
+ * Change Date: 2024-01-01
+ *
+ * On the date above, in accordance with the Business Source License, use
+ * of this software will be governed by version 2.0 of the Apache License.
+ */
+/****/
+
+#ifndef ZT_BP_HPP
+#define ZT_BP_HPP
+
+#include "Constants.hpp"
+
+namespace ZeroTier {
+
+/**
+ * A C-like pointer to a byte array with static bounds checking whenever possible.
+ *
+ * This fills the niche in between Buf and a naked C pointer and behaves like a C pointer
+ * annotated with a length that is statically checked at compile time. It should have no
+ * runtime overhead at all.
+ *
+ * - Explicit or implicit casts are supported to pointers to smaller but not larger arrays
+ * - A templated slice() method (analogous to Go slices) allows getting subset arrays
+ * - A templated at() method allows bounds checked access to indices known at compile time
+ * - Copy and assignment from larger or equal sized arrays, but not smaller
+ * - NULL pointers are explicitly not allowed, so a naked pointer must still be used in that case
+ *
+ * Note that the [] operator for dynamic access is NOT bounds checked as this would add
+ * runtime overhead that is not desirable where this is used. The goal here is to keep
+ * C performance while being safer to the extent that C++ allows.
+ *
+ * @tparam S Size of memory to which this pointer must point
+ */
+template<unsigned int S>
+class BP
+{
+public:
+	typedef uint8_t * iterator;
+	typedef const uint8_t * const_iterator;
+
+	explicit ZT_INLINE BP(void *const bytes) : p(reinterpret_cast<uint8_t *>(bytes)) {}
+
+	template<unsigned int CS>
+	ZT_INLINE BP(BP<CS> &b) noexcept :
+		p(b.p)
+	{
+		static_assert(CS <= S,"attempt to copy byte pointer from one of smaller size");
+	}
+
+	template<unsigned int CS>
+	ZT_INLINE BP &operator=(BP<CS> &b)
+	{
+		static_assert(CS <= S,"attempt to assign byte pointer from one of smaller size");
+		p = b.p;
+		return *this;
+	}
+
+	template<unsigned int CS>
+	ZT_INLINE operator BP<CS>() noexcept // NOLINT(google-explicit-constructor,hicpp-explicit-conversions)
+	{
+		static_assert(CS <= S,"attempt to cast byte pointer to larger size");
+		return BP<CS>(p);
+	}
+
+	ZT_INLINE uint8_t &operator[](const unsigned int i) noexcept
+	{
+		return p[i];
+	}
+	ZT_INLINE uint8_t operator[](const unsigned int i) const noexcept
+	{
+		return p[i];
+	}
+	template<typename I>
+	ZT_INLINE uint8_t *operator+(const I i) noexcept
+	{
+		return p + i;
+	}
+	template<typename I>
+	ZT_INLINE const uint8_t *operator+(const I i) const noexcept
+	{
+		return p + i;
+	}
+
+	ZT_INLINE uint8_t &operator*() noexcept
+	{
+		static_assert(S > 0,"attempt to access empty array");
+		return *p;
+	}
+	ZT_INLINE uint8_t operator*() const noexcept
+	{
+		static_assert(S > 0,"attempt to access empty array");
+		return *p;
+	}
+
+	template<unsigned int I>
+	ZT_INLINE uint8_t &at() noexcept
+	{
+		static_assert(I < S,"static access beyond end of byte pointer");
+		return p[I];
+	}
+	template<unsigned int I>
+	ZT_INLINE uint8_t at() const noexcept
+	{
+		static_assert(I < S,"static access beyond end of byte pointer");
+		return p[I];
+	}
+
+	template<unsigned int RS,unsigned int RE>
+	ZT_INLINE BP<RE - RS> &slice() noexcept
+	{
+		static_assert(RE > RS,"slice must end after it begins");
+		static_assert(RE <= S,"slice ends after byte array end");
+		return reinterpret_cast< BP<RE - RS> >(*this);
+	}
+
+	template<unsigned int RS,unsigned int RE>
+	ZT_INLINE const BP<RE - RS> &slice() const noexcept
+	{
+		static_assert(RE > RS,"slice must end after it begins");
+		static_assert(RE <= S,"slice ends after byte array end");
+		return reinterpret_cast< BP<RE - RS> >(*this);
+	}
+
+	template<unsigned int F>
+	ZT_INLINE BP<S - F> &from() noexcept
+	{
+		static_assert(F < S,"attempt to get array from beyond bounds");
+		return reinterpret_cast< BP<S - F> >(*this);
+	}
+	template<unsigned int F>
+	ZT_INLINE const BP<S - F> &from() const noexcept
+	{
+		static_assert(F < S,"attempt to get array from beyond bounds");
+		return reinterpret_cast< BP<S - F> >(*this);
+	}
+
+	ZT_INLINE iterator begin() noexcept { return p; }
+	ZT_INLINE iterator end() noexcept { return p + S; }
+	ZT_INLINE const_iterator begin() const noexcept { return p; }
+	ZT_INLINE const_iterator end() const noexcept { return p + S; }
+
+	static constexpr unsigned int size() noexcept { return S; }
+
+	template<unsigned int CS>
+	ZT_INLINE bool operator==(const BP<CS> &b) const noexcept { return p == b.p; }
+	template<unsigned int CS>
+	ZT_INLINE bool operator!=(const BP<CS> &b) const noexcept { return p != b.p; }
+	template<unsigned int CS>
+	ZT_INLINE bool operator<(const BP<CS> &b) const noexcept { return p < b.p; }
+	template<unsigned int CS>
+	ZT_INLINE bool operator>(const BP<CS> &b) const noexcept { return p > b.p; }
+	template<unsigned int CS>
+	ZT_INLINE bool operator<=(const BP<CS> &b) const noexcept { return p <= b.p; }
+	template<unsigned int CS>
+	ZT_INLINE bool operator>=(const BP<CS> &b) const noexcept { return p >= b.p; }
+
+	ZT_INLINE bool operator==(const void *const b) const noexcept { return p == reinterpret_cast<const uint8_t *>(b); }
+	ZT_INLINE bool operator!=(const void *const b) const noexcept { return p != reinterpret_cast<const uint8_t *>(b); }
+	ZT_INLINE bool operator<(const void *const b) const noexcept { return p < reinterpret_cast<const uint8_t *>(b); }
+	ZT_INLINE bool operator>(const void *const b) const noexcept { return p > reinterpret_cast<const uint8_t *>(b); }
+	ZT_INLINE bool operator<=(const void *const b) const noexcept { return p <= reinterpret_cast<const uint8_t *>(b); }
+	ZT_INLINE bool operator>=(const void *const b) const noexcept { return p >= reinterpret_cast<const uint8_t *>(b); }
+
+private:
+	uint8_t *const p;
+};
+
+} // namespace ZeroTier
+
+#endif