Imported Upstream version 16.3.2
[platform/upstream/libzypp.git] / zypp / Bit.h
1 /*---------------------------------------------------------------------\
2 |                          ____ _   __ __ ___                          |
3 |                         |__  / \ / / . \ . \                         |
4 |                           / / \ V /|  _/  _/                         |
5 |                          / /__ | | | | | |                           |
6 |                         /_____||_| |_| |_|                           |
7 |                                                                      |
8 \---------------------------------------------------------------------*/
9 /** \file       zypp/Bit.h
10  *
11 */
12 #ifndef ZYPP_BIT_H
13 #define ZYPP_BIT_H
14
15 #include <iosfwd>
16 #include <string>
17
18 ///////////////////////////////////////////////////////////////////
19 namespace zypp
20 { /////////////////////////////////////////////////////////////////
21 ///////////////////////////////////////////////////////////////////
22   /**
23    * \todo Use boost::mpl library to assert constraints
24    * at compiletime! There various like (TInt is an integral type)
25    * (begin+size < maxbits) or ( field dependent
26    * constants must be within the range defined by size ).
27   */
28   namespace bit
29   { /////////////////////////////////////////////////////////////////
30
31     namespace bit_detail
32     {
33       /** Generate constants with \a _size trailing '1'-bits */
34       template<class TInt, unsigned _size>
35         struct Gen1Bits
36         {
37           static const TInt value = (Gen1Bits<TInt,_size-1>::value << 1)+1;
38         };
39       /** Specialization for \a _length 0 */
40       template<class TInt>
41         struct Gen1Bits<TInt, 0>
42         {
43           static const TInt value = 0;
44         };
45     }
46
47     /** Number of bits available in \a TInt. */
48     template<class TInt>
49       struct MaxBits
50       {
51         typedef TInt IntT;
52         static const unsigned value = (sizeof(IntT)*8);
53       };
54
55     /** For printing bits. */
56     template<class TInt>
57       inline std::string asString( TInt val, char zero = '0', char one = '1' )
58       {
59         std::string s( MaxBits<TInt>::value, zero );
60         for( unsigned i = MaxBits<TInt>::value; i; )
61           {
62             --i;
63             if ( val & (TInt)1 )
64               s[i] = one;
65             val = val >> 1;
66           };
67         return s;
68       }
69
70     /** A bitmaks of \a _size 1-bits starting at bit \a _begin. */
71     template<class TInt, unsigned _begin, unsigned _size>
72       struct Mask
73       {
74         typedef TInt IntT;
75         static const IntT value    = bit_detail::Gen1Bits<IntT,_size>::value << _begin;
76         static const IntT inverted = ~value;
77       };
78
79     /** Range of bits starting at bit \a _begin with length \a _size. */
80     template<class TInt, unsigned _begin, unsigned _size>
81       struct Range
82       {
83         typedef TInt IntT;
84         typedef zypp::bit::MaxBits<IntT>           MaxBits;
85         typedef zypp::bit::Mask<IntT,_begin,_size> Mask;
86
87         static const unsigned begin  = _begin;
88         static const unsigned size   = _size;
89         static const unsigned end    = _begin + _size;
90       };
91     /** Range specialisation for (illegal) zero \a _size.
92      * Force error at compiletime. Currently because types
93      * and values are undefined
94     */
95     template<class TInt, unsigned _begin>
96       struct Range<TInt, _begin, 0>
97       {};
98
99     /** A value with in a Range.
100      * \code
101      * typedef Range<char,2,3> SubField; // bits 2,3,4 in a char field
102      * SubField::Mask::value;            // 00011100
103      * RangeValue<SubField,0>::value;    // 00000000
104      * RangeValue<SubField,1>::value;    // 00000100
105      * RangeValue<SubField,2>::value;    // 00001000
106      * RangeValue<SubField,3>::value;    // 00001100
107      * \endcode
108     */
109     template<class TRange, typename TRange::IntT _value>
110       struct RangeValue
111       {
112         typedef TRange                RangeT;
113         typedef typename TRange::IntT IntT;
114
115         static const IntT value = _value << RangeT::begin;
116       };
117
118     /** A single 1-bit within a Range.
119      * \code
120      * typedef Range<char,2,3> SubField; // bits 2,3,4 in a char field
121      * SubField::Mask::value;            // 00011100
122      * RangeBit<SubField,0>::value;      // 00000100
123      * RangeBit<SubField,1>::value;      // 00001000
124      * RangeBit<SubField,2>::value;      // 00010000
125      * \endcode
126     */
127     template<class TRange, unsigned _pos>
128       struct RangeBit
129       {
130         typedef TRange                RangeT;
131         typedef typename TRange::IntT IntT;
132
133         static const IntT value = IntT(1) << (RangeT::begin + _pos);
134       };
135
136     ///////////////////////////////////////////////////////////////////
137     //
138     //  CLASS NAME : BitField
139     //
140     /** An integral type used as BitField.
141      *
142      * Most methods exist as templated and nontemplated
143      * version. The nontemplated operates on the complete
144      * BitField, while the tamplated ones are restricted
145      * to the given Range.
146      * \code
147      * BitField<char> bf;                // 00000000
148      * typedef Range<char,2,3> SubField; // bits 2,3,4 in a char field
149      *
150      * bf<SubField>.assign( -1 );        // assign SubField in -1
151      *                                   // to SubField in bf.
152      *                                   // 00011100
153      * bf.assign( -1 );                  // assign -1 to bf
154      *                                   // 11111111
155      * bf<SubField>.assign( 0 );         // 11100011
156      * \endcode
157     */
158     template<class TInt>
159       class BitField  : public Range<TInt, 0, MaxBits<TInt>::value>
160       {
161       public:
162         /** Default ctor: zero. */
163         BitField()
164         : _value( (TInt)0 )
165         {}
166         /** Ctor taking an \a TInt. */
167         BitField( const TInt & value_r )
168         : _value( value_r )
169         {}
170
171       public:
172         /** Validate in a boolean context. */
173         explicit operator bool() const
174         { return _value != (TInt)0; }
175
176       public:
177         /** Return the value. */
178         template<class TRange>
179           TInt value() const
180           {
181             return _value & TRange::Mask::value;
182           }
183         TInt value() const
184         {
185           return _value;
186         }
187
188         /** Value as bit string. */
189         template<class TRange>
190           std::string asString() const
191           {
192             return bit::asString( _value & TRange::Mask::value, '_' );
193           }
194         std::string asString() const
195         {
196           return bit::asString( _value, '_' );
197         }
198
199         /** Assign Range in \a rhs to \c this. */
200         template<class TRange>
201           BitField & assign( TInt rhs )
202           {
203             _value = (_value & TRange::Mask::inverted)
204                    | (rhs & TRange::Mask::value);
205             return *this;
206           }
207         BitField & assign( TInt rhs )
208         {
209           _value = rhs;
210           return *this;
211         }
212
213         /** Test for equal value within a Range. */
214         template<class TRange>
215           bool isEqual( TInt rhs ) const
216           {
217             return (_value & TRange::Mask::value)
218                 == (rhs & TRange::Mask::value);
219           }
220         bool isEqual( TInt rhs ) const
221         {
222           return _value == rhs;
223         }
224
225        public:
226
227          /** Set or unset bits of \a rhs. */
228         template<class TRange>
229             BitField & set( TInt rhs, bool doset_r )
230             { return set( (rhs & TRange::Mask::value), doset_r ); }
231
232         BitField & set( TInt rhs, bool doset_r )
233         { return doset_r ? set( rhs ) : unset( rhs ); }
234
235         /** Set bits of \a rhs. */
236         template<class TRange>
237             BitField & set( TInt rhs )
238             { return set( rhs & TRange::Mask::value ); }
239
240         BitField & set( TInt rhs )
241         { _value |= rhs; return *this; }
242
243         /** Unset bits of \a rhs. */
244         template<class TRange>
245             BitField & unset( TInt rhs )
246             { return unset( rhs & TRange::Mask::value ); }
247
248         BitField & unset( TInt rhs )
249         { _value &= ~rhs; return *this; }
250
251         /** Test whether \b all bits of \a rhs are set. */
252         template<class TRange>
253             bool test( TInt rhs )
254             { return test( rhs & TRange::Mask::value ); }
255
256         bool test( TInt rhs ) const
257         { return (_value & rhs) == rhs; }
258
259         /** Test whether \b at \b least \b one bit of \a rhs is set. */
260         template<class TRange>
261             bool testAnyOf( TInt rhs )
262             { return testAnyOf( rhs & TRange::Mask::value ); }
263
264         bool testAnyOf( TInt rhs ) const
265         { return (_value & rhs); }
266
267       public:
268
269         BitField & operator=( const BitField & rhs )
270         { _value = rhs._value; return *this; }
271
272         BitField & operator&=( const BitField & rhs )
273         { _value &= rhs._value; return *this; }
274
275         BitField & operator|=( const BitField & rhs )
276         { _value |= rhs._value; return *this; }
277
278         BitField & operator^=( const BitField & rhs )
279         { _value ^= rhs._value; return *this; }
280
281         BitField & operator<<=( unsigned num )
282         { _value <<= num; return *this; }
283
284         BitField & operator>>=( unsigned num )
285         { _value >>= num; return *this; }
286
287         BitField operator~() const
288         { return ~_value; }
289
290       private:
291         TInt _value;
292       };
293     ///////////////////////////////////////////////////////////////////
294
295     /** \relates BitField Stream output */
296     template<class TInt>
297       std::ostream & operator<<( std::ostream & str, const BitField<TInt> & obj )
298       {
299         return str << obj.asString();
300       }
301
302     /** \relates BitField */
303     template<class TInt>
304       inline bool operator==( const BitField<TInt> & lhs, const BitField<TInt> & rhs )
305       { return lhs.value() == rhs.value(); }
306
307     /** \relates BitField */
308     template<class TInt>
309       inline bool operator!=( const BitField<TInt> & lhs, const BitField<TInt> & rhs )
310       { return ! (lhs == rhs); }
311
312
313     /** \relates BitField */
314     template<class TInt>
315       inline BitField<TInt> operator&( const BitField<TInt> & lhs, const BitField<TInt> & rhs )
316       { return BitField<TInt>(lhs) &= rhs; }
317
318     /** \relates BitField */
319     template<class TInt>
320       inline BitField<TInt> operator|( const BitField<TInt> & lhs, const BitField<TInt> & rhs )
321       { return BitField<TInt>(lhs) |= rhs; }
322
323     /** \relates BitField */
324     template<class TInt>
325       inline BitField<TInt> operator^( const BitField<TInt> & lhs, const BitField<TInt> & rhs )
326       { return BitField<TInt>(lhs) ^= rhs; }
327
328     /** \relates BitField */
329     template<class TInt>
330       inline BitField<TInt> operator<<( const BitField<TInt> & lhs, unsigned num )
331       { return BitField<TInt>(lhs) <<= num; }
332
333     /** \relates BitField */
334     template<class TInt>
335       inline BitField<TInt> operator>>( const BitField<TInt> & lhs, unsigned num )
336       { return BitField<TInt>(lhs) >>= num; }
337
338     /////////////////////////////////////////////////////////////////
339   } // namespace bit
340   ///////////////////////////////////////////////////////////////////
341   /////////////////////////////////////////////////////////////////
342 } // namespace zypp
343 ///////////////////////////////////////////////////////////////////
344 #endif // ZYPP_BIT_H