BDE 4.39.x Production Release
Loading...
Searching...
No Matches
baljsn_simpleformatter.h
Go to the documentation of this file.
1/// @file baljsn_simpleformatter.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// baljsn_simpleformatter.h -*-C++-*-
8#ifndef INCLUDED_BALJSN_SIMPLEFORMATTER
9#define INCLUDED_BALJSN_SIMPLEFORMATTER
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup baljsn_simpleformatter baljsn_simpleformatter
15/// @brief Provide a simple formatter for encoding data in the JSON format.
16/// @addtogroup bal
17/// @{
18/// @addtogroup baljsn
19/// @{
20/// @addtogroup baljsn_simpleformatter
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#baljsn_simpleformatter-purpose"> Purpose</a>
25/// * <a href="#baljsn_simpleformatter-classes"> Classes </a>
26/// * <a href="#baljsn_simpleformatter-description"> Description </a>
27/// * <a href="#baljsn_simpleformatter-comparison-to-baljsn-formatter"> Comparison to baljsn::Formatter </a>
28/// * <a href="#baljsn_simpleformatter-api-comparison"> API Comparison </a>
29/// * <a href="#baljsn_simpleformatter-json-format"> JSON Format </a>
30/// * <a href="#baljsn_simpleformatter-usage"> Usage </a>
31/// * <a href="#baljsn_simpleformatter-example-1-encoding-a-stock-portfolio-in-json"> Example 1: Encoding a Stock Portfolio in JSON </a>
32/// * <a href="#baljsn_simpleformatter-example-2-encoding-an-array"> Example 2: Encoding an array </a>
33///
34/// # Purpose {#baljsn_simpleformatter-purpose}
35/// Provide a simple formatter for encoding data in the JSON format.
36///
37/// # Classes {#baljsn_simpleformatter-classes}
38///
39/// - baljsn::SimpleFormatter: a mechanism to encode data into JSON
40///
41/// @see baljsn_encoder, baljsn_formatter, baljsn_printutil
42///
43/// # Description {#baljsn_simpleformatter-description}
44/// This component provides a class, `baljsn::SimpleFormatter`, for
45/// rendering JSON conforming text for objects, arrays, and various scalar
46/// types.
47///
48/// This component provides an interface that is easier to use, and renders more
49/// readable "pretty" JSON, than `baljsn::Formatter`. Clients are encouraged to
50/// use `baljsn::SimpleFormatter` instead of `baljsn::Formatter` (see
51/// {Comparison to `baljsn::Formatter`}).
52///
53/// The `SimpleFormatter` `class` also provides the ability to specify
54/// formatting options at construction. The options that can be provided
55/// include the encoding style (compact or pretty), the initial indentation
56/// level and spaces per level if encoding in the pretty format.
57///
58/// ## Comparison to baljsn::Formatter {#baljsn_simpleformatter-comparison-to-baljsn-formatter}
59///
60///
61///
62/// ### API Comparison {#baljsn_simpleformatter-api-comparison}
63///
64///
65/// Here is the side-by-side sequence of calls to create the following JSON
66/// using both components, assuming an existing stream `os`:
67/// @code
68/// {
69/// "Object" : {
70/// "Field 1": 1,
71/// "Field 2": null
72/// },
73/// "Array": [
74/// 1,
75/// "string",
76/// [],
77/// [
78/// [
79/// {
80/// }
81/// ]
82/// ]
83/// ],
84/// "True" : true
85/// }
86/// @endcode
87/// Some extra indentation has been added in these examples to show the various
88/// `open`/`close` call nesting levels.
89/// @code
90/// Formatter | SimpleFormatter
91/// -----------------------------------+----------------------------------------
92/// baljsn::Formatter f(os); | baljsn::SimpleFormatter sf(os);
93/// |
94/// f.openObject(); | sf.openObject();
95/// |
96/// f.openMember("Object"); | sf.openObject("Object");
97/// f.openObject(); | sf.addValue("Field 1", 1);
98/// f.openMember("Field 1"); | sf.addNullValue("Field 2");
99/// f.putValue(1); | sf.closeObject();
100/// f.closeMember(); |
101/// f.openMember("Field 2"); | sf.openArray("Array");
102/// f.putNullValue(); | sf.addValue(1); // No name
103/// // Must remember NOT to call | sf.addValue("string"); // No name
104/// // closeMember here! | sf.openArray(e_EMPTY_ARRAY_FORMAT);
105/// f.closeObject(); | sf.closeArray(e_EMPTY_ARRAY_FORMAT);
106/// f.closeMember(); | sf.openArray();
107/// | sf.openArray();
108/// f.openMember("Array"); | sf.openObject();
109/// f.openArray(); | sf.closeObject();
110/// f.putValue(1); | sf.closeArray();
111/// f.addArrayElementSeparator(); | sf.closeArray();
112/// f.putValue("string"); | sf.closeArray();
113/// f.addArrayElementSeparator(); |
114/// f.openArray(true); | sf.addValue("True", true);
115/// f.closeArray(true); | sf.closeObject();
116/// f.addArrayElementSeparator(); |
117/// f.openArray(); |
118/// f.openArray(); |
119/// f.openObject(); |
120/// f.closeObject(); |
121/// f.closeArray(); |
122/// f.closeArray(); |
123/// |
124/// // Must remember NOT to call |
125/// // addArrayElementSeparator |
126/// // here! |
127/// f.closeArray(); |
128/// f.closeMember(); |
129/// |
130/// f.openMember("True"); |
131/// f.putValue(true); |
132/// // Must remember NOT to call |
133/// // closeMember here! |
134/// |
135/// f.closeObject(); |
136/// -----------------------------------+----------------------------------------
137///
138/// @endcode
139///
140/// ## JSON Format {#baljsn_simpleformatter-json-format}
141///
142///
143/// The JSON encoding format (see http://json.org or ECMA-404 standard for more
144/// information) specifies a self-describing and simple syntax that is built on
145/// two structures:
146///
147/// * Objects: JSON objects are represented as collections of name value
148/// pairs. The `SimpleFormatter` `class` allows encoding objects by
149/// providing the `openObject` and `closeObject` methods to open and close an
150/// object and overloads for `openObject`, `openArray`, `addValue` and
151/// `addNullValue` which take a `name` to specify the named fields in the
152/// object, or the use of the `addMemberName` manipulator followed by the
153/// overloads of `openObject`, `openArray`, `addValue`, and `addNullValue`
154/// which do not take a name.
155/// * Arrays: JSON arrays are specified as an ordered list of values. The
156/// `SimpleFormatter` `class` provides the `openArray` and `closeArray`
157/// method to open and close an array, as well as overloads for `openObject`,
158/// `openArray`, `addValue` and `addNullValue` which do not take a `name` for
159/// array elements.
160///
161/// The `SimpleFormatter` `class` provides the ability to specify formatting
162/// options at construction. The options that can be provided include the
163/// encoding style (compact or pretty), the initial indentation level and spaces
164/// per level if encoding in the pretty format.
165///
166/// ## Usage {#baljsn_simpleformatter-usage}
167///
168///
169/// This section illustrates intended use of this component.
170///
171/// ### Example 1: Encoding a Stock Portfolio in JSON {#baljsn_simpleformatter-example-1-encoding-a-stock-portfolio-in-json}
172///
173///
174/// Let us suppose we have to encode a JSON document containing information
175/// about a small portfolio of stocks. The eventual data we want to encode is
176/// represented by the following JSON string (which is the expected output of
177/// the encoding process):
178///
179/// First, we specify the result that we are expecting to get:
180/// @code
181/// {
182/// const bsl::string EXPECTED =
183/// "{\n"
184/// " \"Stocks\": [\n"
185/// " {\n"
186/// " \"Name\": \"International Business Machines Corp\",\n"
187/// " \"Ticker\": \"IBM US Equity\",\n"
188/// " \"Last Price\": 149.3,\n"
189/// " \"Dividend Yield\": 3.95\n"
190/// " },\n"
191/// " {\n"
192/// " \"Name\": \"Apple Inc\",\n"
193/// " \"Ticker\": \"AAPL US Equity\",\n"
194/// " \"Last Price\": 205.8,\n"
195/// " \"Dividend Yield\": 1.4\n"
196/// " }\n"
197/// " ]\n"
198/// "}";
199/// @endcode
200/// Then, to encode this JSON document we create a `baljsn::SimpleFormatter`
201/// object. Since we want the document to be written in a pretty, easy to
202/// understand format we will specify `true` for the `usePrettyStyle` option and
203/// provide an appropriate initial indent level and spaces per level values:
204/// @code
205/// bsl::ostringstream os;
206/// baljsn::EncoderOptions encoderOptions;
207///
208/// encoderOptions.setEncodingStyle(baljsn::EncoderOptions::e_PRETTY);
209/// encoderOptions.setSpacesPerLevel(2);
210///
211/// baljsn::SimpleFormatter formatter(os, encoderOptions);
212/// @endcode
213/// Next, we encode the start of the top level object, and open the first member
214/// "Stocks" (which holds an array of stock information):
215/// @code
216/// formatter.openObject();
217/// formatter.openArray("Stocks");
218/// @endcode
219/// Next, we render each element within the array of "Stocks" as an object that
220/// contains information for an individual stock:
221/// @code
222/// formatter.openObject();
223/// @endcode
224/// We now encode the other elements in the stock object.
225/// @code
226/// formatter.addValue("Name", "International Business Machines Corp");
227/// formatter.addValue("Ticker", "IBM US Equity");
228/// formatter.addValue("Last Price", 149.3);
229/// formatter.addValue("Dividend Yield", 3.95);
230/// @endcode
231/// Then, close the first stock object.
232/// @code
233/// formatter.closeObject();
234/// @endcode
235/// Next, we add another stock object.
236/// @code
237/// formatter.openObject();
238///
239/// formatter.addValue("Name", "Apple Inc");
240/// formatter.addValue("Ticker", "AAPL US Equity");
241/// formatter.addValue("Last Price", 205.8);
242/// formatter.addValue("Dividend Yield", 1.4);
243///
244/// formatter.closeObject();
245/// @endcode
246/// Similarly, we can continue to format the rest of the document. For the
247/// purpose of this usage example we will complete this document.
248/// @code
249/// formatter.closeArray();
250/// formatter.closeObject();
251/// @endcode
252/// Once the formatting is complete the written data can be viewed from the
253/// stream passed to the formatter at construction.
254/// @code
255/// if (verbose)
256/// bsl::cout << os.str() << bsl::endl;
257/// @endcode
258/// Finally, verify the received result:
259/// @code
260/// assert(EXPECTED == os.str());
261/// }
262/// @endcode
263///
264/// ### Example 2: Encoding an array {#baljsn_simpleformatter-example-2-encoding-an-array}
265///
266///
267/// Let us say we want to encode an array of various values.
268///
269/// First, we create our `formatter` as we did above:
270/// @code
271/// {
272/// bsl::ostringstream os;
273/// baljsn::EncoderOptions encoderOptions;
274///
275/// encoderOptions.setEncodingStyle(baljsn::EncoderOptions::e_PRETTY);
276/// encoderOptions.setSpacesPerLevel(2);
277///
278/// baljsn::SimpleFormatter formatter(os, encoderOptions);
279/// @endcode
280/// Then we open our array.
281/// @code
282/// formatter.openArray();
283/// @endcode
284/// Next, we populate the array with a series of unnamed values. Named values
285/// are only used in objects, not arrays.
286/// @code
287/// formatter.addValue("First value");
288/// formatter.addValue(2);
289/// formatter.addValue(3);
290/// @endcode
291/// Then, we demonstrate that arrays can be nested, opening another level of
292/// array, populating it, and closing it:
293/// @code
294/// formatter.openArray();
295/// formatter.addValue("First value of inner array");
296/// formatter.addValue(3.14159);
297/// formatter.closeArray();
298/// @endcode
299/// Arrays can also contain (unnamed) objects:
300/// @code
301/// formatter.openObject();
302/// @endcode
303/// Next, we add (named) values to our object:
304/// @code
305/// formatter.addValue("Greeting", "Hello from the first inner object");
306/// formatter.addValue("PI approximation", 3.14);
307/// // We could, similarly, add nested named objects and/or named arrays
308/// @endcode
309/// Then we close the nested object:
310/// @code
311/// formatter.closeObject();
312/// @endcode
313/// Finally, we close the outer array:
314/// @code
315/// formatter.closeArray();
316/// }
317/// @endcode
318/// @}
319/** @} */
320/** @} */
321
322/** @addtogroup bal
323 * @{
324 */
325/** @addtogroup baljsn
326 * @{
327 */
328/** @addtogroup baljsn_simpleformatter
329 * @{
330 */
331
332#include <balscm_version.h>
333
335#include <baljsn_printutil.h>
336
337#include <bdlb_print.h>
338
339#include <bdlc_bitarray.h>
340
341#include <bsl_ostream.h>
342
343#include <bslma_allocator.h>
345
347
348#include <bsls_assert.h>
349#include <bsls_review.h>
350
351#include <bsl_string_view.h>
352
353
354namespace baljsn {
355
356class EncoderOptions;
357
358 // =====================
359 // class SimpleFormatter
360 // =====================
361
362/// This class implements a formatter providing operations for rendering
363/// JSON text elements to an output stream (supplied at construction)
364/// according to a set of formatting options (also supplied at
365/// construction).
366///
367/// This class has an interface that's easier to use than that of
368/// `baljsn::Formatter`, and generates more correctly-formatted `pretty`
369/// output.
370///
371/// See @ref baljsn_simpleformatter
373
374 public:
375 // TYPES
377 // This 'enum' lists all possible array formatting styles.
380 };
381
382 private:
383 // DATA
384 bsl::ostream& d_outputStream; // stream for output (held, not
385 // owned)
386
387 bool d_useComma; // whether next start item
388 // ('add*', 'open*') needs a
389 // preceding comma
390
391 bool d_started; // whether we've formatted at
392 // least one element
393
394 bool d_memberNameSupplied; // whether the previous output
395 // operation was 'addMemberName'
396
397 bdlc::BitArray d_callSequence; // array specifying the sequence
398 // in which the 'openObject' and
399 // 'openArray' methods were
400 // called. An 'openObject' call
401 // is represented by 'false' and
402 // an 'openArray' call by 'true'.
403
404 EncoderOptions d_encoderOptions; // formatting and encoding
405 // options
406
407 int d_indentLevel; // current indent level
408
409 // PRIVATE MANIPULATORS
410
411 /// Unconditionally print onto the stream supplied at construction the
412 /// sequence of whitespace characters for the proper indentation of an element at the current indentation level.
413 ///
414 /// \note Note that this method
415 /// does not check that `usePrettyStyle()` is `true` before indenting.
416 void indent();
417
418 /// If `d_useComma` is `true`, print a comma. If `usePrettyStyle()` is
419 /// also `true`, also print a newline. This also sets
420 /// `d_memberNameSupplied` to `false`.
421 void printComma();
422
423 /// Set `d_useComma` to the value of the specified `flag`, indicating
424 /// whether the next `printComma()` call should actually print a comma.
425 void followWithComma(bool flag);
426
427 /// Print onto the stream supplied at construction the specified `name`,
428 /// followed by a `:`. The `:` is surrounded by a space on each side if
429 /// `usePrettyStyle()` is `true`. It is the caller's responsibility to
430 /// call `printComma()` - this routine does not handle commas, but does
431 /// call `indent()` if necessary.
432 void printName(const bsl::string_view& name);
433
434 // PRIVATE ACCESSORS
435
436 /// Return `true` if `e_PRETTY == d_encoderOptions.encodingStyle()`.
437 bool usePrettyStyle() const;
438
439 /// Return `d_encoderOptions.spacesPerLevel()`.
440 int spacesPerLevel() const;
441
442 public:
443 // TRAITS
446
447 // CREATORS
448
449 /// Create a `SimpleFormatter` object using the specified `stream`.
450 /// Optionally specify `encoderOptions` to configure the output options
451 /// - if `encoderOptions` is not supplied, a default-constructed `EncoderOptions` object will be used.
452 ///
453 /// \note Note that the
454 /// `encodeEmptyArrays` attribute in the `encoderOptions` is ignored.
455 /// Optionally specify a `basicAllocator` used to supply memory. If
456 /// `basicAllocator` is 0, the currently installed default allocator is
457 /// used.
458 explicit SimpleFormatter(bsl::ostream& stream,
459 bslma::Allocator *basicAllocator = 0);
460 explicit SimpleFormatter(bsl::ostream& stream,
461 const EncoderOptions& encoderOptions,
462 bslma::Allocator *basicAllocator = 0);
463
464 /// Create a `SimpleFormatter` object having the same value as the
465 /// specified `original` object. Optionally specify a `basicAllocator`
466 /// used to supply memory. If `basicAllocator` is 0, the currently
467 /// installed default allocator is used.
469 bslma::Allocator *basicAllocator);
470
471 /// Destroy this object.
472 /// \note Note that correct JSON has been generated if
473 /// the `isCompleteJSON()` call returns `true`.
475
476 // MANIPULATORS
477
478 /// Print onto the stream supplied at construction the sequence of
479 /// characters designating the start of an object (referred to as an
480 /// "object" in JSON), preceded, if necessary, by a comma.
481 ///
482 /// \pre The behavior is undefined unless `isNameNeeded()` is `false`.
484
485 /// Print onto the stream supplied at construction the sequence of
486 /// characters designating the start of an object (referred to as an
487 /// "object" in JSON) with the specified `name` , preceded, if necessary, by a comma.
488 ///
489 /// \pre The behavior is undefined unless
490 /// `isNameNeeded()` is `true`.
491 void openObject(const bsl::string_view& name);
492
493 /// Print onto the stream supplied at construction the specified `name`
494 /// in double-quotes, preceded, if necessary, by a comma, and followed by a `:`.
495 ///
496 /// \pre The behavior is undefined unless `isNameNeeded()` is
497 /// `true`. After this operation, `isNameNeeded()` will be `false`, and
498 /// an immediately subsequent attempt to add a value (or open an object
499 /// or array) should not provide a name.
500 void addMemberName(const bsl::string_view& name);
501
502 /// Print onto the stream supplied at construction the sequence of
503 /// characters designating the end of an object (referred to as an "object" in JSON).
504 ///
505 /// \pre The behavior is undefined unless
506 /// `isNameNeeded()` is `true`.
508
509 /// Print onto the stream supplied at construction the sequence of
510 /// characters designating the start of an array (referred to as an
511 /// "array" in JSON), preceded, if necessary, by a comma. Optionally
512 /// specify `formattingStyle` denoting if the array being opened should
513 /// be formatted as an empty array. If `formattingStyle` is not
514 /// specified then the array being opened is formatted as a regular array having elements.
515 ///
516 /// \pre The behavior is undefined unless `isNameNeeded()` is `false`.
517 ///
518 /// \note Note that the formatting (and as a
519 /// consequence the `formattingStyle`) is relevant only if this
520 /// formatter encodes in the pretty style and is ignored otherwise.
523
524 /// Print onto the stream supplied at construction the sequence of
525 /// characters designating the start of an array (referred to as an
526 /// "array" in JSON) with the specified `name`, preceded, if necessary,
527 /// by a comma. Optionally specify `formattingStyle` denoting if the
528 /// array being opened should be formatted as an empty array. If
529 /// `formattingStyle` is not specified then the array being opened is
530 /// formatted as a regular array having elements.
531 ///
532 /// \pre The behavior is undefined unless `isNameNeeded()` is `true`.
533 /// \note Note that the
534 /// formatting (and as a consequence the `formattingStyle`) is relevant
535 /// only if this formatter encodes in the pretty style and is ignored
536 /// otherwise.
538 const bsl::string_view& name,
540
541 /// Print onto the stream supplied at construction the sequence of
542 /// characters designating the end of an array (referred to as an
543 /// "array" in JSON). Optionally specify `formattingStyle` denoting if
544 /// the array being closed should be formatted as an empty array. If
545 /// `formattingStyle` is not specified then the array being closed is
546 /// formatted as a regular array having elements.
547 ///
548 /// \pre The behavior is undefined if `isFormattingArray()` is `false`.
549 /// \note Note that the
550 /// formatting (and as a consequence the `formattingStyle`) is relevant
551 /// only if this formatter encodes in the pretty style and is ignored
552 /// otherwise.
555
556 /// Print onto the stream supplied at construction the value
557 /// corresponding to a null element, preceded, if necessary, by a comma.
558 ///
559 /// \pre The behavior is undefined unless `isNameNeeded()` is `false`.
560 void addNullValue();
561
562 /// Print onto the stream supplied at construction the value
563 /// corresponding to a null element with the specified `name`, preceded, if necessary, by a comma.
564 ///
565 /// \pre The behavior is undefined unless
566 /// `isNameNeeded()` is `true`.
567 void addNullValue(const bsl::string_view& name);
568
569 /// Print onto the stream supplied at construction the specified
570 /// `value`, preceded, if necessary, by a comma, passing the optionally
571 /// specified `options` through to the rendering routines. Return 0 on
572 /// success and a non-zero value otherwise.
573 ///
574 /// \pre The behavior is undefined unless `isNameNeeded()` is `false`.
575 template <class TYPE>
576 int addValue(const TYPE& value);
577
578 /// Print onto the stream supplied at construction the specified `name`
579 /// and the specified `value`, preceded, if necessary, by a comma,
580 /// passing the optionally specified `options` through to the rendering
581 /// routines. Return 0 on success and a non-zero value otherwise.
582 ///
583 /// \pre The behavior is undefined unless `isNameNeeded()` is `true`.
584 template <class TYPE>
585 int addValue(const bsl::string_view& name, const TYPE& value);
586
587 // ACCESSORS
588
589 /// Return `true` if this `SimpleFormatter` has formatted a complete
590 /// JSON object, where all `open*` calls have been balanced by their corresponding `close*` calls.
591 ///
592 /// \note Note that a default-constructed
593 /// `SimpleFormatter` will return `false` - an empty string is not valid
594 /// JSON.
595 bool isCompleteJSON() const;
596
597 /// Return `true` if this `SimpleFormatter` is currently formatting an
598 /// array and `false` otherwise. It is formatting an array if the last
599 /// `open*` method overload (`openArray` or `openObject`) called on this
600 /// `SimpleFormatter` for which the corresponding `close*` method
601 /// (respectively, `closeArray` or `closeObject`) was `openArray`. If
602 /// `isFormattingArray()` is `true`, then `isFormattingObject()` is `false`.
603 ///
604 /// \note Note that both can be `false`, at the `top-level` initial
605 /// scope before anything is added/opened or after the first `open*`
606 /// call has been closed'
607 bool isFormattingArray() const;
608
609 /// Return `true` if this `SimpleFormatter` is currently formatting an
610 /// object scope and `false` otherwise. It is formatting an object
611 /// scope if the last `open*` method overload (`openArray` or
612 /// `openObject`) called on this `SimpleFormatter` for which the
613 /// corresponding `close*` method (respectively, `closeArray` or
614 /// `closeObject`) was `openObject`. If `isFormattingObject()` is `true`, then `isFormattingArray()` is `false`.
615 ///
616 /// \note Note that both can
617 /// be `false`, at the `top-level` initial scope before anything is
618 /// added/opened or after the first `open*` call has been closed'
619 /// JSON.
620 bool isFormattingObject() const;
621
622 /// Return `true` if a subsequent attempt to add a value must supply a
623 /// `name`, and `false` otherwise. This will be `true` if
624 /// `isFormattingObject()` is `true`, and `addMemberName()` was not the
625 /// most recently called manipulator. That is, a name is needed if this
626 /// formatter is currently in the context of formatting the members of a
627 /// JSON object, and `addMemberName` has not been called to explicitly
628 /// provide a name for the next member.
629 bool isNameNeeded() const;
630
631 // Aspects
632
633 /// Return the allocator used by this object to supply memory.
634 ///
635 /// \note Note that if no allocator was supplied at construction the currently
636 /// installed default allocator is used.
638};
639
640// ============================================================================
641// INLINE DEFINITIONS
642// ============================================================================
643
644 // ---------------
645 // class SimpleFormatter
646 // ---------------
647
648// PRIVATE MANIPULATORS
649inline
650void SimpleFormatter::followWithComma(bool flag)
651{
652 d_useComma = flag;
653}
654
655inline
656void SimpleFormatter::indent()
657{
658 bdlb::Print::indent(d_outputStream, d_indentLevel, spacesPerLevel());
659}
660
661inline
662void SimpleFormatter::printComma()
663{
664 d_started = true;
665
666 if (d_useComma) {
667 d_outputStream << ',';
668
669 if (usePrettyStyle()) {
670 d_outputStream << '\n';
671 }
672 }
673
674 d_memberNameSupplied = false;
675}
676
677inline
678void SimpleFormatter::printName(const bsl::string_view& name)
679{
680 if (usePrettyStyle()) {
681 indent();
682 }
683
684 const int rc = PrintUtil::printValue(d_outputStream,
685 name,
686 &d_encoderOptions);
687 if (rc) {
688 return; // RETURN
689 }
690
691 d_outputStream << (usePrettyStyle() ? ": " : ":");
692}
693
694// PRIVATE ACCESSORS
695inline
696int SimpleFormatter::spacesPerLevel() const
697{
698 return d_encoderOptions.spacesPerLevel();
699}
700
701inline
702bool SimpleFormatter::usePrettyStyle() const
703{
704 return EncoderOptions::e_PRETTY == d_encoderOptions.encodingStyle();
705}
706
707// MANIPULATORS
708inline
710{
712
713 printComma();
714 followWithComma(false);
715
716 printName(name);
717
718 d_memberNameSupplied = true;
719}
720
721inline
723{
725
726 bool needIndent = usePrettyStyle() && !d_memberNameSupplied;
727
728 printComma();
729 followWithComma(true);
730
731 if (needIndent) {
732 indent();
733 }
734
735 d_outputStream << "null";
736}
737
738inline
740{
742
743 printComma();
744 followWithComma(true);
745
746 printName(name);
747
748 d_outputStream << "null";
749}
750
751template <class TYPE>
752int SimpleFormatter::addValue(const TYPE& value)
753{
755
756 bool needIndent = usePrettyStyle() && !d_memberNameSupplied;
757
758 printComma();
759 followWithComma(true);
760
761 if (needIndent) {
762 indent();
763 }
764
766 d_outputStream, value, &d_encoderOptions);
767}
768
769template <class TYPE>
770int SimpleFormatter::addValue(const bsl::string_view& name, const TYPE& value)
771{
773
774 printComma();
775 followWithComma(true);
776
777 printName(name);
778
780 d_outputStream, value, &d_encoderOptions);
781}
782
783// ACCESSORS
784inline
786{
787 return d_started && (1 == d_callSequence.length());
788}
789
790inline
792{
793 BSLS_ASSERT(d_callSequence.length() >= 1);
794
795 return d_callSequence.length() > 1 &&
796 d_callSequence[d_callSequence.length() - 1];
797}
798
799inline
801{
802 BSLS_ASSERT(d_callSequence.length() >= 1);
803
804 return d_callSequence.length() > 1 &&
805 !d_callSequence[d_callSequence.length() - 1];
806}
807
808inline
810{
811 return isFormattingObject() && !d_memberNameSupplied;
812}
813
814 // Aspects
815
816inline
818{
819 return d_callSequence.allocator();
820}
821
822} // close package namespace
823
824
825
826#endif
827
828// ----------------------------------------------------------------------------
829// Copyright 2019 Bloomberg Finance L.P.
830//
831// Licensed under the Apache License, Version 2.0 (the "License");
832// you may not use this file except in compliance with the License.
833// You may obtain a copy of the License at
834//
835// http://www.apache.org/licenses/LICENSE-2.0
836//
837// Unless required by applicable law or agreed to in writing, software
838// distributed under the License is distributed on an "AS IS" BASIS,
839// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
840// See the License for the specific language governing permissions and
841// limitations under the License.
842// ----------------------------- END-OF-FILE ----------------------------------
843
844/** @} */
845/** @} */
846/** @} */
Definition baljsn_encoderoptions.h:290
@ e_PRETTY
Definition baljsn_encoderoptions.h:353
baljsn::EncoderOptions::EncodingStyle encodingStyle() const
Definition baljsn_encoderoptions.h:1043
int spacesPerLevel() const
Definition baljsn_encoderoptions.h:1037
Definition baljsn_simpleformatter.h:372
void openArray(ArrayFormattingStyle formattingStyle=e_REGULAR_ARRAY_FORMAT)
void closeArray(ArrayFormattingStyle formattingStyle=e_REGULAR_ARRAY_FORMAT)
void openArray(const bsl::string_view &name, ArrayFormattingStyle formattingStyle=e_REGULAR_ARRAY_FORMAT)
void addMemberName(const bsl::string_view &name)
Definition baljsn_simpleformatter.h:709
SimpleFormatter(const SimpleFormatter &original, bslma::Allocator *basicAllocator)
SimpleFormatter(bsl::ostream &stream, bslma::Allocator *basicAllocator=0)
bool isFormattingArray() const
Definition baljsn_simpleformatter.h:791
bool isFormattingObject() const
Definition baljsn_simpleformatter.h:800
ArrayFormattingStyle
Definition baljsn_simpleformatter.h:376
@ e_EMPTY_ARRAY_FORMAT
Definition baljsn_simpleformatter.h:379
@ e_REGULAR_ARRAY_FORMAT
Definition baljsn_simpleformatter.h:378
SimpleFormatter(bsl::ostream &stream, const EncoderOptions &encoderOptions, bslma::Allocator *basicAllocator=0)
bslma::Allocator * allocator() const
Definition baljsn_simpleformatter.h:817
void addNullValue()
Definition baljsn_simpleformatter.h:722
void openObject(const bsl::string_view &name)
bool isCompleteJSON() const
Definition baljsn_simpleformatter.h:785
bool isNameNeeded() const
Definition baljsn_simpleformatter.h:809
int addValue(const TYPE &value)
Definition baljsn_simpleformatter.h:752
BSLMF_NESTED_TRAIT_DECLARATION(SimpleFormatter, bslma::UsesBslmaAllocator)
Definition bdlc_bitarray.h:525
bsl::size_t length() const
Return the number of bits in this array.
Definition bdlc_bitarray.h:1886
bslma::Allocator * allocator() const
Return the allocator used by this object to supply memory.
Definition bdlc_bitarray.h:1918
Definition bslstl_stringview.h:471
Definition bslma_allocator.h:545
#define BSLS_ASSERT(X)
Definition bsls_assert.h:1976
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
Definition baljsn_convertfromjsonoptions.h:112
static int printValue(bsl::ostream &stream, bool value, const EncoderOptions *options=0)
Definition baljsn_printutil.h:442
static bsl::ostream & indent(bsl::ostream &stream, int level, int spacesPerLevel=4)
Definition bslma_usesbslmaallocator.h:344