BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bslim_printer.h
Go to the documentation of this file.
1/// @file bslim_printer.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bslim_printer.h -*-C++-*-
8#ifndef INCLUDED_BSLIM_PRINTER
9#define INCLUDED_BSLIM_PRINTER
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bslim_printer bslim_printer
15/// @brief Provide a mechanism to implement standard `print` methods.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bslim
19/// @{
20/// @addtogroup bslim_printer
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bslim_printer-purpose"> Purpose</a>
25/// * <a href="#bslim_printer-classes"> Classes </a>
26/// * <a href="#bslim_printer-description"> Description </a>
27/// * <a href="#bslim_printer-usage"> Usage </a>
28/// * <a href="#bslim_printer-example-1-print-method-for-a-value-semantic-class"> Example 1: print Method for a Value-Semantic Class </a>
29/// * <a href="#bslim_printer-example-2-print-method-for-a-mechanism-class"> Example 2: print Method for a Mechanism Class </a>
30/// * <a href="#bslim_printer-example-3-foreign-classes-and-printing-stl-containers"> Example 3: Foreign (Third-Party) Classes, and Printing STL Containers </a>
31/// * <a href="#bslim_printer-example-4-printing-ranges-and-typed-pointers"> Example 4: Printing Ranges, and Typed Pointers </a>
32/// * <a href="#bslim_printer-example-5-print-method-for-a-low-level-value-semantic-class"> Example 5: print Method for a Low-Level Value-Semantic Class </a>
33///
34/// # Purpose {#bslim_printer-purpose}
35/// Provide a mechanism to implement standard `print` methods.
36///
37/// # Classes {#bslim_printer-classes}
38///
39/// - bslim::Printer: mechanism to implement standard `print` methods
40///
41/// # Description {#bslim_printer-description}
42/// This component provides a mechanism class, `bslim::Printer`,
43/// that, in many cases, simplifies the implementation of types providing a
44/// `print` method with the signature:
45/// @code
46/// bsl::ostream& print(bsl::ostream& stream,
47/// int level = 0,
48/// int spacesPerLevel = 4) const;
49/// // Format this object to the specified output 'stream' at the (absolute
50/// // value of) the optionally specified indentation 'level' and return a
51/// // reference to 'stream'. If 'level' is specified, optionally specify
52/// // 'spacesPerLevel', the number of spaces per indentation level for
53/// // this and all of its nested objects. If 'level' is negative,
54/// // suppress indentation of the first line. If 'spacesPerLevel' is
55/// // negative format the entire output on one line, suppressing all but
56/// // the initial indentation (as governed by 'level'). If 'stream' is
57/// // not valid on entry, this operation has no effect.
58/// @endcode
59/// Note that all value-semantic types are expected to provide this method.
60/// `bslim::Printer` also supports generic containers, including those in BSL's
61/// standard library implementation, through use of standard conforming
62/// iterators and the `bslalg::HasStlIterators` trait. Use of the `Printer`
63/// mechanism provides a uniform style of output formatting:
64///
65/// * Enclose the object's salient attributes with square brackets.
66/// * Prefix each attribute with the attribute's name, separated by an "equal"
67/// sign surrounded by space characters (" = ").
68/// * If the attributes are to be printed on multiple lines, then print them
69/// with one more level of indentation than that of the enclosing brackets.
70/// If any of the attributes are compositions, then the composite values
71/// must be printed with an additional level of indentation.
72/// * If the attributes are to be printed on a single line, then separate each
73/// value with a single space character.
74/// * For small, common types, such as `bdlt::Date`, the names of attributes,
75/// equal sign, and brackets may be omitted, with the entire value
76/// represented on a single line in a custom format. For example, the
77/// `bdlt::Date::print` method emits the date value in the format: 01JAN2001.
78///
79/// For example, consider a class having two attributes, `ticker`, represented
80/// by a `bsl::string`, and `price`, represented by a `double`. The output for
81/// a `print` method that produces standardized output for
82/// `print(bsl::cout, 0, -4)` (single-line output) is shown below:
83/// @code
84/// [ ticker = "ABC" price = 65.89 ]
85/// @endcode
86/// Output for `print(bsl::cout, 0, 4)` (multi-line output) is shown below:
87/// @code
88/// [
89/// ticker = "ABC"
90/// price = 65.89
91/// ]
92/// @endcode
93/// The `Printer` mechanism provides methods and method templates to format data
94/// as described above. `Printer` objects are instantiated with the target
95/// stream to be written to, and the values of the indentation level of the
96/// data, `level`, and the spaces per level, `spacesPerLevel`. The methods
97/// provided by `Printer`, `printAttribute`, `printValue`, `printOrNull`,
98/// `printHexAddr` and `printForeign`, use these values for formatting. The
99/// `start` and `end` methods print the enclosing brackets of the output. In
100/// order to generate the standard output format, `start` should be called
101/// before any of the other methods, and `end` should be called after all the
102/// other methods have been called.
103///
104/// ## Usage {#bslim_printer-usage}
105///
106///
107/// In the following examples, we examine the implementation of the `print`
108/// method of different types of classes using `Printer`.
109///
110/// ### Example 1: print Method for a Value-Semantic Class {#bslim_printer-example-1-print-method-for-a-value-semantic-class}
111///
112///
113/// In this example, we demonstrate how to use `Printer` to implement the
114/// standard `print` function of a value-semantic class having multiple
115/// attributes. Suppose we have a class, `StockTrade`, that provides a
116/// container for a fixed set of attributes. A `StockTrade` object has four
117/// attributes, `ticker`, `price`, `quantity`, and optional `notes`:
118/// @code
119/// class StockTrade {
120/// // This class represents the properties of a stock trace.
121///
122/// // DATA
123/// bsl::string d_ticker; // ticker symbol
124/// double d_price; // stock price
125/// double d_quantity; // quanity traded
126/// bsl::optional<bsl::string> d_notes; // optional trade notes
127///
128/// public:
129/// ...
130///
131/// // ACCESSORS
132/// bsl::ostream& print(bsl::ostream& stream,
133/// int level = 0,
134/// int spacesPerLevel = 4) const
135/// {
136/// if (stream.bad()) {
137/// return stream; // RETURN
138/// }
139///
140/// bslim::Printer printer(&stream, level, spacesPerLevel);
141/// printer.start();
142/// printer.printAttribute("ticker", d_ticker);
143/// printer.printAttribute("price", d_price);
144/// printer.printAttribute("quantity", d_quantity);
145/// printer.printAttribute("notes", d_notes);
146/// printer.end();
147///
148/// return stream;
149/// }
150/// };
151/// @endcode
152/// Sample output for `StockTrade::print(bsl::cout, 0, -4)`:
153/// @code
154/// [ ticker = "IBM" price = 107.3 quantity = 200 notes = "XYZ" ]
155/// @endcode
156/// Sample output for `StockTrade::print(bsl::cout, 0, 4)`:
157/// @code
158/// [
159/// ticker = "IBM"
160/// price = 107.3
161/// quantity = 200
162/// notes = "XYZ"
163/// ]
164/// @endcode
165///
166/// ### Example 2: print Method for a Mechanism Class {#bslim_printer-example-2-print-method-for-a-mechanism-class}
167///
168///
169/// In this example, we discuss the implementation of `print` for a mechanism
170/// class. A mechanism class does not have any salient attributes that define
171/// its value (as a mechanism does not have a "value"). However, the `print`
172/// method may be implemented to output the internal state of an object of such
173/// a type, e.g., for debugging purposes.
174///
175/// For example, consider a memory manager class, `BlockList`, that maintains a
176/// linked list of memory blocks:
177/// @code
178/// class BlockList {
179/// // This class implements a low-level memory manager that allocates and
180/// // manages a sequence of memory blocks.
181///
182/// // TYPES
183/// struct Block {
184/// // This 'struct' overlays the beginning of each managed block of
185/// // allocated memory, implementing a doubly-linked list of managed
186/// // blocks, and thereby enabling constant-time deletions from, as
187/// // well as additions to, the list of blocks.
188///
189/// Block *d_next_p; // next
190/// // pointer
191///
192/// Block **d_addrPrevNext; // enable
193/// // delete
194///
195/// bsls::AlignmentUtil::MaxAlignedType d_memory; // force
196/// // alignment
197/// };
198///
199/// // DATA
200/// Block *d_head_p; // address of first block of memory
201/// // (or 0)
202///
203/// bslma::Allocator *d_allocator_p; // memory allocator; held, but not
204/// // owned
205///
206/// public:
207/// // ...
208/// // ACCESSORS
209/// // ...
210/// bsl::ostream& print(bsl::ostream& stream,
211/// int level = 0,
212/// int spacesPerLevel = 4) const;
213/// };
214/// @endcode
215/// For the purposes of debugging, it may be useful to print the starting
216/// address of every memory block in a `BlockList`, which can be done using the
217/// `printHexAddr` method of the `Printer` class:
218/// @code
219/// bsl::ostream& BlockList::print(bsl::ostream& stream,
220/// int level,
221/// int spacesPerLevel) const
222/// {
223/// if (stream.bad()) {
224/// return stream; // RETURN
225/// }
226///
227/// bslim::Printer printer(&stream, level, spacesPerLevel);
228/// printer.start();
229/// for (Block *it = d_head_p; it; it = it->d_next_p) {
230/// printer.printHexAddr(it, 0);
231/// }
232/// printer.end();
233///
234/// return stream;
235/// }
236/// @endcode
237/// Sample output for 'BlockList::print(bsl::cout, 0, -4):
238/// @code
239/// [ 0x0012fab4 0x0012fab8 ]
240/// @endcode
241/// Sample output for 'BlockList::print(bsl::cout, 0, 4):
242/// @code
243/// [
244/// 0x0012fab4
245/// 0x0012fab8
246/// ]
247/// @endcode
248///
249/// ### Example 3: Foreign (Third-Party) Classes, and Printing STL Containers {#bslim_printer-example-3-foreign-classes-and-printing-stl-containers}
250///
251///
252/// In this example, we use a `Printer` object to help format the properties of
253/// a class supplied by a third-party that does not implement the standard
254/// `print` method. Consider a struct, `ThirdPartyStruct`, defined in
255/// `/usr/include/thirdparty.h` that has no standard `print` method. We will be
256/// using this struct within another class `Customer`, storing some `Customer`
257/// objects in a map, and printing the map.
258/// @code
259/// struct ThirdPartyStruct {
260/// // Suppose this struct is defined somewhere in
261/// // '/usr/include/thirdparty.h', we have no control over it and hence
262/// // cannot add a .print method to it.
263///
264/// enum { PRIVATE = 1,
265/// WRITABLE = 2 };
266///
267/// short pid; // process id
268/// short access_flags; // options
269/// char user_id[20]; // userid
270/// };
271/// @endcode
272/// We create a struct `MyThirdPartyStructPrintUtil`:
273/// @code
274/// struct MyThirdPartyStructPrintUtil {
275/// static
276/// bsl::ostream& print(bsl::ostream& stream,
277/// const ThirdPartyStruct& data,
278/// int level = 0,
279/// int spacesPerLevel = 4);
280/// // You write this function in your own code to accommodate
281/// // 'ThirdPartyStruct'.
282/// };
283///
284/// bsl::ostream& MyThirdPartyStructPrintUtil::print(
285/// bsl::ostream& stream,
286/// const ThirdPartyStruct& data,
287/// int level,
288/// int spacesPerLevel)
289/// {
290/// bslim::Printer printer(&stream, level, spacesPerLevel);
291/// printer.start();
292/// printer.printAttribute("pid", data.pid);
293/// printer.printAttribute("access_flags", data.access_flags);
294/// printer.printAttribute("user_id", data.user_id);
295/// printer.end();
296///
297/// return stream;
298/// }
299/// @endcode
300/// We create a class `Customer` that has a `ThirdPartyStruct` in it:
301/// @code
302/// class Customer {
303/// // DATA
304/// bsl::string d_companyName;
305/// ThirdPartyStruct d_thirdPartyStruct;
306/// bool d_loyalCustomer;
307///
308/// public:
309/// // CREATORS
310/// Customer() {}
311///
312/// Customer(const bsl::string& companyName,
313/// short pid,
314/// short accessFlags,
315/// const bsl::string& userId,
316/// bool loyalCustomer)
317/// : d_companyName(companyName)
318/// , d_loyalCustomer(loyalCustomer)
319/// {
320/// d_thirdPartyStruct.pid = pid;
321/// d_thirdPartyStruct.access_flags = accessFlags;
322/// bsl::strcpy(d_thirdPartyStruct.user_id, userId.c_str());
323/// }
324///
325/// // ACCESSORS
326/// void print(bsl::ostream& stream,
327/// int level = 0,
328/// int spacesPerLevel = 4) const
329/// {
330/// bslim::Printer printer(&stream, level, spacesPerLevel);
331/// printer.start();
332/// printer.printAttribute("CompanyName", d_companyName);
333/// printer.printForeign(d_thirdPartyStruct,
334/// &MyThirdPartyStructPrintUtil::print,
335/// "ThirdPartyStruct");
336/// printer.printAttribute("LoyalCustomer", d_loyalCustomer);
337/// printer.end();
338/// }
339/// };
340/// @endcode
341/// We then create some `Customer` objects and put them in a map:
342/// @code
343/// void myFunc()
344/// {
345/// bsl::map<int, Customer> myMap;
346/// myMap[7] = Customer("Honeywell",
347/// 27,
348/// ThirdPartyStruct::PRIVATE,
349/// "hw",
350/// true);
351/// myMap[5] = Customer("IBM",
352/// 32,
353/// ThirdPartyStruct::WRITABLE,
354/// "ibm",
355/// false);
356/// myMap[8] = Customer("Burroughs",
357/// 45,
358/// 0,
359/// "burr",
360/// true);
361/// @endcode
362/// Now we print the map
363/// @code
364/// bslim::Printer printer(&cout, 0, 4);
365/// printer.start();
366/// printer.printValue(myMap);
367/// printer.end();
368/// }
369/// @endcode
370/// The following is written to `stdout`:
371/// @code
372/// [
373/// [
374/// [
375/// 5
376/// [
377/// CompanyName = "IBM"
378/// ThirdPartyStruct = [
379/// pid = 32
380/// access_flags = 2
381/// user_id = "ibm"
382/// ]
383/// LoyalCustomer = false
384/// ]
385/// ]
386/// [
387/// 7
388/// [
389/// CompanyName = "Honeywell"
390/// ThirdPartyStruct = [
391/// pid = 27
392/// access_flags = 1
393/// user_id = "hw"
394/// ]
395/// LoyalCustomer = true
396/// ]
397/// ]
398/// [
399/// 8
400/// [
401/// CompanyName = "Burroughs"
402/// ThirdPartyStruct = [
403/// pid = 45
404/// access_flags = 0
405/// user_id = "burr"
406/// ]
407/// LoyalCustomer = true
408/// ]
409/// ]
410/// ]
411/// ]
412/// @endcode
413///
414/// ### Example 4: Printing Ranges, and Typed Pointers {#bslim_printer-example-4-printing-ranges-and-typed-pointers}
415///
416///
417/// In this examples we demonstrate two capabilities of a `bslim::Printer`
418/// object: printing a range of elements using iterators and printing a pointer
419/// type.
420///
421/// The `printValue` or `printAttribute` methods of `bslim::Printer` will print
422/// out all of the elements in the range specified by a pair of iterator
423/// arguments, which can be of any type that provides appropriately behaving
424/// operators `++`, `*`, and `==` (a non-void pointer would qualify).
425///
426/// When `bslim` encounters a single pointer of type `TYPE *`, where `TYPE` is
427/// neither `void` nor `char`, the pointer value is printed out in hex followed
428/// by printing out the value of `TYPE`. A compile error will occur if bslim is
429/// unable to print out `TYPE`.
430///
431/// As an example, we print out a range of pointers to sets.
432///
433/// First we create 3 sets and populate them with different values.
434/// @code
435/// typedef bsl::set<int> Set;
436///
437/// Set s0, s1, s2;
438///
439/// s0.insert(0);
440/// s0.insert(1);
441/// s0.insert(2);
442///
443/// s1.insert(4);
444/// s1.insert(5);
445///
446/// s2.insert(8);
447/// @endcode
448/// Then, we store the addresses to those 3 sets into a fixed-length array:
449/// @code
450/// const Set *setArray[] = { &s0, &s1, &s2 };
451/// const int NUM_SET_ARRAY = sizeof setArray / sizeof *setArray;
452/// @endcode
453/// Next we use `printValue` to print a range of values by supplying an iterator
454/// to the beginning and end of the range, in the address of `setArray` and the
455/// address one past the end of `setArray`:
456/// @code
457/// bslim::Printer printer(&cout, 0, -1);
458/// printer.printValue(setArray + 0, setArray + NUM_SET_ARRAY);
459/// @endcode
460/// The expected output is:
461/// @code
462/// [ 0xffbfd688 [ 0 1 2 ] 0xffbfd678 [ 4 5 ] 0xffbfd668 [ 8 ] ]
463/// @endcode
464///
465/// ### Example 5: print Method for a Low-Level Value-Semantic Class {#bslim_printer-example-5-print-method-for-a-low-level-value-semantic-class}
466///
467///
468/// For very simple classes, it may be desirable always to format the attributes
469/// on a single line. In this example, we discuss the `print` method formatting
470/// for such a low-level value-semantic class.
471///
472/// Usually, single-line or multi-line formatting options are specified by the
473/// value of the `spacesPerLevel` argument, but for a simple class that always
474/// prints on a single line, the only difference between the single- and
475/// multi-line cases is that a newline character is printed at the end of the
476/// output for the multi-line case. For such classes, the "name" of the
477/// attribute and the enclosing brackets may be omitted as well.
478///
479/// For example, consider a class, `DateTz`, having as attributes a local date
480/// and a time offset:
481/// @code
482/// class DateTz {
483/// // This 'class' represents a date value explicitly in a local time
484/// // zone. The offset of that time (in minutes) from UTC is also part of
485/// // the value of this class.
486///
487/// private:
488/// // DATA
489/// int d_localDate; // date in YYYYMMDD format, local to the timezone
490/// // indicated by 'd_offset'
491///
492/// int d_offset; // offset from UTC (in minutes)
493///
494/// public:
495/// // ...
496/// // ACCESSORS
497/// bsl::ostream& print(bsl::ostream& stream,
498/// int level = 0,
499/// int spacesPerLevel = 4) const;
500/// // ...
501/// };
502/// @endcode
503/// The `Printer` class may be used in this case to print the start and end
504/// indentation by passing a `suppressBracket` flag to the `start` and `end`
505/// methods. The value itself can be written to the stream directly without
506/// using `Printer`. Note that to ensure correct formatting of the value in the
507/// presence of a call to `setw` on the stream, the output must be written to a
508/// `bsl::ostringstream` first; the string containing the output can then be
509/// written to the specified `stream`:
510/// @code
511/// bsl::ostream& DateTz::print(bsl::ostream& stream,
512/// int level,
513/// int spacesPerLevel) const
514/// {
515/// if (stream.bad()) {
516/// return stream; // RETURN
517/// }
518///
519/// bsl::ostringstream tmp;
520/// tmp << d_localDate;
521///
522/// const char sign = d_offset < 0 ? '-' : '+';
523/// const int minutes = '-' == sign ? -d_offset : d_offset;
524/// const int hours = minutes / 60;
525///
526/// // space usage: +- hh mm nil
527/// const int SIZE = 1 + 2 + 2 + 1;
528/// char buf[SIZE];
529///
530/// // Use at most 2 digits for 'hours'
531/// if (hours < 100) {
532/// bsl::sprintf(buf, "%c%02d%02d", sign, hours, minutes % 60);
533/// }
534/// else {
535/// bsl::sprintf(buf, "%cXX%02d", sign, minutes % 60);
536/// }
537///
538/// tmp << buf;
539///
540/// bslim::Printer printer(&stream, level, spacesPerLevel);
541/// printer.start(true);
542/// stream << tmp.str();
543/// printer.end(true);
544///
545/// return stream;
546/// }
547/// @endcode
548/// Sample output for 'DateTz::print(bsl::cout, 0, -4):
549/// @code
550/// 01JAN2011-0500
551/// @endcode
552/// Sample output for 'DateTz::print(bsl::cout, 0, 4):
553/// @code
554/// 01JAN2011-0500<\n>
555/// @endcode
556/// @}
557/** @} */
558/** @} */
559
560/** @addtogroup bsl
561 * @{
562 */
563/** @addtogroup bslim
564 * @{
565 */
566/** @addtogroup bslim_printer
567 * @{
568 */
569
570#include <bslscm_version.h>
571
573
575#include <bslmf_isarray.h>
576#include <bslmf_isfundamental.h>
577#include <bslmf_ispointer.h>
578#include <bslmf_selecttrait.h>
579
580#include <bsls_assert.h>
581#include <bsls_types.h>
582
583#include <bsl_optional.h>
584#include <bsl_ostream.h>
585#include <bsl_memory.h>
586#include <bsl_string.h>
587#include <bsl_utility.h>
588
589
590
591namespace bslim {
592
593 // =============
594 // class Printer
595 // =============
596
597/// This class implements a *mechanism* used to format data as required by
598/// the standard BDE `print` method contract.
599///
600/// See @ref bslim_printer
601class Printer {
602
603 // DATA
604 bsl::ostream *d_stream_p; // output stream (held, not
605 // owned)
606
607 int d_level; // level used in formatting
608
609 int d_levelPlusOne; // 'd_level + 1'; useful in
610 // implementation
611
612 bool d_suppressInitialIndentFlag; // formatting flag
613
614 int d_spacesPerLevel; // spaces per level used in
615 // formatting
616
617 private:
618 // NOT IMPLEMENTED
619 Printer& operator=(const Printer&);
620
621 public:
622 // CREATORS
623
624 /// Create a `Printer` object that will print to the specified `stream`
625 /// in a format dictated by the values of the specified `level` and
626 /// `spacesPerLevel`, as per the contract of the standard BDE `print`
627 /// method. The behavior is undefined unless `stream` is valid.
628 Printer(bsl::ostream *stream, int level, int spacesPerLevel);
629
630 /// Destroy this `Printer` object.
632
633 // ACCESSORS
634
635 /// Return the absolute value of the formatting level supplied at
636 /// construction.
637 int absLevel() const;
638
639 /// If `spacesPerLevel() >= 0`, print a newline character to the output
640 /// stream supplied at construction. If the optionally specified
641 /// `suppressBracket` is false, print a closing square bracket, indented
642 /// by `absLevel() * spacesPerLevel()` blank spaces.
643 void end(bool suppressBracket = false) const;
644
645#ifndef BDE_OPENSOURCE_PUBLICATION // DEPRECATED
646
647 /// [**DEPRECATED** -- use `printAttribute` instead, or `printValue` if
648 /// no name is wanted.]
649 ///
650 /// Format to the output stream supplied at construction the specified
651 /// `data`, prefixed by the specified `name` if `name` is not 0. Format
652 /// `data` based on the parameterized `TYPE`:
653 ///
654 /// * If `TYPE` is a fundamental type, output `data` to the stream.
655 /// * If `TYPE` is `char *` or `const char *`, print `data` to the
656 /// stream as a null-terminated C-style string enclosed in quotes if
657 /// `data` is not 0, and print the string "NULL" otherwise.
658 /// * If `TYPE` is `void *` or `const void *`, print the address value
659 /// of `data` in hexadecimal format if it is not 0, and print the
660 /// string "NULL" otherwise.
661 /// * If `TYPE` is a pointer type (other than the, potentially
662 /// const-qualified, `char *` or `void *`), print the address
663 /// value of `data` in hexadecimal format, then format the object at
664 /// that address if `data` is not 0, and print the string "NULL"
665 /// otherwise. There will be a compile-time error if `data` is a
666 /// pointer to a user-defined type that does not provide a standard
667 /// `print` method.
668 /// * If `TYPE` is any other type, call the standard `print` method on
669 /// `data`, specifying one additional level of indentation than the
670 /// current one. There will be a compile-time error if `TYPE` does
671 /// not provide a standard `print` method.
672 ///
673 /// If `spacesPerLevel() < 0`, format `data` on a single line.
674 /// Otherwise, indent `data` by `(absLevel() + 1) * spacesPerLevel()`
675 /// blank spaces. The behavior is undefined if `TYPE` is a `char *`,
676 /// but not a null-terminated string.
677 template <class TYPE>
678 void print(const TYPE& data, const char *name) const;
679#endif // BDE_OPENSOURCE_PUBLICATION
680
681 /// Format to the output stream supplied at construction the specified
682 /// `data`, prefixed by the specified `name`. Format `data` based on
683 /// the parameterized `TYPE`:
684 ///
685 /// * If `TYPE` is a fundamental type, output `data` to the stream.
686 /// * If `TYPE` is a fixed length array (`Element[NUM]`) and not a char
687 /// array, print out all the elements of the array.
688 /// * If `TYPE` is `void * or `const void *', or function pointer,
689 /// print the address value of `data` in hexadecimal format if it is
690 /// not 0, and print the string "NULL" otherwise.
691 /// * If `TYPE` is `char *`, `const char *`, `char [*]`, or 'const char
692 /// `[*]` or `bsl::string` print `data` to the stream as a
693 /// null-terminated C-style string enclosed in quotes if `data` is
694 /// not 0, and print the string "NULL" otherwise.
695 /// * If `TYPE` is a pointer type (other than the, potentially
696 /// const-qualified, `char *` or `void *`), print the address
697 /// value of `data` in hexadecimal format, then format the object at
698 /// that address if `data` is not 0, and print the string "NULL"
699 /// otherwise. There will be a compile-time error if `data` is a
700 /// pointer to a user-defined type that does not provide a standard
701 /// `print` method.
702 /// * If `TYPE` is a `bsl::pair` object, print out the two elements of
703 /// the pair.
704 /// * If `TYPE` is a `bslstl::StringRef` object, print the referenced
705 /// string enclosed in quotes (possibly including embedded 0s).
706 /// * If `TYPE` has STL iterators (this includes all STL sequence and
707 /// associative containers: vector, deque, list, set, map, multiset,
708 /// multimap, unordered_set, unordered_map, unordered_multiset, and
709 /// unordered_multimap), print all the objects in the container.
710 /// * If `TYPE` is any other type, call the standard `print` method on
711 /// `data`, specifying one additional level of indentation than the
712 /// current one. There will be a compile-time error if `TYPE` does
713 /// not provide a standard `print` method.
714 ///
715 /// If `spacesPerLevel() < 0`, format `data` on a single line.
716 /// Otherwise, indent `data` by `(absLevel() + 1) * spacesPerLevel()`
717 /// blank spaces. The behavior is undefined if `TYPE` is a `char *`,
718 /// but not a null-terminated string.
719 template <class TYPE>
720 void printAttribute(const bslstl::StringRef& name, const TYPE& data) const;
721
722 /// Format to the output stream supplied at construction, the specified
723 /// `name` followed by the range of values starting at the specified
724 /// `begin` position and ending immediately before the specified `end`
725 /// position. The parameterized `ITERATOR` type must support
726 /// `operator++`, `operator*`, and `operator==`. This function will
727 /// call `printValue` on each element in the range `[begin, end)`.
728 template <class ITERATOR>
729 void printAttribute(const bslstl::StringRef& name,
730 const ITERATOR& begin,
731 const ITERATOR& end) const;
732
733 /// Print to the output stream supplied at construction the specified
734 /// `name` and then call the specified `printFunctionObject` with the
735 /// range of values starting at the specified `begin` position and
736 /// ending immediately before the specified `end` position, the stream
737 /// supplied at construction, `absLevel() + 1`, and `spacesPerLevel()`.
738 /// The parameterized `PRINT_FUNCTOR` must be an invocable type whose
739 /// arguments match the following function signature:
740 /// @code
741 /// bsl::ostream& (*)(bsl::ostream& stream,
742 /// const TYPE& data,
743 /// int level,
744 /// int spacesPerLevel)
745 /// @endcode
746 template <class ITERATOR, class PRINT_FUNCTOR>
747 void printAttribute(const bslstl::StringRef& name,
748 const ITERATOR& begin,
749 const ITERATOR& end,
750 const PRINT_FUNCTOR& printFunctionObject) const;
751
752 /// Print to the output stream supplied at construction
753 /// `absLevel() * spacesPerLevel()` blank spaces if
754 /// `spacesPerLevel() >= 0`, and print a single blank space otherwise.
756
757 /// Print to the output stream supplied at construction the specified
758 /// `name`, if name is not 0, and then call the specified
759 /// `printFunctionObject` with the specified `data`, the `stream`
760 /// supplied at construction, `absLevel() + 1`, and `spacesPerLevel()`.
761 /// The parameterized `PRINT_FUNCTOR` must be an invocable type whose
762 /// arguments match the following function signature:
763 /// @code
764 /// bsl::ostream& (*)(bsl::ostream& stream,
765 /// const TYPE& data,
766 /// int level,
767 /// int spacesPerLevel)
768 /// @endcode
769 template <class TYPE, class PRINT_FUNCTOR>
770 void printForeign(const TYPE& data,
771 const PRINT_FUNCTOR& printFunctionObject,
772 const char *name) const;
773
774 /// Write to the output stream supplied at construction the specified
775 /// `address` in a hexadecimal format, if `address` is not 0, and print
776 /// the string "NULL" otherwise, prefixed by the specified `name` if
777 /// `name` is not 0. If `spacesPerLevel() < 0`, print on a single line.
778 /// If `spacesPerLevel() >= 0`, indent by
779 /// `(absLevel() + 1) * spacesPerLevel()` blank spaces.
780 void printHexAddr(const void *address, const char *name) const;
781
782 /// Print to the output stream supplied at construction
783 /// `(absLevel() + 1) * spacesPerLevel()` blank spaces if
784 /// `spacesPerLevel() >= 0`, and print a single blank space otherwise.
785 void printIndentation() const;
786
787 /// Format to the output stream supplied at construction the object at
788 /// the specified `address`, if `address` is not 0, and print the string
789 /// "NULL" otherwise, prefixed by the specified `name` if `name` is not
790 /// 0. If `spacesPerLevel() < 0`, print on a single line. If
791 /// `spacesPerLevel() >= 0`, indent by
792 /// `(absLevel() + 1) * spacesPerLevel()` blank spaces. The behavior is
793 /// undefined unless `TYPE` is a pointer type.
794 template <class TYPE>
795 void printOrNull(const TYPE& address, const char *name) const;
796
797 /// Format to the output stream supplied at construction the specified
798 /// `data`. Format `data` based on the parameterized `TYPE`:
799 ///
800 /// * If `TYPE` is a fundamental type, output `data` to the stream.
801 /// * If `TYPE` is a fixed length array (`Element[NUM]`) and not a char
802 /// array, print out all the elements of the array.
803 /// * If `TYPE` is `void * or `const void *', or function pointer,
804 /// print the address value of `data` in hexadecimal format if it is
805 /// not 0, and print the string "NULL" otherwise.
806 /// * If `TYPE` is `char *`, `const char *`, `char [*]`, or 'const char
807 /// `[*]` or `bsl::string` print `data` to the stream as a
808 /// null-terminated C-style string enclosed in quotes if `data` is
809 /// not 0, and print the string "NULL" otherwise.
810 /// * If `TYPE` is a pointer type (other than the, potentially
811 /// const-qualified, `char *` or `void *`), print the address
812 /// value of `data` in hexadecimal format, then format the object at
813 /// that address if `data` is not 0, and print the string "NULL"
814 /// otherwise. There will be a compile-time error if `data` is a
815 /// pointer to a user-defined type that does not provide a standard
816 /// `print` method.
817 /// * If `TYPE` is a `bsl::pair` object, print out the two elements of
818 /// the pair.
819 /// * If `TYPE` is a `bslstl::StringRef` object, print the referenced
820 /// string enclosed in quotes (possibly including embedded 0s).
821 /// * If `TYPE` has STL iterators (this includes all STL sequence and
822 /// associative containers: vector, deque, list, set, map, multiset,
823 /// multimap, unordered_set, unordered_map, unordered_multiset, and
824 /// unordered_multimap), print all the objects in the container.
825 /// * If `TYPE` is any other type, call the standard `print` method on
826 /// `data`, specifying one additional level of indentation than the
827 /// current one. There will be a compile-time error if `TYPE` does
828 /// not provide a standard `print` method.
829 ///
830 /// If `spacesPerLevel() < 0`, format `data` on a single line.
831 /// Otherwise, indent `data` by `(absLevel() + 1) * spacesPerLevel()`
832 /// blank spaces. The behavior is undefined if `TYPE` is a `char *`,
833 /// but not a null-terminated string.
834 template <class TYPE>
835 void printValue(const TYPE& data) const;
836
837 /// Format to the output stream supplied at construction, the range of
838 /// values starting at the specified `begin` position and ending
839 /// immediately before the specified `end` position. The parameterized
840 /// `ITERATOR` type must support `operator++`, `operator*`, and
841 /// `operator==`. This function will call `printValue` on each element
842 /// in the range `[begin, end)`.
843 template <class ITERATOR>
844 void printValue(const ITERATOR& begin,
845 const ITERATOR& end) const;
846
847 /// Print to the output stream supplied at construction the specified
848 /// `name`, if name is not 0, and then call the specified
849 /// `printFunctionObject` with the range of values starting at the
850 /// specified `begin` position and ending immediately before the
851 /// specified `end` position, the `stream` supplied at construction,
852 /// `absLevel() + 1`, and `spacesPerLevel()`. The parameterized
853 /// `PRINT_FUNCTOR` must be an invocable type whose arguments match the
854 /// following function signature:
855 /// @code
856 /// bsl::ostream& (*)(bsl::ostream& stream,
857 /// const TYPE& data,
858 /// int level,
859 /// int spacesPerLevel)
860 /// @endcode
861 template <class ITERATOR, class PRINT_FUNCTOR>
862 void printValue(const ITERATOR& begin,
863 const ITERATOR& end,
864 const PRINT_FUNCTOR& printFunctionObject) const;
865
866 /// Return the number of whitespace characters to output for each level
867 /// of indentation. The number of whitespace characters for each level
868 /// of indentation is configured using the `spacesPerLevel` supplied at
869 /// construction.
870 int spacesPerLevel() const;
871
872 /// Print to the output stream supplied at construction
873 /// `absLevel() * spacesPerLevel()` blank spaces if the
874 /// `suppressInitialIndentFlag` is `false`, and suppress the initial
875 /// indentation otherwise. If the optionally specified
876 /// `suppressBracket` is `false`, print an opening square bracket.
877 void start(bool suppressBracket = false) const;
878
879 /// Return `true` if the initial output indentation will be suppressed,
880 /// and `false` otherwise. The initial indentation will be suppressed
881 /// if the `level` supplied at construction is negative.
883};
884
885 // =====================
886 // struct Printer_Helper
887 // =====================
888
889/// This struct is an aid to the implementation of the accessors of the
890/// `Printer` mechanism. It provides a method template, `print`, that
891/// adheres to the BDE `print` method contract. It is not to be accessed
892/// directly by clients of `bslim`.
894
895 // CLASS METHODS
896
897 /// Format the specified `data` to the specified output `stream` at the
898 /// (absolute value of) the specified indentation `level`, using the
899 /// specified `spacesPerLevel`, the number of spaces per indentation
900 /// level for this and all of its nested objects. Note that this
901 /// function dispatches to `printRaw` based on the type traits of the
902 /// deduced (template parameter) `TYPE`.
903 template <class TYPE>
904 static void print(bsl::ostream& stream,
905 const TYPE& data,
906 int level,
907 int spacesPerLevel);
908
909 /// Format the range of objects specified by `[ begin, end )` to the
910 /// specified output `stream` at the (absolute value of) the specified
911 /// indentation `level`, using the specified `spacesPerLevel`, the
912 /// number of spaces per indentation level for the objects and their
913 /// nested objects, where `ITERATOR` supports the operators `++` and `*`
914 /// to access the objects. Individual objects are printed with
915 /// `printValue`.
916 template <class ITERATOR>
917 static void print(bsl::ostream& stream,
918 const ITERATOR& begin,
919 const ITERATOR& end,
920 int level,
921 int spacesPerLevel);
922
923 /// Format the range of objects specified by `[ begin, end )` to the
924 /// specified output `stream` at the (absolute value of) the specified
925 /// indentation `level`, using the specified `spacesPerLevel`, the
926 /// number of spaces per indentation level for the objects and their
927 /// nested objects, where `ITERATOR` supports the operators `++` and `*`
928 /// to access the objects, printing the individual objects with the
929 /// specified `printFunctionObject`.
930 template <class ITERATOR, class PRINT_FUNCTOR>
931 static void print(bsl::ostream& stream,
932 const ITERATOR& begin,
933 const ITERATOR& end,
934 const PRINT_FUNCTOR& printFunctionObject,
935 const int level,
936 const int spacesPerLevel);
937
938 // Fundamental types
939
940 static void printRaw(bsl::ostream& stream,
941 char data,
942 int level,
943 int spacesPerLevel,
945 static void printRaw(bsl::ostream& stream,
946 unsigned char data,
947 int level,
948 int spacesPerLevel,
950 static void printRaw(bsl::ostream& stream,
951 bool data,
952 int level,
953 int spacesPerLevel,
955 template <class TYPE>
956 static void printRaw(bsl::ostream& stream,
957 TYPE data,
958 int level,
959 int spacesPerLevel,
961 template <class TYPE>
962 static void printRaw(bsl::ostream& stream,
963 TYPE data,
964 int level,
965 int spacesPerLevel,
967
968 // Function pointer types
969
970 template <class TYPE>
971 static void printRaw(bsl::ostream& stream,
972 const TYPE& data,
973 int level,
974 int spacesPerLevel,
976
977 // Pointer types
978
979 static void printRaw(bsl::ostream& stream,
980 const char *data,
981 int level,
982 int spacesPerLevel,
984 static void printRaw(bsl::ostream& stream,
985 const void *data,
986 int level,
987 int spacesPerLevel,
989 template <class TYPE>
990 static void printRaw(bsl::ostream& stream,
991 const TYPE *data,
992 int level,
993 int spacesPerLevel,
995 template <class TYPE>
996 static void printRaw(bsl::ostream& stream,
997 const TYPE *data,
998 int level,
999 int spacesPerLevel,
1001
1002 // Types with STL iterators
1003
1004 static void printRaw(bsl::ostream& stream,
1005 const bsl::string& data,
1006 int level,
1007 int spacesPerLevel,
1009 template <class TYPE>
1010 static void printRaw(bsl::ostream& stream,
1011 const TYPE& data,
1012 int level,
1013 int spacesPerLevel,
1015
1016 // Default types
1017
1018 template <class T1, class T2>
1019 static void printRaw(bsl::ostream& stream,
1020 const bsl::pair<T1, T2>& data,
1021 int level,
1022 int spacesPerLevel,
1024
1025 static void printRaw(bsl::ostream& stream,
1026 const bslstl::StringRef& data,
1027 int level,
1028 int spacesPerLevel,
1030
1031 static void printRaw(bsl::ostream& stream,
1032 const bsl::string_view& data,
1033 int level,
1034 int spacesPerLevel,
1036
1037 template <class TYPE>
1038 static void printRaw(bsl::ostream& stream,
1039 const bsl::shared_ptr<TYPE>& data,
1040 int level,
1041 int spacesPerLevel,
1043
1044 template <class TYPE>
1045 static void printRaw(bsl::ostream& stream,
1046 const bsl::optional<TYPE>& data,
1047 int level,
1048 int spacesPerLevel,
1050
1051 /// The `print` method of this class dispatches based on `TYPE` and
1052 /// traits to a `printRaw` method to do the actual printing of the
1053 /// specified `data` to the specified `stream` with indentation based on
1054 /// the specified `level` and `spacesPerLevel`.
1055 template <class TYPE>
1056 static void printRaw(bsl::ostream& stream,
1057 const TYPE& data,
1058 int level,
1059 int spacesPerLevel,
1061};
1062
1063// ============================================================================
1064// INLINE DEFINITIONS
1065// ============================================================================
1066
1067
1068 // -------------
1069 // class Printer
1070 // -------------
1071
1072// ACCESSORS
1073#ifndef BDE_OPENSOURCE_PUBLICATION // DEPRECATED
1074template <class TYPE>
1075void Printer::print(const TYPE& data, const char *name) const
1076{
1078
1079 if (name) {
1080 *d_stream_p << name << " = ";
1081 }
1082
1083 Printer_Helper::print(*d_stream_p,
1084 data,
1085 -d_levelPlusOne,
1086 d_spacesPerLevel);
1087}
1088#endif // BDE_OPENSOURCE_PUBLICATION
1089
1090template <class TYPE>
1092 const TYPE& data) const
1093{
1095
1096 *d_stream_p << name << " = ";
1097
1098 Printer_Helper::print(*d_stream_p,
1099 data,
1100 -d_levelPlusOne,
1101 d_spacesPerLevel);
1102}
1103
1104template <class ITERATOR>
1106 const ITERATOR& begin,
1107 const ITERATOR& end) const
1108{
1110
1111 *d_stream_p << name << " = ";
1112
1113 Printer_Helper::print(*d_stream_p,
1114 begin,
1115 end,
1116 -d_levelPlusOne,
1117 d_spacesPerLevel);
1118}
1119
1120template <class ITERATOR, class PRINT_FUNCTOR>
1122 const bslstl::StringRef& name,
1123 const ITERATOR& begin,
1124 const ITERATOR& end,
1125 const PRINT_FUNCTOR& printFunctionObject) const
1126{
1128
1129 *d_stream_p << name << " = ";
1130
1131 Printer_Helper::print(*d_stream_p,
1132 begin,
1133 end,
1134 printFunctionObject,
1135 -d_levelPlusOne,
1136 d_spacesPerLevel);
1137}
1138
1139template <class TYPE, class PRINT_FUNCTOR>
1140void Printer::printForeign(const TYPE& data,
1141 const PRINT_FUNCTOR& printFunctionObject,
1142 const char *name) const
1143{
1145
1146 if (name) {
1147 *d_stream_p << name << " = ";
1148 }
1149
1150 printFunctionObject(*d_stream_p,
1151 data,
1152 -d_levelPlusOne,
1153 d_spacesPerLevel);
1154}
1155
1156template <class TYPE>
1157void Printer::printOrNull(const TYPE& address, const char *name) const
1158{
1160
1161 if (name) {
1162 *d_stream_p << name << " = ";
1163 }
1164
1165 if (0 == address) {
1166 *d_stream_p << "NULL";
1167 if (d_spacesPerLevel >= 0) {
1168 *d_stream_p << '\n';
1169 }
1170 }
1171 else {
1172 Printer_Helper::print(*d_stream_p,
1173 *address,
1174 -d_levelPlusOne,
1175 d_spacesPerLevel);
1176 }
1177}
1178
1179template <>
1180inline
1181void Printer::printOrNull<const void *>(const void *const& address,
1182 const char *name) const
1183{
1185
1186 if (name) {
1187 *d_stream_p << name << " = ";
1188 }
1189 const void *temp = address;
1190
1191 Printer_Helper::print(*d_stream_p,
1192 temp,
1193 -d_levelPlusOne,
1194 d_spacesPerLevel);
1195}
1196
1197template <>
1198inline
1199void Printer::printOrNull<void *>(void *const& address, const char *name) const
1200{
1201 const void *const& temp = address;
1202 printOrNull(temp, name);
1203}
1204
1205template <class TYPE>
1206inline
1207void Printer::printValue(const TYPE& data) const
1208{
1210
1211 Printer_Helper::print(*d_stream_p,
1212 data,
1213 -d_levelPlusOne,
1214 d_spacesPerLevel);
1215}
1216
1217template <class ITERATOR>
1218void Printer::printValue(const ITERATOR& begin,
1219 const ITERATOR& end) const
1220{
1222
1223 Printer_Helper::print(*d_stream_p,
1224 begin,
1225 end,
1226 -d_levelPlusOne,
1227 d_spacesPerLevel);
1228}
1229
1230template <class ITERATOR, class PRINT_FUNCTOR>
1231void Printer::printValue(const ITERATOR& begin,
1232 const ITERATOR& end,
1233 const PRINT_FUNCTOR& printFunctionObject) const
1234{
1235
1237
1238 Printer_Helper::print(*d_stream_p,
1239 begin,
1240 end,
1241 printFunctionObject,
1242 -d_levelPlusOne,
1243 d_spacesPerLevel);
1244}
1245
1246 // ---------------------
1247 // struct Printer_Helper
1248 // ---------------------
1249
1250// CLASS METHODS
1251
1252// 'Printer_Helper::print(stream, data, level, spacesPerLevel)', though defined
1253// first in the struct, is implemented last within this class so it can inline
1254// the calls to 'printRaw' that it makes.
1255
1256template <class ITERATOR>
1257inline
1258void Printer_Helper::print(bsl::ostream& stream,
1259 const ITERATOR& begin,
1260 const ITERATOR& end,
1261 const int level,
1262 const int spacesPerLevel)
1263{
1264 bslim::Printer printer(&stream, level, spacesPerLevel);
1265 printer.start();
1266 for (ITERATOR it = begin; end != it; ++it) {
1267 printer.printValue(*it);
1268 }
1269 printer.end();
1270}
1271
1272template <class ITERATOR, class PRINT_FUNCTOR>
1273inline
1274void Printer_Helper::print(bsl::ostream& stream,
1275 const ITERATOR& begin,
1276 const ITERATOR& end,
1277 const PRINT_FUNCTOR& printFunctionObject,
1278 const int level,
1279 const int spacesPerLevel)
1280{
1281 bslim::Printer printer(&stream, level, spacesPerLevel);
1282 printer.start();
1283 for (ITERATOR it = begin; end != it; ++it) {
1284 printFunctionObject(stream,
1285 *it,
1286 printer.absLevel() + 1,
1287 spacesPerLevel);
1288 if (spacesPerLevel >= 0) {
1289 stream << '\n';
1290 }
1291 }
1292 printer.end();
1293}
1294
1295 // Fundamental types
1296
1297template <class TYPE>
1298inline
1299void Printer_Helper::printRaw(bsl::ostream& stream,
1300 TYPE data,
1301 int ,
1302 int spacesPerLevel,
1304{
1305 stream << data;
1306 if (spacesPerLevel >= 0) {
1307 stream << '\n';
1308 }
1309}
1310
1311template <class TYPE>
1312inline
1313void Printer_Helper::printRaw(bsl::ostream& stream,
1314 TYPE data,
1315 int ,
1316 int spacesPerLevel,
1318{
1320 data,
1321 0,
1322 spacesPerLevel,
1324}
1325
1326 // Function pointer types
1327
1328template <class TYPE>
1329inline
1331 bsl::ostream& stream,
1332 const TYPE& data,
1333 int level,
1334 int spacesPerLevel,
1336{
1337 // GCC 3.4.6 does not allow a reinterpret-cast a function pointer directly
1338 // to 'void *', so first cast it to an integer data type.
1339
1340 Printer_Helper::print(stream,
1341 reinterpret_cast<const void *>(
1342 reinterpret_cast<bsls::Types::UintPtr>(data)),
1343 level,
1344 spacesPerLevel);
1345}
1346
1347 // Pointer types
1348
1349template <class TYPE>
1350inline
1351void Printer_Helper::printRaw(bsl::ostream& stream,
1352 const TYPE *data,
1353 int level,
1354 int spacesPerLevel,
1356{
1358 static_cast<const void *>(data),
1359 level,
1360 -1,
1362 if (0 == data) {
1363 if (spacesPerLevel >= 0) {
1364 stream << '\n';
1365 }
1366 }
1367 else {
1368 stream << ' ';
1369 Printer_Helper::print(stream, *data, level, spacesPerLevel);
1370 }
1371}
1372
1373template <class TYPE>
1374inline
1375void Printer_Helper::printRaw(bsl::ostream& stream,
1376 const TYPE *data,
1377 int level,
1378 int spacesPerLevel,
1380{
1382 data,
1383 level,
1384 spacesPerLevel,
1386}
1387
1388
1389 // Types with STL iterators
1390
1391inline
1393 bsl::ostream& stream,
1394 const bsl::string& data,
1395 int level,
1396 int spacesPerLevel,
1398{
1400 data.c_str(),
1401 level,
1402 spacesPerLevel,
1404}
1405
1406template <class TYPE>
1407inline
1409 bsl::ostream& stream,
1410 const TYPE& data,
1411 int level,
1412 int spacesPerLevel,
1414{
1415 Printer_Helper::print(stream,
1416 data.begin(),
1417 data.end(),
1418 level,
1419 spacesPerLevel);
1420}
1421
1422 // Default types
1423
1424template <class T1, class T2>
1425inline
1426void Printer_Helper::printRaw(bsl::ostream& stream,
1427 const bsl::pair<T1, T2>& data,
1428 int level,
1429 int spacesPerLevel,
1431{
1432 bslim::Printer printer(&stream, level, spacesPerLevel);
1433 printer.start();
1434 printer.printValue(data.first);
1435 printer.printValue(data.second);
1436 printer.end();
1437}
1438
1439template <class TYPE>
1440inline
1441void Printer_Helper::printRaw(bsl::ostream& stream,
1442 const bsl::shared_ptr<TYPE>& data,
1443 int level,
1444 int spacesPerLevel,
1446{
1448 static_cast<const void *>(data.get()),
1449 level,
1450 -1,
1452 if (data) {
1453 stream << ' ';
1454 Printer_Helper::print(stream, *data, level, spacesPerLevel);
1455 }
1456 else if (spacesPerLevel >= 0) {
1457 stream << '\n';
1458 }
1459}
1460
1461template <class TYPE>
1462inline
1463void Printer_Helper::printRaw(bsl::ostream& stream,
1464 const bsl::optional<TYPE>& data,
1465 int level,
1466 int spacesPerLevel,
1468{
1469 if (data.has_value()) {
1470 Printer_Helper::print(stream, *data, level, spacesPerLevel);
1471 }
1472 else {
1473 if (spacesPerLevel >= 0) {
1474 stream << "NULL\n";
1475 }
1476 else {
1477 stream << "NULL";
1478 }
1479 }
1480}
1481
1482template <class TYPE>
1483inline
1484void Printer_Helper::printRaw(bsl::ostream& stream,
1485 const TYPE& data,
1486 int level,
1487 int spacesPerLevel,
1489{
1490 data.print(stream, level, spacesPerLevel);
1491}
1492
1493// This method, though declared first in the struct, is placed last among the
1494// methods in 'Printer_Helper' so that it can inline the 'printRaw' methods it
1495// calls.
1496
1497template <class TYPE>
1498inline
1499void Printer_Helper::print(bsl::ostream& stream,
1500 const TYPE& data,
1501 int level,
1502 int spacesPerLevel)
1503{
1504 typedef bslmf::SelectTrait<TYPE,
1510 bslalg::HasStlIterators> Selection;
1511
1512 Printer_Helper::printRaw(stream, data, level, spacesPerLevel, Selection());
1513}
1514
1515} // close package namespace
1516
1517
1518#endif
1519
1520// ----------------------------------------------------------------------------
1521// Copyright 2014 Bloomberg Finance L.P.
1522//
1523// Licensed under the Apache License, Version 2.0 (the "License");
1524// you may not use this file except in compliance with the License.
1525// You may obtain a copy of the License at
1526//
1527// http://www.apache.org/licenses/LICENSE-2.0
1528//
1529// Unless required by applicable law or agreed to in writing, software
1530// distributed under the License is distributed on an "AS IS" BASIS,
1531// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1532// See the License for the specific language governing permissions and
1533// limitations under the License.
1534// ----------------------------- END-OF-FILE ----------------------------------
1535
1536/** @} */
1537/** @} */
1538/** @} */
Definition bslstl_stringview.h:441
Definition bslstl_string.h:1281
Definition bslstl_optional.h:1861
Definition bslstl_pair.h:1210
Definition bslstl_sharedptr.h:1830
Definition bslim_printer.h:601
int spacesPerLevel() const
void printOrNull(const TYPE &address, const char *name) const
Definition bslim_printer.h:1157
void printValue(const TYPE &data) const
Definition bslim_printer.h:1207
void printForeign(const TYPE &data, const PRINT_FUNCTOR &printFunctionObject, const char *name) const
Definition bslim_printer.h:1140
void printHexAddr(const void *address, const char *name) const
int absLevel() const
void end(bool suppressBracket=false) const
~Printer()
Destroy this Printer object.
void start(bool suppressBracket=false) const
void print(const TYPE &data, const char *name) const
Definition bslim_printer.h:1075
void printEndIndentation() const
Printer(bsl::ostream *stream, int level, int spacesPerLevel)
void printAttribute(const bslstl::StringRef &name, const TYPE &data) const
Definition bslim_printer.h:1091
bool suppressInitialIndentFlag() const
void printIndentation() const
Definition bslstl_stringref.h:372
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
Definition bslim_formatguard.h:120
Definition bslmf_isarray.h:168
Definition bslmf_isenum.h:270
Definition bslmf_isfundamental.h:329
Definition bslmf_ispointer.h:138
Definition bslalg_hasstliterators.h:99
Definition bslim_printer.h:893
static void printRaw(bsl::ostream &stream, const bslstl::StringRef &data, int level, int spacesPerLevel, bslmf::SelectTraitCase<>)
static void printRaw(bsl::ostream &stream, const bsl::string_view &data, int level, int spacesPerLevel, bslmf::SelectTraitCase<>)
static void printRaw(bsl::ostream &stream, const void *data, int level, int spacesPerLevel, bslmf::SelectTraitCase< bsl::is_pointer >)
static void printRaw(bsl::ostream &stream, const char *data, int level, int spacesPerLevel, bslmf::SelectTraitCase< bsl::is_pointer >)
static void printRaw(bsl::ostream &stream, char data, int level, int spacesPerLevel, bslmf::SelectTraitCase< bsl::is_fundamental >)
static void printRaw(bsl::ostream &stream, unsigned char data, int level, int spacesPerLevel, bslmf::SelectTraitCase< bsl::is_fundamental >)
static void print(bsl::ostream &stream, const TYPE &data, int level, int spacesPerLevel)
Definition bslim_printer.h:1499
static void printRaw(bsl::ostream &stream, bool data, int level, int spacesPerLevel, bslmf::SelectTraitCase< bsl::is_fundamental >)
Definition bslmf_functionpointertraits.h:153
Definition bslmf_selecttrait.h:438
Definition bslmf_selecttrait.h:522
std::size_t UintPtr
Definition bsls_types.h:126