From afa01074c57da3230d7940b6304d3bd697449ba7 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Tue, 31 Mar 2020 11:03:02 -0700 Subject: [PATCH] File this idea away. --- attic/BP.hpp | 176 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 176 insertions(+) create mode 100644 attic/BP.hpp diff --git a/attic/BP.hpp b/attic/BP.hpp new file mode 100644 index 000000000..3e71bd525 --- /dev/null +++ b/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 +class BP +{ +public: + typedef uint8_t * iterator; + typedef const uint8_t * const_iterator; + + explicit ZT_INLINE BP(void *const bytes) : p(reinterpret_cast(bytes)) {} + + template + ZT_INLINE BP(BP &b) noexcept : + p(b.p) + { + static_assert(CS <= S,"attempt to copy byte pointer from one of smaller size"); + } + + template + ZT_INLINE BP &operator=(BP &b) + { + static_assert(CS <= S,"attempt to assign byte pointer from one of smaller size"); + p = b.p; + return *this; + } + + template + ZT_INLINE operator BP() noexcept // NOLINT(google-explicit-constructor,hicpp-explicit-conversions) + { + static_assert(CS <= S,"attempt to cast byte pointer to larger size"); + return BP(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 + ZT_INLINE uint8_t *operator+(const I i) noexcept + { + return p + i; + } + template + 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 + ZT_INLINE uint8_t &at() noexcept + { + static_assert(I < S,"static access beyond end of byte pointer"); + return p[I]; + } + template + ZT_INLINE uint8_t at() const noexcept + { + static_assert(I < S,"static access beyond end of byte pointer"); + return p[I]; + } + + template + ZT_INLINE BP &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 >(*this); + } + + template + ZT_INLINE const BP &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 >(*this); + } + + template + ZT_INLINE BP &from() noexcept + { + static_assert(F < S,"attempt to get array from beyond bounds"); + return reinterpret_cast< BP >(*this); + } + template + ZT_INLINE const BP &from() const noexcept + { + static_assert(F < S,"attempt to get array from beyond bounds"); + return reinterpret_cast< BP >(*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 + ZT_INLINE bool operator==(const BP &b) const noexcept { return p == b.p; } + template + ZT_INLINE bool operator!=(const BP &b) const noexcept { return p != b.p; } + template + ZT_INLINE bool operator<(const BP &b) const noexcept { return p < b.p; } + template + ZT_INLINE bool operator>(const BP &b) const noexcept { return p > b.p; } + template + ZT_INLINE bool operator<=(const BP &b) const noexcept { return p <= b.p; } + template + ZT_INLINE bool operator>=(const BP &b) const noexcept { return p >= b.p; } + + ZT_INLINE bool operator==(const void *const b) const noexcept { return p == reinterpret_cast(b); } + ZT_INLINE bool operator!=(const void *const b) const noexcept { return p != reinterpret_cast(b); } + ZT_INLINE bool operator<(const void *const b) const noexcept { return p < reinterpret_cast(b); } + ZT_INLINE bool operator>(const void *const b) const noexcept { return p > reinterpret_cast(b); } + ZT_INLINE bool operator<=(const void *const b) const noexcept { return p <= reinterpret_cast(b); } + ZT_INLINE bool operator>=(const void *const b) const noexcept { return p >= reinterpret_cast(b); } + +private: + uint8_t *const p; +}; + +} // namespace ZeroTier + +#endif