// bdlat_enumfunctions.h -*-C++-*- // ---------------------------------------------------------------------------- // NOTICE // // This component is not up to date with current BDE coding standards, and // should not be used as an example for new development. // ---------------------------------------------------------------------------- #ifndef INCLUDED_BDLAT_ENUMFUNCTIONS #define INCLUDED_BDLAT_ENUMFUNCTIONS #include <bsls_ident.h> BSLS_IDENT("$Id: $") //@PURPOSE: Provide a namespace defining enumeration functions. // //@CLASSES: // bdlat_EnumFunctions: namespace for calling enumeration functions // //@SEE_ALSO: // //@DESCRIPTION: The 'bdlat_EnumFunctions' 'namespace' provided in this // component defines parameterized functions that expose "enumeration" behavior // for "enumeration" types. See the package-level documentation for a full // description of "enumeration" types. The functions in this namespace allow // users to: //.. // o load an enumeration value from an integer value ('fromInt'). // o load an enumeration value from a string value ('fromString'). // o load an integer value from an enumeration value ('toInt'). // o load a string value from an enumeration value ('toString'). //.. // Also, the meta-function 'IsEnumeration' contains a compile-time constant // 'VALUE' that is non-zero if the parameterized 'TYPE' exposes "enumeration" // behavior through the 'bdlat_EnumFunctions' 'namespace'. // // This component specializes all of these functions for types that have the // 'bdlat_TypeTraitBasicEnumeration' trait. // // Types that do not have the 'bdlat_TypeTraitBasicEnumeration' trait may have // the functions in the 'bdlat_EnumFunctions' 'namespace' specialized for them. // An example of this is provided in the 'Usage' section of this document. // ///Usage ///----- // The following snippets of code illustrate the usage of this component. // Suppose you had a C++ 'enum' type called 'MyEnum': //.. // #include <bdlat_enumfunctions.h> // #include <bdlb_string.h> // #include <sstream> // #include <string> // // namespace BloombergLP { // // namespace mine { // // enum MyEnum { // RED = 1, // GREEN = 2, // BLUE = 3 // }; //.. // We can now make 'MyEnum' expose "enumeration" behavior by implementing all // the necessary 'bdlat_enum*' functions for 'MyEnum' inside the 'mine' // namespace. First we should forward declare all the functions that we will // implement inside the 'mine' namespace: //.. // // MANIPULATORS // // int bdlat_enumFromInt(MyEnum *result, int number); // // Load into the specified 'result' the enumerator matching the // // specified 'number'. Return 0 on success, and a non-zero value // // with no effect on 'result' if 'number' does not match any // // enumerator. // // int bdlat_enumFromString(MyEnum *result, // const char *string, int stringLength); // // Load into the specified 'result' the enumerator matching the // // specified 'string' of the specified 'stringLength'. Return 0 on // // success, and a non-zero value with no effect on 'result' if // // 'string' and 'stringLength' do not match any enumerator. // // // ACCESSORS // // void bdlat_enumToInt(int *result, const MyEnum& value); // // Return the integer representation exactly matching the // // enumerator name corresponding to the specified enumeration // // 'value'. // // void bdlat_enumToString(bsl::string *result, const MyEnum& value); // // Return the string representation exactly matching the enumerator // // name corresponding to the specified enumeration 'value'. // // } // close namespace mine //.. // Next, we provide the definitions for each of these functions: //.. // // MANIPULATORS // // inline // int mine::bdlat_enumFromInt(MyEnum *result, int number) // { // enum { SUCCESS = 0, NOT_FOUND = -1 }; // // switch (number) { // case RED: { // *result = RED; // // return SUCCESS; // } // case GREEN: { // *result = GREEN; // // return SUCCESS; // } // case BLUE: { // *result = BLUE; // // return SUCCESS; // } // default: { // return NOT_FOUND; // } // } // } // // inline // int mine::bdlat_enumFromString(MyEnum *result, // const char *string, // int stringLength) // { // enum { SUCCESS = 0, NOT_FOUND = -1 }; // // if (bdlb::String::areEqualCaseless("red", // string, // stringLength)) { // *result = RED; // // return SUCCESS; // } // // if (bdlb::String::areEqualCaseless("green", // string, // stringLength)) { // *result = GREEN; // // return SUCCESS; // } // // if (bdlb::String::areEqualCaseless("blue", // string, // stringLength)) { // *result = BLUE; // // return SUCCESS; // } // // return NOT_FOUND; // } // // // ACCESSORS // // void mine::bdlat_enumToInt(int *result, const MyEnum& value) // { // *result = static_cast<int>(value); // } // // void mine::bdlat_enumToString(bsl::string *result, const MyEnum& value) // { // switch (value) { // case RED: { // *result = "RED"; // } break; // case GREEN: { // *result = "GREEN"; // } break; // case BLUE: { // *result = "BLUE"; // } break; // default: { // *result = "UNKNOWN"; // } break; // } // } //.. // Finally, we need to specialize the 'IsEnum' meta-function in the // 'bdlat_EnumFunctions' namespace for the 'mine::MyEnum' type. This makes the // 'bdlat' infrastructure recognize 'MyEnum' as an enumeration abstraction: //.. // namespace bdlat_EnumFunctions { // // template <> // struct IsEnumeration<mine::MyEnum> { // enum { VALUE = 1 }; // }; // // } // close namespace 'bdlat_EnumFunctions' // } // close namespace 'BloombergLP' //.. // The 'bdlat' infrastructure (and any component that uses this infrastructure) // will now recognize 'MyEnum' as an "enumeration" type. For example, suppose // we have the following XML data: //.. // <?xml version='1.0' encoding='UTF-8' ?> // <MyEnum>GREEN</MyEnum> //.. // Using the 'balxml_decoder' component, we can load this XML data into a // 'MyEnum' object: //.. // #include <balxml_decoder.h> // // void decodeMyEnumFromXML(bsl::istream& inputData) // { // using namespace BloombergLP; // // MyEnum object = 0; // // balxml::DecoderOptions options; // balxml::MiniReader reader; // balxml::ErrorInfo errInfo; // // balxml::Decoder decoder(&options, &reader, &errInfo); // int result = decoder.decode(inputData, &object); // // assert(0 == result); // assert(GREEN == object); // } //.. // Note that the 'bdlat' framework can be used for functionality other than // encoding/decoding into XML. When 'mine::MyEnum' is plugged into the // framework, then it will be automatically usable within the framework. For // example, the following snippets of code will convert a string from a stream // and load it into a 'mine::MyEnum' object: //.. // template <typename TYPE> // void readMyEnum(bsl::istream& stream, TYPE *object) // { // bsl::string value; // stream >> value; // // return bdlat_EnumType::fromString(object, value); // } //.. // Now we have a generic function that takes an input stream and a 'Cusip' // object, and inputs its value. We can use this generic function as follows: //.. // void usageExample() // { // using namespace BloombergLP; // // bsl::stringstream ss; // mine::MyEnum object; // // ss << "GREEN" << bsl::endl << "BROWN" << bsl::endl; // // assert(0 == readMyEnum(ss, &object)); // assert(mine::GREEN == object); // // assert(0 != readMyEnum(ss, &object)); // } //.. #include <bdlscm_version.h> #include <bdlat_bdeatoverrides.h> #include <bdlat_typetraits.h> #include <bslalg_hastrait.h> #include <bslmf_assert.h> #include <bslmf_matchanytype.h> #include <bslmf_metaint.h> #include <bsls_assert.h> #include <bsls_platform.h> #include <bsl_string.h> namespace BloombergLP { // ============================= // namespace bdlat_EnumFunctions // ============================= namespace bdlat_EnumFunctions { // This 'namespace' provides functions that expose "enumeration" behavior // for "enumeration" types. See the component-level documentation for more // information. // META-FUNCTIONS template <class TYPE> struct IsEnumeration { // This 'struct' should be specialized for third-party types that need // to expose "enumeration" behavior. See the component-level // documentation for further information. enum { VALUE = bslalg::HasTrait<TYPE, bdlat_TypeTraitBasicEnumeration>::VALUE }; }; // MANIPULATORS template <class TYPE> int fromInt(TYPE *result, int number); // Load into the specified 'result' the enumerator matching the // specified 'number'. Return 0 on success, and a non-zero value with // no effect on 'result' if 'number' does not match any enumerator. template <class TYPE> int fromString(TYPE *result, const char *string, int stringLength); // Load into the specified 'result' the enumerator matching the // specified 'string' of the specified 'stringLength'. Return 0 on // success, and a non-zero value with no effect on 'result' if 'string' // and 'stringLength' do not match any enumerator. // ACCESSORS template <class TYPE> void toInt(int *result, const TYPE& value); // Return the integer representation exactly matching the enumerator // name corresponding to the specified enumeration 'value'. template <class TYPE> void toString(bsl::string *result, const TYPE& value); // Return the string representation exactly matching the enumerator // name corresponding to the specified enumeration 'value'. } // close namespace bdlat_EnumFunctions // ==================== // default declarations // ==================== namespace bdlat_EnumFunctions { // This namespace declaration adds the default implementations of the // "enumeration" customization-point functions to 'bdlat_EnumFunctions'. // These default implementations assume the type of the acted-upon object // is a basic-enumeration type. For more information about // basic-enumeration types, see {'bdlat_typetraits'}. // MANIPULATORS template <class TYPE> int bdlat_enumFromInt(TYPE *result, int number); template <class TYPE> int bdlat_enumFromString(TYPE *result, const char *string, int stringLength); // ACCESSORS template <class TYPE> void bdlat_enumToInt(int *result, const TYPE& value); template <class TYPE> void bdlat_enumToString(bsl::string *result, const TYPE& value); } // close namespace bdlat_EnumFunctions // ============================================================================ // INLINE FUNCTION DEFINITIONS // ============================================================================ // ----------------------------- // namespace bdlat_EnumFunctions // ----------------------------- // MANIPULATORS template <class TYPE> inline int bdlat_EnumFunctions::fromInt(TYPE *result, int number) { return bdlat_enumFromInt(result, number); } template <class TYPE> inline int bdlat_EnumFunctions::fromString(TYPE *result, const char *string, int stringLength) { return bdlat_enumFromString(result, string, stringLength); } // ACCESSORS template <class TYPE> inline void bdlat_EnumFunctions::toInt(int *result, const TYPE& value) { bdlat_enumToInt(result, value); } template <class TYPE> inline void bdlat_EnumFunctions::toString(bsl::string *result, const TYPE& value) { bdlat_enumToString(result, value); } // ------------------- // default definitions // ------------------- // MANIPULATORS template <class TYPE> inline int bdlat_EnumFunctions::bdlat_enumFromInt(TYPE *result, int number) { BSLMF_ASSERT(bdlat_IsBasicEnumeration<TYPE>::value); typedef typename bdlat_BasicEnumerationWrapper<TYPE>::Wrapper Wrapper; return Wrapper::fromInt(result, number); } template <class TYPE> inline int bdlat_EnumFunctions::bdlat_enumFromString(TYPE *result, const char *string, int stringLength) { BSLMF_ASSERT( (bslalg::HasTrait<TYPE, bdlat_TypeTraitBasicEnumeration>::VALUE)); typedef typename bdlat_BasicEnumerationWrapper<TYPE>::Wrapper Wrapper; return Wrapper::fromString(result, string, stringLength); } // ACCESSORS template <class TYPE> inline void bdlat_EnumFunctions::bdlat_enumToInt(int *result, const TYPE& value) { BSLMF_ASSERT( (bslalg::HasTrait<TYPE, bdlat_TypeTraitBasicEnumeration>::VALUE)); *result = static_cast<int>(value); } template <class TYPE> inline void bdlat_EnumFunctions::bdlat_enumToString(bsl::string *result, const TYPE& value) { BSLMF_ASSERT( (bslalg::HasTrait<TYPE, bdlat_TypeTraitBasicEnumeration>::VALUE)); typedef typename bdlat_BasicEnumerationWrapper<TYPE>::Wrapper Wrapper; *result = Wrapper::toString(value); } } // close enterprise namespace #endif // ---------------------------------------------------------------------------- // Copyright 2015 Bloomberg Finance L.P. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // ----------------------------- END-OF-FILE ----------------------------------