1
0
mirror of https://github.com/upx/upx synced 2025-09-28 19:06:07 +08:00
upx/src/util/xspan_impl_span.h
2023-01-29 11:39:57 +01:00

151 lines
4.8 KiB
C++

/* xspan -- a minimally invasive checked memory smart pointer
This file is part of the UPX executable compressor.
Copyright (C) 1996-2023 Markus Franz Xaver Johannes Oberhumer
All Rights Reserved.
UPX and the UCL library are free software; you can redistribute them
and/or modify them under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; see the file COPYING.
If not, write to the Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Markus F.X.J. Oberhumer
<markus@oberhumer.com>
*/
#pragma once
XSPAN_NAMESPACE_BEGIN
/*************************************************************************
// Span
//
// invariants:
// ptr != null, base != null
// ptr is valid in base
**************************************************************************/
template <class T>
struct Span {
private:
#define CSelf Span
typedef CSelf<T> Self;
// core config
enum { configRequirePtr = true };
enum { configRequireBase = true };
#include "xspan_impl_common.h"
public:
// constructors from pointers
CSelf(pointer first) XSPAN_DELETED_FUNCTION;
// constructors
CSelf(const Self &other)
: ptr(other.ensurePtr()), base(other.ensureBase()), size_in_bytes(other.size_in_bytes) {
assertInvariants();
}
template <class U>
CSelf(const CSelf<U> &other, XSPAN_REQUIRES_CONVERTIBLE_A)
: ptr(other.ensurePtr()), base(other.ensureBase()), size_in_bytes(other.size_in_bytes) {
assertInvariants();
}
// constructors from Span friends
#if XSPAN_CONFIG_ENABLE_SPAN_CONVERSION
template <class U>
CSelf(const PtrOrSpanOrNull<U> &other, XSPAN_REQUIRES_CONVERTIBLE_A)
: ptr(other.ensurePtr()), base(other.ensureBase()), size_in_bytes(other.size_in_bytes) {
assertInvariants();
}
template <class U>
CSelf(const PtrOrSpan<U> &other, XSPAN_REQUIRES_CONVERTIBLE_A)
: ptr(other.ensurePtr()), base(other.ensureBase()), size_in_bytes(other.size_in_bytes) {
assertInvariants();
}
#endif
// assignment from Span friends
#if XSPAN_CONFIG_ENABLE_SPAN_CONVERSION
// TODO: use Unchecked to avoid double checks in both constructor and assignment
template <class U>
XSPAN_REQUIRES_CONVERTIBLE_R(Self &)
operator=(const PtrOrSpan<U> &other) {
if (other.base == nullptr)
return assign(Self(other.ptr, size_in_bytes, base));
return assign(Self(other.ptr, other.size_in_bytes, other.base));
}
template <class U>
XSPAN_REQUIRES_CONVERTIBLE_R(Self &)
operator=(const PtrOrSpanOrNull<U> &other) {
if (other.base == nullptr)
return assign(Self(other.ptr, size_in_bytes, base));
return assign(Self(other.ptr, other.size_in_bytes, other.base));
}
#endif
// nullptr
CSelf(std::nullptr_t) XSPAN_DELETED_FUNCTION;
CSelf(std::nullptr_t, XSpanCount, const void *) XSPAN_DELETED_FUNCTION;
CSelf(std::nullptr_t, XSpanSizeInBytes, const void *) XSPAN_DELETED_FUNCTION;
CSelf(std::nullptr_t, size_type, const void *) XSPAN_DELETED_FUNCTION;
Self &operator=(std::nullptr_t) XSPAN_DELETED_FUNCTION;
#if 0
// don't enable, this prevents generic usage
bool operator==(std::nullptr_t) const XSPAN_DELETED_FUNCTION;
bool operator!=(std::nullptr_t) const XSPAN_DELETED_FUNCTION;
#else
bool operator==(std::nullptr_t) const {
assertInvariants();
return false;
}
bool operator!=(std::nullptr_t) const {
assertInvariants();
return true;
}
#endif
#undef CSelf
};
// raw_bytes overload
template <class T>
inline typename Span<T>::pointer raw_bytes(const Span<T> &a, size_t size_in_bytes) {
return a.raw_bytes(size_in_bytes);
}
template <class T>
inline typename Span<T>::pointer raw_index_bytes(const Span<T> &a, size_t index,
size_t size_in_bytes) {
typedef typename Span<T>::element_type element_type;
return a.raw_bytes(mem_size(sizeof(element_type), index, size_in_bytes)) + index;
}
/*************************************************************************
//
**************************************************************************/
XSPAN_NAMESPACE_END
#if !XSPAN_CONFIG_ENABLE_IMPLICIT_CONVERSION || 1
#define C XSPAN_NS(Span)
#define D XSPAN_NS(PtrOrSpanOrNull)
#define E XSPAN_NS(PtrOrSpan)
#include "xspan_fwd.h"
#undef C
#undef D
#undef E
#endif
/* vim:set ts=4 sw=4 et: */