/* xspan -- a minimally invasive checked memory smart pointer This file is part of the UPX executable compressor. Copyright (C) 1996-2022 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 */ #pragma once #if WITH_SPAN #if 1 #define SPAN_NAMESPACE_NAME XSpan #define SPAN_NAMESPACE_BEGIN namespace SPAN_NAMESPACE_NAME { #define SPAN_NAMESPACE_END } #define SPAN_NS(x) SPAN_NAMESPACE_NAME ::x #else #define SPAN_NAMESPACE_BEGIN /*empty*/ #define SPAN_NAMESPACE_END /*empty*/ #define SPAN_NS(x) ::x #endif SPAN_NAMESPACE_BEGIN __acc_noinline void span_fail_nullptr(); __acc_noinline void span_fail_not_same_base(); __acc_noinline void span_fail_range_nullptr(); __acc_noinline void span_fail_range_nullbase(); __acc_noinline void span_fail_range_range(); void span_check_range(const void *p, const void *base, ptrdiff_t size_in_bytes); // help constructor to distinguish between number of elements and bytes struct SpanCount { explicit SpanCount(size_t n) : count(n) {} size_t count; // public }; struct SpanSizeInBytes { explicit SpanSizeInBytes(size_t bytes) : size_in_bytes(bytes) {} size_t size_in_bytes; // public }; template struct TypeForSizeOf { typedef T type; }; template <> struct TypeForSizeOf { typedef char type; }; template <> struct TypeForSizeOf { typedef const char type; }; template struct ValueForSizeOf { static const size_t value = sizeof(typename TypeForSizeOf::type); }; ACC_COMPILE_TIME_ASSERT_HEADER(ValueForSizeOf::value == 1) ACC_COMPILE_TIME_ASSERT_HEADER(ValueForSizeOf::value == 1) ACC_COMPILE_TIME_ASSERT_HEADER(ValueForSizeOf::value == 1) ACC_COMPILE_TIME_ASSERT_HEADER(ValueForSizeOf::value == 1) ACC_COMPILE_TIME_ASSERT_HEADER(ValueForSizeOf::value == 4) #ifndef span_mem_size_impl template inline size_t span_mem_size_impl(size_t n) { #ifdef UPX_VERSION_HEX // check for overflow and sane limits return mem_size(sizeof(T), n); #else return sizeof(T) * n; #endif } #endif template inline size_t span_mem_size(size_t n) { return span_mem_size_impl::type>(n); } template inline void span_mem_size_assert_ptrdiff(ptrdiff_t n) { if (n >= 0) (void) span_mem_size((size_t) n); else (void) span_mem_size((size_t) -n); } #if 0 template struct Span_is_convertible : public std::is_convertible {}; #else namespace detail { template struct Span_void_to_T { typedef U type; }; template struct Span_void_to_T { typedef typename std::remove_const::type type; }; template struct Span_void_to_T { // typedef typename std::add_const::type type; typedef T type; }; template struct Span_ptr_is_convertible : public std::false_type {}; template struct Span_ptr_is_convertible : public std::true_type {}; template struct Span_ptr_is_convertible : public std::true_type {}; } // namespace detail template struct Span_is_convertible : public detail::Span_ptr_is_convertible::type> {}; #endif #if 1 // char => char ACC_COMPILE_TIME_ASSERT_HEADER((Span_is_convertible::value)); ACC_COMPILE_TIME_ASSERT_HEADER((Span_is_convertible::value)); ACC_COMPILE_TIME_ASSERT_HEADER((Span_is_convertible::value)); ACC_COMPILE_TIME_ASSERT_HEADER((!Span_is_convertible::value)); // void => void ACC_COMPILE_TIME_ASSERT_HEADER((Span_is_convertible::value)); ACC_COMPILE_TIME_ASSERT_HEADER((Span_is_convertible::value)); ACC_COMPILE_TIME_ASSERT_HEADER((Span_is_convertible::value)); ACC_COMPILE_TIME_ASSERT_HEADER((!Span_is_convertible::value)); // char => void ACC_COMPILE_TIME_ASSERT_HEADER((Span_is_convertible::value)); ACC_COMPILE_TIME_ASSERT_HEADER((Span_is_convertible::value)); ACC_COMPILE_TIME_ASSERT_HEADER((Span_is_convertible::value)); ACC_COMPILE_TIME_ASSERT_HEADER((!Span_is_convertible::value)); // void => char ACC_COMPILE_TIME_ASSERT_HEADER((!Span_is_convertible::value)); ACC_COMPILE_TIME_ASSERT_HEADER((!Span_is_convertible::value)); ACC_COMPILE_TIME_ASSERT_HEADER((!Span_is_convertible::value)); ACC_COMPILE_TIME_ASSERT_HEADER((!Span_is_convertible::value)); // char => int ACC_COMPILE_TIME_ASSERT_HEADER(!(Span_is_convertible::value)); ACC_COMPILE_TIME_ASSERT_HEADER(!(Span_is_convertible::value)); ACC_COMPILE_TIME_ASSERT_HEADER(!(Span_is_convertible::value)); ACC_COMPILE_TIME_ASSERT_HEADER((!Span_is_convertible::value)); #endif /************************************************************************* // PtrOrSpanOrNull // PtrOrSpan // Span // Ptr **************************************************************************/ // forward declarations template struct PtrOrSpanOrNull; template struct PtrOrSpan; template struct Span; template struct Ptr; template inline T *raw_bytes(const PtrOrSpanOrNull &a, size_t size_in_bytes); template inline T *raw_bytes(const PtrOrSpan &a, size_t size_in_bytes); template inline T *raw_bytes(const Span &a, size_t size_in_bytes); template inline T *raw_bytes(const Ptr &a, size_t size_in_bytes); class SpanInternalDummyArg; // not implemented SPAN_NAMESPACE_END #ifndef SPAN_DELETED_FUNCTION #define SPAN_DELETED_FUNCTION = delete #endif #define SPAN_REQUIRES_CONVERTIBLE_UT(T, U, RType) \ typename std::enable_if::value, RType > ::type #define SPAN_REQUIRES_CONVERTIBLE_ANY_DIRECTION(T, U, RType) \ typename std::enable_if::value || \ SPAN_NS(Span_is_convertible)::value, \ RType > ::type // note: these use "T" and "U" #define SPAN_REQUIRES_CONVERTIBLE_R(RType) SPAN_REQUIRES_CONVERTIBLE_UT(T, U, RType) #define SPAN_REQUIRES_CONVERTIBLE_A \ SPAN_REQUIRES_CONVERTIBLE_R(SPAN_NS(SpanInternalDummyArg) *) = nullptr #define SPAN_REQUIRES_CONVERTIBLE_T SPAN_REQUIRES_CONVERTIBLE_R(SPAN_NS(SpanInternalDummyArg) *) // note: these use "T" and "U" #define SPAN_REQUIRES_SIZE_1_R(RType) \ typename std::enable_if::value &&SPAN_NS( \ ValueForSizeOf)::value == 1 && \ SPAN_NS(ValueForSizeOf)::value == 1, \ RType > ::type #define SPAN_REQUIRES_SIZE_1_A SPAN_REQUIRES_SIZE_1_R(SPAN_NS(SpanInternalDummyArg) *) = nullptr #include "xspan_impl_ptr_or_null.h" #include "xspan_impl_ptr_or_span.h" #include "xspan_impl_span.h" #include "xspan_impl_ptr.h" #undef SPAN_REQUIRES_CONVERTIBLE_UT #undef SPAN_REQUIRES_CONVERTIBLE_ANY_DIRECTION #undef SPAN_REQUIRES_CONVERTIBLE_A #undef SPAN_REQUIRES_CONVERTIBLE_R #undef SPAN_REQUIRES_CONVERTIBLE_T #undef SPAN_REQUIRES_SIZE_1_A #undef SPAN_REQUIRES_SIZE_1_R #endif // WITH_SPAN /* vim:set ts=4 sw=4 et: */