BDE 4.39.x Production Release
Loading...
Searching...
No Matches
baljsn_decoder.h
Go to the documentation of this file.
1/// @file baljsn_decoder.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// baljsn_decoder.h -*-C++-*-
8#ifndef INCLUDED_BALJSN_DECODER
9#define INCLUDED_BALJSN_DECODER
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup baljsn_decoder baljsn_decoder
15/// @brief Provide a JSON decoder for `bdeat` compatible types.
16/// @addtogroup bal
17/// @{
18/// @addtogroup baljsn
19/// @{
20/// @addtogroup baljsn_decoder
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#baljsn_decoder-purpose"> Purpose</a>
25/// * <a href="#baljsn_decoder-classes"> Classes </a>
26/// * <a href="#baljsn_decoder-description"> Description </a>
27/// * <a href="#baljsn_decoder-validateinputisutf8-option"> validateInputIsUtf8 Option </a>
28/// * <a href="#baljsn_decoder-strict-conformance"> Strict Conformance </a>
29/// * <a href="#baljsn_decoder-usage"> Usage </a>
30/// * <a href="#baljsn_decoder-example-1-decoding-into-a-bas_codegen-pl-generated-from-data-in-json"> Example 1: Decoding into a bas_codegen.pl-generated from data in JSON </a>
31///
32/// # Purpose {#baljsn_decoder-purpose}
33/// Provide a JSON decoder for `bdeat` compatible types.
34///
35/// # Classes {#baljsn_decoder-classes}
36///
37/// - baljsn::Decoder: JSON decoder for `bdeat`-compliant types
38///
39/// @see baljsn_decoderoptions, balsjn_decoderoptionsutil,
40/// baljsn_encoder, baljsn_parserutil, baljsn_parser
41///
42/// # Description {#baljsn_decoder-description}
43/// This component provides a class, `baljsn::Decoder`, for
44/// decoding value-semantic objects in the JSON format. In particular, the
45/// `class` contains a parameterized `decode` function that decodes an object
46/// from a specified stream. There are two overloaded versions of this
47/// function:
48///
49/// * one that reads from a `bsl::streambuf`
50/// * one that reads from a `bsl::istream`
51///
52/// This component can be used with types that support the `bdeat` framework
53/// (see the `bdeat` package for details), which is a compile-time interface for
54/// manipulating struct-like and union-like objects. In particular, types
55/// generated by the `bas_codegen.pl` tool, and other dynamic types, can be
56/// decoded using this `class`. The `decode` function can be invoked on any
57/// object that satisfies the requirements of a sequence, choice, or array
58/// object as defined in the @ref bdlat_sequencefunctions , @ref bdlat_choicefunctions ,
59/// and @ref bdlat_arrayfunctions components.
60///
61/// Although the JSON format is easy to read and write and is very useful for
62/// debugging, it is relatively expensive to encode and decode and relatively
63/// bulky to transmit. It is more efficient to use a binary encoding (such as
64/// BER) if the encoding format is under your control (see @ref balber_berdecoder ).
65///
66/// Refer to the details of the JSON encoding format supported by this decoder
67/// in the package documentation file (doc/baljsn.txt).
68///
69/// ## validateInputIsUtf8 Option {#baljsn_decoder-validateinputisutf8-option}
70///
71///
72/// The `baljsn::DecoderOption` parameter of the `decode` function has a
73/// configuration option named `validateInputIsUtf8`. If this option is `true`,
74/// the `decode` function will succeed only if the encoding of the JSON data is
75/// UTF-8, which the JSON specification requires. If the option is `false`,
76/// `decode` will not validate that the encoding of the JSON data is UTF-8, and
77/// may succeed even if the data does not satisfy the UTF-8 validity requirement
78/// of the JSON specification. This option primarily affects the acceptance of
79/// string literals, which are the parts of JSON documents that may have
80/// rational justification for having non-UTF-8, and therefore invalid, content.
81///
82/// Ideally, users *should* set `validateInputIsUtf8` to `true`. However, some
83/// legacy applications currently might be trafficking in JSON that contains
84/// non-UTF-8 with no adverse effects to their clients. Consequently, this
85/// option is `false` by default to maintain backward compatibility.
86///
87/// ## Strict Conformance {#baljsn_decoder-strict-conformance}
88///
89///
90/// The `baljsn::Decoder` class allows several convenient variances from the
91/// JSON grammar as described in RFC8259 (see
92/// https://www.rfc-editor.org/rfc/rfc8259). If strict conformance is needed,
93/// users should use the `read` overloads that accept a `baljsn::DecoderOptions`
94/// object and set the following attributes to the values shown below:
95/// @code
96/// validateInputIsUtf8() == true;
97/// allowConsecutiveSeparators() == false;
98/// allowFormFeedAsWhitespace() == false;
99/// allowUnescapedControlCharacters() == false;
100/// @endcode
101/// See also {@ref bdljsn_tokenizer |Strict Conformance}.
102///
103/// ## Usage {#baljsn_decoder-usage}
104///
105///
106/// This section illustrates intended use of this component.
107///
108/// ## Example 1: Decoding into a bas_codegen.pl-generated from data in JSON {#baljsn_decoder-example-1-decoding-into-a-bas_codegen-pl-generated-from-data-in-json}
109///
110///
111/// Consider that we want to exchange an employee's information between two
112/// processes. To allow this information exchange we will define the XML schema
113/// representation for that class, use `bas_codegen.pl` to create the `Employee`
114/// `class` for storing that information, and decode into that object using the
115/// `baljsn` decoder.
116///
117/// First, we will define the XML schema inside a file called `employee.xsd`:
118/// @code
119/// <?xml version='1.0' encoding='UTF-8'?>
120/// <xs:schema xmlns:xs='http://www.w3.org/2001/XMLSchema'
121/// xmlns:test='http://bloomberg.com/schemas/test'
122/// targetNamespace='http://bloomberg.com/schemas/test'
123/// elementFormDefault='unqualified'>
124///
125/// <xs:complexType name='Address'>
126/// <xs:sequence>
127/// <xs:element name='street' type='xs:string'/>
128/// <xs:element name='city' type='xs:string'/>
129/// <xs:element name='state' type='xs:string'/>
130/// </xs:sequence>
131/// </xs:complexType>
132///
133/// <xs:complexType name='Employee'>
134/// <xs:sequence>
135/// <xs:element name='name' type='xs:string'/>
136/// <xs:element name='homeAddress' type='test:Address'/>
137/// <xs:element name='age' type='xs:int'/>
138/// </xs:sequence>
139/// </xs:complexType>
140///
141/// <xs:element name='Employee' type='test:Employee'/>
142///
143/// </xs:schema>
144/// @endcode
145/// Then, we will use the `bas_codegen.pl` tool, to generate the C++ classes for
146/// this schema. The following command will generate the header and
147/// implementation files for the all the classes in the @ref test_messages
148/// components in the current directory:
149/// @code
150/// $ bas_codegen.pl -m msg -p test xsdfile.xsd
151/// @endcode
152/// Next, we will create a `test::Employee` object:
153/// @code
154/// test::Employee employee;
155/// @endcode
156/// Then, we will create a `baljsn::Decoder` object:
157/// @code
158/// baljsn::Decoder decoder;
159/// @endcode
160/// Next, we will specify the input data provided to the decoder:
161/// @code
162/// const char INPUT[] = "{\"name\":\"Bob\",\"homeAddress\":{\"street\":"
163/// "\"Lexington Ave\",\"city\":\"New York City\","
164/// "\"state\":\"New York\"},\"age\":21}";
165///
166/// bsl::istringstream is(INPUT);
167/// @endcode
168/// Now, we will decode this object using the `decode` function of the baljsn
169/// decoder by providing it a `baljsn::DecoderOptions` object. The decoder
170/// options allow us to specify that unknown elements should *not* be skipped.
171/// Setting this option to `false` will result in the decoder returning an error
172/// on encountering an unknown element:
173/// @code
174/// baljsn::DecoderOptions options;
175/// options.setSkipUnknownElements(false);
176///
177/// const int rc = decoder.decode(is, &employee, options);
178/// assert(!rc);
179/// assert(is);
180/// @endcode
181/// Finally, we will verify that the decoded object is as expected:
182/// @code
183/// assert("Bob" == employee.name());
184/// assert("Lexington Ave" == employee.homeAddress().street());
185/// assert("New York City" == employee.homeAddress().city());
186/// assert("New York" == employee.homeAddress().state());
187/// assert(21 == employee.age());
188/// @endcode
189/// @}
190/** @} */
191/** @} */
192
193/** @addtogroup bal
194 * @{
195 */
196/** @addtogroup baljsn
197 * @{
198 */
199/** @addtogroup baljsn_decoder
200 * @{
201 */
202
203#include <balscm_version.h>
204
206#include <baljsn_parserutil.h>
207#include <baljsn_tokenizer.h>
208
209#include <bdlar_isref.h>
210#include <bdlar_refutil.h>
211
212#include <bdlat_attributeinfo.h>
215#include <bdlat_enumfunctions.h>
216#include <bdlat_enumutil.h>
217#include <bdlat_formattingmode.h>
218#include <bdlat_selectioninfo.h>
220#include <bdlat_typecategory.h>
222
223#include <bdlb_printmethods.h>
224
226
227#include <bsla_fallthrough.h>
228
229#include <bslmf_assert.h>
230#include <bslmf_isintegral.h>
231
232#include <bsls_assert.h>
233#include <bsls_types.h>
234
235#include <bsl_iostream.h>
236#include <bsl_sstream.h>
237#include <bsl_streambuf.h>
238#include <bsl_string.h>
239#include <bsl_string_view.h>
240#include <bsl_unordered_set.h>
241
242
243namespace baljsn {
244
245 // =============
246 // class Decoder
247 // =============
248
249/// This class provides a mechanism for decoding JSON data into
250/// value-semantic objects. The `decode` methods are function templates
251/// that will decode any object that meets the requirements of a sequence,
252/// choice, or array object as defined in the @ref bdlat_sequencefunctions ,
253/// @ref bdlat_choicefunctions , and @ref bdlat_choicefunctions components
254/// respectively. These generic frameworks provide a common compile-time
255/// interface for manipulating struct-like and union-like objects. In
256/// particular, the types generated by `bas_codegen.pl` provide the
257/// necessary interface and can be decoded using this component.
258///
259/// See @ref baljsn_decoder
260class Decoder {
261
262 // DATA
263 bsl::ostringstream d_logStream; // stream to record errors
264 Tokenizer d_tokenizer; // JSON tokenizer
265 bsl::string d_elementName; // current element name
266 int d_currentDepth; // current decoding depth
267 int d_maxDepth; // max decoding depth
268 bool d_skipUnknownElements; // skip unknown elements flag
269 int d_numUnknownElementsSkipped; // number of unknown
270 // elements skipped
271 bool d_allowMissingRequiredAttributes; // allow missing
272 // non-optional attrs
273
274 // FRIENDS
277
278 // PRIVATE TYPES
280
281 // PRIVATE MANIPULATORS
282
283 /// Decode into the specified `value`, of a (template parameter) `TYPE`
284 /// corresponding to the specified `bdeat` `category`, the JSON data
285 /// currently referred to by the tokenizer owned by this object, using
286 /// the specified formatting `mode`. Return 0 on success and a non-zero value otherwise.
287 ///
288 /// \pre The behavior is undefined unless `value`
289 /// corresponds to the specified `bdeat` category and `mode` is a valid
290 /// formatting mode as specified in `bdlat_FormattingMode`.
291 ///
292 /// \note Note that `ANY_CATEGORY` shall be a tag-type defined in `bdlat_TypeCategory`.
293 template <class TYPE>
294 int decodeImp(TYPE *value, int mode, bdlat_TypeCategory::DynamicType);
295 template <class TYPE>
296 int decodeImp(TYPE *value, int mode, bdlat_TypeCategory::Sequence);
297 template <class TYPE>
298 int decodeImp(TYPE *value, int mode, bdlat_TypeCategory::Choice);
299 template <class TYPE>
300 int decodeImp(TYPE *value, int mode, bdlat_TypeCategory::Enumeration);
301 template <class TYPE>
302 int decodeImp(TYPE *value, int mode, bdlat_TypeCategory::CustomizedType);
303 template <class TYPE>
304 int decodeImp(TYPE *value, int mode, bdlat_TypeCategory::Simple);
305 template <class TYPE>
306 int decodeImp(TYPE *value, int mode, bdlat_TypeCategory::Array);
307 template <class TYPE>
308 int decodeImp(TYPE *value, int mode, bdlat_TypeCategory::NullableValue);
309 int decodeImp(bsl::vector<char> *value,
310 int mode,
312 template <class TYPE, class ANY_CATEGORY>
313 int decodeImp(TYPE *value, ANY_CATEGORY category);
314
315 /// Log the latest tokenizer error to `d_logStream`. If the tokenizer
316 /// did not have an error, log the specified `alternateString`. Return
317 /// a reference to `d_logStream`.
318 bsl::ostream& logTokenizerError(const char *alternateString);
319
320 /// Skip the unknown element specified by `elementName` by discarding
321 /// all the data associated with it and advancing the parser to the next
322 /// element. Return 0 on success and a non-zero value otherwise.
323 int skipUnknownElement(const bsl::string_view& elementName);
324
325 private:
326 // NOT IMPLEMENTED
327 Decoder(const Decoder&);
328 Decoder& operator=(const Decoder&);
329
330 public:
331 // CREATORS
332
333 /// Construct a decoder object using the optionally specified
334 /// `basicAllocator`. If `basicAllocator` is 0, the default allocator
335 /// is used.
336 explicit Decoder(bslma::Allocator *basicAllocator = 0);
337
338 // MANIPULATORS
339
340 /// Decode into the specified `value`, of a (template parameter) `TYPE`,
341 /// the JSON data read from the specified `streamBuf` and using the
342 /// specified `options`. Specifying a nullptr `options` is equivalent
343 /// to passing a default-constructed DecoderOptions in `options`.
344 /// `TYPE` shall be a `bdeat`-compatible sequence, choice, or array
345 /// type, or a `bdeat`-compatible dynamic type referring to one of those
346 /// types. Return 0 on success, and a non-zero value otherwise.
347 ///
348 /// \note Note that this operation internally buffers input from `streambuf`, and
349 /// if decoding is successful, will attempt to update the input position
350 /// of `streambuf` to the last unprocessed byte.
351 template <class TYPE>
352 int decode(bsl::streambuf *streamBuf,
353 TYPE *value,
354 const DecoderOptions& options);
355 template <class TYPE>
356 int decode(bsl::streambuf *streamBuf,
357 TYPE *value,
358 const DecoderOptions *options);
359
360 /// Decode into the specified `value`, of a (template parameter) `TYPE`,
361 /// the JSON data read from the specified `stream` and using the
362 /// specified `options`. `TYPE` shall be a `bdeat`-compatible sequence,
363 /// choice, or array type, or a `bdeat`-compatible dynamic type
364 /// referring to one of those types. Specifying a nullptr `options` is
365 /// equivalent to passing a default-constructed DecoderOptions in
366 /// `options`. Return 0 on success, and a non-zero value otherwise.
367 ///
368 /// \note Note that this operation internally buffers input from `stream`, and
369 /// if decoding is successful, will attempt to update the input position
370 /// of `stream` to the last unprocessed byte.
371 template <class TYPE>
372 int decode(bsl::istream& stream,
373 TYPE *value,
374 const DecoderOptions& options);
375 template <class TYPE>
376 int decode(bsl::istream& stream,
377 TYPE *value,
378 const DecoderOptions *options);
379
380 /// Decode an object of (template parameter) `TYPE` from the specified
381 /// `streamBuf` and load the result into the specified modifiable `value`.
382 /// Return 0 on success, and a non-zero value otherwise.
383 ///
384 /// @deprecated Use @ref decode function passed a reference to a
385 /// non-modifiable `DecoderOptions` object instead.
386 template <class TYPE>
387 int decode(bsl::streambuf *streamBuf, TYPE *value);
388
389 /// Decode an object of (template parameter) `TYPE` from the specified
390 /// `stream` and load the result into the specified modifiable `value`.
391 /// Return 0 on success, and a non-zero value otherwise.
392 ///
393 /// \note Note that `stream` will be invalidated if the decoding fails.
394 ///
395 /// @deprecated Use @ref decode function passed a reference to a
396 /// non-modifiable `DecoderOptions` object instead.
397 template <class TYPE>
398 int decode(bsl::istream& stream, TYPE *value);
399
400 /// Decode into the specified `value`, of a (template parameter) `TYPE`,
401 /// the JSON data read from the specified `streamBuf` and using the
402 /// specified `options`. Specifying a nullptr `options` is equivalent to
403 /// passing a default-constructed `DecoderOptions` in `options`. `TYPE`
404 /// shall be a `bdlat`-compatible sequence, choice, or array type, or a
405 /// `bdlat`-compatible dynamic type referring to one of those types. Return 0 on success, and a non-zero value otherwise.
406 ///
407 /// \note Note that this
408 /// function behaves identically to `decode`, but does not instantiate any
409 /// templates at compile time at the expense of being slightly slower at
410 /// runtime; see the `baljsn` package documentation for more details.
411 template <class TYPE>
412 int decodeAny(bsl::streambuf *streamBuf,
413 TYPE *value,
414 const DecoderOptions& options);
415 template <class TYPE>
416 int decodeAny(bsl::streambuf *streamBuf,
417 TYPE *value,
418 const DecoderOptions *options = 0);
419 int decodeAny(bsl::streambuf *streamBuf,
420 bdlar::AnyRef *value,
421 const DecoderOptions& options);
422
423 /// Decode into the specified `value`, of a (template parameter) `TYPE`,
424 /// the JSON data read from the specified `stream` and using the specified
425 /// `options`. `TYPE` shall be a `bdlat`-compatible sequence, choice, or
426 /// array type, or a `bdlat`-compatible dynamic type referring to one of
427 /// those types. Specifying a nullptr `options` is equivalent to passing a
428 /// default-constructed `DecoderOptions` in `options`. Return 0 on success, and a non-zero value otherwise.
429 ///
430 /// \note Note that this function
431 /// behaves identically to `decode`, but does not instantiate any templates
432 /// at compile time at the expense of being slightly slower at runtime; see
433 /// the `baljsn` package documentation for more details.
434 template <class TYPE>
435 int decodeAny(bsl::istream& stream,
436 TYPE *value,
437 const DecoderOptions& options);
438 template <class TYPE>
439 int decodeAny(bsl::istream& stream,
440 TYPE *value,
441 const DecoderOptions *options = 0);
442 int decodeAny(bsl::istream& stream,
443 bdlar::AnyRef *value,
444 const DecoderOptions& options);
445
446 // ACCESSORS
447
448 /// Return a string containing any error, warning, or trace messages that
449 /// were logged during the last call to the `decode` method. The log is
450 /// reset each time `decode` is called.
452
453 /// Return the number of unknown elements that were skipped during the previous decoding operation.
454 ///
455 /// \note Note that unknown elements are skipped
456 /// only if `options.skipUnknownElements() == true`.
457 int numUnknownElementsSkipped() const;
458};
459
460 // =============================
461 // struct Decoder_ElementVisitor
462 // =============================
463
464/// This `class` implements a visitor for decoding elements within a sequence,
465/// choice, or array type. This is a component-private class and should not be used outside of this component.
466///
467/// \note Note that the operators provided in this
468/// `class` match the function signatures required of visitors decoding into
469/// elements of compatible types.
470///
471/// See @ref baljsn_decoder
473
474 // DATA
475 Decoder *d_decoder_p; // decoder (held, not owned)
476 int d_mode; // formatting mode
477
478 // CREATORS
479
480 // Creators have been omitted to allow simple static initialization of this
481 // struct.
482
483 // MANIPULATORS
484
485 /// Decode into the specified `value` the data in the JSON format.
486 /// Return 0 on success and a non-zero value otherwise.
487 template <class TYPE>
488 int operator()(TYPE *value);
489
490 /// Decode into the specified `value` using the specified `info` the data
491 /// in the JSON format. Return 0 on success and a non-zero value
492 /// otherwise.
493 template <class TYPE, class INFO>
494 int operator()(TYPE *value, const INFO& info);
495};
496
497 // =============================
498 // struct Decoder_DecodeImpProxy
499 // =============================
500
501/// This class provides a functor that dispatches the appropriate `decodeImp` method for a `bdeat` Dynamic type.
502///
503/// \note Note that the operators provided in
504/// this `class` match the function signatures required of visitors decoding
505/// into compatible types.
506///
507/// See @ref baljsn_decoder
509
510 // DATA
511 Decoder *d_decoder_p; // decoder (held, not owned)
512 int d_mode; // formatting mode
513
514 // CREATORS
515
516 // Creators have been omitted to allow simple static initialization of this
517 // struct.
518
519 // MANIPULATORS
520 template <class TYPE>
521 int operator()(TYPE *, bslmf::Nil);
522
523 /// Dencode into the specified `value` of the specified `bdeat` `category`
524 /// from the data in the JSON format. Return 0 on success and a non-zero
525 /// value otherwise.
526 template <class TYPE, class ANY_CATEGORY>
527 int operator()(TYPE *object, ANY_CATEGORY category);
528};
529
530 // ===================================
531 // struct Decoder_RequiredAttrsVisitor
532 // ===================================
533
534/// This class provides a functor that finds and remembers all non-optional
535/// sequence attributes.
536///
537/// See @ref baljsn_decoder
539 // PUBLIC DATA
542
543 // MANIPULATORS
544 template <class TYPE, class INFO>
545 int operator()(TYPE *value, const INFO& info);
546};
547
548// ============================================================================
549// INLINE DEFINITIONS
550// ============================================================================
551
552 // -------------
553 // class Decoder
554 // -------------
555
556// PRIVATE TYPES
558 // PUBLIC DATA
562
563 // MANIPULATORS
564 template <class t_BASE_TYPE>
566 operator()(t_BASE_TYPE *value) {
567 int rc = ParserUtil::getValue(value, d_dataValue);
568 // For integral base types, we also accept a quoted representation
569 // (DRQS 166048981).
573 }
574 if (rc) {
575 d_logStream << "Could not decode Enum Customized, "
576 << "value not allowed \"" << d_dataValue << "\"\n";
577 return -1; // RETURN
578 }
579 d_convertCalled = true;
580 return 0;
581 }
582
583 /// Stub for the `bdlar` ref types.
584 template <class t_REF>
586 operator()(t_REF *) {
587 return -1;
588 }
589};
590
591// PRIVATE MANIPULATORS
592template <class TYPE>
593inline
594int Decoder::decodeImp(TYPE *value, int mode, bdlat_TypeCategory::DynamicType)
595{
596 Decoder_DecodeImpProxy proxy = { this, mode };
598}
599
600template <class TYPE>
601int Decoder::decodeImp(TYPE *value, int mode, bdlat_TypeCategory::Sequence)
602{
604 // This is an anonymous element. Do not read anything and instead
605 // decode into the corresponding sub-element.
606
608 *value,
609 d_elementName.data(),
610 static_cast<int>(d_elementName.length()))) {
611 Decoder_ElementVisitor visitor = { this, mode };
612
614 value,
615 visitor,
616 d_elementName.data(),
617 static_cast<int>(d_elementName.length()))) {
618 d_logStream << "Could not decode sequence, error decoding "
619 << "element or bad element name '"
620 << d_elementName << "' \n";
621 return -1; // RETURN
622 }
623 }
624 else {
625 if (d_skipUnknownElements) {
626 const int rc = skipUnknownElement(d_elementName);
627 if (rc) {
628 d_logStream << "Error reading unknown element '"
629 << d_elementName << "' or after it\n";
630 return -1; // RETURN
631 }
632 }
633 else {
634 d_logStream << "Unknown element '" << d_elementName
635 << "' found\n";
636 return -1; // RETURN
637 }
638 }
639 }
640 else {
641 if (++d_currentDepth > d_maxDepth) {
642 d_logStream << "Maximum allowed decoding depth reached: "
643 << d_currentDepth << "\n";
644 return -1; // RETURN
645 }
646
647 if (Tokenizer::e_START_OBJECT != d_tokenizer.tokenType()) {
648 d_logStream << "Could not decode sequence, missing starting '{'\n";
649 return -1; // RETURN
650 }
651
652 int rc = d_tokenizer.advanceToNextToken();
653 if (rc) {
654 d_logStream << "Could not decode sequence, ";
655 logTokenizerError("error") << " reading token after '{'\n";
656 return -1; // RETURN
657 }
658
660 bsl::unordered_set<bsl::string> requiredAttributes(&localAllocator);
661 if (!d_allowMissingRequiredAttributes) {
662 // Collect a list of the non-optional attributes
663 Decoder_RequiredAttrsVisitor visitor = {&requiredAttributes,
664 ::BloombergLP::bdlat_UsesDefaultValueFlag<TYPE>::value};
666 }
667
668 while (Tokenizer::e_ELEMENT_NAME == d_tokenizer.tokenType()) {
669
670 bslstl::StringRef elementName;
671 rc = d_tokenizer.value(&elementName);
672 if (rc) {
673 d_logStream << "Error reading attribute name after '{'\n";
674 return -1; // RETURN
675 }
676
678 *value,
679 elementName.data(),
680 static_cast<int>(elementName.length()))) {
681 d_elementName = elementName;
682
683 rc = d_tokenizer.advanceToNextToken();
684 if (rc) {
685 logTokenizerError("Error") << " reading value for"
686 << " attribute '" << d_elementName << "' \n";
687 return -1; // RETURN
688 }
689
690 Decoder_ElementVisitor visitor = { this, mode };
691
693 value,
694 visitor,
695 d_elementName.data(),
696 static_cast<int>(d_elementName.length()))) {
697 d_logStream << "Could not decode sequence, error decoding "
698 << "element or bad element name '"
699 << d_elementName << "' \n";
700 return -1; // RETURN
701 }
702
703 if (!requiredAttributes.empty()) {
704 requiredAttributes.erase(elementName);
705 }
706 }
707 else {
708 if (d_skipUnknownElements) {
709 rc = skipUnknownElement(elementName);
710 if (rc) {
711 d_logStream << "Error reading unknown element '"
712 << elementName << "' or after it\n";
713 return -1; // RETURN
714 }
715 }
716 else {
717 d_logStream << "Unknown element '"
718 << elementName << "' found\n";
719 return -1; // RETURN
720 }
721 }
722
723 rc = d_tokenizer.advanceToNextToken();
724 if (rc) {
725 d_logStream << "Could not decode sequence, ";
726 logTokenizerError("error") << " reading token"
727 << " after value for attribute '"
728 << d_elementName << "' \n";
729 return -1; // RETURN
730 }
731 }
732
733 if (Tokenizer::e_END_OBJECT != d_tokenizer.tokenType()) {
734 d_logStream << "Could not decode sequence, "
735 << "missing terminator '}' or seperator ','\n";
736 return -1; // RETURN
737 }
738
739 if (!requiredAttributes.empty()) {
740 // There are non-optional attributes that are not presented
741 // in the decoded message (sequence).
742 d_logStream << "Could not decode sequence, "
743 << "missing required attribute \""
744 << *requiredAttributes.begin() << "\"\n";
745 return -1; // RETURN
746 }
747
748 --d_currentDepth;
749 }
750 return 0;
751}
752
753template <class TYPE>
754int Decoder::decodeImp(TYPE *value,
755 int mode,
757{
759 // This is an anonymous element. Do not read anything and instead
760 // decode into the corresponding sub-element.
761
762 bslstl::StringRef selectionName;
763 selectionName.assign(d_elementName.begin(), d_elementName.end());
764
766 *value,
767 selectionName.data(),
768 static_cast<int>(selectionName.length()))) {
770 value,
771 selectionName.data(),
772 static_cast<int>(selectionName.length()))) {
773 d_logStream << "Could not decode choice, bad selection name '"
774 << selectionName << "' \n";
775 return -1; // RETURN
776 }
777
778 Decoder_ElementVisitor visitor = { this, mode };
779
781 visitor)) {
782 d_logStream << "Could not decode choice, selection "
783 << "was not decoded\n";
784 return -1; // RETURN
785 }
786 }
787 else {
788 if (d_skipUnknownElements) {
789 const int rc = skipUnknownElement(selectionName);
790 if (rc) {
791 d_logStream << "Error reading unknown element '"
792 << selectionName << "' or after that "
793 << "element\n";
794 return -1; // RETURN
795 }
796 }
797 else {
798 d_logStream << "Unknown element '"
799 << selectionName << "' found\n";
800 return -1; // RETURN
801 }
802 }
803 }
804 else {
805 if (++d_currentDepth > d_maxDepth) {
806 d_logStream << "Maximum allowed decoding depth reached: "
807 << d_currentDepth << "\n";
808 return -1; // RETURN
809 }
810
811 if (Tokenizer::e_START_OBJECT != d_tokenizer.tokenType()) {
812 d_logStream << "Could not decode choice, missing starting {\n";
813 return -1; // RETURN
814 }
815
816 int rc = d_tokenizer.advanceToNextToken();
817 if (rc) {
818 d_logStream << "Could not decode choice, ";
819 logTokenizerError("error") << " reading token after {\n";
820 return -1; // RETURN
821 }
822
823 if (Tokenizer::e_ELEMENT_NAME == d_tokenizer.tokenType()) {
824 bslstl::StringRef selectionName;
825 rc = d_tokenizer.value(&selectionName);
826 if (rc) {
827 d_logStream << "Error reading selection name after '{'\n";
828 return -1; // RETURN
829 }
830
832 *value,
833 selectionName.data(),
834 static_cast<int>(selectionName.length()))) {
836 value,
837 selectionName.data(),
838 static_cast<int>(selectionName.length()))) {
839 d_logStream << "Could not decode choice, bad selection "
840 << "name '" << selectionName << "' \n";
841 return -1; // RETURN
842 }
843
844 rc = d_tokenizer.advanceToNextToken();
845 if (rc) {
846 d_logStream << "Could not decode choice, ";
847 logTokenizerError("error") << " reading value \n";
848 return -1; // RETURN
849 }
850
851 Decoder_ElementVisitor visitor = { this, mode };
852
854 visitor)) {
855 d_logStream << "Could not decode choice, selection "
856 << "was not decoded\n";
857 return -1; // RETURN
858 }
859 }
860 else {
861 if (d_skipUnknownElements) {
862 rc = skipUnknownElement(selectionName);
863 if (rc) {
864 d_logStream << "Error reading unknown element '"
865 << selectionName << "' or after that "
866 << "element\n";
867 return -1; // RETURN
868 }
869 }
870 else {
871 d_logStream << "Unknown element '"
872 << selectionName << "' found\n";
873 return -1; // RETURN
874 }
875 }
876
877 rc = d_tokenizer.advanceToNextToken();
878 if (rc) {
879 d_logStream << "Could not decode choice, ";
880 logTokenizerError("error") << " reading token after value for"
881 " selection \n";
882
883 return -1; // RETURN
884 }
885 }
886
887 if (Tokenizer::e_END_OBJECT != d_tokenizer.tokenType()) {
888 d_logStream << "Could not decode choice, "
889 << "missing terminator '}'\n";
890 return -1; // RETURN
891 }
892
893 --d_currentDepth;
894 }
895 return 0;
896}
897
898template <class TYPE>
899int Decoder::decodeImp(TYPE *value, int, bdlat_TypeCategory::Enumeration)
900{
901 enum { k_MIN_ENUM_STRING_LENGTH = 2 };
902
903 if (Tokenizer::e_ELEMENT_VALUE != d_tokenizer.tokenType()) {
904 d_logStream << "Enumeration element value was not found\n";
905 return -1; // RETURN
906 }
907
908 bslstl::StringRef dataValue;
909 int rc = d_tokenizer.value(&dataValue);
910 if (rc) {
911 d_logStream << "Error reading enumeration value\n";
912 return -1; // RETURN
913 }
914
915 if (dataValue.length() >= k_MIN_ENUM_STRING_LENGTH &&
916 '"' == dataValue.front() && '"' == dataValue.back()) {
917 const int kBufSize = 128;
919 bsl::string tmpString(&bufferAllocator);
920
921 rc = baljsn::ParserUtil::getValue(&tmpString, dataValue);
922 if (rc) {
923 d_logStream << "Error reading enumeration value\n";
924 return -1; // RETURN
925 }
926
928 value, tmpString.data(), static_cast<int>(tmpString.size()));
929 if (rc) {
930 d_logStream << "Could not decode Enum String, value not allowed \""
931 << dataValue << "\"\n";
932 }
933
934 return rc; // RETURN
935 }
936
937 // We also accept an unquoted integer (DRQS 166048981).
938 int intValue;
939 rc = ParserUtil::getValue(&intValue, dataValue);
940 if (rc) {
941 d_logStream << "Error reading enumeration value\n";
942 return -1; // RETURN
943 }
944
946 if (rc) {
947 d_logStream << "Could not decode int Enum, value " << intValue
948 << " not allowed\n";
949 }
950
951 return rc;
952}
953
954template <class TYPE>
955int Decoder::decodeImp(TYPE *value, int, bdlat_TypeCategory::CustomizedType)
956{
957 if (Tokenizer::e_ELEMENT_VALUE != d_tokenizer.tokenType()) {
958 d_logStream << "Customized element value was not found\n";
959 return -1; // RETURN
960 }
961
962 bslstl::StringRef dataValue;
963 int rc = d_tokenizer.value(&dataValue);
964 if (rc) {
965 d_logStream << "Error reading customized type value\n";
966 return -1; // RETURN
967 }
968
969 CustomizedManipulator baseManipulator = {d_logStream, dataValue, false};
971 baseManipulator);
972
973 if (rc && baseManipulator.d_convertCalled) {
974 d_logStream << "Could not convert base type to customized type, "
975 << "base value disallowed: \"";
976 bdlb::PrintMethods::print(d_logStream, dataValue, 0, -1);
977 d_logStream << "\"\n";
978 }
979 return rc;
980}
981
982template <class TYPE>
983int Decoder::decodeImp(TYPE *value, int, bdlat_TypeCategory::Simple)
984{
985 if (Tokenizer::e_ELEMENT_VALUE != d_tokenizer.tokenType()) {
986 d_logStream << "Simple element value was not found\n";
987 return -1; // RETURN
988 }
989
990 bslstl::StringRef dataValue;
991 int rc = d_tokenizer.value(&dataValue);
992 if (rc) {
993 d_logStream << "Error reading simple value\n";
994 return -1; // RETURN
995 }
996
997 rc = ParserUtil::getValue(value, dataValue);
998 // For integral types, we also accept a quoted representation
999 // (DRQS 166048981).
1000 if (bsl::is_integral<TYPE>::value && 0 != rc &&
1001 ParserUtil::stripQuotes(&dataValue)) {
1002 rc = ParserUtil::getValue(value, dataValue);
1003 }
1004 return rc;
1005}
1006
1007inline
1008int Decoder::decodeImp(bsl::vector<char> *value,
1009 int,
1011{
1012 if (Tokenizer::e_ELEMENT_VALUE != d_tokenizer.tokenType()) {
1013 d_logStream << "Could not decode vector<char> "
1014 << "expected as an element value\n";
1015 return -1; // RETURN
1016 }
1017
1018 bslstl::StringRef dataValue;
1019 int rc = d_tokenizer.value(&dataValue);
1020
1021 if (rc) {
1022 d_logStream << "Error reading customized type element value\n";
1023 return -1; // RETURN
1024 }
1025
1026 return ParserUtil::getValue(value, dataValue);
1027}
1028
1029template <class TYPE>
1030int Decoder::decodeImp(TYPE *value,
1031 int mode,
1033{
1034 if (Tokenizer::e_START_ARRAY != d_tokenizer.tokenType()) {
1035 d_logStream << "Could not decode vector, missing start token: '['\n";
1036 return -1; // RETURN
1037 }
1038
1039 int rc = d_tokenizer.advanceToNextToken();
1040 if (rc) {
1041 logTokenizerError("Error") << " reading array.\n";
1042 return rc; // RETURN
1043 }
1044
1045 int i = 0;
1046 while (Tokenizer::e_END_ARRAY != d_tokenizer.tokenType()) {
1047 if (Tokenizer::e_ELEMENT_VALUE == d_tokenizer.tokenType()
1048 || Tokenizer::e_START_OBJECT == d_tokenizer.tokenType()
1049 || Tokenizer::e_START_ARRAY == d_tokenizer.tokenType()) {
1050 ++i;
1052
1053 Decoder_ElementVisitor visitor = { this, mode };
1054
1056 visitor,
1057 i - 1)) {
1058 d_logStream << "Error adding element '" << i - 1 << "'\n";
1059 return -1; // RETURN
1060 }
1061
1062 rc = d_tokenizer.advanceToNextToken();
1063 if (rc) {
1064 logTokenizerError("Error") << " reading token after value of"
1065 " element '" << i - 1 << "'\n";
1066 return rc; // RETURN
1067 }
1068 }
1069 else {
1070 d_logStream << "Erroneous token found instead of array element\n";
1071 return -1; // RETURN
1072 }
1073 }
1074
1075 if (Tokenizer::e_END_ARRAY != d_tokenizer.tokenType()) {
1076 d_logStream << "Could not decode vector, missing end token: ']'\n";
1077 return -1; // RETURN
1078 }
1079
1080 return 0;
1081}
1082
1083template <class TYPE>
1084int Decoder::decodeImp(TYPE *value,
1085 int mode,
1087{
1088 enum { k_NULL_VALUE_LENGTH = 4 };
1089
1090 if (Tokenizer::e_ELEMENT_VALUE == d_tokenizer.tokenType()) {
1091 bslstl::StringRef dataValue;
1092 const int rc = d_tokenizer.value(&dataValue);
1093 if (rc) {
1094 return rc; // RETURN
1095 }
1096
1097 if (k_NULL_VALUE_LENGTH == dataValue.length()
1098 && 'n' == dataValue[0]
1099 && 'u' == dataValue[1]
1100 && 'l' == dataValue[2]
1101 && 'l' == dataValue[3]) {
1102 return 0; // RETURN
1103 }
1104 }
1105
1107
1108 Decoder_ElementVisitor visitor = { this, mode };
1109 return bdlat_NullableValueFunctions::manipulateValue(value, visitor);
1110}
1111
1112template <class TYPE, class ANY_CATEGORY>
1113inline
1114int Decoder::decodeImp(TYPE *, ANY_CATEGORY)
1115{
1116 BSLS_ASSERT_OPT(0 == "Unreachable");
1117
1118 return -1;
1119}
1120
1121// CREATORS
1122inline
1123Decoder::Decoder(bslma::Allocator *basicAllocator)
1124: d_logStream(basicAllocator)
1125, d_tokenizer(basicAllocator)
1126, d_elementName(basicAllocator)
1127, d_currentDepth(0)
1128, d_maxDepth(0)
1129, d_skipUnknownElements(false)
1130, d_numUnknownElementsSkipped(0)
1131, d_allowMissingRequiredAttributes(
1132 DecoderOptions::DEFAULT_INITIALIZER_ALLOW_MISSING_REQUIRED_ATTRIBUTES)
1133{
1134}
1135
1136// MANIPULATORS
1137template <class TYPE>
1138int Decoder::decode(bsl::streambuf *streamBuf,
1139 TYPE *value,
1140 const DecoderOptions& options)
1141{
1142 BSLS_ASSERT(streamBuf);
1143 BSLS_ASSERT(value);
1144
1145 d_logStream.clear();
1146 d_logStream.str("");
1147
1148 d_currentDepth = 0;
1149 d_maxDepth = options.maxDepth();
1150 d_skipUnknownElements = options.skipUnknownElements();
1151 d_numUnknownElementsSkipped = 0;
1152
1153 d_allowMissingRequiredAttributes =
1155
1156 bdlat_TypeCategory::Value category =
1158
1161 && bdlat_TypeCategory::e_ARRAY_CATEGORY != category) {
1162 d_logStream << "The object being decoded must be a Sequence, "
1163 << "Choice, or Array type\n";
1164 return -1; // RETURN
1165 }
1166
1167 d_tokenizer.reset(streamBuf);
1168 d_tokenizer
1170 .setAllowHeterogenousArrays(true) // needed for nillable arrays
1177
1178 typedef typename bdlat_TypeCategory::Select<TYPE>::Type TypeCategory;
1179
1180 int rc = d_tokenizer.advanceToNextToken();
1181 if (rc) {
1182 logTokenizerError("Error") << " advancing to the first token. "
1183 "Expecting a '{' or '[' as the first character\n";
1184 return rc; // RETURN
1185 }
1186
1188
1189 rc = decodeImp(value, 0, TypeCategory());
1190
1191 d_tokenizer.resetStreamBufGetPointer();
1192
1193 return rc;
1194}
1195
1196template <class TYPE>
1197int Decoder::decode(bsl::streambuf *streamBuf,
1198 TYPE *value,
1199 const DecoderOptions *options)
1200{
1201 DecoderOptions localOpts;
1202 return decode(streamBuf, value, options ? *options : localOpts);
1203}
1204
1205template <class TYPE>
1206int Decoder::decode(bsl::istream& stream,
1207 TYPE *value,
1208 const DecoderOptions& options)
1209{
1210 if (!stream.good()) {
1211 d_logStream
1212 << "Input stream state is not 'good()' ["
1213 << (stream.bad() ? " 'bad()'" : "")
1214 << (stream.fail() ? " 'fail()'" : "")
1215 << (stream.eof() ? " 'eof()'" : "")
1216 << " ] - nothing to decode\n";
1217 return -1; // RETURN
1218 }
1219
1220 if (0 != decode(stream.rdbuf(), value, options)) {
1221 stream.setstate(bsl::ios_base::failbit);
1222 return -1; // RETURN
1223 }
1224
1225 return 0;
1226}
1227
1228template <class TYPE>
1229int Decoder::decode(bsl::istream& stream,
1230 TYPE *value,
1231 const DecoderOptions *options)
1232{
1233 DecoderOptions localOpts;
1234 return decode(stream, value, options ? *options : localOpts);
1235}
1236
1237template <class TYPE>
1238int Decoder::decode(bsl::streambuf *streamBuf, TYPE *value)
1239{
1240 const DecoderOptions options;
1241 return decode(streamBuf, value, options);
1242}
1243
1244template <class TYPE>
1245int Decoder::decode(bsl::istream& stream, TYPE *value)
1246{
1247 const DecoderOptions options;
1248 return decode(stream, value, options);
1249}
1250
1251template <class TYPE>
1252inline
1253int Decoder::decodeAny(bsl::streambuf *streamBuf,
1254 TYPE *value,
1255 const DecoderOptions& options)
1256{
1258 return decodeAny(streamBuf, &any, options);
1259}
1260
1261template <class TYPE>
1262inline
1263int Decoder::decodeAny(bsl::streambuf *streamBuf,
1264 TYPE *value,
1265 const DecoderOptions *options)
1266{
1267 return decodeAny(streamBuf, value, options ? *options : DecoderOptions());
1268}
1269
1270template <class TYPE>
1271inline
1272int Decoder::decodeAny(bsl::istream& stream,
1273 TYPE *value,
1274 const DecoderOptions& options)
1275{
1277 return decodeAny(stream, &any, options);
1278}
1279
1280template <class TYPE>
1281inline
1282int Decoder::decodeAny(bsl::istream& stream,
1283 TYPE *value,
1284 const DecoderOptions *options)
1285{
1286 return decodeAny(stream, value, options ? *options : DecoderOptions());
1287}
1288
1289// ACCESSORS
1290inline
1292{
1293 return d_logStream.str();
1294}
1295
1296inline
1298{
1299 return d_numUnknownElementsSkipped;
1300}
1301
1302 // -----------------------------
1303 // struct Decoder_ElementVisitor
1304 // -----------------------------
1305
1306template <class TYPE>
1307inline
1309{
1310 typedef typename bdlat_TypeCategory::Select<TYPE>::Type TypeCategory;
1311 return d_decoder_p->decodeImp(value, d_mode, TypeCategory());
1312}
1313
1314template <class TYPE, class INFO>
1315inline
1316int Decoder_ElementVisitor::operator()(TYPE *value, const INFO& info)
1317{
1318 typedef typename bdlat_TypeCategory::Select<TYPE>::Type TypeCategory;
1319 return d_decoder_p->decodeImp(value,
1320 info.formattingMode(),
1321 TypeCategory());
1322}
1323
1324 // -----------------------------
1325 // struct Decoder_DecodeImpProxy
1326 // -----------------------------
1327
1328// MANIPULATORS
1329template <class TYPE>
1330inline
1332{
1333 BSLS_ASSERT_OPT(0 == "Unreachable");
1334
1335 return -1;
1336}
1337
1338template <class TYPE, class ANY_CATEGORY>
1339inline
1341 ANY_CATEGORY category)
1342{
1343 return d_decoder_p->decodeImp(object, d_mode, category);
1344}
1345
1346 // -----------------------------------
1347 // struct Decoder_RequiredAttrsVisitor
1348 // -----------------------------------
1349
1350// MANIPULATORS
1351template <class TYPE, class INFO>
1352inline
1353int Decoder_RequiredAttrsVisitor::operator()(TYPE *value, const INFO& info) {
1355 {
1357 break; // skip
1358 // The following categories can have default values:
1363 break; // skip
1364 }
1366 default:
1368 !(info.formattingMode() & bdlat_FormattingMode::e_DEFAULT_VALUE)) {
1369 d_requiredAttributes_p->emplace(info.name(), info.nameLength());
1370 }
1371 }
1372 return 0;
1373}
1374
1375} // close package namespace
1376
1377
1378#endif
1379
1380// ----------------------------------------------------------------------------
1381// Copyright 2015 Bloomberg Finance L.P.
1382//
1383// Licensed under the Apache License, Version 2.0 (the "License");
1384// you may not use this file except in compliance with the License.
1385// You may obtain a copy of the License at
1386//
1387// http://www.apache.org/licenses/LICENSE-2.0
1388//
1389// Unless required by applicable law or agreed to in writing, software
1390// distributed under the License is distributed on an "AS IS" BASIS,
1391// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1392// See the License for the specific language governing permissions and
1393// limitations under the License.
1394// ----------------------------- END-OF-FILE ----------------------------------
1395
1396/** @} */
1397/** @} */
1398/** @} */
Definition baljsn_decoderoptions.h:155
bool validateInputIsUtf8() const
Definition baljsn_decoderoptions.h:739
bool allowUnescapedControlCharacters() const
Definition baljsn_decoderoptions.h:757
bool allowMissingRequiredAttributes() const
Definition baljsn_decoderoptions.h:763
bool skipUnknownElements() const
Definition baljsn_decoderoptions.h:733
bool allowConsecutiveSeparators() const
Definition baljsn_decoderoptions.h:745
bool allowFormFeedAsWhitespace() const
Definition baljsn_decoderoptions.h:751
int maxDepth() const
Return the value of the "MaxDepth" attribute of this object.
Definition baljsn_decoderoptions.h:727
Definition baljsn_decoder.h:260
friend struct Decoder_ElementVisitor
Definition baljsn_decoder.h:276
int decodeAny(bsl::streambuf *streamBuf, bdlar::AnyRef *value, const DecoderOptions &options)
int decodeAny(bsl::istream &stream, bdlar::AnyRef *value, const DecoderOptions &options)
int numUnknownElementsSkipped() const
Definition baljsn_decoder.h:1297
int decode(bsl::streambuf *streamBuf, TYPE *value, const DecoderOptions &options)
Definition baljsn_decoder.h:1138
bsl::string loggedMessages() const
Definition baljsn_decoder.h:1291
int decodeAny(bsl::streambuf *streamBuf, TYPE *value, const DecoderOptions &options)
Definition baljsn_decoder.h:1253
Definition bdlar_anyref.h:85
static bsl::enable_if<!IsDynamic< t_TYPE >::value, AnyRef >::type makeAnyRef(t_TYPE &object)
Make AnyRef to the specified object.
Definition bdlar_refutil.h:209
Definition bdljsn_tokenizer.h:234
int resetStreamBufGetPointer()
TokenType tokenType() const
Return the token type of the current token.
Definition bdljsn_tokenizer.h:944
Tokenizer & setAllowConsecutiveSeparators(bool value)
Definition bdljsn_tokenizer.h:790
Tokenizer & setAllowHeterogenousArrays(bool value)
Definition bdljsn_tokenizer.h:799
Tokenizer & setAllowStandAloneValues(bool value)
Definition bdljsn_tokenizer.h:826
Tokenizer & setAllowUnescapedControlCharacters(bool value)
Definition bdljsn_tokenizer.h:844
Tokenizer & setAllowTrailingTopLevelComma(bool value)
Definition bdljsn_tokenizer.h:835
Tokenizer & setAllowFormFeedAsWhitespace(bool value)
Definition bdljsn_tokenizer.h:808
void reset(bsl::streambuf *streambuf)
Definition bdljsn_tokenizer.h:772
Tokenizer & setAllowNonUtf8StringLiterals(bool value)
Definition bdljsn_tokenizer.h:817
@ e_ELEMENT_NAME
Definition bdljsn_tokenizer.h:245
@ e_END_OBJECT
Definition bdljsn_tokenizer.h:247
@ e_END_ARRAY
Definition bdljsn_tokenizer.h:249
@ e_ELEMENT_VALUE
Definition bdljsn_tokenizer.h:250
@ e_START_ARRAY
Definition bdljsn_tokenizer.h:248
@ e_START_OBJECT
Definition bdljsn_tokenizer.h:246
int value(bsl::string_view *data) const
Definition bdlma_localsequentialallocator.h:230
Definition bslstl_stringview.h:471
BSLS_KEYWORD_CONSTEXPR_CPP14 const_reference back() const
Definition bslstl_stringview.h:1977
BSLS_KEYWORD_CONSTEXPR_CPP14 const_reference front() const
Definition bslstl_stringview.h:1966
Definition bslstl_string.h:1252
size_type length() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_string.h:7301
iterator end() BSLS_KEYWORD_NOEXCEPT
Return the past-the-end iterator for this modifiable string.
Definition bslstl_string.h:6065
CHAR_TYPE * data() BSLS_KEYWORD_NOEXCEPT
Definition bslstl_string.h:7177
void swap(basic_string &other) BSLS_KEYWORD_NOEXCEPT_SPECIFICATION(AllocatorTraits const_iterator begin() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_string.h:2792
basic_string & erase(size_type position=0, size_type numChars=npos)
Definition bslstl_string.h:6740
Definition bslstl_unorderedset.h:733
Definition bslstl_vector.h:1120
Definition bslma_allocator.h:545
Definition bslstl_stringref.h:374
const CHAR_TYPE * data() const
Definition bslstl_stringref.h:962
size_type length() const
Definition bslstl_stringref.h:984
void assign(const CHAR_TYPE *data, INT_TYPE length, typename bsl::enable_if< bsl::is_integral< INT_TYPE >::value, bslmf::Nil >::type=bslmf::Nil())
Definition bslstl_stringref.h:847
static int manipulateByCategory(TYPE *object, MANIPULATOR &manipulator)
Definition bdlat_typecategory.h:1414
#define BSLA_FALLTHROUGH
Definition bsla_fallthrough.h:188
#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
int manipulateElement(TYPE *array, MANIPULATOR &manipulator, int index)
void resize(TYPE *array, int newSize)
bool hasSelection(const TYPE &object, const char *selectionName, int selectionNameLength)
int manipulateSelection(TYPE *object, MANIPULATOR &manipulator)
int makeSelection(TYPE *object, int selectionId)
int createBaseAndConvert(t_TYPE *object, t_MANIPULATOR &baseManipulator)
int manipulateValue(TYPE *object, MANIPULATOR &manipulator)
void makeValue(TYPE *object)
int manipulateAttribute(TYPE *object, MANIPULATOR &manipulator, const char *attributeName, int attributeNameLength)
int manipulateAttributes(TYPE *object, MANIPULATOR &manipulator)
bool hasAttribute(const TYPE &object, const char *attributeName, int attributeNameLength)
bdlat_TypeCategory::Value select(const TYPE &object)
void reset(TYPE *object)
Reset the value of the specified object to its default value.
bsl::ostream & print(bsl::ostream &stream, const TYPE &object, int level=0, int spacesPerLevel=4)
Definition bdlb_printmethods.h:725
basic_ostringstream< char, char_traits< char >, allocator< char > > ostringstream
Definition bslstl_iosfwd.h:97
Definition baljsn_decoder.h:557
bool d_convertCalled
Definition baljsn_decoder.h:561
bsl::enable_if< bdlar::IsRef< t_REF >::value, int >::type operator()(t_REF *)
Stub for the bdlar ref types.
Definition baljsn_decoder.h:586
bslstl::StringRef d_dataValue
Definition baljsn_decoder.h:560
bsl::ostringstream & d_logStream
Definition baljsn_decoder.h:559
bsl::enable_if<!bdlar::IsRef< t_BASE_TYPE >::value, int >::type operator()(t_BASE_TYPE *value)
Definition baljsn_decoder.h:566
Definition baljsn_decoder.h:508
int operator()(TYPE *, bslmf::Nil)
Definition baljsn_decoder.h:1331
int d_mode
Definition baljsn_decoder.h:512
Decoder * d_decoder_p
Definition baljsn_decoder.h:511
Definition baljsn_decoder.h:472
int d_mode
Definition baljsn_decoder.h:476
int operator()(TYPE *value)
Definition baljsn_decoder.h:1308
Decoder * d_decoder_p
Definition baljsn_decoder.h:475
Definition baljsn_decoder.h:538
bsl::unordered_set< bsl::string > * d_requiredAttributes_p
Definition baljsn_decoder.h:540
int operator()(TYPE *value, const INFO &info)
Definition baljsn_decoder.h:1353
bool d_usesDefaultValueFlag
Definition baljsn_decoder.h:541
static int getValue(bool *value, const bsl::string_view &data)
static bool stripQuotes(bsl::string_view *str)
static int fromIntOrFallbackIfEnabled(TYPE *result, int number)
Definition bdlat_enumutil.h:333
static int fromStringOrFallbackIfEnabled(TYPE *result, const char *string, int stringLength)
Definition bdlat_enumutil.h:347
@ e_DEFAULT_VALUE
Definition bdlat_formattingmode.h:127
@ 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
Value
Definition bdlat_typecategory.h:1046
@ e_ARRAY_CATEGORY
Definition bdlat_typecategory.h:1048
@ e_CHOICE_CATEGORY
Definition bdlat_typecategory.h:1049
@ e_SEQUENCE_CATEGORY
Definition bdlat_typecategory.h:1053
@ e_SIMPLE_CATEGORY
Definition bdlat_typecategory.h:1054
@ e_CUSTOMIZED_TYPE_CATEGORY
Definition bdlat_typecategory.h:1050
@ e_NULLABLE_VALUE_CATEGORY
Definition bdlat_typecategory.h:1052
@ e_ENUMERATION_CATEGORY
Definition bdlat_typecategory.h:1051
Definition bslmf_enableif.h:530
Definition bslmf_isintegral.h:140
Definition bslmf_nil.h:133