Imported Upstream version 16.3.2
[platform/upstream/libzypp.git] / zypp / base / Flags.h
1 /*---------------------------------------------------------------------\
2 |                          ____ _   __ __ ___                          |
3 |                         |__  / \ / / . \ . \                         |
4 |                           / / \ V /|  _/  _/                         |
5 |                          / /__ | | | | | |                           |
6 |                         /_____||_| |_| |_|                           |
7 |                                                                      |
8 \---------------------------------------------------------------------*/
9 /** \file       zypp/base/Flags.h
10  *
11 */
12 #ifndef ZYPP_BASE_FLAGS_H
13 #define ZYPP_BASE_FLAGS_H
14
15 #include "zypp/base/String.h"
16
17 ///////////////////////////////////////////////////////////////////
18 namespace zypp
19 { /////////////////////////////////////////////////////////////////
20   ///////////////////////////////////////////////////////////////////
21   namespace base
22   { /////////////////////////////////////////////////////////////////
23
24     ///////////////////////////////////////////////////////////////////
25     //
26     //  CLASS NAME : Flags<Enum>
27     //
28     /** A type-safe way of storing OR-combinations of enum values (like QTs QFlags).
29      * \see <a href="http://doc.trolltech.com/4.1/qflags.html">QFlags Class Reference</a>
30      * \code
31      *  class RpmDb
32      *  {
33      *    public:
34      *      enum DbStateInfoBits {
35      *        DbSI_NO_INIT      = 0x0000,
36      *        DbSI_HAVE_V4      = 0x0001,
37      *        DbSI_MADE_V4      = 0x0002,
38      *        DbSI_MODIFIED_V4  = 0x0004,
39      *        DbSI_HAVE_V3      = 0x0008,
40      *        DbSI_HAVE_V3TOV4  = 0x0010,
41      *        DbSI_MADE_V3TOV4  = 0x0020
42      *      };
43      *
44      *      ZYPP_DECLARE_FLAGS(DbStateInfo,DbStateInfoBits);
45      *  };
46      *  ZYPP_DECLARE_OPERATORS_FOR_FLAGS(RpmDb::DbStateInfo);
47      *
48      *  ...
49      *  enum Other { OTHERVAL = 13 };
50      *  {
51      *    XRpmDb::DbStateInfo s;
52      *    s = XRpmDb::DbSI_MODIFIED_V4|XRpmDb::DbSI_HAVE_V4;
53      *    // s |= OTHERVAL; // As desired: it does not compile
54      *  }
55      * \endcode
56      */
57     template<typename TEnum>
58     class Flags
59     {
60       public:
61         typedef TEnum Enum;     ///< The underlying enum type
62         typedef typename std::underlying_type<Enum>::type Integral;     ///< The underlying integral type
63
64       public:
65         constexpr Flags()                               : _val( 0 ) {}
66         constexpr Flags( Enum flag_r )                  : _val( integral(flag_r) ) {}
67         constexpr explicit Flags( Integral flag_r )     : _val( flag_r ) {}
68
69         constexpr static Flags none()                   { return Flags( Integral(0) ); }
70         constexpr static Flags all()                    { return Flags( ~Integral(0) ); }
71
72         constexpr bool isNone() const                   { return _val == Integral(0); }
73         constexpr bool isAll() const                    { return _val == ~Integral(0); }
74
75         Flags & operator&=( Flags rhs )                 { _val &= integral(rhs); return *this; }
76         Flags & operator&=( Enum rhs )                  { _val &= integral(rhs); return *this; }
77
78         Flags & operator|=( Flags rhs )                 { _val |= integral(rhs); return *this; }
79         Flags & operator|=( Enum rhs )                  { _val |= integral(rhs); return *this; }
80
81         Flags & operator^=( Flags rhs )                 { _val ^= integral(rhs); return *this; }
82         Flags & operator^=( Enum rhs )                  { _val ^= integral(rhs); return *this; }
83
84       public:
85         constexpr operator Integral() const             { return _val; }
86
87         constexpr Flags operator&( Flags rhs ) const    { return Flags( _val & integral(rhs) ); }
88         constexpr Flags operator&( Enum rhs ) const     { return Flags( _val & integral(rhs) ); }
89
90         constexpr Flags operator|( Flags rhs ) const    { return Flags( _val | integral(rhs) ); }
91         constexpr Flags operator|( Enum rhs ) const     { return Flags( _val | integral(rhs) ); }
92
93         constexpr Flags operator^( Flags rhs ) const    { return Flags( _val ^ integral(rhs) ); }
94         constexpr Flags operator^( Enum rhs ) const     { return Flags( _val ^ integral(rhs) ); }
95
96         constexpr Flags operator~() const               { return Flags( ~_val ); }
97
98         constexpr bool operator==( Enum rhs ) const     {  return( _val == integral(rhs) ); }
99         constexpr bool operator!=( Enum rhs ) const     {  return( _val != integral(rhs) ); }
100
101       public:
102         Flags & setFlag( Flags flag_r, bool newval_r )  { return( newval_r ? setFlag(flag_r) : unsetFlag(flag_r) ); }
103         Flags & setFlag( Enum flag_r, bool newval_r )   { return( newval_r ? setFlag(flag_r) : unsetFlag(flag_r) ); }
104
105         Flags & setFlag( Flags flag_r )                 { _val |= integral(flag_r); return *this; }
106         Flags & setFlag( Enum flag_r )                  { _val |= integral(flag_r); return *this; }
107
108         Flags & unsetFlag( Flags flag_r )               { _val &= ~integral(flag_r); return *this; }
109         Flags & unsetFlag( Enum flag_r )                { _val &= ~integral(flag_r); return *this; }
110
111         constexpr bool testFlag( Flags flag_r ) const   { return testFlag( integral(flag_r) ); }
112         constexpr bool testFlag( Enum flag_r ) const    { return testFlag( integral(flag_r) ); }
113
114       private:
115         constexpr bool testFlag( Integral flag )        { return flag ? ( _val & flag ) == flag : !_val; }
116
117         constexpr static Integral integral( Flags obj ) { return obj._val; }
118         constexpr static Integral integral( Enum obj )  { return static_cast<Integral>(obj); }
119
120         Integral _val;
121     };
122     ///////////////////////////////////////////////////////////////////
123
124     /** \relates Flags Stringify
125      * Build a string of OR'ed names of each flag value set in \a flag_r.
126      * Remaining bits in \a flag_r are added as hexstring.
127      * \code
128      *   enum E { a=1, b=2, c=4 };
129      *   ZYPP_DECLARE_FLAGS( E, MyFlags );
130      *
131      *   MyFlags f = a|b|c;
132      *   cout << f << " = " << stringify( f, { {a,"A"}, {b,"B"} } ) << endl;
133      *   // prints: 0x0007 = [A|B|0x4]
134      * \endcode
135      */
136     template<typename Enum>
137     std::string stringify( const Flags<Enum> & flag_r, const std::initializer_list<std::pair<Flags<Enum>,std::string> > & flaglist_r = {},
138                            std::string intro_r = "[", std::string sep_r = "|", std::string extro_r = "]" )
139     {
140       std::string ret( std::move(intro_r) );
141       std::string sep;
142
143       Flags<Enum> mask;
144       for ( const auto & pair : flaglist_r )
145       {
146         if ( flag_r.testFlag( pair.first ) )
147         {
148           mask |= pair.first;
149           ret += sep;
150           ret += pair.second;
151           if ( sep.empty() && !sep_r.empty() )
152           { sep = std::move(sep_r); }
153         }
154       }
155       mask = flag_r & ~mask;
156       if ( mask )
157       {
158         ret += sep;
159         ret += str::hexstring( mask, 0 );
160       }
161       ret += std::move(extro_r);
162       return ret;
163     }
164
165     template<typename TEnum>
166     inline std::ostream & operator<<( std::ostream & str, const Flags<TEnum> & obj )
167     { return str << str::hexstring(obj); }
168
169     template<typename TEnum>
170     inline std::ostream & operator<<( std::ostream & str, const typename Flags<TEnum>::Enum & obj )
171     { return str << Flags<TEnum>(obj); }
172
173     /** \relates Flags */
174 #define ZYPP_DECLARE_FLAGS(Name,Enum) typedef zypp::base::Flags<Enum> Name
175
176     /** \relates Flags */
177 #define ZYPP_DECLARE_OPERATORS_FOR_FLAGS(Name) \
178 inline constexpr bool operator==( Name::Enum lhs, Name rhs )            { return( rhs == lhs ); }       \
179 inline constexpr bool operator!=(Name:: Enum lhs, Name rhs )            { return( rhs != lhs ); }       \
180 inline constexpr Name operator&( Name::Enum lhs, Name::Enum rhs )       { return Name( lhs ) & rhs; }   \
181 inline constexpr Name operator&( Name::Enum lhs, Name rhs )             { return rhs & lhs; }           \
182 inline constexpr Name operator|( Name::Enum lhs, Name::Enum rhs )       { return Name( lhs ) | rhs; }   \
183 inline constexpr Name operator|( Name::Enum lhs, Name rhs )             { return rhs | lhs; }           \
184 inline constexpr Name operator^( Name::Enum lhs, Name::Enum rhs )       { return Name( lhs ) ^ rhs; }   \
185 inline constexpr Name operator^( Name::Enum lhs, Name rhs )             { return rhs ^ lhs; }           \
186 inline constexpr Name operator~( Name::Enum lhs )                       { return ~Name( lhs ); }
187
188     /** \relates Flags */
189 #define ZYPP_DECLARE_FLAGS_AND_OPERATORS(Name,Enum) \
190     ZYPP_DECLARE_FLAGS(Name,Enum); \
191     ZYPP_DECLARE_OPERATORS_FOR_FLAGS(Name)
192
193     /////////////////////////////////////////////////////////////////
194   } // namespace base
195   ///////////////////////////////////////////////////////////////////
196   /////////////////////////////////////////////////////////////////
197 } // namespace zypp
198 ///////////////////////////////////////////////////////////////////
199 #endif // ZYPP_BASE_FLAGS_H