Skip to content

Commit 0eb26a6

Browse files
committed
Add enum class flag definition to platform
1 parent 296961d commit 0eb26a6

File tree

1 file changed

+158
-0
lines changed

1 file changed

+158
-0
lines changed

platform/mbed_enum_flags.h

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
/*
2+
* Copyright (c) 2020 ARM Limited. All rights reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
* Licensed under the Apache License, Version 2.0 (the License); you may
5+
* not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
12+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#ifndef MBED_SCOPED_ENUM_FLAGS_H
18+
#define MBED_SCOPED_ENUM_FLAGS_H
19+
20+
#ifdef __cplusplus
21+
#include <type_traits>
22+
23+
#define ENUM_FLAG_OPERATOR(T,OP) \
24+
inline constexpr T operator OP( T lhs, T rhs) {\
25+
return ( T ) ( \
26+
static_cast<std::underlying_type< T >::type>(lhs) OP \
27+
static_cast<std::underlying_type< T >::type>(rhs)); \
28+
};
29+
30+
31+
#define ENUM_FLAG_OPERATOR_LHS_REFERNCE(T, X) \
32+
inline T & operator X (T & a, T b) { \
33+
a = a X b; \
34+
return a; \
35+
}
36+
37+
38+
/**
39+
* @brief Applies bitwise operators to a enum class defined elsewhere.
40+
*
41+
* @param T The enum class typename
42+
*
43+
* This macro applies the bitwise negate, AND, OR, XOR operators and the
44+
* corresponding assigment operators to an existing enum class. The macro
45+
* uses underlying type traits to convert back and forth.
46+
*
47+
* Due to the way the macro works, there is no semicolon required at the end.
48+
*
49+
* Usage:
50+
* @code
51+
* external_enum.h:
52+
*
53+
* enum class SpokenLanguages : uint8_t {
54+
* Sindarin = (1 << 0),
55+
* Westron = (1 << 1),
56+
* Rohirric = (1 << 2),
57+
* BlackSpeech = (1 << 3)
58+
* };
59+
*
60+
* my_code.cpp:
61+
*
62+
* #include "mbed_enum_flags.h"
63+
* #include "external_enum.h"
64+
*
65+
* MBED_ENUM_FLAG_APPLY_OPERATORS(SpokenLanguages)
66+
*
67+
* SpokenLanguages gandalf = SpokenLanguages::Sindarin | SpokenLanguages::Westron |
68+
* SpokenLanguages::Rohirric | SpokenLanguages::BlackSpeech;
69+
* @endcode
70+
*
71+
*/
72+
#define MBED_ENUM_FLAG_APPLY_OPERATORS(T) \
73+
\
74+
inline constexpr T operator ~( T lhs) { \
75+
return ( T ) (~static_cast<std::underlying_type< T >::type>(lhs)) ;\
76+
}\
77+
ENUM_FLAG_OPERATOR(T, |)\
78+
ENUM_FLAG_OPERATOR(T, ^)\
79+
ENUM_FLAG_OPERATOR(T, &)\
80+
ENUM_FLAG_OPERATOR_LHS_REFERNCE(T, |=) \
81+
ENUM_FLAG_OPERATOR_LHS_REFERNCE(T, ^=) \
82+
ENUM_FLAG_OPERATOR_LHS_REFERNCE(T, &=) \
83+
84+
85+
#define MBED_SCOPED_ENUM_FLAGS_TYPED(T, UNDER_TYPE) \
86+
enum class T : UNDER_TYPE; \
87+
MBED_ENUM_FLAG_APPLY_OPERATORS(T) \
88+
enum class T : UNDER_TYPE
89+
90+
#define MBED_SCOPED_ENUM_FLAGS_UNTYPED(T) \
91+
enum class T; \
92+
MBED_ENUM_FLAG_APPLY_OPERATORS(T) \
93+
enum class T
94+
95+
#define MBED_SCOPED_ENUM_FLAGS_CHOOSER(_1, _2, NAME, ...) NAME
96+
97+
/**
98+
* @brief Creates an enum class with bitwise operator overloads.
99+
*
100+
* @param T The enum class typename
101+
* @param UNDER_TYPE Optional: specify the underlying integral type. If left blank will
102+
* default to the compiler default (by standard, an int)
103+
*
104+
* This macro creates both the enum class type and defines NOT, AND, OR, and
105+
* XOR operators. It also defines as three bitwise assignment operators, AND,
106+
* OR, and XOR. It allows for the scoped nature of the enum class, but adds back
107+
* the bitwise operators that were missing.
108+
*
109+
* This macro uses type traits to convert between the underlying type and back
110+
* again for the bitwise operations.
111+
*
112+
* Usage:
113+
* @code
114+
* my_nice_enum_class_with_flags.h:
115+
*
116+
* MBED_SCOPED_ENUM_FLAGS(MyFlagName) {
117+
* HasEars = (1 << 0),
118+
* HasFur = (1 << 1),
119+
* LaysEggs = (1 << 2),
120+
* Meows = (1 << 3),
121+
* Polydactyl = (1 << 30)
122+
* };
123+
*
124+
* MBED_SCOPED_ENUM_FLAGS(SpokenLanguages, uint8_t) {
125+
* Sindarin = (1 << 0),
126+
* Westron = (1 << 1),
127+
* Rohirric = (1 << 2),
128+
* BlackSpeech = (1 << 3)
129+
* }
130+
*
131+
* my_enum_class_flag_consumer.h:
132+
*
133+
* class EnumEater {
134+
* public:
135+
* EnumEater(MyFlagName flags) : _flags(flags) {}
136+
*
137+
* static MyFlagName DefaultFlags = MyFlagName::HasEars | MyFlagName::Meows;
138+
*
139+
* bool is_cat() const {
140+
* return ( ((_flags & DefaultFlags) == DefaultFlags) &&
141+
* ((_flags & MyFlagName::LaysEggs) == MyFlagName()) );
142+
* }
143+
* private:
144+
* MyFlagName _flags;
145+
* };
146+
*
147+
* bool is_Gandalf(SpokenLanguages flags) {
148+
* return flags == (SpokenLanguages::Sindarin | SpokenLanguages::Westron |
149+
* SpokenLanguages::SpeaksRohirric | SpokenLanguages::BlackSpeech);
150+
* }
151+
* @endcode
152+
*
153+
*/
154+
#define MBED_SCOPED_ENUM_FLAGS(...) MBED_SCOPED_ENUM_FLAGS_CHOOSER(__VA_ARGS__, MBED_SCOPED_ENUM_FLAGS_TYPED, MBED_SCOPED_ENUM_FLAGS_UNTYPED)(__VA_ARGS__)
155+
156+
#endif // __cplusplus
157+
158+
#endif //MBED_SCOPED_ENUM_FLAGS_H

0 commit comments

Comments
 (0)