Quick Links: |
Provide a namespace defining sequence functions. More...
Namespaces | |
namespace | bdlat_SequenceFunctions |
bdlat_SequenceFunctions | namespace for calling sequence functions |
bdlat_SequenceFunctions
namespace
provided in this component defines parameterized functions that expose "sequence" behavior for "sequence" types. See the bdlat
package-level documentation for a full description of "sequence" types. manipulateAttribute
), manipulateAttributes
), accessAttribute
), and accessAttributes
). IsSequence
contains a compile-time constant VALUE
that is non-zero if the parameterized TYPE
exposes "sequence" behavior through the bdlat_SequenceFunctions
namespace
. bdlat_TypeTraitBasicSequence
trait. bdlat_TypeTraitBasicSequence
trait can be plugged into the bdlat
framework. This is done by overloading the bdlat_sequence*
functions inside the namespace of the plugged in type. For example, suppose there is a type called mine::MySequence
. In order to plug this type into the bdlat
framework as a "sequence", the following functions must be declared and implemented in the mine
namespace: namespace mine { // MANIPULATORS template <typename MANIPULATOR> int bdlat_sequenceManipulateAttribute( MySequence *object, MANIPULATOR& manipulator, const char *attributeName, int attributeNameLength); // Invoke the specified 'manipulator' on the address of the // (modifiable) attribute indicated by the specified 'attributeName' // and 'attributeNameLength' of the specified 'object', supplying // 'manipulator' with the corresponding attribute information // structure. Return non-zero value if the attribute is not found, and // the value returned from the invocation of 'manipulator' otherwise. template <typename MANIPULATOR> int bdlat_sequenceManipulateAttribute(MySequence *object, MANIPULATOR& manipulator, int attributeId); // Invoke the specified 'manipulator' on the address of the // (modifiable) attribute indicated by the specified 'attributeId' of // the specified 'object', supplying 'manipulator' with the // corresponding attribute information structure. Return non-zero // value if the attribute is not found, and the value returned from the // invocation of 'manipulator' otherwise. template <typename MANIPULATOR> int bdlat_sequenceManipulateAttributes(MySequence *object, MANIPULATOR& manipulator); // Invoke the specified 'manipulator' sequentially on the address of // each (modifiable) attribute of the specified 'object', supplying // 'manipulator' with the corresponding attribute information structure // until such invocation returns non-zero value. Return the value from // the last invocation of 'manipulator' (i.e., the invocation that // terminated the sequence). // ACCESSORS template <typename ACCESSOR> int bdlat_sequenceAccessAttribute(const MySequence& object, ACCESSOR& accessor, const char *attributeName, int attributeNameLength); // Invoke the specified 'accessor' on the (non-modifiable) attribute of // the specified 'object' indicated by the specified 'attributeName' // and 'attributeNameLength', supplying 'accessor' with the // corresponding attribute information structure. Return non-zero // value if the attribute is not found, and the value returned from the // invocation of 'accessor' otherwise. template <typename ACCESSOR> int bdlat_sequenceAccessAttribute(const MySequence& object, ACCESSOR& accessor, int attributeId); // Invoke the specified 'accessor' on the attribute of the specified // 'object' with the given 'attributeId', supplying 'accessor' with the // corresponding attribute information structure. Return non-zero if // the attribute is not found, and the value returned from the // invocation of 'accessor' otherwise. template <typename ACCESSOR> int bdlat_sequenceAccessAttributes(const MySequence& object, ACCESSOR& accessor); // Invoke the specified 'accessor' sequentially on each attribute of // the specified 'object', supplying 'accessor' with the corresponding // attribute information structure until such invocation returns a // non-zero value. Return the value from the last invocation of // 'accessor' (i.e., the invocation that terminated the sequence). bool bdlat_sequenceHasAttribute(const MySequence& object, const char *attributeName, int attributeNameLength); // Return true if the specified 'object' has an attribute with the // specified 'attributeName' of the specified 'attributeNameLength', // and false otherwise. bool bdlat_sequenceHasAttribute(const MySequence& object, int attributeId); // Return true if the specified 'object' has an attribute with the // specified 'attributeId', and false otherwise. } // close namespace 'mine'
IsSequence
meta-function must be specialized for the mine::MySequence
type in the bdlat_SequenceFunctions
namespace. bdlat
framework is shown in the Usage
section of this document. struct
that contains three members: namespace BloombergLP { namespace mine { struct MySequence { // This struct represents a sequence containing a 'string' member, an // 'int' member, and a 'float' member. // CONSTANTS enum { NAME_ATTRIBUTE_ID = 1, AGE_ATTRIBUTE_ID = 2, SALARY_ATTRIBUTE_ID = 3 }; // DATA MEMBERS bsl::string d_name; int d_age; float d_salary; }; } // close namespace mine
mine::MySequence
expose "sequence" behavior by implementing the necessary bdlat_sequence*
functions for MySequence
inside the mine
namespace. First, we should forward declare all the functions that we will implement inside the mine
namespace: namespace mine { template <class MANIPULATOR> int bdlat_sequenceManipulateAttribute(MySequence *object, MANIPULATOR& manipulator, const char *attributeName, int attributeNameLength); template <class MANIPULATOR> int bdlat_sequenceManipulateAttribute(MySequence *object, MANIPULATOR& manipulator, int attributeId); template <class MANIPULATOR> int bdlat_sequenceManipulateAttributes(MySequence *object, MANIPULATOR& manipulator); template <class ACCESSOR> int bdlat_sequenceAccessAttribute(const MySequence& object, ACCESSOR& accessor, const char *attributeName, int attributeNameLength); template <class ACCESSOR> int bdlat_sequenceAccessAttribute(const MySequence& object, ACCESSOR& accessor, int attributeId); template <class ACCESSOR> int bdlat_sequenceAccessAttributes(const MySequence& object, ACCESSOR& accessor); bool bdlat_sequenceHasAttribute(const MySequence& object, const char *attributeName, int attributeNameLength); bool bdlat_sequenceHasAttribute(const MySequence& object, int attributeId); } // close namespace mine
bdlat_AttributeInfo
object and pass it along when invoking the manipulator or accessor. See the bdlat_attributeinfo
component-level documentation for more information. The implementation of the functions are as follows: template <class MANIPULATOR> int mine::bdlat_sequenceManipulateAttribute( MySequence *object, MANIPULATOR& manipulator, const char *attributeName, int attributeNameLength) { enum { NOT_FOUND = -1 }; if (bdlb::String::areEqualCaseless("name", attributeName, attributeNameLength)) { return bdlat_sequenceManipulateAttribute( object, manipulator, MySequence::NAME_ATTRIBUTE_ID); // RETURN } if (bdlb::String::areEqualCaseless("age", attributeName, attributeNameLength)) { return bdlat_sequenceManipulateAttribute( object, manipulator, MySequence::AGE_ATTRIBUTE_ID); // RETURN } if (bdlb::String::areEqualCaseless("salary", attributeName, attributeNameLength)) { return bdlat_sequenceManipulateAttribute( object, manipulator, MySequence::SALARY_ATTRIBUTE_ID); // RETURN } return NOT_FOUND; } template <class MANIPULATOR> int mine::bdlat_sequenceManipulateAttribute(MySequence *object, MANIPULATOR& manipulator, int attributeId) { enum { NOT_FOUND = -1 }; switch (attributeId) { case MySequence::NAME_ATTRIBUTE_ID: { bdlat_AttributeInfo info; info.annotation() = "Name of employee"; info.formattingMode() = bdlat_FormattingMode::e_DEFAULT; info.id() = MySequence::NAME_ATTRIBUTE_ID; info.name() = "name"; info.nameLength() = 4; return manipulator(&object->d_name, info); // RETURN } case MySequence::AGE_ATTRIBUTE_ID: { bdlat_AttributeInfo info; info.annotation() = "Age of employee"; info.formattingMode() = bdlat_FormattingMode::e_DEFAULT; info.id() = MySequence::AGE_ATTRIBUTE_ID; info.name() = "age"; info.nameLength() = 3; return manipulator(&object->d_age, info); // RETURN } case MySequence::SALARY_ATTRIBUTE_ID: { bdlat_AttributeInfo info; info.annotation() = "Salary of employee"; info.formattingMode() = bdlat_FormattingMode::e_DEFAULT; info.id() = MySequence::SALARY_ATTRIBUTE_ID; info.name() = "salary"; info.nameLength() = 6; return manipulator(&object->d_salary, info); // RETURN } default: { return NOT_FOUND; // RETURN } } } template <class MANIPULATOR> int mine::bdlat_sequenceManipulateAttributes(MySequence *object, MANIPULATOR& manipulator) { int retVal; retVal = bdlat_sequenceManipulateAttribute( object, manipulator, MySequence::NAME_ATTRIBUTE_ID); if (0 != retVal) { return retVal; // RETURN } retVal = bdlat_sequenceManipulateAttribute( object, manipulator, MySequence::AGE_ATTRIBUTE_ID); if (0 != retVal) { return retVal; // RETURN } retVal = bdlat_sequenceManipulateAttribute( object, manipulator, MySequence::SALARY_ATTRIBUTE_ID); return retVal; } // ACCESSORS template <class ACCESSOR> int mine::bdlat_sequenceAccessAttribute( const MySequence& object, ACCESSOR& accessor, const char *attributeName, int attributeNameLength) { enum { NOT_FOUND = -1 }; if (bdlb::String::areEqualCaseless("name", attributeName, attributeNameLength)) { return bdlat_sequenceAccessAttribute( object, accessor, MySequence::NAME_ATTRIBUTE_ID); // RETURN } if (bdlb::String::areEqualCaseless("age", attributeName, attributeNameLength)) { return bdlat_sequenceAccessAttribute(object, accessor, MySequence::AGE_ATTRIBUTE_ID); // RETURN } if (bdlb::String::areEqualCaseless("salary", attributeName, attributeNameLength)) { return bdlat_sequenceAccessAttribute( object, accessor, MySequence::SALARY_ATTRIBUTE_ID); // RETURN } return NOT_FOUND; } template <class ACCESSOR> int mine::bdlat_sequenceAccessAttribute(const MySequence& object, ACCESSOR& accessor, int attributeId) { enum { NOT_FOUND = -1 }; switch (attributeId) { case MySequence::NAME_ATTRIBUTE_ID: { bdlat_AttributeInfo info; info.annotation() = "Name of employee"; info.formattingMode() = bdlat_FormattingMode::e_DEFAULT; info.id() = MySequence::NAME_ATTRIBUTE_ID; info.name() = "name"; info.nameLength() = 4; return accessor(object.d_name, info); // RETURN } case MySequence::AGE_ATTRIBUTE_ID: { bdlat_AttributeInfo info; info.annotation() = "Age of employee"; info.formattingMode() = bdlat_FormattingMode::e_DEFAULT; info.id() = MySequence::AGE_ATTRIBUTE_ID; info.name() = "age"; info.nameLength() = 3; return accessor(object.d_age, info); // RETURN } case MySequence::SALARY_ATTRIBUTE_ID: { bdlat_AttributeInfo info; info.annotation() = "Salary of employee"; info.formattingMode() = bdlat_FormattingMode::e_DEFAULT; info.id() = MySequence::SALARY_ATTRIBUTE_ID; info.name() = "salary"; info.nameLength() = 6; return accessor(object.d_salary, info); // RETURN } default: { return NOT_FOUND; // RETURN } } } template <class ACCESSOR> int mine::bdlat_sequenceAccessAttributes(const MySequence& object, ACCESSOR& accessor) { int retVal; retVal = bdlat_sequenceAccessAttribute(object, accessor, MySequence::NAME_ATTRIBUTE_ID); if (0 != retVal) { return retVal; // RETURN } retVal = bdlat_sequenceAccessAttribute(object, accessor, MySequence::AGE_ATTRIBUTE_ID); if (0 != retVal) { return retVal; // RETURN } retVal = bdlat_sequenceAccessAttribute( object, accessor, MySequence::SALARY_ATTRIBUTE_ID); return retVal; } bool mine::bdlat_sequenceHasAttribute( const MySequence& , const char *attributeName, int attributeNameLength) { return bdlb::String::areEqualCaseless("name", attributeName, attributeNameLength) || bdlb::String::areEqualCaseless("age", attributeName, attributeNameLength) || bdlb::String::areEqualCaseless("salary", attributeName, attributeNameLength); } bool mine::bdlat_sequenceHasAttribute(const MySequence& , int attributeId) { return MySequence::NAME_ATTRIBUTE_ID == attributeId || MySequence::AGE_ATTRIBUTE_ID == attributeId || MySequence::SALARY_ATTRIBUTE_ID == attributeId; }
IsSequence
meta-function in the bdlat_SequenceFunctions
namespace for the mine::MySequence
type. This makes the bdlat
infrastructure recognize mine::MySequence
as a sequence abstraction: namespace bdlat_SequenceFunctions { template <> struct IsSequence<mine::MySequence> { enum { VALUE = 1 }; }; } // close namespace bdlat_SequenceFunctions } // close enterprise namespace
bdlat
infrastructure (and any component that uses this infrastructure) will now recognize mine::MySequence
as a "sequence" type. For example, suppose we have the following XML data: <?xml version='1.0' encoding='UTF-8' ?> <MySequence> <name>John Doe</name> <age>29</age> <salary>12345.00</salary> </MySequence>
balxml_decoder
component, we can now load this XML data into a mine::MySequence
object: #include <balxml_decoder.h> void decodeMySequenceFromXML(bsl::istream& inputData) { using namespace BloombergLP; mine::MySequence object; 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("John Doe" == object.d_name); assert(29 == object.d_age); assert(12345.00 == object.d_salary); }
bdlat
framework can be used for functionality other than encoding/decoding into XML. When mine::MySequence
is plugged into the framework, then it will be automatically usable within the framework. For example, the following snippets of code will print out all the attributes of a sequence object: struct PrintAttribute { // Print each visited object to the bound 'd_stream_p' object. // DATA MEMBERS bsl::ostream *d_stream_p; template <class TYPE, class INFO> int operator()(const TYPE& object, const INFO& info) { (*d_stream_p) << info.name() << ": " << object << bsl::endl; return 0; } }; template <class TYPE> void printSequenceAttributes(bsl::ostream& stream, const TYPE& object) { PrintAttribute accessor; accessor.d_stream_p = &stream; bdlat_SequenceFunctions::accessAttributes(object, accessor); }
void printMySequence(bsl::ostream& stream) { mine::MySequence object; object.d_name = "John Doe"; object.d_age = 25; object.d_salary = 12345.00; stream << bsl::fixed << bsl::setprecision(2); printSequenceAttributes(stream, object); }
name: John Doe age: 25 salary: 12345.00