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

Detailed Description

Outline

Purpose

Provide extra functions that operate on bdld::Datum objects.

Classes

See also
bdld_datum

Description

This component provides a struct, bdld::DatumUtil that serves as a namespace for utility functions that operate on bdld::Datum objects. The functions provided are typedPrint and safeTypedPrint. They are a variation on the standard BDE-style print function but print the Datum values in a manner that disambiguates the type when the value itself would not do so.

Usage

This section illustrates intended use of this component.

Example 1: Showing the Difference Between an Integer and a Double Value

Suppose we are testing a system with operations that result in bdld::Datum values. We verify that those results are what we have expected, including that their type matches. After a getting an unexpected value, we use normal printing and get the following test failure: "Expected 1, got 1". Obviously, the type difference is not visible. Instead, we can use bdld::DatumUtil::typedPrint to display the type as well as the value.

First, let us define two bdld::Datum objects that have the same value, but use different types to represent them:

assert(expected != actual);
Definition bdld_datum.h:787
static Datum createDouble(double value)
Definition bdld_datum.h:3820
static Datum createInteger(int value)
Return, by value, a datum having the specified int value.
Definition bdld_datum.h:3848

Next, we demonstrate that printing these results in the same printout:

os << expected;
bsl::string expectedStr = os.str();
os.str("");
os.clear();
os << actual;
bsl::string actualStr = os.str();
assert(expectedStr == actualStr); // "1" is equal to "1"
Definition bslstl_ostringstream.h:175
void str(const StringType &value)
Definition bslstl_ostringstream.h:581
Definition bslstl_string.h:1281

Then, we create a shorthand for bdld::DatumUtil::typedPrint:

void printWithType(bsl::ostream& outStream, const bdld::Datum& object)
{
bdld::DatumUtil::typedPrint(outStream, object, 0, -1);
}
static bsl::ostream & typedPrint(bsl::ostream &outputStream, const Datum &object, int level=0, int spacesPerLevel=4)

The 0 level and -1 spacesPerLevel results in single-line printout without a trailing newline, just like the stream output operator works.

Finally, we verify that now we get a different printout for the two values:

os.str("");
os.clear();
printWithType(os, expected);
expectedStr = os.str();
os.str("");
os.clear();
printWithType(os, actual);
actualStr = os.str();
assert(expectedStr != actualStr); // "1i" is *not* equal to "1."

Example 2: Avoiding Endless Printing of Data with Cycles

Suppose that we are testing a system that creates a complex data structure that it stores is bdld::Datum objects. Suppose that such a system doesn't use the fail-safe Datum builders for optimization purposes (for example it stores all map entries in one big allocation), and so it may be able to create a self-referential data structure.

It is not easy to legitimately create self-referential data structures so we won't even attempt it in a short example code.

First, we use a bdld::DatumMaker with a local allocator so we can ignore any cleanup and allocation:

Definition bdld_datummaker.h:158
Definition bdlma_localsequentialallocator.h:230

Next, we create two array datums with a Nil element each:

bdld::Datum arr1 = dm.a(dm());
bdld::Datum arr2 = dm.a(dm());

Then, we circumvent the type system to initialize their single elements to "contain" each other:

const_cast<bdld::Datum&>(arr1.theArray()[0]) = arr2;
const_cast<bdld::Datum&>(arr2.theArray()[0]) = arr1;
DatumArrayRef theArray() const
Definition bdld_datum.h:4257

Finally, we use the safe printing on this trapdoor of an endless loop to nevertheless safely print them:

static bsl::ostream & safeTypedPrint(bsl::ostream &outputStream, const Datum &object, int level=0, int spacesPerLevel=4)

Were we to print the results standard out, say

we would see something akin to:

<array@000000EFE4CFF928[
<array@000000EFE4CFF908[
<array@000000EFE4CFF928[!CYCLE!]>
]>
]>

The hexadecimal numbers above identify the arrays (and maps or int-maps) so we can clearly see that the cycle "points" back to the top-level array.