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