1 /*---------------------------------------------------------------------\
3 | |__ / \ / / . \ . \ |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/UserData.h
11 #ifndef ZYPP_USERDATA_H
12 #define ZYPP_USERDATA_H
17 #include <boost/any.hpp>
19 #include "zypp/base/PtrTypes.h"
20 #include "zypp/ContentType.h"
22 ///////////////////////////////////////////////////////////////////
25 ///////////////////////////////////////////////////////////////////
28 ///////////////////////////////////////////////////////////////////
30 /// \brief Typesafe passing of user data via callbacks
32 /// Basically a <tt>std::map<std::string,AnyType></tt> plus
33 /// associated \ref ContentType.
35 /// Constness protects non-empty values from being modified.
36 /// It is possible to overwrite empty values or to add new ones.
37 ///////////////////////////////////////////////////////////////////
41 typedef boost::any AnyType;
42 typedef boost::bad_any_cast bad_AnyType_cast;
44 typedef std::map<std::string,AnyType> DataType;
45 typedef DataType::size_type size_type;
46 typedef DataType::key_type key_type;
47 typedef DataType::value_type value_type;
48 typedef DataType::const_iterator const_iterator;
50 typedef zypp::ContentType ContentType;
57 /** Ctor taking ContentType. */
58 explicit UserData( ContentType type_r )
59 : _type( std::move(type_r) )
61 /** Ctor taking ContentType. */
62 explicit UserData( std::string type_r )
63 : UserData( ContentType( std::move(type_r) ) )
65 /** Ctor taking ContentType. */
66 UserData( std::string type_r, std::string subtype_r )
67 : UserData( ContentType( std::move(type_r), std::move(subtype_r) ) )
72 const ContentType & type() const
76 void type( ContentType type_r )
77 { _type = std::move(type_r); }
80 /** Validate object in a boolean context: has data */
81 explicit operator bool() const
84 /** Whether \ref data is empty. */
86 { return !_dataP || _dataP->empty(); }
88 /** Size of \ref data. */
89 size_type size() const
90 { return _dataP ? _dataP->size() : 0; }
93 const DataType & data() const
96 /** Whether \a key_r is in \ref data. */
97 bool haskey( const std::string & key_r ) const
98 { return _dataP && _dataP->find( key_r ) != _dataP->end(); }
100 /** Whether \a key_r is in \ref data and value is not empty. */
101 bool hasvalue( const std::string & key_r ) const
106 const_iterator it = _dataP->find( key_r );
107 if ( it != _dataP->end() && ! it->second.empty() )
115 /** Set the value for key (nonconst version always returns true).
116 * Const version is allowed to set empty values or to add new ones only.
118 bool set( const std::string & key_r, AnyType val_r )
119 { dataRef()[key_r] = std::move(val_r); return true; }
120 /** \overload const version */
121 bool set( const std::string & key_r, AnyType val_r ) const
124 AnyType & val( dataRef()[key_r] );
127 val = std::move(val_r);
133 /** Set an empty value for \a key_r (if possible). */
134 bool reset( const std::string & key_r )
135 { return set( key_r, AnyType() ); }
136 /** \overload const version */
137 bool reset( const std::string & key_r ) const
138 { return set( key_r, AnyType() ); }
140 /** Remove key from data.*/
141 void erase( const std::string & key_r )
142 { if ( _dataP ) _dataP->erase( key_r ); }
144 /** \ref get helper returning the keys AnyType value or an empty value if key does not exist. */
145 const AnyType & getvalue( const std::string & key_r ) const
149 const_iterator it = _dataP->find( key_r );
150 if ( it != _dataP->end() )
155 static const AnyType none;
159 /** Pass back a <tt>const Tp &</tt> reference to \a key_r value.
160 * \throws bad_AnyType_cast if key is not set or value is not of appropriate type
163 * std::string value( "defaultvalue" );
166 * value = data.get<std::string>( "mykey" );
168 * catch ( const UserData::bad_AnyType_cast & )
170 * // no "mykey" or not a std::sting
175 const Tp & get( const std::string & key_r ) const
176 { return boost::any_cast<const Tp &>( getvalue( key_r ) ); }
178 /** Pass back a \a Tp copy of \a key_r value.
179 * \throws bad_AnyType_cast if key is not set or value is not of appropriate type
182 * std::string value = data.get<std::string>( "mykey", "defaultvalue" );
186 Tp get( const std::string & key_r, const Tp & default_r ) const
187 { Tp ret( default_r ); get( key_r, ret ); return ret; }
189 /** 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;.
192 * std::string value( "defaultvalue" );
193 * if ( ! data.get<std::string>( "mykey", value )
195 * // no "mykey" or not a std::sting
200 bool get( const std::string & key_r, Tp & ret_r ) const
205 const_iterator it = _dataP->find( key_r );
206 if ( it != _dataP->end() )
208 auto ptr = boost::any_cast<const Tp>(&it->second);
220 DataType & dataRef() const
221 { if ( ! _dataP ) _dataP.reset( new DataType ); return *_dataP; }
225 mutable shared_ptr<DataType> _dataP;
228 /** \relates UserData Stream output */
229 inline std::ostream & operator<<( std::ostream & str, const UserData & obj )
230 { return str << "UserData(" << obj.type() << ":" << obj.size() << ")";}
232 } // namespace callback
233 ///////////////////////////////////////////////////////////////////
235 ///////////////////////////////////////////////////////////////////
236 #endif // ZYPP_USERDATA_H