Outline
Purpose
Provide a namespace defining sequence functions.
Classes
- See also
- bdlat_attributeinfo
Description
The 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.
The functions in this namespace allow users to:
- manipulate an attribute by attribute id or attribute name using a parameterized manipulator (
manipulateAttribute),
- manipulate all attributes sequentially using a parameterized manipulator (
manipulateAttributes),
- access an attribute by attribute id or attribute name using a parameterized accessor (
accessAttribute), and
- access all attributes sequentially using a parameterized accessor (
accessAttributes).
Also, the meta-function IsSequence contains a compile-time constant value that is non-zero if the parameterized TYPE exposes "sequence" behavior through the bdlat_SequenceFunctions namespace.
This component specializes all of these functions for types that have the bdlat_TypeTraitBasicSequence trait.
Types that do not have the 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 {
template <typename MANIPULATOR>
int bdlat_sequenceManipulateAttribute(
MySequence *object,
MANIPULATOR& manipulator,
const char *attributeName,
int attributeNameLength);
template <typename MANIPULATOR>
int bdlat_sequenceManipulateAttribute(MySequence *object,
MANIPULATOR& manipulator,
int attributeId);
template <typename MANIPULATOR>
int bdlat_sequenceManipulateAttributes(MySequence *object,
MANIPULATOR& manipulator);
template <typename ACCESSOR>
int bdlat_sequenceAccessAttribute(const MySequence& object,
ACCESSOR& accessor,
const char *attributeName,
int attributeNameLength);
template <typename ACCESSOR>
int bdlat_sequenceAccessAttribute(const MySequence& object,
ACCESSOR& accessor,
int attributeId);
template <typename 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);
}
Also, the IsSequence meta-function must be specialized for the mine::MySequence type in the bdlat_SequenceFunctions namespace.
An example of plugging in a user-defined sequence type into the bdlat framework is shown in the {Usage} section of this document.
Usage
This section illustrates intended use of this component.
Example 1: Basic Usage
Suppose you had a struct that contains three members:
namespace BloombergLP {
namespace mine {
struct MySequence {
enum {
NAME_ATTRIBUTE_ID = 1,
AGE_ATTRIBUTE_ID = 2,
SALARY_ATTRIBUTE_ID = 3
};
int d_age;
float d_salary;
};
}
Definition bslstl_string.h:1281
We can now make 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);
}
Now, we will implement these functions. Note that for this implementation, we will create a temporary 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 };
attributeName,
attributeNameLength)) {
return bdlat_sequenceManipulateAttribute(
object,
manipulator,
MySequence::NAME_ATTRIBUTE_ID);
}
attributeName,
attributeNameLength)) {
object,
manipulator,
MySequence::AGE_ATTRIBUTE_ID);
}
attributeName,
attributeNameLength)) {
object,
manipulator,
MySequence::SALARY_ATTRIBUTE_ID);
}
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: {
info.
id() = MySequence::NAME_ATTRIBUTE_ID;
return manipulator(&object->d_name, info);
}
case MySequence::AGE_ATTRIBUTE_ID: {
info.
id() = MySequence::AGE_ATTRIBUTE_ID;
return manipulator(&object->d_age, info);
}
case MySequence::SALARY_ATTRIBUTE_ID: {
info.
id() = MySequence::SALARY_ATTRIBUTE_ID;
return manipulator(&object->d_salary, info);
}
default: {
return NOT_FOUND;
}
}
}
template <class MANIPULATOR>
int mine::bdlat_sequenceManipulateAttributes(MySequence *object,
MANIPULATOR& manipulator)
{
int retVal;
object,
manipulator,
MySequence::NAME_ATTRIBUTE_ID);
if (0 != retVal) {
return retVal;
}
object,
manipulator,
MySequence::AGE_ATTRIBUTE_ID);
if (0 != retVal) {
return retVal;
}
object,
manipulator,
MySequence::SALARY_ATTRIBUTE_ID);
return retVal;
}
template <class ACCESSOR>
int mine::bdlat_sequenceAccessAttribute(
const MySequence& object,
ACCESSOR& accessor,
const char *attributeName,
int attributeNameLength)
{
enum { NOT_FOUND = -1 };
attributeName,
attributeNameLength)) {
object,
accessor,
MySequence::NAME_ATTRIBUTE_ID);
}
attributeName,
attributeNameLength)) {
accessor,
MySequence::AGE_ATTRIBUTE_ID);
}
attributeName,
attributeNameLength)) {
object,
accessor,
MySequence::SALARY_ATTRIBUTE_ID);
}
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: {
info.
id() = MySequence::NAME_ATTRIBUTE_ID;
return accessor(object.d_name, info);
}
case MySequence::AGE_ATTRIBUTE_ID: {
info.
id() = MySequence::AGE_ATTRIBUTE_ID;
return accessor(object.d_age, info);
}
case MySequence::SALARY_ATTRIBUTE_ID: {
info.
id() = MySequence::SALARY_ATTRIBUTE_ID;
return accessor(object.d_salary, info);
}
default: {
return NOT_FOUND;
}
}
}
template <class ACCESSOR>
int mine::bdlat_sequenceAccessAttributes(const MySequence& object,
ACCESSOR& accessor)
{
int retVal;
accessor,
MySequence::NAME_ATTRIBUTE_ID);
if (0 != retVal) {
return retVal;
}
accessor,
MySequence::AGE_ATTRIBUTE_ID);
if (0 != retVal) {
return retVal;
}
object,
accessor,
MySequence::SALARY_ATTRIBUTE_ID);
return retVal;
}
bool mine::bdlat_sequenceHasAttribute(
const MySequence& ,
const char *attributeName,
int attributeNameLength)
{
attributeName,
attributeNameLength)
attributeName,
attributeNameLength)
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;
}
int & formattingMode()
Definition bdlat_attributeinfo.h:251
const char *& name()
Definition bdlat_attributeinfo.h:263
int & nameLength()
Definition bdlat_attributeinfo.h:269
const char *& annotation()
Definition bdlat_attributeinfo.h:245
int & id()
Definition bdlat_attributeinfo.h:257
int bdlat_sequenceAccessAttribute(const TYPE &object, ACCESSOR &accessor, const char *attributeName, int attributeNameLength)
int bdlat_sequenceManipulateAttribute(TYPE *object, MANIPULATOR &manipulator, const char *attributeName, int attributeNameLength)
Definition bdlat_attributeinfo.h:137
static bool areEqualCaseless(const char *lhsString, const char *rhsString)
Finally, we need to specialize the 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:
template <>
};
}
}
Definition bdlat_sequencefunctions.h:635
The 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>
Using the balxml_decoder component, we can now load this XML data into a mine::MySequence object:
void decodeMySequenceFromXML(bsl::istream& inputData)
{
using namespace BloombergLP;
mine::MySequence object;
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);
}
Definition balxml_decoderoptions.h:72
Definition balxml_decoder.h:402
Definition balxml_errorinfo.h:353
Definition balxml_minireader.h:343
Note that the 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 {
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;
}
int accessAttributes(const TYPE &object, ACCESSOR &accessor)
Now we have a generic function that takes an output stream and a sequence object, and prints out each attribute with its name and value. We can use this generic function as follows:
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);
}
The function above will print the following to provided stream:
name: John Doe
age: 25
salary: 12345.00