Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers SafeEnum.h Source File

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_ */