BDE 4.14.0 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/// ## Usage {#balber_berencoder-usage}
51///
52///
53/// This section illustrates intended use of this component.
54///
55/// ### Example 1: Encoding an Employee Record {#balber_berencoder-example-1-encoding-an-employee-record}
56///
57///
58/// Suppose that an "employee record" consists of a sequence of attributes --
59/// `name`, `age`, and `salary` -- that are of types `bsl::string`, `int`, and
60/// `float`, respectively. Furthermore, we have a need to BER encode employee
61/// records as a sequence of values (for out-of-process consumption).
62///
63/// Assume that we have defined a `usage::EmployeeRecord` class to represent
64/// employee record values, and assume that we have provided the `bdlat`
65/// specializations that allow the `balber` codec components to represent class
66/// values as a sequence of BER primitive values. See
67/// {@ref bdlat_sequencefunctions |Usage} for details of creating specializations
68/// for a sequence type.
69///
70/// First, we create an employee record object having typical values:
71/// @code
72/// usage::EmployeeRecord bob("Bob", 56, 1234.00);
73/// assert("Bob" == bob.name());
74/// assert( 56 == bob.age());
75/// assert(1234.00 == bob.salary());
76/// @endcode
77/// Now, we create a `balber::Encoder` object and use it to encode our `bob`
78/// object. Here, to facilitate the examination of our results, the BER
79/// encoding data is delivered to a `bslsb::MemOutStreamBuf` object:
80/// @code
81/// bdlsb::MemOutStreamBuf osb;
82/// balber::BerEncoder encoder;
83/// int rc = encoder.encode(&osb, bob);
84/// assert( 0 == rc);
85/// assert(18 == osb.length());
86/// @endcode
87/// Finally, we confirm that the generated BER encoding has the expected layout
88/// and values. We create an `bdlsb::FixedMemInStreamBuf` to manage our access
89/// to the data portion of the `bdlsb::MemOutStreamBuf` where our BER encoding
90/// resides:
91/// @code
92/// bdlsb::FixedMemInStreamBuf isb(osb.data(), osb.length());
93/// @endcode
94/// The @ref balber_berutil component provides functions that allow us to decode
95/// the descriptive fields and values of the BER encoded sequence:
96/// @code
97/// balber::BerConstants::TagClass tagClass;
98/// balber::BerConstants::TagType tagType;
99/// int tagNumber;
100/// int accumNumBytesConsumed = 0;
101/// int length;
102///
103/// rc = balber::BerUtil::getIdentifierOctets(&isb,
104/// &tagClass,
105/// &tagType,
106/// &tagNumber,
107/// &accumNumBytesConsumed);
108/// assert(0 == rc);
109/// assert(balber::BerConstants::e_UNIVERSAL == tagClass);
110/// assert(balber::BerConstants::e_CONSTRUCTED == tagType);
111/// assert(balber::BerUniversalTagNumber::e_BER_SEQUENCE == tagNumber);
112///
113/// rc = balber::BerUtil::getLength(&isb, &length, &accumNumBytesConsumed);
114/// assert(0 == rc);
115/// assert(balber::BerUtil::k_INDEFINITE_LENGTH == length);
116/// @endcode
117/// The `UNIVERSAL` value in `tagClass` indicates that the `tagNumber` value
118/// represents a type in the BER standard, a `BER_SEQUENCE`, as we requested of
119/// the infrastructure (see the `IsSequence` specialization above). The
120/// `tagType` value of `CONSTRUCTED` indicates that this is a non-primitive
121/// type. The `INDEFINITE` value for length is typical for sequence encodings.
122/// In these cases, the end-of-data is indicated by a sequence to two null
123/// bytes.
124///
125/// We now examine the tags and values corresponding to each of the data members
126/// of `usage::EmployeeRecord` class. For each of these the `tagClass` is
127/// `CONTEXT_SPECIFIC` (i.e., member of a larger construct) and the `tagType` is
128/// `PRIMITIVE` (`bsl::string`, `int`, and `float` each correspond to a
129/// primitive BER type. The `tagNumber` for each field was defined (in the
130/// elided definiton) to correspond the position of the field in the
131/// `usage::EmployeeRecord` class.
132/// @code
133/// rc = balber::BerUtil::getIdentifierOctets(&isb,
134/// &tagClass,
135/// &tagType,
136/// &tagNumber,
137/// &accumNumBytesConsumed);
138/// assert(0 == rc);
139/// assert(balber::BerConstants::e_CONTEXT_SPECIFIC == tagClass);
140/// assert(balber::BerConstants::e_PRIMITIVE == tagType);
141/// assert(1 == tagNumber);
142///
143/// bsl::string name;
144/// rc = balber::BerUtil::getValue(&isb, &name, &accumNumBytesConsumed);
145/// assert(0 == rc);
146/// assert("Bob" == name);
147///
148/// rc = balber::BerUtil::getIdentifierOctets(&isb,
149/// &tagClass,
150/// &tagType,
151/// &tagNumber,
152/// &accumNumBytesConsumed);
153/// assert(0 == rc);
154/// assert(balber::BerConstants::e_CONTEXT_SPECIFIC == tagClass);
155/// assert(balber::BerConstants::e_PRIMITIVE == tagType);
156/// assert(2 == tagNumber);
157///
158/// int age = 0;
159/// rc = balber::BerUtil::getValue(&isb, &age, &accumNumBytesConsumed);
160/// assert(0 == rc);
161/// assert(56 == age);
162///
163/// rc = balber::BerUtil::getIdentifierOctets(&isb,
164/// &tagClass,
165/// &tagType,
166/// &tagNumber,
167/// &accumNumBytesConsumed);
168/// assert(0 == rc);
169/// assert(balber::BerConstants::e_CONTEXT_SPECIFIC == tagClass);
170/// assert(balber::BerConstants::e_PRIMITIVE == tagType);
171/// assert(3 == tagNumber);
172///
173/// float salary = 0.0;
174/// rc = balber::BerUtil::getValue(&isb, &salary, &accumNumBytesConsumed);
175/// assert(0 == rc);
176/// assert(1234.00 == salary);
177/// @endcode
178/// Lastly, we confirm that end-of-data sequence (two null bytes) are found we
179/// expect them and that we have entirely consumed the data that we generated by
180/// our encoding.
181/// @code
182/// rc = balber::BerUtil::getEndOfContentOctets(&isb, &accumNumBytesConsumed);
183/// assert(0 == rc);
184/// assert(osb.length() == static_cast<bsl::size_t>(accumNumBytesConsumed));
185/// @endcode
186/// @}
187/** @} */
188/** @} */
189
190/** @addtogroup bal
191 * @{
192 */
193/** @addtogroup balber
194 * @{
195 */
196/** @addtogroup balber_berencoder
197 * @{
198 */
199
200#include <balscm_version.h>
201
202#include <balber_berconstants.h>
205#include <balber_berutil.h>
206
207#include <bdlat_arrayfunctions.h>
208#include <bdlat_attributeinfo.h>
211#include <bdlat_enumfunctions.h>
212#include <bdlat_formattingmode.h>
215#include <bdlat_typecategory.h>
216#include <bdlat_typename.h>
217
219
220#include <bslma_allocator.h>
221
222#include <bsls_assert.h>
223#include <bsls_keyword.h>
224#include <bsls_objectbuffer.h>
225
226#include <bsl_ostream.h>
227#include <bsl_string.h>
228#include <bsl_vector.h>
229#include <bsl_typeinfo.h>
230
231
232
233namespace balber {
234
235struct BerEncoder_encodeProxy;
236class BerEncoder_Visitor;
237class BerEncoder_UniversalElementVisitor;
238class BerEncoder_LevelGuard;
239
240 // ================
241 // class BerEncoder
242 // ================
243
244/// This class contains the parameterized `encode` functions that encode
245/// `bdlat` types to an outgoing stream in BER format.
246///
247/// See @ref balber_berencoder
249
250 private:
251 // FRIENDS
253 friend class BerEncoder_Visitor;
256
257 // PRIVATE TYPES
258
259 /// This class provides stream for logging using
260 /// `bdlsb::MemOutStreamBuf` as a streambuf. The logging stream is
261 /// created on demand, i.e., during the first attempt to log message.
262 ///
263 /// See @ref balber_berencoder
264 class MemOutStream : public bsl::ostream {
265
266 // DATA
268
269 // NOT IMPLEMENTED
270 MemOutStream(const MemOutStream&); // = delete;
271 MemOutStream& operator=(const MemOutStream&); // = delete;
272
273 public:
274 // CREATORS
275
276 /// Create a `MemOutStream` object. Optionally specify a
277 /// `basicAllocator` used to supply memory. If `basicAllocator` is
278 /// 0, the currently installed default allocator is used.
279 MemOutStream(bslma::Allocator *basicAllocator = 0);
280
281 /// Destroy this stream and release memory back to the allocator.
282 ///
283 /// Although the compiler should generate this destructor
284 /// implicitly, xlC 8 breaks when the destructor is called by name
285 /// unless it is explicitly declared.
286 ~MemOutStream() BSLS_KEYWORD_OVERRIDE;
287
288 // MANIPULATORS
289
290 /// Reset the internal streambuf to empty.
291 void reset();
292
293 // ACCESSORS
294
295 /// Return the address of the memory containing the values formatted
296 /// to this stream. The data is not null-terminated unless a null
297 /// character was appended onto this stream.
298 const char *data() const;
299
300 /// Return the length of the formatted data, including null
301 /// characters appended to the stream, if any.
302 int length() const;
303 };
304
305 public:
306 // PUBLIC TYPES
308 e_BER_SUCCESS = 0x00
309 , e_BER_ERROR = 0x02
310
311#ifndef BDE_OMIT_INTERNAL_DEPRECATED
314#endif // BDE_OMIT_INTERNAL_DEPRECATED
315 };
316
317 private:
318 // DATA
319 const BerEncoderOptions *d_options; // held, not owned
320 bslma::Allocator *d_allocator; // held, not owned
321
322 // placeholder for MemOutStream
324
325 // if not zero, log stream was created at the moment of first logging
326 // and must be destroyed
327 MemOutStream *d_logStream;
328
329 ErrorSeverity d_severity; // error severity
330
331 bsl::streambuf *d_streamBuf; // held, not owned
332 int d_currentDepth; // current depth
333
334 // NOT IMPLEMENTED
335 BerEncoder(const BerEncoder&); // = delete;
336 BerEncoder& operator=(const BerEncoder&); // = delete;
337
338 // PRIVATE MANIPULATORS
339
340 /// Log the specified `msg` using the specified `tagClass`, `tagNumber`,
341 /// name, and `index`, and return `errorSeverity()`.
342 ErrorSeverity logMsg(const char *msg,
343 BerConstants::TagClass tagClass,
344 int tagNumber,
345 const char *name = 0,
346 int index = -1);
347
348 /// Log error and upgrade the severity level. Return `errorSeverity()`.
349 ErrorSeverity logError(BerConstants::TagClass tagClass,
350 int tagNumber,
351 const char *name = 0,
352 int index = -1);
353
354 /// Return the stream for logging. Note the if stream has not been
355 /// created yet, it will be created during this call.
356 bsl::ostream& logStream();
357
358 int encodeImpl(const bsl::vector<char>& value,
359 BerConstants::TagClass tagClass,
360 int tagNumber,
361 int formattingMode,
363
364 template <typename TYPE>
365 int encodeArrayImpl(const TYPE& value,
366 BerConstants::TagClass tagClass,
367 int tagNumber,
368 int formattingMode);
369
370 template <typename TYPE>
371 int encodeImpl(const TYPE& value,
372 BerConstants::TagClass tagClass,
373 int tagNumber,
374 int formattingMode,
376
377 template <typename TYPE>
378 int encodeImpl(const TYPE& value,
379 BerConstants::TagClass tagClass,
380 int tagNumber,
381 int formattingMode,
383
384 template <typename TYPE>
385 int encodeImpl(const TYPE& value,
386 BerConstants::TagClass tagClass,
387 int tagNumber,
388 int formattingMode,
390
391 template <typename TYPE>
392 int encodeImpl(const TYPE& value,
393 BerConstants::TagClass tagClass,
394 int tagNumber,
395 int formattingMode,
397
398 template <typename TYPE>
399 int encodeImpl(const TYPE& value,
400 BerConstants::TagClass tagClass,
401 int tagNumber,
402 int formattingMode,
404
405 template <typename TYPE>
406 int encodeImpl(const TYPE& value,
407 BerConstants::TagClass tagClass,
408 int tagNumber,
409 int formattingMode,
411
412 template <typename TYPE>
413 int encodeImpl(const TYPE& value,
414 BerConstants::TagClass tagClass,
415 int tagNumber,
416 int formattingMode,
418
419 template <typename TYPE>
420 int encodeImpl(const TYPE& value,
421 BerConstants::TagClass tagClass,
422 int tagNumber,
423 int formattingMode,
425
426 public:
427 // CREATORS
428
429 /// Construct an encoder object. Optionally specify encoder `options`.
430 /// If `options` is 0, `BerEncoderOptions()` is used. Optionally
431 /// specify a `basicAllocator` used to supply memory. If
432 /// `basicAllocator` is 0, the currently installed default allocator is
433 /// used.
435 bslma::Allocator *basicAllocator = 0);
436
437 /// Destroy this object. This destruction has no effect on objects
438 /// pointed-to by the pointers provided at construction.
440
441 /// Encode the specified non-modifiable `value` to the specified
442 /// `streamBuf`. Return 0 on success, and a non-zero value otherwise.
443 template <typename TYPE>
444 int encode(bsl::streambuf *streamBuf, const TYPE& value);
445
446 /// Encode the specified non-modifiable `value` to the specified
447 /// `stream`. Return 0 on success, and a non-zero value otherwise. If
448 /// the encoding fails `stream` will be invalidated.
449 template <typename TYPE>
450 int encode(bsl::ostream& stream, const TYPE& value);
451
452 // ACCESSORS
453
454 /// Return address of the options.
455 const BerEncoderOptions *options() const;
456
457 /// Return the severity of the most severe warning or error encountered
458 /// during the last call to the `encode` method. The severity is reset
459 /// each time `encode` is called.
461
462 /// Return a string containing any error, warning, or trace messages
463 /// that were logged during the last call to the `encode` method. The
464 /// log is reset each time `encode` is called.
466};
467
468 // ===================================
469 // private class BerEncoder_LevelGuard
470 // ===================================
471
472/// This class serves the purpose to automatically increment-decrement the
473/// current depth level.
474///
475/// See @ref balber_berencoder
477
478 // DATA
479 BerEncoder *d_encoder;
480
481 // NOT IMPLEMENTED
483 BerEncoder_LevelGuard& operator=(BerEncoder_LevelGuard&); // = delete;
484
485 public:
486 // CREATORS
489};
490
491 // ================================
492 // private class BerEncoder_Visitor
493 // ================================
494
495/// This class is used as a visitor for visiting contained objects during
496/// encoding. Produces always BER elements with CONTEXT_SPECIFIC BER tag.
497///
498/// See @ref balber_berencoder
500
501 // DATA
502 BerEncoder *d_encoder; // encoder to write data to
503 BerEncoder_LevelGuard d_levelGuard;
504
505 // NOT IMPLEMENTED
506 BerEncoder_Visitor(const BerEncoder_Visitor&); // = delete;
507 BerEncoder_Visitor& operator=(const BerEncoder_Visitor&); // = delete;
508
509 public:
510 // CREATORS
513
514 // MANIPULATORS
515 template <typename TYPE, typename INFO>
516 int operator()(const TYPE& value, const INFO& info);
517};
518
519 // ================================================
520 // private class BerEncoder_UniversalElementVisitor
521 // ================================================
522
523/// This class is used as a visitor for visiting the top-level element and
524/// also array elements during encoding. This class is required so that the
525/// universal tag number of the element can be determined when the element
526/// is visited.
527///
528/// See @ref balber_berencoder
530
531 // PRIVATE DATA MEMBERS
532 BerEncoder *d_encoder; // streambuf to write data to
533 int d_formattingMode; // formatting mode to use
534 BerEncoder_LevelGuard d_levelGuard;
535
536 private:
537 // NOT IMPLEMENTED
540 // = delete;
543 // = delete;
544 public:
545 // CREATORS
547 int formattingMode);
548
550
551 // MANIPULATORS
552 template <typename TYPE>
553 int operator()(const TYPE& value);
554};
555
556// ============================================================================
557// PROXY CLASSES
558// ============================================================================
559
560 // =============================
561 // struct BerEncoder_encodeProxy
562 // =============================
563
564/// Component-private struct. Provides accessor that keeps current context
565/// and can be used in different `bdlat` Category Functions.
567
568 // DATA MEMBERS
573
574 // CREATORS Creators have been omitted to allow simple static
575 // initialization of this struct.
576
577 // FUNCTIONS
578 template <typename TYPE>
579 int operator()(const TYPE& object, bslmf::Nil);
580
581 template <typename TYPE, typename ANY_CATEGORY>
582 int operator()(const TYPE& object, ANY_CATEGORY category);
583
584 template <typename TYPE>
585 int operator()(const TYPE& object);
586};
587
588} // close package namespace
589
590// ============================================================================
591// INLINE DEFINITIONS
592// ============================================================================
593
594 // --------------------------------------
595 // class balber::BerEncoder::MemOutStream
596 // --------------------------------------
597
598inline
599balber::BerEncoder::MemOutStream::MemOutStream(
600 bslma::Allocator *basicAllocator)
601: bsl::ostream(0)
602, d_sb(bslma::Default::allocator(basicAllocator))
603{
604 rdbuf(&d_sb);
605}
606
607// MANIPULATORS
608inline
610{
611 d_sb.reset();
612}
613
614// ACCESSORS
615inline
617{
618 return d_sb.data();
619}
620
621inline
623{
624 return static_cast<int>(d_sb.length());
625}
626
627namespace balber {
628
629 // ----------------------------
630 // class BerEncoder::LevelGuard
631 // ----------------------------
632
633inline
634BerEncoder_LevelGuard::BerEncoder_LevelGuard(BerEncoder *encoder)
635: d_encoder (encoder)
636{
637 ++d_encoder->d_currentDepth;
638}
639
640inline
642{
643 --d_encoder->d_currentDepth;
644}
645
646 // -----------------------------
647 // struct BerEncoder_encodeProxy
648 // -----------------------------
649
650template <typename TYPE>
651inline
653{
655 return -1;
656}
657
658template <typename TYPE, typename ANY_CATEGORY>
659inline
661 ANY_CATEGORY category)
662{
663 return d_encoder->encodeImpl(object,
667 category);
668}
669
670template <typename TYPE>
671inline
673{
674 typedef typename
676
677 return this->operator()(object, TypeCategory());
678}
679
680 // ----------------
681 // class BerEncoder
682 // ----------------
683
684// ACCESSORS
685inline
687{
688 return d_options;
689}
690
691inline
693{
694 return d_severity;
695}
696
697inline
699{
700 if (d_logStream) {
701 return bslstl::StringRef(d_logStream->data(), d_logStream->length());
702 }
703
704 return bslstl::StringRef();
705}
706
707inline
708bsl::ostream& BerEncoder::logStream()
709{
710 if (d_logStream == 0) {
711 d_logStream = new(d_logArea.buffer()) MemOutStream(d_allocator);
712 }
713 return *d_logStream;
714}
715
716template <typename TYPE>
717int BerEncoder::encode(bsl::streambuf *streamBuf, const TYPE& value)
718{
719 BSLS_ASSERT(!d_streamBuf);
720
721 d_streamBuf = streamBuf;
722 d_severity = e_BER_SUCCESS;
723
724 if (d_logStream != 0) {
725 d_logStream->reset();
726 }
727
728 d_currentDepth = 0;
729
730 int rc;
731
732 if (! d_options) {
733 BerEncoderOptions options; // temporary options object
734 d_options = &options;
736 this,
738
739 rc = visitor(value);
740 d_options = 0;
741 }
742 else {
744 this,
746 rc = visitor(value);
747 }
748
749 d_streamBuf = 0;
750
751 streamBuf->pubsync();
752
753 return rc;
754}
755
756template <typename TYPE>
757int BerEncoder::encode(bsl::ostream& stream, const TYPE& value)
758{
759 if (!stream.good()) {
760 return -1;
761 }
762
763 if (0 != this->encode(stream.rdbuf(), value)) {
764 stream.setstate(bsl::ios_base::failbit);
765 return -1;
766 }
767 return 0;
768}
769
770// PRIVATE MANIPULATORS
771template <typename TYPE>
772int BerEncoder::encodeImpl(const TYPE& value,
773 BerConstants::TagClass tagClass,
774 int tagNumber,
775 int formattingMode,
777{
778 enum { k_SUCCESS = 0, k_FAILURE = -1 };
779
781
782 int rc = BerUtil::putIdentifierOctets(d_streamBuf,
783 tagClass,
784 tagType,
785 tagNumber);
786 if (rc | BerUtil::putIndefiniteLengthOctet(d_streamBuf)) {
787 return k_FAILURE; // RETURN
788 }
789
790 const bool isUntagged = formattingMode
792
793 if (!isUntagged) {
794 // According to X.694 (clause 20.4), an XML choice (not anonymous)
795 // element is encoded as a sequence with 1 element.
796
797 rc = BerUtil::putIdentifierOctets(d_streamBuf,
799 tagType,
800 0);
801 if (rc | BerUtil::putIndefiniteLengthOctet(d_streamBuf)) {
802 return k_FAILURE;
803 }
804 }
805
807
809
810 BerEncoder_Visitor visitor(this);
811
812 if (0 != bdlat_ChoiceFunctions::accessSelection(value, visitor)) {
813 return k_FAILURE; // RETURN
814 }
815 }
816 else {
817
818 if (d_options->disableUnselectedChoiceEncoding()) {
819
820 this->logError(tagClass,
821 tagNumber);
822
823 return k_FAILURE; // RETURN
824 }
825
826 }
827
828 if (!isUntagged) {
829 // According to X.694 (clause 20.4), an XML choice (not anonymous)
830 // element is encoded as a sequence with 1 element.
831
832 // Don't waste time checking the result of this call -- the only thing
833 // that can go wrong is eof, which will happen again when we call it
834 // again below.
836 }
837
838 return BerUtil::putEndOfContentOctets(d_streamBuf);
839}
840
841template <typename TYPE>
842int BerEncoder::encodeImpl(const TYPE& value,
843 BerConstants::TagClass tagClass,
844 int tagNumber,
845 int formattingMode,
847{
848 enum { k_SUCCESS = 0, k_FAILURE = -1 };
849
850 bool isNillable = formattingMode & bdlat_FormattingMode::e_NILLABLE;
851
852 if (isNillable) {
853
854 // nillable is encoded in BER as a sequence with one optional element
855
856 int rc = BerUtil::putIdentifierOctets(d_streamBuf,
857 tagClass,
859 tagNumber);
860 if (rc | BerUtil::putIndefiniteLengthOctet(d_streamBuf)) {
861 return k_FAILURE;
862 }
863
865
866 BerEncoder_encodeProxy proxy1 = {
867 this,
869 0, // tagNumber
870 formattingMode };
871
873 proxy1)) {
874 return k_FAILURE;
875 }
876 } // end of bdlat_NullableValueFunctions::isNull(...)
877
878 return BerUtil::putEndOfContentOctets(d_streamBuf);
879 } // end of isNillable
880
882
883 BerEncoder_encodeProxy proxy2 = { this,
884 tagClass,
885 tagNumber,
886 formattingMode };
887
888 if (0 != bdlat_NullableValueFunctions::accessValue(value, proxy2)) {
889 return k_FAILURE;
890 }
891 }
892
893 return k_SUCCESS;
894}
895
896template <typename TYPE>
897int BerEncoder::encodeImpl(const TYPE& value,
898 BerConstants::TagClass tagClass,
899 int tagNumber,
900 int formattingMode,
902{
903 typedef typename
905
906 typedef typename
908
909 int rc = encodeImpl(
911 tagClass,
912 tagNumber,
913 formattingMode,
914 BaseTypeCategory());
915
916 return rc;
917}
918
919template <typename TYPE>
920int BerEncoder::encodeImpl(const TYPE& value,
921 BerConstants::TagClass tagClass,
922 int tagNumber,
923 int ,
925{
926 int rc = BerUtil::putIdentifierOctets(d_streamBuf,
927 tagClass,
929 tagNumber);
930
931 int intValue;
932 bdlat_EnumFunctions::toInt(&intValue, value);
933
934 rc |= BerUtil::putValue(d_streamBuf, intValue);
935
936 return rc;
937}
938
939template <typename TYPE>
940int BerEncoder::encodeImpl(const TYPE& value,
941 BerConstants::TagClass tagClass,
942 int tagNumber,
943 int ,
945{
946 BerEncoder_Visitor visitor(this);
947
948 int rc = BerUtil::putIdentifierOctets(d_streamBuf,
949 tagClass,
951 tagNumber);
952 rc |= BerUtil::putIndefiniteLengthOctet(d_streamBuf);
953 if (rc) {
954 return rc;
955 }
956
958 rc |= BerUtil::putEndOfContentOctets(d_streamBuf);
959
960 return rc;
961}
962
963template <typename TYPE>
964int BerEncoder::encodeImpl(const TYPE& value,
965 BerConstants::TagClass tagClass,
966 int tagNumber,
967 int ,
969{
970 int rc = BerUtil::putIdentifierOctets(d_streamBuf,
971 tagClass,
973 tagNumber);
974 rc |= BerUtil::putValue(d_streamBuf, value, d_options);
975
976 return rc;
977}
978
979template <typename TYPE>
980inline
981int BerEncoder::encodeImpl(const TYPE& value,
982 BerConstants::TagClass tagClass,
983 int tagNumber,
984 int formattingMode,
986{
987 enum { k_SUCCESS = 0, k_FAILURE = -1 };
988
989 if (d_currentDepth <= 1 || tagClass == BerConstants::e_UNIVERSAL) {
990 return k_FAILURE;
991 }
992 // Note: bsl::vector<char> is handled as a special case in the CPP file.
993 return this->encodeArrayImpl(value,
994 tagClass,
995 tagNumber,
996 formattingMode);
997}
998
999template <typename TYPE>
1000int
1001BerEncoder::encodeArrayImpl(const TYPE& value,
1002 BerConstants::TagClass tagClass,
1003 int tagNumber,
1004 int formattingMode)
1005{
1006 enum { k_FAILURE = -1, k_SUCCESS = 0 };
1007
1008 const int size = static_cast<int>(bdlat_ArrayFunctions::size(value));
1009
1010 if (0 == size && d_options && !d_options->encodeEmptyArrays()) {
1011 return k_SUCCESS; // RETURN
1012 }
1013
1015
1016 int rc = BerUtil::putIdentifierOctets(d_streamBuf,
1017 tagClass,
1018 tagType,
1019 tagNumber);
1020 rc |= BerUtil::putIndefiniteLengthOctet(d_streamBuf);
1021 if (rc) {
1022 return k_FAILURE; // RETURN
1023 }
1024
1025 BerEncoder_UniversalElementVisitor visitor(this, formattingMode);
1026
1027 for (int i = 0; i < size; ++i) {
1028 if (0 != bdlat_ArrayFunctions::accessElement(value, visitor, i)) {
1029
1030 this->logError(tagClass,
1031 tagNumber,
1032 0, // bdlat_TypeName::name(value),
1033 i);
1034
1035 return k_FAILURE; // RETURN
1036 }
1037 }
1038
1039 return BerUtil::putEndOfContentOctets(d_streamBuf);
1040}
1041
1042template <typename TYPE>
1043inline
1044int BerEncoder::encodeImpl(const TYPE& value,
1045 BerConstants::TagClass tagClass,
1046 int tagNumber,
1047 int formattingMode,
1049{
1050 BerEncoder_encodeProxy proxy = { this,
1051 tagClass,
1052 tagNumber,
1053 formattingMode
1054 };
1055
1056 return bdlat_TypeCategoryUtil::accessByCategory(value, proxy);
1057}
1058
1059 // --------------------------------
1060 // private class BerEncoder_Visitor
1061 // --------------------------------
1062
1063// CREATORS
1064inline
1065BerEncoder_Visitor::BerEncoder_Visitor(BerEncoder *encoder)
1066: d_encoder(encoder)
1067, d_levelGuard(encoder)
1068{
1069}
1070
1071inline
1075
1076// MANIPULATORS
1077template <typename TYPE, typename INFO>
1078inline
1079int BerEncoder_Visitor::operator()(const TYPE& value, const INFO& info)
1080{
1081 typedef typename
1083
1084 int rc = d_encoder->encodeImpl(value,
1086 info.id(),
1087 info.formattingMode(),
1088 TypeCategory());
1089
1090 if (rc) {
1091 d_encoder->logError(BerConstants::e_CONTEXT_SPECIFIC,
1092 info.id(),
1093 info.name());
1094 }
1095
1096 return rc;
1097}
1098
1099 // ------------------------------------------------
1100 // private class BerEncoder_UniversalElementVisitor
1101 // ------------------------------------------------
1102
1103// CREATORS
1104inline
1105BerEncoder_UniversalElementVisitor::
1106BerEncoder_UniversalElementVisitor(BerEncoder *encoder,
1107 int formattingMode)
1108: d_encoder(encoder)
1109, d_formattingMode(formattingMode)
1110, d_levelGuard(encoder)
1111{
1112}
1113
1114inline
1119
1120// MANIPULATORS
1121template <typename TYPE>
1123{
1124 enum { k_SUCCESS = 0, k_FAILURE = -1 };
1125
1126 typedef typename
1128
1130 value,
1131 d_formattingMode,
1132 d_encoder->options());
1133
1134 if (d_encoder->encodeImpl(value,
1136 static_cast<int>(tagNumber),
1137 d_formattingMode,
1138 TypeCategory())) {
1139 d_encoder->logError(BerConstants::e_UNIVERSAL,
1140 tagNumber);
1141 return k_FAILURE;
1142 }
1143
1144 return k_SUCCESS;
1145}
1146
1147} // close package namespace
1148
1149#endif
1150
1151// ----------------------------------------------------------------------------
1152// Copyright 2015 Bloomberg Finance L.P.
1153//
1154// Licensed under the Apache License, Version 2.0 (the "License");
1155// you may not use this file except in compliance with the License.
1156// You may obtain a copy of the License at
1157//
1158// http://www.apache.org/licenses/LICENSE-2.0
1159//
1160// Unless required by applicable law or agreed to in writing, software
1161// distributed under the License is distributed on an "AS IS" BASIS,
1162// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1163// See the License for the specific language governing permissions and
1164// limitations under the License.
1165// ----------------------------- END-OF-FILE ----------------------------------
1166
1167/** @} */
1168/** @} */
1169/** @} */
Definition balber_berencoderoptions.h:73
bool disableUnselectedChoiceEncoding() const
Definition balber_berencoderoptions.h:752
bool encodeEmptyArrays() const
Definition balber_berencoderoptions.h:734
Definition balber_berencoder.h:476
~BerEncoder_LevelGuard()
Definition balber_berencoder.h:641
Definition balber_berencoder.h:529
~BerEncoder_UniversalElementVisitor()
Definition balber_berencoder.h:1116
int operator()(const TYPE &value)
Definition balber_berencoder.h:1122
Definition balber_berencoder.h:499
~BerEncoder_Visitor()
Definition balber_berencoder.h:1072
int operator()(const TYPE &value, const INFO &info)
Definition balber_berencoder.h:1079
Definition balber_berencoder.h:248
int encode(bsl::streambuf *streamBuf, const TYPE &value)
Definition balber_berencoder.h:717
friend struct BerEncoder_encodeProxy
Definition balber_berencoder.h:252
ErrorSeverity errorSeverity() const
Definition balber_berencoder.h:692
ErrorSeverity
Definition balber_berencoder.h:307
@ e_BER_ERROR
Definition balber_berencoder.h:309
@ e_BER_SUCCESS
Definition balber_berencoder.h:308
@ BDEM_BER_SUCCESS
Definition balber_berencoder.h:312
@ BDEM_BER_ERROR
Definition balber_berencoder.h:313
friend class BerEncoder_Visitor
Definition balber_berencoder.h:253
const BerEncoderOptions * options() const
Return address of the options.
Definition balber_berencoder.h:686
friend class BerEncoder_LevelGuard
Definition balber_berencoder.h:255
friend class BerEncoder_UniversalElementVisitor
Definition balber_berencoder.h:254
bslstl::StringRef loggedMessages() const
Definition balber_berencoder.h:698
BerEncoder(const BerEncoderOptions *options=0, bslma::Allocator *basicAllocator=0)
Definition bdlsb_memoutstreambuf.h:212
Definition bslstl_vector.h:1025
Definition bslma_allocator.h:457
Definition bslstl_stringref.h:372
const char * data() const
Definition balber_berencoder.h:616
void reset()
Reset the internal streambuf to empty.
Definition balber_berencoder.h:609
int length() const
Definition balber_berencoder.h:622
static int accessByCategory(const TYPE &object, ACCESSOR &accessor)
Definition bdlat_typecategory.h:1444
#define BSLS_ASSERT(X)
Definition bsls_assert.h:1804
#define BSLS_ASSERT_SAFE(X)
Definition bsls_assert.h:1762
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
#define BSLS_KEYWORD_OVERRIDE
Definition bsls_keyword.h:653
Definition balber_berconstants.h:82
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:511
int selectionId(const TYPE &object)
const BaseType< TYPE >::Type & convertToBaseType(const TYPE &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 bdlb_printmethods.h:283
Definition balxml_encoderoptions.h:68
StringRefImp< char > StringRef
Definition bslstl_stringref.h:699
TagType
Definition balber_berconstants.h:113
@ e_PRIMITIVE
Definition balber_berconstants.h:116
@ e_CONSTRUCTED
Definition balber_berconstants.h:117
TagClass
Definition balber_berconstants.h:92
@ e_CONTEXT_SPECIFIC
Definition balber_berconstants.h:97
@ e_UNIVERSAL
Definition balber_berconstants.h:95
Definition balber_berencoder.h:566
BerEncoder * d_encoder
Definition balber_berencoder.h:569
BerConstants::TagClass d_tagClass
Definition balber_berencoder.h:570
int operator()(const TYPE &object, bslmf::Nil)
Definition balber_berencoder.h:652
int d_formattingMode
Definition balber_berencoder.h:572
int d_tagNumber
Definition balber_berencoder.h:571
Value
Definition balber_beruniversaltagnumber.h:194
static Value select(const TYPE &object, int formattingMode, int *alternateTag)
Definition balber_beruniversaltagnumber.h:595
static int putEndOfContentOctets(bsl::streambuf *streamBuf)
Definition balber_berutil.h:3951
static int putIndefiniteLengthOctet(bsl::streambuf *streamBuf)
Definition balber_berutil.h:3957
static int putValue(bsl::streambuf *streamBuf, const TYPE &value, const BerEncoderOptions *options=0)
Definition balber_berutil.h:3970
static int putIdentifierOctets(bsl::streambuf *streamBuf, BerConstants::TagClass tagClass, BerConstants::TagType tagType, int tagNumber)
TYPE::BaseType Type
Definition bdlat_customizedtypefunctions.h:536
@ e_DEFAULT
Definition bdlat_formattingmode.h:110
@ e_NILLABLE
Definition bdlat_formattingmode.h:121
@ e_UNTAGGED
Definition bdlat_formattingmode.h:118
Definition bdlat_typecategory.h:1035
Definition bdlat_typecategory.h:1036
Definition bdlat_typecategory.h:1037
Definition bdlat_typecategory.h:1034
Definition bdlat_typecategory.h:1038
Definition bdlat_typecategory.h:1039
Definition bdlat_typecategory.h:1040
Definition bdlat_typecategory.h:1041
This struct is empty and represents a nil type.
Definition bslmf_nil.h:131
Definition bsls_objectbuffer.h:276
char * buffer()
Definition bsls_objectbuffer.h:344