// Custom pointer adapter and sample storage policies

// Copyright (C) 2008, 2009 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
 * @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

#include <iosfwd>
#include <bits/stl_iterator_base_types.h>
#include <ext/cast.h>
#include <ext/type_traits.h>

_GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)

  /** 
   * @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<_UIntPtrType>(this)
					+ _M_diff);
      }
  
      void 
      set(_Tp* __arg)
      {
        if (!__arg)
          _M_diff = 1;
        else
          _M_diff = reinterpret_cast<_UIntPtrType>(__arg) 
                    - reinterpret_cast<_UIntPtrType>(this);
      }
  
      // Comparison of pointers
      inline bool
      operator<(const _Relative_pointer_impl& __rarg) const
      { return (reinterpret_cast<_UIntPtrType>(this->get())
		< reinterpret_cast<_UIntPtrType>(__rarg.get())); }

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

    private:
      typedef __gnu_cxx::__conditional_type<
	 (sizeof(unsigned long) >= sizeof(void*)),
	 unsigned long, unsigned long long>::__type _UIntPtrType;
      _UIntPtrType _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<_UIntPtrType>(this) + _M_diff);
      }
  
      void 
      set(const _Tp* __arg)
      {
        if (!__arg)
          _M_diff = 1;
        else
          _M_diff = reinterpret_cast<_UIntPtrType>(__arg) 
                    - reinterpret_cast<_UIntPtrType>(this);
      }
  
      // Comparison of pointers
      inline bool
      operator<(const _Relative_pointer_impl& __rarg) const
      { return (reinterpret_cast<_UIntPtrType>(this->get())
		< reinterpret_cast<_UIntPtrType>(__rarg.get())); }

      inline bool
      operator==(const _Relative_pointer_impl& __rarg) const
      { return (reinterpret_cast<_UIntPtrType>(this->get())
		== reinterpret_cast<_UIntPtrType>(__rarg.get())); }
  
    private:
      typedef __gnu_cxx::__conditional_type
	<(sizeof(unsigned long) >= sizeof(void*)),
	 unsigned long, unsigned long long>::__type _UIntPtrType;
      _UIntPtrType _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 accomodates 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; };
    
  template<typename _Tp> 
    struct _Unqualified_type<volatile _Tp> 
    { typedef volatile _Tp type; };
    
  template<typename _Tp> 
    struct _Unqualified_type<volatile const _Tp> 
    { typedef volatile _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' Alocator::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
   *    is 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)..."
    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); }
  
      // 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 arithmatic 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);

      // Mathematical Manipulators
      inline _Pointer_adapter& 
      operator++()
      {
        _Storage_policy::set(_Storage_policy::get() + 1); 
        return *this;
      }
  
      inline _Pointer_adapter 
      operator++(int __unused) 
      {
        _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;
      }
  
    }; // class _Pointer_adapter


#define _GCC_CXX_POINTER_COMPARISON_OPERATION_SET(OPERATOR,BLANK) \
  template<typename _Tp1, typename _Tp2> \
    inline bool \
    operator OPERATOR##BLANK (const _Pointer_adapter<_Tp1>& __lhs, _Tp2 __rhs) \
    { return __lhs.get() OPERATOR##BLANK __rhs; } \
\
  template<typename _Tp1, typename _Tp2> \
    inline bool \
    operator OPERATOR##BLANK (_Tp1 __lhs, const _Pointer_adapter<_Tp2>& __rhs) \
    { return __lhs OPERATOR##BLANK __rhs.get(); } \
\
  template<typename _Tp1, typename _Tp2> \
    inline bool \
    operator OPERATOR##BLANK (const _Pointer_adapter<_Tp1>& __lhs, \
                              const _Pointer_adapter<_Tp2>& __rhs) \
    { return __lhs.get() OPERATOR##BLANK __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'es
   * 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)); }

  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()); }

_GLIBCXX_END_NAMESPACE

#endif // _POINTER_H
