all: assorted cleanups and updates
Changes include: - add a bunch of "noexcept", mostly to operators and forceinline - use "uchar" - use "charptr" - rename options_t to Options - add ptr_check_no_overlap() - rewrite p_exe.cpp, NFCI - clang-format help.cpp - spelling fixes
This commit is contained in:
+365
-334
@@ -28,165 +28,176 @@
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
public:
|
||||
typedef T element_type;
|
||||
typedef typename std::add_lvalue_reference<T>::type reference;
|
||||
typedef typename std::add_pointer<T>::type pointer;
|
||||
typedef size_t size_type;
|
||||
#if CLANG_FORMAT_DUMMY_CLASS
|
||||
class CSelf {
|
||||
#endif
|
||||
|
||||
// befriend all
|
||||
template <class>
|
||||
friend struct PtrOrSpan;
|
||||
template <class>
|
||||
friend struct PtrOrSpanOrNull;
|
||||
template <class>
|
||||
friend struct Span;
|
||||
public:
|
||||
typedef T element_type;
|
||||
typedef typename std::add_lvalue_reference<T>::type reference;
|
||||
typedef typename std::add_pointer<T>::type pointer;
|
||||
typedef size_t size_type;
|
||||
|
||||
// befriend all
|
||||
template <class>
|
||||
friend struct PtrOrSpan;
|
||||
template <class>
|
||||
friend struct PtrOrSpanOrNull;
|
||||
template <class>
|
||||
friend struct Span;
|
||||
|
||||
#if XSPAN_CONFIG_ENABLE_IMPLICIT_CONVERSION
|
||||
operator pointer() const { return ptr; }
|
||||
public:
|
||||
operator pointer() const noexcept { return ptr; }
|
||||
#endif
|
||||
|
||||
private:
|
||||
pointer ptr; // current view into (base, base+size_in_bytes) iff base != nullptr
|
||||
pointer base;
|
||||
size_type size_in_bytes;
|
||||
pointer ptr; // current view into (base, base+size_in_bytes) iff base != nullptr
|
||||
pointer base;
|
||||
size_type size_in_bytes;
|
||||
|
||||
// debug - internal sanity check; also serves as pseudo-documentation
|
||||
#if DEBUG
|
||||
noinline void assertInvariants() const {
|
||||
if __acc_cte (configRequirePtr)
|
||||
assert(ptr != nullptr);
|
||||
if __acc_cte (configRequireBase)
|
||||
assert(base != nullptr);
|
||||
if __acc_cte ((configRequirePtr || ptr != nullptr) && (configRequireBase || base != nullptr))
|
||||
xspan_check_range(ptr, base, size_in_bytes);
|
||||
}
|
||||
noinline void assertInvariants() const {
|
||||
if __acc_cte (configRequirePtr)
|
||||
assert(ptr != nullptr);
|
||||
if __acc_cte (configRequireBase)
|
||||
assert(base != nullptr);
|
||||
if __acc_cte ((configRequirePtr || ptr != nullptr) &&
|
||||
(configRequireBase || base != nullptr))
|
||||
xspan_check_range(ptr, base, size_in_bytes);
|
||||
}
|
||||
#else
|
||||
forceinline void assertInvariants() const {}
|
||||
inline void assertInvariants() const noexcept {}
|
||||
#endif
|
||||
|
||||
static forceinline pointer makeNotNull(pointer p) {
|
||||
if very_unlikely (p == nullptr)
|
||||
xspan_fail_nullptr();
|
||||
return p;
|
||||
}
|
||||
// enforce config invariants at constructor time - static functions
|
||||
static forceinline pointer makePtr(pointer p) {
|
||||
if __acc_cte (configRequirePtr && p == nullptr)
|
||||
xspan_fail_nullptr();
|
||||
return p;
|
||||
}
|
||||
static forceinline pointer makeBase(pointer b) {
|
||||
if __acc_cte (configRequireBase && b == nullptr)
|
||||
xspan_fail_nullbase();
|
||||
return b;
|
||||
}
|
||||
// inverse logic for ensuring valid pointers from existing objets
|
||||
forceinline pointer ensurePtr() const {
|
||||
if __acc_cte (!configRequirePtr && ptr == nullptr)
|
||||
xspan_fail_nullptr();
|
||||
return ptr;
|
||||
}
|
||||
forceinline pointer ensureBase() const {
|
||||
if __acc_cte (!configRequireBase && base == nullptr)
|
||||
xspan_fail_nullbase();
|
||||
return base;
|
||||
}
|
||||
static inline pointer makeNotNull(pointer p) {
|
||||
if very_unlikely (p == nullptr)
|
||||
xspan_fail_nullptr();
|
||||
return p;
|
||||
}
|
||||
// enforce config invariants at constructor time - static functions
|
||||
static inline pointer makePtr(pointer p) {
|
||||
if __acc_cte (configRequirePtr && p == nullptr)
|
||||
xspan_fail_nullptr();
|
||||
return p;
|
||||
}
|
||||
static inline pointer makeBase(pointer b) {
|
||||
if __acc_cte (configRequireBase && b == nullptr)
|
||||
xspan_fail_nullbase();
|
||||
return b;
|
||||
}
|
||||
// inverse logic for ensuring valid pointers from existing objects
|
||||
inline pointer ensurePtr() const {
|
||||
if __acc_cte (!configRequirePtr && ptr == nullptr)
|
||||
xspan_fail_nullptr();
|
||||
return ptr;
|
||||
}
|
||||
inline pointer ensureBase() const {
|
||||
if __acc_cte (!configRequireBase && base == nullptr)
|
||||
xspan_fail_nullbase();
|
||||
return base;
|
||||
}
|
||||
|
||||
public:
|
||||
inline ~CSelf() {
|
||||
#if DEBUG
|
||||
invalidate();
|
||||
inline ~CSelf() { invalidate(); }
|
||||
#else
|
||||
inline ~CSelf() noexcept {}
|
||||
#endif
|
||||
}
|
||||
noinline void invalidate() {
|
||||
assertInvariants();
|
||||
ptr = (pointer) (acc_uintptr_t) 16; // point to non-null invalid address
|
||||
// ptr = (pointer) (void *) &ptr; // point to self
|
||||
base = ptr;
|
||||
size_in_bytes = 0;
|
||||
assertInvariants();
|
||||
}
|
||||
// constructors from pointers
|
||||
CSelf(pointer first, XSpanCount count)
|
||||
: ptr(makePtr(first)), base(makeBase(first)), size_in_bytes(xspan_mem_size<T>(count.count)) {
|
||||
assertInvariants();
|
||||
}
|
||||
CSelf(pointer first, XSpanSizeInBytes bytes)
|
||||
: ptr(makePtr(first)), base(makeBase(first)),
|
||||
size_in_bytes(xspan_mem_size<char>(bytes.size_in_bytes)) {
|
||||
assertInvariants();
|
||||
}
|
||||
// enable this constructor only if the underlying type is char or void
|
||||
template <class U>
|
||||
CSelf(U *first, size_type count, XSPAN_REQUIRES_SIZE_1_A)
|
||||
: ptr(makePtr(first)), base(makeBase(first)), size_in_bytes(xspan_mem_size<T>(count)) {
|
||||
assertInvariants();
|
||||
}
|
||||
CSelf(pointer first, XSpanCount count, pointer base_)
|
||||
: ptr(makePtr(first)), base(makeBase(base_)), size_in_bytes(xspan_mem_size<T>(count.count)) {
|
||||
// check invariants
|
||||
if __acc_cte ((configRequirePtr || ptr != nullptr) && (configRequireBase || base != nullptr))
|
||||
xspan_check_range(ptr, base, size_in_bytes);
|
||||
// double sanity check
|
||||
assertInvariants();
|
||||
}
|
||||
CSelf(pointer first, XSpanSizeInBytes bytes, pointer base_)
|
||||
: ptr(makePtr(first)), base(makeBase(base_)),
|
||||
size_in_bytes(xspan_mem_size<char>(bytes.size_in_bytes)) {
|
||||
// check invariants
|
||||
if __acc_cte ((configRequirePtr || ptr != nullptr) && (configRequireBase || base != nullptr))
|
||||
xspan_check_range(ptr, base, size_in_bytes);
|
||||
// double sanity check
|
||||
assertInvariants();
|
||||
}
|
||||
// enable this constructor only if the underlying type is char or void
|
||||
template <class U>
|
||||
CSelf(pointer first, size_type count, U *base_, XSPAN_REQUIRES_SIZE_1_A)
|
||||
: ptr(makePtr(first)), base(makeBase(base_)), size_in_bytes(xspan_mem_size<T>(count)) {
|
||||
// check invariants
|
||||
if __acc_cte ((configRequirePtr || ptr != nullptr) && (configRequireBase || base != nullptr))
|
||||
xspan_check_range(ptr, base, size_in_bytes);
|
||||
// double sanity check
|
||||
assertInvariants();
|
||||
}
|
||||
noinline void invalidate() {
|
||||
assertInvariants();
|
||||
ptr = (pointer) (upx_uintptr_t) 16; // point to non-null invalid address
|
||||
// ptr = (pointer) (void *) &ptr; // point to self
|
||||
base = ptr;
|
||||
size_in_bytes = 0;
|
||||
assertInvariants();
|
||||
}
|
||||
// constructors from pointers
|
||||
CSelf(pointer first, XSpanCount count)
|
||||
: ptr(makePtr(first)), base(makeBase(first)),
|
||||
size_in_bytes(xspan_mem_size<T>(count.count)) {
|
||||
assertInvariants();
|
||||
}
|
||||
CSelf(pointer first, XSpanSizeInBytes bytes)
|
||||
: ptr(makePtr(first)), base(makeBase(first)),
|
||||
size_in_bytes(xspan_mem_size<char>(bytes.size_in_bytes)) {
|
||||
assertInvariants();
|
||||
}
|
||||
// enable this constructor only if the underlying type is char or void
|
||||
template <class U>
|
||||
CSelf(U *first, size_type count, XSPAN_REQUIRES_SIZE_1_A)
|
||||
: ptr(makePtr(first)), base(makeBase(first)), size_in_bytes(xspan_mem_size<T>(count)) {
|
||||
assertInvariants();
|
||||
}
|
||||
CSelf(pointer first, XSpanCount count, pointer base_)
|
||||
: ptr(makePtr(first)), base(makeBase(base_)),
|
||||
size_in_bytes(xspan_mem_size<T>(count.count)) {
|
||||
// check invariants
|
||||
if __acc_cte ((configRequirePtr || ptr != nullptr) &&
|
||||
(configRequireBase || base != nullptr))
|
||||
xspan_check_range(ptr, base, size_in_bytes);
|
||||
// double sanity check
|
||||
assertInvariants();
|
||||
}
|
||||
CSelf(pointer first, XSpanSizeInBytes bytes, pointer base_)
|
||||
: ptr(makePtr(first)), base(makeBase(base_)),
|
||||
size_in_bytes(xspan_mem_size<char>(bytes.size_in_bytes)) {
|
||||
// check invariants
|
||||
if __acc_cte ((configRequirePtr || ptr != nullptr) &&
|
||||
(configRequireBase || base != nullptr))
|
||||
xspan_check_range(ptr, base, size_in_bytes);
|
||||
// double sanity check
|
||||
assertInvariants();
|
||||
}
|
||||
// enable this constructor only if the underlying type is char or void
|
||||
template <class U>
|
||||
CSelf(pointer first, size_type count, U *base_, XSPAN_REQUIRES_SIZE_1_A)
|
||||
: ptr(makePtr(first)), base(makeBase(base_)), size_in_bytes(xspan_mem_size<T>(count)) {
|
||||
// check invariants
|
||||
if __acc_cte ((configRequirePtr || ptr != nullptr) &&
|
||||
(configRequireBase || base != nullptr))
|
||||
xspan_check_range(ptr, base, size_in_bytes);
|
||||
// double sanity check
|
||||
assertInvariants();
|
||||
}
|
||||
#ifdef UPX_VERSION_HEX
|
||||
// constructors from MemBuffer
|
||||
CSelf(MemBuffer &mb)
|
||||
: CSelf(makeNotNull((pointer) membuffer_get_void_ptr(mb)),
|
||||
XSpanSizeInBytes(membuffer_get_size(mb))) {}
|
||||
CSelf(pointer first, MemBuffer &mb)
|
||||
: CSelf(first, XSpanSizeInBytes(membuffer_get_size(mb)),
|
||||
makeNotNull((pointer) membuffer_get_void_ptr(mb))) {}
|
||||
CSelf(std::nullptr_t, MemBuffer &) XSPAN_DELETED_FUNCTION;
|
||||
// constructors from MemBuffer
|
||||
CSelf(MemBuffer &mb)
|
||||
: CSelf(makeNotNull((pointer) membuffer_get_void_ptr(mb)),
|
||||
XSpanSizeInBytes(membuffer_get_size(mb))) {}
|
||||
CSelf(pointer first, MemBuffer &mb)
|
||||
: CSelf(first, XSpanSizeInBytes(membuffer_get_size(mb)),
|
||||
makeNotNull((pointer) membuffer_get_void_ptr(mb))) {}
|
||||
CSelf(std::nullptr_t, MemBuffer &) XSPAN_DELETED_FUNCTION;
|
||||
#endif
|
||||
// disable constructors from nullptr to catch compile-time misuse
|
||||
// disable constructors from nullptr to catch compile-time misuse
|
||||
private:
|
||||
CSelf(std::nullptr_t, XSpanCount) XSPAN_DELETED_FUNCTION;
|
||||
CSelf(std::nullptr_t, XSpanCount, std::nullptr_t) XSPAN_DELETED_FUNCTION;
|
||||
CSelf(const void *, XSpanCount, std::nullptr_t) XSPAN_DELETED_FUNCTION;
|
||||
CSelf(std::nullptr_t, XSpanSizeInBytes) XSPAN_DELETED_FUNCTION;
|
||||
CSelf(std::nullptr_t, XSpanSizeInBytes, std::nullptr_t) XSPAN_DELETED_FUNCTION;
|
||||
CSelf(const void *, XSpanSizeInBytes, std::nullptr_t) XSPAN_DELETED_FUNCTION;
|
||||
CSelf(std::nullptr_t, size_type) XSPAN_DELETED_FUNCTION;
|
||||
CSelf(std::nullptr_t, size_type, std::nullptr_t) XSPAN_DELETED_FUNCTION;
|
||||
CSelf(const void *, size_type, std::nullptr_t) XSPAN_DELETED_FUNCTION;
|
||||
CSelf(std::nullptr_t, XSpanCount) XSPAN_DELETED_FUNCTION;
|
||||
CSelf(std::nullptr_t, XSpanCount, std::nullptr_t) XSPAN_DELETED_FUNCTION;
|
||||
CSelf(const void *, XSpanCount, std::nullptr_t) XSPAN_DELETED_FUNCTION;
|
||||
CSelf(std::nullptr_t, XSpanSizeInBytes) XSPAN_DELETED_FUNCTION;
|
||||
CSelf(std::nullptr_t, XSpanSizeInBytes, std::nullptr_t) XSPAN_DELETED_FUNCTION;
|
||||
CSelf(const void *, XSpanSizeInBytes, std::nullptr_t) XSPAN_DELETED_FUNCTION;
|
||||
CSelf(std::nullptr_t, size_type) XSPAN_DELETED_FUNCTION;
|
||||
CSelf(std::nullptr_t, size_type, std::nullptr_t) XSPAN_DELETED_FUNCTION;
|
||||
CSelf(const void *, size_type, std::nullptr_t) XSPAN_DELETED_FUNCTION;
|
||||
|
||||
// unchecked constructor
|
||||
// unchecked constructor
|
||||
protected:
|
||||
enum ModeUnchecked { Unchecked };
|
||||
CSelf(ModeUnchecked, pointer p, size_type bytes, pointer b)
|
||||
: ptr(p), base(b), size_in_bytes(bytes) {
|
||||
assertInvariants();
|
||||
}
|
||||
// unchecked assignment
|
||||
Self &assign(ModeUnchecked, pointer p, size_type bytes, pointer b) {
|
||||
ptr = p;
|
||||
base = b;
|
||||
size_in_bytes = bytes;
|
||||
assertInvariants();
|
||||
return *this;
|
||||
}
|
||||
enum ModeUnchecked { Unchecked };
|
||||
CSelf(ModeUnchecked, pointer p, size_type bytes, pointer b)
|
||||
: ptr(p), base(b), size_in_bytes(bytes) {
|
||||
assertInvariants();
|
||||
}
|
||||
// unchecked assignment
|
||||
Self &assign(ModeUnchecked, pointer p, size_type bytes, pointer b) {
|
||||
ptr = p;
|
||||
base = b;
|
||||
size_in_bytes = bytes;
|
||||
assertInvariants();
|
||||
return *this;
|
||||
}
|
||||
#if 0
|
||||
Self &assign(ModeUnchecked, const Self &other) {
|
||||
ptr = other.ptr;
|
||||
@@ -198,230 +209,250 @@ Self &assign(ModeUnchecked, const Self &other) {
|
||||
#endif
|
||||
|
||||
public:
|
||||
// assignment - here we can rely on invariants enforced at construction time by makePtr/makeBase
|
||||
// NOTE: *this remains unmodified in case of failure
|
||||
Self &assign(pointer other) {
|
||||
assertInvariants();
|
||||
other = makePtr(other);
|
||||
if __acc_cte ((configRequirePtr || other != nullptr) && (configRequireBase || base != nullptr))
|
||||
xspan_check_range(other, base, size_in_bytes);
|
||||
// ok
|
||||
ptr = other;
|
||||
assertInvariants();
|
||||
return *this;
|
||||
}
|
||||
Self &assign(const Self &other) {
|
||||
assertInvariants();
|
||||
other.assertInvariants();
|
||||
if __acc_cte (!configRequireBase && base == nullptr) {
|
||||
// magic 1: if base is unset, automatically set base/size_in_bytes from other
|
||||
if __acc_cte ((configRequirePtr || other.ptr != nullptr) &&
|
||||
(configRequireBase || other.base != nullptr))
|
||||
xspan_check_range(other.ptr, other.base, other.size_in_bytes);
|
||||
// ok
|
||||
ptr = other.ptr;
|
||||
base = other.base;
|
||||
size_in_bytes = other.size_in_bytes;
|
||||
} else {
|
||||
// magic 2: assert same base (but ignore size_in_bytes !)
|
||||
if __acc_cte (configRequireBase || other.base != nullptr)
|
||||
if very_unlikely (base != other.base)
|
||||
xspan_fail_not_same_base();
|
||||
if __acc_cte ((configRequirePtr || other.ptr != nullptr) &&
|
||||
// assignment - here we can rely on invariants enforced at construction time by makePtr/makeBase
|
||||
// NOTE: *this remains unmodified in case of failure
|
||||
Self &assign(pointer other) {
|
||||
assertInvariants();
|
||||
other = makePtr(other);
|
||||
if __acc_cte ((configRequirePtr || other != nullptr) &&
|
||||
(configRequireBase || base != nullptr))
|
||||
xspan_check_range(other.ptr, base, size_in_bytes);
|
||||
xspan_check_range(other, base, size_in_bytes);
|
||||
// ok
|
||||
ptr = other.ptr;
|
||||
ptr = other;
|
||||
assertInvariants();
|
||||
return *this;
|
||||
}
|
||||
Self &assign(const Self &other) {
|
||||
assertInvariants();
|
||||
other.assertInvariants();
|
||||
if __acc_cte (!configRequireBase && base == nullptr) {
|
||||
// magic 1: if base is unset, automatically set base/size_in_bytes from other
|
||||
if __acc_cte ((configRequirePtr || other.ptr != nullptr) &&
|
||||
(configRequireBase || other.base != nullptr))
|
||||
xspan_check_range(other.ptr, other.base, other.size_in_bytes);
|
||||
// ok
|
||||
ptr = other.ptr;
|
||||
base = other.base;
|
||||
size_in_bytes = other.size_in_bytes;
|
||||
} else {
|
||||
// magic 2: assert same base (but ignore size_in_bytes !)
|
||||
if __acc_cte (configRequireBase || other.base != nullptr)
|
||||
if very_unlikely (base != other.base)
|
||||
xspan_fail_not_same_base();
|
||||
if __acc_cte ((configRequirePtr || other.ptr != nullptr) &&
|
||||
(configRequireBase || base != nullptr))
|
||||
xspan_check_range(other.ptr, base, size_in_bytes);
|
||||
// ok
|
||||
ptr = other.ptr;
|
||||
}
|
||||
assertInvariants();
|
||||
return *this;
|
||||
}
|
||||
assertInvariants();
|
||||
return *this;
|
||||
}
|
||||
|
||||
Self &operator=(pointer other) { return assign(other); }
|
||||
Self &operator=(pointer other) { return assign(other); }
|
||||
|
||||
Self &operator=(const Self &other) { return assign(other); }
|
||||
Self &operator=(const Self &other) { return assign(other); }
|
||||
|
||||
// FIXME: this is not called??
|
||||
template <class U>
|
||||
XSPAN_REQUIRES_CONVERTIBLE_R(Self &)
|
||||
operator=(const CSelf<U> &other) {
|
||||
// assert(0);
|
||||
return assign(Self(other));
|
||||
}
|
||||
// FIXME: this is not called??
|
||||
template <class U>
|
||||
XSPAN_REQUIRES_CONVERTIBLE_R(Self &)
|
||||
operator=(const CSelf<U> &other) {
|
||||
// assert(0);
|
||||
return assign(Self(other));
|
||||
}
|
||||
|
||||
#ifdef UPX_VERSION_HEX
|
||||
Self &operator=(MemBuffer &mb) { return assign(Self(mb)); }
|
||||
Self &operator=(MemBuffer &mb) { return assign(Self(mb)); }
|
||||
#endif
|
||||
|
||||
Self subspan(ptrdiff_t offset, ptrdiff_t count) {
|
||||
pointer begin = check_add(ptr, offset);
|
||||
pointer end = check_add(begin, count);
|
||||
if (begin <= end)
|
||||
return Self(Unchecked, begin, (end - begin) * sizeof(T), begin);
|
||||
else
|
||||
return Self(Unchecked, end, (begin - end) * sizeof(T), end);
|
||||
}
|
||||
Self subspan(ptrdiff_t offset, ptrdiff_t count) {
|
||||
pointer begin = check_add(ptr, offset);
|
||||
pointer end = check_add(begin, count);
|
||||
if (begin <= end)
|
||||
return Self(Unchecked, begin, (end - begin) * sizeof(T), begin);
|
||||
else
|
||||
return Self(Unchecked, end, (begin - end) * sizeof(T), end);
|
||||
}
|
||||
|
||||
bool operator==(pointer other) const { return ptr == other; }
|
||||
template <class U>
|
||||
XSPAN_REQUIRES_CONVERTIBLE_R(bool)
|
||||
operator==(U *other) const {
|
||||
return ptr == other;
|
||||
}
|
||||
bool operator!=(pointer other) const { return ptr != other; }
|
||||
template <class U>
|
||||
XSPAN_REQUIRES_CONVERTIBLE_R(bool)
|
||||
operator!=(U *other) const {
|
||||
return ptr != other;
|
||||
}
|
||||
bool operator==(pointer other) const { return ptr == other; }
|
||||
template <class U>
|
||||
XSPAN_REQUIRES_CONVERTIBLE_R(bool)
|
||||
operator==(U *other) const {
|
||||
return ptr == other;
|
||||
}
|
||||
bool operator!=(pointer other) const { return ptr != other; }
|
||||
template <class U>
|
||||
XSPAN_REQUIRES_CONVERTIBLE_R(bool)
|
||||
operator!=(U *other) const {
|
||||
return ptr != other;
|
||||
}
|
||||
|
||||
template <class U>
|
||||
XSPAN_REQUIRES_CONVERTIBLE_R(bool)
|
||||
operator==(const PtrOrSpan<U> &other) const {
|
||||
return ptr == other.ptr;
|
||||
}
|
||||
template <class U>
|
||||
XSPAN_REQUIRES_CONVERTIBLE_R(bool)
|
||||
operator==(const PtrOrSpanOrNull<U> &other) const {
|
||||
return ptr == other.ptr;
|
||||
}
|
||||
template <class U>
|
||||
XSPAN_REQUIRES_CONVERTIBLE_R(bool)
|
||||
operator==(const Span<U> &other) const {
|
||||
return ptr == other.ptr;
|
||||
}
|
||||
template <class U>
|
||||
XSPAN_REQUIRES_CONVERTIBLE_R(bool)
|
||||
operator==(const PtrOrSpan<U> &other) const {
|
||||
return ptr == other.ptr;
|
||||
}
|
||||
template <class U>
|
||||
XSPAN_REQUIRES_CONVERTIBLE_R(bool)
|
||||
operator==(const PtrOrSpanOrNull<U> &other) const {
|
||||
return ptr == other.ptr;
|
||||
}
|
||||
template <class U>
|
||||
XSPAN_REQUIRES_CONVERTIBLE_R(bool)
|
||||
operator==(const Span<U> &other) const {
|
||||
return ptr == other.ptr;
|
||||
}
|
||||
|
||||
template <class U>
|
||||
XSPAN_REQUIRES_CONVERTIBLE_R(bool)
|
||||
operator!=(const PtrOrSpan<U> &other) const {
|
||||
return !(*this == other);
|
||||
}
|
||||
template <class U>
|
||||
XSPAN_REQUIRES_CONVERTIBLE_R(bool)
|
||||
operator!=(const PtrOrSpanOrNull<U> &other) const {
|
||||
return !(*this == other);
|
||||
}
|
||||
template <class U>
|
||||
XSPAN_REQUIRES_CONVERTIBLE_R(bool)
|
||||
operator!=(const Span<U> &other) const {
|
||||
return !(*this == other);
|
||||
}
|
||||
template <class U>
|
||||
XSPAN_REQUIRES_CONVERTIBLE_R(bool)
|
||||
operator!=(const PtrOrSpan<U> &other) const {
|
||||
return !(*this == other);
|
||||
}
|
||||
template <class U>
|
||||
XSPAN_REQUIRES_CONVERTIBLE_R(bool)
|
||||
operator!=(const PtrOrSpanOrNull<U> &other) const {
|
||||
return !(*this == other);
|
||||
}
|
||||
template <class U>
|
||||
XSPAN_REQUIRES_CONVERTIBLE_R(bool)
|
||||
operator!=(const Span<U> &other) const {
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
// check for notNull here
|
||||
bool operator<(std::nullptr_t) const XSPAN_DELETED_FUNCTION;
|
||||
bool operator<(pointer other) const { return ensurePtr() < makeNotNull(other); }
|
||||
// check for notNull here
|
||||
bool operator<(std::nullptr_t) const XSPAN_DELETED_FUNCTION;
|
||||
bool operator<(pointer other) const { return ensurePtr() < makeNotNull(other); }
|
||||
|
||||
template <class U>
|
||||
XSPAN_REQUIRES_CONVERTIBLE_R(bool)
|
||||
operator<(const PtrOrSpan<U> &other) const {
|
||||
return ensurePtr() < other.ensurePtr();
|
||||
}
|
||||
template <class U>
|
||||
XSPAN_REQUIRES_CONVERTIBLE_R(bool)
|
||||
operator<(const PtrOrSpanOrNull<U> &other) const {
|
||||
return ensurePtr() < other.ensurePtr();
|
||||
}
|
||||
template <class U>
|
||||
XSPAN_REQUIRES_CONVERTIBLE_R(bool)
|
||||
operator<(const Span<U> &other) const {
|
||||
return ensurePtr() < other.ensurePtr();
|
||||
}
|
||||
template <class U>
|
||||
XSPAN_REQUIRES_CONVERTIBLE_R(bool)
|
||||
operator<(const PtrOrSpan<U> &other) const {
|
||||
return ensurePtr() < other.ensurePtr();
|
||||
}
|
||||
template <class U>
|
||||
XSPAN_REQUIRES_CONVERTIBLE_R(bool)
|
||||
operator<(const PtrOrSpanOrNull<U> &other) const {
|
||||
return ensurePtr() < other.ensurePtr();
|
||||
}
|
||||
template <class U>
|
||||
XSPAN_REQUIRES_CONVERTIBLE_R(bool)
|
||||
operator<(const Span<U> &other) const {
|
||||
return ensurePtr() < other.ensurePtr();
|
||||
}
|
||||
|
||||
// dereference
|
||||
reference operator*() const { return *check_deref(ptr); }
|
||||
// dereference
|
||||
reference operator*() const { return *check_deref(ptr); }
|
||||
|
||||
// array access
|
||||
reference operator[](ptrdiff_t i) const { return *check_deref(ptr, i); }
|
||||
// array access
|
||||
reference operator[](ptrdiff_t i) const { return *check_deref(ptr, i); }
|
||||
|
||||
// arrow operator
|
||||
pointer operator->() const { return check_deref(ptr); }
|
||||
// arrow operator
|
||||
pointer operator->() const { return check_deref(ptr); }
|
||||
|
||||
Self &operator++() {
|
||||
ptr = check_add(ptr, 1);
|
||||
return *this;
|
||||
}
|
||||
Self operator++(int) {
|
||||
Self tmp = *this;
|
||||
++*this;
|
||||
return tmp;
|
||||
}
|
||||
Self &operator--() {
|
||||
ptr = check_add(ptr, -1);
|
||||
return *this;
|
||||
}
|
||||
Self operator--(int) {
|
||||
Self tmp = *this;
|
||||
--*this;
|
||||
return tmp;
|
||||
}
|
||||
Self &operator++() {
|
||||
ptr = check_add(ptr, 1);
|
||||
return *this;
|
||||
}
|
||||
Self operator++(int) {
|
||||
Self tmp = *this;
|
||||
++*this;
|
||||
return tmp;
|
||||
}
|
||||
Self &operator--() {
|
||||
ptr = check_add(ptr, -1);
|
||||
return *this;
|
||||
}
|
||||
Self operator--(int) {
|
||||
Self tmp = *this;
|
||||
--*this;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
Self &operator+=(ptrdiff_t n) {
|
||||
ptr = check_add(ptr, n);
|
||||
return *this;
|
||||
}
|
||||
Self &operator-=(ptrdiff_t n) {
|
||||
ptr = check_add(ptr, -n);
|
||||
return *this;
|
||||
}
|
||||
Self &operator+=(ptrdiff_t n) {
|
||||
ptr = check_add(ptr, n);
|
||||
return *this;
|
||||
}
|
||||
Self &operator-=(ptrdiff_t n) {
|
||||
ptr = check_add(ptr, -n);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Self operator+(ptrdiff_t n) const {
|
||||
pointer first = check_add(ptr, n);
|
||||
return Self(Unchecked, first, size_in_bytes, base);
|
||||
}
|
||||
Self operator-(ptrdiff_t n) const {
|
||||
pointer first = check_add(ptr, -n);
|
||||
return Self(Unchecked, first, size_in_bytes, base);
|
||||
}
|
||||
Self operator+(ptrdiff_t n) const {
|
||||
pointer first = check_add(ptr, n);
|
||||
return Self(Unchecked, first, size_in_bytes, base);
|
||||
}
|
||||
Self operator-(ptrdiff_t n) const {
|
||||
pointer first = check_add(ptr, -n);
|
||||
return Self(Unchecked, first, size_in_bytes, base);
|
||||
}
|
||||
|
||||
private:
|
||||
pointer check_deref(pointer p) const {
|
||||
if __acc_cte (!configRequirePtr && p == nullptr)
|
||||
xspan_fail_nullptr();
|
||||
if __acc_cte (configRequireBase || base != nullptr)
|
||||
xspan_check_range(p, base, size_in_bytes - sizeof(T));
|
||||
assertInvariants();
|
||||
return p;
|
||||
}
|
||||
pointer check_deref(pointer p, ptrdiff_t n) const {
|
||||
if __acc_cte (!configRequirePtr && p == nullptr)
|
||||
xspan_fail_nullptr();
|
||||
xspan_mem_size_assert_ptrdiff<T>(n);
|
||||
p += n;
|
||||
if __acc_cte (configRequireBase || base != nullptr)
|
||||
xspan_check_range(p, base, size_in_bytes - sizeof(T));
|
||||
assertInvariants();
|
||||
return p;
|
||||
}
|
||||
pointer check_add(pointer p, ptrdiff_t n) const {
|
||||
if __acc_cte (!configRequirePtr && p == nullptr)
|
||||
xspan_fail_nullptr();
|
||||
xspan_mem_size_assert_ptrdiff<T>(n);
|
||||
p += n;
|
||||
if __acc_cte (configRequireBase || base != nullptr)
|
||||
xspan_check_range(p, base, size_in_bytes);
|
||||
assertInvariants();
|
||||
return p;
|
||||
}
|
||||
pointer check_deref(pointer p) const {
|
||||
if __acc_cte (!configRequirePtr && p == nullptr)
|
||||
xspan_fail_nullptr();
|
||||
if __acc_cte (configRequireBase || base != nullptr)
|
||||
xspan_check_range(p, base, size_in_bytes - sizeof(T));
|
||||
assertInvariants();
|
||||
return p;
|
||||
}
|
||||
pointer check_deref(pointer p, ptrdiff_t n) const {
|
||||
if __acc_cte (!configRequirePtr && p == nullptr)
|
||||
xspan_fail_nullptr();
|
||||
xspan_mem_size_assert_ptrdiff<T>(n);
|
||||
p += n;
|
||||
if __acc_cte (configRequireBase || base != nullptr)
|
||||
xspan_check_range(p, base, size_in_bytes - sizeof(T));
|
||||
assertInvariants();
|
||||
return p;
|
||||
}
|
||||
pointer check_add(pointer p, ptrdiff_t n) const {
|
||||
if __acc_cte (!configRequirePtr && p == nullptr)
|
||||
xspan_fail_nullptr();
|
||||
xspan_mem_size_assert_ptrdiff<T>(n);
|
||||
p += n;
|
||||
if __acc_cte (configRequireBase || base != nullptr)
|
||||
xspan_check_range(p, base, size_in_bytes);
|
||||
assertInvariants();
|
||||
return p;
|
||||
}
|
||||
|
||||
// disable taking the address => force passing by reference
|
||||
// [I'm not too sure about this design decision, but we can always allow it if needed]
|
||||
Self *operator&() const XSPAN_DELETED_FUNCTION;
|
||||
// disable taking the address => force passing by reference
|
||||
// [I'm not too sure about this design decision, but we can always allow it if needed]
|
||||
Self *operator&() const XSPAN_DELETED_FUNCTION;
|
||||
|
||||
public: // raw access
|
||||
pointer raw_ptr() const { return ptr; }
|
||||
pointer raw_base() const { return base; }
|
||||
size_type raw_size_in_bytes() const { return size_in_bytes; }
|
||||
pointer raw_ptr() const noexcept { return ptr; }
|
||||
pointer raw_base() const noexcept { return base; }
|
||||
size_type raw_size_in_bytes() const noexcept { return size_in_bytes; }
|
||||
|
||||
pointer raw_bytes(size_t bytes) const {
|
||||
assertInvariants();
|
||||
if (bytes > 0) {
|
||||
if __acc_cte (!configRequirePtr && ptr == nullptr)
|
||||
xspan_fail_nullptr();
|
||||
if __acc_cte (configRequireBase || base != nullptr) {
|
||||
xspan_check_range(ptr, base, size_in_bytes - bytes);
|
||||
pointer raw_bytes(size_t bytes) const {
|
||||
assertInvariants();
|
||||
if (bytes > 0) {
|
||||
if __acc_cte (!configRequirePtr && ptr == nullptr)
|
||||
xspan_fail_nullptr();
|
||||
if __acc_cte (configRequireBase || base != nullptr) {
|
||||
xspan_check_range(ptr, base, size_in_bytes - bytes);
|
||||
}
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
// like C++ std::span
|
||||
pointer data() const noexcept { return ptr; }
|
||||
pointer data(size_t bytes) const { return raw_bytes(bytes); } // UPX extra
|
||||
// size_type size() const { return size_bytes() / sizeof(element_type); } // NOT USED
|
||||
size_type size_bytes() const {
|
||||
assertInvariants();
|
||||
if __acc_cte (!configRequirePtr && ptr == nullptr)
|
||||
return 0;
|
||||
if __acc_cte (!configRequireBase && base == nullptr)
|
||||
return 0;
|
||||
const charptr begin = (const charptr) ptr;
|
||||
const charptr end = (const charptr) base + size_in_bytes;
|
||||
return end - begin;
|
||||
}
|
||||
|
||||
#if CLANG_FORMAT_DUMMY_CLASS
|
||||
}; // class
|
||||
#endif
|
||||
|
||||
/* vim:set ts=4 sw=4 et: */
|
||||
|
||||
Reference in New Issue
Block a user