String: don't split at quoted sep-chars
[platform/upstream/libzypp.git] / zypp / base / PtrTypes.h
1 /*---------------------------------------------------------------------\
2 |                          ____ _   __ __ ___                          |
3 |                         |__  / \ / / . \ . \                         |
4 |                           / / \ V /|  _/  _/                         |
5 |                          / /__ | | | | | |                           |
6 |                         /_____||_| |_| |_|                           |
7 |                                                                      |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/base/PtrTypes.h
10  *  \ingroup ZYPP_SMART_PTR
11  *  \see ZYPP_SMART_PTR
12 */
13 #ifndef ZYPP_BASE_PTRTYPES_H
14 #define ZYPP_BASE_PTRTYPES_H
15
16 #include <string>
17
18 #include <boost/scoped_ptr.hpp>
19 #include <boost/shared_ptr.hpp>
20 #include <boost/weak_ptr.hpp>
21 #include <boost/intrusive_ptr.hpp>
22
23 ///////////////////////////////////////////////////////////////////
24 namespace zypp
25 { /////////////////////////////////////////////////////////////////
26
27     /** \defgroup ZYPP_SMART_PTR Smart pointer types
28      *  Smart pointer types.
29      *
30      * Namespace zypp provides 3 smart pointer types \b using the
31      * boost smart pointer library.
32      *
33      * \li \c scoped_ptr Simple sole ownership of single objects. Noncopyable.
34      *
35      * \li \c shared_ptr Object ownership shared among multiple pointers
36      *
37      * \li \c weak_ptr Non-owning observers of an object owned by shared_ptr.
38      *
39      * And \ref zypp::RW_pointer, as wrapper around a smart pointer,
40      * poviding \c const correct read/write access to the object it refers.
41     */
42     /*@{*/
43
44     /** shared_ptr custom deleter doing nothing.
45      * A custom deleter is a function being called when the
46      * last shared_ptr goes out of score. Per default the
47      * object gets deleted, but you can insall custom deleters
48      * as well. This one does nothing.
49      *
50      * \code
51      *  // Some class providing a std::istream
52      *  struct InpuStream
53      * {
54      *   // Per deafult use std::cin.
55      *   InputStream()
56      *   : _stream( &std::cin, NullDeleter() )
57      *   {}
58      *   // Or read from a file.
59      *   InputStream( const Pathname & file_r )
60      *   : _stream( new ifgzstream( _path.asString().c_str() ) )
61      *   {}
62      *   // Or use a stream priovided by the application.
63      *   InputStream( std::istream & stream_r )
64      *   : _stream( &stream_r, NullDeleter() )
65      *   {}
66      *
67      *   std::istream & stream()
68      *   { return *_stream; }
69      *
70      * private:
71      *   shared_ptr<std::istream> _stream;
72      * };
73      * \endcode
74     */
75     struct NullDeleter
76     {
77       void operator()( const void *const ) const
78       {}
79     };
80
81     /** \class scoped_ptr */
82     using boost::scoped_ptr;
83
84     /** \class shared_ptr */
85     using boost::shared_ptr;
86
87     /** \class weak_ptr */
88     using boost::weak_ptr;
89
90     /** \class intrusive_ptr */
91     using boost::intrusive_ptr;
92
93     /** */
94     using boost::static_pointer_cast;
95     /**  */
96     using boost::const_pointer_cast;
97     /**  */
98     using boost::dynamic_pointer_cast;
99
100   /////////////////////////////////////////////////////////////////
101 } // namespace zypp
102 ///////////////////////////////////////////////////////////////////
103 ///////////////////////////////////////////////////////////////////
104 namespace std
105 { /////////////////////////////////////////////////////////////////
106
107   // namespace sub {
108   //    class Foo;
109   //    typedef zypp::intrusive_ptr<Foo> Foo_Ptr; // see DEFINE_PTR_TYPE(NAME) macro below
110   // }
111
112   // Defined in namespace std g++ finds the output operator (König-Lookup),
113   // even if we typedef the pointer in a different namespace than ::zypp.
114   // Otherwise we had to define an output operator always in the same namespace
115   // as the typedef (else g++ will just print the pointer value).
116
117   /** \relates zypp::shared_ptr Stream output. */
118   template<class _D>
119   inline std::ostream & operator<<( std::ostream & str, const zypp::shared_ptr<_D> & obj )
120   {
121     if ( obj )
122       return str << *obj;
123     return str << std::string("NULL");
124   }
125   /** \relates zypp::shared_ptr Stream output. */
126   template<class _D>
127   inline std::ostream & dumpOn( std::ostream & str, const zypp::shared_ptr<_D> & obj )
128   {
129     if ( obj )
130       return dumpOn( str, *obj );
131     return str << std::string("NULL");
132   }
133
134   /** \relates zypp::intrusive_ptr Stream output. */
135   template<class _D>
136   inline std::ostream & operator<<( std::ostream & str, const zypp::intrusive_ptr<_D> & obj )
137   {
138     if ( obj )
139       return str << *obj;
140     return str << std::string("NULL");
141   }
142   /** \relates zypp::intrusive_ptr Stream output. */
143   template<class _D>
144   inline std::ostream & dumpOn( std::ostream & str, const zypp::intrusive_ptr<_D> & obj )
145   {
146     if ( obj )
147       return dumpOn( str, *obj );
148     return str << std::string("NULL");
149   }
150   /////////////////////////////////////////////////////////////////
151 } // namespace std
152 ///////////////////////////////////////////////////////////////////
153 ///////////////////////////////////////////////////////////////////
154 namespace zypp
155 { /////////////////////////////////////////////////////////////////
156
157     ///////////////////////////////////////////////////////////////////
158     //
159     //  RW_pointer traits
160     //
161     ///////////////////////////////////////////////////////////////////
162     /**
163      * Don't forgett to provide versions for _Ptr and _constPtr,
164      * esp. if creation a of temporary is not acceptable (eg. when
165      * checking the ref count value).
166     */
167     namespace rw_pointer {
168
169       template<class _D>
170         struct Shared
171         {
172           typedef shared_ptr<_D>       _Ptr;
173           typedef shared_ptr<const _D> _constPtr;
174           /** Check whether pointer is not shared. */
175           bool unique( const _constPtr & ptr_r )
176           { return !ptr_r || ptr_r.unique(); }
177           bool unique( const _Ptr & ptr_r )
178           { return !ptr_r || ptr_r.unique(); }
179           /** Return number of references. */
180           long use_count( const _constPtr & ptr_r ) const
181           { return ptr_r.use_count(); }
182           long use_count( const _Ptr & ptr_r ) const
183           { return ptr_r.use_count(); }
184         };
185
186       template<class _D>
187         struct Intrusive
188         {
189           typedef intrusive_ptr<_D>       _Ptr;
190           typedef intrusive_ptr<const _D> _constPtr;
191           /** Check whether pointer is not shared. */
192           bool unique( const _constPtr & ptr_r )
193           { return !ptr_r || (ptr_r->refCount() <= 1); }
194           bool unique( const _Ptr & ptr_r )
195           { return !ptr_r || (ptr_r->refCount() <= 1); }
196           /** Return number of references. */
197           long use_count( const _constPtr & ptr_r ) const
198           { return ptr_r ? ptr_r->refCount() : 0; }
199           long use_count( const _Ptr & ptr_r ) const
200           { return ptr_r ? ptr_r->refCount() : 0; }
201         };
202
203        template<class _D>
204         struct Scoped
205         {
206           typedef scoped_ptr<_D>       _Ptr;
207           typedef scoped_ptr<const _D> _constPtr;
208           /** Check whether pointer is not shared. */
209           bool unique( const _constPtr & ptr_r )
210           { return true; }
211           bool unique( const _Ptr & ptr_r )
212           { return true; }
213           /** Return number of references. */
214           long use_count( const _constPtr & ptr_r ) const
215           { return ptr_r ? 1 : 0; }
216           long use_count( const _Ptr & ptr_r ) const
217           { return ptr_r ? 1 : 0; }
218         };
219
220    }
221     ///////////////////////////////////////////////////////////////////
222
223     ///////////////////////////////////////////////////////////////////
224     //
225     //  CLASS NAME : RW_pointer
226     //
227     /** Wrapper for \c const correct access via \ref ZYPP_SMART_PTR.
228      *
229      * zypp::RW_pointer<tt>\<_D,_Traits></tt> stores a \ref ZYPP_SMART_PTR
230      * of type \c _Traits::_Ptr, which must be convertible into a <tt>_D *</tt>.
231      * Pointer style access (via \c -> and \c *) offers a <tt>const _D *</tt> in const
232      * a context, otherwise a <tt>_D *</tt>. Thus \em RW_ means \em read/write,
233      * as you get a different type, dependent on whether you're allowed to
234      * read or write.
235      *
236      * Forwarding access from an interface to an implemantation class, an
237      * RW_pointer prevents const interface methods from accidentally calling
238      * nonconst implementation methods.
239      *
240      * The second template argument defaults to
241      * <tt>_Traits = rw_pointer::Shared<_D></tt> thus wraping a
242      * <tt>shared_ptr<_D></tt>. To wrap an <tt>intrusive_ptr<_D></tt>
243      * use <tt>rw_pointer::Intrusive<_D></tt>.
244      *
245      * \see zypp::RWCOW_pointer for 'copy on write' functionality.
246      *
247      * \code
248      * #include "zypp/base/PtrTypes.h"
249      *
250      * class Foo
251      * {
252      *   ...
253      *   private:
254      *     // Implementation class
255      *     struct Impl;
256      *     // Pointer to implementation; actually a shared_ptr<Impl>
257      *     RW_pointer<Impl> _pimpl;
258      *
259      *     void baa()       { _pimpl->... } // is Impl *
260      *     void baa() const { _pimpl->... } // is Impl const *
261      * };
262      * \endcode
263     */
264     template<class _D, class _Traits = rw_pointer::Shared<_D> >
265       struct RW_pointer
266       {
267         typedef typename _Traits::_Ptr               _Ptr;
268         typedef typename _Traits::_constPtr          _constPtr;
269
270         RW_pointer()
271         {}
272
273         RW_pointer( std::nullptr_t )
274         {}
275
276         explicit
277         RW_pointer( typename _Ptr::element_type * dptr )
278         : _dptr( dptr )
279         {}
280
281         explicit
282         RW_pointer( _Ptr dptr )
283         : _dptr( dptr )
284         {}
285
286         RW_pointer & operator=( std::nullptr_t )
287         { reset(); return *this; }
288
289         void reset()
290         { _Ptr().swap( _dptr ); }
291
292         void reset( typename _Ptr::element_type * dptr )
293         { _Ptr( dptr ).swap( _dptr ); }
294
295         void swap( RW_pointer & rhs )
296         { _dptr.swap( rhs._dptr ); }
297
298         void swap( _Ptr & rhs )
299         { _dptr.swap( rhs ); }
300
301         explicit operator bool() const
302         { return _dptr.get() != nullptr; }
303
304         const _D & operator*() const
305         { return *_dptr; };
306
307         const _D * operator->() const
308         { return _dptr.operator->(); }
309
310         const _D * get() const
311         { return _dptr.get(); }
312
313         _D & operator*()
314         { return *_dptr; }
315
316         _D * operator->()
317         { return _dptr.operator->(); }
318
319         _D * get()
320         { return _dptr.get(); }
321
322       public:
323         bool unique() const
324         { return _Traits().unique( _dptr ); }
325
326         long use_count() const
327         { return _Traits().use_count( _dptr ); }
328
329         _constPtr getPtr() const
330         { return _dptr; }
331
332         _Ptr getPtr()
333         { return _dptr; }
334
335         _constPtr cgetPtr()
336         { return _dptr; }
337
338       private:
339         _Ptr _dptr;
340       };
341     ///////////////////////////////////////////////////////////////////
342
343     /** \relates RW_pointer Stream output.
344      *
345      * Print the \c _D object the RW_pointer refers, or \c "NULL"
346      * if the pointer is \c NULL.
347      */
348     template<class _D, class _Ptr>
349       inline std::ostream & operator<<( std::ostream & str, const RW_pointer<_D, _Ptr> & obj )
350       {
351         if ( obj.get() )
352           return str << *obj.get();
353         return str << std::string("NULL");
354       }
355
356     /** \relates RW_pointer */
357     template<class _D, class _Ptr>
358       inline bool operator==( const RW_pointer<_D, _Ptr> & lhs, const RW_pointer<_D, _Ptr> & rhs )
359       { return( lhs.get() == rhs.get() ); }
360     /** \relates RW_pointer */
361     template<class _D, class _Ptr>
362       inline bool operator==( const RW_pointer<_D, _Ptr> & lhs, const typename _Ptr::_Ptr & rhs )
363       { return( lhs.get() == rhs.get() ); }
364     /** \relates RW_pointer */
365     template<class _D, class _Ptr>
366       inline bool operator==( const typename _Ptr::_Ptr & lhs, const RW_pointer<_D, _Ptr> & rhs )
367       { return( lhs.get() == rhs.get() ); }
368     /** \relates RW_pointer */
369     template<class _D, class _Ptr>
370       inline bool operator==( const RW_pointer<_D, _Ptr> & lhs, const typename _Ptr::_constPtr & rhs )
371       { return( lhs.get() == rhs.get() ); }
372     /** \relates RW_pointer */
373     template<class _D, class _Ptr>
374       inline bool operator==( const typename _Ptr::_constPtr & lhs, const RW_pointer<_D, _Ptr> & rhs )
375       { return( lhs.get() == rhs.get() ); }
376     /** \relates RW_pointer */
377     template<class _D, class _Ptr>
378       inline bool operator==( const RW_pointer<_D, _Ptr> & lhs, std::nullptr_t )
379       { return( lhs.get() == nullptr ); }
380     /** \relates RW_pointer */
381     template<class _D, class _Ptr>
382       inline bool operator==( std::nullptr_t, const RW_pointer<_D, _Ptr> & rhs )
383       { return( nullptr == rhs.get() ); }
384
385
386     /** \relates RW_pointer */
387     template<class _D, class _Ptr>
388       inline bool operator!=( const RW_pointer<_D, _Ptr> & lhs, const RW_pointer<_D, _Ptr> & rhs )
389       { return ! ( lhs == rhs ); }
390     /** \relates RW_pointer */
391     template<class _D, class _Ptr>
392       inline bool operator!=( const RW_pointer<_D, _Ptr> & lhs, const typename _Ptr::_Ptr & rhs )
393       { return ! ( lhs == rhs ); }
394     /** \relates RW_pointer */
395     template<class _D, class _Ptr>
396       inline bool operator!=( const typename _Ptr::_Ptr & lhs, const RW_pointer<_D, _Ptr> & rhs )
397       { return ! ( lhs == rhs ); }
398     /** \relates RW_pointer */
399     template<class _D, class _Ptr>
400       inline bool operator!=( const RW_pointer<_D, _Ptr> & lhs, const typename _Ptr::_constPtr & rhs )
401       { return ! ( lhs == rhs ); }
402     /** \relates RW_pointer */
403     template<class _D, class _Ptr>
404       inline bool operator!=( const typename _Ptr::_constPtr & lhs, const RW_pointer<_D, _Ptr> & rhs )
405       { return ! ( lhs == rhs ); }
406     /** \relates RW_pointer */
407     template<class _D, class _Ptr>
408       inline bool operator!=( const RW_pointer<_D, _Ptr> & lhs, std::nullptr_t )
409       { return( lhs.get() != nullptr ); }
410     /** \relates RW_pointer */
411     template<class _D, class _Ptr>
412       inline bool operator!=( std::nullptr_t, const RW_pointer<_D, _Ptr> & rhs )
413       { return( nullptr != rhs.get() ); }
414
415     ///////////////////////////////////////////////////////////////////
416
417     /** \relates RWCOW_pointer Clone the underlying object.
418      * Calls \a rhs <tt>-\>clone()</tt>. Being defined as a
419      * function outside \ref RWCOW_pointer allows to overload
420      * it, in case a specific \a _D does not have <tt>clone()</tt>.
421      */
422     template<class _D>
423       inline _D * rwcowClone( const _D * rhs )
424       { return rhs->clone(); }
425
426     ///////////////////////////////////////////////////////////////////
427     //
428     //  CLASS NAME : RWCOW_pointer
429     //
430     /** \ref RW_pointer supporting 'copy on write' functionality.
431      *
432      * \em Write access to the underlying object creates a copy, iff
433      * the object is shared.
434      *
435      * See \ref RW_pointer.
436     */
437     template<class _D, class _Traits = rw_pointer::Shared<_D> >
438       struct RWCOW_pointer
439       {
440         typedef typename _Traits::_Ptr               _Ptr;
441         typedef typename _Traits::_constPtr          _constPtr;
442
443         RWCOW_pointer()
444         {}
445
446         RWCOW_pointer( std::nullptr_t )
447         {}
448
449         explicit
450         RWCOW_pointer( typename _Ptr::element_type * dptr )
451         : _dptr( dptr )
452         {}
453
454         explicit
455         RWCOW_pointer( _Ptr dptr )
456         : _dptr( dptr )
457         {}
458
459         RWCOW_pointer & operator=( std::nullptr_t )
460         { reset(); return *this; }
461
462         void reset()
463         { _Ptr().swap( _dptr ); }
464
465         void reset( typename _Ptr::element_type * dptr )
466         { _Ptr( dptr ).swap( _dptr ); }
467
468         void swap( RWCOW_pointer & rhs )
469         { _dptr.swap( rhs._dptr ); }
470
471         void swap( _Ptr & rhs )
472         { _dptr.swap( rhs ); }
473
474         explicit operator bool() const
475         { return _dptr.get() != nullptr; }
476
477         const _D & operator*() const
478         { return *_dptr; };
479
480         const _D * operator->() const
481         { return _dptr.operator->(); }
482
483         const _D * get() const
484         { return _dptr.get(); }
485
486         _D & operator*()
487         { assertUnshared(); return *_dptr; }
488
489         _D * operator->()
490         { assertUnshared(); return _dptr.operator->(); }
491
492         _D * get()
493         { assertUnshared(); return _dptr.get(); }
494
495       public:
496         bool unique() const
497         { return _Traits().unique( _dptr ); }
498
499         long use_count() const
500         { return _Traits().use_count( _dptr ); }
501
502         _constPtr getPtr() const
503         { return _dptr; }
504
505         _Ptr getPtr()
506         { assertUnshared(); return _dptr; }
507
508         _constPtr cgetPtr()
509         { return _dptr; }
510
511       private:
512
513         void assertUnshared()
514         {
515           if ( !unique() )
516             _Ptr( rwcowClone( _dptr.get() ) ).swap( _dptr );
517         }
518
519       private:
520         _Ptr _dptr;
521       };
522     ///////////////////////////////////////////////////////////////////
523
524     /** \relates RWCOW_pointer Stream output.
525      *
526      * Print the \c _D object the RWCOW_pointer refers, or \c "NULL"
527      * if the pointer is \c NULL.
528      */
529     template<class _D, class _Ptr>
530       inline std::ostream & operator<<( std::ostream & str, const RWCOW_pointer<_D, _Ptr> & obj )
531       {
532         if ( obj.get() )
533           return str << *obj.get();
534         return str << std::string("NULL");
535       }
536
537     /** \relates RWCOW_pointer */
538     template<class _D, class _Ptr>
539       inline bool operator==( const RWCOW_pointer<_D, _Ptr> & lhs, const RWCOW_pointer<_D, _Ptr> & rhs )
540       { return( lhs.get() == rhs.get() ); }
541     /** \relates RWCOW_pointer */
542     template<class _D, class _Ptr>
543       inline bool operator==( const RWCOW_pointer<_D, _Ptr> & lhs, const typename _Ptr::_Ptr & rhs )
544       { return( lhs.get() == rhs.get() ); }
545     /** \relates RWCOW_pointer */
546     template<class _D, class _Ptr>
547       inline bool operator==( const typename _Ptr::_Ptr & lhs, const RWCOW_pointer<_D, _Ptr> & rhs )
548       { return( lhs.get() == rhs.get() ); }
549     /** \relates RWCOW_pointer */
550     template<class _D, class _Ptr>
551       inline bool operator==( const RWCOW_pointer<_D, _Ptr> & lhs, const typename _Ptr::_constPtr & rhs )
552       { return( lhs.get() == rhs.get() ); }
553     /** \relates RWCOW_pointer */
554     template<class _D, class _Ptr>
555       inline bool operator==( const typename _Ptr::_constPtr & lhs, const RWCOW_pointer<_D, _Ptr> & rhs )
556       { return( lhs.get() == rhs.get() ); }
557     /** \relates RWCOW_pointer */
558     template<class _D, class _Ptr>
559       inline bool operator==( const RWCOW_pointer<_D, _Ptr> & lhs, std::nullptr_t )
560       { return( lhs.get() == nullptr ); }
561     /** \relates RWCOW_pointer */
562     template<class _D, class _Ptr>
563       inline bool operator==( std::nullptr_t, const RWCOW_pointer<_D, _Ptr> & rhs )
564       { return( nullptr == rhs.get() ); }
565
566     /** \relates RWCOW_pointer */
567     template<class _D, class _Ptr>
568       inline bool operator!=( const RWCOW_pointer<_D, _Ptr> & lhs, const RWCOW_pointer<_D, _Ptr> & rhs )
569       { return ! ( lhs == rhs ); }
570     /** \relates RWCOW_pointer */
571     template<class _D, class _Ptr>
572       inline bool operator!=( const RWCOW_pointer<_D, _Ptr> & lhs, const typename _Ptr::_Ptr & rhs )
573       { return ! ( lhs == rhs ); }
574     /** \relates RWCOW_pointer */
575     template<class _D, class _Ptr>
576       inline bool operator!=( const typename _Ptr::_Ptr & lhs, const RWCOW_pointer<_D, _Ptr> & rhs )
577       { return ! ( lhs == rhs ); }
578     /** \relates RWCOW_pointer */
579     template<class _D, class _Ptr>
580       inline bool operator!=( const RWCOW_pointer<_D, _Ptr> & lhs, const typename _Ptr::_constPtr & rhs )
581       { return ! ( lhs == rhs ); }
582     /** \relates RWCOW_pointer */
583     template<class _D, class _Ptr>
584       inline bool operator!=( const typename _Ptr::_constPtr & lhs, const RWCOW_pointer<_D, _Ptr> & rhs )
585       { return ! ( lhs == rhs ); }
586     /** \relates RWCOW_pointer */
587     template<class _D, class _Ptr>
588       inline bool operator!=( const RWCOW_pointer<_D, _Ptr> & lhs, std::nullptr_t )
589       { return( lhs.get() != nullptr ); }
590     /** \relates RWCOW_pointer */
591     template<class _D, class _Ptr>
592       inline bool operator!=( std::nullptr_t, const RWCOW_pointer<_D, _Ptr> & rhs )
593       { return( nullptr != rhs.get() ); }
594
595     ///////////////////////////////////////////////////////////////////
596
597     /*@}*/
598   /////////////////////////////////////////////////////////////////
599 } // namespace zypp
600 ///////////////////////////////////////////////////////////////////
601
602 /** Forward declaration of Ptr types */
603 #define DEFINE_PTR_TYPE(NAME) \
604 class NAME;                                                      \
605 extern void intrusive_ptr_add_ref( const NAME * );               \
606 extern void intrusive_ptr_release( const NAME * );               \
607 typedef zypp::intrusive_ptr<NAME>       NAME##_Ptr;        \
608 typedef zypp::intrusive_ptr<const NAME> NAME##_constPtr;
609
610 ///////////////////////////////////////////////////////////////////
611 #endif // ZYPP_BASE_PTRTYPES_H