Provide a BER encoder class.
More...
Detailed Description
- Outline
-
-
- Purpose:
- Provide a BER encoder class.
-
- Classes:
-
- See also:
- Component balber_berdecoder, bdem_bdemencoder, Component balxml_encoder
-
- Description:
- This component defines a single class,
balber::BerEncoder
, that contains a parameterized encode
function. The encode
function encodes data read from a specified stream and loads the corresponding object to an object of the parameterized type. The encode
method is overloaded for two types of input streams:
-
bsl::streambuf
-
bsl::istream
- This component encodes objects based on the X.690 BER specification. It can only be used with types supported by the
bdlat
framework.
-
- Usage:
- This section illustrates intended use of this component.
-
- Example 1: Encoding an Employee Record:
- Suppose that an "employee record" consists of a sequence of attributes --
name
, age
, and salary
-- that are of types bsl::string
, int
, and float
, respectively. Furthermore, we have a need to BER encode employee records as a sequence of values (for out-of-process consumption).
- Assume that we have defined a
usage::EmployeeRecord
class to represent employee record values, and assume that we have provided the bdlat
specializations that allow the balber
codec components to represent class values as a sequence of BER primitive values. See bdlat_sequencefunctions
|Usage for details of creating specializations for a sequence type.
- First, we create an employee record object having typical values:
usage::EmployeeRecord bob("Bob", 56, 1234.00);
assert("Bob" == bob.name());
assert( 56 == bob.age());
assert(1234.00 == bob.salary());
Now, we create a balber::Encoder
object and use it to encode our bob
object. Here, to facilitate the examination of our results, the BER encoding data is delivered to a bslsb::MemOutStreamBuf
object: Finally, we confirm that the generated BER encoding has the expected layout and values. We create an bdlsb::FixedMemInStreamBuf
to manage our access to the data portion of the bdlsb::MemOutStreamBuf
where our BER encoding resides: The balber_berutil
component provides functions that allow us to decode the descriptive fields and values of the BER encoded sequence: The UNIVERSAL
value in tagClass
indicates that the tagNumber
value represents a type in the BER standard, a BER_SEQUENCE
, as we requested of the infrastructure (see the IsSequence
specialization above). The tagType
value of CONSTRUCTED
indicates that this is a non-primitive type. The INDEFINITE
value for length is typical for sequence encodings. In these cases, the end-of-data is indicated by a sequence to two null bytes.
- We now examine the tags and values corresponding to each of the data members of
usage::EmployeeRecord
class. For each of these the tagClass
is CONTEXT_SPECIFIC
(i.e., member of a larger construct) and the tagType
is PRIMITIVE
(bsl::string
, int
, and float
each correspond to a primitive BER type. The tagNumber
for each field was defined (in the elided definiton) to correspond the position of the field in the usage::EmployeeRecord
class. rc = balber::BerUtil::getIdentifierOctets(&isb,
&tagClass,
&tagType,
&tagNumber,
&accumNumBytesConsumed);
assert(0 == rc);
assert(balber::BerConstants::e_CONTEXT_SPECIFIC == tagClass);
assert(balber::BerConstants::e_PRIMITIVE == tagType);
assert(1 == tagNumber);
bsl::string name;
rc = balber::BerUtil::getValue(&isb, &name, &accumNumBytesConsumed);
assert(0 == rc);
assert("Bob" == name);
rc = balber::BerUtil::getIdentifierOctets(&isb,
&tagClass,
&tagType,
&tagNumber,
&accumNumBytesConsumed);
assert(0 == rc);
assert(balber::BerConstants::e_CONTEXT_SPECIFIC == tagClass);
assert(balber::BerConstants::e_PRIMITIVE == tagType);
assert(2 == tagNumber);
int age = 0;
rc = balber::BerUtil::getValue(&isb, &age, &accumNumBytesConsumed);
assert(0 == rc);
assert(56 == age);
rc = balber::BerUtil::getIdentifierOctets(&isb,
&tagClass,
&tagType,
&tagNumber,
&accumNumBytesConsumed);
assert(0 == rc);
assert(balber::BerConstants::e_CONTEXT_SPECIFIC == tagClass);
assert(balber::BerConstants::e_PRIMITIVE == tagType);
assert(3 == tagNumber);
float salary = 0.0;
rc = balber::BerUtil::getValue(&isb, &salary, &accumNumBytesConsumed);
assert(0 == rc);
assert(1234.00 == salary);
Lastly, we confirm that end-of-data sequence (two null bytes) are found we expect them and that we have entirely consumed the data that we generated by our encoding.