BDE 4.39.x 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/// snprintf(buf, sizeof buf, "%c%02d%02d", sign, hours, minutes % 60);
533/// }
534/// else {
535/// snprintf(buf, sizeof 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#ifdef BSLS_LIBRARYFEATURES_HAS_CPP11_TUPLE
588#include <bsl_tuple.h>
589#endif // BSLS_LIBRARYFEATURES_HAS_CPP11_TUPLE
590#include <bsl_utility.h>
591
592
593
594namespace bslim {
595
596 // =============
597 // class Printer
598 // =============
599
600/// This class implements a *mechanism* used to format data as required by
601/// the standard BDE `print` method contract.
602///
603/// See @ref bslim_printer
604class Printer {
605
606 // DATA
607 bsl::ostream *d_stream_p; // output stream (held, not
608 // owned)
609
610 int d_level; // level used in formatting
611
612 int d_levelPlusOne; // 'd_level + 1'; useful in
613 // implementation
614
615 bool d_suppressInitialIndentFlag; // formatting flag
616
617 int d_spacesPerLevel; // spaces per level used in
618 // formatting
619
620 private:
621 // NOT IMPLEMENTED
622 Printer& operator=(const Printer&);
623
624 public:
625 // CREATORS
626
627 /// Create a `Printer` object that will print to the specified `stream`
628 /// in a format dictated by the values of the specified `level` and
629 /// `spacesPerLevel`, as per the contract of the standard BDE `print` method.
630 ///
631 /// \pre The behavior is undefined unless `stream` is valid.
632 Printer(bsl::ostream *stream, int level, int spacesPerLevel);
633
634 /// Destroy this `Printer` object.
636
637 // ACCESSORS
638
639 /// Return the absolute value of the formatting level supplied at
640 /// construction.
641 int absLevel() const;
642
643 /// If `spacesPerLevel() >= 0`, print a newline character to the output
644 /// stream supplied at construction. If the optionally specified
645 /// `suppressBracket` is false, print a closing square bracket, indented
646 /// by `absLevel() * spacesPerLevel()` blank spaces.
647 void end(bool suppressBracket = false) const;
648
649#ifndef BDE_OPENSOURCE_PUBLICATION // DEPRECATED
650
651 /// Format to the output stream supplied at construction the specified
652 /// `data`, prefixed by the specified `name` if `name` is not 0. Format
653 /// `data` based on the parameterized `TYPE`:
654 ///
655 /// * If `TYPE` is a fundamental type, output `data` to the stream.
656 /// * If `TYPE` is `char *` or `const char *`, print `data` to the
657 /// stream as a null-terminated C-style string enclosed in quotes if
658 /// `data` is not 0, and print the string "NULL" otherwise.
659 /// * If `TYPE` is `void *` or `const void *`, print the address value
660 /// of `data` in hexadecimal format if it is not 0, and print the
661 /// string "NULL" otherwise.
662 /// * If `TYPE` is a pointer type (other than the, potentially
663 /// const-qualified, `char *` or `void *`), print the address
664 /// value of `data` in hexadecimal format, then format the object at
665 /// that address if `data` is not 0, and print the string "NULL"
666 /// otherwise. There will be a compile-time error if `data` is a
667 /// pointer to a user-defined type that does not provide a standard
668 /// `print` method.
669 /// * If `TYPE` is any other type, call the standard `print` method on
670 /// `data`, specifying one additional level of indentation than the
671 /// current one. There will be a compile-time error if `TYPE` does
672 /// not provide a standard `print` method.
673 ///
674 /// If `spacesPerLevel() < 0`, format `data` on a single line. Otherwise,
675 /// indent `data` by `(absLevel() + 1) * spacesPerLevel()` blank spaces.
676 ///
677 /// \pre The behavior is undefined if `TYPE` is a `char *`, but not a
678 /// null-terminated string.
679 ///
680 /// @deprecated Use @ref printAttribute` instead, or `printValue if no name
681 /// is wanted.
682 template <class TYPE>
683 void print(const TYPE& data, const char *name) const;
684#endif // BDE_OPENSOURCE_PUBLICATION
685
686 /// Format to the output stream supplied at construction the specified
687 /// `data`, prefixed by the specified `name`. Format `data` based on
688 /// the parameterized `TYPE`:
689 ///
690 /// * If `TYPE` is a fundamental type, output `data` to the stream.
691 /// * If `TYPE` is a fixed length array (`Element[NUM]`) and not a char
692 /// array, print out all the elements of the array.
693 /// * If `TYPE` is `void * or `const void *', or function pointer,
694 /// print the address value of `data` in hexadecimal format if it is
695 /// not 0, and print the string "NULL" otherwise.
696 /// * If `TYPE` is `char *`, `const char *`, `char [*]`, or 'const char
697 /// `[*]` or `bsl::string` print `data` to the stream as a
698 /// null-terminated C-style string enclosed in quotes if `data` is
699 /// not 0, and print the string "NULL" otherwise.
700 /// * If `TYPE` is a pointer type (other than the, potentially
701 /// const-qualified, `char *` or `void *`), print the address
702 /// value of `data` in hexadecimal format, then format the object at
703 /// that address if `data` is not 0, and print the string "NULL"
704 /// otherwise. There will be a compile-time error if `data` is a
705 /// pointer to a user-defined type that does not provide a standard
706 /// `print` method.
707 /// * If `TYPE` is a `bsl::pair` object, print out the two elements of
708 /// the pair.
709 /// * If `TYPE` is a `bslstl::StringRef` object, print the referenced
710 /// string enclosed in quotes (possibly including embedded 0s).
711 /// * If `TYPE` has STL iterators (this includes all STL sequence and
712 /// associative containers: vector, deque, list, set, map, multiset,
713 /// multimap, unordered_set, unordered_map, unordered_multiset, and
714 /// unordered_multimap), print all the objects in the container.
715 /// * If `TYPE` is any other type, call the standard `print` method on
716 /// `data`, specifying one additional level of indentation than the
717 /// current one. There will be a compile-time error if `TYPE` does
718 /// not provide a standard `print` method.
719 ///
720 /// If `spacesPerLevel() < 0`, format `data` on a single line.
721 /// Otherwise, indent `data` by `(absLevel() + 1) * spacesPerLevel()` blank spaces.
722 ///
723 /// \pre The behavior is undefined if `TYPE` is a `char *`,
724 /// but not a null-terminated string.
725 template <class TYPE>
726 void printAttribute(const bslstl::StringRef& name, const TYPE& data) const;
727
728 /// Format to the output stream supplied at construction, the specified
729 /// `name` followed by the range of values starting at the specified
730 /// `begin` position and ending immediately before the specified `end`
731 /// position. The parameterized `ITERATOR` type must support
732 /// `operator++`, `operator*`, and `operator==`. This function will
733 /// call `printValue` on each element in the range `[begin, end)`.
734 template <class ITERATOR>
735 void printAttribute(const bslstl::StringRef& name,
736 const ITERATOR& begin,
737 const ITERATOR& end) const;
738
739 /// Print to the output stream supplied at construction the specified
740 /// `name` and then call the specified `printFunctionObject` with the
741 /// range of values starting at the specified `begin` position and
742 /// ending immediately before the specified `end` position, the stream
743 /// supplied at construction, `absLevel() + 1`, and `spacesPerLevel()`.
744 /// The parameterized `PRINT_FUNCTOR` must be an invocable type whose
745 /// arguments match the following function signature:
746 /// @code
747 /// bsl::ostream& (*)(bsl::ostream& stream,
748 /// const TYPE& data,
749 /// int level,
750 /// int spacesPerLevel)
751 /// @endcode
752 template <class ITERATOR, class PRINT_FUNCTOR>
753 void printAttribute(const bslstl::StringRef& name,
754 const ITERATOR& begin,
755 const ITERATOR& end,
756 const PRINT_FUNCTOR& printFunctionObject) const;
757
758 /// Print to the output stream supplied at construction
759 /// `absLevel() * spacesPerLevel()` blank spaces if
760 /// `spacesPerLevel() >= 0`, and print a single blank space otherwise.
762
763 /// Print to the output stream supplied at construction the specified
764 /// `name`, if name is not 0, and then call the specified
765 /// `printFunctionObject` with the specified `data`, the `stream`
766 /// supplied at construction, `absLevel() + 1`, and `spacesPerLevel()`.
767 /// The parameterized `PRINT_FUNCTOR` must be an invocable type whose
768 /// arguments match the following function signature:
769 /// @code
770 /// bsl::ostream& (*)(bsl::ostream& stream,
771 /// const TYPE& data,
772 /// int level,
773 /// int spacesPerLevel)
774 /// @endcode
775 template <class TYPE, class PRINT_FUNCTOR>
776 void printForeign(const TYPE& data,
777 const PRINT_FUNCTOR& printFunctionObject,
778 const char *name) const;
779
780 /// Write to the output stream supplied at construction the specified
781 /// `address` in a hexadecimal format, if `address` is not 0, and print
782 /// the string "NULL" otherwise, prefixed by the specified `name` if
783 /// `name` is not 0. If `spacesPerLevel() < 0`, print on a single line.
784 /// If `spacesPerLevel() >= 0`, indent by
785 /// `(absLevel() + 1) * spacesPerLevel()` blank spaces.
786 void printHexAddr(const void *address, const char *name) const;
787
788 /// Print to the output stream supplied at construction
789 /// `(absLevel() + 1) * spacesPerLevel()` blank spaces if
790 /// `spacesPerLevel() >= 0`, and print a single blank space otherwise.
791 void printIndentation() const;
792
793 /// Format to the output stream supplied at construction the object at
794 /// the specified `address`, if `address` is not 0, and print the string
795 /// "NULL" otherwise, prefixed by the specified `name` if `name` is not
796 /// 0. If `spacesPerLevel() < 0`, print on a single line. If
797 /// `spacesPerLevel() >= 0`, indent by
798 /// `(absLevel() + 1) * spacesPerLevel()` blank spaces.
799 ///
800 /// \pre The behavior is undefined unless `TYPE` is a pointer type.
801 template <class TYPE>
802 void printOrNull(const TYPE& address, const char *name) const;
803
804 /// Format to the output stream supplied at construction the specified
805 /// `data`. Format `data` based on the parameterized `TYPE`:
806 ///
807 /// * If `TYPE` is a fundamental type, output `data` to the stream.
808 /// * If `TYPE` is a fixed length array (`Element[NUM]`) and not a char
809 /// array, print out all the elements of the array.
810 /// * If `TYPE` is `void * or `const void *', or function pointer,
811 /// print the address value of `data` in hexadecimal format if it is
812 /// not 0, and print the string "NULL" otherwise.
813 /// * If `TYPE` is `char *`, `const char *`, `char [*]`, or 'const char
814 /// `[*]` or `bsl::string` print `data` to the stream as a
815 /// null-terminated C-style string enclosed in quotes if `data` is
816 /// not 0, and print the string "NULL" otherwise.
817 /// * If `TYPE` is a pointer type (other than the, potentially
818 /// const-qualified, `char *` or `void *`), print the address
819 /// value of `data` in hexadecimal format, then format the object at
820 /// that address if `data` is not 0, and print the string "NULL"
821 /// otherwise. There will be a compile-time error if `data` is a
822 /// pointer to a user-defined type that does not provide a standard
823 /// `print` method.
824 /// * If `TYPE` is a `bsl::pair` object, print out the two elements of
825 /// the pair.
826 /// * If `TYPE` is a `bslstl::StringRef` object, print the referenced
827 /// string enclosed in quotes (possibly including embedded 0s).
828 /// * If `TYPE` has STL iterators (this includes all STL sequence and
829 /// associative containers: vector, deque, list, set, map, multiset,
830 /// multimap, unordered_set, unordered_map, unordered_multiset, and
831 /// unordered_multimap), print all the objects in the container.
832 /// * If `TYPE` is any other type, call the standard `print` method on
833 /// `data`, specifying one additional level of indentation than the
834 /// current one. There will be a compile-time error if `TYPE` does
835 /// not provide a standard `print` method.
836 ///
837 /// If `spacesPerLevel() < 0`, format `data` on a single line.
838 /// Otherwise, indent `data` by `(absLevel() + 1) * spacesPerLevel()` blank spaces.
839 ///
840 /// \pre The behavior is undefined if `TYPE` is a `char *`,
841 /// but not a null-terminated string.
842 template <class TYPE>
843 void printValue(const TYPE& data) const;
844
845 /// Format to the output stream supplied at construction, the range of
846 /// values starting at the specified `begin` position and ending
847 /// immediately before the specified `end` position. The parameterized
848 /// `ITERATOR` type must support `operator++`, `operator*`, and
849 /// `operator==`. This function will call `printValue` on each element
850 /// in the range `[begin, end)`.
851 template <class ITERATOR>
852 void printValue(const ITERATOR& begin,
853 const ITERATOR& end) const;
854
855 /// Print to the output stream supplied at construction the specified
856 /// `name`, if name is not 0, and then call the specified
857 /// `printFunctionObject` with the range of values starting at the
858 /// specified `begin` position and ending immediately before the
859 /// specified `end` position, the `stream` supplied at construction,
860 /// `absLevel() + 1`, and `spacesPerLevel()`. The parameterized
861 /// `PRINT_FUNCTOR` must be an invocable type whose arguments match the
862 /// following function signature:
863 /// @code
864 /// bsl::ostream& (*)(bsl::ostream& stream,
865 /// const TYPE& data,
866 /// int level,
867 /// int spacesPerLevel)
868 /// @endcode
869 template <class ITERATOR, class PRINT_FUNCTOR>
870 void printValue(const ITERATOR& begin,
871 const ITERATOR& end,
872 const PRINT_FUNCTOR& printFunctionObject) const;
873
874 /// Return the number of whitespace characters to output for each level
875 /// of indentation. The number of whitespace characters for each level
876 /// of indentation is configured using the `spacesPerLevel` supplied at
877 /// construction.
878 int spacesPerLevel() const;
879
880 /// Print to the output stream supplied at construction
881 /// `absLevel() * spacesPerLevel()` blank spaces if the
882 /// `suppressInitialIndentFlag` is `false`, and suppress the initial
883 /// indentation otherwise. If the optionally specified
884 /// `suppressBracket` is `false`, print an opening square bracket.
885 void start(bool suppressBracket = false) const;
886
887 /// Return `true` if the initial output indentation will be suppressed,
888 /// and `false` otherwise. The initial indentation will be suppressed
889 /// if the `level` supplied at construction is negative.
891};
892
893 // =====================
894 // struct Printer_Helper
895 // =====================
896
897/// This struct is an aid to the implementation of the accessors of the
898/// `Printer` mechanism. It provides a method template, `print`, that
899/// adheres to the BDE `print` method contract. It is not to be accessed
900/// directly by clients of `bslim`.
901///
902/// See @ref bslim_printer
904
905 // CLASS METHODS
906
907 /// Format the specified `data` to the specified output `stream` at the
908 /// (absolute value of) the specified indentation `level`, using the
909 /// specified `spacesPerLevel`, the number of spaces per indentation level for this and all of its nested objects.
910 ///
911 /// \note Note that this
912 /// function dispatches to `printRaw` based on the type traits of the
913 /// deduced (template parameter) `TYPE`.
914 template <class TYPE>
915 static void print(bsl::ostream& stream,
916 const TYPE& data,
917 int level,
918 int spacesPerLevel);
919
920 /// Format the range of objects specified by `[ begin, end )` to the
921 /// specified output `stream` at the (absolute value of) the specified
922 /// indentation `level`, using the specified `spacesPerLevel`, the
923 /// number of spaces per indentation level for the objects and their
924 /// nested objects, where `ITERATOR` supports the operators `++` and `*`
925 /// to access the objects. Individual objects are printed with
926 /// `printValue`.
927 template <class ITERATOR>
928 static void print(bsl::ostream& stream,
929 const ITERATOR& begin,
930 const ITERATOR& end,
931 int level,
932 int spacesPerLevel);
933
934 /// Format the range of objects specified by `[ begin, end )` to the
935 /// specified output `stream` at the (absolute value of) the specified
936 /// indentation `level`, using the specified `spacesPerLevel`, the
937 /// number of spaces per indentation level for the objects and their
938 /// nested objects, where `ITERATOR` supports the operators `++` and `*`
939 /// to access the objects, printing the individual objects with the
940 /// specified `printFunctionObject`.
941 template <class ITERATOR, class PRINT_FUNCTOR>
942 static void print(bsl::ostream& stream,
943 const ITERATOR& begin,
944 const ITERATOR& end,
945 const PRINT_FUNCTOR& printFunctionObject,
946 const int level,
947 const int spacesPerLevel);
948
949 // Fundamental types
950
951 static void printRaw(bsl::ostream& stream,
952 char data,
953 int level,
954 int spacesPerLevel,
956 static void printRaw(bsl::ostream& stream,
957 unsigned char data,
958 int level,
959 int spacesPerLevel,
961 static void printRaw(bsl::ostream& stream,
962 bool data,
963 int level,
964 int spacesPerLevel,
966 template <class TYPE>
967 static void printRaw(bsl::ostream& stream,
968 TYPE data,
969 int level,
970 int spacesPerLevel,
972 template <class TYPE>
973 static void printRaw(bsl::ostream& stream,
974 TYPE data,
975 int level,
976 int spacesPerLevel,
978
979 // Function pointer types
980
981 template <class TYPE>
982 static void printRaw(bsl::ostream& stream,
983 const TYPE& data,
984 int level,
985 int spacesPerLevel,
987
988 // Pointer types
989
990 static void printRaw(bsl::ostream& stream,
991 const char *data,
992 int level,
993 int spacesPerLevel,
995 static void printRaw(bsl::ostream& stream,
996 const void *data,
997 int level,
998 int spacesPerLevel,
1000 template <class TYPE>
1001 static void printRaw(bsl::ostream& stream,
1002 const TYPE *data,
1003 int level,
1004 int spacesPerLevel,
1006 template <class TYPE>
1007 static void printRaw(bsl::ostream& stream,
1008 const TYPE *data,
1009 int level,
1010 int spacesPerLevel,
1012
1013 // Types with STL iterators
1014
1015 static void printRaw(bsl::ostream& stream,
1016 const bsl::string& data,
1017 int level,
1018 int spacesPerLevel,
1020 template <class TYPE>
1021 static void printRaw(bsl::ostream& stream,
1022 const TYPE& data,
1023 int level,
1024 int spacesPerLevel,
1026
1027 // Default types
1028
1029 template <class T1, class T2>
1030 static void printRaw(bsl::ostream& stream,
1031 const bsl::pair<T1, T2>& data,
1032 int level,
1033 int spacesPerLevel,
1035
1036#ifdef BSLS_LIBRARYFEATURES_HAS_CPP11_TUPLE
1037 /// No op.
1038 template <class t_TUPLE>
1039 static void printTupleElements(Printer&,
1040 const t_TUPLE&,
1042
1043 /// Print the first `t_SIZE` elements of the specified tuple, `data`, using the
1044 /// specified `printer`.
1045 template <int t_SIZE, class t_TUPLE>
1046 static void printTupleElements(Printer& printer,
1047 const t_TUPLE& data,
1049
1050 template <class... t_TYPES>
1051 static void printRaw(bsl::ostream& stream,
1052 const bsl::tuple<t_TYPES...>& data,
1053 int level,
1054 int spacesPerLevel,
1056#endif // BSLS_LIBRARYFEATURES_HAS_CPP11_TUPLE
1057
1058 static void printRaw(bsl::ostream& stream,
1059 const bslstl::StringRef& data,
1060 int level,
1061 int spacesPerLevel,
1063
1064 static void printRaw(bsl::ostream& stream,
1065 const bsl::string_view& data,
1066 int level,
1067 int spacesPerLevel,
1069
1070 template <class TYPE>
1071 static void printRaw(bsl::ostream& stream,
1072 const bsl::shared_ptr<TYPE>& data,
1073 int level,
1074 int spacesPerLevel,
1076
1077 template <class TYPE>
1078 static void printRaw(bsl::ostream& stream,
1079 const bsl::optional<TYPE>& data,
1080 int level,
1081 int spacesPerLevel,
1083
1084 /// The `print` method of this class dispatches based on `TYPE` and
1085 /// traits to a `printRaw` method to do the actual printing of the
1086 /// specified `data` to the specified `stream` with indentation based on
1087 /// the specified `level` and `spacesPerLevel`.
1088 template <class TYPE>
1089 static void printRaw(bsl::ostream& stream,
1090 const TYPE& data,
1091 int level,
1092 int spacesPerLevel,
1094};
1095
1096// ============================================================================
1097// INLINE DEFINITIONS
1098// ============================================================================
1099
1100
1101 // -------------
1102 // class Printer
1103 // -------------
1104
1105// ACCESSORS
1106#ifndef BDE_OPENSOURCE_PUBLICATION // DEPRECATED
1107template <class TYPE>
1108void Printer::print(const TYPE& data, const char *name) const
1109{
1111
1112 if (name) {
1113 *d_stream_p << name << " = ";
1114 }
1115
1116 Printer_Helper::print(*d_stream_p,
1117 data,
1118 -d_levelPlusOne,
1119 d_spacesPerLevel);
1120}
1121#endif // BDE_OPENSOURCE_PUBLICATION
1122
1123template <class TYPE>
1125 const TYPE& data) const
1126{
1128
1129 *d_stream_p << name << " = ";
1130
1131 Printer_Helper::print(*d_stream_p,
1132 data,
1133 -d_levelPlusOne,
1134 d_spacesPerLevel);
1135}
1136
1137template <class ITERATOR>
1139 const ITERATOR& begin,
1140 const ITERATOR& end) const
1141{
1143
1144 *d_stream_p << name << " = ";
1145
1146 Printer_Helper::print(*d_stream_p,
1147 begin,
1148 end,
1149 -d_levelPlusOne,
1150 d_spacesPerLevel);
1151}
1152
1153template <class ITERATOR, class PRINT_FUNCTOR>
1155 const bslstl::StringRef& name,
1156 const ITERATOR& begin,
1157 const ITERATOR& end,
1158 const PRINT_FUNCTOR& printFunctionObject) const
1159{
1161
1162 *d_stream_p << name << " = ";
1163
1164 Printer_Helper::print(*d_stream_p,
1165 begin,
1166 end,
1167 printFunctionObject,
1168 -d_levelPlusOne,
1169 d_spacesPerLevel);
1170}
1171
1172template <class TYPE, class PRINT_FUNCTOR>
1173void Printer::printForeign(const TYPE& data,
1174 const PRINT_FUNCTOR& printFunctionObject,
1175 const char *name) const
1176{
1178
1179 if (name) {
1180 *d_stream_p << name << " = ";
1181 }
1182
1183 printFunctionObject(*d_stream_p,
1184 data,
1185 -d_levelPlusOne,
1186 d_spacesPerLevel);
1187}
1188
1189template <class TYPE>
1190void Printer::printOrNull(const TYPE& address, const char *name) const
1191{
1193
1194 if (name) {
1195 *d_stream_p << name << " = ";
1196 }
1197
1198 if (0 == address) {
1199 *d_stream_p << "NULL";
1200 if (d_spacesPerLevel >= 0) {
1201 *d_stream_p << '\n';
1202 }
1203 }
1204 else {
1205 Printer_Helper::print(*d_stream_p,
1206 *address,
1207 -d_levelPlusOne,
1208 d_spacesPerLevel);
1209 }
1210}
1211
1212template <>
1213inline
1214void Printer::printOrNull<const void *>(const void *const& address,
1215 const char *name) const
1216{
1218
1219 if (name) {
1220 *d_stream_p << name << " = ";
1221 }
1222 const void *temp = address;
1223
1224 Printer_Helper::print(*d_stream_p,
1225 temp,
1226 -d_levelPlusOne,
1227 d_spacesPerLevel);
1228}
1229
1230template <>
1231inline
1232void Printer::printOrNull<void *>(void *const& address, const char *name) const
1233{
1234 const void *const& temp = address;
1235 printOrNull(temp, name);
1236}
1237
1238template <class TYPE>
1239inline
1240void Printer::printValue(const TYPE& data) const
1241{
1243
1244 Printer_Helper::print(*d_stream_p,
1245 data,
1246 -d_levelPlusOne,
1247 d_spacesPerLevel);
1248}
1249
1250template <class ITERATOR>
1251void Printer::printValue(const ITERATOR& begin,
1252 const ITERATOR& end) const
1253{
1255
1256 Printer_Helper::print(*d_stream_p,
1257 begin,
1258 end,
1259 -d_levelPlusOne,
1260 d_spacesPerLevel);
1261}
1262
1263template <class ITERATOR, class PRINT_FUNCTOR>
1264void Printer::printValue(const ITERATOR& begin,
1265 const ITERATOR& end,
1266 const PRINT_FUNCTOR& printFunctionObject) const
1267{
1268
1270
1271 Printer_Helper::print(*d_stream_p,
1272 begin,
1273 end,
1274 printFunctionObject,
1275 -d_levelPlusOne,
1276 d_spacesPerLevel);
1277}
1278
1279 // ---------------------
1280 // struct Printer_Helper
1281 // ---------------------
1282
1283// CLASS METHODS
1284
1285// 'Printer_Helper::print(stream, data, level, spacesPerLevel)', though defined
1286// first in the struct, is implemented last within this class so it can inline
1287// the calls to 'printRaw' that it makes.
1288
1289template <class ITERATOR>
1290inline
1291void Printer_Helper::print(bsl::ostream& stream,
1292 const ITERATOR& begin,
1293 const ITERATOR& end,
1294 const int level,
1295 const int spacesPerLevel)
1296{
1297 bslim::Printer printer(&stream, level, spacesPerLevel);
1298 printer.start();
1299 for (ITERATOR it = begin; end != it; ++it) {
1300 printer.printValue(*it);
1301 }
1302 printer.end();
1303}
1304
1305template <class ITERATOR, class PRINT_FUNCTOR>
1306inline
1307void Printer_Helper::print(bsl::ostream& stream,
1308 const ITERATOR& begin,
1309 const ITERATOR& end,
1310 const PRINT_FUNCTOR& printFunctionObject,
1311 const int level,
1312 const int spacesPerLevel)
1313{
1314 bslim::Printer printer(&stream, level, spacesPerLevel);
1315 printer.start();
1316 for (ITERATOR it = begin; end != it; ++it) {
1317 printFunctionObject(stream,
1318 *it,
1319 printer.absLevel() + 1,
1320 spacesPerLevel);
1321 if (spacesPerLevel >= 0) {
1322 stream << '\n';
1323 }
1324 }
1325 printer.end();
1326}
1327
1328 // Fundamental types
1329
1330template <class TYPE>
1331inline
1332void Printer_Helper::printRaw(bsl::ostream& stream,
1333 TYPE data,
1334 int ,
1335 int spacesPerLevel,
1337{
1338 stream << data;
1339 if (spacesPerLevel >= 0) {
1340 stream << '\n';
1341 }
1342}
1343
1344template <class TYPE>
1345inline
1346void Printer_Helper::printRaw(bsl::ostream& stream,
1347 TYPE data,
1348 int ,
1349 int spacesPerLevel,
1351{
1353 data,
1354 0,
1355 spacesPerLevel,
1357}
1358
1359 // Function pointer types
1360
1361template <class TYPE>
1362inline
1364 bsl::ostream& stream,
1365 const TYPE& data,
1366 int level,
1367 int spacesPerLevel,
1369{
1370 // GCC 3.4.6 does not allow a reinterpret-cast a function pointer directly
1371 // to 'void *', so first cast it to an integer data type.
1372
1373 Printer_Helper::print(stream,
1374 reinterpret_cast<const void *>(
1375 reinterpret_cast<bsls::Types::UintPtr>(data)),
1376 level,
1377 spacesPerLevel);
1378}
1379
1380 // Pointer types
1381
1382template <class TYPE>
1383inline
1384void Printer_Helper::printRaw(bsl::ostream& stream,
1385 const TYPE *data,
1386 int level,
1387 int spacesPerLevel,
1389{
1391 static_cast<const void *>(data),
1392 level,
1393 -1,
1395 if (0 == data) {
1396 if (spacesPerLevel >= 0) {
1397 stream << '\n';
1398 }
1399 }
1400 else {
1401 stream << ' ';
1402 Printer_Helper::print(stream, *data, level, spacesPerLevel);
1403 }
1404}
1405
1406template <class TYPE>
1407inline
1408void Printer_Helper::printRaw(bsl::ostream& stream,
1409 const TYPE *data,
1410 int level,
1411 int spacesPerLevel,
1413{
1415 data,
1416 level,
1417 spacesPerLevel,
1419}
1420
1421
1422 // Types with STL iterators
1423
1424inline
1426 bsl::ostream& stream,
1427 const bsl::string& data,
1428 int level,
1429 int spacesPerLevel,
1431{
1433 data.c_str(),
1434 level,
1435 spacesPerLevel,
1437}
1438
1439template <class TYPE>
1440inline
1442 bsl::ostream& stream,
1443 const TYPE& data,
1444 int level,
1445 int spacesPerLevel,
1447{
1448 Printer_Helper::print(stream,
1449 data.begin(),
1450 data.end(),
1451 level,
1452 spacesPerLevel);
1453}
1454
1455 // Default types
1456
1457template <class T1, class T2>
1458inline
1459void Printer_Helper::printRaw(bsl::ostream& stream,
1460 const bsl::pair<T1, T2>& data,
1461 int level,
1462 int spacesPerLevel,
1464{
1465 bslim::Printer printer(&stream, level, spacesPerLevel);
1466 printer.start();
1467 printer.printValue(data.first);
1468 printer.printValue(data.second);
1469 printer.end();
1470}
1471
1472#ifdef BSLS_LIBRARYFEATURES_HAS_CPP11_TUPLE
1473template <class t_TUPLE>
1474inline
1475void Printer_Helper::printTupleElements(Printer&,
1476 const t_TUPLE&,
1478{
1479}
1480
1481template <int t_SIZE, class t_TUPLE>
1482inline
1483void Printer_Helper::printTupleElements(Printer& printer,
1484 const t_TUPLE& data,
1486{
1487 printTupleElements(printer, data, bsl::integral_constant<int, t_SIZE-1>{});
1488 printer.printValue(bsl::get<t_SIZE-1>(data));
1489}
1490
1491template <class... t_TYPES>
1492inline
1493void Printer_Helper::printRaw(bsl::ostream& stream,
1494 const bsl::tuple<t_TYPES...>& data,
1495 int level,
1496 int spacesPerLevel,
1498{
1499 bslim::Printer printer(&stream, level, spacesPerLevel);
1500 printer.start();
1501 printTupleElements(printer, data, bsl::integral_constant<int, sizeof...(t_TYPES)>{});
1502 printer.end();
1503}
1504#endif // BSLS_LIBRARYFEATURES_HAS_CPP11_TUPLE
1505
1506template <class TYPE>
1507inline
1508void Printer_Helper::printRaw(bsl::ostream& stream,
1509 const bsl::shared_ptr<TYPE>& data,
1510 int level,
1511 int spacesPerLevel,
1513{
1515 static_cast<const void *>(data.get()),
1516 level,
1517 -1,
1519 if (data) {
1520 stream << ' ';
1521 Printer_Helper::print(stream, *data, level, spacesPerLevel);
1522 }
1523 else if (spacesPerLevel >= 0) {
1524 stream << '\n';
1525 }
1526}
1527
1528template <class TYPE>
1529inline
1530void Printer_Helper::printRaw(bsl::ostream& stream,
1531 const bsl::optional<TYPE>& data,
1532 int level,
1533 int spacesPerLevel,
1535{
1536 if (data.has_value()) {
1537 Printer_Helper::print(stream, *data, level, spacesPerLevel);
1538 }
1539 else {
1540 if (spacesPerLevel >= 0) {
1541 stream << "NULL\n";
1542 }
1543 else {
1544 stream << "NULL";
1545 }
1546 }
1547}
1548
1549template <class TYPE>
1550inline
1551void Printer_Helper::printRaw(bsl::ostream& stream,
1552 const TYPE& data,
1553 int level,
1554 int spacesPerLevel,
1556{
1557 data.print(stream, level, spacesPerLevel);
1558}
1559
1560// This method, though declared first in the struct, is placed last among the
1561// methods in 'Printer_Helper' so that it can inline the 'printRaw' methods it
1562// calls.
1563
1564template <class TYPE>
1565inline
1566void Printer_Helper::print(bsl::ostream& stream,
1567 const TYPE& data,
1568 int level,
1569 int spacesPerLevel)
1570{
1571 typedef bslmf::SelectTrait<TYPE,
1577 bslalg::HasStlIterators> Selection;
1578
1579 Printer_Helper::printRaw(stream, data, level, spacesPerLevel, Selection());
1580}
1581
1582} // close package namespace
1583
1584
1585#endif
1586
1587// ----------------------------------------------------------------------------
1588// Copyright 2014 Bloomberg Finance L.P.
1589//
1590// Licensed under the Apache License, Version 2.0 (the "License");
1591// you may not use this file except in compliance with the License.
1592// You may obtain a copy of the License at
1593//
1594// http://www.apache.org/licenses/LICENSE-2.0
1595//
1596// Unless required by applicable law or agreed to in writing, software
1597// distributed under the License is distributed on an "AS IS" BASIS,
1598// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1599// See the License for the specific language governing permissions and
1600// limitations under the License.
1601// ----------------------------- END-OF-FILE ----------------------------------
1602
1603/** @} */
1604/** @} */
1605/** @} */
Definition bslstl_stringview.h:471
Definition bslstl_string.h:1252
Definition bslstl_optional.h:2043
Definition bslstl_pair.h:1280
Definition bslstl_sharedptr.h:1838
Definition bslim_printer.h:604
int spacesPerLevel() const
void printOrNull(const TYPE &address, const char *name) const
Definition bslim_printer.h:1190
void printValue(const TYPE &data) const
Definition bslim_printer.h:1240
void printForeign(const TYPE &data, const PRINT_FUNCTOR &printFunctionObject, const char *name) const
Definition bslim_printer.h:1173
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:1108
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:1124
bool suppressInitialIndentFlag() const
void printIndentation() const
Definition bslstl_stringref.h:374
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
Definition bslim_formatguard.h:120
Definition bslmf_integralconstant.h:261
Definition bslmf_isarray.h:168
Definition bslmf_isenum.h:272
Definition bslmf_isfundamental.h:330
Definition bslmf_ispointer.h:138
Definition bslalg_hasstliterators.h:99
Definition bslim_printer.h:903
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:1566
static void printRaw(bsl::ostream &stream, bool data, int level, int spacesPerLevel, bslmf::SelectTraitCase< bsl::is_fundamental >)
Definition bslmf_functionpointertraits.h:163
Definition bslmf_selecttrait.h:438
Definition bslmf_selecttrait.h:524
std::size_t UintPtr
Definition bsls_types.h:128