BDE 4.39.x Production Release
Loading...
Searching...
No Matches
balber_berencoder.h
Go to the documentation of this file.
1/// @file balber_berencoder.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// balber_berencoder.h -*-C++-*-
8#ifndef INCLUDED_BALBER_BERENCODER
9#define INCLUDED_BALBER_BERENCODER
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup balber_berencoder balber_berencoder
15/// @brief Provide a BER encoder class.
16/// @addtogroup bal
17/// @{
18/// @addtogroup balber
19/// @{
20/// @addtogroup balber_berencoder
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#balber_berencoder-purpose"> Purpose</a>
25/// * <a href="#balber_berencoder-classes"> Classes </a>
26/// * <a href="#balber_berencoder-description"> Description </a>
27/// * <a href="#balber_berencoder-usage"> Usage </a>
28/// * <a href="#balber_berencoder-example-1-encoding-an-employee-record"> Example 1: Encoding an Employee Record </a>
29///
30/// # Purpose {#balber_berencoder-purpose}
31/// Provide a BER encoder class.
32///
33/// # Classes {#balber_berencoder-classes}
34///
35/// - balber::BerEncoder: BER encoder
36///
37/// @see balber_berdecoder, bdem_bdemencoder, balxml_encoder
38///
39/// # Description {#balber_berencoder-description}
40/// This component defines a single class, `balber::BerEncoder`,
41/// that contains a parameterized `encode` function. The `encode` function
42/// encodes the object of the parameterized type into the specified stream.
43/// The `encode` method is overloaded for two types of output streams:
44/// * `bsl::streambuf`
45/// * `bsl::ostream`
46///
47/// This component encodes objects based on the X.690 BER specification. It can
48/// only be used with types supported by the `bdlat` framework.
49///
50/// Note that encoding top-level `array` objects (a.k.a. `sequence-of` types, in
51/// the X.680-X.693 specs) is not allowed.
52///
53/// ## Usage {#balber_berencoder-usage}
54///
55///
56/// This section illustrates intended use of this component.
57///
58/// ### Example 1: Encoding an Employee Record {#balber_berencoder-example-1-encoding-an-employee-record}
59///
60///
61/// Suppose that an "employee record" consists of a sequence of attributes --
62/// `name`, `age`, and `salary` -- that are of types `bsl::string`, `int`, and
63/// `float`, respectively. Furthermore, we have a need to BER encode employee
64/// records as a sequence of values (for out-of-process consumption).
65///
66/// Assume that we have defined a `usage::EmployeeRecord` class to represent
67/// employee record values, and assume that we have provided the `bdlat`
68/// specializations that allow the `balber` codec components to represent class
69/// values as a sequence of BER primitive values. See
70/// {@ref bdlat_sequencefunctions |Usage} for details of creating specializations
71/// for a sequence type.
72///
73/// First, we create an employee record object having typical values:
74/// @code
75/// usage::EmployeeRecord bob("Bob", 56, 1234.00);
76/// assert("Bob" == bob.name());
77/// assert( 56 == bob.age());
78/// assert(1234.00 == bob.salary());
79/// @endcode
80/// Now, we create a `balber::Encoder` object and use it to encode our `bob`
81/// object. Here, to facilitate the examination of our results, the BER
82/// encoding data is delivered to a `bdlsb::MemOutStreamBuf` object:
83/// @code
84/// bdlsb::MemOutStreamBuf osb;
85/// balber::BerEncoder encoder;
86/// int rc = encoder.encode(&osb, bob);
87/// assert( 0 == rc);
88/// assert(18 == osb.length());
89/// @endcode
90/// Finally, we confirm that the generated BER encoding has the expected layout
91/// and values. We create an `bdlsb::FixedMemInStreamBuf` to manage our access
92/// to the data portion of the `bdlsb::MemOutStreamBuf` where our BER encoding
93/// resides:
94/// @code
95/// bdlsb::FixedMemInStreamBuf isb(osb.data(), osb.length());
96/// @endcode
97/// The @ref balber_berutil component provides functions that allow us to decode
98/// the descriptive fields and values of the BER encoded sequence:
99/// @code
100/// balber::BerConstants::TagClass tagClass;
101/// balber::BerConstants::TagType tagType;
102/// int tagNumber;
103/// int accumNumBytesConsumed = 0;
104/// int length;
105///
106/// rc = balber::BerUtil::getIdentifierOctets(&isb,
107/// &tagClass,
108/// &tagType,
109/// &tagNumber,
110/// &accumNumBytesConsumed);
111/// assert(0 == rc);
112/// assert(balber::BerConstants::e_UNIVERSAL == tagClass);
113/// assert(balber::BerConstants::e_CONSTRUCTED == tagType);
114/// assert(balber::BerUniversalTagNumber::e_BER_SEQUENCE == tagNumber);
115///
116/// rc = balber::BerUtil::getLength(&isb, &length, &accumNumBytesConsumed);
117/// assert(0 == rc);
118/// assert(balber::BerUtil::k_INDEFINITE_LENGTH == length);
119/// @endcode
120/// The `UNIVERSAL` value in `tagClass` indicates that the `tagNumber` value
121/// represents a type in the BER standard, a `BER_SEQUENCE`, as we requested of
122/// the infrastructure (see the `IsSequence` specialization above). The
123/// `tagType` value of `CONSTRUCTED` indicates that this is a non-primitive
124/// type. The `INDEFINITE` value for length is typical for sequence encodings.
125/// In these cases, the end-of-data is indicated by a sequence to two null
126/// bytes.
127///
128/// We now examine the tags and values corresponding to each of the data members
129/// of `usage::EmployeeRecord` class. For each of these the `tagClass` is
130/// `CONTEXT_SPECIFIC` (i.e., member of a larger construct) and the `tagType` is
131/// `PRIMITIVE` (`bsl::string`, `int`, and `float` each correspond to a
132/// primitive BER type. The `tagNumber` for each field was defined (in the
133/// elided definiton) to correspond the position of the field in the
134/// `usage::EmployeeRecord` class.
135/// @code
136/// rc = balber::BerUtil::getIdentifierOctets(&isb,
137/// &tagClass,
138/// &tagType,
139/// &tagNumber,
140/// &accumNumBytesConsumed);
141/// assert(0 == rc);
142/// assert(balber::BerConstants::e_CONTEXT_SPECIFIC == tagClass);
143/// assert(balber::BerConstants::e_PRIMITIVE == tagType);
144/// assert(1 == tagNumber);
145///
146/// bsl::string name;
147/// rc = balber::BerUtil::getValue(&isb, &name, &accumNumBytesConsumed);
148/// assert(0 == rc);
149/// assert("Bob" == name);
150///
151/// rc = balber::BerUtil::getIdentifierOctets(&isb,
152/// &tagClass,
153/// &tagType,
154/// &tagNumber,
155/// &accumNumBytesConsumed);
156/// assert(0 == rc);
157/// assert(balber::BerConstants::e_CONTEXT_SPECIFIC == tagClass);
158/// assert(balber::BerConstants::e_PRIMITIVE == tagType);
159/// assert(2 == tagNumber);
160///
161/// int age = 0;
162/// rc = balber::BerUtil::getValue(&isb, &age, &accumNumBytesConsumed);
163/// assert(0 == rc);
164/// assert(56 == age);
165///
166/// rc = balber::BerUtil::getIdentifierOctets(&isb,
167/// &tagClass,
168/// &tagType,
169/// &tagNumber,
170/// &accumNumBytesConsumed);
171/// assert(0 == rc);
172/// assert(balber::BerConstants::e_CONTEXT_SPECIFIC == tagClass);
173/// assert(balber::BerConstants::e_PRIMITIVE == tagType);
174/// assert(3 == tagNumber);
175///
176/// float salary = 0.0;
177/// rc = balber::BerUtil::getValue(&isb, &salary, &accumNumBytesConsumed);
178/// assert(0 == rc);
179/// assert(1234.00 == salary);
180/// @endcode
181/// Lastly, we confirm that end-of-data sequence (two null bytes) are found we
182/// expect them and that we have entirely consumed the data that we generated by
183/// our encoding.
184/// @code
185/// rc = balber::BerUtil::getEndOfContentOctets(&isb, &accumNumBytesConsumed);
186/// assert(0 == rc);
187/// assert(osb.length() == static_cast<bsl::size_t>(accumNumBytesConsumed));
188/// @endcode
189/// @}
190/** @} */
191/** @} */
192
193/** @addtogroup bal
194 * @{
195 */
196/** @addtogroup balber
197 * @{
198 */
199/** @addtogroup balber_berencoder
200 * @{
201 */
202
203#include <balscm_version.h>
204
205#include <balber_berconstants.h>
208#include <balber_berutil.h>
209
210#include <bdlar_refutil.h>
211
212#include <bdlat_arrayfunctions.h>
213#include <bdlat_attributeinfo.h>
216#include <bdlat_enumfunctions.h>
217#include <bdlat_formattingmode.h>
220#include <bdlat_typecategory.h>
221#include <bdlat_typename.h>
222
224
225#include <bslma_allocator.h>
226
227#include <bsls_assert.h>
228#include <bsls_keyword.h>
229#include <bsls_objectbuffer.h>
230
231#include <bsl_ostream.h>
232#include <bsl_string.h>
233#include <bsl_vector.h>
234#include <bsl_typeinfo.h>
235
236
237
238namespace balber {
239
240struct BerEncoder_encodeProxy;
241class BerEncoder_Visitor;
242class BerEncoder_UniversalElementVisitor;
243class BerEncoder_LevelGuard;
244class BerEncoder_UseArrayLengthHintGuard;
245
246 // ================
247 // class BerEncoder
248 // ================
249
250/// This class contains the parameterized `encode` functions that encode
251/// `bdlat` types to an outgoing stream in BER format.
252///
253/// See @ref balber_berencoder
255
256 private:
257 // FRIENDS
259 friend class BerEncoder_Visitor;
263
264 // PRIVATE TYPES
265
266 /// This class provides stream for logging using
267 /// `bdlsb::MemOutStreamBuf` as a streambuf. The logging stream is
268 /// created on demand, i.e., during the first attempt to log message.
269 ///
270 /// See @ref balber_berencoder
271 class MemOutStream : public bsl::ostream {
272
273 // DATA
275
276 private:
277 // NOT IMPLEMENTED
278 MemOutStream(const MemOutStream&); // = delete;
279 MemOutStream& operator=(const MemOutStream&); // = delete;
280
281 public:
282 // CREATORS
283
284 /// Create a `MemOutStream` object. Optionally specify a
285 /// `basicAllocator` used to supply memory. If `basicAllocator` is
286 /// 0, the currently installed default allocator is used.
287 MemOutStream(bslma::Allocator *basicAllocator = 0);
288
289 /// Destroy this stream and release memory back to the allocator.
290 ///
291 /// Although the compiler should generate this destructor
292 /// implicitly, xlC 8 breaks when the destructor is called by name
293 /// unless it is explicitly declared.
294 ~MemOutStream() BSLS_KEYWORD_OVERRIDE;
295
296 // MANIPULATORS
297
298 /// Reset the internal streambuf to empty.
299 void reset();
300
301 // ACCESSORS
302
303 /// Return the address of the memory containing the values formatted
304 /// to this stream. The data is not null-terminated unless a null
305 /// character was appended onto this stream.
306 const char *data() const;
307
308 /// Return the length of the formatted data, including null
309 /// characters appended to the stream, if any.
310 int length() const;
311 };
312
313 public:
314 // PUBLIC TYPES
316 e_BER_SUCCESS = 0x00
317 , e_BER_ERROR = 0x02
318
319#ifndef BDE_OMIT_INTERNAL_DEPRECATED
322#endif // BDE_OMIT_INTERNAL_DEPRECATED
323 };
324
325 private:
326 // DATA
327 const BerEncoderOptions *d_options; // held, not owned
328 bslma::Allocator *d_allocator; // held, not owned
329
330 // placeholder for MemOutStream
332
333 // if not zero, log stream was created at the moment of first logging
334 // and must be destroyed
335 MemOutStream *d_logStream;
336
337 ErrorSeverity d_severity; // error severity
338
339 bsl::streambuf *d_streamBuf; // held, not owned
340 int d_currentDepth; // current depth
341
342 bool d_useArrayLengthHint;
343 // encode the array
344 // length hint
345
346 private:
347 // NOT IMPLEMENTED
348 BerEncoder(const BerEncoder&); // = delete;
349 BerEncoder& operator=(const BerEncoder&); // = delete;
350
351 // PRIVATE MANIPULATORS
352
353 /// Log the specified `msg` using the specified `tagClass`, `tagNumber`,
354 /// name, and `index`, and return `errorSeverity()`.
355 ErrorSeverity logMsg(const char *msg,
356 BerConstants::TagClass tagClass,
357 int tagNumber,
358 const char *name = 0,
359 int index = -1);
360
361 /// Log error and upgrade the severity level. Return `errorSeverity()`.
362 ErrorSeverity logError(BerConstants::TagClass tagClass,
363 int tagNumber,
364 const char *name = 0,
365 int index = -1);
366
367 /// Return the stream for logging. Note the if stream has not been
368 /// created yet, it will be created during this call.
369 bsl::ostream& logStream();
370
371 int encodeImpl(const bsl::vector<char>& value,
372 BerConstants::TagClass tagClass,
373 int tagNumber,
374 int formattingMode,
376
377 template <typename TYPE>
378 int encodeArrayImpl(const TYPE& value,
379 BerConstants::TagClass tagClass,
380 int tagNumber,
381 int formattingMode);
382
383 template <typename TYPE>
384 int encodeImpl(const TYPE& value,
385 BerConstants::TagClass tagClass,
386 int tagNumber,
387 int formattingMode,
389
390 template <typename TYPE>
391 int encodeImpl(const TYPE& value,
392 BerConstants::TagClass tagClass,
393 int tagNumber,
394 int formattingMode,
396
397 template <typename TYPE>
398 int encodeImpl(const TYPE& value,
399 BerConstants::TagClass tagClass,
400 int tagNumber,
401 int formattingMode,
403
404 template <typename TYPE>
405 int encodeImpl(const TYPE& value,
406 BerConstants::TagClass tagClass,
407 int tagNumber,
408 int formattingMode,
410
411 template <typename TYPE>
412 int encodeImpl(const TYPE& value,
413 BerConstants::TagClass tagClass,
414 int tagNumber,
415 int formattingMode,
417
418 template <typename TYPE>
419 int encodeImpl(const TYPE& value,
420 BerConstants::TagClass tagClass,
421 int tagNumber,
422 int formattingMode,
424
425 template <typename TYPE>
426 int encodeImpl(const TYPE& value,
427 BerConstants::TagClass tagClass,
428 int tagNumber,
429 int formattingMode,
431
432 template <typename TYPE>
433 int encodeImpl(const TYPE& value,
434 BerConstants::TagClass tagClass,
435 int tagNumber,
436 int formattingMode,
438
439 public:
440 // CREATORS
441
442 /// Construct an encoder object. Optionally specify encoder `options`.
443 /// If `options` is 0, `BerEncoderOptions()` is used. Optionally
444 /// specify a `basicAllocator` used to supply memory. If
445 /// `basicAllocator` is 0, the currently installed default allocator is
446 /// used.
448 bslma::Allocator *basicAllocator = 0);
449
450 /// Destroy this object. This destruction has no effect on objects
451 /// pointed-to by the pointers provided at construction.
453
454 /// Encode the specified non-modifiable `value` to the specified
455 /// `streamBuf`. Return 0 on success, and a non-zero value otherwise.
456 template <typename TYPE>
457 int encode(bsl::streambuf *streamBuf, const TYPE& value);
458
459 /// Encode the specified non-modifiable `value` to the specified
460 /// `stream`. Return 0 on success, and a non-zero value otherwise. If
461 /// the encoding fails `stream` will be invalidated.
462 template <typename TYPE>
463 int encode(bsl::ostream& stream, const TYPE& value);
464
465 /// Encode the specified non-modifiable `value` to the specified
466 /// `streamBuf`. Return 0 on success, and a non-zero value otherwise.
467 ///
468 /// \note Note that this function behaves identically to `encode`, but does not
469 /// instantiate any templates at compile time at the expense of being
470 /// slightly slower at runtime; see the `balber` package documentation for
471 /// more details.
472 template <typename TYPE>
473 int encodeAny(bsl::streambuf *streamBuf, const TYPE& value);
474 int encodeAny(bsl::streambuf *streamBuf, const bdlar::AnyConstRef& any);
475
476 /// Encode the specified non-modifiable `value` to the specified `stream`.
477 /// Return 0 on success, and a non-zero value otherwise. If the encoding fails `stream` will be invalidated.
478 ///
479 /// \note Note that this function behaves
480 /// identically to `encode`, but does not instantiate any templates at
481 /// compile time at the expense of being slightly slower at runtime; see
482 /// the `balber` package documentation for more details.
483 template <typename TYPE>
484 int encodeAny(bsl::ostream& stream, const TYPE& value);
485 int encodeAny(bsl::ostream& stream, const bdlar::AnyConstRef& any);
486
487 // ACCESSORS
488
489 /// Return address of the options.
490 const BerEncoderOptions *options() const;
491
492 /// Return the severity of the most severe warning or error encountered
493 /// during the last call to the `encode` method. The severity is reset
494 /// each time `encode` is called.
496
497 /// Return a string containing any error, warning, or trace messages
498 /// that were logged during the last call to the `encode` method. The
499 /// log is reset each time `encode` is called.
501};
502
503 // ===================================
504 // private class BerEncoder_LevelGuard
505 // ===================================
506
507/// This class serves the purpose to automatically increment-decrement the
508/// current depth level.
509///
510/// See @ref balber_berencoder
512
513 // DATA
514 BerEncoder *d_encoder;
515
516 private:
517 // NOT IMPLEMENTED
519 BerEncoder_LevelGuard& operator=(BerEncoder_LevelGuard&); // = delete;
520
521 public:
522 // CREATORS
525};
526
527 // ================================================
528 // private class BerEncoder_UseArrayLengthHintGuard
529 // ================================================
530
531/// This class serves the purpose to set and reset the value of
532/// `d_useArrayLengthHint`.
533///
534/// See @ref balber_berencoder
536
537 // DATA
538 BerEncoder *d_encoder;
539 bool d_previous;
540
541 private:
542 // NOT IMPLEMENTED
547
548 public:
549 // CREATORS
552};
553
554 // ================================
555 // private class BerEncoder_Visitor
556 // ================================
557
558/// This class is used as a visitor for visiting contained objects during
559/// encoding. Produces always BER elements with CONTEXT_SPECIFIC BER tag.
560///
561/// See @ref balber_berencoder
563
564 // DATA
565 BerEncoder *d_encoder; // encoder to write data to
566 BerEncoder_LevelGuard d_levelGuard;
567
568 private:
569 // NOT IMPLEMENTED
570 BerEncoder_Visitor(const BerEncoder_Visitor&); // = delete;
571 BerEncoder_Visitor& operator=(const BerEncoder_Visitor&); // = delete;
572
573 public:
574 // CREATORS
577
578 // MANIPULATORS
579 template <typename TYPE, typename INFO>
580 int operator()(const TYPE& value, const INFO& info);
581};
582
583 // ================================================
584 // private class BerEncoder_UniversalElementVisitor
585 // ================================================
586
587/// This class is used as a visitor for visiting the top-level element and
588/// also array elements during encoding. This class is required so that the
589/// universal tag number of the element can be determined when the element
590/// is visited.
591///
592/// See @ref balber_berencoder
594
595 // PRIVATE DATA MEMBERS
596 BerEncoder *d_encoder; // streambuf to write data to
597 int d_formattingMode; // formatting mode to use
598 BerEncoder_LevelGuard d_levelGuard;
599
600 private:
601 // NOT IMPLEMENTED
604 // = delete;
607 // = delete;
608 public:
609 // CREATORS
611 int formattingMode);
612
614
615 // MANIPULATORS
616 template <typename TYPE>
617 int operator()(const TYPE& value);
618};
619
620// ============================================================================
621// PROXY CLASSES
622// ============================================================================
623
624 // =============================
625 // struct BerEncoder_encodeProxy
626 // =============================
627
628/// Component-private struct. Provides accessor that keeps current context
629/// and can be used in different `bdlat` Category Functions.
630///
631/// See @ref balber_berencoder
633
634 // DATA MEMBERS
639
640 // CREATORS Creators have been omitted to allow simple static
641 // initialization of this struct.
642
643 // FUNCTIONS
644 template <typename TYPE>
645 int operator()(const TYPE& object, bslmf::Nil);
646
647 template <typename TYPE, typename ANY_CATEGORY>
648 int operator()(const TYPE& object, ANY_CATEGORY category);
649
650 template <typename TYPE>
651 int operator()(const TYPE& object);
652};
653
654} // close package namespace
655
656// ============================================================================
657// INLINE DEFINITIONS
658// ============================================================================
659
660 // --------------------------------------
661 // class balber::BerEncoder::MemOutStream
662 // --------------------------------------
663
664inline
665balber::BerEncoder::MemOutStream::MemOutStream(
666 bslma::Allocator *basicAllocator)
667: bsl::ostream(0)
668, d_sb(bslma::Default::allocator(basicAllocator))
669{
670 rdbuf(&d_sb);
671}
672
673// MANIPULATORS
674inline
676{
677 d_sb.reset();
678}
679
680// ACCESSORS
681inline
683{
684 return d_sb.data();
685}
686
687inline
689{
690 return static_cast<int>(d_sb.length());
691}
692
693namespace balber {
694
695 // ----------------------------
696 // class BerEncoder::LevelGuard
697 // ----------------------------
698
699inline
700BerEncoder_LevelGuard::BerEncoder_LevelGuard(BerEncoder *encoder)
701: d_encoder (encoder)
702{
703 ++d_encoder->d_currentDepth;
704}
705
706inline
708{
709 --d_encoder->d_currentDepth;
710}
711
712 // ----------------------------------------
713 // class BerEncoder_UseArrayLengthHintGuard
714 // ----------------------------------------
715
716inline
717BerEncoder_UseArrayLengthHintGuard::BerEncoder_UseArrayLengthHintGuard(
718 BerEncoder *encoder, bool value)
719: d_encoder (encoder)
720, d_previous (encoder->d_useArrayLengthHint)
721{
722 d_encoder->d_useArrayLengthHint = value;
723}
724
725inline
727{
728 d_encoder->d_useArrayLengthHint = d_previous;
729}
730
731 // -----------------------------
732 // struct BerEncoder_encodeProxy
733 // -----------------------------
734
735template <typename TYPE>
736inline
738{
740 return -1;
741}
742
743template <typename TYPE, typename ANY_CATEGORY>
744inline
746 ANY_CATEGORY category)
747{
748 return d_encoder->encodeImpl(object,
752 category);
753}
754
755template <typename TYPE>
756inline
758{
759 typedef typename
761
762 return this->operator()(object, TypeCategory());
763}
764
765 // ----------------
766 // class BerEncoder
767 // ----------------
768
769// ACCESSORS
770inline
772{
773 return d_options;
774}
775
776inline
778{
779 return d_severity;
780}
781
782inline
784{
785 if (d_logStream) {
786 return bslstl::StringRef(d_logStream->data(), d_logStream->length());
787 }
788
789 return bslstl::StringRef();
790}
791
792inline
793bsl::ostream& BerEncoder::logStream()
794{
795 if (d_logStream == 0) {
796 d_logStream = new(d_logArea.buffer()) MemOutStream(d_allocator);
797 }
798 return *d_logStream;
799}
800
801template <typename TYPE>
802int BerEncoder::encode(bsl::streambuf *streamBuf, const TYPE& value)
803{
804 BSLS_ASSERT(!d_streamBuf);
805
806 d_streamBuf = streamBuf;
807 d_severity = e_BER_SUCCESS;
808
809 if (d_logStream != 0) {
810 d_logStream->reset();
811 }
812
813 d_currentDepth = 0;
814
815 int rc;
816
817 if (! d_options) {
818 BerEncoderOptions options; // temporary options object
819 d_options = &options;
821 this,
823
824 rc = visitor(value);
825 d_options = 0;
826 }
827 else {
829 this,
831 rc = visitor(value);
832 }
833
834 d_streamBuf = 0;
835
836 streamBuf->pubsync();
837
838 return rc;
839}
840
841template <typename TYPE>
842int BerEncoder::encode(bsl::ostream& stream, const TYPE& value)
843{
844 if (!stream.good()) {
845 return -1;
846 }
847
848 if (0 != this->encode(stream.rdbuf(), value)) {
849 stream.setstate(bsl::ios_base::failbit);
850 return -1;
851 }
852 return 0;
853}
854
855template <typename TYPE>
856inline
857int BerEncoder::encodeAny(bsl::streambuf *streamBuf, const TYPE& value)
858{
859 return encodeAny(streamBuf, bdlar::RefUtil::makeAnyConstRef(value));
860}
861
862template <typename TYPE>
863inline
864int BerEncoder::encodeAny(bsl::ostream& stream, const TYPE& value)
865{
866 return encodeAny(stream, bdlar::RefUtil::makeAnyConstRef(value));
867}
868
869// PRIVATE MANIPULATORS
870template <typename TYPE>
871int BerEncoder::encodeImpl(const TYPE& value,
872 BerConstants::TagClass tagClass,
873 int tagNumber,
874 int formattingMode,
876{
877 enum { k_SUCCESS = 0, k_FAILURE = -1 };
878
879 BerEncoder_UseArrayLengthHintGuard guard(this, false);
880
882
883 int rc = BerUtil::putIdentifierOctets(d_streamBuf,
884 tagClass,
885 tagType,
886 tagNumber);
887 if (rc | BerUtil::putIndefiniteLengthOctet(d_streamBuf)) {
888 return k_FAILURE; // RETURN
889 }
890
891 const bool isUntagged = formattingMode
893
894 if (!isUntagged) {
895 // According to X.694 (clause 20.4), an XML choice (not anonymous)
896 // element is encoded as a sequence with 1 element.
897
898 rc = BerUtil::putIdentifierOctets(d_streamBuf,
900 tagType,
901 0);
902 if (rc | BerUtil::putIndefiniteLengthOctet(d_streamBuf)) {
903 return k_FAILURE;
904 }
905 }
906
908
910
911 BerEncoder_Visitor visitor(this);
912
913 if (0 != bdlat_ChoiceFunctions::accessSelection(value, visitor)) {
914 return k_FAILURE; // RETURN
915 }
916 }
917 else {
918
919 if (d_options->disableUnselectedChoiceEncoding()) {
920
921 this->logError(tagClass,
922 tagNumber);
923
924 return k_FAILURE; // RETURN
925 }
926
927 }
928
929 if (!isUntagged) {
930 // According to X.694 (clause 20.4), an XML choice (not anonymous)
931 // element is encoded as a sequence with 1 element.
932
933 // Don't waste time checking the result of this call -- the only thing
934 // that can go wrong is eof, which will happen again when we call it
935 // again below.
937 }
938
939 return BerUtil::putEndOfContentOctets(d_streamBuf);
940}
941
942template <typename TYPE>
943int BerEncoder::encodeImpl(const TYPE& value,
944 BerConstants::TagClass tagClass,
945 int tagNumber,
946 int formattingMode,
948{
949 enum { k_SUCCESS = 0, k_FAILURE = -1 };
950
951 BerEncoder_UseArrayLengthHintGuard guard(this, false);
952
953 bool isNillable = formattingMode & bdlat_FormattingMode::e_NILLABLE;
954
955 if (isNillable) {
956
957 // nillable is encoded in BER as a sequence with one optional element
958
959 int rc = BerUtil::putIdentifierOctets(d_streamBuf,
960 tagClass,
962 tagNumber);
963 if (rc | BerUtil::putIndefiniteLengthOctet(d_streamBuf)) {
964 return k_FAILURE;
965 }
966
968
969 BerEncoder_encodeProxy proxy1 = {
970 this,
972 0, // tagNumber
973 formattingMode };
974
976 proxy1)) {
977 return k_FAILURE;
978 }
979 } // end of bdlat_NullableValueFunctions::isNull(...)
980
981 return BerUtil::putEndOfContentOctets(d_streamBuf);
982 } // end of isNillable
983
985
986 BerEncoder_encodeProxy proxy2 = { this,
987 tagClass,
988 tagNumber,
989 formattingMode };
990
991 if (0 != bdlat_NullableValueFunctions::accessValue(value, proxy2)) {
992 return k_FAILURE;
993 }
994 }
995
996 return k_SUCCESS;
997}
998
999template <typename TYPE>
1000int BerEncoder::encodeImpl(const TYPE& value,
1001 BerConstants::TagClass tagClass,
1002 int tagNumber,
1003 int formattingMode,
1005{
1006 typedef typename
1008
1009 typedef typename
1011
1012 int rc = encodeImpl(
1014 tagClass,
1015 tagNumber,
1016 formattingMode,
1017 BaseTypeCategory());
1018
1019 return rc;
1020}
1021
1022template <typename TYPE>
1023int BerEncoder::encodeImpl(const TYPE& value,
1024 BerConstants::TagClass tagClass,
1025 int tagNumber,
1026 int ,
1028{
1029 int rc = BerUtil::putIdentifierOctets(d_streamBuf,
1030 tagClass,
1032 tagNumber);
1033
1034 int intValue;
1035 bdlat_EnumFunctions::toInt(&intValue, value);
1036
1037 rc |= BerUtil::putValue(d_streamBuf, intValue);
1038
1039 return rc;
1040}
1041
1042template <typename TYPE>
1043int BerEncoder::encodeImpl(const TYPE& value,
1044 BerConstants::TagClass tagClass,
1045 int tagNumber,
1046 int ,
1048{
1049 BerEncoder_UseArrayLengthHintGuard guard(this, true);
1050
1051 BerEncoder_Visitor visitor(this);
1052
1053 int rc = BerUtil::putIdentifierOctets(d_streamBuf,
1054 tagClass,
1056 tagNumber);
1057 rc |= BerUtil::putIndefiniteLengthOctet(d_streamBuf);
1058 if (rc) {
1059 return rc;
1060 }
1061
1062 rc = bdlat_SequenceFunctions::accessAttributes(value, visitor);
1063 rc |= BerUtil::putEndOfContentOctets(d_streamBuf);
1064
1065 return rc;
1066}
1067
1068template <typename TYPE>
1069int BerEncoder::encodeImpl(const TYPE& value,
1070 BerConstants::TagClass tagClass,
1071 int tagNumber,
1072 int ,
1074{
1075 int rc = BerUtil::putIdentifierOctets(d_streamBuf,
1076 tagClass,
1078 tagNumber);
1079 rc |= BerUtil::putValue(d_streamBuf, value, d_options);
1080
1081 return rc;
1082}
1083
1084template <typename TYPE>
1085inline
1086int BerEncoder::encodeImpl(const TYPE& value,
1087 BerConstants::TagClass tagClass,
1088 int tagNumber,
1089 int formattingMode,
1091{
1092 enum { k_SUCCESS = 0, k_FAILURE = -1 };
1093
1094 if (d_currentDepth <= 1 || tagClass == BerConstants::e_UNIVERSAL) {
1095 return k_FAILURE;
1096 }
1097 // Note: bsl::vector<char> is handled as a special case in the CPP file.
1098 return this->encodeArrayImpl(value,
1099 tagClass,
1100 tagNumber,
1101 formattingMode);
1102}
1103
1104template <typename TYPE>
1105int
1106BerEncoder::encodeArrayImpl(const TYPE& value,
1107 BerConstants::TagClass tagClass,
1108 int tagNumber,
1109 int formattingMode)
1110{
1111 enum { k_FAILURE = -1, k_SUCCESS = 0 };
1112
1113 const int size = static_cast<int>(bdlat_ArrayFunctions::size(value));
1114
1115 if (0 == size && d_options && !d_options->encodeEmptyArrays()) {
1116 return k_SUCCESS; // RETURN
1117 }
1118
1119 int rc = 0;
1120
1121 if ( d_useArrayLengthHint
1122 && size > 1
1123 && d_options->encodeArrayLengthHints()) {
1125 d_streamBuf,
1126 tagClass,
1129 rc |= BerUtil::putValue(d_streamBuf, size);
1130 }
1131
1133
1134 rc |= BerUtil::putIdentifierOctets(d_streamBuf,
1135 tagClass,
1136 tagType,
1137 tagNumber);
1138 rc |= BerUtil::putIndefiniteLengthOctet(d_streamBuf);
1139 if (rc) {
1140 return k_FAILURE; // RETURN
1141 }
1142
1143 BerEncoder_UniversalElementVisitor visitor(this, formattingMode);
1144
1145 for (int i = 0; i < size; ++i) {
1146 if (0 != bdlat_ArrayFunctions::accessElement(value, visitor, i)) {
1147
1148 this->logError(tagClass,
1149 tagNumber,
1150 0, // bdlat_TypeName::name(value),
1151 i);
1152
1153 return k_FAILURE; // RETURN
1154 }
1155 }
1156
1157 return BerUtil::putEndOfContentOctets(d_streamBuf);
1158}
1159
1160template <typename TYPE>
1161inline
1162int BerEncoder::encodeImpl(const TYPE& value,
1163 BerConstants::TagClass tagClass,
1164 int tagNumber,
1165 int formattingMode,
1167{
1168 BerEncoder_encodeProxy proxy = { this,
1169 tagClass,
1170 tagNumber,
1171 formattingMode
1172 };
1173
1174 return bdlat_TypeCategoryUtil::accessByCategory(value, proxy);
1175}
1176
1177 // --------------------------------
1178 // private class BerEncoder_Visitor
1179 // --------------------------------
1180
1181// CREATORS
1182inline
1183BerEncoder_Visitor::BerEncoder_Visitor(BerEncoder *encoder)
1184: d_encoder(encoder)
1185, d_levelGuard(encoder)
1186{
1187}
1188
1189inline
1193
1194// MANIPULATORS
1195template <typename TYPE, typename INFO>
1196inline
1197int BerEncoder_Visitor::operator()(const TYPE& value, const INFO& info)
1198{
1199 typedef typename
1201
1202 int rc = d_encoder->encodeImpl(value,
1204 info.id(),
1205 info.formattingMode(),
1206 TypeCategory());
1207
1208 if (rc) {
1209 d_encoder->logError(BerConstants::e_CONTEXT_SPECIFIC,
1210 info.id(),
1211 info.name());
1212 }
1213
1214 return rc;
1215}
1216
1217 // ------------------------------------------------
1218 // private class BerEncoder_UniversalElementVisitor
1219 // ------------------------------------------------
1220
1221// CREATORS
1222inline
1223BerEncoder_UniversalElementVisitor::
1224BerEncoder_UniversalElementVisitor(BerEncoder *encoder,
1225 int formattingMode)
1226: d_encoder(encoder)
1227, d_formattingMode(formattingMode)
1228, d_levelGuard(encoder)
1229{
1230}
1231
1232inline
1237
1238// MANIPULATORS
1239template <typename TYPE>
1241{
1242 enum { k_SUCCESS = 0, k_FAILURE = -1 };
1243
1244 typedef typename
1246
1248 value,
1249 d_formattingMode,
1250 d_encoder->options());
1251
1252 if (d_encoder->encodeImpl(value,
1254 static_cast<int>(tagNumber),
1255 d_formattingMode,
1256 TypeCategory())) {
1257 d_encoder->logError(BerConstants::e_UNIVERSAL,
1258 tagNumber);
1259 return k_FAILURE;
1260 }
1261
1262 return k_SUCCESS;
1263}
1264
1265} // close package namespace
1266
1267#endif
1268
1269// ----------------------------------------------------------------------------
1270// Copyright 2015 Bloomberg Finance L.P.
1271//
1272// Licensed under the Apache License, Version 2.0 (the "License");
1273// you may not use this file except in compliance with the License.
1274// You may obtain a copy of the License at
1275//
1276// http://www.apache.org/licenses/LICENSE-2.0
1277//
1278// Unless required by applicable law or agreed to in writing, software
1279// distributed under the License is distributed on an "AS IS" BASIS,
1280// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1281// See the License for the specific language governing permissions and
1282// limitations under the License.
1283// ----------------------------- END-OF-FILE ----------------------------------
1284
1285/** @} */
1286/** @} */
1287/** @} */
Definition balber_berencoderoptions.h:70
bool disableUnselectedChoiceEncoding() const
Definition balber_berencoderoptions.h:806
bool encodeEmptyArrays() const
Definition balber_berencoderoptions.h:788
bool encodeArrayLengthHints() const
Definition balber_berencoderoptions.h:818
Definition balber_berencoder.h:511
~BerEncoder_LevelGuard()
Definition balber_berencoder.h:707
Definition balber_berencoder.h:593
~BerEncoder_UniversalElementVisitor()
Definition balber_berencoder.h:1234
int operator()(const TYPE &value)
Definition balber_berencoder.h:1240
Definition balber_berencoder.h:535
~BerEncoder_UseArrayLengthHintGuard()
Definition balber_berencoder.h:726
Definition balber_berencoder.h:562
~BerEncoder_Visitor()
Definition balber_berencoder.h:1190
int operator()(const TYPE &value, const INFO &info)
Definition balber_berencoder.h:1197
Definition balber_berencoder.h:254
friend class BerEncoder_UseArrayLengthHintGuard
Definition balber_berencoder.h:262
int encode(bsl::streambuf *streamBuf, const TYPE &value)
Definition balber_berencoder.h:802
friend struct BerEncoder_encodeProxy
Definition balber_berencoder.h:258
int encodeAny(bsl::streambuf *streamBuf, const TYPE &value)
Definition balber_berencoder.h:857
ErrorSeverity errorSeverity() const
Definition balber_berencoder.h:777
ErrorSeverity
Definition balber_berencoder.h:315
@ e_BER_ERROR
Definition balber_berencoder.h:317
@ e_BER_SUCCESS
Definition balber_berencoder.h:316
@ BDEM_BER_SUCCESS
Definition balber_berencoder.h:320
@ BDEM_BER_ERROR
Definition balber_berencoder.h:321
friend class BerEncoder_Visitor
Definition balber_berencoder.h:259
int encodeAny(bsl::ostream &stream, const bdlar::AnyConstRef &any)
const BerEncoderOptions * options() const
Return address of the options.
Definition balber_berencoder.h:771
friend class BerEncoder_LevelGuard
Definition balber_berencoder.h:261
friend class BerEncoder_UniversalElementVisitor
Definition balber_berencoder.h:260
int encodeAny(bsl::streambuf *streamBuf, const bdlar::AnyConstRef &any)
bslstl::StringRef loggedMessages() const
Definition balber_berencoder.h:783
BerEncoder(const BerEncoderOptions *options=0, bslma::Allocator *basicAllocator=0)
Definition bdlar_anyref.h:247
static bsl::enable_if<!IsDynamic< t_TYPE >::value, AnyConstRef >::type makeAnyConstRef(const t_TYPE &object)
Make AnyConstRef to the specified object.
Definition bdlar_refutil.h:194
Definition bdlsb_memoutstreambuf.h:212
Definition bslstl_vector.h:1120
Definition bslma_allocator.h:545
Definition bslstl_stringref.h:374
const char * data() const
Definition balber_berencoder.h:682
void reset()
Reset the internal streambuf to empty.
Definition balber_berencoder.h:675
int length() const
Definition balber_berencoder.h:688
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_SAFE(X)
Definition bsls_assert.h:1917
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
#define BSLS_KEYWORD_OVERRIDE
Definition bsls_keyword.h:695
Definition balber_berconstants.h:84
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 toInt(int *result, const TYPE &value)
bool isNull(const TYPE &object)
int accessValue(const TYPE &object, ACCESSOR &accessor)
int accessAttributes(const TYPE &object, ACCESSOR &accessor)
Definition bdlat_valuetypefunctions.h:939
Definition baljsn_encoder_testtypes.h:76
StringRefImp< char > StringRef
Definition bslstl_stringref.h:725
TagType
Definition balber_berconstants.h:117
@ e_PRIMITIVE
Definition balber_berconstants.h:120
@ e_CONSTRUCTED
Definition balber_berconstants.h:121
TagClass
Definition balber_berconstants.h:96
@ e_CONTEXT_SPECIFIC
Definition balber_berconstants.h:101
@ e_UNIVERSAL
Definition balber_berconstants.h:99
static const int k_ARRAY_LENGTH_HINT_TAG_NUMBER
Definition balber_berconstants.h:132
Definition balber_berencoder.h:632
BerEncoder * d_encoder
Definition balber_berencoder.h:635
BerConstants::TagClass d_tagClass
Definition balber_berencoder.h:636
int operator()(const TYPE &object, bslmf::Nil)
Definition balber_berencoder.h:737
int d_formattingMode
Definition balber_berencoder.h:638
int d_tagNumber
Definition balber_berencoder.h:637
Value
Definition balber_beruniversaltagnumber.h:196
static Value select(const TYPE &object, int formattingMode, int *alternateTag)
Definition balber_beruniversaltagnumber.h:605
static int putEndOfContentOctets(bsl::streambuf *streamBuf)
Definition balber_berutil.h:4022
static int putIndefiniteLengthOctet(bsl::streambuf *streamBuf)
Definition balber_berutil.h:4028
static int putValue(bsl::streambuf *streamBuf, const TYPE &value, const BerEncoderOptions *options=0)
Definition balber_berutil.h:4041
static int putIdentifierOctets(bsl::streambuf *streamBuf, BerConstants::TagClass tagClass, BerConstants::TagType tagType, int tagNumber)
TYPE::BaseType Type
Definition bdlat_customizedtypefunctions.h:535
@ e_DEFAULT
Definition bdlat_formattingmode.h:114
@ e_NILLABLE
Definition bdlat_formattingmode.h:125
@ 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
Definition bslmf_nil.h:133
Definition bsls_objectbuffer.h:277
char * buffer()
Definition bsls_objectbuffer.h:345