Mistake on this page?
Report an issue in GitHub or email us
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 
25 namespace 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  */
110 template<typename Target, typename LayoutType = unsigned int>
111 struct SafeEnum {
112  /**
113  * Type of the representation.
114  */
115  typedef LayoutType representation_t;
116 
117 protected:
118  /**
119  * Construction of an enumeration value.
120  */
121  explicit SafeEnum(LayoutType value) : _value(value) { }
122 
123 public:
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 
216 private:
217  LayoutType _value;
218 };
219 
220 } // namespace ble
221 
222 #endif /* BLE_SAFE_ENUM_H_ */
friend bool operator==(Target lhs, Target rhs)
Equal to operator for Target instances.
friend bool operator>=(Target lhs, Target rhs)
Greater than or equal to operator for Target instances.
const LayoutType * storage() const
Return a pointer to the inner storage.
LayoutType value() const
Explicit access to the inner value of the SafeEnum instance.
Helper class used to define safe enumerations.
SafeEnum(LayoutType value)
Construction of an enumeration value.
friend bool operator>(Target lhs, Target rhs)
Greater than operator for Target instances.
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)
Less than or equal to operator for Target instances.
friend bool operator<(Target lhs, Target rhs)
Less than operator for Target instances.
Entry namespace for all BLE API definitions.
Important Information for this Arm website

This site uses cookies to store information on your computer. By continuing to use our site, you consent to our cookies. If you are not happy with the use of these cookies, please review our Cookie Policy to learn how they can be disabled. By disabling cookies, some features of the site will not work.