BDE 4.14.0 Production release
Loading...
Searching...
No Matches
balxml_formatter_prettyimpl.h
Go to the documentation of this file.
1/// @file balxml_formatter_prettyimpl.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// balxml_formatter_prettyimpl.h -*-C++-*-
8#ifndef INCLUDED_BALXML_FORMATTER_PRETTYIMPL
9#define INCLUDED_BALXML_FORMATTER_PRETTYIMPL
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup balxml_formatter_prettyimpl balxml_formatter_prettyimpl
15/// @brief Provide pretty-printing implementation for `balxml_formatter`.
16/// @addtogroup bal
17/// @{
18/// @addtogroup balxml
19/// @{
20/// @addtogroup balxml_formatter_prettyimpl
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#balxml_formatter_prettyimpl-purpose"> Purpose</a>
25/// * <a href="#balxml_formatter_prettyimpl-classes"> Classes </a>
26/// * <a href="#balxml_formatter_prettyimpl-description"> Description </a>
27///
28/// # Purpose {#balxml_formatter_prettyimpl-purpose}
29/// Provide pretty-printing implementation for @ref balxml_formatter .
30///
31/// # Classes {#balxml_formatter_prettyimpl-classes}
32///
33/// - balxml::Formatter_PrettyImplState: state of formatter state machine
34/// - balxml::Formatter_PrettyImplStateId: labels for formatter state
35/// - balxml::Formatter_PrettyImplUtil: actions of formatter state machine
36///
37/// # Description {#balxml_formatter_prettyimpl-description}
38/// This private, subordinate component to @ref balxml_formatter
39/// provides an in-core value semantic attribute class,
40/// `balxml::Formatter_PrettyImplState`, and a utility `struct`,
41/// `balxml::Formatter_PrettyImplUtil`, that implements XML pretty-printing
42/// operations using the state value type. These two classes work in
43/// conjunction to implement a state machine for pretty-printing an XML document
44/// given a sequence of tokens to emit. The class
45/// `balxml::Formatter_PrettyImplStateId` enumerates the set of labels for
46/// distinct states of `balxml::Formatter_PrettyImplState`, upon which most
47/// control-flow decisions of `balxml::Formatter_PrettyImplUtil` are based.
48/// @}
49/** @} */
50/** @} */
51
52/** @addtogroup bal
53 * @{
54 */
55/** @addtogroup balxml
56 * @{
57 */
58/** @addtogroup balxml_formatter_prettyimpl
59 * @{
60 */
61
62#include <balscm_version.h>
63
67
69
71
72#include <bslma_bslallocator.h>
74
76
77#include <bsl_ios.h>
78#include <bsl_ostream.h>
79#include <bsl_string_view.h>
80#include <bsl_vector.h>
81
82
83namespace balxml {
84
85 // ==================================
86 // struct Formatter_PrettyImplStateId
87 // ==================================
88
89/// This `struct` provides a namespace for enumerating the set of labels for
90/// distinct states of `Formatter_PrettyImplState`.
92
93 // TYPES
94 enum Enum {
95 /// This state indicates that the current write position of the
96 /// formatter is at the start of the document. The formatter is
97 /// only allowed to add an XML header when in this state.
99
100 /// This state indicates that the current write position of the
101 /// formatter is after some tokens have been emitted, such as an XML
102 /// header and/or some comments, but before any XML tags have been
103 /// emitted. The formatter is not allowed to emit an XML header
104 /// when in this state.
106
107 /// This state indicates that the current write position of the
108 /// formatter is immediately after the name of an opening tag, or
109 /// otherwise immediately after the value of an attribute of an
110 /// opening tag. In this state, most token printing operations,
111 /// other than adding attributes, need to emit a ">" character to
112 /// close the currently open tag before emitting their content. For
113 /// example:
114 /// @code
115 /// 1| <someTag
116 /// `---------^
117 ///
118 /// * Note that there is no '>' character yet
119 /// @endcode
120 /// or:
121 /// @code
122 /// 1| <someTag attr="value" otherAttr="42"
123 /// `-------------------------------------^
124 /// @endcode
126
127 /// This state indicates that the current write position of the
128 /// formatter is after a complete opening tag, before any data for
129 /// the tag, and that there are tokens already emitted on the
130 /// current line (i.e., that the current write position is not at
131 /// the start of the line). In this state, whether or not token
132 /// printing operations need to emit a new line and indentation
133 /// generally depends on the whitespace mode set for the
134 /// currently-open tag. Note that comments are not considered data.
135 /// For example:
136 /// @code
137 /// 1| <someTag>
138 /// `----------^
139 /// @endcode
140 /// or:
141 /// @code
142 /// 1| <someTag> <!-- comment -->
143 /// `---------------------------^
144 /// @endcode
145 /// or:
146 /// @code
147 /// 1| <someTag attr="value">
148 /// 2| <!-- comment -->
149 /// `-------------------^
150 /// @endcode
152
153 /// This state indicates that the current write position of the
154 /// formatter is at column 0 (i.e., that it is at the start of a new
155 /// line) and either 1) after a closing tag, or 2) after a complete
156 /// opening tag and optional data. In this state, most token
157 /// printing operations need to emit indentation before their
158 /// content. For example:
159 /// @code
160 /// 1| <someTag>
161 /// 2|
162 /// `^
163 /// @endcode
164 /// or:
165 /// @code
166 /// 1| <someTag>
167 /// 2| </someTag>
168 /// 3|
169 /// `^
170 ///
171 /// * Note that the 'closeElement' operation, which is used to
172 /// print closing tags, e.g., "</example>", *always* writes a
173 /// newline character after the closing tag.
174 /// @endcode
175 /// or:
176 /// @code
177 /// 1| <someTag>
178 /// 2| some list data
179 /// 3| some more list data
180 /// 4|
181 /// `^
182 /// @endcode
184
185 /// This state indicates that the current write position of the
186 /// formatter is after one or more data tokens for the
187 /// currently-open tag, and that there are tokens already emitted on
188 /// the current line (i.e., that the current write position is not
189 /// at the start of a new line). In this state, data printing
190 /// operations must put delimiting whitespace before their data.
191 /// What whitespace they emit may depend on the whitespace mode of
192 /// the currently-open tag. For example:
193 /// @code
194 /// 1| <someTag> someData
195 /// `-------------------^
196 /// @endcode
197 /// or
198 /// @code
199 /// 1| <someTag>
200 /// 2| some list data
201 /// 3| some more list data
202 /// `----------------------^
203 /// @endcode
205
206 /// This state indicates that the current write position of the
207 /// formatter is immediately after the top-level closing tag of the
208 /// document.
210 };
211};
212
213 // ===============================
214 // class Formatter_PrettyImplState
215 // ===============================
216
217/// This class provides an in-core, value-semantic attribute type that
218/// maintains all of the state information needed to pretty-print an XML
219/// document using the operations provided by `Formatter_PrettyImplUtil`.
220///
221/// See @ref balxml_formatter_prettyimpl
223
224 public:
225 // TYPES
229
230 private:
231 // DATA
232
233 // the canonical "state" in the state machine, upon which most
234 // control-flow decisions are based when printing
235 Id::Enum d_id;
236
237 // number of indentations to perform when printing an element on a new
238 // line
239 int d_indentLevel;
240
241 // number of spaces to print per level of indentation
242 int d_spacesPerLevel;
243
244 // the current column number
245 int d_column;
246
247 // the column number at which an element will be printed on the next
248 // line and optionally indented depending on the requested whitespace
249 // mode
250 int d_wrapColumn;
251
252 // a stack of names of currently nested elements with the whitespace
253 // handling constraint for each element in the stack
254 bsl::vector<WhitespaceType::Enum> d_elementNesting;
255
256 public:
257 // TRAITS
260
261 // CREATORS
262
264 /// Create a `Formatter_PrettyImplState` having an `id` attribute of
265 /// `Id::e_AT_START`, `indentLevel`, `spacesPerLevel`, `column`, and
266 /// `wrapColumn` attributes of 0, and an empty `elementNesting`
267 /// attribute. Optionally specify an `allocator` (e.g., the address of
268 /// a `bslma::Allocator` object) to supply memory; otherwise, the
269 /// default allocator is used.
270 explicit Formatter_PrettyImplState(const allocator_type& allocator);
271
272 /// Create a `Formatter_PrettyImplState` having an `id` attribute of
273 /// `Id::e_AT_START`, the specified `indentLevel`, the specified
274 /// `spacesPerLevel`, and the specified `wrapColumn`, a `column`
275 /// attribute of 0, and an empty `elementNesting` attribute. Optionally
276 /// specify an `allocator` (e.g., the address of a `bslma::Allocator`
277 /// object) to supply memory; otherwise, the default allocator is used.
279 int indentLevel,
280 int spacesPerLevel,
281 int wrapColumn,
282 const allocator_type& allocator = allocator_type());
283
284 /// Create a `Formatter_PrettyImplState` having the specified `id`,
285 /// `indentLevel`, `spacesPerLevel`, `column`, `wrapColumn`, and
286 /// `elementNesting` attributes. Optionally specify an `allocator`
287 /// (e.g., the address of a `bslma::Allocator` object) to supply memory;
288 /// otherwise, the default allocator is used.
290 Id::Enum id,
291 int indentLevel,
292 int spacesPerLevel,
293 int column,
294 int wrapColumn,
296 const allocator_type& allocator = allocator_type());
297
298 /// Create a `Formatter_PrettyImplState` object having the same value as
299 /// the specified `original` object. Optionally specify an `allocator`
300 /// (e.g., the address of a `bslma::Allocator` object) to supply memory;
301 /// otherwise, the default allocator is used.
303 const Formatter_PrettyImplState& original,
304 const allocator_type& allocator = allocator_type());
305
306 // MANIPULATORS
307
308 /// Return a reference providing modifiable access to the `column`
309 /// attribute of this object.
310 int& column();
311
312 /// Return a reference providing modifiable access to the
313 /// `elementNesting` attribute of this object.
315
316 /// Return a reference providing modifiable access to the `id` attribute
317 /// of this object.
318 Id::Enum& id();
319
320 /// Return a reference providing modifiable access to the `indentLevel`
321 /// attribute of this object.
322 int& indentLevel();
323
324 /// Return a reference providing modifiable access to the
325 /// `spacesPerLevel` attribute of this object.
326 int& spacesPerLevel();
327
328 /// Return a reference providing modifiable access to the `wrapColumn`
329 /// attribute of this object.
330 int& wrapColumn();
331
332 // ACCESSORS
333
334 /// Return a reference providing non-modifiable access to the `column`
335 /// attribute of this object.
336 const int& column() const;
337
338 /// Return a reference providing non-modifiable access to the
339 /// `elementNesting` attribute of this object.
341
342 /// Return the allocator associated with this object.
344
345 /// Return a reference providing non-modifiable access to the `id`
346 /// attribute of this object.
347 const Id::Enum& id() const;
348
349 /// Return a reference providing non-modifiable access to the
350 /// `indentLevel` attribute of this object.
351 const int& indentLevel() const;
352
353 /// Return a reference providing non-modifiable access to the
354 /// `spacesPerLevel` attribute of this object.
355 const int& spacesPerLevel() const;
356
357 /// Return a reference providing non-modifiable access to the
358 /// `wrapColumn` attribute of this object.
359 const int& wrapColumn() const;
360};
361
362 // ==============================
363 // class Formatter_PrettyImplUtil
364 // ==============================
365
366/// This utility `struct` provides a namespace for a suite of operations
367/// used to pretty-print XML documents given a sequence of tokens to emit.
368/// Together with `Formatter_PrettyImplState`, this `struct` provides an
369/// implementation of a state machine for such pretty-printing.
371
372 // TYPES
376
377 private:
378 // PRIVATE TYPES
379 enum {
380 k_VALUE_STRING_BUFFER_SIZE = 256,
381
382 k_INFINITE_WRAP_COLUMN = 0
383 };
384
386 BufferedAllocator;
387
388 // PRIVATE CLASS METHODS
389
390 /// Add an attribute of the specified `name` and `value` to the
391 /// currently open element in the specified `stream`, with formatting
392 /// depending on the specified `state`, and update the `state`
393 /// accordingly. Precede this name="value" pair with a single space.
394 /// Wrap line (write the attribute on next line with proper
395 /// indentation), if the length of name="value" is too long. `value` is
396 /// truncated at any invalid UTF-8 byte-sequence or any control
397 /// character. The list of invalid control characters includes
398 /// characters in the range `[0x00, 0x20)` and `0x7F` (DEL) but does not
399 /// include `0x9`, `0xA`, and `0x0D`. The five special characters:
400 /// apostrophe, double quote, ampersand, less than, and greater than are
401 /// escaped in the output XML. The behavior is undefined unless the
402 /// last manipulator was `openElement` or `addAttribute`.
403 static void addAttributeImpl(bsl::ostream& stream,
404 State *state,
405 const bsl::string_view& name,
406 const bsl::string_view& value);
407
408 /// Write the specified `openMarker`, `comment`, and then `closeMarker`
409 /// into the specified `stream`, with formatting depending on the
410 /// specified `state`, and update the `state` accordingly. If an
411 /// element-opening tag is not completed with a `>`, `addCommentImpl`
412 /// will add `>`.
413 static void addCommentImpl(bsl::ostream& stream,
414 State *state,
415 const bsl::string_view& comment,
416 const bsl::string_view& openMarker,
417 const bsl::string_view& closeMarker);
418
419 static void addCommentOnNewLineImpl(bsl::ostream& stream,
420 State *state,
421 const bsl::string_view& comment,
422 const bsl::string_view& openMarker,
423 const bsl::string_view& closeMarker);
424 /// Write the specified `openMarker`, `comment`, and then `closeMarker`
425 /// into the specified `stream` on their own line, with formatting
426 /// depending on the specified `state`, and update the `state`
427 /// accordingly. If an element-opening tag is not completed with a `>`,
428 /// `addCommentImpl` will add `>`.
429
430 static void addDataImpl(bsl::ostream& stream,
431 State *state,
432 const bsl::string_view& value);
433
434 /// Add the specified `value` as the data content to the specified
435 /// `stream`, with formatting depending on the specified `state`, and
436 /// update `state` accordingly. `addListData` prefixes the `value` with
437 /// a space(`0x20`) unless the data being added is the first data on a
438 /// line. In the case of `addData`, perform no line-wrapping or
439 /// indentation as if the whitespace constraint were always
440 /// `BAEXML_PRESERVE_WHITESPACE` in `openElement`, with the only
441 /// exception that an initial newline and an initial indent is added
442 /// when `openElement` specifies `BAEXML_NEWLINE_INDENT` option. In the
443 /// case of `addListData`, when adding the data makes the line too long,
444 /// perform line-wrapping and indentation as determined by the
445 /// whitespace constraint used when the current element is opened with
446 /// `openElement`. `value` is truncated at any invalid UTF-8
447 /// byte-sequence or any control character. The list of invalid control
448 /// characters includes characters in the range `[0x00, 0x20)` and
449 /// `0x7F` (DEL) but does not include `0x9`, `0xA`, and `0x0D`. The
450 /// five special characters: apostrophe, double quote, ampersand, less
451 /// than, and greater than are escaped in the output XML. The behavior
452 /// is undefined if the call is made when there are no opened elements.
453 static void addListDataImpl(bsl::ostream& stream,
454 State *state,
455 const bsl::string_view& value);
456
457 public:
458 // CLASS METHODS
459
460 /// Add an attribute of the specified `name` and specified `value` to
461 /// the currently open element in the specified `stream`, with
462 /// formatting depending on the specified `state`, and update the
463 /// `state` accordingly. Return the `stream`. `value` can be of the
464 /// following types: `char`, `short`, `int`, `bsls::Types::Int64`,
465 /// `float`, `double`, `bsl::string`, `bdlt::Datetime`, `bdlt::Date`,
466 /// and `bdlt::Time`. Precede this name="value" pair with a single
467 /// space. Wrap line (write the attribute on next line with proper
468 /// indentation), if the length of name="value" is too long. Optionally
469 /// specify `formattingMode` and `encoderOptions` to control the
470 /// formatting of `value`. If `value` is of type `bsl::string`, it is
471 /// truncated at any invalid UTF-8 byte-sequence or any control
472 /// character. The list of invalid control characters includes
473 /// characters in the range `[0x00, 0x20)` and `0x7F` (DEL) but does not
474 /// include `0x9`, `0xA`, and `0x0D`. The five special characters:
475 /// apostrophe, double quote, ampersand, less than, and greater than are
476 /// escaped in the output XML. If `value` is of type `char`, it is cast
477 /// to a signed byte value with a range `[ -128 .. 127 ]`. The
478 /// behavior is undefined unless the last manipulator was `openElement`
479 /// or `addAttribute`.
480 template <class VALUE_TYPE>
481 static bsl::ostream& addAttribute(
482 bsl::ostream& stream,
483 State *state,
484 const bsl::string_view& name,
485 const VALUE_TYPE& value,
486 int formattingMode = 0,
487 const EncoderOptions& encoderOptions = EncoderOptions());
488
489 /// Insert one or two newline characters into the specified `stream`
490 /// stream such that a blank line results, depending on the specified
491 /// `state`, and update the `state` accordingly. Return the `stream`.
492 /// If the last output was a newline, then only one newline is added,
493 /// otherwise two newlines are added. If following a call to
494 /// `openElement`, or `addAttribute`, add a closing `>` to the opened
495 /// tag.
496 static bsl::ostream& addBlankLine(bsl::ostream& stream, State *state);
497
498 /// @deprecated Use @ref addValidComment instead.
499 ///
500 /// Write the specified `comment` into the specified `stream`, with
501 /// formatting depending on the specified `state`, and update the
502 /// `state` accordingly. Return the `stream`. The optionally specified
503 /// `forceNewline`, if true, forces to start a new line solely for the
504 /// comment if it's not on a new line already. Otherwise, comments
505 /// continue on current line. If an element-opening tag is not
506 /// completed with a `>`, `addComment` will add `>`.
507 static bsl::ostream& addComment(
508 bsl::ostream& stream,
509 State *state,
510 const bsl::string_view& comment,
511 bool forceNewline = true);
512
513 /// Add the specified `value` as the data content to the specified
514 /// `stream`, with formatting depending on the specified `state`, and
515 /// update `state` accordingly. Return the `stream`. Return the
516 /// `stream`. `value` can be of the following types: `char`, `short`,
517 /// `int`, `bsls::Types::Int64`, `float`, `double`, `bsl::string`,
518 /// `bdlt::Datetime`, `bdlt::Date`, and `bdlt::Time`. Perform no
519 /// line-wrapping or indentation as if the whitespace constraint were
520 /// always `BAEXML_PRESERVE_WHITESPACE` in `openElement`, with the only
521 /// exception that an initial newline and an initial indent is added
522 /// when `openElement` specifies `BAEXML_NEWLINE_INDENT` option. If
523 /// `value` is of type `bsl::string`, it is truncated at any invalid
524 /// UTF-8 byte-sequence or any control character. The list of invalid
525 /// control characters includes characters in the range `[0x00, 0x20)`
526 /// and `0x7F` (DEL) but does not include `0x9`, `0xA`, and `0x0D`. The
527 /// five special characters: apostrophe, double quote, ampersand, less
528 /// than, and greater than are escaped in the output XML. If `value` is
529 /// of type `char`, it is cast to a signed byte value with a range of '[
530 /// -128 .. 127 ]`. Optionally specify the `formattingMode' and
531 /// `encoderOptions` to specify the format used to encode `value`. The
532 /// behavior is undefined if the call is made when there are no opened
533 /// elements.
534 template <class VALUE_TYPE>
535 static bsl::ostream& addData(
536 bsl::ostream& stream,
537 State *state,
538 const VALUE_TYPE& value,
539 int formattingMode = 0,
540 const EncoderOptions& encoderOptions = EncoderOptions());
541
542 /// Add element of the specified `name` and the specified `value` as the
543 /// data content to the specified `stream`, with formatting depending on
544 /// the specified `state` and the optionally specified `encoderOptions`,
545 /// and update `state` accordingly. Return the `stream`. This has the
546 /// same effect as calling the following sequence: 'openElement(name);
547 /// addData(value), closeElement(name);'. Optionally specify the
548 /// `formattingMode`.
549 template <class TYPE>
550 static bsl::ostream& addElementAndData(
551 bsl::ostream& stream,
552 State *state,
553 const bsl::string_view& name,
554 const TYPE& value,
555 int formattingMode = 0,
556 const EncoderOptions& encoderOptions = EncoderOptions());
557
558 /// Add XML header with optionally specified `encoding` to the specified
559 /// `stream`, with formatting depending on the specified `state`, and
560 /// update `state` accordingly. Return the `stream`. Version is always
561 /// "1.0". The behavior is undefined unless `addHeader` is the first
562 /// manipulator (with the exception of `rawOutputStream`) after
563 /// construction or `reset`.
564 static bsl::ostream& addHeader(bsl::ostream& stream,
565 State *state,
566 const bsl::string_view& encoding);
567
568 /// Add the specified `value` as the data content to the specified
569 /// `stream`, with formatting depending on the specified `state`, and
570 /// update `state` accordingly. Return the `stream`. `value` can be of
571 /// the following types: `char`, `short`, `int`, `bsls::Types::Int64`,
572 /// `float`, `double`, `bsl::string`, `bdlt::Datetime`, `bdlt::Date`,
573 /// and `bdlt::Time`. Prefix the `value` with a space(`0x20`) unless
574 /// the data being added is the first data on a line. When adding the
575 /// data makes the line too long, perform line-wrapping and indentation
576 /// as determined by the whitespace constraint used when the current
577 /// element is opened with `openElement`. If `value` is of type
578 /// `bsl::string`, it is truncated at any invalid UTF-8 byte-sequence or
579 /// any control character. The list of invalid control characters
580 /// includes characters in the range `[0x00, 0x20)` and `0x7F` (DEL) but
581 /// does not include `0x9`, `0xA`, and `0x0D`. The five special
582 /// characters: apostrophe, double quote, ampersand, less than, and
583 /// greater than are escaped in the output XML. If `value` is of type
584 /// `char`, it is cast to a signed byte value with a range of '[ -128 ..
585 /// 127 ]`. Optionally specify the `formattingMode' and
586 /// `encoderOptions` to specify the format used to encode `value`. The
587 /// behavior is undefined if the call is made when there are no opened
588 /// elements.
589 template <class VALUE_TYPE>
590 static bsl::ostream& addListData(
591 bsl::ostream& stream,
592 State *state,
593 const VALUE_TYPE& value,
594 int formattingMode = 0,
595 const EncoderOptions& encoderOptions = EncoderOptions());
596
597 /// Insert a literal newline into the XML output of the specified
598 /// `stream`, with formatting depending on the specified `state`, and
599 /// update `state` accordingly. Return the `stream`. If following a
600 /// call to `openElement`, or `addAttribute`, add a closing `>` to the
601 /// opened tag.
602 static bsl::ostream& addNewline(bsl::ostream& stream, State *state);
603
604 /// Write the specified `comment` into the specified `stream`, with
605 /// formatting depending on the specified `state`, and update the
606 /// `state` accordingly. If the optionally specified `forceNewline` is
607 /// `true` then a new line is inserted for comments not already on a new
608 /// line. Also optionally specify an `omitEnclosingWhitespace` that
609 /// specifies if a space character should be omitted before and after
610 /// `comment`. If `omitEnclosingWhitespace` is not specified then a
611 /// space character is inserted before and after `comment`. Return 0 on
612 /// success, and non-zero value otherwise. Note that a non-zero return
613 /// value is returned if either `comment` contains `--` or if
614 /// `omitEnclosingWhitespace` is `true` and `comment` ends with `-`.
615 /// Also note that if an element-opening tag is not completed with a
616 /// `>`, `addValidComment` will add `>`.
617 static int addValidComment(
618 bsl::ostream& stream,
619 State *state,
620 const bsl::string_view& comment,
621 bool forceNewline = true,
622 bool omitEnclosingWhitespace = false);
623
624 /// Decrement the indent level and add the closing tag for the element
625 /// of the specified `name` to the specified `stream`, with formatting
626 /// depending on the specified `state`, and update `state` accordingly.
627 /// Return the `stream`. If the element does not have content, write
628 /// `/>` and a newline into stream. Otherwise, write `</name>` and a
629 /// newline. If this `</name>` does not share the same line with data,
630 /// or it follows another element's closing tag, indent properly before
631 /// writing `</name>` and the newline. If `name` is root element, flush
632 /// the output stream. The behavior is undefined if `name` is not the
633 /// most recently opened element that's yet to be closed.
634 static bsl::ostream& closeElement(bsl::ostream& stream,
635 State *state,
636 const bsl::string_view& name);
637
638 /// Insert the closing `>` if there is an incomplete tag, and flush the
639 /// specified output `stream`, with formatting depending on the
640 /// specified `state`, and update `state` accordingly. Return the
641 /// `stream`.
642 static bsl::ostream& flush(bsl::ostream& stream, State *state);
643
644 /// Open an element of the specified `name` at current indent level with
645 /// the optionally specified whitespace constraint `whitespaceMode` for
646 /// its textual data to the specified `stream`, with formatting
647 /// depending on the specified `state`, and update `state` accordingly,
648 /// incrementing the indent level. Return the `stream`.
649 /// `whitespaceMode` constrains how textual data is written with
650 /// `addListData` for the current element, but not its nested elements.
651 /// The behavior is undefined if `openElement` is called after the root
652 /// element is closed and there is no subsequent call to `reset`.
653 static bsl::ostream&
654 openElement(bsl::ostream& stream,
655 State *state,
656 const bsl::string_view& name,
657 WhitespaceType::Enum whitespaceMode =
659
660 /// Reset the specified formatter `state` such that it can be used to
661 /// format a new XML document as if the formatter were just constructed
662 static void reset(State *state);
663};
664
665// ============================================================================
666// INLINE DEFINITIONS
667// ============================================================================
668
669 // -------------------------------
670 // class Formatter_PrettyImplState
671 // -------------------------------
672
673// CREATORS
674inline
676: d_id(Id::e_AT_START)
677, d_indentLevel(0)
678, d_spacesPerLevel(0)
679, d_column(0)
680, d_wrapColumn(0)
681, d_elementNesting()
682{
683}
684
685inline
687 const allocator_type& allocator)
688: d_id(Id::e_AT_START)
689, d_indentLevel(0)
690, d_spacesPerLevel(0)
691, d_column(0)
692, d_wrapColumn(0)
693, d_elementNesting(allocator)
694{
695}
696
697inline
699 const Formatter_PrettyImplState& original,
700 const allocator_type& allocator)
701: d_id(original.d_id)
702, d_indentLevel(original.d_indentLevel)
703, d_spacesPerLevel(original.d_spacesPerLevel)
704, d_column(original.d_column)
705, d_wrapColumn(original.d_wrapColumn)
706, d_elementNesting(original.d_elementNesting, allocator)
707{
708}
709
710inline
712 int indentLevel,
713 int spacesPerLevel,
714 int wrapColumn,
715 const allocator_type& allocator)
716: d_id(Id::e_AT_START)
717, d_indentLevel(indentLevel)
718, d_spacesPerLevel(spacesPerLevel)
719, d_column()
720, d_wrapColumn(wrapColumn)
721, d_elementNesting(allocator)
722{
723}
724
725inline
727 Id::Enum id,
728 int indentLevel,
729 int spacesPerLevel,
730 int column,
731 int wrapColumn,
732 const bsl::vector<WhitespaceType::Enum>& elementNesting,
733 const allocator_type& allocator)
734: d_id(id)
735, d_indentLevel(indentLevel)
736, d_spacesPerLevel(spacesPerLevel)
737, d_column(column)
738, d_wrapColumn(wrapColumn)
739, d_elementNesting(elementNesting, allocator)
740{
741}
742
743// MANIPULATORS
744inline
746{
747 return d_column;
748}
749
750inline
753{
754 return d_elementNesting;
755}
756
757inline
762
763inline
765{
766 return d_indentLevel;
767}
768
769inline
771{
772 return d_spacesPerLevel;
773}
774
775inline
777{
778 return d_wrapColumn;
779}
780
781// ACCESSORS
782inline
784{
785 return d_column;
786}
787
788inline
791{
792 return d_elementNesting;
793}
794
795inline
798{
799 return d_elementNesting.get_allocator();
800}
801
802inline
804{
805 return d_id;
806}
807
808inline
810{
811 return d_indentLevel;
812}
813
814inline
816{
817 return d_spacesPerLevel;
818}
819
820inline
822{
823 return d_wrapColumn;
824}
825
826 // ------------------------------
827 // class Formatter_PrettyImplUtil
828 // ------------------------------
829
830// CLASS METHODS
831template <class VALUE_TYPE>
833 bsl::ostream& stream,
834 State *state,
835 const bsl::string_view& name,
836 const VALUE_TYPE& value,
837 int formattingMode,
838 const EncoderOptions& encoderOptions)
839{
840 BufferedAllocator allocator;
841 bdlsb::MemOutStreamBuf sb(&allocator);
842 bsl::ostream ss(&sb);
843
844 TypesPrintUtil::print(ss, value, formattingMode, &encoderOptions);
845 if (!ss.good()) {
846 stream.setstate(bsl::ios_base::failbit);
847 return stream; // RETURN
848 }
849
850 const bsl::string_view valueString(sb.data(), sb.length());
851
852 addAttributeImpl(stream, state, name, valueString);
853
854 return stream;
855}
856
857
858template <class VALUE_TYPE>
860 bsl::ostream& stream,
861 State *state,
862 const VALUE_TYPE& valueData,
863 int formattingMode,
864 const EncoderOptions& encoderOptions)
865{
866 BufferedAllocator allocator;
867 bdlsb::MemOutStreamBuf sb(&allocator);
868 bsl::ostream ss(&sb);
869
870 TypesPrintUtil::print(ss, valueData, formattingMode, &encoderOptions);
871 if (!ss.good()) {
872 stream.setstate(bsl::ios_base::failbit);
873 return stream; // RETURN
874 }
875
876 const bsl::string_view valueString(sb.data(), sb.length());
877 addDataImpl(stream, state, valueString);
878 return stream;
879}
880
881template <class TYPE>
883 bsl::ostream& stream,
884 State *state,
885 const bsl::string_view& name,
886 const TYPE& value,
887 int formattingMode,
888 const EncoderOptions& encoderOptions)
889{
891 addData(stream, state, value, formattingMode, encoderOptions);
892 closeElement(stream, state, name);
893 return stream;
894}
895
896template <class VALUE_TYPE>
898 bsl::ostream& stream,
899 State *state,
900 const VALUE_TYPE& value,
901 int formattingMode,
902 const EncoderOptions& encoderOptions)
903{
904 BufferedAllocator allocator;
905 bdlsb::MemOutStreamBuf sb(&allocator);
906 bsl::ostream ss(&sb);
907
908 TypesPrintUtil::print(ss, value, formattingMode, &encoderOptions);
909 if (!ss.good()) {
910 stream.setstate(bsl::ios_base::failbit);
911 return stream; // RETURN
912 }
913
914 const bsl::string_view valueString(sb.data(), sb.length());
915 addListDataImpl(stream, state, valueString);
916 return stream;
917}
918
919inline
921{
922 state->column() = 0;
923 state->id() = StateId::e_AT_START;
924 state->indentLevel() -= static_cast<int>(state->elementNesting().size());
925 state->elementNesting().clear();
926}
927
928} // close package namespace
929
930
931#endif // INCLUDED_BALXML_FORMATTER_PRETTYIMPL
932
933// ----------------------------------------------------------------------------
934// Copyright 2021 Bloomberg Finance L.P.
935//
936// Licensed under the Apache License, Version 2.0 (the "License");
937// you may not use this file except in compliance with the License.
938// You may obtain a copy of the License at
939//
940// http://www.apache.org/licenses/LICENSE-2.0
941//
942// Unless required by applicable law or agreed to in writing, software
943// distributed under the License is distributed on an "AS IS" BASIS,
944// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
945// See the License for the specific language governing permissions and
946// limitations under the License.
947// ----------------------------- END-OF-FILE ----------------------------------
948
949/** @} */
950/** @} */
951/** @} */
Definition balxml_encoderoptions.h:88
Definition balxml_formatter_prettyimpl.h:222
Formatter_PrettyImplState()
Definition balxml_formatter_prettyimpl.h:675
Id::Enum & id()
Definition balxml_formatter_prettyimpl.h:758
bsl::allocator< char > allocator_type
Definition balxml_formatter_prettyimpl.h:226
int & column()
Definition balxml_formatter_prettyimpl.h:745
int & wrapColumn()
Definition balxml_formatter_prettyimpl.h:776
Formatter_PrettyImplStateId Id
Definition balxml_formatter_prettyimpl.h:227
int & spacesPerLevel()
Definition balxml_formatter_prettyimpl.h:770
FormatterWhitespaceType WhitespaceType
Definition balxml_formatter_prettyimpl.h:228
int & indentLevel()
Definition balxml_formatter_prettyimpl.h:764
BSLMF_NESTED_TRAIT_DECLARATION(Formatter_PrettyImplState, bslma::UsesBslmaAllocator)
allocator_type get_allocator() const
Return the allocator associated with this object.
Definition balxml_formatter_prettyimpl.h:797
bsl::vector< WhitespaceType::Enum > & elementNesting()
Definition balxml_formatter_prettyimpl.h:752
Definition bdlma_localsequentialallocator.h:230
Definition bdlsb_memoutstreambuf.h:212
bsl::size_t length() const
Return the number of valid characters in this stream buffer.
Definition bdlsb_memoutstreambuf.h:400
const char * data() const
Definition bdlsb_memoutstreambuf.h:394
Definition bslma_bslallocator.h:580
Definition bslstl_stringview.h:441
size_type size() const BSLS_KEYWORD_NOEXCEPT
Return the number of elements in this vector.
Definition bslstl_vector.h:2664
Definition bslstl_vector.h:1025
allocator_type get_allocator() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_vector.h:4019
void swap(vector &other) BSLS_KEYWORD_NOEXCEPT_SPECIFICATION(AllocatorTraits void clear() BSLS_KEYWORD_NOEXCEPT
Definition bslstl_vector.h:1712
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
Definition balxml_base64parser.h:150
Definition balxml_formatterwhitespacetype.h:68
Enum
Definition balxml_formatterwhitespacetype.h:71
@ e_PRESERVE_WHITESPACE
Definition balxml_formatterwhitespacetype.h:72
Definition balxml_formatter_prettyimpl.h:91
Enum
Definition balxml_formatter_prettyimpl.h:94
@ e_TRAILING_DATA_BETWEEN_TAGS
Definition balxml_formatter_prettyimpl.h:204
@ e_IN_TAG
Definition balxml_formatter_prettyimpl.h:125
@ e_AFTER_START_NO_TAG
Definition balxml_formatter_prettyimpl.h:105
@ e_AT_START
Definition balxml_formatter_prettyimpl.h:98
@ e_FIRST_DATA_BETWEEN_TAGS
Definition balxml_formatter_prettyimpl.h:151
@ e_AT_END
Definition balxml_formatter_prettyimpl.h:209
@ e_FIRST_DATA_AT_LINE_BETWEEN_TAGS
Definition balxml_formatter_prettyimpl.h:183
Definition balxml_formatter_prettyimpl.h:370
static bsl::ostream & addListData(bsl::ostream &stream, State *state, const VALUE_TYPE &value, int formattingMode=0, const EncoderOptions &encoderOptions=EncoderOptions())
Definition balxml_formatter_prettyimpl.h:897
Formatter_PrettyImplState State
Definition balxml_formatter_prettyimpl.h:373
static bsl::ostream & addNewline(bsl::ostream &stream, State *state)
static bsl::ostream & addAttribute(bsl::ostream &stream, State *state, const bsl::string_view &name, const VALUE_TYPE &value, int formattingMode=0, const EncoderOptions &encoderOptions=EncoderOptions())
Definition balxml_formatter_prettyimpl.h:832
static bsl::ostream & flush(bsl::ostream &stream, State *state)
static bsl::ostream & addComment(bsl::ostream &stream, State *state, const bsl::string_view &comment, bool forceNewline=true)
FormatterWhitespaceType WhitespaceType
Definition balxml_formatter_prettyimpl.h:375
static bsl::ostream & addData(bsl::ostream &stream, State *state, const VALUE_TYPE &value, int formattingMode=0, const EncoderOptions &encoderOptions=EncoderOptions())
Definition balxml_formatter_prettyimpl.h:859
static int addValidComment(bsl::ostream &stream, State *state, const bsl::string_view &comment, bool forceNewline=true, bool omitEnclosingWhitespace=false)
static bsl::ostream & openElement(bsl::ostream &stream, State *state, const bsl::string_view &name, WhitespaceType::Enum whitespaceMode=WhitespaceType::e_PRESERVE_WHITESPACE)
static bsl::ostream & addElementAndData(bsl::ostream &stream, State *state, const bsl::string_view &name, const TYPE &value, int formattingMode=0, const EncoderOptions &encoderOptions=EncoderOptions())
Definition balxml_formatter_prettyimpl.h:882
static bsl::ostream & addBlankLine(bsl::ostream &stream, State *state)
static bsl::ostream & addHeader(bsl::ostream &stream, State *state, const bsl::string_view &encoding)
static void reset(State *state)
Definition balxml_formatter_prettyimpl.h:920
static bsl::ostream & closeElement(bsl::ostream &stream, State *state, const bsl::string_view &name)
Formatter_PrettyImplStateId StateId
Definition balxml_formatter_prettyimpl.h:374
static bsl::ostream & print(bsl::ostream &stream, const TYPE &object, int formattingMode, const EncoderOptions *encoderOptions=0)
Definition balxml_typesprintutil.h:1161
Definition bslma_usesbslmaallocator.h:343