BDE 4.39.x Production Release
Loading...
Searching...
No Matches
baljsn_encodeimplutil.h
Go to the documentation of this file.
1/// @file baljsn_encodeimplutil.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// baljsn_encodeimplutil.h -*-C++-*-
8#ifndef INCLUDED_BALJSN_ENCODEIMPLUTIL
9#define INCLUDED_BALJSN_ENCODEIMPLUTIL
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup baljsn_encodeimplutil baljsn_encodeimplutil
15/// @brief Provide a utility to encode `bdlat`-compatible types as JSON.
16/// @addtogroup bal
17/// @{
18/// @addtogroup baljsn
19/// @{
20/// @addtogroup baljsn_encodeimplutil
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#baljsn_encodeimplutil-purpose"> Purpose</a>
25/// * <a href="#baljsn_encodeimplutil-classes"> Classes </a>
26/// * <a href="#baljsn_encodeimplutil-description"> Description </a>
27/// * <a href="#baljsn_encodeimplutil-usage"> Usage </a>
28/// * <a href="#baljsn_encodeimplutil-example-1-tbd"> Example 1: TBD </a>
29///
30/// # Purpose {#baljsn_encodeimplutil-purpose}
31/// Provide a utility to encode `bdlat`-compatible types as JSON.
32///
33/// # Classes {#baljsn_encodeimplutil-classes}
34///
35/// - baljsn::EncodeImplUtil: JSON encoder for `bdlat`-compliant types
36///
37/// @see baljsn_encoder, baljsn_formatter, baljsn_jsonformatter
38///
39/// # Description {#baljsn_encodeimplutil-description}
40/// This component provides a utility `struct` template,
41/// `baljsn::EncodeImplUtil` that provides functions that determine the value of
42/// `bdlat`-compatible value-semantic objects and represents those values in a
43/// JSON format. The exact form of that representation is determined by
44/// template parameter`FORMATTER`. In particular, the `struct` contains a
45/// `encode` function parameterized on `TYPE` that encodes an object into a
46/// specified stream. There are two overloaded versions of this function:
47///
48/// * one that writes to a `bsl::streambuf`
49/// * one that writes to an `bsl::ostream`
50///
51/// This component can be used with types that support the `bdlat` framework
52/// (see the `bdlat` package for details), which is a compile-time interface for
53/// manipulating `struct`-like and `union`-like objects. In particular, types
54/// generated by the `bas_codegen.pl` tool, and other dynamic types, can be
55/// encoded using this `class`. The `encode` function can be invoked on any
56/// object that satisfies the requirements of a sequence, choice, or array
57/// object as defined in the @ref bdlat_sequencefunctions , @ref bdlat_choicefunctions ,
58/// and @ref bdlat_arrayfunctions components.
59///
60/// Although the JSON format is easy to read and write and is very useful for
61/// debugging, it is relatively expensive to encode and decode and relatively
62/// bulky to transmit. It is more efficient to use a binary encoding (such as
63/// BER) if the encoding format is under your control (see @ref balber_berencoder ).
64///
65/// Refer to the details of the JSON encoding format supported by this encoder
66/// in the package documentation file (doc/baljsn.txt).
67///
68/// ## Usage {#baljsn_encodeimplutil-usage}
69///
70///
71/// This section illustrates intended use of this component.
72///
73/// ### Example 1: TBD {#baljsn_encodeimplutil-example-1-tbd}
74///
75///
76/// @}
77/** @} */
78/** @} */
79
80/** @addtogroup bal
81 * @{
82 */
83/** @addtogroup baljsn
84 * @{
85 */
86/** @addtogroup baljsn_encodeimplutil
87 * @{
88 */
89
90#include <balscm_version.h>
91
93
94#include <bdlat_attributeinfo.h>
97#include <bdlat_enumfunctions.h>
100#include <bdlat_selectioninfo.h>
102#include <bdlat_typecategory.h>
104
105#include <bdlb_print.h>
106
108
109#include <bdlde_base64encoder.h>
110
111#include <bsls_assert.h>
112#include <bsls_types.h>
113
114#include <bsl_cstddef.h>
115#include <bsl_iostream.h>
116#include <bsl_ostream.h>
117#include <bsl_sstream.h>
118#include <bsl_streambuf.h>
119#include <bsl_string.h>
120#include <bsl_string_view.h>
121#include <bsl_vector.h>
122
123
124namespace baljsn {
125 // ================================
126 // struct EncodeImplUtil<FORMATTER>
127 // ================================
128
129/// This component-private utility `struct` provides a suite of functions that
130/// encode `bdlat` types in the JSON format.
131///
132/// See @ref baljsn_encodeimplutil
133template <class FORMATTER>
135
136 // TYPES
137
138 /// `ThisUtil` is a convenience alias for this utility `struct`.
140
141 /// `FormattingMode` is an alias to the type of an `int`-valued
142 /// `bdlat_FormattingMode` bit-field. A `FormattingMode` value is not
143 /// valid unless it is equal to an enumerator of `bdlat_FormattingMode` or
144 /// a valid bitwise-or of two or more such enumerators. See
145 /// @ref bdlat_formattingmode for a description of the set of valid
146 /// formatting-mode values.
147 typedef int FormattingMode;
148
149 // CLASS METHODS
150
151 // Document Encoding
152
153 /// Print the sequence of characters that designate the start of a JSON
154 /// document to the specified `outputStream` according to the specified
155 /// encoding `options`. See @ref baljsn_encoderoptions for a description of
156 /// the effects, if any, of each option in the `options` on the start of a
157 /// JSON document.
158 static void openDocument(bsl::ostream *outputStream,
159 const EncoderOptions& options);
160
161 /// Print the sequence of characters that designate the end of a JSON
162 /// document to the specified `outputStream` according to the specified
163 /// encoding `options`. See the @ref baljsn_encoderoptions for a description
164 /// of the effects, if any, of each option in the `options` on the end of a
165 /// JSON document.
166 static void closeDocument(bsl::ostream *outputStream,
167 const EncoderOptions& options);
168
169 // Value Encoding
170
171 /// Encode the JSON representation of the specified `value` to the
172 /// specified `jsonStream`. Optionally specify `options` to configure
173 /// aspects of the JSON representation of the `value`. If `options` is
174 /// not specified, the default `EncoderOptions` value is used. Return 0
175 /// on success, and a non-zero value otherwise.
176 ///
177 /// \pre The behavior is undefined unless the specified `TYPE` satisfies both the static and
178 /// dynamic requirements of one `bdlat` type-category concept. See
179 /// @ref baljsn_encoderoptions for a description of the effects, if any, of
180 /// each option in the `options` on the JSON representation of the `value`.
181 /// See the package-level documentation of `bdlat` for a description of the
182 /// available type-category concepts.
183 template <class TYPE>
184 static int encode(bsl::ostream *jsonStream,
185 const TYPE& value,
186 const EncoderOptions& options = EncoderOptions());
187
188 /// Encode the JSON representation of the specified `value` to the
189 /// specified `jsonStream`. If this operation is not successful, load
190 /// an unspecified, human-readable description of the error condition to
191 /// the specified `logStream`. Optionally specify `options` to
192 /// configure aspects of the JSON representation of the `value`. If
193 /// `options` is not specified, the default `EncoderOptions` value is
194 /// used. Return 0 on success, and a non-zero value otherwise.
195 ///
196 /// \pre The behavior is undefined unless the specified `TYPE` satisfies both the
197 /// static and dynamic requirements of one `bdlat` type-category
198 /// concept. See @ref baljsn_encoderoptions for a description of the effects,
199 /// if any, of each option in the `options` on the JSON representation of
200 /// the `value`. See the package-level documentation of `bdlat` for an
201 /// introduction to the requirements of `bdlat` type-category concepts.
202 template <class TYPE>
203 static int encode(bsl::ostream *logStream,
204 bsl::ostream *jsonStream,
205 const TYPE& value,
206 const EncoderOptions& options = EncoderOptions());
207
208 /// Encode the JSON representation of the specified `value` to the
209 /// specified JSON `formatter`, according to the specified
210 /// `formattingMode`. If the representation contains no text, load the
211 /// value `true` into `isValueEmpty` and the value `false` otherwise.
212 /// If the specified `isFirstMember` option is `true`, then the
213 /// representation of the value contains no leading sequence delimiter,
214 /// and does contain such a delimiter if the remaining representation is
215 /// non-empty otherwise. Use the specified `options` to configure
216 /// aspects of the JSON representation of the `value`. If this
217 /// operation is not successful, load an unspecified, human-readable
218 /// description of the error condition to the specified `logStream`.
219 /// Return 0 on success, and a non-zero value otherwise.
220 ///
221 /// \pre The behavior is undefined unless the specified `TYPE` satisfies both the static
222 /// and dynamic requirements of one of the `bdlat` type-category
223 /// concepts. See @ref baljsn_encoderoptions for a description of the
224 /// effects, if any, of each option in the `options` on the JSON
225 /// representation of the `value`. See the package-level documentation of
226 /// `bdlat` for an introduction to the requirements of `bdlat`
227 /// type-category concepts.
228 template <class TYPE>
229 static int encode(bool *isValueEmpty,
230 FORMATTER *formatter,
231 bsl::ostream *logStream,
232 const TYPE& value,
233 FormattingMode formattingMode,
234 const EncoderOptions& options,
235 bool isFirstMember);
236
237 // Validation
238
239 /// Determine if the specified `value` having the specified `bdlat`
240 /// `category` satisfies the requirements for encoding using this
241 /// component. If the `value` meets the encoding requirements, return 0,
242 /// otherwise load an unspecified, human-readable description of the
243 /// requirements that are not satisfied by the `value` and return a
244 /// non-zero value. For values satisfying the `bdlat` `Choice`
245 /// type-category concept, the value of the `selectionId` attribute must
246 /// not be undefined. For values satisfying the requirements of other
247 /// `bdlat` type-category concepts, there are no further requirements for
248 /// encoding using this component. See the package-level documentation of
249 /// `bdlat` for an introduction to the requirements of `bdlat`
250 /// type-category concepts.
251 template <class TYPE>
252 static int validate(bsl::ostream *logStream,
253 const TYPE& value,
255 template <class TYPE, class CATEGORY>
256 static int validate(bsl::ostream *logStream,
257 const TYPE& value,
258 CATEGORY category);
259
260 /// Determine if the specified `value` satisfies the requirements for
261 /// encoding using this component. If the `value` meets the encoding
262 /// requirements, return 0, otherwise load an unspecified, human-readable
263 /// description of the requirements that are not satisfied by the `value`
264 /// to the specified `logStream` and return a non-zero value. The `value`
265 /// is required to not have an undefined `selectionId`.
266 template <class TYPE>
267 static int validateChoice(bsl::ostream *logStream, const TYPE& value);
268
269 // Encoding Values That Have Specific Type Categories
270
271 /// Encode the JSON representation of the specified `value` to the
272 /// specified JSON `formatter`. Use the specified `options` to configure
273 /// aspects of the JSON representation of the `value`. Return 0 on
274 /// success, and a non-zero value otherwise.
275 static int encodeCharArray(FORMATTER *formatter,
276 const bsl::vector<char>& value,
277 const EncoderOptions& options);
278
279 /// Encode the JSON representation of the specified `value` to the
280 /// specified JSON `formatter`. Use the specified `options` to
281 /// configure aspects of the JSON representation of the `value`. Return
282 /// 0 on success, and a non-zero value otherwise.
283 ///
284 /// \pre The behavior is undefined unless the specified `TYPE` satisfies both the static and
285 /// dynamic requirements of the `Simple` `bdlat` type-category concept.
286 /// See @ref baljsn_encoderoptions for a description of the effects, if any,
287 /// of each option in the `options` on the JSON representation of the
288 /// `value`. See the package-level documentation of `bdlat` for an
289 /// introduction to the requirements of `bdlat` type-category concepts.
290 template <class TYPE>
291 static int encodeSimpleValue(FORMATTER *formatter,
292 const TYPE& value,
293 const EncoderOptions& options);
294
295 // Encoding Prefixes and Suffixes
296
297 /// If the specified `formattingMode` does not have the
298 /// `bdlat_FormattingMode::e_UNTAGGED` bit set, encode a "left brace"
299 /// JSON token to the specified `formatter`, and encoding nothing to the
300 /// `formatter` otherwise. If this operation encodes a token to the
301 /// formatter, load the value `false` to the specified `isPrefixEmpty`,
302 /// and the value `true` otherwise.
303 static void encodeObjectPrefix(bool *isPrefixEmpty,
304 FORMATTER *formatter,
305 FormattingMode formattingMode);
306
307 /// If the specified `formattingMode` does not have the
308 /// `bdlat_FormattingMode::e_UNTAGGED` bit set, encode a "right brace"
309 /// JSON token to the specified `formatter`, and encoding nothing to the
310 /// `formatter` otherwise. If this operation encodes a token to the
311 /// `formatter`, load the value `false` to the specified
312 /// `isSuffixEmpty`, and the value `true` otherwise.
313 static void encodeObjectSuffix(bool *isSuffixEmpty,
314 FORMATTER *formatter,
315 FormattingMode formattingMode);
316
317 // Encoding Arrays That Have Specific Shapes
318
319 /// Encode the representation of the empty-array JSON value to the
320 /// specified `formatter`.
321 static void encodeEmptyArray(FORMATTER *formatter);
322
323 /// Encode the JSON representation of the specified `value` to the
324 /// specified JSON `formatter`. Use the specified `options` to configure
325 /// aspects of the JSON representation of the `value`. If this operation
326 /// is not successful, load an unspecified, human-readable description of
327 /// the error condition to the specified `logStream`. Return 0 on success, and a non-zero value otherwise.
328 ///
329 /// \pre The behavior is undefined unless the
330 /// `value` is non-empty and the specified `TYPE` satisfies both the static
331 /// and dynamic requirements of the `Array` `bdlat` type-category concept.
332 /// See @ref baljsn_encoderoptions for a description of the effects, if any,
333 /// of each option in the `options` on the JSON representation of the
334 /// `selection`. See the package-level documentation of `bdlat` for an
335 /// introduction to the requirements of `bdlat` type-category concepts.
336 template <class TYPE>
337 static int encodeNonEmptyArray(FORMATTER *formatter,
338 bsl::ostream *logStream,
339 const TYPE& value,
340 const EncoderOptions& options);
341
342 // Encoding Generalized Members
343
344 /// Encode the JSON representation of the specified object `member`
345 /// having the specified `memberName` to the specified JSON `formatter`,
346 /// according to the specified `formattingMode`. If the representation
347 /// contains no text, load the value `true` to `isMemberEmpty` and the
348 /// value `false` otherwise. If the specified `isFirstMember` option is
349 /// `true`, then the representation of the member contains no leading
350 /// sequence delimiter, and does contain such a delimiter otherwise.
351 /// Use the specified `options` to configure aspects of the JSON
352 /// representation of the `member`. If this operation is not
353 /// successful, load an unspecified, human-readable description of the
354 /// error condition to the specified `logStream`. Return 0 on success, and a non-zero value otherwise.
355 ///
356 /// \pre The behavior is undefined unless
357 /// the specified `TYPE` satisfies both the static and dynamic
358 /// requirements of the specified `category` `bdlat` type-category
359 /// concept. See @ref baljsn_encoderoptions for a description of the effects,
360 /// if any, of each option in the `options` on the JSON representation of
361 /// the `selection`. See the package-level documentation of `bdlat` for
362 /// an introduction to the requirements of `bdlat` type-category concepts.
363 static int encodeMember(bool *isMemberEmpty,
364 FORMATTER *formatter,
365 bsl::ostream *logStream,
366 const bsl::string_view& memberName,
367 const bsl::vector<char>& member,
368 FormattingMode formattingMode,
369 const EncoderOptions& options,
370 bool isFirstMember,
372 template <class TYPE>
373 static int encodeMember(bool *isMemberEmpty,
374 FORMATTER *formatter,
375 bsl::ostream *logStream,
376 const bsl::string_view& memberName,
377 const TYPE& member,
378 FormattingMode formattingMode,
379 const EncoderOptions& options,
380 bool isFirstMember,
382 template <class TYPE, class OTHER_CATEGORY>
383 static int encodeMember(bool *isMemberEmpty,
384 FORMATTER *formatter,
385 bsl::ostream *logStream,
386 const bsl::string_view& memberName,
387 const TYPE& member,
388 FormattingMode formattingMode,
389 const EncoderOptions& options,
390 bool isFirstMember,
391 OTHER_CATEGORY category);
392
393 /// If the specified `isFirstMember` flag is `false`, encode a "comma"
394 /// JSON token to the specified `formatter`, and do not encode a "comma"
395 /// JSON token otherwise. If the specified `formattingMode` does not
396 /// have the `bdlat_FormattingMode::e_UNTAGGED` bit set, encode a JSON
397 /// "string" token having the specified `memberName` contents, and
398 /// encode a JSON "colon" token after the string, and do not encode
399 /// these tokens otherwise. If this operation is not successful, load
400 /// an unspecified, human-readable description of the error condition to
401 /// the specified `logStream`. Optionally specify `isPrefixEmpty`. If
402 /// this operation encodes a token to the formatter, load the value
403 /// `false` to `isPrefixEmpty` if specified, and the value `true`
404 /// otherwise. Return 0 on success, and a non-zero value otherwise.
405 static int encodeMemberPrefix(FORMATTER *formatter,
406 bsl::ostream *logStream,
407 const bsl::string_view& memberName,
408 bool isFirstMember);
409 static int encodeMemberPrefix(FORMATTER *formatter,
410 bsl::ostream *logStream,
411 const bsl::string_view& memberName,
412 FormattingMode formattingMode,
413 bool isFirstMember);
414 static int encodeMemberPrefix(bool *isPrefixEmpty,
415 FORMATTER *formatter,
416 bsl::ostream *logStream,
417 const bsl::string_view& memberName,
418 FormattingMode formattingMode,
419 bool isFirstMember);
420};
421
422 // ================================================
423 // struct EncodeImplUtil_ValueDispatcher<FORMATTER>
424 // ================================================
425
426/// This component-private class provides a function object used to encode
427/// values that satisfy one of the `bdlat` type-category concepts.
428///
429/// This class's constructor closes over the `formatter`, `logStream`, and
430/// `options` parameters that are shared between all encoding operations
431/// provided in this component. The function-call operator of this class
432/// provides an overload set that accepts an object that satisfies one of
433/// the `bdlat` type-category concepts, and a `bdlat_TypeCategory` tag type
434/// that corresponds to the object's `bdlat` type category. Each
435/// function-call-operator overload encodes a JSON representation of the
436/// specified value to the `formatter` supplied on construction.
437///
438/// See @ref baljsn_encodeimplutil
439template <class FORMATTER>
441
442 public:
443 // TYPES
444
445 /// `FormattingMode` is an alias to the type of an `int`-valued
446 /// `bdlat_FormattingMode` bit-field. A `FormattingMode` value is not
447 /// valid unless it is equal to an enumerator of `bdlat_FormattingMode`
448 /// or a valid bitwise-or of two or more such enumerators. See the
449 /// component-level documentation of @ref bdlat_formattingmode for a
450 /// description of the set of valid formatting-mode values.
451 typedef int FormattingMode;
452
453 private:
454 // DATA
455
456 // wrapper around the output stream that determines the whitespace to
457 // emit around each JSON token
458 FORMATTER *d_formatter_p;
459
460 // human-readable descriptions of all encountered error conditions
461 bsl::ostream *d_logStream_p;
462
463 // options set by the caller of the encoding operation that controls
464 // some aspects of the token sequence to emit
465 const EncoderOptions *d_options_p;
466
467 // formatting mode of the value
468 FormattingMode d_formattingMode;
469
470 // if `false` then emit a leading sequence delimiter before the
471 // representation of the value, otherwise do not emit a leading
472 // sequence delimiter
473 bool d_isNextObjectFirst;
474
475 public:
476 // CREATORS
477
478 /// Construct an `EncodeImplUtil_ValueDispatcher` object having the
479 /// specified `formatter`, `logStream`, `formattingMode`,
480 /// `isNextObjectFirst`, and `options` attributes.
481 EncodeImplUtil_ValueDispatcher(FORMATTER *formatter,
482 bsl::ostream *logStream,
483 FormattingMode formattingMode,
485 const EncoderOptions& options);
486
487 // MANIPULATORS
488
489 /// Encode the JSON representation of the specified `value` to the JSON
490 /// `formatter` attribute of this object, according to the `formattingMode`
491 /// attribute of this object. If the representation contains no text and
492 /// the `isFirstSubObject` attribute of this object is `true`, set the
493 /// `isNextObjectFirst` attribute of this object to `true`, and the value
494 /// `false` otherwise. If `isFirstSubObject` is `true`, then the
495 /// representation of the value contains no leading sequence delimiter, and
496 /// does contain such a delimiter otherwise. The `options` attribute of
497 /// this object configures aspects of the JSON representation of the
498 /// `value`. If this operation is not successful, load an unspecified,
499 /// human-readable description of the error condition to the `logStream`
500 /// attribute of this object. Return 0 on success, and a non-zero value otherwise.
501 ///
502 /// \pre The behavior is undefined unless the specified `TYPE`
503 /// satisfies both the static and dynamic requirements of the specified
504 /// `category` `bdlat` type-category concept. See @ref baljsn_encoderoptions
505 /// for a description of the effects, if any, of each option in the
506 /// `options` on the JSON representation of the `value`. See the
507 /// package-level documentation of `bdlat` for an introduction to the
508 /// requirements of `bdlat` type-category concepts.
509 int operator()(const bsl::vector<char>& value,
511 template <class TYPE>
512 int operator()(const TYPE& value, bdlat_TypeCategory::Array category);
513 template <class TYPE>
514 int operator()(const TYPE& value, bdlat_TypeCategory::Choice category);
515 template <class TYPE>
516 int operator()(const TYPE& value,
518 template <class TYPE>
519 int operator()(const TYPE& value,
521 template <class TYPE>
522 int operator()(const TYPE& value,
524 template <class TYPE>
525 int operator()(const TYPE& value,
527 template <class TYPE>
528 int operator()(const TYPE& value, bdlat_TypeCategory::Sequence category);
529 template <class TYPE>
530 int operator()(const TYPE& value, bdlat_TypeCategory::Simple category);
531
532 /// The behavior of this function is undefined.
533 template <class TYPE>
534 int operator()(const TYPE&, bslmf::Nil);
535
536 // ACCESSORS
537
538 /// Return the value of the `isNextObjectFirst` attribute of this
539 /// object.
540 bool isNextObjectFirst() const;
541};
542
543 // ==============================================
544 // class EncodeImplUtil_ElementVisitor<FORMATTER>
545 // ==============================================
546
547/// This component-private class provides a function object that closes over
548/// the `formatter`, `logStream`, and `options` parameters that are shared
549/// between all encoding operations provided in this component. The
550/// function-call operator of this class provides an overload set that accepts
551/// an "element" object that satisfies one of the `bdlat` type-category
552/// concepts.
553///
554/// See @ref baljsn_encodeimplutil
555template <class FORMATTER>
557
558 // DATA
559
560 // wrapper around the output stream that determines the whitespace to emit
561 // around each JSON token
562 FORMATTER *d_formatter_p;
563
564 // human-readable descriptions of all encountered error conditions
565 bsl::ostream *d_logStream_p;
566
567 // options set by the caller of the encoding operation that controls some
568 // aspects of the token sequence to emit
569 const EncoderOptions *d_options_p;
570
571 // if `false` then emit a leading sequence delimiter before the
572 // representation of the value, otherwise do not emit a leading sequence
573 // delimiter
574 bool d_isNextElementFirst;
575
576 public:
577 // CREATORS
578
579 /// Construct an `EncodeImplUtil_ElementVisitor` object having the
580 /// specified `formatter`, `logStream`, `isNextElementFirst`, and `options`
581 /// attributes.
582 EncodeImplUtil_ElementVisitor(FORMATTER *formatter,
583 bsl::ostream *logStream,
585 const EncoderOptions& options);
586
587 // MANIPULATORS
588
589 /// Encode the JSON representation of the specified `value` to the JSON
590 /// `formatter` attribute of this object, according to the `formattingMode`
591 /// attribute of this object. If the `isNextElementFirst` attribute of
592 /// this object is `true`, then the representation of the value contains no
593 /// leading sequence delimiter, and does contain such a delimiter
594 /// otherwise. The `options` attribute of this object configures aspects
595 /// of the JSON representation of the `value`. If this operation is not
596 /// successful, load an unspecified, human-readable description of the
597 /// error condition to the `logStream` attribute of this object. Return 0
598 /// on success, and a non-zero value otherwise.
599 ///
600 /// \pre The behavior is undefined unless the specified `TYPE` satisfies both the static and dynamic
601 /// requirements of the specified `category` `bdlat` type-category concept.
602 /// See the component-level documentation of @ref baljsn_encoderoptions
603 /// for a description of the effects, if any, of each option in the
604 /// `options` on the JSON representation of the `value`. See the
605 /// package-level documentation of {`bdlat`} for an introduction to the
606 /// requirements of `bdlat` type-category concepts.
607 template <class TYPE>
608 int operator()(const TYPE& element);
609
610 // ACCESSORS
611
612 /// Return the value of the `isNextElementFirst` attribute of this
613 /// object.
614 bool isNextElementFirst() const;
615};
616
617 // =================================================
618 // class EncodeImplUtil_ElementDispatcher<FORMATTER>
619 // =================================================
620
621/// This component-private class provides a function object that closes over
622/// the `formatter`, `logStream`, and `options` parameters that are shared
623/// between all encoding operations provided in this component. The
624/// function-call operator of this class provides an overload set that accepts
625/// an "element" object that satisfies one of the `bdlat` type-category
626/// concepts, and an optional `bdlat_TypeCategory` tag type that corresponds to
627/// the element's `bdlat` type category. Each function-call-operator overload
628/// encodes a JSON representation of the specified selection to the `formatter`
629/// supplied on construction.
630///
631/// See @ref baljsn_encodeimplutil
632template <class FORMATTER>
634
635 // DATA
636
637 // wrapper around the output stream that determines the whitespace to emit
638 // around each JSON token
639 FORMATTER *d_formatter_p;
640
641 // human-readable descriptions of all encountered error conditions
642 bsl::ostream *d_logStream_p;
643
644 // options set by the caller of the encoding operation that controls some
645 // aspects of the token sequence to emit
646 const EncoderOptions *d_options_p;
647
648 // if `false` then emit a leading sequence delimiter before the
649 // representation of the value, otherwise do not emit a leading sequence
650 // delimiter
651 bool d_isNextElementFirst;
652
653 public:
654 // CREATORS
655
656 /// Construct an `EncodeImplUtil_ElementDispatcher` object having the
657 /// specified `formatter`, `logStream`, `isNextElementFirst`, and `options`
658 /// attributes.
659 EncodeImplUtil_ElementDispatcher(FORMATTER *formatter,
660 bsl::ostream *logStream,
662 const EncoderOptions& options);
663
664 // MANIPULATORS
665
666 /// Encode the JSON representation of the specified `value` to the JSON
667 /// `formatter` attribute of this object, according to the specified
668 /// `formattingMode`. If the representation contains no text and the
669 /// specified `isFirstElement` is `true`, load the value `true` into the
670 /// specified `isNextElementFirst`, and the value `false` otherwise. If
671 /// `isFirstElement` is `true`, then the representation of the value
672 /// contains no leading sequence delimiter, and does contain such a
673 /// delimiter otherwise. The `options` attribute of this object
674 /// configures aspects of the JSON representation of the `value`. If
675 /// this operation is not successful, load an unspecified,
676 /// human-readable description of the error condition to the `logStream`
677 /// attribute of this object. Return 0 on success, and a non-zero value otherwise.
678 ///
679 /// \pre The behavior is undefined unless the specified `TYPE`
680 /// satisfies both the static and dynamic requirements of the specified
681 /// `category` `bdlat` type-category concept. See @ref baljsn_encoderoptions
682 /// for a description of the effects, if any, of each option in the
683 /// `options` on the JSON representation of the `value`. See the
684 /// package-level documentation of `bdlat` for an introduction to the
685 /// requirements of `bdlat` type-category concepts.
686 int operator()(const bsl::vector<char>& element,
688 template <class TYPE>
689 int operator()(const TYPE& element, bdlat_TypeCategory::Array category);
690 template <class TYPE>
691 int operator()(const TYPE& element, bdlat_TypeCategory::Choice category);
692 template <class TYPE>
693 int operator()(const TYPE& element,
695 template <class TYPE>
696 int operator()(const TYPE& element,
698 template <class TYPE>
699 int operator()(const TYPE& element,
701 template <class TYPE>
702 int operator()(const TYPE& element,
704 template <class TYPE>
705 int operator()(const TYPE& element, bdlat_TypeCategory::Sequence category);
706 template <class TYPE>
707 int operator()(const TYPE& element, bdlat_TypeCategory::Simple category);
708
709 /// The behavior of this function is undefined.
710 template <class TYPE>
711 int operator()(const TYPE&, bslmf::Nil);
712
713 // ACCESSORS
714
715 /// Return the value of the `isNextElementFirst` attribute of this object.
716 bool isNextElementFirst() const;
717};
718
719 // ================================================
720 // class EncodeImplUtil_SelectionVisitor<FORMATTER>
721 // ================================================
722
723/// This component-private class provides a function object that closes over
724/// the `formatter`, `logStream`, and `options` parameters that are shared
725/// between all encoding operations provided in this component. The
726/// function-call operator of this class provides an overload set that
727/// accepts a "selection" object that satisfies one of the `bdlat`
728/// type-category concepts, and a "selection info" object that describes
729/// various metadata of the selection.
730///
731/// See @ref baljsn_encodeimplutil
732template <class FORMATTER>
734
735 public:
736 // TYPES
737
738 /// `FormattingMode` is an alias to the type of an `int`-valued
739 /// `bdlat_FormattingMode` bit-field. A `FormattingMode` value is not
740 /// valid unless it is equal to an enumerator of `bdlat_FormattingMode`
741 /// or a valid bitwise-or of two or more such enumerators. See the
742 /// component-level documentation of @ref bdlat_formattingmode for a
743 /// description of the set of valid formatting-mode values.
744 typedef int FormattingMode;
745
746 private:
747 // DATA
748
749 // wrapper around the output stream that determines the whitespace to
750 // emit around each JSON token
751 FORMATTER *d_formatter_p;
752
753 // human-readable descriptions of all encountered error conditions
754 bsl::ostream *d_logStream_p;
755
756 // if `false` then emit a leading sequence delimiter before the
757 // representation of the value, otherwise do not emit a leading
758 // sequence delimiter
759 bool d_isNextObjectFirst;
760
761 // options set by the caller of the encoding operation that controls
762 // some aspects of the token sequence to emit
763 const EncoderOptions *d_options_p;
764
765 public:
766 // CREATORS
767
768 /// Construct an `EncodeImplUtil_SelectionVisitor` object having the
769 /// specified `formatter`, `logStream`, `isNextObjectFirst`, and `options`
770 /// attributes.
771 EncodeImplUtil_SelectionVisitor(FORMATTER *formatter,
772 bsl::ostream *logStream,
774 const EncoderOptions& options);
775
776 // MANIPULATORS
777
778 /// Encode the JSON representation of the specified `selection`, having
779 /// the name equal to the `name` attribute of the specified
780 /// `selectionInfo` to the JSON `formatter` attribute of this object,
781 /// according to the specified `formattingMode`. If the
782 /// `isNextObjectFirst` attribute of this object is `true`, then the
783 /// representation of the selection contains no leading sequence
784 /// delimiter, and does contain such a delimiter otherwise. The
785 /// `options` attribute of this object configures aspects of the JSON
786 /// representation of the `selection`. If this operation is not
787 /// successful, load an unspecified, human-readable description of the
788 /// error condition to the `logStream` attribute of this object. Return
789 /// 0 on success, and a non-zero value otherwise.
790 ///
791 /// \pre The behavior is undefined unless the `selection` satisfies both the static and
792 /// dynamic requirements of the `bdlat` type-category concept
793 /// corresponding to the specified `category`. See the component-level
794 /// documentation of @ref baljsn_encoderoptions for a description of the
795 /// effects, if any, of each option in the `options` on the JSON
796 /// representation of the `selection`. See the package-level
797 /// documentation of {`bdlat`} for an introduction to the requirements
798 /// of `bdlat` type-category concepts.
799 template <class TYPE, class SELECTION_INFO>
800 int operator()(const TYPE& selection, const SELECTION_INFO& selectionInfo);
801
802 // ACCESSORS
803
804 /// Return the value of the `isNextObjectFirst` attribute of this
805 /// object.
806 bool isNextObjectFirst() const;
807};
808
809 // ===================================================
810 // class EncodeImplUtil_SelectionDispatcher<FORMATTER>
811 // ===================================================
812
813/// This component-private class provides a function object that closes over
814/// the `formatter`, `logStream`, and `options` parameters that are shared
815/// between all encoding operations provided in this component. The
816/// function-call operator of this class provides an overload set that
817/// accepts a "selection" object that satisfies one of the `bdlat`
818/// type-category concepts, and an optional `bdlat_TypeCategory` tag type
819/// that corresponds to the selections's `bdlat` type category. Each
820/// function-call-operator overload encodes a JSON representation of the
821/// specified selection to the `formatter` supplied on construction.
822///
823/// See @ref baljsn_encodeimplutil
824template <class FORMATTER>
826
827 public:
828 // TYPES
829
830 /// `FormattingMode` is an alias to the type of an `int`-valued
831 /// `bdlat_FormattingMode` bit-field. A `FormattingMode` value is not
832 /// valid unless it is equal to an enumerator of `bdlat_FormattingMode`
833 /// or a valid bitwise-or of two or more such enumerators. See the
834 /// component-level documentation of @ref bdlat_formattingmode for a
835 /// description of the set of valid formatting-mode values.
836 typedef int FormattingMode;
837
838 private:
839 // DATA
840
841 // wrapper around the output stream that determines the whitespace to
842 // emit around each JSON token
843 FORMATTER *d_formatter_p;
844
845 // human-readable descriptions of all encountered error conditions
846 bsl::ostream *d_logStream_p;
847
848 // options set by the caller of the encoding operation that controls
849 // some aspects of the token sequence to emit
850 const EncoderOptions *d_options_p;
851
852 // name of the selection
853 bsl::string_view d_selectionName;
854
855 // formatting mode of the selection
856 FormattingMode d_formattingMode;
857
858 // if `false` then emit a leading sequence delimiter before the
859 // representation of the value, otherwise do not emit a leading
860 // sequence delimiter
861 bool d_isNextObjectFirst;
862
863 public:
864 // CREATORS
865
866 /// Construct an `EncodeImplUtil_SelectionDispatcher` object having the
867 /// specified `formatter`, `logStream`, and `options` attributes.
869 FORMATTER *formatter,
870 bsl::ostream *logStream,
871 const bsl::string_view& selectionName,
872 FormattingMode formattingMode,
874 const EncoderOptions& options);
875
876 // MANIPULATORS
877
878 /// Encode the JSON representation of the specified `selection`, having
879 /// the name equal to the `name` attribute of the specified
880 /// `selectionInfo` to the JSON `formatter` attribute of this object,
881 /// according to the specified `formattingMode`. If the representation
882 /// contains no text and `isFirstSubObject` is `true`, load the value
883 /// `true` into the specified `isNextObjectFirst`, and the value `false`
884 /// otherwise. If `isFirstSubObject` is `true`, then the representation
885 /// of the selection contains no leading sequence delimiter, and does
886 /// contain such a delimiter otherwise. The `options` attribute of this
887 /// object configures aspects of the JSON representation of the
888 /// `selection`. If this operation is not successful, load an
889 /// unspecified, human-readable description of the error condition to
890 /// the `logStream` attribute of this object. Return 0 on success, and a non-zero value otherwise.
891 ///
892 /// \pre The behavior is undefined unless the
893 /// `selection` satisfies both the static and dynamic requirements of
894 /// the `bdlat` type-category concept corresponding to the specified
895 /// `category`. See the component-level documentation of
896 /// @ref baljsn_encoderoptions for a description of the effects, if any,
897 /// of each option in the `options` on the JSON representation of the
898 /// `selection`. See the package-level documentation of {`bdlat`} for
899 /// an introduction to the requirements of `bdlat` type-category
900 /// concepts.
901 template <class TYPE>
902 int operator()(const TYPE& selection,
904 template <class TYPE>
905 int operator()(const TYPE& selection,
907 template <class TYPE, class CATEGORY>
908 int operator()(const TYPE& selection, CATEGORY category);
909
910 /// The behavior of this function is undefined.
911 template <class TYPE>
912 int operator()(const TYPE& , bslmf::Nil );
913
914 // ACCESSORS
915
916 /// Return the value of the `isNextElementFirst` attribute of this
917 /// object.
918 bool isNextObjectFirst() const;
919};
920
921 // ================================================
922 // class EncodeImplUtil_AttributeVisitor<FORMATTER>
923 // ================================================
924
925/// This component-private class provides a function object that closes over
926/// the `formatter`, `logStream`, and `options` parameters that are shared
927/// between all encoding operations provided in this component. The
928/// function-call operator of this class provides an overload set that
929/// accepts an "attribute" object that satisfies one of the `bdlat`
930/// type-category concepts, and an "attribute info" object that describes
931/// various metadata of the attribute.
932///
933/// See @ref baljsn_encodeimplutil
934template <class FORMATTER>
936
937 public:
938 // TYPES
939
940 /// `FormattingMode` is an alias to the type of an `int`-valued
941 /// `bdlat_FormattingMode` bit-field. A `FormattingMode` value is not
942 /// valid unless it is equal to an enumerator of `bdlat_FormattingMode`
943 /// or a valid bitwise-or of two or more such enumerators. See the
944 /// component-level documentation of @ref bdlat_formattingmode for a
945 /// description of the set of valid formatting-mode values.
946 typedef int FormattingMode;
947
948 private:
949 // DATA
950
951 // wrapper around the output stream that determines the whitespace to
952 // emit around each JSON token
953 FORMATTER *d_formatter_p;
954
955 // human-readable descriptions of all encountered error conditions
956 bsl::ostream *d_logStream_p;
957
958 // if `false` then emit a leading sequence delimiter before the
959 // representation of the value, otherwise do not emit a leading
960 // sequence delimiter
961 bool d_isNextAttributeFirst;
962
963 // options set by the caller of the encoding operation that controls
964 // some aspects of the token sequence to emit
965 const EncoderOptions *d_options_p;
966
967 public:
968 // CREATORS
969
970 /// Construct an `EncodeImplUtil_AttributeVisitor` object having the
971 /// specified `formatter`, `logStream`, `isNextAttributeFirst`, and
972 /// `options` attributes.
973 EncodeImplUtil_AttributeVisitor(FORMATTER *formatter,
974 bsl::ostream *logStream,
976 const EncoderOptions& options);
977
978 // MANIPULATORS
979
980 /// Encode the JSON representation of the specified `attribute`, having
981 /// the name equal to the `name` of the specified `attributeInfo`, to
982 /// the JSON `formatter` attribute of this object according to the
983 /// `formattingMode` attribute of this object. If the
984 /// `isNextAttributeFirst` attribute of this object is `true`, then the
985 /// representation of the attribute contains no leading sequence
986 /// delimiter, and does contain such a delimiter otherwise. The
987 /// `options` attribute of this object configures aspects of the JSON
988 /// representation of the `attribute`. If this operation is not
989 /// successful, load an unspecified, human-readable description of the
990 /// error condition to the `logStream` attribute of this object. Return
991 /// 0 on success, and a non-zero value otherwise.
992 ///
993 /// \pre The behavior is undefined unless the `attribute` satisfies both the static and
994 /// dynamic requirements of the `bdlat` type-category concept
995 /// corresponding to the specified `category`. See the component-level
996 /// documentation of @ref baljsn_encoderoptions for a description of the
997 /// effects, if any, of each option in the `options` on the JSON
998 /// representation of the `attribute`. See the package-level
999 /// documentation of {`bdlat`} for an introduction to the requirements
1000 /// of `bdlat` type-category concepts.
1001 template <class TYPE, class ATTRIBUTE_INFO>
1002 int operator()(const TYPE& attribute, const ATTRIBUTE_INFO& attributeInfo);
1003
1004 // ACCESSORS
1005
1006 /// Return the value of the `isNextAttributeFirst` attribute of this
1007 /// object.
1008 bool isNextAttributeFirst() const;
1009};
1010
1011 // ===================================================
1012 // class EncodeImplUtil_AttributeDispatcher<FORMATTER>
1013 // ===================================================
1014
1015/// This component-private class provides a function object that closes over
1016/// the `formatter`, `logStream`, and `options` parameters that are shared
1017/// between all encoding operations provided in this component. The
1018/// function-call operator of this class provides an overload set that
1019/// accepts an "attribute" object that satisfies one of the `bdlat`
1020/// type-category concepts, and an optional `bdlat_TypeCategory` tag type
1021/// that corresponds to the attribute's `bdlat` type category. Each
1022/// function-call-operator overload encodes a JSON representation of the
1023/// specified attribute to the `formatter` supplied on construction.
1024///
1025/// See @ref baljsn_encodeimplutil
1026template <class FORMATTER>
1028
1029 public:
1030 // TYPES
1031
1032 /// `FormattingMode` is an alias to the type of an `int`-valued
1033 /// `bdlat_FormattingMode` bit-field. A `FormattingMode` value is not
1034 /// valid unless it is equal to an enumerator of `bdlat_FormattingMode`
1035 /// or a valid bitwise-or of two or more such enumerators. See the
1036 /// component-level documentation of @ref bdlat_formattingmode for a
1037 /// description of the set of valid formatting-mode values.
1038 typedef int FormattingMode;
1039
1040 private:
1041 // DATA
1042
1043 // wrapper around the output stream that determines the whitespace to
1044 // emit around each JSON token
1045 FORMATTER *d_formatter_p;
1046
1047 // human-readable descriptions of all encountered error conditions
1048 bsl::ostream *d_logStream_p;
1049
1050 // options set by the caller of the encoding operation that controls
1051 // some aspects of the token sequence to emit
1052 const EncoderOptions *d_options_p;
1053
1054 // name of the attribute
1055 bsl::string_view d_attributeName;
1056
1057 // formatting mode of the attribute
1058 FormattingMode d_formattingMode;
1059
1060 // if `false` then emit a leading sequence delimiter before the
1061 // representation of the value, otherwise do not emit a leading
1062 // sequence delimiter
1063 bool d_isNextAttributeFirst;
1064
1065 public:
1066 // CREATORS
1067
1068 /// Construct an `EncodeImplUtil_AttributeDispatcher` object having the
1069 /// specified `formatter`, `logStream`, `attributeName`, `formattingMode`,
1070 /// `isNextAttributeFirst`, and `options` attributes.
1072 FORMATTER *formatter,
1073 bsl::ostream *logStream,
1074 const bsl::string_view& attributeName,
1075 FormattingMode formattingMode,
1077 const EncoderOptions& options);
1078
1079 // MANIPULATORS
1080
1081 /// Encode the JSON representation of the specified `attribute`, having
1082 /// the name equal to the `name` of the `attributeInfo` attribute of
1083 /// this object, to the JSON `formatter` attribute of this object
1084 /// according to the `formattingMode` attribute of this object. If the
1085 /// `isNextAttributeFirst` attribute of this object is `true`, then the
1086 /// representation of the attribute contains no leading sequence
1087 /// delimiter, and does contain such a delimiter otherwise. The
1088 /// `options` attribute of this object configures aspects of the JSON
1089 /// representation of the `attribute`. If this operation is not
1090 /// successful, load an unspecified, human-readable description of the
1091 /// error condition to the `logStream` attribute of this object. Return
1092 /// 0 on success, and a non-zero value otherwise.
1093 ///
1094 /// \pre The behavior is undefined unless the `attribute` satisfies both the static and
1095 /// dynamic requirements of the `bdlat` type-category concept
1096 /// corresponding to the specified `category`. See the component-level
1097 /// documentation of @ref baljsn_encoderoptions for a description of the
1098 /// effects, if any, of each option in the `options` on the JSON
1099 /// representation of the `attribute`. See the package-level
1100 /// documentation of {`bdlat`} for an introduction to the requirements
1101 /// of `bdlat` type-category concepts.
1102 int operator()(const bsl::vector<char>& attribute,
1103 bdlat_TypeCategory::Array category);
1104 template <class TYPE>
1105 int operator()(const TYPE& attribute, bdlat_TypeCategory::Array category);
1106 template <class TYPE>
1107 int operator()(const TYPE& attribute,
1109 template <class TYPE>
1110 int operator()(const TYPE& attribute,
1112 template <class TYPE>
1113 int operator()(const TYPE& attribute,
1115 template <class TYPE, class CATEGORY>
1116 int operator()(const TYPE& attribute, CATEGORY category);
1117
1118 /// The behavior of this function is undefined.
1119 template <class TYPE>
1120 int operator()(const TYPE&, bslmf::Nil);
1121
1122 // ACCESSORS
1123
1124 /// Return the value of the `isNextAttributeFirst` attribute of this
1125 /// object.
1126 bool isNextAttributeFirst() const;
1127};
1128
1129// ============================================================================
1130// INLINE DEFINITIONS
1131// ============================================================================
1132
1133 // --------------------------------
1134 // struct EncodeImplUtil<FORMATTER>
1135 // --------------------------------
1136
1137// CLASS METHODS
1138
1139template <class FORMATTER>
1141 FORMATTER *formatter,
1142 const bsl::vector<char>& value,
1143 const EncoderOptions& encoderOptions)
1144{
1145 bsl::string base64String;
1146 bdlde::Base64Encoder encoder(0);
1147 base64String.resize(
1148 bdlde::Base64Encoder::encodedLength(static_cast<int>(value.size()), 0));
1149
1150 // Ensure length is a multiple of 4.
1151
1152 BSLS_ASSERT(0 == (base64String.length() & 0x03));
1153
1154 int numOut;
1155 int numIn;
1156 int rc = encoder.convert(base64String.begin(),
1157 &numOut,
1158 &numIn,
1159 value.begin(),
1160 value.end());
1161
1162 if (rc < 0) {
1163 return rc; // RETURN
1164 }
1165
1166 rc = encoder.endConvert(base64String.begin() + numOut);
1167 if (rc < 0) {
1168 return rc; // RETURN
1169 }
1170
1171 return encodeSimpleValue(formatter, base64String, encoderOptions);
1172}
1173
1174 // Member Encoding
1175
1176template <class FORMATTER>
1178 bool *memberIsEmpty,
1179 FORMATTER *formatter,
1180 bsl::ostream *logStream,
1181 const bsl::string_view& memberName,
1182 const bsl::vector<char>& member,
1183 FormattingMode formattingMode,
1184 const EncoderOptions& options,
1185 bool isFirstMember,
1187{
1188 int rc = ThisUtil::encodeMemberPrefix(formatter,
1189 logStream,
1190 memberName,
1191 formattingMode,
1192 isFirstMember);
1193 if (0 != rc) {
1194 return rc; // RETURN
1195 }
1196
1197 rc = ThisUtil::encodeCharArray(formatter, member, options);
1198 if (0 != rc) {
1199 (*logStream) << "Unable to encode value of element "
1200 << "named: '" << memberName << "'."
1201 << bsl::endl;
1202 return rc; // RETURN
1203 }
1204
1205 *memberIsEmpty = false;
1206 return 0;
1207}
1208
1209// Document Encoding Functions
1210
1211template <class FORMATTER>
1213 bsl::ostream *outputStream,
1214 const EncoderOptions& options)
1215{
1217 bdlb::Print::indent(*outputStream,
1218 options.initialIndentLevel(),
1219 options.spacesPerLevel());
1220 }
1221}
1222
1223template <class FORMATTER>
1225 bsl::ostream *outputStream,
1226 const baljsn::EncoderOptions& options)
1227{
1229 (*outputStream) << '\n';
1230 }
1231}
1232
1233// Value Encoding
1234
1235template <class FORMATTER>
1236template <class TYPE>
1237int EncodeImplUtil<FORMATTER>::encode(bsl::ostream *jsonStream,
1238 const TYPE& value,
1239 const EncoderOptions& options)
1240{
1241 bdlsb::MemOutStreamBuf logStreamBuf;
1242 bsl::ostream logStream(&logStreamBuf);
1243
1244 return encode(&logStream, jsonStream, value, options);
1245}
1246
1247template <class FORMATTER>
1248template <class TYPE>
1249int EncodeImplUtil<FORMATTER>::encode(bsl::ostream *logStream,
1250 bsl::ostream *jsonStream,
1251 const TYPE& value,
1252 const EncoderOptions& options)
1253{
1254 static const FormattingMode s_MODE = bdlat_FormattingMode::e_DEFAULT;
1255 static const bool s_FIRST_MEMBER_FLAG = false;
1256
1257 FORMATTER formatter(
1258 *jsonStream,
1260 options.initialIndentLevel(),
1261 options.spacesPerLevel(),
1262 options.escapeForwardSlash());
1263
1264 bool isValueEmpty = false;
1265
1266 int rc = encode(&isValueEmpty,
1267 &formatter,
1268 logStream,
1269 value,
1270 s_MODE,
1271 options,
1272 s_FIRST_MEMBER_FLAG);
1273
1274 if (0 != formatter.nestingDepth()) {
1275 *logStream << "Encoding failed leaving an unclosed element (rc = "
1276 << rc << ")\n";
1277 }
1278
1279 return rc;
1280}
1281
1282template <class FORMATTER>
1283template <class TYPE>
1285 FORMATTER *formatter,
1286 bsl::ostream *logStream,
1287 const TYPE& value,
1288 FormattingMode formattingMode,
1289 const EncoderOptions& options,
1290 bool isFirstMember)
1291{
1293 logStream,
1294 formattingMode,
1295 isFirstMember,
1296 options);
1297
1298 typedef typename bdlat_TypeCategory::Select<TYPE>::Type Category;
1299 int rc = visitor(value, Category());
1300 if (0 != rc) {
1301 return rc; // RETURN
1302 }
1303
1304 *isValueEmpty = visitor.isNextObjectFirst();
1305 return 0;
1306}
1307
1308// Validation
1309
1310template <class FORMATTER>
1311template <class TYPE>
1312int EncodeImplUtil<FORMATTER>::validate(bsl::ostream *logStream,
1313 const TYPE& value,
1315{
1316 return validateChoice(logStream, value);
1317}
1318
1319template <class FORMATTER>
1320template <class TYPE, class CATEGORY>
1322 const TYPE& ,
1323 CATEGORY )
1324{
1325 return 0;
1326}
1327
1328template <class FORMATTER>
1329template <class TYPE>
1331 const TYPE& value)
1332{
1335 (*logStream) << "Undefined selection for Choice object" << bsl::endl;
1336 return -1; // RETURN
1337 }
1338
1339 return 0;
1340}
1341
1342// Encoding Values That Have Specific Type Categories
1343
1344template <class FORMATTER>
1345template <class TYPE>
1347 FORMATTER *formatter,
1348 const TYPE& value,
1349 const EncoderOptions& options)
1350{
1351 return formatter->putValue(value, &options);
1352}
1353
1354// Encoding Value Prefixes and Suffixes
1355
1356template <class FORMATTER>
1358 bool *isPrefixEmpty,
1359 FORMATTER *formatter,
1360 FormattingMode formattingMode)
1361{
1362 if (bdlat_FormattingMode::e_UNTAGGED & formattingMode) {
1363 *isPrefixEmpty = true;
1364 return; // RETURN
1365 }
1366
1367 formatter->openObject();
1368
1369 *isPrefixEmpty = false;
1370}
1371
1372template <class FORMATTER>
1374 bool *isSuffixEmpty,
1375 FORMATTER *formatter,
1376 FormattingMode formattingMode)
1377{
1378 if (bdlat_FormattingMode::e_UNTAGGED & formattingMode) {
1379 *isSuffixEmpty = true;
1380 return; // RETURN
1381 }
1382
1383 formatter->closeObject();
1384
1385 *isSuffixEmpty = false;
1386}
1387
1388// Encoding Arrays That Have Specific Shapes
1389
1390template <class FORMATTER>
1392{
1393 formatter-> openArray(true);
1394 formatter->closeArray(true);
1395}
1396
1397template <class FORMATTER>
1398template <class TYPE>
1400 FORMATTER *formatter,
1401 bsl::ostream *logStream,
1402 const TYPE& value,
1403 const EncoderOptions& options)
1404{
1405 const int size = static_cast<int>(bdlat_ArrayFunctions::size(value));
1406 BSLS_ASSERT(0 < size);
1407
1408 formatter->openArray();
1409
1411 logStream,
1412 true,
1413 options);
1414
1415 for (int index = 0; index != size; ++index) {
1416 int rc = bdlat_ArrayFunctions::accessElement(value, visitor, index);
1417 if (0 != rc) {
1418 return rc; // RETURN
1419 }
1420 }
1421
1422 formatter->closeArray();
1423
1424 return 0;
1425}
1426
1427// Encoding Generalized Members
1428
1429/// ## Implementation Note
1430/// This function purposefully ignores the `EncodeEmptyArrays` option in the
1431/// specified `options` and always encodes the value of the specified
1432/// `member` array. The caller is responsible for checking the value of
1433/// this option and deciding whether to obey the option or not. Callers
1434/// that encode array-valued attributes of sequences must always obey the
1435/// option. Callers that encode array-valued selections of choices must
1436/// never obey the option, and must always encode the array value.
1437template <class FORMATTER>
1438template <class TYPE>
1440 bool *isMemberEmpty,
1441 FORMATTER *formatter,
1442 bsl::ostream *logStream,
1443 const bsl::string_view& memberName,
1444 const TYPE& member,
1445 FormattingMode formattingMode,
1446 const EncoderOptions& options,
1447 bool isFirstMember,
1449{
1450 int rc = ThisUtil::validate(logStream, member, category);
1451 if (0 != rc) {
1452 return rc; // RETURN
1453 }
1454
1455 rc = ThisUtil::encodeMemberPrefix(formatter,
1456 logStream,
1457 memberName,
1458 formattingMode,
1459 isFirstMember);
1460 if (0 != rc) {
1461 return rc; // RETURN
1462 }
1463
1464 if (bdlat_ArrayFunctions::size(member) == 0) {
1465 ThisUtil::encodeEmptyArray(formatter);
1466
1467 *isMemberEmpty = false;
1468 return 0; // RETURN
1469 }
1470
1471 rc = ThisUtil::encodeNonEmptyArray(formatter, logStream, member, options);
1472 if (0 != rc) {
1473 (*logStream) << "Unable to encode value of element "
1474 << "named: '" << memberName << "'." << bsl::endl;
1475 return rc; // RETURN
1476 }
1477
1478 *isMemberEmpty = false;
1479 return 0;
1480}
1481
1482template <class FORMATTER>
1483template <class TYPE, class OTHER_CATEGORY>
1485 bool *isMemberEmpty,
1486 FORMATTER *formatter,
1487 bsl::ostream *logStream,
1488 const bsl::string_view& memberName,
1489 const TYPE& member,
1490 FormattingMode formattingMode,
1491 const EncoderOptions& options,
1492 bool isFirstMember,
1493 OTHER_CATEGORY category)
1494{
1495 int rc = ThisUtil::validate(logStream, member, category);
1496 if (0 != rc) {
1497 return rc; // RETURN
1498 }
1499
1500 bool isPrefixEmpty = false;
1501 rc = ThisUtil::encodeMemberPrefix(&isPrefixEmpty,
1502 formatter,
1503 logStream,
1504 memberName,
1505 formattingMode,
1506 isFirstMember);
1507 if (0 != rc) {
1508 return rc; // RETURN
1509 }
1510
1511 bool isValueEmpty = false;
1512 rc = ThisUtil::encode(&isValueEmpty,
1513 formatter,
1514 logStream,
1515 member,
1516 formattingMode,
1517 options,
1518 !isPrefixEmpty || isFirstMember);
1519 if (0 != rc) {
1520 (*logStream) << "Unable to encode value of element "
1521 << "named: '" << memberName << "'." << bsl::endl;
1522 return rc; // RETURN
1523 }
1524
1525 BSLS_ASSERT(!isValueEmpty || isPrefixEmpty);
1526 // If the value is empty then the prefix is empty. Otherwise, this
1527 // function would produce invalid JSON because it would emit a member name
1528 // token and a colon token, but no member value.
1529
1530 *isMemberEmpty = isFirstMember && isValueEmpty;
1531 return 0;
1532}
1533
1534template <class FORMATTER>
1536 FORMATTER *formatter,
1537 bsl::ostream *logStream,
1538 const bsl::string_view& memberName,
1539 bool isFirstMember)
1540{
1541 if (!isFirstMember) {
1542 formatter->closeMember();
1543 }
1544
1545 int rc = formatter->openMember(memberName);
1546 if (0 != rc) {
1547 (*logStream) << "Unable to encode element name: '" << memberName
1548 << "'." << bsl::endl;
1549 return rc; // RETURN
1550 }
1551
1552 return 0;
1553}
1554
1555template <class FORMATTER>
1557 FORMATTER *formatter,
1558 bsl::ostream *logStream,
1559 const bsl::string_view& memberName,
1560 FormattingMode formattingMode,
1561 bool isFirstMember)
1562{
1563 if (bdlat_FormattingMode::e_UNTAGGED & formattingMode) {
1564 return 0; // RETURN
1565 }
1566
1567 return ThisUtil::encodeMemberPrefix(formatter,
1568 logStream,
1569 memberName,
1570 isFirstMember);
1571}
1572
1573template <class FORMATTER>
1575 bool *isPrefixEmpty,
1576 FORMATTER *formatter,
1577 bsl::ostream *logStream,
1578 const bsl::string_view& memberName,
1579 FormattingMode formattingMode,
1580 bool isFirstMember)
1581{
1582 if (bdlat_FormattingMode::e_UNTAGGED & formattingMode) {
1583 *isPrefixEmpty = true;
1584 return 0; // RETURN
1585 }
1586
1587 int rc = ThisUtil::encodeMemberPrefix(formatter,
1588 logStream,
1589 memberName,
1590 isFirstMember);
1591 if (0 != rc) {
1592 return rc; // RETURN
1593 }
1594
1595 *isPrefixEmpty = false;
1596 return 0;
1597}
1598
1599 // ------------------------------------------------
1600 // struct EncodeImplUtil_ValueDispatcher<FORMATTER>
1601 // ------------------------------------------------
1602
1603// CREATORS
1604template <class FORMATTER>
1605inline
1607 FORMATTER *formatter,
1608 bsl::ostream *logStream,
1609 FormattingMode formattingMode,
1610 bool isNextObjectFirst,
1611 const EncoderOptions& options)
1612: d_formatter_p(formatter)
1613, d_logStream_p(logStream)
1614, d_options_p(&options)
1615, d_formattingMode(formattingMode)
1616, d_isNextObjectFirst(isNextObjectFirst)
1617{
1618}
1619
1620// ACCESSORS
1621template <class FORMATTER>
1622inline
1624 const bsl::vector<char>& value,
1626{
1627 d_isNextObjectFirst = false;
1628 return EncodeImplUtil<FORMATTER>::encodeCharArray(d_formatter_p,
1629 value,
1630 *d_options_p);
1631}
1632
1633template <class FORMATTER>
1634template <class TYPE>
1635inline
1637 const TYPE& value,
1639{
1640 const bool arrayIsEmpty = (0 == bdlat_ArrayFunctions::size(value));
1641
1642 if (arrayIsEmpty && !d_options_p->encodeEmptyArrays()) {
1643 d_isNextObjectFirst = true;
1644 return 0; // RETURN
1645 }
1646
1647 if (arrayIsEmpty && d_options_p->encodeEmptyArrays()) {
1649 d_isNextObjectFirst = false;
1650 return 0; // RETURN
1651 }
1652
1654 d_logStream_p,
1655 value,
1656 *d_options_p);
1657 if (0 != rc) {
1658 return rc; // RETURN
1659 }
1660
1661 d_isNextObjectFirst = false;
1662 return 0;
1663}
1664
1665template <class FORMATTER>
1666template <class TYPE>
1667inline
1669 const TYPE& value,
1671{
1672 int rc = EncodeImplUtil<FORMATTER>::validateChoice(d_logStream_p,
1673 value);
1674 if (0 != rc) {
1675 return rc; // RETURN
1676 }
1677
1678 bool isPrefixEmpty = false;
1680 d_formatter_p,
1681 d_formattingMode);
1682
1684 d_formatter_p,
1685 d_logStream_p,
1686 !isPrefixEmpty || d_isNextObjectFirst,
1687 *d_options_p);
1688 rc = bdlat_ChoiceFunctions::accessSelection(value, visitor);
1689 if (0 != rc) {
1690 return rc; // RETURN
1691 }
1692
1693 const bool isSelectionEmpty = visitor.isNextObjectFirst();
1694
1695 bool isSuffixEmpty = false;
1697 d_formatter_p,
1698 d_formattingMode);
1699
1700 d_isNextObjectFirst = isPrefixEmpty && isSelectionEmpty && isSuffixEmpty;
1701 return 0;
1702}
1703
1704template <class FORMATTER>
1705template <class TYPE>
1706inline
1708 const TYPE& value,
1710{
1712 &d_isNextObjectFirst,
1713 d_formatter_p,
1714 d_logStream_p,
1716 d_formattingMode,
1717 *d_options_p,
1718 d_isNextObjectFirst);
1719}
1720
1721template <class FORMATTER>
1722template <class TYPE>
1723inline
1730
1731template <class FORMATTER>
1732template <class TYPE>
1733inline
1735 const TYPE& value,
1737{
1738 bsl::string valueString;
1739 bdlat_EnumFunctions::toString(&valueString, value);
1740
1741 d_isNextObjectFirst = false;
1743 valueString,
1744 *d_options_p);
1745}
1746
1747template <class FORMATTER>
1748template <class TYPE>
1749inline
1751 const TYPE& value,
1753{
1755 int rc = d_formatter_p->putNullValue();
1756 d_isNextObjectFirst = false;
1757 return rc; // RETURN
1758 }
1759
1760 EncodeImplUtil_ValueDispatcher visitor(d_formatter_p,
1761 d_logStream_p,
1762 d_formattingMode,
1763 d_isNextObjectFirst,
1764 *d_options_p);
1765
1766 int rc = bdlat::NullableValueUtil::accessValueByCategory(value, visitor);
1767 if (0 != rc) {
1768 return rc; // RETURN
1769 }
1770
1771 d_isNextObjectFirst = visitor.isNextObjectFirst();
1772 return 0;
1773}
1774
1775template <class FORMATTER>
1776template <class TYPE>
1777inline
1779 const TYPE& value,
1781{
1782 bool isPrefixEmpty = false;
1784 d_formatter_p,
1785 d_formattingMode);
1786
1788 d_formatter_p,
1789 d_logStream_p,
1790 !isPrefixEmpty || d_isNextObjectFirst,
1791 *d_options_p);
1792
1793 int rc = bdlat_SequenceFunctions::accessAttributes(value, visitor);
1794 if (0 != rc) {
1795 return rc; // RETURN
1796 }
1797
1798 const bool isAttributeEmpty = visitor.isNextAttributeFirst();
1799
1800 bool isSuffixEmpty = false;
1802 d_formatter_p,
1803 d_formattingMode);
1804
1805 d_isNextObjectFirst = isPrefixEmpty && isAttributeEmpty && isSuffixEmpty;
1806 return 0;
1807}
1808
1809template <class FORMATTER>
1810template <class TYPE>
1811inline
1813 const TYPE& value,
1815{
1816 d_isNextObjectFirst = false;
1818 value,
1819 *d_options_p);
1820}
1821
1822template <class FORMATTER>
1823template <class TYPE>
1824inline
1826 bslmf::Nil )
1827{
1828 BSLS_ASSERT_OPT(0 == "Unreachable");
1829 return -1;
1830}
1831
1832// ACCESSORS
1833template <class FORMATTER>
1834inline
1836{
1837 return d_isNextObjectFirst;
1838}
1839
1840 // ----------------------------------------------
1841 // class EncodeImplUtil_ElementVisitor<FORMATTER>
1842 // ----------------------------------------------
1843
1844// CREATORS
1845template <class FORMATTER>
1846inline
1848 FORMATTER *formatter,
1849 bsl::ostream *logStream,
1850 bool isNextElementFirst,
1851 const EncoderOptions& options)
1852: d_formatter_p(formatter)
1853, d_logStream_p(logStream)
1854, d_options_p(&options)
1855, d_isNextElementFirst(isNextElementFirst)
1856{
1857}
1858
1859// MANIPULATORS
1860template <class FORMATTER>
1861template <class TYPE>
1862inline
1864{
1866 d_formatter_p,
1867 d_logStream_p,
1868 d_isNextElementFirst,
1869 *d_options_p);
1870
1871 typedef typename bdlat_TypeCategory::Select<TYPE>::Type Category;
1872 int rc = dispatcher(element, Category());
1873 if (0 != rc) {
1874 return rc; // RETURN
1875 }
1876
1877 d_isNextElementFirst = dispatcher.isNextElementFirst();
1878 return 0;
1879}
1880
1881// ACCESSORS
1882template <class FORMATTER>
1883inline
1885{
1886 return d_isNextElementFirst;
1887}
1888
1889 // -------------------------------------------------
1890 // class EncodeImplUtil_ElementDispatcher<FORMATTER>
1891 // -------------------------------------------------
1892
1893// CREATORS
1894template <class FORMATTER>
1895inline
1897 FORMATTER *formatter,
1898 bsl::ostream *logStream,
1899 bool isNextElementFirst,
1900 const EncoderOptions& options)
1901: d_formatter_p(formatter)
1902, d_logStream_p(logStream)
1903, d_options_p(&options)
1904, d_isNextElementFirst(isNextElementFirst)
1905{
1906}
1907
1908// MANIPULATORS
1909template <class FORMATTER>
1910inline
1912 const bsl::vector<char>& element,
1914{
1915 if (!d_isNextElementFirst) {
1916 d_formatter_p->addArrayElementSeparator();
1917 }
1918
1919 int rc = EncodeImplUtil<FORMATTER>::encodeCharArray(d_formatter_p,
1920 element,
1921 *d_options_p);
1922 if (0 != rc) {
1923 return rc; // RETURN
1924 }
1925
1926 d_isNextElementFirst = false;
1927 return 0;
1928}
1929
1930template <class FORMATTER>
1931template <class TYPE>
1933 const TYPE& element,
1935{
1936 const bool arrayIsEmpty = (0 == bdlat_ArrayFunctions::size(element));
1937
1938 if (arrayIsEmpty && !d_options_p->encodeEmptyArrays()) {
1939 return 0; // RETURN
1940 }
1941
1942 if (!d_isNextElementFirst) {
1943 d_formatter_p->addArrayElementSeparator();
1944 }
1945
1946 if (arrayIsEmpty && d_options_p->encodeEmptyArrays()) {
1948 d_isNextElementFirst = false;
1949 return 0; // RETURN
1950 }
1951
1953 d_logStream_p,
1954 element,
1955 *d_options_p);
1956 if (0 != rc) {
1957 return rc; // RETURN
1958 }
1959
1960 d_isNextElementFirst = false;
1961 return 0;
1962}
1963
1964template <class FORMATTER>
1965template <class TYPE>
1967 const TYPE& element,
1969{
1970 int rc = EncodeImplUtil<FORMATTER>::validateChoice(d_logStream_p, element);
1971 if (0 != rc) {
1972 return rc; // RETURN
1973 }
1974
1975 if (!d_isNextElementFirst) {
1976 d_formatter_p->addArrayElementSeparator();
1977 }
1978
1979 d_formatter_p->openObject();
1980
1981 EncodeImplUtil_SelectionVisitor<FORMATTER> visitor(d_formatter_p,
1982 d_logStream_p,
1983 true,
1984 *d_options_p);
1985 rc = bdlat_ChoiceFunctions::accessSelection(element, visitor);
1986 if (0 != rc) {
1987 return rc; // RETURN
1988 }
1989
1990 d_formatter_p->closeObject();
1991
1992 d_isNextElementFirst = false;
1993 return 0;
1994}
1995
1996template <class FORMATTER>
1997template <class TYPE>
2006
2007template <class FORMATTER>
2008template <class TYPE>
2015
2016template <class FORMATTER>
2017template <class TYPE>
2019 const TYPE& element,
2021{
2022 if (!d_isNextElementFirst) {
2023 d_formatter_p->addArrayElementSeparator();
2024 }
2025
2026 bsl::string valueString;
2027 bdlat_EnumFunctions::toString(&valueString, element);
2028
2029 d_isNextElementFirst = false;
2031 valueString,
2032 *d_options_p);
2033}
2034
2035template <class FORMATTER>
2036template <class TYPE>
2038 const TYPE& element,
2040{
2041 const bool elementIsNull = bdlat_NullableValueFunctions::isNull(element);
2042
2043 if (elementIsNull) {
2044 if (!d_isNextElementFirst) {
2045 d_formatter_p->addArrayElementSeparator();
2046 }
2047
2048 d_isNextElementFirst = false;
2049 int rc = d_formatter_p->putNullValue();
2050 return rc; // RETURN
2051 }
2052
2053 EncodeImplUtil_ElementVisitor<FORMATTER> visitor(d_formatter_p,
2054 d_logStream_p,
2055 d_isNextElementFirst,
2056 *d_options_p);
2057
2058 int rc = bdlat_NullableValueFunctions::accessValue(element, visitor);
2059 if (0 != rc) {
2060 return rc; // RETURN
2061 }
2062
2063 d_isNextElementFirst = visitor.isNextElementFirst();
2064 return 0;
2065}
2066
2067template <class FORMATTER>
2068template <class TYPE>
2070 const TYPE& element,
2072{
2073 if (!d_isNextElementFirst) {
2074 d_formatter_p->addArrayElementSeparator();
2075 }
2076
2077 d_formatter_p->openObject();
2078
2079 EncodeImplUtil_AttributeVisitor<FORMATTER> visitor(d_formatter_p,
2080 d_logStream_p,
2081 true,
2082 *d_options_p);
2083
2084 int rc = bdlat_SequenceFunctions::accessAttributes(element, visitor);
2085 if (0 != rc) {
2086 return rc; // RETURN
2087 }
2088
2089 d_formatter_p->closeObject();
2090
2091 d_isNextElementFirst = false;
2092 return 0;
2093}
2094
2095template <class FORMATTER>
2096template <class TYPE>
2098 const TYPE& element,
2100{
2101 if (!d_isNextElementFirst) {
2102 d_formatter_p->addArrayElementSeparator();
2103 }
2104
2105 d_isNextElementFirst = false;
2107 element,
2108 *d_options_p);
2109}
2110
2111template <class FORMATTER>
2112template <class TYPE>
2114 bslmf::Nil )
2115{
2116 BSLS_ASSERT_OPT(0 == "Unreachable");
2117 return -1;
2118}
2119
2120// ACCESSORS
2121template <class FORMATTER>
2122inline
2124{
2125 return d_isNextElementFirst;
2126}
2127
2128 // ------------------------------------------------
2129 // class EncodeImplUtil_SelectionVisitor<FORMATTER>
2130 // ------------------------------------------------
2131
2132// CREATORS
2133template <class FORMATTER>
2134inline
2136 FORMATTER *formatter,
2137 bsl::ostream *logStream,
2138 bool isNextObjectFirst,
2139 const EncoderOptions& options)
2140: d_formatter_p(formatter)
2141, d_logStream_p(logStream)
2142, d_isNextObjectFirst(isNextObjectFirst)
2143, d_options_p(&options)
2144{
2145}
2146
2147// MANIPULATORS
2148template <class FORMATTER>
2149template <class TYPE, class SELECTION_INFO>
2150inline
2152 const TYPE& selection,
2153 const SELECTION_INFO& selectionInfo)
2154{
2156 d_formatter_p,
2157 d_logStream_p,
2158 selectionInfo.name(),
2159 selectionInfo.formattingMode(),
2160 d_isNextObjectFirst,
2161 *d_options_p);
2162
2163 typedef typename bdlat_TypeCategory::Select<TYPE>::Type Category;
2164 int rc = dispatcher(selection, Category());
2165 if (0 != rc) {
2166 return rc; // RETURN
2167 }
2168
2169 d_isNextObjectFirst = dispatcher.isNextObjectFirst();
2170
2171 return 0;
2172}
2173
2174// ACCESSORS
2175template <class FORMATTER>
2176inline
2178{
2179 return d_isNextObjectFirst;
2180}
2181
2182 // ---------------------------------------------------
2183 // class EncodeImplUtil_SelectionDispatcher<FORMATTER>
2184 // ---------------------------------------------------
2185
2186// CREATORS
2187template <class FORMATTER>
2188inline
2190EncodeImplUtil_SelectionDispatcher(FORMATTER *formatter,
2191 bsl::ostream *logStream,
2192 const bsl::string_view& selectionName,
2193 FormattingMode formattingMode,
2194 bool isNextObjectFirst,
2195 const EncoderOptions& options)
2196: d_formatter_p(formatter)
2197, d_logStream_p(logStream)
2198, d_options_p(&options)
2199, d_selectionName(selectionName)
2200, d_formattingMode(formattingMode)
2201, d_isNextObjectFirst(isNextObjectFirst)
2202{
2203}
2204
2205// MANIPULATORS
2206template <class FORMATTER>
2207template <class TYPE>
2208inline
2217
2218template <class FORMATTER>
2219template <class TYPE>
2220inline
2227
2228template <class FORMATTER>
2229template <class TYPE, class CATEGORY>
2230inline
2232 const TYPE& selection,
2233 CATEGORY category)
2234{
2235 return EncodeImplUtil<FORMATTER>::encodeMember(&d_isNextObjectFirst,
2236 d_formatter_p,
2237 d_logStream_p,
2238 d_selectionName.data(),
2239 selection,
2240 d_formattingMode,
2241 *d_options_p,
2242 d_isNextObjectFirst,
2243 category);
2244}
2245
2246template <class FORMATTER>
2247template <class TYPE>
2248inline
2250 bslmf::Nil )
2251{
2252 BSLS_ASSERT_OPT(0 == "Unreachable");
2253 return -1;
2254}
2255
2256// ACCESSORS
2257template <class FORMATTER>
2258inline
2260{
2261 return d_isNextObjectFirst;
2262}
2263
2264 // ------------------------------------------------
2265 // class EncodeImplUtil_AttributeVisitor<FORMATTER>
2266 // -----------------------------------------------
2267
2268// CREATORS
2269template <class FORMATTER>
2270inline
2272 FORMATTER *formatter,
2273 bsl::ostream *logStream,
2274 bool isNextAttributeFirst,
2275 const EncoderOptions& options)
2276: d_formatter_p(formatter)
2277, d_logStream_p(logStream)
2278, d_isNextAttributeFirst(isNextAttributeFirst)
2279, d_options_p(&options)
2280{
2281}
2282
2283// MANIPULATORS
2284template <class FORMATTER>
2285template <class TYPE, class ATTRIBUTE_INFO>
2287 const TYPE& attribute,
2288 const ATTRIBUTE_INFO& attributeInfo)
2289{
2291 d_formatter_p,
2292 d_logStream_p,
2293 attributeInfo.name(),
2294 attributeInfo.formattingMode(),
2295 d_isNextAttributeFirst,
2296 *d_options_p);
2297
2298 typedef typename bdlat_TypeCategory::Select<TYPE>::Type Category;
2299 int rc = dispatcher(attribute, Category());
2300 if (0 != rc) {
2301 return -rc; // RETURN
2302 }
2303
2304 d_isNextAttributeFirst = dispatcher.isNextAttributeFirst();
2305 return 0;
2306}
2307
2308// ACCESSORS
2309template <class FORMATTER>
2310inline
2312{
2313 return d_isNextAttributeFirst;
2314}
2315
2316 // ---------------------------------------------------
2317 // class EncodeImplUtil_AttributeDispatcher<FORMATTER>
2318 // ---------------------------------------------------
2319
2320// CREATORS
2321template <class FORMATTER>
2322inline
2325 FORMATTER *formatter,
2326 bsl::ostream *logStream,
2327 const bsl::string_view& attributeName,
2328 FormattingMode formattingMode,
2329 bool isNextAttributeFirst,
2330 const EncoderOptions& options)
2331: d_formatter_p(formatter)
2332, d_logStream_p(logStream)
2333, d_options_p(&options)
2334, d_attributeName(attributeName)
2335, d_formattingMode(formattingMode)
2336, d_isNextAttributeFirst(isNextAttributeFirst)
2337{
2338}
2339
2340// MANIPULATORS
2341template <class FORMATTER>
2342inline
2344 const bsl::vector<char>& attribute,
2346{
2347 return EncodeImplUtil<FORMATTER>::encodeMember(&d_isNextAttributeFirst,
2348 d_formatter_p,
2349 d_logStream_p,
2350 d_attributeName.data(),
2351 attribute,
2352 d_formattingMode,
2353 *d_options_p,
2354 d_isNextAttributeFirst,
2355 category);
2356}
2357
2358template <class FORMATTER>
2359template <class TYPE>
2360inline
2362 const TYPE& attribute,
2364{
2365 const bool isArrayEmpty = (0 == bdlat_ArrayFunctions::size(attribute));
2366
2367 if (!d_options_p->encodeEmptyArrays() && isArrayEmpty) {
2368 return 0; // RETURN
2369 }
2370
2371 return EncodeImplUtil<FORMATTER>::encodeMember(&d_isNextAttributeFirst,
2372 d_formatter_p,
2373 d_logStream_p,
2374 d_attributeName.data(),
2375 attribute,
2376 d_formattingMode,
2377 *d_options_p,
2378 d_isNextAttributeFirst,
2379 category);
2380}
2381
2382template <class FORMATTER>
2383template <class TYPE>
2384inline
2393
2394template <class FORMATTER>
2395template <class TYPE>
2396inline
2403
2404template <class FORMATTER>
2405template <class TYPE>
2406inline
2408 const TYPE& attribute,
2410{
2411 if (bdlat_NullableValueFunctions::isNull(attribute) &&
2412 !d_options_p->encodeNullElements()) {
2413 return 0; // RETURN
2414 }
2415
2416 return EncodeImplUtil<FORMATTER>::encodeMember(&d_isNextAttributeFirst,
2417 d_formatter_p,
2418 d_logStream_p,
2419 d_attributeName.data(),
2420 attribute,
2421 d_formattingMode,
2422 *d_options_p,
2423 d_isNextAttributeFirst,
2424 category);
2425}
2426
2427template <class FORMATTER>
2428template <class TYPE, class CATEGORY>
2429inline
2431 const TYPE& attribute,
2432 CATEGORY category )
2433{
2434 return EncodeImplUtil<FORMATTER>::encodeMember(&d_isNextAttributeFirst,
2435 d_formatter_p,
2436 d_logStream_p,
2437 d_attributeName.data(),
2438 attribute,
2439 d_formattingMode,
2440 *d_options_p,
2441 d_isNextAttributeFirst,
2442 category);
2443}
2444
2445template <class FORMATTER>
2446template <class TYPE>
2447inline
2449 bslmf::Nil )
2450{
2451 BSLS_ASSERT_OPT(0 == "Unreachable");
2452 return -1;
2453}
2454
2455// ACCESSORS
2456template <class FORMATTER>
2457inline
2459 const
2460{
2461 return d_isNextAttributeFirst;
2462}
2463
2464} // close package namespace
2465
2466
2467#endif
2468
2469// ----------------------------------------------------------------------------
2470// Copyright 2025 Bloomberg Finance L.P.
2471//
2472// Licensed under the Apache License, Version 2.0 (the "License");
2473// you may not use this file except in compliance with the License.
2474// You may obtain a copy of the License at
2475//
2476// http://www.apache.org/licenses/LICENSE-2.0
2477//
2478// Unless required by applicable law or agreed to in writing, software
2479// distributed under the License is distributed on an "AS IS" BASIS,
2480// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2481// See the License for the specific language governing permissions and
2482// limitations under the License.
2483// ----------------------------- END-OF-FILE ----------------------------------
2484
2485/** @} */
2486/** @} */
2487/** @} */
Definition baljsn_encodeimplutil.h:1027
EncodeImplUtil_AttributeDispatcher(FORMATTER *formatter, bsl::ostream *logStream, const bsl::string_view &attributeName, FormattingMode formattingMode, bool isNextAttributeFirst, const EncoderOptions &options)
Definition baljsn_encodeimplutil.h:2324
int operator()(const bsl::vector< char > &attribute, bdlat_TypeCategory::Array category)
Definition baljsn_encodeimplutil.h:2343
bool isNextAttributeFirst() const
Definition baljsn_encodeimplutil.h:2458
int FormattingMode
Definition baljsn_encodeimplutil.h:1038
Definition baljsn_encodeimplutil.h:935
EncodeImplUtil_AttributeVisitor(FORMATTER *formatter, bsl::ostream *logStream, bool isNextAttributeFirst, const EncoderOptions &options)
Definition baljsn_encodeimplutil.h:2271
int FormattingMode
Definition baljsn_encodeimplutil.h:946
int operator()(const TYPE &attribute, const ATTRIBUTE_INFO &attributeInfo)
Definition baljsn_encodeimplutil.h:2286
bool isNextAttributeFirst() const
Definition baljsn_encodeimplutil.h:2311
Definition baljsn_encodeimplutil.h:633
EncodeImplUtil_ElementDispatcher(FORMATTER *formatter, bsl::ostream *logStream, bool isNextElementFirst, const EncoderOptions &options)
Definition baljsn_encodeimplutil.h:1896
int operator()(const bsl::vector< char > &element, bdlat_TypeCategory::Array category)
Definition baljsn_encodeimplutil.h:1911
bool isNextElementFirst() const
Return the value of the isNextElementFirst attribute of this object.
Definition baljsn_encodeimplutil.h:2123
Definition baljsn_encodeimplutil.h:556
int operator()(const TYPE &element)
Definition baljsn_encodeimplutil.h:1863
bool isNextElementFirst() const
Definition baljsn_encodeimplutil.h:1884
EncodeImplUtil_ElementVisitor(FORMATTER *formatter, bsl::ostream *logStream, bool isNextElementFirst, const EncoderOptions &options)
Definition baljsn_encodeimplutil.h:1847
Definition baljsn_encodeimplutil.h:825
bool isNextObjectFirst() const
Definition baljsn_encodeimplutil.h:2259
int FormattingMode
Definition baljsn_encodeimplutil.h:836
int operator()(const TYPE &selection, bdlat_TypeCategory::CustomizedType category)
Definition baljsn_encodeimplutil.h:2209
EncodeImplUtil_SelectionDispatcher(FORMATTER *formatter, bsl::ostream *logStream, const bsl::string_view &selectionName, FormattingMode formattingMode, bool isNextObjectFirst, const EncoderOptions &options)
Definition baljsn_encodeimplutil.h:2190
Definition baljsn_encodeimplutil.h:733
int FormattingMode
Definition baljsn_encodeimplutil.h:744
bool isNextObjectFirst() const
Definition baljsn_encodeimplutil.h:2177
EncodeImplUtil_SelectionVisitor(FORMATTER *formatter, bsl::ostream *logStream, bool isNextObjectFirst, const EncoderOptions &options)
Definition baljsn_encodeimplutil.h:2135
int operator()(const TYPE &selection, const SELECTION_INFO &selectionInfo)
Definition baljsn_encodeimplutil.h:2151
Definition baljsn_encodeimplutil.h:440
bool isNextObjectFirst() const
Definition baljsn_encodeimplutil.h:1835
int FormattingMode
Definition baljsn_encodeimplutil.h:451
int operator()(const bsl::vector< char > &value, bdlat_TypeCategory::Array category)
Definition baljsn_encodeimplutil.h:1623
EncodeImplUtil_ValueDispatcher(FORMATTER *formatter, bsl::ostream *logStream, FormattingMode formattingMode, bool isNextObjectFirst, const EncoderOptions &options)
Definition baljsn_encodeimplutil.h:1606
Definition baljsn_encoderoptions.h:290
@ e_PRETTY
Definition baljsn_encoderoptions.h:353
baljsn::EncoderOptions::EncodingStyle encodingStyle() const
Definition baljsn_encoderoptions.h:1043
int initialIndentLevel() const
Definition baljsn_encoderoptions.h:1031
bool escapeForwardSlash() const
Return the value of the "EscapeForwardSlash" attribute of this object.
Definition baljsn_encoderoptions.h:1091
int spacesPerLevel() const
Definition baljsn_encoderoptions.h:1037
Definition bdlde_base64encoder.h:497
static bsl::size_t encodedLength(const EncoderOptions &options, bsl::size_t inputLength)
Definition bdlde_base64encoder.h:945
int convert(OUTPUT_ITERATOR out, INPUT_ITERATOR begin, INPUT_ITERATOR end)
Definition bdlde_base64encoder.h:1021
int endConvert(OUTPUT_ITERATOR out)
Definition bdlde_base64encoder.h:1092
Definition bdlsb_memoutstreambuf.h:212
Definition bslstl_stringview.h:471
Definition bslstl_string.h:1252
size_type length() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_string.h:7301
void resize(size_type newLength, CHAR_TYPE character)
Definition bslstl_string.h:5977
void swap(basic_string &other) BSLS_KEYWORD_NOEXCEPT_SPECIFICATION(AllocatorTraits const_iterator begin() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_string.h:2792
size_type size() const BSLS_KEYWORD_NOEXCEPT
Return the number of elements in this vector.
Definition bslstl_vector.h:3019
iterator begin() BSLS_KEYWORD_NOEXCEPT
Definition bslstl_vector.h:2866
iterator end() BSLS_KEYWORD_NOEXCEPT
Definition bslstl_vector.h:2874
Definition bslstl_vector.h:1120
static int accessByCategory(const TYPE &object, ACCESSOR &accessor)
Definition bdlat_typecategory.h:1455
#define BSLS_ASSERT(X)
Definition bsls_assert.h:1976
#define BSLS_ASSERT_OPT(X)
Definition bsls_assert.h:2045
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
Definition baljsn_convertfromjsonoptions.h:112
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)
const BaseType< TYPE >::Type & convertToBaseType(const TYPE &object)
Load into the specified result the value of the specified object.
void toString(bsl::string *result, const TYPE &value)
bool isNull(const TYPE &object)
int accessValue(const TYPE &object, ACCESSOR &accessor)
int accessAttributes(const TYPE &object, ACCESSOR &accessor)
Definition baljsn_encodeimplutil.h:134
static int encodeCharArray(FORMATTER *formatter, const bsl::vector< char > &value, const EncoderOptions &options)
Definition baljsn_encodeimplutil.h:1140
EncodeImplUtil ThisUtil
ThisUtil is a convenience alias for this utility struct.
Definition baljsn_encodeimplutil.h:139
static int encode(bsl::ostream *jsonStream, const TYPE &value, const EncoderOptions &options=EncoderOptions())
Definition baljsn_encodeimplutil.h:1237
static void closeDocument(bsl::ostream *outputStream, const EncoderOptions &options)
Definition baljsn_encodeimplutil.h:1224
static void encodeObjectPrefix(bool *isPrefixEmpty, FORMATTER *formatter, FormattingMode formattingMode)
Definition baljsn_encodeimplutil.h:1357
static void openDocument(bsl::ostream *outputStream, const EncoderOptions &options)
Definition baljsn_encodeimplutil.h:1212
int FormattingMode
Definition baljsn_encodeimplutil.h:147
static int encodeSimpleValue(FORMATTER *formatter, const TYPE &value, const EncoderOptions &options)
Definition baljsn_encodeimplutil.h:1346
static int encodeMemberPrefix(FORMATTER *formatter, bsl::ostream *logStream, const bsl::string_view &memberName, bool isFirstMember)
Definition baljsn_encodeimplutil.h:1535
static int encodeMember(bool *isMemberEmpty, FORMATTER *formatter, bsl::ostream *logStream, const bsl::string_view &memberName, const bsl::vector< char > &member, FormattingMode formattingMode, const EncoderOptions &options, bool isFirstMember, bdlat_TypeCategory::Array category)
Definition baljsn_encodeimplutil.h:1177
static void encodeEmptyArray(FORMATTER *formatter)
Definition baljsn_encodeimplutil.h:1391
static int validate(bsl::ostream *logStream, const TYPE &value, bdlat_TypeCategory::Choice category)
Definition baljsn_encodeimplutil.h:1312
static int validateChoice(bsl::ostream *logStream, const TYPE &value)
Definition baljsn_encodeimplutil.h:1330
static int encodeNonEmptyArray(FORMATTER *formatter, bsl::ostream *logStream, const TYPE &value, const EncoderOptions &options)
Definition baljsn_encodeimplutil.h:1399
static void encodeObjectSuffix(bool *isSuffixEmpty, FORMATTER *formatter, FormattingMode formattingMode)
Definition baljsn_encodeimplutil.h:1373
static int accessValueByCategory(const TYPE &object, ACCESSOR &accessor)
Definition bdlat_nullablevalueutil.h:328
@ e_DEFAULT
Definition bdlat_formattingmode.h:114
@ e_UNTAGGED
Definition bdlat_formattingmode.h:122
Definition bdlat_typecategory.h:1037
Definition bdlat_typecategory.h:1038
Definition bdlat_typecategory.h:1039
Definition bdlat_typecategory.h:1036
Definition bdlat_typecategory.h:1040
Definition bdlat_typecategory.h:1041
Definition bdlat_typecategory.h:1042
Definition bdlat_typecategory.h:1043
static bsl::ostream & indent(bsl::ostream &stream, int level, int spacesPerLevel=4)
Definition bslmf_nil.h:133