BDE 4.39.x Production Release
Loading...
Searching...
No Matches
balxml_encoder.h
Go to the documentation of this file.
1/// @file balxml_encoder.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// balxml_encoder.h -*-C++-*-
8#ifndef INCLUDED_BALXML_ENCODER
9#define INCLUDED_BALXML_ENCODER
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup balxml_encoder balxml_encoder
15/// @brief Provide an XML encoder utility.
16/// @addtogroup bal
17/// @{
18/// @addtogroup balxml
19/// @{
20/// @addtogroup balxml_encoder
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#balxml_encoder-purpose"> Purpose</a>
25/// * <a href="#balxml_encoder-classes"> Classes </a>
26/// * <a href="#balxml_encoder-description"> Description </a>
27/// * <a href="#balxml_encoder-usage"> Usage </a>
28///
29/// # Purpose {#balxml_encoder-purpose}
30/// Provide an XML encoder utility.
31///
32/// # Classes {#balxml_encoder-classes}
33///
34/// - balxml::Encoder: XML encoder utility class
35///
36/// @see balxml_decoder, balber_berencoder
37///
38/// # Description {#balxml_encoder-description}
39/// This component provides a class for encoding value-semantic
40/// objects in XML format. In particular, the `balxml::Encoder` `class`
41/// contains a parameterized `encode` function that encodes a specified
42/// value-semantic object into a specified stream. There are three overloaded
43/// versions of this function:
44///
45/// * writes to an `bsl::streambuf`
46/// * writes to an `bsl::ostream`
47/// * writes to an `balxml::Formatter`
48///
49/// The `encode` function encodes objects in XML format, which is a very useful
50/// format for debugging. For more efficient performance, a binary encoding
51/// (such as BER) should be used.
52///
53/// This component can be used with types supported by the `bdlat` framework.
54/// In particular, types generated by the `bas_codegen.pl` tool can be used.
55///
56/// Note that encoding top-level `array` objects (a.k.a. `sequence-of` types, in
57/// the X.690 spec) is not allowed.
58///
59/// ## Usage {#balxml_encoder-usage}
60///
61///
62/// The following snippets of code illustrate the usage of this component.
63/// Suppose we have an XML schema inside a file named `employee.xsd`:
64/// @code
65/// <?xml version='1.0' encoding='UTF-8'?>
66/// <xs:schema xmlns:xs='http://www.w3.org/2001/XMLSchema'
67/// xmlns:test='http://bloomberg.com/schemas/test'
68/// targetNamespace='http://bloomberg.com/schemas/test'
69/// elementFormDefault='unqualified'>
70///
71/// <xs:complexType name='Address'>
72/// <xs:sequence>
73/// <xs:element name='street' type='xs:string'/>
74/// <xs:element name='city' type='xs:string'/>
75/// <xs:element name='state' type='xs:string'/>
76/// </xs:sequence>
77/// </xs:complexType>
78///
79/// <xs:complexType name='Employee'>
80/// <xs:sequence>
81/// <xs:element name='name' type='xs:string'/>
82/// <xs:element name='homeAddress' type='test:Address'/>
83/// <xs:element name='age' type='xs:int'/>
84/// </xs:sequence>
85/// </xs:complexType>
86/// </xs:schema>
87/// @endcode
88/// Using the `bas_codegen.pl` tool, we generate C++ classes for this schema as
89/// follows:
90/// @code
91/// $ bas_codegen.pl -m msg -p test employee.xsd
92/// @endcode
93/// This tool will generate the header and implementation files for the
94/// @ref test_messages components in the current directory.
95///
96/// Now suppose we wanted to encode information about a particular employee
97/// using XML encoding to the standard output, and using the `PRETTY` option for
98/// formatting the output. The following function will do this:
99/// @code
100/// #include <test_messages.h>
101///
102/// #include <balxml_encoder.h>
103/// #include <balxml_encodingstyle.h>
104///
105/// #include <bsl_iostream.h>
106/// #include <bsl_sstream.h>
107///
108/// using namespace BloombergLP;
109///
110/// void usageExample()
111/// {
112/// test::Employee bob;
113///
114/// bob.name() = "Bob";
115/// bob.homeAddress().street() = "Some Street";
116/// bob.homeAddress().city() = "Some City";
117/// bob.homeAddress().state() = "Some State";
118/// bob.age() = 21;
119///
120/// balxml::EncoderOptions options;
121/// options.setEncodingStyle(balxml::EncodingStyle::BAEXML_PRETTY);
122///
123/// balxml::Encoder encoder(&options, &bsl::cerr, &bsl::cerr);
124///
125/// const bsl::string EXPECTED_OUTPUT =
126/// "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"
127/// "<Employee xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n"
128/// " <name>Bob</name>\n"
129/// " <homeAddress>\n"
130/// " <street>Some Street</street>\n"
131/// " <city>Some City</city>\n"
132/// " <state>Some State</state>\n"
133/// " </homeAddress>\n"
134/// " <age>21</age>\n"
135/// "</Employee>\n";
136///
137/// bsl::ostringstream os;
138/// const int rc = encoder.encodeToStream(os, bob);
139///
140/// assert(0 == rc);
141/// assert(EXPECTED_OUTPUT == os.str());
142/// }
143/// @endcode
144/// @}
145/** @} */
146/** @} */
147
148/** @addtogroup bal
149 * @{
150 */
151/** @addtogroup balxml
152 * @{
153 */
154/** @addtogroup balxml_encoder
155 * @{
156 */
157
158#include <balscm_version.h>
159
161#include <balxml_encodingstyle.h>
162#include <balxml_errorinfo.h> // for Severity
163#include <balxml_formatter.h>
165
166#include <bdlar_refutil.h>
167
168#include <bdlat_arrayfunctions.h>
172#include <bdlat_typecategory.h>
173#include <bdlat_typename.h>
174
176
177#include <bslma_allocator.h>
178#include <bslma_default.h>
180
182
183#include <bsls_assert.h>
184#include <bsls_keyword.h>
185#include <bsls_objectbuffer.h>
186#include <bsls_review.h>
187
188#include <bsl_ostream.h>
189#include <bsl_string.h>
190#include <bsl_vector.h>
191
192
193namespace balxml {
194
195class Encoder_Context;
196
197 // =============
198 // class Encoder
199 // =============
200
201/// This `class` contains the parameterized `encode` functions that encode
202/// `bdlat` types in XML format.
203///
204/// See @ref balxml_encoder
205class Encoder {
206
207 // FRIENDS
208 friend class Encoder_Context;
209
210 private:
211 // PRIVATE TYPES
212
213 /// This class provides stream for logging using
214 /// `bdlsb::MemOutStreamBuf` as a streambuf. The logging stream is
215 /// created on demand, i.e., during the first attempt to log message.
216 class MemOutStream : public bsl::ostream
217 {
219
220 // Not implemented:
221 MemOutStream(const MemOutStream&);
222 MemOutStream& operator=(const MemOutStream&);
223
224 public:
225 // CREATORS
226
227 /// Create a new stream using the optionally specified
228 /// `basicAllocator`.
229 MemOutStream(bslma::Allocator *basicAllocator = 0);
230
231 /// Destroy this stream and release memory back to the allocator.
232 ///
233 /// Although the compiler should generate this destructor
234 /// implicitly, xlC 8 breaks when the destructor is called by name
235 /// unless it is explicitly declared.
236 ~MemOutStream() BSLS_KEYWORD_OVERRIDE;
237
238 // MANIPULATORS
239
240 /// Reset the internal streambuf to empty.
241 void reset();
242
243 // ACCESSORS
244
245 /// Return a pointer to the memory containing the formatted values
246 /// formatted to this stream. The data is not null-terminated
247 /// unless a null character was appended onto this stream.
248 const char *data() const;
249
250 /// Return the length of the formatted data, including null
251 /// characters appended to the stream, if any.
252 int length() const;
253 };
254
255 private:
256 // DATA
257 const EncoderOptions *d_options; // held, not owned
258 bslma::Allocator *d_allocator; // held, not owned
259
260 // placeholder for MemOutStream
261 bsls::ObjectBuffer<MemOutStream> d_logArea;
262
263 // if not zero, log stream was created at the moment of first logging
264 // and must be destroyed
265 MemOutStream *d_logStream;
266
267 ErrorInfo::Severity d_severity; // error severity
268
269 bsl::ostream *d_errorStream; // held, not owned
270 bsl::ostream *d_warningStream; // held, not owned
271
272 // PRIVATE MANIPULATORS
273 ErrorInfo::Severity logError(const char *text,
274 const bsl::string_view& tag,
275 int formattingMode,
276 int index = -1);
277
278 /// Return the stream for logging. Note the if stream has not been
279 /// created yet, it will be created during this call.
280 bsl::ostream& logStream();
281
282 public:
283 // TRAITS
285
286 // CREATORS
287 Encoder(const EncoderOptions *options, bslma::Allocator *basicAllocator);
288
289 /// Construct a encoder object using the specified `options`. Errors
290 /// and warnings will be rendered to the optionally specified
291 /// `errorStream` and `warningStream` respectively.
293 bsl::ostream *errorStream = 0,
294 bsl::ostream *warningStream = 0,
295 bslma::Allocator *basicAllocator = 0);
296
297 /// Destroy this object. This destruction has no effect on objects
298 /// pointed-to by the pointers provided at construction.
300
301 /// Encode the specified non-modifiable `object` to the specified
302 /// `buffer`. Return 0 on success, and a non-zero value otherwise.
303 ///
304 /// \note Note that the encoder will use encoder options, error and warning
305 /// streams specified at the construction time.
306 template <class TYPE>
307 int encode(bsl::streambuf *buffer, const TYPE& object);
308
309 /// Encode the specified non-modifiable `object` to the specified
310 /// `stream`. Return 0 on success, and a non-zero value otherwise.
311 ///
312 /// \note Note that the encoder will use encoder options, error and warning
313 /// streams specified at the construction time.
314 template <class TYPE>
315 int encodeToStream(bsl::ostream& stream, const TYPE& object);
316
317 /// Encode the specified non-modifiable `object` to the specified
318 /// `stream`. Return a reference to `stream`. If an encoding error is detected, `stream.fail()` will be true on return.
319 ///
320 /// \note Note that the
321 /// encoder will use encoder options, error and warning streams
322 /// specified at the construction time. IMPORTANT: The use of
323 /// `stream.fail()` to communicate errors to the caller has two
324 /// consequences: 1) if `stream` is the same as the `errorStream`
325 /// passed to the constructor, then the error message may be suppressed
326 /// (because of the output/error stream becoming invalidated) and 2) it
327 /// is important to call `stream.clear()` after testing the stream
328 /// state. To avoid these issues, we recommend that you use use
329 /// `encodeToStream`, above, instead of this version of `encode`.
330 template <class TYPE>
331 bsl::ostream& encode(bsl::ostream& stream, const TYPE& object);
332
333 /// Encode the specified non-modifiable `object` to the specified
334 /// `formatter`. Return 0 on success, and a non-zero value otherwise.
335 ///
336 /// \note Note that encoder will use encoder options, error and warning
337 /// streams specified at the construction time.
338 template <class TYPE>
339 int encode(Formatter& formatter, const TYPE& object);
340
341 /// Encode the specified non-modifiable `object` to the specified `buffer`. Return 0 on success, and a non-zero value otherwise.
342 ///
343 /// \note Note that the
344 /// encoder will use encoder options, error and warning streams specified
345 /// at the construction time. Also note that this function behaves
346 /// identically to `encode`, but does not instantiate any templates at
347 /// compile time at the expense of being slightly slower at runtime; see
348 /// the `balxml` package documentation for more details.
349 template <class TYPE>
350 int encodeAny(bsl::streambuf *buffer, const TYPE& object);
351 int encodeAny(bsl::streambuf *buffer, const bdlar::AnyConstRef& object);
352
353 /// Encode the specified non-modifiable `object` to the specified `stream`. Return 0 on success, and a non-zero value otherwise.
354 ///
355 /// \note Note that the
356 /// encoder will use encoder options, error and warning streams specified
357 /// at the construction time. Also note that this function behaves
358 /// identically to `encodeToStream`, but does not instantiate any templates
359 /// at compile time at the expense of being slightly slower at runtime; see
360 /// the `balxml` package documentation for more details.
361 template <class TYPE>
362 int encodeAnyToStream(bsl::ostream& stream, const TYPE& object);
363 int encodeAnyToStream(bsl::ostream& stream,
364 const bdlar::AnyConstRef& object);
365
366 /// Encode the specified non-modifiable `object` to the specified `stream`.
367 /// Return a reference to `stream`. If an encoding error is detected, `stream.fail()` will be true on return.
368 ///
369 /// \note Note that the encoder will use
370 /// encoder options, error and warning streams specified at the
371 /// construction time. Also note that this function behaves identically to
372 /// `encode`, but does not instantiate any templates at compile time at the
373 /// expense of being slightly slower at runtime; see the `balxml` package
374 /// documentation for more details.
375 template <class TYPE>
376 bsl::ostream& encodeAny(bsl::ostream& stream, const TYPE& object);
377 bsl::ostream& encodeAny(bsl::ostream& stream,
378 const bdlar::AnyConstRef& object);
379
380 /// Encode the specified non-modifiable `object` to the specified
381 /// `formatter`. Return 0 on success, and a non-zero value otherwise.
382 ///
383 /// \note Note that encoder will use encoder options, error and warning streams
384 /// specified at the construction time. Also note that this function
385 /// behaves identically to `encode`, but does not instantiate any templates
386 /// at compile time at the expense of being slightly slower at runtime; see
387 /// the `balxml` package documentation for more details.
388 template <class TYPE>
389 int encodeAny(Formatter& formatter, const TYPE& object);
390 int encodeAny(Formatter& formatter, const bdlar::AnyConstRef& object);
391
392 //ACCESSORS
393
394 /// Return the encoder options.
395 const EncoderOptions *options() const;
396
397 /// Return `true` if the encoding style in the encoder options is
398 /// defined as `EncodingStyle::BAEXML_COMPACT`, and `false` otherwise.
399 bool isCompact() const;
400
401 /// Return pointer to the error stream.
402 bsl::ostream *errorStream() const;
403
404 /// Return pointer to the warning stream.
405 bsl::ostream *warningStream() const;
406
407 /// Return the severity of the most severe warning or error encountered
408 /// during the last call to the `encode` method. The severity is reset
409 /// each time `encode` is called.
410 ErrorInfo::Severity errorSeverity() const;
411
412 /// Return a string containing any error, warning, or trace messages
413 /// that were logged during the last call to the `encode` method. The
414 /// log is reset each time `encode` is called.
415 bslstl::StringRef loggedMessages() const;
416};
417
418// ---- Anything below this line is implementation specific. Do not use. ----
419
420 // ======================
421 // struct Encoder_Context
422 // ======================
423
424/// This `struct` contains state that is maintained during encoding. It
425/// also contains methods for switching between pretty formatting and
426/// compact formatting, based on the encoding options.
427///
428/// See @ref balxml_encoder
430
431 // DATA
432 Formatter *d_formatter;
433 Encoder *d_encoder;
434
435 private:
436 // NOT IMPLEMENTED
437 Encoder_Context(const Encoder_Context& other);
438 Encoder_Context& operator=(const Encoder_Context& other);
439
440 public:
441 // CREATORS
442 Encoder_Context(Formatter *formatter, Encoder *encoder);
443
444 // MANIPULATORS
445 template <class NAME_TYPE, class VALUE_TYPE>
446 void addAttribute(const NAME_TYPE& name, const VALUE_TYPE& value);
447
448 template<class NAME_TYPE, class VALUE_TYPE>
449 void addAttribute(const NAME_TYPE& name,
450 const VALUE_TYPE& value,
451 int formattingMode);
452
453 template <class NAME_TYPE>
454 void closeElement(const NAME_TYPE& name);
455
456 void invalidate();
457
458 ErrorInfo::Severity logError(const char *text,
459 const bsl::string_view& tag,
460 int formattingMode,
461 int index = -1);
462
463 template <class NAME_TYPE>
464 void openElement(const NAME_TYPE& name);
465
466 bsl::ostream& rawOutputStream();
467
468 // ACCESSORS
469 const EncoderOptions& encoderOptions() const;
470
471 int status() const;
472};
473
474 // =======================================
475 // struct Encoder_OptionsCompatibilityUtil
476 // =======================================
477
478/// Component-private `struct`. Do not use.
479///
480/// This struct provides a namespace for a suite of functions used to
481/// compute the options for the underlying XML formatter used by the
482/// encoder, given the encoder's options.
483///
484/// See @ref balxml_encoder
486
487 private:
488 // PRIVATE CLASS METHODS
489
490 /// Return the value of the `InitialIndentLevel` field for a
491 /// `FormatterOptions` object that corresponds to the specified
492 /// `encoderOptions`, which is 0 if the `EncodingStyle` of
493 /// `encoderOptions` is `EncodingStyle::e_COMPACT`, and is the value of
494 /// `InitialIndentLevel` of `encoderOptions` otherwise.
495 static int getFormatterInitialIndentLevel(
496 const EncoderOptions& encoderOptions);
497
498 /// Return the value of the `SpacesPerLevel` field for a
499 /// `FormatterOptions` object that corresponds to the specified
500 /// `encoderOptions`, which is 0 if the `EncodingStyle` of
501 /// `encoderOptions` is `EncodingStyle::e_COMPACT`, and is the value of
502 /// `SpacesPerLevel` of `encoderOptions` otherwise.
503 static int getFormatterSpacesPerLevel(
504 const EncoderOptions& encoderOptions);
505
506 /// Return the value of the `WrapColumn` field for a
507 /// `FormatterOptions` object that corresponds to the specified
508 /// `encoderOptions`, which is -1 if the `EncodingStyle` of
509 /// `encoderOptions` is `EncodingStyle::e_COMPACT`, and is the value of
510 /// `WrapColumn` of `encoderOptions` otherwise.
511 static int getFormatterWrapColumn(const EncoderOptions& encoderOptions);
512
513 public:
514 // CLASS METHODS
515
516 /// Load to the specified `formatterIndentLevel`,
517 /// `formatterSpacesPerLevel`, and `formatterWrapColumn`, the number of
518 /// spaces to indent the first element in the XML document, the number
519 /// of spaces to use for indenting each level of nesting in the
520 /// document, and the maximum horizontal column number after which the
521 /// encoder should insert a line break, respectively, based on the
522 /// specified `encoderOptions`. Load to the specified
523 /// `formatterOptions` the options that the formatter should use to emit
524 /// XML, based on the `encoderOptions`.
525 ///
526 /// \pre The behavior is undefined unless `formatterOptions` has the default value.
528 int *formatterIndentLevel,
529 int *formatterSpacesPerLevel,
530 int *formatterWrapColumn,
531 EncoderOptions *formatterOptions,
532 const EncoderOptions& encoderOptions);
533};
534
535 // ==========================
536 // class Encoder_EncodeObject
537 // ==========================
538
539/// Component-private class. Do not use.
540///
541/// This struct encodes an object *with* enclosing tags. Compared to the
542/// `EncoderUtil_EncodeValue` class below, this class prefixes the value
543/// with an opening tag, and suffixes the value with a closing tag. In
544/// pseudocode, this is equivalent to:
545/// @code
546/// openTag()
547/// Encoder_EncodeValue()
548/// closeTag()
549/// @endcode
550/// There is an overloaded version of `bsl::vector<char>` because, based on
551/// the formatting mode, this class needs to switch between encoding the
552/// value in a single tag (i.e., when using BASE64, TEXT, IS_LIST or HEX)
553/// and encoding the value in multiple tags (i.e., when repetition is used).
554///
555/// See @ref balxml_encoder
557
558 // PRIVATE TYPES
559 struct CanBeListOrRepetition { };
560 struct CanBeRepetitionOnly { };
561
562 // PRIVATE DATA MEMBERS
563 Encoder_Context *d_context_p;
564
565 public:
566 // IMPLEMENTATION MANIPULATORS
567 template <class TYPE>
568 int executeImp(const TYPE& object,
569 const bsl::string_view& tag,
570 int formattingMode,
571 bool isMultiple,
573
574 template <class TYPE>
575 int executeImp(const TYPE& object,
576 const bsl::string_view& tag,
577 int formattingMode,
578 bool isMultiple,
580
581 template <class TYPE>
582 int executeImp(const TYPE& object,
583 const bsl::string_view& tag,
584 int formattingMode,
585 bool isMultiple,
587
588 template <class TYPE, class ANY_CATEGORY>
589 int executeImp(const TYPE& object,
590 const bsl::string_view& tag,
591 int formattingMode,
592 bool isMultiple,
593 ANY_CATEGORY);
594
595 int executeImp(const bsl::vector<char>& object,
596 const bsl::string_view& tag,
597 int formattingMode,
598 bool isMultiple,
600
601 template <class TYPE>
602 int executeArrayListImp(const TYPE& object, const bsl::string_view& tag);
603
604 template <class TYPE>
605 int executeArrayRepetitionImp(const TYPE& object,
606 const bsl::string_view& tag,
607 int formattingMode);
608
609 private:
610 // NOT IMPLEMENTED
613
614 public:
615 // CREATORS
616 explicit Encoder_EncodeObject(Encoder_Context *context);
617
618 // Using compiler generated destructor:
619 // ~Encoder_EncodeObject();
620
621 // MANIPULATORS
622 template <class TYPE, class INFO_TYPE>
623 int operator()(const TYPE& object, const INFO_TYPE& info);
624
625 template <class TYPE>
626 int execute(const TYPE& object,
627 const bsl::string_view& tag,
628 int formattingMode,
629 bool isMultiple);
630};
631
632 // =========================
633 // class Encoder_EncodeValue
634 // =========================
635
636/// Component-private class. Do not use.
637///
638/// This class just encodes a value *without* any enclosing tags.
639///
640/// See @ref balxml_encoder
642
643 // PRIVATE DATA MEMBERS
644 Encoder_Context *d_context_p;
645
646 public:
647 // IMPLEMENTATION MANIPULATORS
648 template <class TYPE>
649 int executeImp(const TYPE& object,
650 int formattingMode,
652
653 template <class TYPE>
654 int executeImp(const TYPE& object,
655 int formattingMode,
657
658 template <class TYPE>
659 int executeImp(const TYPE& object,
660 int formattingMode,
662
663 template <class TYPE, class ANY_CATEGORY>
664 int executeImp(const TYPE& object, int formattingMode, ANY_CATEGORY);
665
666 private:
667 // NOT IMPLEMENTED
669 Encoder_EncodeValue& operator=(const Encoder_EncodeValue&);
670
671 public:
672 // CREATORS
673 explicit Encoder_EncodeValue(Encoder_Context *context);
674
675 // Using compiler generated destructor:
676 // ~Encoder_EncodeValue();
677
678 // MANIPULATORS
679 template <class TYPE, class INFO_TYPE>
680 int operator()(const TYPE& object, const INFO_TYPE& info);
681
682 template <class TYPE>
683 int execute(const TYPE& object, int formattingMode);
684};
685
686 // ===============================
687 // class Encoder_SequenceFirstPass
688 // ===============================
689
690/// Component private class. Do not use.
691///
692/// This class is used as the first pass when encoding elements of a
693/// sequence. It basically does two things:
694/// o encode elements with the
695/// `bdlat_FormattingMode::e_IS_ATTRIBUTE` flag using the
696/// `Formatter::addAttribute` method.
697/// o looks for an element with the
698/// `bdlat_FormattingMode::e_IS_SIMPLE_CONTENT` flag and, if
699/// found, provides accessors to obtain the `id` of the element.
700///
701/// \note Note that the behavior is undefined unless there is only one
702/// element with `IS_SIMPLE_CONTENT` flag and, if this element exist,
703/// all other elements must have `IS_ATTRIBUTE` flag.
704///
705/// See @ref balxml_encoder
707
708 // PRIVATE DATA MEMBERS
709 Encoder_Context *d_context_p; // held, not owned
710 bool d_hasSubElements; // true if an element with
711 // neither 'IS_ATTRIBUTE' nor
712 // 'IS_SIMPLE_CONTENT' is
713 // found
714 bdlb::NullableValue<int> d_simpleContentId; // the 'id' of the element
715 // with 'IS_SIMPLE_CONTENT'
716 // flag, if found
717
718 public:
719 // IMPLEMENTATION MANIPULATORS
720
721 /// Add an attribute with the specified `name`, the value of the
722 /// specified `object`, using the specified `formattingMode`.
723 ///
724 /// \note Note that the last argument is used for overloading purposes only.
725 template <class TYPE>
726 int addAttributeImp(const TYPE& object,
727 const bsl::string_view& name,
728 int formattingMode,
730 template <class TYPE>
731 int addAttributeImp(const TYPE& object,
732 const bsl::string_view& name,
733 int formattingMode,
735 template <class TYPE, class ANY_CATEGORY>
736 int addAttributeImp(const TYPE& object,
737 const bsl::string_view& name,
738 int formattingMode,
739 ANY_CATEGORY);
740
741 /// Add an attribute with the specified `name`, the value of the
742 /// specified `object`, using the specified `formattingMode`.
743 template <class TYPE>
744 int addAttribute(const TYPE& object,
745 const bsl::string_view& name,
746 int formattingMode);
747
748 private:
749 // NOT IMPLEMENTED
752
753 public:
754 // CREATORS
755
756 /// Create a visitor for first pass for sequences.
758
759 // Generated by compiler:
760 // ~Encoder_SequenceFirstPass();
761
762 // MANIPULATORS
763
764 /// Called back when an element is visited.
765 template <class TYPE, class INFO_TYPE>
766 int operator()(const TYPE& object, const INFO_TYPE& info);
767
768 // ACCESSORS
769
770 /// Return true if a sub-element is found, and false otherwise.
771 const bool& hasSubElements() const;
772
773 /// Return a null value if there is no element with `IS_SIMPLE_CONTENT`
774 /// flag, or a non-null value with the integer `id` of the element
775 /// otherwise.
776 const bdlb::NullableValue<int>& simpleContentId() const;
777};
778
779 // ================================
780 // class Encoder_SequenceSecondPass
781 // ================================
782
783/// Component-private class. Do not use.
784///
785/// This class is used as the second pass when encoding elements of a
786/// sequence. It basically calls `EncoderUtil_EncodeObject` for elements that do not have `IS_ATTRIBUTE` flag.
787///
788/// \note Note that the behavior is
789/// undefined if there is an element with the `IS_SIMPLE_CONTENT` flag.
790///
791/// See @ref balxml_encoder
793
794 // DATA
795
796 // functor used to encode sub-elements
797 Encoder_EncodeObject d_encodeObjectFunctor;
798
799 private:
800 // NOT IMPLEMENTED
803
804 public:
805 // CREATORS
806
807 /// Create a visitor for the second pass for sequences.
808 explicit
810
811 // Generated by compiler:
812 // ~Encoder_SequenceSecondPass();
813
814 // MANIPULATORS
815
816 /// Called back when an element is visited.
817 template <class TYPE, class INFO_TYPE>
818 int operator()(const TYPE& object, const INFO_TYPE& info);
819};
820
821// ============================================================================
822// PROXY CLASSES
823// ============================================================================
824
825 // ========================================
826 // struct Encoder_EncodeObject_executeProxy
827 // ========================================
828
829/// Component-private struct. Do not use.
830///
831/// See @ref balxml_encoder
833
834 // DATA MEMBERS
838 bool d_isMultiple; // = false
839
840 // CREATORS
841
842 // Creators have been omitted to allow simple static initialization of this
843 // struct.
844
845 // FUNCTIONS
846 template <class TYPE>
847 inline
848 int operator()(const TYPE& object)
849 {
850 return d_instance_p->execute(object,
851 *d_tag_p,
852 d_formattingMode,
853 d_isMultiple);
854 }
855};
856
857 // ===========================================
858 // struct Encoder_EncodeObject_executeImpProxy
859 // ===========================================
860
861/// Component-private struct. Do not use.
862///
863/// See @ref balxml_encoder
865
866 // DATA
871
872 // CREATORS
873
874 // Creators have been omitted to allow simple static initialization of this
875 // struct.
876
877 // FUNCTIONS
878 template <class TYPE>
879 inline
880 int operator()(const TYPE&, bslmf::Nil)
881 {
883 return -1;
884 }
885
886 template <class TYPE, class ANY_CATEGORY>
887 inline
888 int operator()(const TYPE& object, ANY_CATEGORY category)
889 {
890 return d_instance_p->executeImp(object,
891 *d_tag_p,
892 d_formattingMode,
893 d_isMultiple,
894 category);
895 }
896};
897
898 // ==========================================
899 // struct Encoder_EncodeValue_executeImpProxy
900 // ==========================================
901
902/// Component-private struct. Do not use.
903///
904/// See @ref balxml_encoder
906
907 // DATA MEMBERS
910
911 // CREATORS
912
913 // Creators have been omitted to allow simple static initialization of this
914 // struct.
915
916 // FUNCTIONS
917 template <class TYPE>
918 inline
919 int operator()(const TYPE&, bslmf::Nil)
920 {
922 return -1;
923 }
924
925 template <class TYPE, class ANY_CATEGORY>
926 inline
927 int operator()(const TYPE& object, ANY_CATEGORY category)
928 {
929 return d_instance_p->executeImp(object, d_formattingMode, category);
930 }
931};
932
933 // ==================================================
934 // struct Encoder_SequenceFirstPass_addAttributeProxy
935 // ==================================================
936
937/// Component-private struct. Do not use.
938///
939/// See @ref balxml_encoder
941
942 // DATA MEMBERS
946
947 // CREATORS
948
949 // Creators have been omitted to allow simple static initialization of this
950 // struct.
951
952 // FUNCTIONS
953 template <class TYPE>
954 inline
955 int operator()(const TYPE& object)
956 {
957 return d_instance_p->addAttribute(object, *d_name_p, d_formattingMode);
958 }
959};
960
961 // =====================================================
962 // struct Encoder_SequenceFirstPass_addAttributeImpProxy
963 // =====================================================
964
965/// Component-private struct. Do not use.
966///
967/// See @ref balxml_encoder
969
970 // DATA MEMBERS
974
975 // CREATORS
976
977 // Creators have been omitted to allow simple static initialization of this
978 // struct.
979
980 // FUNCTIONS
981 template <class TYPE>
982 inline
983 int operator()(const TYPE&, bslmf::Nil)
984 {
986 return -1;
987 }
988
989 template <class TYPE, class ANY_CATEGORY>
990 inline
991 int operator()(const TYPE& object, ANY_CATEGORY category)
992 {
993 return d_instance_p->addAttributeImp(object,
994 *d_name_p,
995 d_formattingMode,
996 category);
997 }
998};
999} // close package namespace
1000
1001// ============================================================================
1002// INLINE DEFINITIONS
1003// ============================================================================
1004
1005namespace balxml {
1006
1007 // ------------------------------
1008 // class BerEncoder::MemOutStream
1009 // ------------------------------
1010
1011inline
1012Encoder::MemOutStream::MemOutStream(bslma::Allocator *basicAllocator)
1013: bsl::ostream(0)
1014, d_sb(bslma::Default::allocator(basicAllocator))
1015{
1016 rdbuf(&d_sb);
1017}
1018
1019// MANIPULATORS
1020inline
1021void Encoder::MemOutStream::reset()
1022{
1023 d_sb.reset();
1024}
1025
1026// ACCESSORS
1027inline
1028const char *Encoder::MemOutStream::data() const
1029{
1030 return d_sb.data();
1031}
1032
1033inline
1034int Encoder::MemOutStream::length() const
1035{
1036 return (int)d_sb.length();
1037}
1038
1039 // -------------
1040 // class Encoder
1041 // -------------
1042
1043inline
1045{
1046 return EncodingStyle::COMPACT == d_options->encodingStyle();
1047}
1048
1049inline
1051{
1052 return d_options;
1053}
1054
1055inline
1056bsl::ostream *Encoder::errorStream() const
1057{
1058 return d_errorStream;
1059}
1060
1061inline
1062bsl::ostream *Encoder::warningStream() const
1063{
1064 return d_warningStream;
1065}
1066
1067inline
1069{
1070 return d_severity;
1071}
1072
1073inline
1075{
1076 if (d_logStream) {
1077 return bslstl::StringRef(d_logStream->data(), d_logStream->length());
1078 // RETURN
1079 }
1080 return bslstl::StringRef();
1081}
1082
1083inline
1084bsl::ostream& Encoder::logStream()
1085{
1086 if (0 == d_logStream) {
1087 d_logStream = new(d_logArea.buffer()) MemOutStream(d_allocator);
1088 }
1089 return *d_logStream;
1090}
1091
1092template <class TYPE>
1093inline
1094int Encoder::encode(bsl::streambuf *buffer, const TYPE& object)
1095{
1096 int indentLevel = 0;
1097 int spacesPerLevel = 0;
1098 int wrapColumn = 0;
1099
1100 EncoderOptions formatterEncoderOptions;
1102 &indentLevel,
1103 &spacesPerLevel,
1104 &wrapColumn,
1105 &formatterEncoderOptions,
1106 *d_options);
1107
1108 Formatter formatter(buffer,
1109 formatterEncoderOptions,
1110 indentLevel,
1111 spacesPerLevel,
1112 wrapColumn);
1113
1114 const int rc = encode(formatter, object);
1115
1116 buffer->pubsync();
1117
1118 return rc;
1119}
1120
1121template <class TYPE>
1122inline
1123int Encoder::encodeToStream(bsl::ostream& stream, const TYPE& object)
1124{
1125 return encode(stream.rdbuf(), object);
1126}
1127
1128template <class TYPE>
1129inline
1130bsl::ostream& Encoder::encode(bsl::ostream& stream, const TYPE& object)
1131{
1132 int indentLevel = 0;
1133 int spacesPerLevel = 0;
1134 int wrapColumn = 0;
1135
1136 EncoderOptions formatterEncoderOptions;
1138 &indentLevel,
1139 &spacesPerLevel,
1140 &wrapColumn,
1141 &formatterEncoderOptions,
1142 *d_options);
1143
1144 Formatter formatter(stream,
1145 formatterEncoderOptions,
1146 indentLevel,
1147 spacesPerLevel,
1148 wrapColumn);
1149
1150 encode(formatter, object);
1151
1152 stream.flush();
1153
1154 return stream;
1155}
1156
1157template <class TYPE>
1158int Encoder::encode(Formatter& formatter, const TYPE& object)
1159{
1160 d_severity = ErrorInfo::e_NO_ERROR;
1161 if (d_logStream != 0) {
1162 d_logStream->reset();
1163 }
1164
1165 Encoder_Context context(&formatter,this);
1166
1167 if (d_options->outputXMLHeader()) {
1168 formatter.addHeader();
1169 }
1170
1171 const char *tag = d_options->tag().empty()
1172 ? bdlat_TypeName::xsdName(object,
1173 d_options->formattingMode())
1174 : d_options->tag().c_str();
1175
1176 context.openElement(tag);
1177
1178 if (!d_options->objectNamespace().empty()) {
1179
1180 context.addAttribute("xmlns", d_options->objectNamespace());
1181
1182 if (d_options->outputXSIAlias()) {
1183 // Only declare the "xsi" namespace and schema location if an
1184 // object namespace was provided because only then can validation
1185 // happen.
1186 context.addAttribute("xmlns:xsi",
1187 "http://www.w3.org/2001/XMLSchema-instance");
1188
1189 if (!d_options->schemaLocation().empty()) {
1190 context.addAttribute("xsi:schemaLocation",
1191 d_options->objectNamespace()
1192 + " "
1193 + d_options->schemaLocation());
1194 }
1195 }
1196 }
1197 else if (d_options->outputXSIAlias()) {
1198 context.addAttribute("xmlns:xsi",
1199 "http://www.w3.org/2001/XMLSchema-instance");
1200 }
1201
1202 Encoder_EncodeValue encodeValue(&context);
1203
1204 int rc = 0;
1205 if (0 != encodeValue.execute(object,d_options->formattingMode())) {
1206
1207 logError("Failed to encode", tag, d_options->formattingMode());
1208
1209 context.invalidate();
1210 rc = -1;
1211 }
1212 else {
1213 context.closeElement(tag);
1214 }
1215
1216 switch (d_severity) {
1217 case ErrorInfo::e_NO_ERROR: {
1218 } break;
1219 case ErrorInfo::e_WARNING: {
1220 if (d_warningStream) {
1221 *d_warningStream << loggedMessages();
1222 }
1223 } break;
1224 default: {
1225 if (d_errorStream) {
1226 *d_errorStream << loggedMessages();
1227 }
1228 } break;
1229 }
1230 return rc;
1231}
1232
1233template <class TYPE>
1234inline
1235int Encoder::encodeAny(bsl::streambuf *streamBuf, const TYPE& object)
1236{
1237 return encodeAny(streamBuf, bdlar::RefUtil::makeAnyConstRef(object));
1238}
1239
1240template <class TYPE>
1241inline
1242int Encoder::encodeAnyToStream(bsl::ostream& stream, const TYPE& object)
1243{
1244 return encodeAnyToStream(stream, bdlar::RefUtil::makeAnyConstRef(object));
1245}
1246
1247inline
1248int Encoder::encodeAnyToStream(bsl::ostream& stream,
1249 const bdlar::AnyConstRef& object)
1250{
1251 return encodeAny(stream.rdbuf(), object);
1252}
1253
1254template <class TYPE>
1255inline
1256bsl::ostream& Encoder::encodeAny(bsl::ostream& stream, const TYPE& object)
1257{
1258 return encodeAny(stream, bdlar::RefUtil::makeAnyConstRef(object));
1259}
1260
1261template <class TYPE>
1262inline
1263int Encoder::encodeAny(Formatter& formatter, const TYPE& object)
1264{
1265 return encode(formatter, bdlar::RefUtil::makeAnyConstRef(object));
1266}
1267
1268 // ---------------------
1269 // class Encoder_Context
1270 // ---------------------
1271
1272// MANIPULATORS
1273template <class NAME_TYPE, class VALUE_TYPE>
1274inline
1275void Encoder_Context::addAttribute(const NAME_TYPE& name,
1276 const VALUE_TYPE& value)
1277{
1278 d_formatter->addAttribute(name,
1279 value,
1281}
1282
1283template <class NAME_TYPE, class VALUE_TYPE>
1284inline
1285void Encoder_Context::addAttribute(const NAME_TYPE& name,
1286 const VALUE_TYPE& value,
1287 int formattingMode)
1288{
1289 d_formatter->addAttribute(name, value, formattingMode);
1290}
1291
1292template <class NAME_TYPE>
1293inline
1294void Encoder_Context::closeElement(const NAME_TYPE& name)
1295{
1296 d_formatter->closeElement(name);
1297}
1298
1299inline
1301{
1302 rawOutputStream().setstate(bsl::ios_base::failbit);
1303}
1304
1305inline
1307 const char *text,
1308 const bsl::string_view& tag,
1309 int formattingMode,
1310 int index)
1311{
1312 return d_encoder->logError(text, tag, formattingMode, index);
1313}
1314
1315template <class NAME_TYPE>
1316inline
1317void Encoder_Context::openElement(const NAME_TYPE& name)
1318{
1319 d_formatter->openElement(name);
1320}
1321
1322inline
1324{
1325 return d_formatter->rawOutputStream();
1326}
1327
1328// ACCESSORS
1329inline
1331{
1332 return *d_encoder->options();
1333}
1334
1335inline
1337{
1338 return d_formatter->status();
1339}
1340
1341 // --------------------------
1342 // class Encoder_EncodeObject
1343 // --------------------------
1344
1345// IMPLEMENTATION MANIPULATORS
1346template <class TYPE>
1347inline
1349 const bsl::string_view& tag,
1350 int formattingMode,
1351 bool ,
1353{
1354 if (formattingMode & bdlat_FormattingMode::e_LIST) {
1355 return executeArrayListImp(object, tag); // RETURN
1356 }
1357 // else { return ... } removed, to prevent warning with gcc-4.1.1 (reach
1358 // end of non-void function), instead, have unconditional:
1359
1360 return executeArrayRepetitionImp(object, tag, formattingMode);
1361}
1362
1363template <class TYPE>
1364inline
1366 const TYPE& object,
1367 const bsl::string_view& tag,
1368 int formattingMode,
1369 bool isMultiple,
1371{
1372 enum { k_SUCCESS = 0 };
1373
1375 if (formattingMode & bdlat_FormattingMode::e_NILLABLE) {
1376 if ((!d_context_p->encoderOptions().objectNamespace().empty() &&
1377 d_context_p->encoderOptions().outputXSIAlias()) ||
1378 isMultiple) {
1379 // Add the "xsi:nil" attribute for array elements even when
1380 // `outputXSIAlias()` is false; otherwise the number of the
1381 // encoded array elements wiil be different.
1382 d_context_p->openElement(tag);
1383 d_context_p->addAttribute("xsi:nil", "true");
1384 d_context_p->closeElement(tag);
1385 }
1386 }
1387
1388 return d_context_p->status(); // RETURN
1389 }
1390
1392 this,
1393 &tag,
1394 formattingMode,
1395 false
1396 };
1397
1398 return bdlat_NullableValueFunctions::accessValue(object, proxy);
1399}
1400
1401template <class TYPE>
1402inline
1404 const TYPE& object,
1405 const bsl::string_view& tag,
1406 int formattingMode,
1407 bool isMultiple,
1409{
1411 this,
1412 &tag,
1413 formattingMode,
1414 isMultiple
1415 };
1416
1417 return bdlat_TypeCategoryUtil::accessByCategory(object, proxy);
1418}
1419
1420template <class TYPE, class ANY_CATEGORY>
1422 const bsl::string_view& tag,
1423 int formattingMode,
1424 bool ,
1425 ANY_CATEGORY)
1426{
1427 enum { k_FAILURE = -1 };
1428
1429 bool isUntagged = formattingMode & bdlat_FormattingMode::e_UNTAGGED;
1430
1431 if (!isUntagged) {
1432 d_context_p->openElement(tag);
1433 }
1434
1435 Encoder_EncodeValue encodeValue(d_context_p);
1436
1437 if (0 != encodeValue.execute(object, formattingMode)) {
1438 d_context_p->logError("Unable to encode value", tag, formattingMode);
1439 return k_FAILURE; // RETURN
1440 }
1441
1442 if (!isUntagged) {
1443 d_context_p->closeElement(tag);
1444 }
1445
1446 int ret = d_context_p->status();
1447
1448 if (ret) {
1449 d_context_p->logError("Formatter was invalidated for",
1450 tag,
1451 formattingMode);
1452 }
1453
1454 return ret;
1455}
1456
1457template <class TYPE>
1459 const bsl::string_view& tag)
1460{
1461 d_context_p->openElement(tag);
1462
1464 object,
1465 &d_context_p->encoderOptions());
1466
1467 d_context_p->closeElement(tag);
1468
1469 int ret = d_context_p->status();
1470
1471 if (ret) {
1472
1473 d_context_p->logError(
1474 "Error while encoding list for",
1475 tag,
1477 }
1478
1479 return ret;
1480}
1481
1482template <class TYPE>
1484 const TYPE& object,
1485 const bsl::string_view& tag,
1486 int formattingMode)
1487{
1488 enum { k_SUCCESS = 0, k_FAILURE = -1 };
1489
1490 const int size = (int)bdlat_ArrayFunctions::size(object);
1491
1493 { this, &tag, formattingMode, true };
1494
1495 for (int i = 0; i < size; ++i) {
1496 if (0 != bdlat_ArrayFunctions::accessElement(object, proxy, i)) {
1497
1498 d_context_p->logError(
1499 "Error while encoding array element",
1500 tag,
1501 formattingMode,
1502 i);
1503
1504 return k_FAILURE; // RETURN
1505 }
1506 }
1507
1508 return k_SUCCESS;
1509}
1510
1511// CREATORS
1512inline
1513Encoder_EncodeObject::Encoder_EncodeObject(Encoder_Context *context)
1514: d_context_p(context)
1515{
1516 BSLS_ASSERT(d_context_p);
1517}
1518
1519// MANIPULATORS
1520template <class TYPE, class INFO_TYPE>
1521inline
1522int Encoder_EncodeObject::operator()(const TYPE& object, const INFO_TYPE& info)
1523{
1524 bsl::string_view name(info.name(), info.nameLength());
1525
1526 return execute(object, name, info.formattingMode(), false);
1527}
1528
1529template <class TYPE>
1530inline
1531int Encoder_EncodeObject::execute(const TYPE& object,
1532 const bsl::string_view& tag,
1533 int formattingMode,
1534 bool isMultiple)
1535{
1536 typedef typename bdlat_TypeCategory::Select<TYPE>::Type TypeCategory;
1537
1538 return executeImp(object, tag, formattingMode, isMultiple, TypeCategory());
1539}
1540
1541 // -------------------------
1542 // class Encoder_EncodeValue
1543 // -------------------------
1544
1545// IMPLEMENTATION MANIPULATORS
1546template <class TYPE>
1547inline
1549 const TYPE& object,
1550 int formattingMode,
1552{
1553 enum { k_SUCCESS = 0, k_FAILURE = -1 };
1554
1555#if defined(BSLS_ASSERT_SAFE_IS_ACTIVE)
1556 int type = formattingMode & bdlat_FormattingMode::e_TYPE_MASK;
1557
1559#else
1560 (void) formattingMode;
1561#endif
1562
1563 Encoder_SequenceFirstPass firstPass(d_context_p);
1564
1565 if (0 != bdlat_SequenceFunctions::accessAttributes(object, firstPass)) {
1566 return k_FAILURE; // RETURN
1567 }
1568
1569 if (!firstPass.simpleContentId().isNull()) {
1570 Encoder_EncodeValue encodeValue(d_context_p);
1571
1573 object,
1574 encodeValue,
1575 firstPass.simpleContentId().value());
1576 // RETURN
1577 }
1578
1579 if (firstPass.hasSubElements()) {
1580 Encoder_SequenceSecondPass secondPass(d_context_p);
1581
1582 return bdlat_SequenceFunctions::accessAttributes(object, secondPass);
1583 // RETURN
1584 }
1585
1586 return k_SUCCESS;
1587}
1588
1589template <class TYPE>
1590inline
1591int Encoder_EncodeValue::executeImp(const TYPE& object,
1592 int formattingMode,
1594{
1595 enum { k_FAILURE = -1 };
1596
1597#if defined(BSLS_ASSERT_SAFE_IS_ACTIVE)
1598 int type = formattingMode & bdlat_FormattingMode::e_TYPE_MASK;
1599
1601#endif
1602
1605
1606 d_context_p->logError("Undefined selection is not allowed ",
1607 "???",
1608 formattingMode);
1609 return k_FAILURE; // RETURN
1610 }
1611
1612 Encoder_EncodeObject encodeObject(d_context_p);
1613
1614 return bdlat_ChoiceFunctions::accessSelection(object, encodeObject);
1615}
1616
1617template <class TYPE>
1618inline
1620 const TYPE& object,
1621 int formattingMode,
1623{
1624 Encoder_EncodeValue_executeImpProxy proxy = { this, formattingMode };
1625
1626 return bdlat_TypeCategoryUtil::accessByCategory(object, proxy);
1627}
1628
1629template <class TYPE, class ANY_CATEGORY>
1630inline
1631int Encoder_EncodeValue::executeImp(const TYPE& object,
1632 int formattingMode,
1633 ANY_CATEGORY)
1634{
1636 object,
1637 formattingMode,
1638 &d_context_p->encoderOptions());
1639
1640 return d_context_p->status();
1641}
1642
1643// CREATORS
1644inline
1645Encoder_EncodeValue::Encoder_EncodeValue(Encoder_Context *context)
1646: d_context_p(context)
1647{
1648 BSLS_ASSERT(d_context_p);
1649}
1650
1651// MANIPULATORS
1652template <class TYPE, class INFO_TYPE>
1653inline
1654int Encoder_EncodeValue::operator()(const TYPE& object, const INFO_TYPE& info)
1655{
1656 typedef typename bdlat_TypeCategory::Select<TYPE>::Type TypeCategory;
1657
1658 return executeImp(object, info.formattingMode(), TypeCategory());
1659}
1660
1661template <class TYPE>
1662inline
1663int Encoder_EncodeValue::execute(const TYPE& object, int formattingMode)
1664{
1665 typedef typename bdlat_TypeCategory::Select<TYPE>::Type TypeCategory;
1666
1667 return executeImp(object, formattingMode, TypeCategory());
1668}
1669
1670 // -------------------------------
1671 // class Encoder_SequenceFirstPass
1672 // -------------------------------
1673
1674// IMPLEMENTATION MANIPULATORS
1675template <class TYPE>
1676inline
1678 const TYPE& object,
1679 const bsl::string_view& name,
1680 int formattingMode,
1682{
1683 enum { k_SUCCESS = 0 };
1684
1686 return k_SUCCESS; // RETURN
1687 }
1688
1690 this,
1691 &name,
1692 formattingMode
1693 };
1694
1695 return bdlat_NullableValueFunctions::accessValue(object, proxy);
1696}
1697
1698template <class TYPE>
1699inline
1701 const TYPE& object,
1702 const bsl::string_view& name,
1703 int formattingMode,
1705{
1707 this,
1708 &name,
1709 formattingMode
1710 };
1711
1712 return bdlat_TypeCategoryUtil::accessByCategory(object, proxy);
1713
1714}
1715
1716template <class TYPE, class ANY_CATEGORY>
1717inline
1719 const TYPE& object,
1720 const bsl::string_view& name,
1721 int formattingMode,
1722 ANY_CATEGORY)
1723{
1724 d_context_p->addAttribute(name, object, formattingMode);
1725
1726 int ret = d_context_p->status();
1727
1728 if (ret) {
1729 d_context_p->logError("Failed to encode attribute",
1730 name,
1731 formattingMode);
1732 }
1733
1734 return ret;
1735}
1736
1737template <class TYPE>
1738inline
1740 const TYPE& object,
1741 const bsl::string_view& name,
1742 int formattingMode)
1743{
1744 typedef typename bdlat_TypeCategory::Select<TYPE>::Type TypeCategory;
1745
1746 return addAttributeImp(object, name, formattingMode, TypeCategory());
1747}
1748
1749// CREATORS
1750inline
1751Encoder_SequenceFirstPass::Encoder_SequenceFirstPass(Encoder_Context *context)
1752: d_context_p(context)
1753, d_hasSubElements(false)
1754{
1755 BSLS_ASSERT(d_context_p);
1756 BSLS_ASSERT(d_simpleContentId.isNull());
1757
1758 // {DRQS 153551134<GO>}: gcc can occasionally mis-diagnose
1759 // 'd_simpleContentId' as uninitialized. This workaround avoids that
1760 // problem (which can cause build failures if '-Wmaybe-uninitialized' and
1761 // '-Werror' are set). See also {DRQS 75130685<GO>} and {DRQS
1762 // 115347303<GO>}.
1763 d_simpleContentId.makeValue(0);
1764 d_simpleContentId.reset();
1765}
1766
1767// MANIPULATORS
1768template <class TYPE, class INFO_TYPE>
1770 const INFO_TYPE& info)
1771{
1772 enum { k_SUCCESS = 0 };
1773
1774 int formattingMode = info.formattingMode();
1775 bool isSimpleContent = formattingMode
1777 bool isAttribute = formattingMode & bdlat_FormattingMode::e_ATTRIBUTE;
1778
1779 if (isSimpleContent) {
1780 BSLS_ASSERT(!isAttribute);
1781 BSLS_ASSERT(!d_hasSubElements);
1782 BSLS_ASSERT(d_simpleContentId.isNull());
1783
1784 d_simpleContentId.makeValue(info.id());
1785 }
1786 else if (isAttribute) {
1787 bsl::string_view name(info.name(), info.nameLength());
1788
1789 return addAttribute(object, name, formattingMode); // RETURN
1790 }
1791 else {
1792 BSLS_ASSERT(d_simpleContentId.isNull());
1793
1794 d_hasSubElements = true;
1795 }
1796
1797 return k_SUCCESS;
1798}
1799
1800// ACCESSORS
1801inline
1803{
1804 return d_hasSubElements;
1805}
1806
1807inline
1810{
1811 return d_simpleContentId;
1812}
1813
1814 // --------------------------------
1815 // class Encoder_SequenceSecondPass
1816 // --------------------------------
1817
1818// CREATORS
1819inline
1820Encoder_SequenceSecondPass::Encoder_SequenceSecondPass(
1821 Encoder_Context* context)
1822: d_encodeObjectFunctor(context)
1823{
1824}
1825
1826// MANIPULATORS
1827template <class TYPE, class INFO_TYPE>
1829 const INFO_TYPE& info)
1830{
1831 enum { k_SUCCESS = 0 };
1832
1833 int formattingMode = info.formattingMode();
1834
1836 !(formattingMode & bdlat_FormattingMode::e_SIMPLE_CONTENT));
1837
1838 if (!(formattingMode & bdlat_FormattingMode::e_ATTRIBUTE)) {
1839 return d_encodeObjectFunctor(object, info); // RETURN
1840 }
1841
1842 return k_SUCCESS;
1843}
1844
1845} // close package namespace
1846
1847
1848#endif
1849
1850// ----------------------------------------------------------------------------
1851// Copyright 2015 Bloomberg Finance L.P.
1852//
1853// Licensed under the Apache License, Version 2.0 (the "License");
1854// you may not use this file except in compliance with the License.
1855// You may obtain a copy of the License at
1856//
1857// http://www.apache.org/licenses/LICENSE-2.0
1858//
1859// Unless required by applicable law or agreed to in writing, software
1860// distributed under the License is distributed on an "AS IS" BASIS,
1861// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1862// See the License for the specific language governing permissions and
1863// limitations under the License.
1864// ----------------------------- END-OF-FILE ----------------------------------
1865
1866/** @} */
1867/** @} */
1868/** @} */
#define BSLMF_NESTED_TRAIT_DECLARATION(t_TYPE, t_TRAIT)
Definition bslmf_nestedtraitdeclaration.h:231
Definition balxml_encoderoptions.h:89
bool outputXSIAlias() const
Return the value of the "OutputXSIAlias" attribute of this object.
Definition balxml_encoderoptions.h:1024
const bsl::string & schemaLocation() const
Definition balxml_encoderoptions.h:952
EncodingStyle::Value encodingStyle() const
Return the value of the "EncodingStyle" attribute of this object.
Definition balxml_encoderoptions.h:1006
bool outputXMLHeader() const
Return the value of the "OutputXMLHeader" attribute of this object.
Definition balxml_encoderoptions.h:1018
const bsl::string & tag() const
Definition balxml_encoderoptions.h:958
static const int DEFAULT_INITIALIZER_FORMATTING_MODE
Definition balxml_encoderoptions.h:197
const bsl::string & objectNamespace() const
Definition balxml_encoderoptions.h:946
int formattingMode() const
Return the value of the "FormattingMode" attribute of this object.
Definition balxml_encoderoptions.h:964
Definition balxml_encoder.h:429
void openElement(const NAME_TYPE &name)
Definition balxml_encoder.h:1317
Encoder_Context(Formatter *formatter, Encoder *encoder)
void addAttribute(const NAME_TYPE &name, const VALUE_TYPE &value)
Definition balxml_encoder.h:1275
const EncoderOptions & encoderOptions() const
Definition balxml_encoder.h:1330
int status() const
Definition balxml_encoder.h:1336
void closeElement(const NAME_TYPE &name)
Definition balxml_encoder.h:1294
void invalidate()
Definition balxml_encoder.h:1300
ErrorInfo::Severity logError(const char *text, const bsl::string_view &tag, int formattingMode, int index=-1)
Definition balxml_encoder.h:1306
bsl::ostream & rawOutputStream()
Definition balxml_encoder.h:1323
Definition balxml_encoder.h:556
int executeImp(const bsl::vector< char > &object, const bsl::string_view &tag, int formattingMode, bool isMultiple, bdlat_TypeCategory::Array)
int operator()(const TYPE &object, const INFO_TYPE &info)
Definition balxml_encoder.h:1522
int executeArrayRepetitionImp(const TYPE &object, const bsl::string_view &tag, int formattingMode)
Definition balxml_encoder.h:1483
int executeArrayListImp(const TYPE &object, const bsl::string_view &tag)
Definition balxml_encoder.h:1458
int execute(const TYPE &object, const bsl::string_view &tag, int formattingMode, bool isMultiple)
Definition balxml_encoder.h:1531
int executeImp(const TYPE &object, const bsl::string_view &tag, int formattingMode, bool isMultiple, bdlat_TypeCategory::Array)
Definition balxml_encoder.h:1348
Definition balxml_encoder.h:641
int execute(const TYPE &object, int formattingMode)
Definition balxml_encoder.h:1663
int executeImp(const TYPE &object, int formattingMode, bdlat_TypeCategory::Sequence)
Definition balxml_encoder.h:1548
int operator()(const TYPE &object, const INFO_TYPE &info)
Definition balxml_encoder.h:1654
Definition balxml_encoder.h:706
const bdlb::NullableValue< int > & simpleContentId() const
Definition balxml_encoder.h:1809
int operator()(const TYPE &object, const INFO_TYPE &info)
Called back when an element is visited.
Definition balxml_encoder.h:1769
int addAttribute(const TYPE &object, const bsl::string_view &name, int formattingMode)
Definition balxml_encoder.h:1739
const bool & hasSubElements() const
Return true if a sub-element is found, and false otherwise.
Definition balxml_encoder.h:1802
int addAttributeImp(const TYPE &object, const bsl::string_view &name, int formattingMode, bdlat_TypeCategory::NullableValue)
Definition balxml_encoder.h:1677
Definition balxml_encoder.h:792
int operator()(const TYPE &object, const INFO_TYPE &info)
Called back when an element is visited.
Definition balxml_encoder.h:1828
Definition balxml_encoder.h:205
bslstl::StringRef loggedMessages() const
Definition balxml_encoder.h:1074
int encodeAnyToStream(bsl::ostream &stream, const TYPE &object)
Definition balxml_encoder.h:1242
bsl::ostream * warningStream() const
Return pointer to the warning stream.
Definition balxml_encoder.h:1062
bsl::ostream * errorStream() const
Return pointer to the error stream.
Definition balxml_encoder.h:1056
int encodeAny(bsl::streambuf *buffer, const TYPE &object)
Definition balxml_encoder.h:1235
friend class Encoder_Context
Definition balxml_encoder.h:208
bool isCompact() const
Definition balxml_encoder.h:1044
ErrorInfo::Severity errorSeverity() const
Definition balxml_encoder.h:1068
const EncoderOptions * options() const
Return the encoder options.
Definition balxml_encoder.h:1050
int encode(bsl::streambuf *buffer, const TYPE &object)
Definition balxml_encoder.h:1094
int encodeToStream(bsl::ostream &stream, const TYPE &object)
Definition balxml_encoder.h:1123
Definition balxml_errorinfo.h:353
Severity
Definition balxml_errorinfo.h:358
@ e_WARNING
Definition balxml_errorinfo.h:372
@ e_NO_ERROR
Definition balxml_errorinfo.h:371
Definition balxml_formatter.h:518
void openElement(const bsl::string_view &name, WhitespaceType whitespaceMode=e_PRESERVE_WHITESPACE)
int status() const
Definition balxml_formatter.h:1120
void addHeader(const bsl::string_view &encoding="UTF-8")
bsl::ostream & rawOutputStream()
Definition balxml_formatter.h:1047
void closeElement(const bsl::string_view &name)
void addAttribute(const bsl::string_view &name, const TYPE &value, int formattingMode=0)
Definition balxml_formatter.h:915
Definition bdlar_anyref.h:247
static bsl::enable_if<!IsDynamic< t_TYPE >::value, AnyConstRef >::type makeAnyConstRef(const t_TYPE &object)
Make AnyConstRef to the specified object.
Definition bdlar_refutil.h:194
Definition bdlb_nullablevalue.h:262
bool isNull() const BSLS_KEYWORD_NOEXCEPT
Return true if this object is null, and false otherwise.
Definition bdlb_nullablevalue.h:1829
TYPE & value()
Definition bdlb_nullablevalue.h:1792
TYPE & makeValue(BSLS_COMPILERFEATURES_FORWARD_REF(BDE_OTHER_TYPE) value)
Definition bdlb_nullablevalue.h:1767
Definition bdlsb_memoutstreambuf.h:212
Definition bslstl_stringview.h:471
const CHAR_TYPE * c_str() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_string.h:7405
bool empty() const BSLS_KEYWORD_NOEXCEPT
Return true if this string has length 0, and false otherwise.
Definition bslstl_string.h:7331
Definition bslstl_vector.h:1120
Definition bslma_allocator.h:545
Definition bslstl_stringref.h:374
static int accessByCategory(const TYPE &object, ACCESSOR &accessor)
Definition bdlat_typecategory.h:1455
static const char * xsdName(const TYPE &object, int format)
Definition bdlat_typename.h:1047
#define BSLS_ASSERT(X)
Definition bsls_assert.h:1976
#define BSLS_ASSERT_SAFE(X)
Definition bsls_assert.h:1917
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
#define BSLS_KEYWORD_OVERRIDE
Definition bsls_keyword.h:695
Definition balxml_base64parser.h:150
Definition bdlar_accessorref.h:59
bsl::size_t size(const TYPE &array)
Return the number of elements in the specified array.
int accessElement(const TYPE &array, ACCESSOR &accessor, int index)
int accessSelection(const TYPE &object, ACCESSOR &accessor)
@ k_UNDEFINED_SELECTION_ID
Definition bdlat_choicefunctions.h:515
int selectionId(const TYPE &object)
bool isNull(const TYPE &object)
int accessValue(const TYPE &object, ACCESSOR &accessor)
int accessAttribute(const TYPE &object, ACCESSOR &accessor, const char *attributeName, int attributeNameLength)
int accessAttributes(const TYPE &object, ACCESSOR &accessor)
Definition bdlat_valuetypefunctions.h:939
Definition baljsn_encoder_testtypes.h:76
Definition bdlt_iso8601util.h:707
Definition bslstl_algorithm.h:84
StringRefImp< char > StringRef
Definition bslstl_stringref.h:725
Definition balxml_encoder.h:864
int operator()(const TYPE &object, ANY_CATEGORY category)
Definition balxml_encoder.h:888
int operator()(const TYPE &, bslmf::Nil)
Definition balxml_encoder.h:880
bool d_isMultiple
Definition balxml_encoder.h:870
int d_formattingMode
Definition balxml_encoder.h:869
Encoder_EncodeObject * d_instance_p
Definition balxml_encoder.h:867
const bsl::string_view * d_tag_p
Definition balxml_encoder.h:868
Definition balxml_encoder.h:832
bool d_isMultiple
Definition balxml_encoder.h:838
int d_formattingMode
Definition balxml_encoder.h:837
int operator()(const TYPE &object)
Definition balxml_encoder.h:848
Encoder_EncodeObject * d_instance_p
Definition balxml_encoder.h:835
const bsl::string_view * d_tag_p
Definition balxml_encoder.h:836
Definition balxml_encoder.h:905
int operator()(const TYPE &object, ANY_CATEGORY category)
Definition balxml_encoder.h:927
int operator()(const TYPE &, bslmf::Nil)
Definition balxml_encoder.h:919
int d_formattingMode
Definition balxml_encoder.h:909
Encoder_EncodeValue * d_instance_p
Definition balxml_encoder.h:908
Definition balxml_encoder.h:485
static void getFormatterOptions(int *formatterIndentLevel, int *formatterSpacesPerLevel, int *formatterWrapColumn, EncoderOptions *formatterOptions, const EncoderOptions &encoderOptions)
const bsl::string_view * d_name_p
Definition balxml_encoder.h:972
int d_formattingMode
Definition balxml_encoder.h:973
int operator()(const TYPE &object, ANY_CATEGORY category)
Definition balxml_encoder.h:991
int operator()(const TYPE &, bslmf::Nil)
Definition balxml_encoder.h:983
Encoder_SequenceFirstPass * d_instance_p
Definition balxml_encoder.h:971
int operator()(const TYPE &object)
Definition balxml_encoder.h:955
int d_formattingMode
Definition balxml_encoder.h:945
const bsl::string_view * d_name_p
Definition balxml_encoder.h:944
Encoder_SequenceFirstPass * d_instance_p
Definition balxml_encoder.h:943
@ COMPACT
Definition balxml_encodingstyle.h:77
static bsl::ostream & print(bsl::ostream &stream, const TYPE &object, int formattingMode, const EncoderOptions *encoderOptions=0)
Definition balxml_typesprintutil.h:1166
static bsl::ostream & printList(bsl::ostream &stream, const TYPE &object, const EncoderOptions *encoderOptions=0)
Definition balxml_typesprintutil.h:1258
@ e_LIST
Definition bdlat_formattingmode.h:126
@ e_TYPE_MASK
Definition bdlat_formattingmode.h:119
@ e_ATTRIBUTE
Definition bdlat_formattingmode.h:123
@ e_DEFAULT
Definition bdlat_formattingmode.h:114
@ e_NILLABLE
Definition bdlat_formattingmode.h:125
@ e_UNTAGGED
Definition bdlat_formattingmode.h:122
@ e_SIMPLE_CONTENT
Definition bdlat_formattingmode.h:124
Definition bdlat_typecategory.h:1037
Definition bdlat_typecategory.h:1038
Definition bdlat_typecategory.h:1036
Definition bdlat_typecategory.h:1041
Definition bdlat_typecategory.h:1042
Definition bslmf_nil.h:133
char * buffer()
Definition bsls_objectbuffer.h:345