Mbed OS Reference
Loading...
Searching...
No Matches
common/SafeEnum.h
1/* mbed Microcontroller Library
2 * Copyright (c) 2006-2020 ARM Limited
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19#ifndef BLE_SAFE_ENUM_H_
20#define BLE_SAFE_ENUM_H_
21
22#include <cstddef>
23#include <cstdint>
24
25namespace ble {
26
27/**
28 * Helper class used to define safe enumerations.
29 *
30 * C++ 98 enums expose different security holes:
31 * - Scope The scope of the enum is the scope defining it. In other words,
32 * enumerator defined at namespace scope are in the same scope that other
33 * enumerator defined in that namespace even if they belong to a different
34 * enumeration.
35 * As a result it is really easy to collide names between two different
36 * enumerators. At the end, the programmer has to protect its declaration
37 * with long prefixing.
38 * - Unsafe comparison: enumerators really just are named integer and can be
39 * implicitly converted to integer. As a result it is possible to compare
40 * value of different enum type.
41 * - Layout: The layout type of enumerations is implementation defined.
42 *
43 * This template class expose a framework to overcome those issues:
44 *
45 * First enum has to be defined in a structure which inherit from this class.
46 * The target type is the name of the structure containing the enumeration
47 * while LayoutType is the inner type used to stored the enum.
48 *
49 * Comparison operator are provided so it is not possible to compare a SafeEnum
50 * of a type to another SafeEnum of a different type.
51 *
52 * Implicit conversion to integer is not defined, users have to either use the
53 * value function which return the integer value stored in an EnumType. Client
54 * class can also define their own conversion operation.
55 *
56 * @tparam Target structure containing the enumeration definition.
57 * @tparam LayoutType Inner type used to store enumeration value.
58 *
59 * @code
60
61 struct color_t : SafeEnum<color_t> {
62 enum type {
63 RED,
64 GREEN,
65 BLACK
66 };
67
68 color_t(type) : SafeEnum<color_t>(type) { }
69 };
70
71 // use an uint8_t to store the enumeration value
72 struct shape_t : SafeEnum<shape_t, uint8_t> {
73 enum type {
74 RECTANGLE,
75 CIRCLE,
76 TRIANGLE
77 };
78
79 shape_t(type) : SafeEnum<shape_t>(type) { }
80 };
81
82 // shape enumerator is in the shape_t scope.
83 shape_t shape = shape_t::RECTANGLE;
84
85 shape_t shape = color_t::RED; // Compilation error
86
87 if (shape == shape_t::CIRCLE) {
88 }
89
90 // compilation error
91 if (shape == color_t::RED) {
92
93 }
94
95 void sink(shape_t); (1)
96 void sink(color_t); (2)
97
98 sink(shape); // use overload (1)
99 sink(color); // use overload (2)
100
101 // explicit access to the value is mandatory when a SafeEnum value is used
102 // as the condition in a switch statement
103 switch(shape.value()) {
104 case shape_t::RECTANGLE:
105 break;
106 }
107
108 * @endcode
109 */
110template<typename Target, typename LayoutType = unsigned int>
111struct SafeEnum {
112 /**
113 * Type of the representation.
114 */
115 typedef LayoutType representation_t;
116
117protected:
118 /**
119 * Construction of an enumeration value.
120 */
121 explicit SafeEnum(LayoutType value) : _value(value) { }
122
123public:
124 /**
125 * Equal to operator for Target instances.
126 *
127 * @param lhs left hand side of the comparison
128 * @param rhs right hand side of the comparison
129 *
130 * @return true if the inner value of lhs and rhs are equal and false
131 * otherwise.
132 */
133 friend bool operator==(Target lhs, Target rhs) {
134 return lhs._value == rhs._value;
135 }
136
137 /**
138 * Not equal to operator for Target instances.
139 *
140 * @param lhs left hand side of the comparison
141 * @param rhs right hand side of the comparison
142 *
143 * @return true if the inner value of lhs and rhs are not equal and false
144 * otherwise.
145 */
146 friend bool operator!=(Target lhs, Target rhs) {
147 return !(lhs == rhs);
148 }
149
150 /**
151 * Less than operator for Target instances.
152 *
153 * @param lhs left hand side of the comparison
154 * @param rhs right hand side of the comparison
155 *
156 * @return true if the inner value of lhs is less than rhs and false otherwise.
157 */
158 friend bool operator<(Target lhs, Target rhs) {
159 return lhs.value() < rhs.value();
160 }
161
162 /**
163 * Less than or equal to operator for Target instances.
164 *
165 * @param lhs left hand side of the comparison
166 * @param rhs right hand side of the comparison
167 *
168 * @return true if the inner value of lhs is less than or equal to rhs and
169 * false otherwise.
170 */
171 friend bool operator<=(Target lhs, Target rhs) {
172 return lhs.value() < rhs.value() || lhs == rhs;
173 }
174
175 /**
176 * Greater than operator for Target instances.
177 *
178 * @param lhs left hand side of the comparison
179 * @param rhs right hand side of the comparison
180 *
181 * @return true if the inner value of lhs is greater than rhs; false
182 * otherwise.
183 */
184 friend bool operator>(Target lhs, Target rhs) {
185 return !(lhs <= rhs);
186 }
187
188 /**
189 * Greater than or equal to operator for Target instances.
190 *
191 * @param lhs left hand side of the comparison
192 * @param rhs right hand side of the comparison
193 *
194 * @return true if the inner value of lhs is greater than or equal to rhs;
195 * false otherwise.
196 */
197 friend bool operator>=(Target lhs, Target rhs) {
198 return !(lhs < rhs);
199 }
200
201 /**
202 * Explicit access to the inner value of the SafeEnum instance.
203 */
204 LayoutType value() const {
205 return _value;
206 }
207
208 /**
209 * Return a pointer to the inner storage.
210 */
211 const LayoutType* storage() const
212 {
213 return &_value;
214 }
215
216private:
217 LayoutType _value;
218};
219
220} // namespace ble
221
222#endif /* BLE_SAFE_ENUM_H_ */
Entry namespace for all BLE API definitions.
Helper class used to define safe enumerations.
const LayoutType * storage() const
Return a pointer to the inner storage.
friend bool operator<(Target lhs, Target rhs)
Less than operator for Target instances.
friend bool operator<=(Target lhs, Target rhs)
Less than or equal to operator for Target instances.
SafeEnum(LayoutType value)
Construction of an enumeration value.
friend bool operator>(Target lhs, Target rhs)
Greater than operator for Target instances.
friend bool operator==(Target lhs, Target rhs)
Equal to operator for Target instances.
LayoutType value() const
Explicit access to the inner value of the SafeEnum instance.
LayoutType representation_t
Type of the representation.
friend bool operator!=(Target lhs, Target rhs)
Not equal to operator for Target instances.
friend bool operator>=(Target lhs, Target rhs)
Greater than or equal to operator for Target instances.