Merge branch 'master' into cairocanvas
[ardour.git] / libs / audiographer / audiographer / flag_field.h
1 #ifndef AUDIOGRAPHER_FLAG_FIELD_H
2 #define AUDIOGRAPHER_FLAG_FIELD_H
3
4 #include <stdint.h>
5 #include <iterator>
6 #include <climits>
7
8 #include <boost/operators.hpp>
9
10 #include "audiographer/visibility.h"
11
12 namespace AudioGrapher {
13
14 /** Flag field capable of holding 32 flags.
15   * Easily grown in size to 64 flags by changing storage_type.
16   */
17 class LIBAUDIOGRAPHER_API FlagField
18   : public boost::less_than_comparable<FlagField>
19   , boost::equivalent<FlagField>
20   , boost::equality_comparable<FlagField>
21 {
22   public:
23         
24         typedef uint8_t  Flag;
25         typedef uint32_t storage_type;
26         
27         /// Bi-directional iterator for flag set. Iterates over flags that are set in this field.
28         class iterator
29           : public std::iterator<std::bidirectional_iterator_tag, Flag>
30           , public boost::less_than_comparable<iterator>
31           , boost::equivalent<iterator>
32           , boost::equality_comparable<iterator>
33         {
34           public:
35                 iterator (FlagField const & parent, Flag position) : parent (parent), position (position) {}
36                 iterator (iterator const & other) : parent (other.parent), position (other.position) {}
37                 
38                 value_type operator*() const { return position; }
39                 value_type const * operator->() const { return &position; }
40                 
41                 iterator & operator++()
42                 {
43                         do {
44                                 ++position;
45                         } while (!parent.has (position) && position != max());
46                         return *this;
47                 }
48                 iterator operator++(int) { iterator copy (*this); ++(*this); return copy; }
49                 
50                 iterator & operator--()
51                 {
52                         do {
53                                 --position;
54                         } while (!parent.has (position) && position != max());
55                         return *this;
56                 }
57                 iterator   operator--(int) { iterator copy (*this); --(*this); return copy; }
58                 
59                 bool operator< (iterator const & other) const { return position < other.position; }
60                 
61           private:
62                 FlagField const & parent;
63                 Flag              position;
64         };
65         
66   public:
67         
68         FlagField() : _flags (0) {}
69         FlagField(FlagField const & other) : _flags (other._flags) {}
70         
71         inline bool has (Flag flag)    const { return _flags & (1 << flag); }
72         inline storage_type flags ()   const { return _flags; }
73         inline operator bool()         const { return _flags; }
74         inline void set (Flag flag)          { _flags |= (1 << flag); }
75         inline void remove (Flag flag)       { _flags &= ~(1 << flag); }
76         inline void reset ()                 { _flags = 0; }
77
78         /// Returns the flags in \a other that are not set in this field
79         inline FlagField unsupported_flags_of (FlagField const & other) const { return ~(_flags | ~other._flags); }
80         
81         /// Set all flags that are set in \a other
82         inline FlagField & operator+= (FlagField const & other) { _flags |= other._flags; return *this; }
83         
84         /** Checks whether this field has all the flags set that are set in \a other
85           * NOTE: Can NOT be used for strict weak ordering!
86           * \return \a true if \a other has flags set that this field does not
87           */
88         inline bool operator< (FlagField const & other) const { return unsupported_flags_of (other); }
89
90         iterator begin() const
91         {
92                 iterator it (*this, 0);
93                 if (!*this) { return end(); }
94                 if (!has (0)) { ++it; }
95                 return it;
96         }
97         iterator end() const { iterator it (*this, max()); return it; }
98
99   private:
100         FlagField(storage_type flags) : _flags (flags) {}
101         static Flag max() { return CHAR_BIT * sizeof (storage_type) + 1; }
102         
103         storage_type _flags;
104 };
105
106 } // namespace
107
108 #endif // AUDIOGRAPHER_FLAG_FIELD_H