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