BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bdlat_sequencefunctions

Detailed Description

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:

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 {
// 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'

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 {
// 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
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);
} // close namespace mine

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);
// RETURN
}
attributeName,
attributeNameLength)) {
object,
manipulator,
MySequence::AGE_ATTRIBUTE_ID);
// RETURN
}
attributeName,
attributeNameLength)) {
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: {
info.annotation() = "Name of employee";
info.id() = MySequence::NAME_ATTRIBUTE_ID;
info.name() = "name";
info.nameLength() = 4;
return manipulator(&object->d_name, info); // RETURN
}
case MySequence::AGE_ATTRIBUTE_ID: {
info.annotation() = "Age of employee";
info.id() = MySequence::AGE_ATTRIBUTE_ID;
info.name() = "age";
info.nameLength() = 3;
return manipulator(&object->d_age, info); // RETURN
}
case MySequence::SALARY_ATTRIBUTE_ID: {
info.annotation() = "Salary of employee";
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;
object,
manipulator,
MySequence::NAME_ATTRIBUTE_ID);
if (0 != retVal) {
return retVal; // RETURN
}
object,
manipulator,
MySequence::AGE_ATTRIBUTE_ID);
if (0 != retVal) {
return retVal; // RETURN
}
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 };
attributeName,
attributeNameLength)) {
object,
accessor,
MySequence::NAME_ATTRIBUTE_ID);
// RETURN
}
attributeName,
attributeNameLength)) {
accessor,
MySequence::AGE_ATTRIBUTE_ID);
// RETURN
}
attributeName,
attributeNameLength)) {
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: {
info.annotation() = "Name of employee";
info.id() = MySequence::NAME_ATTRIBUTE_ID;
info.name() = "name";
info.nameLength() = 4;
return accessor(object.d_name, info); // RETURN
}
case MySequence::AGE_ATTRIBUTE_ID: {
info.annotation() = "Age of employee";
info.id() = MySequence::AGE_ATTRIBUTE_ID;
info.name() = "age";
info.nameLength() = 3;
return accessor(object.d_age, info); // RETURN
}
case MySequence::SALARY_ATTRIBUTE_ID: {
info.annotation() = "Salary of employee";
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;
accessor,
MySequence::NAME_ATTRIBUTE_ID);
if (0 != retVal) {
return retVal; // RETURN
}
accessor,
MySequence::AGE_ATTRIBUTE_ID);
if (0 != retVal) {
return retVal; // RETURN
}
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
@ e_DEFAULT
Definition bdlat_formattingmode.h:110
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 <>
struct IsSequence<mine::MySequence> : bsl::true_type {
};
} // close namespace bdlat_SequenceFunctions
} // close enterprise namespace
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:

#include <balxml_decoder.h>
void decodeMySequenceFromXML(bsl::istream& inputData)
{
using namespace BloombergLP;
mine::MySequence object;
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);
}
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 {
// 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;
}
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