Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: TYBLE16_simple_data_logger TYBLE16_MP3_Air
SafeEnum.h
00001 /* mbed Microcontroller Library 00002 * Copyright (c) 2017-2017 ARM Limited 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 00017 #ifndef BLE_SAFE_ENUM_H_ 00018 #define BLE_SAFE_ENUM_H_ 00019 00020 #include <stddef.h> 00021 #include <stdint.h> 00022 00023 namespace ble { 00024 00025 /** 00026 * Helper class used to define safe enumerations. 00027 * 00028 * C++ 98 enums expose different security holes: 00029 * - Scope The scope of the enum is the scope defining it. In other words, 00030 * enumerator defined at namespace scope are in the same scope that other 00031 * enumerator defined in that namespace even if they belong to a different 00032 * enumeration. 00033 * As a result it is really easy to collide names between two different 00034 * enumerators. At the end, the programmer has to protect its declaration 00035 * with long prefixing. 00036 * - Unsafe comparison: enumerators really just are named integer and can be 00037 * implicitly converted to integer. As a result it is possible to compare 00038 * value of different enum type. 00039 * - Layout: The layout type of enumerations is implementation defined. 00040 * 00041 * This template class expose a framework to overcome those issues: 00042 * 00043 * First enum has to be defined in a structure which inherit from this class. 00044 * The target type is the name of the structure containing the enumeration 00045 * while LayoutType is the inner type used to stored the enum. 00046 * 00047 * Comparison operator are provided so it is not possible to compare a SafeEnum 00048 * of a type to another SafeEnum of a different type. 00049 * 00050 * Implicit conversion to integer is not defined, users have to either use the 00051 * value function which return the integer value stored in an EnumType. Client 00052 * class can also define their own conversion operation. 00053 * 00054 * @tparam Target structure containing the enumeration definition. 00055 * @tparam LayoutType Inner type used to store enumeration value. 00056 * 00057 * @code 00058 00059 struct color_t : SafeEnum<color_t> { 00060 enum type { 00061 RED, 00062 GREEN, 00063 BLACK 00064 }; 00065 00066 color_t(type) : SafeEnum<color_t>(type) { } 00067 }; 00068 00069 // use an uint8_t to store the enumeration value 00070 struct shape_t : SafeEnum<shape_t, uint8_t> { 00071 enum type { 00072 RECTANGLE, 00073 CIRCLE, 00074 TRIANGLE 00075 }; 00076 00077 shape_t(type) : SafeEnum<shape_t>(type) { } 00078 }; 00079 00080 // shape enumerator is in the shape_t scope. 00081 shape_t shape = shape_t::RECTANGLE; 00082 00083 shape_t shape = color_t::RED; // Compilation error 00084 00085 if (shape == shape_t::CIRCLE) { 00086 } 00087 00088 // compilation error 00089 if (shape == color_t::RED) { 00090 00091 } 00092 00093 void sink(shape_t); (1) 00094 void sink(color_t); (2) 00095 00096 sink(shape); // use overload (1) 00097 sink(color); // use overload (2) 00098 00099 // explicit access to the value is mandatory when a SafeEnum value is used 00100 // as the condition in a switch statement 00101 switch(shape.value()) { 00102 case shape_t::RECTANGLE: 00103 break; 00104 } 00105 00106 * @endcode 00107 */ 00108 template<typename Target, typename LayoutType = unsigned int> 00109 struct SafeEnum { 00110 /** 00111 * Type of the representation. 00112 */ 00113 typedef LayoutType representation_t; 00114 00115 protected: 00116 /** 00117 * Construction of an enumeration value. 00118 */ 00119 explicit SafeEnum(LayoutType value) : _value(value) { } 00120 00121 public: 00122 /** 00123 * Equal to operator for Target instances. 00124 * 00125 * @param lhs left hand side of the comparison 00126 * @param rhs right hand side of the comparison 00127 * 00128 * @return true if the inner value of lhs and rhs are equal and false 00129 * otherwise. 00130 */ 00131 friend bool operator==(Target lhs, Target rhs) { 00132 return lhs._value == rhs._value; 00133 } 00134 00135 /** 00136 * Not equal to operator for Target instances. 00137 * 00138 * @param lhs left hand side of the comparison 00139 * @param rhs right hand side of the comparison 00140 * 00141 * @return true if the inner value of lhs and rhs are not equal and false 00142 * otherwise. 00143 */ 00144 friend bool operator!=(Target lhs, Target rhs) { 00145 return !(lhs == rhs); 00146 } 00147 00148 /** 00149 * Less than operator for Target instances. 00150 * 00151 * @param lhs left hand side of the comparison 00152 * @param rhs right hand side of the comparison 00153 * 00154 * @return true if the inner value of lhs is less than rhs and false otherwise. 00155 */ 00156 friend bool operator<(Target lhs, Target rhs) { 00157 return lhs.value() < rhs.value(); 00158 } 00159 00160 /** 00161 * Less than or equal to operator for Target instances. 00162 * 00163 * @param lhs left hand side of the comparison 00164 * @param rhs right hand side of the comparison 00165 * 00166 * @return true if the inner value of lhs is less than or equal to rhs and 00167 * false otherwise. 00168 */ 00169 friend bool operator<=(Target lhs, Target rhs) { 00170 return lhs.value() < rhs.value() || lhs == rhs; 00171 } 00172 00173 /** 00174 * Greater than operator for Target instances. 00175 * 00176 * @param lhs left hand side of the comparison 00177 * @param rhs right hand side of the comparison 00178 * 00179 * @return true if the inner value of lhs is greater than rhs; false 00180 * otherwise. 00181 */ 00182 friend bool operator>(Target lhs, Target rhs) { 00183 return !(lhs <= rhs); 00184 } 00185 00186 /** 00187 * Greater than or equal to operator for Target instances. 00188 * 00189 * @param lhs left hand side of the comparison 00190 * @param rhs right hand side of the comparison 00191 * 00192 * @return true if the inner value of lhs is greater than or equal to rhs; 00193 * false otherwise. 00194 */ 00195 friend bool operator>=(Target lhs, Target rhs) { 00196 return !(lhs < rhs); 00197 } 00198 00199 /** 00200 * Explicit access to the inner value of the SafeEnum instance. 00201 */ 00202 LayoutType value() const { 00203 return _value; 00204 } 00205 00206 /** 00207 * Return a pointer to the inner storage. 00208 */ 00209 const LayoutType* storage() const 00210 { 00211 return &_value; 00212 } 00213 00214 private: 00215 LayoutType _value; 00216 }; 00217 00218 } // namespace ble 00219 00220 #endif /* BLE_SAFE_ENUM_H_ */
Generated on Tue Jul 12 2022 13:54:49 by
