BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bdld_datumutil.h
Go to the documentation of this file.
1/// @file bdld_datumutil.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bdld_datumutil.h -*-C++-*-
8#ifndef INCLUDED_BDLD_DATUMUTIL
9#define INCLUDED_BDLD_DATUMUTIL
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bdld_datumutil bdld_datumutil
15/// @brief Provide extra functions that operate on `bdld::Datum` objects.
16/// @addtogroup bdl
17/// @{
18/// @addtogroup bdld
19/// @{
20/// @addtogroup bdld_datumutil
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bdld_datumutil-purpose"> Purpose</a>
25/// * <a href="#bdld_datumutil-classes"> Classes </a>
26/// * <a href="#bdld_datumutil-description"> Description </a>
27/// * <a href="#bdld_datumutil-usage"> Usage </a>
28/// * <a href="#bdld_datumutil-example-1-showing-the-difference-between-an-integer-and-a-double-value"> Example 1: Showing the Difference Between an Integer and a Double Value </a>
29/// * <a href="#bdld_datumutil-example-2-avoiding-endless-printing-of-data-with-cycles"> Example 2: Avoiding Endless Printing of Data with Cycles </a>
30///
31/// # Purpose {#bdld_datumutil-purpose}
32/// Provide extra functions that operate on `bdld::Datum` objects.
33///
34/// # Classes {#bdld_datumutil-classes}
35///
36/// - bdld::DatumUtil: namespace for extra functions for `bdld::Datum`
37///
38/// @see bdld_datum
39///
40/// # Description {#bdld_datumutil-description}
41/// This component provides a struct, `bdld::DatumUtil` that serves
42/// as a namespace for utility functions that operate on `bdld::Datum` objects.
43/// The functions provided are `typedPrint` and `safeTypedPrint`. They are a
44/// variation on the standard BDE-style `print` function but print the `Datum`
45/// values in a manner that disambiguates the type when the value itself would
46/// not do so.
47///
48/// ## Usage {#bdld_datumutil-usage}
49///
50///
51/// This section illustrates intended use of this component.
52///
53/// ### Example 1: Showing the Difference Between an Integer and a Double Value {#bdld_datumutil-example-1-showing-the-difference-between-an-integer-and-a-double-value}
54///
55///
56/// Suppose we are testing a system with operations that result in `bdld::Datum`
57/// values. We verify that those results are what we have expected, *including*
58/// that their type matches. After a getting an unexpected value, we use normal
59/// printing and get the following test failure: "Expected 1, got 1".
60/// Obviously, the type difference is not visible. Instead, we can use
61/// `bdld::DatumUtil::typedPrint` to display the type as well as the value.
62///
63/// First, let us define two `bdld::Datum` objects that have the same value, but
64/// use different types to represent them:
65/// @code
66/// bdld::Datum expected = bdld::Datum::createInteger(1);
67/// bdld::Datum actual = bdld::Datum::createDouble(1.);
68///
69/// assert(expected != actual);
70/// @endcode
71/// Next, we demonstrate that printing these results in the same printout:
72/// @code
73/// bsl::ostringstream os;
74///
75/// os << expected;
76/// bsl::string expectedStr = os.str();
77///
78/// os.str("");
79/// os.clear();
80/// os << actual;
81/// bsl::string actualStr = os.str();
82///
83/// assert(expectedStr == actualStr); // "1" is equal to "1"
84/// @endcode
85/// Then, we create a shorthand for `bdld::DatumUtil::typedPrint`:
86/// @code
87/// void printWithType(bsl::ostream& outStream, const bdld::Datum& object)
88/// {
89/// bdld::DatumUtil::typedPrint(outStream, object, 0, -1);
90/// }
91/// @endcode
92/// The 0 `level` and -1 `spacesPerLevel` results in single-line printout
93/// without a trailing newline, just like the stream output operator works.
94///
95/// Finally, we verify that now we get a different printout for the two values:
96/// @code
97/// os.str("");
98/// os.clear();
99/// printWithType(os, expected);
100/// expectedStr = os.str();
101///
102/// os.str("");
103/// os.clear();
104/// printWithType(os, actual);
105/// actualStr = os.str();
106///
107/// assert(expectedStr != actualStr); // "1i" is *not* equal to "1."
108/// @endcode
109///
110/// ### Example 2: Avoiding Endless Printing of Data with Cycles {#bdld_datumutil-example-2-avoiding-endless-printing-of-data-with-cycles}
111///
112///
113/// Suppose that we are testing a system that creates a complex data structure
114/// that it stores is `bdld::Datum` objects. Suppose that such a system doesn't
115/// use the fail-safe `Datum` builders for optimization purposes (for example it
116/// stores all map entries in one big allocation), and so it may be able to
117/// create a self-referential data structure.
118///
119/// It is not easy to legitimately create self-referential data structures so we
120/// won't even attempt it in a short example code.
121///
122/// First, we use a `bdld::DatumMaker` with a local allocator so we can ignore
123/// any cleanup and allocation:
124/// @code
125/// bdlma::LocalSequentialAllocator<1024> lsa;
126/// bdld::DatumMaker dm(&lsa);
127/// @endcode
128/// Next, we create two array datums with a Nil element each:
129/// @code
130/// bdld::Datum arr1 = dm.a(dm());
131/// bdld::Datum arr2 = dm.a(dm());
132/// @endcode
133/// Then, we circumvent the type system to initialize their single elements to
134/// "contain" each other:
135/// @code
136/// const_cast<bdld::Datum&>(arr1.theArray()[0]) = arr2;
137/// const_cast<bdld::Datum&>(arr2.theArray()[0]) = arr1;
138/// @endcode
139/// Finally, we use the safe printing on this trapdoor of an endless loop to
140/// nevertheless safely print them:
141/// @code
142/// bsl::ostringstream os;
143/// bdld::DatumUtil::safeTypedPrint(os, arr1);
144/// @endcode
145/// Were we to print the results standard out, say
146/// @code
147/// bdld::DatumUtil::safeTypedPrint(cout, arr2);
148/// @endcode
149/// we would see something akin to:
150/// @code
151/// <array@000000EFE4CFF928[
152/// <array@000000EFE4CFF908[
153/// <array@000000EFE4CFF928[!CYCLE!]>
154/// ]>
155/// ]>
156/// @endcode
157/// The hexadecimal numbers above identify the arrays (and maps or int-maps) so
158/// we can clearly see that the cycle "points" back to the top-level array.
159/// @}
160/** @} */
161/** @} */
162
163/** @addtogroup bdl
164 * @{
165 */
166/** @addtogroup bdld
167 * @{
168 */
169/** @addtogroup bdld_datumutil
170 * @{
171 */
172
173#include <bdlscm_version.h>
174
175#include <bsl_iosfwd.h>
176
177
178namespace bdld {
179
180class Datum;
181 // ================
182 // struct DatumUtil
183 // ================
184
185/// This struct serves as a namespace for utility functions that operate on
186/// `bdld::Datum` objects.
187struct DatumUtil {
188
189 // CLASS METHODS
190
191 /// Write the value of the specified `object` to the specified
192 /// `outputStream` in a human-readable format that is non-ambiguous
193 /// regarding the type of the `bdld::Datum` value printed, and return a
194 /// reference to the modifiable `outputStream`. Optionally specify an
195 /// initial indentation `level`, whose absolute value is incremented
196 /// recursively for nested objects. If `level` is specified, optionally
197 /// specify `spacesPerLevel`, whose absolute value indicates the number
198 /// of spaces per indentation level for this and all of its nested
199 /// objects. If `level` is negative, suppress indentation of the first
200 /// line. If `spacesPerLevel` is negative, format the entire output on
201 /// one line, suppressing all but the initial indentation (as governed
202 /// by `level`). If `stream` is not valid on entry, this operation has
203 /// no effect. Note that `safeTypedPrint` explicitly allows self-
204 /// referential data structures, or in other words data structures with
205 /// cycles, to be printed. When a cycle is detected, that subgraph is
206 /// not printed again. Also note that the human-readable format is not
207 /// fully specified, and can change without notice.
208 static bsl::ostream& safeTypedPrint(bsl::ostream& outputStream,
209 const Datum& object,
210 int level = 0,
211 int spacesPerLevel = 4);
212
213 /// Write the value of the specified `object` to the specified
214 /// `outputStream` in a human-readable format that is non-ambiguous
215 /// regarding the type of the `bdld::Datum` value printed, and return a
216 /// reference to the modifiable `outputStream`. Optionally specify an
217 /// initial indentation `level`, whose absolute value is incremented
218 /// recursively for nested objects. If `level` is specified, optionally
219 /// specify `spacesPerLevel`, whose absolute value indicates the number
220 /// of spaces per indentation level for this and all of its nested
221 /// objects. If `level` is negative, suppress indentation of the first
222 /// line. If `spacesPerLevel` is negative, format the entire output on
223 /// one line, suppressing all but the initial indentation (as governed
224 /// by `level`). If `stream` is not valid on entry, this operation has
225 /// no effect. The behavior is undefined unless the data structure
226 /// represented by `object` is a graph without any cycles. In case of
227 /// an untrusted data structure, use `safeTypedPrint`. Note that the
228 /// human-readable format is not fully specified, and can change without
229 /// notice.
230 static bsl::ostream& typedPrint(bsl::ostream& outputStream,
231 const Datum& object,
232 int level = 0,
233 int spacesPerLevel = 4);
234};
235
236} // close package namespace
237
238
239#endif
240
241// ----------------------------------------------------------------------------
242// Copyright 2024 Bloomberg Finance L.P.
243//
244// Licensed under the Apache License, Version 2.0 (the "License");
245// you may not use this file except in compliance with the License.
246// You may obtain a copy of the License at
247//
248// http://www.apache.org/licenses/LICENSE-2.0
249//
250// Unless required by applicable law or agreed to in writing, software
251// distributed under the License is distributed on an "AS IS" BASIS,
252// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
253// See the License for the specific language governing permissions and
254// limitations under the License.
255// ----------------------------- END-OF-FILE ----------------------------------
256
257/** @} */
258/** @} */
259/** @} */
Definition bdld_datum.h:787
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
Definition bdld_datum.h:730
Definition bdld_datumutil.h:187
static bsl::ostream & typedPrint(bsl::ostream &outputStream, const Datum &object, int level=0, int spacesPerLevel=4)
static bsl::ostream & safeTypedPrint(bsl::ostream &outputStream, const Datum &object, int level=0, int spacesPerLevel=4)