// Custom pointer adapter and sample storage policies

// Copyright (C) 2008-2025 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library.  This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.

// This library 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.

// Under Section 7 of GPL version 3, you are granted additional
// permissions described in the GCC Runtime Library Exception, version
// 3.1, as published by the Free Software Foundation.

// You should have received a copy of the GNU General Public License and
// a copy of the GCC Runtime Library Exception along with this program;
// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
// <http://www.gnu.org/licenses/>.

/**
 *  @file ext/pointer.h
 *  This file is a GNU extension to the Standard C++ Library.
 *
 *  @author Bob Walters
 *
 * Provides reusable _Pointer_adapter for assisting in the development of
 * custom pointer types that can be used with the standard containers via
 * the allocator::pointer and allocator::const_pointer typedefs.
 */

#ifndef _POINTER_H
#define _POINTER_H 1

#ifdef _GLIBCXX_SYSHDR
#pragma GCC system_header
#endif

#if _GLIBCXX_HOSTED
#  include <iosfwd>
#endif

#include <stdint.h> // uintptr_t
#include <bits/stl_iterator_base_types.h>
#include <ext/cast.h>
#include <ext/type_traits.h>
#if __cplusplus >= 201103L
# include <bits/move.h>
# include <bits/ptr_traits.h>
#endif
#if __cplusplus > 201703L
# include <iterator> // for indirectly_readable_traits
#endif

namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION

  /**
   * @brief A storage policy for use with _Pointer_adapter<> which yields a
   *        standard pointer.
   *
   *  A _Storage_policy is required to provide 4 things:
   *    1) A get() API for returning the stored pointer value.
   *    2) An set() API for storing a pointer value.
   *    3) An element_type typedef to define the type this points to.
   *    4) An operator<() to support pointer comparison.
   *    5) An operator==() to support pointer comparison.
   */
  template<typename _Tp>
    class _Std_pointer_impl
    {
    public:
      // the type this pointer points to.
      typedef _Tp element_type;

      // A method to fetch the pointer value as a standard T* value;
      inline _Tp*
      get() const
      { return _M_value; }

      // A method to set the pointer value, from a standard T* value;
      inline void
      set(element_type* __arg)
      { _M_value = __arg; }

      // Comparison of pointers
      inline bool
      operator<(const _Std_pointer_impl& __rarg) const
      { return (_M_value < __rarg._M_value); }

      inline bool
      operator==(const _Std_pointer_impl& __rarg) const
      { return (_M_value == __rarg._M_value); }

    private:
      element_type* _M_value;
    };

  /**
   * @brief A storage policy for use with _Pointer_adapter<> which stores
   *        the pointer's address as an offset value which is relative to
   *        its own address.
   *
   * This is intended for pointers within shared memory regions which
   * might be mapped at different addresses by different processes.
   * For null pointers, a value of 1 is used.  (0 is legitimate
   * sometimes for nodes in circularly linked lists) This value was
   * chosen as the least likely to generate an incorrect null, As
   * there is no reason why any normal pointer would point 1 byte into
   * its own pointer address.
   */
  template<typename _Tp>
    class _Relative_pointer_impl
    {
    public:
      typedef _Tp element_type;

      _Tp*
      get() const
      {
        if (_M_diff == 1)
          return 0;
        else
          return reinterpret_cast<_Tp*>(reinterpret_cast<uintptr_t>(this)
					+ _M_diff);
      }

      void
      set(_Tp* __arg)
      {
        if (!__arg)
          _M_diff = 1;
        else
          _M_diff = reinterpret_cast<uintptr_t>(__arg)
                    - reinterpret_cast<uintptr_t>(this);
      }

      // Comparison of pointers
      inline bool
      operator<(const _Relative_pointer_impl& __rarg) const
      { return (reinterpret_cast<uintptr_t>(this->get())
		< reinterpret_cast<uintptr_t>(__rarg.get())); }

      inline bool
      operator==(const _Relative_pointer_impl& __rarg) const
      { return (reinterpret_cast<uintptr_t>(this->get())
		== reinterpret_cast<uintptr_t>(__rarg.get())); }

    private:
      typedef __UINTPTR_TYPE__ uintptr_t;
      uintptr_t _M_diff;
    };

  /**
   * Relative_pointer_impl needs a specialization for const T because of
   * the casting done during pointer arithmetic.
   */
  template<typename _Tp>
    class _Relative_pointer_impl<const _Tp>
    {
    public:
      typedef const _Tp element_type;

      const _Tp*
      get() const
      {
        if (_M_diff == 1)
          return 0;
        else
          return reinterpret_cast<const _Tp*>
	      (reinterpret_cast<uintptr_t>(this) + _M_diff);
      }

      void
      set(const _Tp* __arg)
      {
        if (!__arg)
          _M_diff = 1;
        else
          _M_diff = reinterpret_cast<uintptr_t>(__arg)
                    - reinterpret_cast<uintptr_t>(this);
      }

      // Comparison of pointers
      inline bool
      operator<(const _Relative_pointer_impl& __rarg) const
      { return (reinterpret_cast<uintptr_t>(this->get())
		< reinterpret_cast<uintptr_t>(__rarg.get())); }

      inline bool
      operator==(const _Relative_pointer_impl& __rarg) const
      { return (reinterpret_cast<uintptr_t>(this->get())
		== reinterpret_cast<uintptr_t>(__rarg.get())); }

    private:
      typedef __UINTPTR_TYPE__ uintptr_t;
      uintptr_t _M_diff;
    };

  /**
   * The specialization on this type helps resolve the problem of
   * reference to void, and eliminates the need to specialize
   * _Pointer_adapter for cases of void*, const void*, and so on.
   */
  struct _Invalid_type { };

  template<typename _Tp>
    struct _Reference_type
    { typedef _Tp& reference; };

  template<>
    struct _Reference_type<void>
    { typedef _Invalid_type& reference; };

  template<>
    struct _Reference_type<const void>
    { typedef const _Invalid_type& reference; };

  template<>
    struct _Reference_type<volatile void>
    { typedef volatile _Invalid_type&  reference; };

  template<>
    struct _Reference_type<volatile const void>
    { typedef const volatile _Invalid_type&  reference; };

  /**
   * This structure accommodates the way in which
   * std::iterator_traits<> is normally specialized for const T*, so
   * that value_type is still T.
   */
  template<typename _Tp>
    struct _Unqualified_type
    { typedef _Tp type; };

  template<typename _Tp>
    struct _Unqualified_type<const _Tp>
    { typedef _Tp type; };

  /**
   * The following provides an 'alternative pointer' that works with
   * the containers when specified as the pointer typedef of the
   * allocator.
   *
   * The pointer type used with the containers doesn't have to be this
   * class, but it must support the implicit conversions, pointer
   * arithmetic, comparison operators, etc. that are supported by this
   * class, and avoid raising compile-time ambiguities.  Because
   * creating a working pointer can be challenging, this pointer
   * template was designed to wrapper an easier storage policy type,
   * so that it becomes reusable for creating other pointer types.
   *
   * A key point of this class is also that it allows container
   * writers to 'assume' Allocator::pointer is a typedef for a normal
   * pointer.  This class supports most of the conventions of a true
   * pointer, and can, for instance handle implicit conversion to
   * const and base class pointer types.  The only impositions on
   * container writers to support extended pointers are: 1) use the
   * Allocator::pointer typedef appropriately for pointer types.  2)
   * if you need pointer casting, use the __pointer_cast<> functions
   * from ext/cast.h.  This allows pointer cast operations to be
   * overloaded as necessary by custom pointers.
   *
   * Note: The const qualifier works with this pointer adapter as
   * follows:
   *
   * _Tp*             == _Pointer_adapter<_Std_pointer_impl<_Tp> >;
   * const _Tp*       == _Pointer_adapter<_Std_pointer_impl<const _Tp> >;
   * _Tp* const       == const _Pointer_adapter<_Std_pointer_impl<_Tp> >;
   * const _Tp* const == const _Pointer_adapter<_Std_pointer_impl<const _Tp> >;
   */
  template<typename _Storage_policy>
    class _Pointer_adapter : public _Storage_policy
    {
    public:
      typedef typename _Storage_policy::element_type element_type;

      // These are needed for iterator_traits
      typedef std::random_access_iterator_tag                iterator_category;
      typedef typename _Unqualified_type<element_type>::type value_type;
      typedef std::ptrdiff_t                                 difference_type;
      typedef _Pointer_adapter                               pointer;
      typedef typename _Reference_type<element_type>::reference  reference;

      // Reminder: 'const' methods mean that the method is valid when the
      // pointer is immutable, and has nothing to do with whether the
      // 'pointee' is const.

      // Default Constructor (Convert from element_type*)
      _Pointer_adapter(element_type* __arg = 0)
      { _Storage_policy::set(__arg); }

      // Copy constructor from _Pointer_adapter of same type.
      _Pointer_adapter(const _Pointer_adapter& __arg)
      { _Storage_policy::set(__arg.get()); }

      // Convert from _Up* if conversion to element_type* is valid.
      template<typename _Up>
        _Pointer_adapter(_Up* __arg)
        { _Storage_policy::set(__arg); }

      // Conversion from another _Pointer_adapter if _Up if static cast is
      // valid.
      template<typename _Up>
        _Pointer_adapter(const _Pointer_adapter<_Up>& __arg)
        { _Storage_policy::set(__arg.get()); }

      // Destructor
      ~_Pointer_adapter() { }

      // Assignment operator
      _Pointer_adapter&
      operator=(const _Pointer_adapter& __arg)
      {
        _Storage_policy::set(__arg.get());
        return *this;
      }

      template<typename _Up>
        _Pointer_adapter&
        operator=(const _Pointer_adapter<_Up>& __arg)
        {
          _Storage_policy::set(__arg.get());
          return *this;
        }

      template<typename _Up>
        _Pointer_adapter&
        operator=(_Up* __arg)
        {
          _Storage_policy::set(__arg);
          return *this;
        }

      // Operator*, returns element_type&
      inline reference
      operator*() const
      { return *(_Storage_policy::get()); }

      // Operator->, returns element_type*
      inline element_type*
      operator->() const
      { return _Storage_policy::get(); }

      // Operator[], returns a element_type& to the item at that loc.
      inline reference
      operator[](std::ptrdiff_t __index) const
      { return _Storage_policy::get()[__index]; }

      // To allow implicit conversion to "bool", for "if (ptr)..."
#if __cplusplus >= 201103L
      explicit operator bool() const { return _Storage_policy::get() != 0; }
#else
    private:
      typedef element_type*(_Pointer_adapter::*__unspecified_bool_type)() const;

    public:
      operator __unspecified_bool_type() const
      {
        return _Storage_policy::get() == 0 ? 0 :
                         &_Pointer_adapter::operator->;
      }

      // ! operator (for: if (!ptr)...)
      inline bool
      operator!() const
      { return (_Storage_policy::get() == 0); }
#endif

      // Pointer differences
      inline friend std::ptrdiff_t
      operator-(const _Pointer_adapter& __lhs, element_type* __rhs)
      { return (__lhs.get() - __rhs); }

      inline friend std::ptrdiff_t
      operator-(element_type* __lhs, const _Pointer_adapter& __rhs)
      { return (__lhs - __rhs.get()); }

      template<typename _Up>
        inline friend std::ptrdiff_t
        operator-(const _Pointer_adapter& __lhs, _Up* __rhs)
        { return (__lhs.get() - __rhs); }

      template<typename _Up>
        inline friend std::ptrdiff_t
        operator-(_Up* __lhs, const _Pointer_adapter& __rhs)
        { return (__lhs - __rhs.get()); }

      template<typename _Up>
        inline std::ptrdiff_t
        operator-(const _Pointer_adapter<_Up>& __rhs) const
        { return (_Storage_policy::get() - __rhs.get()); }

      // Pointer math
      // Note: There is a reason for all this overloading based on different
      // integer types.  In some libstdc++-v3 test cases, a templated
      // operator+ is declared which can match any types.  This operator
      // tends to "steal" the recognition of _Pointer_adapter's own operator+
      // unless the integer type matches perfectly.

#define _CXX_POINTER_ARITH_OPERATOR_SET(INT_TYPE) \
      inline friend _Pointer_adapter \
      operator+(const _Pointer_adapter& __lhs, INT_TYPE __offset) \
      { return _Pointer_adapter(__lhs.get() + __offset); } \
\
      inline friend _Pointer_adapter \
      operator+(INT_TYPE __offset, const _Pointer_adapter& __rhs) \
      { return _Pointer_adapter(__rhs.get() + __offset); } \
\
      inline friend _Pointer_adapter \
      operator-(const _Pointer_adapter& __lhs, INT_TYPE __offset) \
      { return _Pointer_adapter(__lhs.get() - __offset); } \
\
      inline _Pointer_adapter& \
      operator+=(INT_TYPE __offset) \
      { \
        _Storage_policy::set(_Storage_policy::get() + __offset); \
        return *this; \
      } \
\
      inline _Pointer_adapter& \
      operator-=(INT_TYPE __offset) \
      { \
        _Storage_policy::set(_Storage_policy::get() - __offset); \
        return *this; \
      } \
// END of _CXX_POINTER_ARITH_OPERATOR_SET macro

      // Expand into the various pointer arithmetic operators needed.
      _CXX_POINTER_ARITH_OPERATOR_SET(short);
      _CXX_POINTER_ARITH_OPERATOR_SET(unsigned short);
      _CXX_POINTER_ARITH_OPERATOR_SET(int);
      _CXX_POINTER_ARITH_OPERATOR_SET(unsigned int);
      _CXX_POINTER_ARITH_OPERATOR_SET(long);
      _CXX_POINTER_ARITH_OPERATOR_SET(unsigned long);
#ifdef _GLIBCXX_USE_LONG_LONG
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wlong-long"
      _CXX_POINTER_ARITH_OPERATOR_SET(long long);
      _CXX_POINTER_ARITH_OPERATOR_SET(unsigned long long);
#pragma GCC diagnostic pop
#endif

      // Mathematical Manipulators
      inline _Pointer_adapter&
      operator++()
      {
        _Storage_policy::set(_Storage_policy::get() + 1);
        return *this;
      }

      inline _Pointer_adapter
      operator++(int)
      {
        _Pointer_adapter __tmp(*this);
        _Storage_policy::set(_Storage_policy::get() + 1);
        return __tmp;
      }

      inline _Pointer_adapter&
      operator--()
      {
        _Storage_policy::set(_Storage_policy::get() - 1);
        return *this;
      }

      inline _Pointer_adapter
      operator--(int)
      {
        _Pointer_adapter __tmp(*this);
        _Storage_policy::set(_Storage_policy::get() - 1);
        return __tmp;
      }

#if __cpp_lib_three_way_comparison
      friend std::strong_ordering
      operator<=>(const _Pointer_adapter& __lhs, const _Pointer_adapter& __rhs)
      noexcept
      { return __lhs.get() <=> __rhs.get(); }
#endif
    }; // class _Pointer_adapter


