Imported Upstream version 14.45.0
[platform/upstream/libzypp.git] / zypp / UserData.h
1 /*---------------------------------------------------------------------\
2 |                          ____ _   __ __ ___                          |
3 |                         |__  / \ / / . \ . \                         |
4 |                           / / \ V /|  _/  _/                         |
5 |                          / /__ | | | | | |                           |
6 |                         /_____||_| |_| |_|                           |
7 |                                                                      |
8 \---------------------------------------------------------------------*/
9 /** \file       zypp/UserData.h
10  */
11 #ifndef ZYPP_USERDATA_H
12 #define ZYPP_USERDATA_H
13
14 #include <iosfwd>
15 #include <string>
16 #include <map>
17 #include <boost/any.hpp>
18
19 #include "zypp/base/PtrTypes.h"
20 #include "zypp/ContentType.h"
21
22 ///////////////////////////////////////////////////////////////////
23 namespace zypp
24 {
25   ///////////////////////////////////////////////////////////////////
26   namespace callback
27   {
28     ///////////////////////////////////////////////////////////////////
29     /// \class UserData
30     /// \brief Typesafe passing of user data via callbacks
31     ///
32     /// Basically a <tt>std::map<std::string,boost::any></tt> plus
33     /// associated \ref ContentType.
34     ///
35     /// Constness protects non-empty values from being modified.
36     /// It is possible to overwrite empty values or to add new ones.
37     ///////////////////////////////////////////////////////////////////
38     class UserData
39     {
40       typedef std::map<std::string,boost::any> DataType;
41       typedef DataType::size_type size_type;
42       typedef DataType::key_type key_type;
43       typedef DataType::value_type value_type;
44       typedef DataType::const_iterator const_iterator;
45     public:
46       /** Default ctor. */
47       UserData()
48       {}
49
50       /** Ctor taking ContentType. */
51       explicit UserData( ContentType type_r )
52       : _type( std::move(type_r) )
53       {}
54       /** Ctor taking ContentType. */
55       explicit UserData( std::string type_r )
56       : UserData( ContentType( std::move(type_r) ) )
57       {}
58       /** Ctor taking ContentType. */
59       UserData( std::string type_r, std::string subtype_r )
60       : UserData( ContentType( std::move(type_r), std::move(subtype_r) ) )
61       {}
62
63     public:
64       /** Get type. */
65       const ContentType & type() const
66       { return _type; }
67
68       /** Set type. */
69       void type( ContentType type_r )
70       { _type = std::move(type_r); }
71
72     public:
73        /**  Validate object in a boolean context: has data */
74       explicit operator bool() const
75       { return !empty(); }
76
77       /** Whether \ref data is empty. */
78       bool empty() const
79       { return !_dataP || _dataP->empty(); }
80
81       /** Size of \ref data. */
82       size_type size() const
83       { return _dataP ? _dataP->size() : 0;  }
84
85       /** The \ref data. */
86       const DataType & data() const
87       { return dataRef(); }
88
89       /** Whether \a key_r is in \ref data. */
90       bool haskey( const std::string & key_r ) const
91       { return _dataP && _dataP->find( key_r ) != _dataP->end(); }
92
93       /** Whether \a key_r is in \ref data and value is not empty. */
94       bool hasvalue( const std::string & key_r ) const
95       {
96         bool ret = false;
97         if ( _dataP )
98         {
99           const_iterator it = _dataP->find( key_r );
100           if ( it != _dataP->end() && ! it->second.empty() )
101           {
102             ret = true;
103           }
104         }
105         return ret;
106       }
107
108       /** Set the value for key (nonconst version always returns true).
109        * Const version is allowed to set empty values or to add new ones only.
110        */
111       bool set( const std::string & key_r, boost::any val_r )
112       { dataRef()[key_r] = std::move(val_r); return true; }
113       /** \overload const version */
114       bool set( const std::string & key_r, boost::any val_r ) const
115       {
116         bool ret = false;
117         boost::any & val( dataRef()[key_r] );
118         if ( val.empty() )
119         {
120           val = std::move(val_r);
121           ret = true;
122         }
123         return ret;
124       }
125
126       /** Set an empty value for \a key_r (if possible). */
127       bool reset( const std::string & key_r )
128       { return set( key_r, boost::any() ); }
129       /** \overload const version */
130       bool reset( const std::string & key_r ) const
131       { return set( key_r, boost::any() ); }
132
133       /** Remove key from data.*/
134       void erase( const std::string & key_r )
135       { if ( _dataP ) _dataP->erase( key_r ); }
136
137       /** Return the keys boost::any value or an empty value if key does not exist. */
138       const boost::any & getvalue( const std::string & key_r ) const
139       {
140         if ( _dataP )
141         {
142           const_iterator it = _dataP->find( key_r );
143           if ( it != _dataP->end() )
144           {
145             return it->second;
146           }
147         }
148         static const boost::any none;
149         return none;
150       }
151
152       /** Pass back a <tt>const Tp &</tt> reference to \a key_r value.
153        * \throws boost::bad_any_cast if key is not set or value is not of appropriate type
154        * \code
155        *   UserData data;
156        *   std::string value( "defaultvalue" );
157        *   try
158        *   {
159        *     value = data.get<std::string>( "mykey" );
160        *   }
161        *   catch ( const boost::bad_any_cast & )
162        *   {
163        *     // no "mykey" or not a std::sting
164        *   }
165        * \endcode
166        */
167       template <class Tp>
168       const Tp & get( const std::string & key_r ) const
169       { return boost::any_cast<const Tp &>( getvalue( key_r ) ); }
170
171       /** Pass back a \a Tp copy of \a key_r value.
172        * \throws boost::bad_any_cast if key is not set or value is not of appropriate type
173        * \code
174        *   UserData data;
175        *   std::string value = data.get<std::string>( "mykey", "defaultvalue" );
176        * \endcode
177        */
178       template <class Tp>
179       Tp get( const std::string & key_r, const Tp & default_r ) const
180       { Tp ret( default_r ); get( key_r, ret ); return ret; }
181
182       /** If the value for \a key_r is of the same type as \a ret_r, pass it back in \a ret_r and return \c true;.
183        * \code
184        *   UserData data;
185        *   std::string value( "defaultvalue" );
186        *   if ( ! data.get<std::string>( "mykey", value )
187        *   {
188        *      // no "mykey" or not a std::sting
189        *   }
190        * \endcode
191        */
192       template <class Tp>
193       bool get( const std::string & key_r, Tp & ret_r ) const
194       {
195         bool ret = false;
196         if ( _dataP )
197         {
198           const_iterator it = _dataP->find( key_r );
199           if ( it != _dataP->end() )
200           {
201             auto ptr = boost::any_cast<const Tp>(&it->second);
202             if ( ptr )
203             {
204               ret_r = *ptr;
205               ret = true;
206             }
207           }
208         }
209         return ret;
210       }
211
212     private:
213       DataType & dataRef() const
214       { if ( ! _dataP ) _dataP.reset( new DataType ); return *_dataP; }
215
216     private:
217       ContentType _type;
218       mutable shared_ptr<DataType> _dataP;
219     };
220
221     /** \relates UserData Stream output */
222     inline std::ostream & operator<<( std::ostream & str, const UserData & obj )
223     { return str << "UserData(" << obj.type() << ":" << obj.size() << ")";}
224
225   } // namespace callback
226   ///////////////////////////////////////////////////////////////////
227 } // namespace zypp
228 ///////////////////////////////////////////////////////////////////
229 #endif // ZYPP_USERDATA_H