Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Committer:
kenjiArai
Date:
Tue Dec 17 23:23:45 2019 +0000
Revision:
0:5b88d5760320
mbed-os5 only for TYBLE16

Who changed what in which revision?

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