File this idea away.

This commit is contained in:
Adam Ierymenko 2020-03-31 11:03:02 -07:00
parent 1f85b0402e
commit afa01074c5
No known key found for this signature in database
GPG key ID: C8877CF2D7A5D7F3

176
attic/BP.hpp Normal file
View file

@ -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