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.
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 /** 00112 * Construction of an enumeration value. 00113 */ 00114 SafeEnum(LayoutType value) : _value(value) { } 00115 00116 /** 00117 * Equal to operator for SafeEnum instances. 00118 * 00119 * @param lhs left hand side of the comparison 00120 * @param rhs right hand side of the comparison 00121 * 00122 * @return true if the inner value of lhs and rhs are equal and false 00123 * otherwise. 00124 */ 00125 friend bool operator==(SafeEnum lhs, SafeEnum rhs) { 00126 return lhs._value == rhs._value; 00127 } 00128 00129 /** 00130 * Not equal to operator for SafeEnum instances. 00131 * 00132 * @param lhs left hand side of the comparison 00133 * @param rhs right hand side of the comparison 00134 * 00135 * @return true if the inner value of lhs and rhs are not equal and false 00136 * otherwise. 00137 */ 00138 friend bool operator!=(SafeEnum lhs, SafeEnum rhs) { 00139 return !(lhs == rhs); 00140 } 00141 00142 /** 00143 * Explicit access to the inner value of the SafeEnum instance. 00144 */ 00145 LayoutType value() const { 00146 return _value; 00147 } 00148 00149 private: 00150 LayoutType _value; 00151 }; 00152 00153 } // namespace ble 00154 00155 #endif /* BLE_SAFE_ENUM_H_ */
Generated on Tue Jul 12 2022 12:22:19 by
