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