Provide a utility to build a Datum
object holding an array.
More...
Namespaces |
namespace | bdld |
Detailed Description
- Outline
-
-
- Purpose:
- Provide a utility to build a
Datum
object holding an array.
-
- Classes:
-
- See also:
- Component bdld_datum
-
- Description:
- This component defines a mechanism,
bdld::DatumArrayBuilder
, used to populate a Datum
array value in an exception-safe manner. In addition to providing exception safety, a DatumArrayBuilder
is particularly useful when the length of the array to be constructed is not known in advance. The user can append elements to the datum array as needed, and when there are no more elements to append the user calls commit
and ownership of the populated Datum
object is transferred to the caller. After the call to commit
, no additional elements can be appended to the Datum
array value.
-
- Usage:
- This section illustrates intended use of this component.
-
- Example 1: Using a DatumArrayBuilder to Create a Datum array.:
- Suppose we receive a string that is constructed by streaming a bunch of values together in the format shown below: Notice that the values are separated by a
,
. Also note that a ,
is not allowed to be part of a string value to simplify the implementation of the utility that parses this string. The following code snippets illustrate how to create a Datum
object that holds an array of Datum
objects constructed using the streamed values.
- First we define a function
nextValue
that we will use to tokenize the input string: bsl::size_t nextValue(bsl::string *value, const bsl::string& input)
{
if (input.empty()) {
return bsl::string::npos;
}
int start = 0;
bsl::size_t nextIndex = input.find(',', start);
if (bsl::string::npos != nextIndex) {
*value = input.substr(start, nextIndex - start);
}
else {
*value = input.substr(start);
}
return nextIndex;
}
Next, we define a function convertToDatum
that will convert a string token into a Datum
scalar value: bdld::Datum convertToDatum(const bsl::string& token,
bslma::Allocator *basicAllocator)
{
bool isInteger = true;
bool isDouble = false;
bool isBoolean = false;
for (bsl::size_t i = 0; i < token.size(); ++i) {
if (!isdigit(token[i])) {
if ('.' == token[i] && !isDouble) {
isDouble = true;
isInteger = false;
continue;
}
isInteger = false;
isDouble = false;
break;
}
}
if (!isInteger && !isDouble) {
if ("true" == token || "false" == token) {
isBoolean = true;
}
}
if (isInteger) {
return bdld::Datum::createInteger(atoi(token.c_str()));
}
else if (isDouble) {
return bdld::Datum::createDouble(atof(token.c_str()));
}
else if (isBoolean) {
return bdld::Datum::createBoolean("true" == token ? true : false);
}
else {
return bdld::Datum::copyString(token, basicAllocator);
}
}
Now, in our example main, we tokenize an input string "2.34,4,hi there,true" to populate a Datum
array containing the values '[2.34, 4, "hi there", true]': void exampleMain() {
bslma::TestAllocator allocator;
const bsl::string input("2.34,4,hi there,true", &allocator);
Here, we create a DatumArrayBuilder
, and iterate over the parsed tokens from input
, using pushBack
on the array builder to add the tokens to a Datum
array value: bdld::DatumArrayBuilder builder(0, &allocator);
bsl::string str(input, &allocator);
bsl::string value;
bsl::size_t nextIndex;
do {
nextIndex = nextValue(&value, str);
builder.pushBack(convertToDatum(value, &allocator));
if (bsl::string::npos == nextIndex) {
break;
}
str = str.substr(nextIndex + 1);
} while (bsl::string::npos != nextIndex);
bdld::Datum result = builder.commit();
Notice that calling commit
on the DatumArrayBuilder
adopts ownership for the returned Datum
object, and that the behavior is undefined if pushBack
is called after commit
.
- Finally, we verify that
result
has the expected array value, and destroy the created Datum
value: assert(true == result.isArray());
assert(4 == result.theArray().length());
assert(true == result.theArray()[0].isDouble());
assert(2.34 == result.theArray()[0].theDouble());
assert(true == result.theArray()[1].isInteger());
assert(4 == result.theArray()[1].theInteger());
assert(true == result.theArray()[2].isString());
assert("hi there" == result.theArray()[2].theString());
assert(true == result.theArray()[3].isBoolean());
assert(true == result.theArray()[3].theBoolean());
bdld::Datum::destroy(result, &allocator);
}