1// Custom pointer adapter and sample storage policies
2
3// Copyright (C) 2008, 2009 Free Software Foundation, Inc.
4//
5// This file is part of the GNU ISO C++ Library.  This library is free
6// software; you can redistribute it and/or modify it under the
7// terms of the GNU General Public License as published by the
8// Free Software Foundation; either version 3, or (at your option)
9// any later version.
10
11// This library is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14// GNU General Public License for more details.
15
16// Under Section 7 of GPL version 3, you are granted additional
17// permissions described in the GCC Runtime Library Exception, version
18// 3.1, as published by the Free Software Foundation.
19
20// You should have received a copy of the GNU General Public License and
21// a copy of the GCC Runtime Library Exception along with this program;
22// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
23// <http://www.gnu.org/licenses/>.
24
25/**
26 * @file ext/pointer.h
27 * @author Bob Walters
28 *
29 * Provides reusable _Pointer_adapter for assisting in the development of
30 * custom pointer types that can be used with the standard containers via
31 * the allocator::pointer and allocator::const_pointer typedefs.
32 */
33
34#ifndef _POINTER_H
35#define _POINTER_H 1
36
37#include <iosfwd>
38#include <bits/stl_iterator_base_types.h>
39#include <ext/cast.h>
40#include <ext/type_traits.h>
41
42_GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
43
44  /**
45   * @brief A storage policy for use with _Pointer_adapter<> which yields a
46   *        standard pointer.
47   *
48   *  A _Storage_policy is required to provide 4 things:
49   *    1) A get() API for returning the stored pointer value.
50   *    2) An set() API for storing a pointer value.
51   *    3) An element_type typedef to define the type this points to.
52   *    4) An operator<() to support pointer comparison.
53   *    5) An operator==() to support pointer comparison.
54   */
55  template<typename _Tp>
56    class _Std_pointer_impl
57    {
58    public:
59      // the type this pointer points to.
60      typedef _Tp element_type;
61
62      // A method to fetch the pointer value as a standard T* value;
63      inline _Tp*
64      get() const
65      { return _M_value; }
66
67      // A method to set the pointer value, from a standard T* value;
68      inline void
69      set(element_type* __arg)
70      { _M_value = __arg; }
71
72      // Comparison of pointers
73      inline bool
74      operator<(const _Std_pointer_impl& __rarg) const
75      { return (_M_value < __rarg._M_value); }
76
77      inline bool
78      operator==(const _Std_pointer_impl& __rarg) const
79      { return (_M_value == __rarg._M_value); }
80
81    private:
82      element_type* _M_value;
83    };
84
85  /**
86   * @brief A storage policy for use with _Pointer_adapter<> which stores
87   *        the pointer's address as an offset value which is relative to
88   *        its own address.
89   *
90   * This is intended for pointers
91   * within shared memory regions which might be mapped at different
92   * addresses by different processes.  For null pointers, a value of 1 is
93   * used.  (0 is legitimate sometimes for nodes in circularly linked lists)
94   * This value was chosen as the least likely to generate an incorrect null,
95   * As there is no reason why any normal pointer would point 1 byte into
96   * its own pointer address.
97   */
98  template<typename _Tp>
99    class _Relative_pointer_impl
100    {
101    public:
102      typedef _Tp element_type;
103
104      _Tp*
105      get() const
106      {
107        if (_M_diff == 1)
108          return 0;
109        else
110          return reinterpret_cast<_Tp*>(reinterpret_cast<_UIntPtrType>(this)
111					+ _M_diff);
112      }
113
114      void
115      set(_Tp* __arg)
116      {
117        if (!__arg)
118          _M_diff = 1;
119        else
120          _M_diff = reinterpret_cast<_UIntPtrType>(__arg)
121                    - reinterpret_cast<_UIntPtrType>(this);
122      }
123
124      // Comparison of pointers
125      inline bool
126      operator<(const _Relative_pointer_impl& __rarg) const
127      { return (reinterpret_cast<_UIntPtrType>(this->get())
128		< reinterpret_cast<_UIntPtrType>(__rarg.get())); }
129
130      inline bool
131      operator==(const _Relative_pointer_impl& __rarg) const
132      { return (reinterpret_cast<_UIntPtrType>(this->get())
133		== reinterpret_cast<_UIntPtrType>(__rarg.get())); }
134
135    private:
136      typedef __gnu_cxx::__conditional_type<
137	 (sizeof(unsigned long) >= sizeof(void*)),
138	 unsigned long, unsigned long long>::__type _UIntPtrType;
139      _UIntPtrType _M_diff;
140    };
141
142  /**
143   * Relative_pointer_impl needs a specialization for const T because of
144   * the casting done during pointer arithmetic.
145   */
146  template<typename _Tp>
147    class _Relative_pointer_impl<const _Tp>
148    {
149    public:
150      typedef const _Tp element_type;
151
152      const _Tp*
153      get() const
154      {
155        if (_M_diff == 1)
156          return 0;
157        else
158          return reinterpret_cast<const _Tp*>
159	      (reinterpret_cast<_UIntPtrType>(this) + _M_diff);
160      }
161
162      void
163      set(const _Tp* __arg)
164      {
165        if (!__arg)
166          _M_diff = 1;
167        else
168          _M_diff = reinterpret_cast<_UIntPtrType>(__arg)
169                    - reinterpret_cast<_UIntPtrType>(this);
170      }
171
172      // Comparison of pointers
173      inline bool
174      operator<(const _Relative_pointer_impl& __rarg) const
175      { return (reinterpret_cast<_UIntPtrType>(this->get())
176		< reinterpret_cast<_UIntPtrType>(__rarg.get())); }
177
178      inline bool
179      operator==(const _Relative_pointer_impl& __rarg) const
180      { return (reinterpret_cast<_UIntPtrType>(this->get())
181		== reinterpret_cast<_UIntPtrType>(__rarg.get())); }
182
183    private:
184      typedef __gnu_cxx::__conditional_type
185	<(sizeof(unsigned long) >= sizeof(void*)),
186	 unsigned long, unsigned long long>::__type _UIntPtrType;
187      _UIntPtrType _M_diff;
188    };
189
190  /**
191   * The specialization on this type helps resolve the problem of
192   * reference to void, and eliminates the need to specialize _Pointer_adapter
193   * for cases of void*, const void*, and so on.
194   */
195  struct _Invalid_type { };
196
197  template<typename _Tp>
198    struct _Reference_type
199    { typedef _Tp& reference; };
200
201  template<>
202    struct _Reference_type<void>
203    { typedef _Invalid_type& reference; };
204
205  template<>
206    struct _Reference_type<const void>
207    { typedef const _Invalid_type& reference; };
208
209  template<>
210    struct _Reference_type<volatile void>
211    { typedef volatile _Invalid_type&  reference; };
212
213  template<>
214    struct _Reference_type<volatile const void>
215    { typedef const volatile _Invalid_type&  reference; };
216
217  /**
218   * This structure accomodates the way in which std::iterator_traits<>
219   * is normally specialized for const T*, so that value_type is still T.
220   */
221  template<typename _Tp>
222    struct _Unqualified_type
223    { typedef _Tp type; };
224
225  template<typename _Tp>
226    struct _Unqualified_type<const _Tp>
227    { typedef _Tp type; };
228
229  template<typename _Tp>
230    struct _Unqualified_type<volatile _Tp>
231    { typedef volatile _Tp type; };
232
233  template<typename _Tp>
234    struct _Unqualified_type<volatile const _Tp>
235    { typedef volatile _Tp type; };
236
237  /**
238   * The following provides an 'alternative pointer' that works with the
239   * containers when specified as the pointer typedef of the allocator.
240   *
241   * The pointer type used with the containers doesn't have to be this class,
242   * but it must support the implicit conversions, pointer arithmetic,
243   * comparison operators, etc. that are supported by this class, and avoid
244   * raising compile-time ambiguities.  Because creating a working pointer can
245   * be challenging, this pointer template was designed to wrapper an
246   * easier storage policy type, so that it becomes reusable for creating
247   * other pointer types.
248   *
249   * A key point of this class is also that it allows container writers to
250   * 'assume' Alocator::pointer is a typedef for a normal pointer.  This class
251   * supports most of the conventions of a true pointer, and can, for instance
252   * handle implicit conversion to const and base class pointer types.  The
253   * only impositions on container writers to support extended pointers are:
254   * 1) use the Allocator::pointer typedef appropriately for pointer types.
255   * 2) if you need pointer casting, use the __pointer_cast<> functions
256   *    from ext/cast.h.  This allows pointer cast operations to be overloaded
257   *    is necessary by custom pointers.
258   *
259   * Note:  The const qualifier works with this pointer adapter as follows:
260   *
261   * _Tp*             == _Pointer_adapter<_Std_pointer_impl<_Tp> >;
262   * const _Tp*       == _Pointer_adapter<_Std_pointer_impl<const _Tp> >;
263   * _Tp* const       == const _Pointer_adapter<_Std_pointer_impl<_Tp> >;
264   * const _Tp* const == const _Pointer_adapter<_Std_pointer_impl<const _Tp> >;
265   */
266  template<typename _Storage_policy>
267    class _Pointer_adapter : public _Storage_policy
268    {
269    public:
270      typedef typename _Storage_policy::element_type element_type;
271
272      // These are needed for iterator_traits
273      typedef std::random_access_iterator_tag                iterator_category;
274      typedef typename _Unqualified_type<element_type>::type value_type;
275      typedef std::ptrdiff_t                                 difference_type;
276      typedef _Pointer_adapter                               pointer;
277      typedef typename _Reference_type<element_type>::reference  reference;
278
279      // Reminder: 'const' methods mean that the method is valid when the
280      // pointer is immutable, and has nothing to do with whether the
281      // 'pointee' is const.
282
283      // Default Constructor (Convert from element_type*)
284      _Pointer_adapter(element_type* __arg = 0)
285      { _Storage_policy::set(__arg); }
286
287      // Copy constructor from _Pointer_adapter of same type.
288      _Pointer_adapter(const _Pointer_adapter& __arg)
289      { _Storage_policy::set(__arg.get()); }
290
291      // Convert from _Up* if conversion to element_type* is valid.
292      template<typename _Up>
293        _Pointer_adapter(_Up* __arg)
294        { _Storage_policy::set(__arg); }
295
296      // Conversion from another _Pointer_adapter if _Up if static cast is
297      // valid.
298      template<typename _Up>
299        _Pointer_adapter(const _Pointer_adapter<_Up>& __arg)
300        { _Storage_policy::set(__arg.get()); }
301
302      // Destructor
303      ~_Pointer_adapter() { }
304
305      // Assignment operator
306      _Pointer_adapter&
307      operator=(const _Pointer_adapter& __arg)
308      {
309        _Storage_policy::set(__arg.get());
310        return *this;
311      }
312
313      template<typename _Up>
314        _Pointer_adapter&
315        operator=(const _Pointer_adapter<_Up>& __arg)
316        {
317          _Storage_policy::set(__arg.get());
318          return *this;
319        }
320
321      template<typename _Up>
322        _Pointer_adapter&
323        operator=(_Up* __arg)
324        {
325          _Storage_policy::set(__arg);
326          return *this;
327        }
328
329      // Operator*, returns element_type&
330      inline reference
331      operator*() const
332      { return *(_Storage_policy::get()); }
333
334      // Operator->, returns element_type*
335      inline element_type*
336      operator->() const
337      { return _Storage_policy::get(); }
338
339      // Operator[], returns a element_type& to the item at that loc.
340      inline reference
341      operator[](std::ptrdiff_t __index) const
342      { return _Storage_policy::get()[__index]; }
343
344      // To allow implicit conversion to "bool", for "if (ptr)..."
345    private:
346      typedef element_type*(_Pointer_adapter::*__unspecified_bool_type)() const;
347
348    public:
349      operator __unspecified_bool_type() const
350      {
351        return _Storage_policy::get() == 0 ? 0 :
352                         &_Pointer_adapter::operator->;
353      }
354
355      // ! operator (for: if (!ptr)...)
356      inline bool
357      operator!() const
358      { return (_Storage_policy::get() == 0); }
359
360      // Pointer differences
361      inline friend std::ptrdiff_t
362      operator-(const _Pointer_adapter& __lhs, element_type* __rhs)
363      { return (__lhs.get() - __rhs); }
364
365      inline friend std::ptrdiff_t
366      operator-(element_type* __lhs, const _Pointer_adapter& __rhs)
367      { return (__lhs - __rhs.get()); }
368
369      template<typename _Up>
370        inline friend std::ptrdiff_t
371        operator-(const _Pointer_adapter& __lhs, _Up* __rhs)
372        { return (__lhs.get() - __rhs); }
373
374      template<typename _Up>
375        inline friend std::ptrdiff_t
376        operator-(_Up* __lhs, const _Pointer_adapter& __rhs)
377        { return (__lhs - __rhs.get()); }
378
379      template<typename _Up>
380        inline std::ptrdiff_t
381        operator-(const _Pointer_adapter<_Up>& __rhs) const
382        { return (_Storage_policy::get() - __rhs.get()); }
383
384      // Pointer math
385      // Note: There is a reason for all this overloading based on different
386      // integer types.  In some libstdc++-v3 test cases, a templated
387      // operator+ is declared which can match any types.  This operator
388      // tends to "steal" the recognition of _Pointer_adapter's own operator+
389      // unless the integer type matches perfectly.
390
391#define _CXX_POINTER_ARITH_OPERATOR_SET(INT_TYPE) \
392      inline friend _Pointer_adapter \
393      operator+(const _Pointer_adapter& __lhs, INT_TYPE __offset) \
394      { return _Pointer_adapter(__lhs.get() + __offset); } \
395\
396      inline friend _Pointer_adapter \
397      operator+(INT_TYPE __offset, const _Pointer_adapter& __rhs) \
398      { return _Pointer_adapter(__rhs.get() + __offset); } \
399\
400      inline friend _Pointer_adapter \
401      operator-(const _Pointer_adapter& __lhs, INT_TYPE __offset) \
402      { return _Pointer_adapter(__lhs.get() - __offset); } \
403\
404      inline _Pointer_adapter& \
405      operator+=(INT_TYPE __offset) \
406      { \
407        _Storage_policy::set(_Storage_policy::get() + __offset); \
408        return *this; \
409      } \
410\
411      inline _Pointer_adapter& \
412      operator-=(INT_TYPE __offset) \
413      { \
414        _Storage_policy::set(_Storage_policy::get() - __offset); \
415        return *this; \
416      } \
417// END of _CXX_POINTER_ARITH_OPERATOR_SET macro
418
419      // Expand into the various pointer arithmatic operators needed.
420      _CXX_POINTER_ARITH_OPERATOR_SET(short);
421      _CXX_POINTER_ARITH_OPERATOR_SET(unsigned short);
422      _CXX_POINTER_ARITH_OPERATOR_SET(int);
423      _CXX_POINTER_ARITH_OPERATOR_SET(unsigned int);
424      _CXX_POINTER_ARITH_OPERATOR_SET(long);
425      _CXX_POINTER_ARITH_OPERATOR_SET(unsigned long);
426
427      // Mathematical Manipulators
428      inline _Pointer_adapter&
429      operator++()
430      {
431        _Storage_policy::set(_Storage_policy::get() + 1);
432        return *this;
433      }
434
435      inline _Pointer_adapter
436      operator++(int __unused)
437      {
438        _Pointer_adapter tmp(*this);
439        _Storage_policy::set(_Storage_policy::get() + 1);
440        return tmp;
441      }
442
443      inline _Pointer_adapter&
444      operator--()
445      {
446        _Storage_policy::set(_Storage_policy::get() - 1);
447        return *this;
448      }
449
450      inline _Pointer_adapter
451      operator--(int)
452      {
453        _Pointer_adapter tmp(*this);
454        _Storage_policy::set(_Storage_policy::get() - 1);
455        return tmp;
456      }
457
458    }; // class _Pointer_adapter
459
460
461#define _GCC_CXX_POINTER_COMPARISON_OPERATION_SET(OPERATOR,BLANK) \
462  template<typename _Tp1, typename _Tp2> \
463    inline bool \
464    operator OPERATOR##BLANK (const _Pointer_adapter<_Tp1>& __lhs, _Tp2 __rhs) \
465    { return __lhs.get() OPERATOR##BLANK __rhs; } \
466\
467  template<typename _Tp1, typename _Tp2> \
468    inline bool \
469    operator OPERATOR##BLANK (_Tp1 __lhs, const _Pointer_adapter<_Tp2>& __rhs) \
470    { return __lhs OPERATOR##BLANK __rhs.get(); } \
471\
472  template<typename _Tp1, typename _Tp2> \
473    inline bool \
474    operator OPERATOR##BLANK (const _Pointer_adapter<_Tp1>& __lhs, \
475                              const _Pointer_adapter<_Tp2>& __rhs) \
476    { return __lhs.get() OPERATOR##BLANK __rhs.get(); } \
477\
478// End GCC_CXX_POINTER_COMPARISON_OPERATION_SET Macro
479
480  // Expand into the various comparison operators needed.
481  _GCC_CXX_POINTER_COMPARISON_OPERATION_SET(==,);
482  _GCC_CXX_POINTER_COMPARISON_OPERATION_SET(!=,);
483  _GCC_CXX_POINTER_COMPARISON_OPERATION_SET(<,);
484  _GCC_CXX_POINTER_COMPARISON_OPERATION_SET(<=,);
485  _GCC_CXX_POINTER_COMPARISON_OPERATION_SET(>,);
486  _GCC_CXX_POINTER_COMPARISON_OPERATION_SET(>=,);
487
488  // These are here for expressions like "ptr == 0", "ptr != 0"
489  template<typename _Tp>
490    inline bool
491    operator==(const _Pointer_adapter<_Tp>& __lhs, int __rhs)
492    { return __lhs.get() == reinterpret_cast<void*>(__rhs); }
493
494  template<typename _Tp>
495    inline bool
496    operator==(int __lhs, const _Pointer_adapter<_Tp>& __rhs)
497    { return __rhs.get() == reinterpret_cast<void*>(__lhs); }
498
499  template<typename _Tp>
500    inline bool
501    operator!=(const _Pointer_adapter<_Tp>& __lhs, int __rhs)
502    { return __lhs.get() != reinterpret_cast<void*>(__rhs); }
503
504  template<typename _Tp>
505    inline bool
506    operator!=(int __lhs, const _Pointer_adapter<_Tp>& __rhs)
507    { return __rhs.get() != reinterpret_cast<void*>(__lhs); }
508
509  /**
510   * Comparison operators for _Pointer_adapter defer to the base class'es
511   * comparison operators, when possible.
512   */
513  template<typename _Tp>
514    inline bool
515    operator==(const _Pointer_adapter<_Tp>& __lhs,
516               const _Pointer_adapter<_Tp>& __rhs)
517    { return __lhs._Tp::operator==(__rhs); }
518
519  template<typename _Tp>
520    inline bool
521    operator<=(const _Pointer_adapter<_Tp>& __lhs,
522               const _Pointer_adapter<_Tp>& __rhs)
523    { return __lhs._Tp::operator<(__rhs) || __lhs._Tp::operator==(__rhs); }
524
525  template<typename _Tp>
526    inline bool
527    operator!=(const _Pointer_adapter<_Tp>& __lhs,
528               const _Pointer_adapter<_Tp>& __rhs)
529    { return !(__lhs._Tp::operator==(__rhs)); }
530
531  template<typename _Tp>
532    inline bool
533    operator>(const _Pointer_adapter<_Tp>& __lhs,
534              const _Pointer_adapter<_Tp>& __rhs)
535    { return !(__lhs._Tp::operator<(__rhs) || __lhs._Tp::operator==(__rhs)); }
536
537  template<typename _Tp>
538    inline bool
539    operator>=(const _Pointer_adapter<_Tp>& __lhs,
540               const _Pointer_adapter<_Tp>& __rhs)
541    { return !(__lhs._Tp::operator<(__rhs)); }
542
543  template<typename _CharT, typename _Traits, typename _StoreT>
544    inline std::basic_ostream<_CharT, _Traits>&
545    operator<<(std::basic_ostream<_CharT, _Traits>& __os,
546               const _Pointer_adapter<_StoreT>& __p)
547    { return (__os << __p.get()); }
548
549_GLIBCXX_END_NAMESPACE
550
551#endif // _POINTER_H
552