blob: 55c48a94c5fce5858f1d4e72c3d587ef8cb8113d [file] [log] [blame]
John Park33858a32018-09-28 23:05:48 -07001#ifndef AOS_UTIL_OPTIONS_H_
2#define AOS_UTIL_OPTIONS_H_
Brian Silverman7faaec72014-05-26 16:25:38 -07003
Brian Silverman7faaec72014-05-26 16:25:38 -07004namespace aos {
5
Brian Silverman7faaec72014-05-26 16:25:38 -07006// An "option" that can be combined with other options and passed as one
7// argument. This class is designed to emulate integral constants (except be
8// type-safe), so its instances can be combined with operator| (creating an
9// Options), and an Options can be tested for membership with operator&.
10// Owner is the only class that can construct Option instances and is used to
11// differentiate between options for different classes. It is safe to only have
12// a forward declaration for Owner in scope when instantiating either of these
13// template classes.
14template <class Owner>
15class Options {
16 public:
17 // Represents a single options. Instances of this should be created as
18 // constants by Owner.
19 class Option {
20 public:
21 constexpr Options operator|(Option option) const {
22 return Options(bit_ | option.bit_);
23 }
24
25 constexpr bool operator==(Option other) const { return bit_ == other.bit_; }
26
27 constexpr unsigned int printable() const { return bit_; }
28
29 private:
30 // Bit must have exactly 1 bit set and that must be a different one for each
31 // instance.
32 explicit constexpr Option(unsigned int bit) : bit_(bit) {}
33
34 unsigned int bit_;
35
36 friend class Options;
37 friend Owner;
38 };
39
40 constexpr Options(Option option) : bits_(option.bit_) {}
41
42 constexpr bool operator&(Option option) const {
43 return (bits_ & option.bit_) != 0;
44 }
45
46 constexpr Options operator|(Option option) const {
47 return Options(bits_ | option.bit_);
48 }
49 constexpr Options operator|(Options options) const {
50 return Options(bits_ | options.bits_);
51 }
52
53 constexpr bool operator==(Options other) const {
54 return bits_ == other.bits_;
55 }
56
57 constexpr unsigned int printable() const { return bits_; }
58
59 // Returns true if no Options other than the ones in options are set.
60 // Useful for validating that no illegal options are passed.
61 constexpr bool NoOthersSet(Options options) const {
62 return (bits_ & ~options.bits_) == 0;
63 }
64
65 // Returns true if exactly 1 of the Options in options is set.
66 // Useful for validating that one of a group of mutually exclusive options has
67 // been passed.
68 constexpr bool ExactlyOneSet(Options options) const {
69 return __builtin_popcount(bits_ & options.bits_) == 1;
70 }
71
72 // Returns true if all of the Options in options are set.
73 constexpr bool AllSet(Options options) const {
74 return (bits_ & options.bits_) == options.bits_;
75 }
76
77 private:
78 explicit constexpr Options(unsigned int bits) : bits_(bits) {}
79
80 unsigned int bits_;
81
82 friend class Option;
83};
84
Austin Schuh60e77942022-05-16 17:48:24 -070085} // namespace aos
Brian Silverman7faaec72014-05-26 16:25:38 -070086
John Park33858a32018-09-28 23:05:48 -070087#endif // AOS_UTIL_OPTIONS_H_