Skip to content

Commit 82f5b58

Browse files
authored
Merge pull request #5295 from pan-/GAP-platform-abstraction-layer
BLE: Gap platform abstraction layer
2 parents 8acf00a + 744abca commit 82f5b58

File tree

4 files changed

+1904
-0
lines changed

4 files changed

+1904
-0
lines changed

features/FEATURE_BLE/ble/SafeEnum.h

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
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+
/**
112+
* Construction of an enumeration value.
113+
*/
114+
SafeEnum(LayoutType value) : _value(value) { }
115+
116+
/**
117+
* Equal to operator for SafeEnum instances.
118+
*
119+
* @param lhs left hand side of the comparison
120+
* @param rhs right hand side of the comparison
121+
*
122+
* @return true if the inner value of lhs and rhs are equal and false
123+
* otherwise.
124+
*/
125+
friend bool operator==(SafeEnum lhs, SafeEnum rhs) {
126+
return lhs._value == rhs._value;
127+
}
128+
129+
/**
130+
* Not equal to operator for SafeEnum instances.
131+
*
132+
* @param lhs left hand side of the comparison
133+
* @param rhs right hand side of the comparison
134+
*
135+
* @return true if the inner value of lhs and rhs are not equal and false
136+
* otherwise.
137+
*/
138+
friend bool operator!=(SafeEnum lhs, SafeEnum rhs) {
139+
return !(lhs == rhs);
140+
}
141+
142+
/**
143+
* Explicit access to the inner value of the SafeEnum instance.
144+
*/
145+
LayoutType value() const {
146+
return _value;
147+
}
148+
149+
private:
150+
LayoutType _value;
151+
};
152+
153+
} // namespace ble
154+
155+
#endif /* BLE_SAFE_ENUM_H_ */

0 commit comments

Comments
 (0)