#define _GCC_CXX_POINTER_COMPARISON_OPERATION_SET(OPERATOR) \
  template<typename _Tp1, typename _Tp2> \
    inline bool \
    operator OPERATOR(const _Pointer_adapter<_Tp1>& __lhs, _Tp2 __rhs) \
    { return __lhs.get() OPERATOR __rhs; } \
\
  template<typename _Tp1, typename _Tp2> \
    inline bool \
    operator OPERATOR(_Tp1 __lhs, const _Pointer_adapter<_Tp2>& __rhs) \
    { return __lhs OPERATOR __rhs.get(); } \
\
  template<typename _Tp1, typename _Tp2> \
    inline bool \
    operator OPERATOR(const _Pointer_adapter<_Tp1>& __lhs, \
                              const _Pointer_adapter<_Tp2>& __rhs) \
    { return __lhs.get() OPERATOR __rhs.get(); } \
\
// End GCC_CXX_POINTER_COMPARISON_OPERATION_SET Macro

  // Expand into the various comparison operators needed.
  _GCC_CXX_POINTER_COMPARISON_OPERATION_SET(==)
  _GCC_CXX_POINTER_COMPARISON_OPERATION_SET(!=)
  _GCC_CXX_POINTER_COMPARISON_OPERATION_SET(<)
  _GCC_CXX_POINTER_COMPARISON_OPERATION_SET(<=)
  _GCC_CXX_POINTER_COMPARISON_OPERATION_SET(>)
  _GCC_CXX_POINTER_COMPARISON_OPERATION_SET(>=)

  // These are here for expressions like "ptr == 0", "ptr != 0"
  template<typename _Tp>
    inline bool
    operator==(const _Pointer_adapter<_Tp>& __lhs, int __rhs)
    { return __lhs.get() == reinterpret_cast<void*>(__rhs); }

  template<typename _Tp>
    inline bool
    operator==(int __lhs, const _Pointer_adapter<_Tp>& __rhs)
    { return __rhs.get() == reinterpret_cast<void*>(__lhs); }

  template<typename _Tp>
    inline bool
    operator!=(const _Pointer_adapter<_Tp>& __lhs, int __rhs)
    { return __lhs.get() != reinterpret_cast<void*>(__rhs); }

  template<typename _Tp>
    inline bool
    operator!=(int __lhs, const _Pointer_adapter<_Tp>& __rhs)
    { return __rhs.get() != reinterpret_cast<void*>(__lhs); }

  /**
   * Comparison operators for _Pointer_adapter defer to the base class'
   * comparison operators, when possible.
   */
  template<typename _Tp>
    inline bool
    operator==(const _Pointer_adapter<_Tp>& __lhs,
               const _Pointer_adapter<_Tp>& __rhs)
    { return __lhs._Tp::operator==(__rhs); }

  template<typename _Tp>
    inline bool
    operator<=(const _Pointer_adapter<_Tp>& __lhs,
               const _Pointer_adapter<_Tp>& __rhs)
    { return __lhs._Tp::operator<(__rhs) || __lhs._Tp::operator==(__rhs); }

  template<typename _Tp>
    inline bool
    operator!=(const _Pointer_adapter<_Tp>& __lhs,
               const _Pointer_adapter<_Tp>& __rhs)
    { return !(__lhs._Tp::operator==(__rhs)); }

  template<typename _Tp>
    inline bool
    operator>(const _Pointer_adapter<_Tp>& __lhs,
              const _Pointer_adapter<_Tp>& __rhs)
    { return !(__lhs._Tp::operator<(__rhs) || __lhs._Tp::operator==(__rhs)); }

  template<typename _Tp>
    inline bool
    operator>=(const _Pointer_adapter<_Tp>& __lhs,
               const _Pointer_adapter<_Tp>& __rhs)
    { return !(__lhs._Tp::operator<(__rhs)); }

