Generated decode functions are invoked through the class interface by calling the
base class Decode
method as follows:
status = <object>.Decode();
In this definition, <object> is an instance of the control class (i.e., ASN1C_<prodName>) generated for the given production.
You must pass an ASN1AVNDecodeBuffer
object to the
control class constructor for <object>
; this provides the message
content to be decoded.
The function result variable status
returns the status of the decode
operation. The return status will be zero if decoding is successful or a negative value
if an error occurs. Error status codes are defined in rtsrc/asn1ErrCodes.h
and rtxsrc/rtxErrCodes.h
and are listed in
Appendix A of the C/C++ Common Functions Reference
Manual.
A program fragment that could be used to decode an employee record is as follows:
#include employee.h // include file generated by ASN1C main () { int status; const char* filename = "message.txt"; /* Create buffer on input. Here, we use the convenience constructor that takes a file name. */ ASN1AVNDecodeBuffer decodeBuffer (filename); /* Setup objects to use for decoding. Note that we pass the decodeBuffer to the ASN1C_PersonnelRecord constructor. */ ASN1T_PersonnelRecord data; ASN1C_PersonnelRecord personnelRecordPDU (decodeBuffer, data); /* Decode */ stat = personnelRecordPDU.Decode (); if (stat == 0) { printf ("Decode of data was successful\n"); printf ("Decoded record:\n"); personnelRecordPDU.Print ("PersonnelRecord"); } else { /* Error */ decodeBuffer.printErrorInfo (); }
It is not necessary to free memory when using the C++ interface.
This is because the control class hides all of the details
of managing the context and releasing dynamic memory. The memory is automatically
released when both the message buffer object (ASN1AVNDecodeBuffer
)
and the control class object (ASN1C_<ProdName>
) are deleted or go out of scope.
Reference counting of a context variable shared by both interfaces is used to
accomplish this.
To decode from a buffer, use this constructor: ASN1AVNDecodeBuffer (const OSOCTET* pMsgBuf, size_t msgBufLen)
To decode from a stream, use this constructor: ASN1AVNDecodeBuffer(OSRTInputStream& istream)
and pass a stream object in. The main stream classes are:
OSRTFileInputStream
OSRTMemoryInputStream
OSRTSocketInputStream
Here is an example using a file stream for decoding:
#include "Employee.h" /* Generated header */ #include "rtxsrc\OSRTFileInputStream.h" int main (int argc, char** argv) { const char* filename = "message.txt"; /* Setup the decode buffer. */ OSRTFileInputStream istream(filename); ASN1AVNDecodeBuffer decodeBuffer (istream); /* Create objects to decode into. */ ASN1T_PersonnelRecord data; ASN1C_PersonnelRecord personnelRecordPDU (decodeBuffer, data); /* Decode */ stat = personnelRecordPDU.Decode(); if (0 != stat) { decodeBuffer.printErrorInfo (); return stat; } /* Do whatever with "data". */ ... }
It is not necessary to close the stream object; it will be closed when it goes out of scope.
If the input contains multiple records, you will need
a loop that determines whether to decode another record or not.
An example is provided in cpp/sample_avn/employee_loop
.
In the sample, observe the following points:
rtxTxtSkipWhitespace
is used to skip whitespace that might appear between records.
rtxCheckInputBuffer
is used to check whether more
input is present beyond that whitespace.
memReset
is used to allow memory
allocated by the current decode operation to be reused for the
next decode operation (doing this is optional).