#if _GLIBCXX_HOSTED
  template<typename _CharT, typename _Traits, typename _StoreT>
    inline std::basic_ostream<_CharT, _Traits>&
    operator<<(std::basic_ostream<_CharT, _Traits>& __os,
               const _Pointer_adapter<_StoreT>& __p)
    { return (__os << __p.get()); }
#endif // HOSTED

_GLIBCXX_END_NAMESPACE_VERSION
} // namespace

#if __cplusplus >= 201103L
namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION

  template<typename _Storage_policy>
    struct pointer_traits<__gnu_cxx::_Pointer_adapter<_Storage_policy>>
    {
      /// The pointer type
      typedef __gnu_cxx::_Pointer_adapter<_Storage_policy>         pointer;
      /// The type pointed to
      typedef typename pointer::element_type            element_type;
      /// Type used to represent the difference between two pointers
      typedef typename pointer::difference_type         difference_type;

      template<typename _Up>
        using rebind = typename __gnu_cxx::_Pointer_adapter<
	  typename pointer_traits<_Storage_policy>::template rebind<_Up>>;

      static pointer pointer_to(typename pointer::reference __r) noexcept
      { return pointer(std::addressof(__r)); }
    };

#if __cpp_lib_concepts
  template<typename _Policy>
    struct indirectly_readable_traits<__gnu_cxx::_Pointer_adapter<_Policy>>
    {
      using value_type
	= typename __gnu_cxx::_Pointer_adapter<_Policy>::value_type;
    };
#endif
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace
#endif

#endif // _POINTER_H
