TOP

OssControl

OssControl is an abstract base class from which the ASN.1 compiler derives a class for use with the specification being compiled. Since the class is abstract, objects can only be instantiated in derived forms. The derived class is used for

  • Encoding
  • Decoding
  • Printing
  • Constraint checking
  • Conversion to and from ASN.1 value notation
  • Controlling the encoding/decoding mode
  • Temporary storage by the runtime libraries

Some class constructors and methods are for internal use only and are not included in this documentation. Do not use these or any other undocumented methods.

NOTE: In multithreaded programs, do not use one OssControl object for several threads concurrently.

Definition

class OssControl {
public:
  int setEncodingRules(OssEncodingRules rules);
  OssEncodingRules getEncodingRules() const;
  int setEncodingFlags(unsigned long flags);
  unsigned long getEncodingFlags() const;
  int setDecodingFlags(unsigned long flags);
  unsigned long getDecodingFlags() const;
  const char *getErrorMsg() const;
  int printHex(const char *buffer, unsigned long length);
  int setOutputFile(const char *filename);
  int resetOutputFile();
  virtual int userPrint(FILE *stream, const char *fmt, va_list ap);
  void print(const char *text);
  int setXmlStylesheet(const char *xslFilePath);
  int setXmlDTD(const char *pduName, const char *externalID, short dtdKind);
  void printXML(const char *buffer, unsigned long length, int pretty_print);
  int getNamespacePrefix(const char *ns, const char **prefix);
  int setNamespacePrefix(const char *ns, const char *prefix);
  int setXMLEncodingRules(OssEncodingRules rules);
  OssEncodingRules getXMLEncodingRules() const;
  int setDebugFlags(unsigned long flags);
  unsigned long getDebugFlags() const;
  unsigned long getCompatibilityFlags();
  int setCompatibilityFlags(unsigned long flag);
  void setTimeout(long timeout);
  void setDebugStringTruncate(size_t length);
  size_t getDebugStringTruncate() const;
  int valid();
  void printJSON(const char *buffer, unsigned long length, int pretty_print); 
  int setJsonFlags(unsigned long flags);
  unsigned long getJsonFlags() const;
  int setJsonIndentSize(int indent_size);
  int getJsonIndentSize() const;
  void setCompressor(OssCompressor *comp);
  OssCompressor* getCompressor();
};

Methods

int setEncodingRules(OssEncodingRules rules);
This method sets the encoding rules used by the OssControl object. OssEncodingRules is an enumerated type and has the following members: OSS_BER, OSS_DER, OSS_PER_ALIGNED, OSS_PER_UNALIGNED, OSS_CER, OSS_XER, OSS_CXER, OSS_EXER, OSS_OER, OSS_COER, and OSS_JSON. This enumeration can be extended further as new encoding rules are implemented in the Space Optimized Encoder Decoder. When successful, the method returns 0; otherwise, it returns a non-zero error code. When "full-exception" mode is in effect, errors are signaled with C++ exceptions, so the method never returns anything but 0.
OssEncodingRules getEncodingRules() const;
This method returns the encoding rules currently used by the OssControl object.
int setEncodingFlags(unsigned long flags);
This method sets the encoding mode used by the OssControl object. The following flags can be used:
Flag Description
AUTOMATIC_ENCDEC Specifies automatic encoding of containing structures within open types. This flag eliminates repeated calls to the encoder/decoder when processing structures with nested open types. By default, the encoder/decoder does not handle open types automatically.
BACK_ALIGN Tells the encoder to right-justify data within the preallocated output buffer.
COMPACT_XER_ENCODING Can be set when the XML encoding rules are selected. The resulting XER encoding contains no whitespace or newline symbols, so its length is shorter. By default, the XER encoder formats the XML output to make it more human-readable.
DEBUGPDU Prints trace data as each PDU is encoded, to use for debugging or diagnostic purposes. Only the SOED supports this flag.
DEFAULT_ALIGN Instructs the encoder to use the most efficient alignment in the preallocated output buffer. The data will be
  • Right justified for BER DEFINITE and DER.
  • Left justified for all others: PER, BER INDEFINITE, CER, XER and CXER.
DEFINITE Instructs the encoder to use the definite length form when encoding. This flag only applies to BER.
FRONT_ALIGN Instructs the encoder to left-justify data within the preallocated output buffer. This flag is required when sequentially encoding several PDUs into one preallocated buffer.
INDEFINITE Instructs the encoder to use the indefinite length form when encoding. This flag only applies to BER and can be used only with the SOED. It is ignored by the Lean and the Time-Optimized Encoder/Decoders.
NOCONSTRAIN Instructs the encoder to not perform strict constraint checking at runtime for better overall performance. We recommend that you do not use this flag during development as strict constraint checking can help you find errors in your code.
NOTRAPPING Disables signal trapping and is the default. See also OSS_TRAPPING.
OSS_TRAPPING Enables signal trapping. With signal trapping on, performance suffers somewhat. More importantly, signal trapping is not always thread-safe, depending on the operating system in use. We recommend that you do not enable trapping for multi-threaded applications. In other cases, you can specify this flag to help find coding errors since, with signal trapping enabled, the OSS runtime will return an error code and message, rather than just crashing. The old NOTRAPPING flag is supported for the sake of compatibility, but OSS_TRAPPING takes precedence. That is, if both NOTRAPPING and OSS_TRAPPING are specified then trapping is enabled; if neither flag is specified then trapping is disabled. NOTE: Before release 4.1, the OSS runtime trapped signals by default.
NO_XML_DECLARATION Can be specified when the XML encoding rules are selected. This flag prevents the encoder from generating an XML header declaration (for example, <?xml version="1.0" encoding="UTF-8"?>) at the beginning of the resulting XER encoding. By default, such declarations are generated.
OSS_AUTO_ENCODE_WITHOUT
_CHECKING_CONSTRAINT
Instructs the encoder to disable the extra error check for type values constrained by a component relation constraint. By default, the encoder returns an error if a value is missing from the information object set referred to by the constraint, even if the object set is extensible.
RELAY_OPEN_TYPES_IN_HEX Instructs the XER encoder to encode open type values into their hexadecimal equivalents if they cannot be represented as valid XML. This ensures that the binary encoding (BER, PER, etc.) can be re-encoded into XER and relayed if it contains undecoded BER or PER open type values. When this flag is not set, the encoder does not validate the contents of pre-encoded open types and always puts them in the resulting encoding as is, assuming it is XML. When this flag is set, the encoder checks for well-formed contents and puts them into binary XML. Contents that are not well-formed are put in hexadecimal form. Using this flag slows the encoding process.
The hexadecimal content cannot be used
  • In CXER mode.
  • In combination with automatic decoding; the AUTOMATIC_ENCDEC flag is ignored by the decoder when a hexadecimal encoded format is found.
  • In combination with the ASN1.DeferDecoding directive.
STRICT_CONSTRAINT_CHECKING
  • Enables stricter constraint checking for table and component relation constraints when there is an extensible object set. When this flag is set, the constraints are checked as if the object set is not extensible. NOTE: Regardless of the actual value of the flag, the encoder checks table and component relation constraints as if the flag is set, unless the OSS_AUTO_ENCODE_WITHOUT_CHECKING_CONSTRAINT flag is set.
  • Enables stricter constraint checking in the SOED/LED encoder to ensure that an input value falls within all bounds of an extensible constraint.
  • When this flag is passed to the encoder or the constraint checker, the extension markers ("...") for enumerations, value ranges, and size constraints are ignored during constraint checking. In other words, only the enumeration root or the additional enumeration (extension root and extension additions of constraints) is used to check the value's validity. For example, given the syntax below:
    A ::= INTEGER (1..2, ...)
    B ::= SEQUENCE (SIZE(1..2, ...)) OF INTEGER
    C ::= INTEGER (1..2, ..., 3..4)
    D ::= SEQUENCE (SIZE(1..2, ..., 3..4)) OF INTEGER
    E ::= ENUMERATED {zero(0), one(1), ..., three(3)}
    constraint checking with the flag set results in the following:
    A ::= INTEGER (1..2, ...)
    B ::= SEQUENCE (SIZE(1..2, ...)) OF INTEGER
    C ::= INTEGER (1..2, ..., 3..4)
    D ::= SEQUENCE (SIZE(1..2, ..., 3..4)) OF INTEGER
    E ::= ENUMERATED {zero(0), one(1), ..., three(3)}
    
    v0 A ::= 1           -- valid (extension root)
    v1 A ::= 3           -- invalid (unknown extension)
    v2 B ::= { 1, 2, 3 } -- invalid (unknown SIZE extension)
    v3 C ::= 3           -- valid (extension addition)
    v4 D ::= { 1, 2, 3 } -- valid (SIZE extension addition)
    -- values of the extensible enumerated type E
    0 - valid (root enumeration)
    1 - valid (root enumeration)
    2 - invalid (unknown enumeration)
    3 - valid (additional enumeration)
    4 - invalid (unknown enumeration)
    Without the flag, all the values above are considered valid.
STRICT_PER_ENCODING_OF
_DEFAULT_VALUES
Instructs the PER encoder not to encode components defined with the DEFAULT value when its value is the default. NOTE: To enable support for this runtime flag in the TOED, compile the TOED generated code file with the OSS_STRICT_PER_ENCODING_OF_DEFAULT_VALUES macro.
When successful, the function returns 0; otherwise, it returns a non-zero error code. When "full-exception" mode is in effect, errors are signaled with C++ exceptions, so the function never returns anything but 0.
unsigned long getEncodingFlags() const;
This method gets the current encoding mode used by the OssControl object.
int setDecodingFlags(unsigned long flags);
This method sets the decoding mode used by the OssControl object. The following flags can be used:
Flag Description
AUTOMATIC_ENCDEC Specifies automatic decoding of open types with their containing structures. This flag eliminates repeated calls to the encoder/decoder when processing structures with nested open types. Automatic decoding of open types is possible only when the ASN.1 specification contains enough information for the decoder to determine the type contained in the open type, for example, using the component relation constraints that define the component. If there is not enough information, the open type is left in the encoded form by the decoder. By default, the encoder/decoder does not handle open types automatically.
DEBUG_ERRORS Prints a diagnostic message when an error is encountered, before attempting to continue with the current decode operation.
DEBUGPDU Prints trace data as each PDU is decoded, to use for debugging or diagnostic purposes. Also, when an error is encountered during a decode operation, a diagnostic message is printed and an attempt is made to continue decoding. That is, when the DEBUGPDU flag is set, DEBUG_ERRORS is implied.
DONT_DO_ENCODED Instructs the decoder not to copy/compare encoded open type values. This flag affects only the ASN1Handle::copy and ASN1Handle::equals methods. It does not affect the behavior of the decoder or the OssOpen class.
DONT_DO_DECODED Instructs the decoder not to copy/compare decoded open type values. This flag affects only the ASN1Handle::copy and ASN1Handle::equals methods. It does not affect the behavior of the decoder or the OssOpen class.
DONT_FREE_ENCODED Instructs the decoder to keep (not free) the encoded form of open types when automatically decoding open types.
IGNORE_DEFER_DECODING Instructs the encoder/decoder to encode/decode an open type generated with the ASN1.DeferDecoding directive along with its containing type. Thus, open types created with the ASN1.DeferDecoding directive can be automatically encoded/decoded when this flag is set and AUTOMATIC_ENCDEC is also specified. This flag is not currently supported by the TOED.
NOCONSTRAIN Instructs the decoder to not perform strict constraint checking at runtime for improved CPU performance during decoding. We recommend that you do not set this flag during development because strict constraint checking can help you detect coding errors.
NOTRAPPING Disables signal trapping by default. Also, see OSS_TRAPPING.
OSS_SKIP_UNKNOWN_CONTENT Instructs the E-XER decoder to silently discard any unknown elements and attributes in the input (decoded) XML message. This flag takes precedence over the -relaySafe compiler command line option, so unknown extensions are not saved when the flag is set.
OSS_TRAPPING Enables signal trapping. With signal trapping on, performance suffers somewhat. More importantly, signal trapping is not always thread-safe, depending on the operating system in use. We recommend that you do not enable trapping for multi-threaded applications. In other cases, you can specify this flag to help find coding errors since, with signal trapping enabled, the OSS runtime will return an error code and message, rather than just crashing. The old NOTRAPPING flag is supported for the sake of compatibility, but OSS_TRAPPING takes precedence. That is, if both NOTRAPPING and OSS_TRAPPING are specified then trapping is enabled; if neither flag is specified then trapping is disabled. NOTE: Before release 4.1, the OSS runtime trapped signals by default.
OSS_RELAXED
(RELAXBER, RELAXPER)
Instructs the decoder to not report an error when the input encoding slightly deviates from the ITU-T standards. A list of acceptable deviations follows, grouped by encoding rules.

BER
When BER is in use, the flag relaxes the rules for INTEGER decoding, allowing some invalid encodings to pass without an error check.

Example
I ::= INTEGER (0..MAX)
Using the syntax above, the following encoding is passed to the BER decoder:
0x02, 0x03, 0x80, 0x00, 0x7b
Normally, the decoder issues an error message that says a negative unsigned integer was encountered, which is in strict accordance with the ITU-T Standards. When the OSS_RELAXED flag is set, the decoder silently decodes the encoding as if it were
0x02, 0x04, 0x00, 0x80, 0x00, 0x7b
Also, if the first 9 bits of the encoding are all 1's or all 0's, as follows:
0x02, 0x03, 0x00, 0x00, 0x7b
the decoder normally complains that the integer value encoding is unnecessary long, which is also in strict accordance with the Standards. When the OSS_RELAXED flag is specified, the decoder silently decodes such encodings.

The OSS_RELAXED flag can also disable error checks for
  • BIT STRING encodings that omit the leading octet, which reports the number of non-significant trailing bits in the encoding.
  • BIT STRING encodings that are fragmented, with each fragment containing empty octets.
  • A HUGE integer encoding that contains all zeros in the first 9 bits.
  • A needlessly long tag encoding. For example, an encoding that violates X.690 Clause 8.1.2.2, "For tags with a number ranging from zero to 30 (inclusive), the identifier octets shall comprise a single octet..."

PER
When PER is in use, the flag relaxes the rules related to the length determinant, as specified in clause 11.9 of X.691.

Example
Foo1 ::= VisibleString
The following valid PER ALIGNED encoding could be generated from the syntax above:
04 6E6E6E6E
The first octet, 04, defines a contents length, which is four octets long in this case. However, some applications could incorrectly encode the length field so that the length value can still be retrieved, but the format of the length field is non-standard:
8004 6E6E6E6E
Normally, the PER decoder issues an error message when receiving such an encoding, because the length determinant is encoded with too many octets. According to the ASN.1 standard, a two-octet length should be used only when the length is greater than 127. To work around such problematic encodings, use the OSS_RELAXED flag to instruct the decoder to retrieve the correct value of the length field, while ignoring its incorrect format.

You can also use the OSS_RELAXED flag to instruct the decoder to accept an encoded length that is in the wrong format (i.e., it occupies more bytes than necessary) for extension additions.

The OSS_RELAXED flag also can disable error checks for
  • INTEGER encodings that contain unnecessary zero octets.
  • REAL values with the mantissa or exponent encoded in a format longer than it should be.

E-XER
When E-XER is in use, the flag instructs the E-XER decoder to silently accept input XML documents in UTF-8 encoding, even when the encoding specified by the XML declaration differs from "UTF 8" and "US-ASCII".

Example
<?xml version="1.0" encoding="ISO-8859-1"?><A/>

Any Encoding Rules
When any set of encoding rules is used, the flag instructs the decoder to
  • Not report an error.
  • Decode the NONE and MINUS-ZERO special REAL values as regular zero values on platforms that do not support them.
NOTE: RELAXBER and RELAXPER are just different names for the OSS_RELAXED flag. They are still supported for compatibility reasons, but we encourage you to use OSS_RELAXED instead, since RELAXBER and RELAXPER actually affect all encoding rules, not just the one in their names.
STRICT_ENCODING_DECODING_RULES Instructs the encoder and decoder to strictly check for conformance to encoding rules. When this flag is set, the encoder/decoder performs these additional checks:
  • No zero-length extensions.
  • No extension addition bit-map fields with a zero-length or with all bits set to zero.
  • No PER encodings with incorrect fragmentation; refer to Clause 11.9.3.8.1 of X.691 for details.
  • No zero-length BIT STRING BER encodings are allowed in the Space-Optimized (SOED) decoder; this is the default behavior for the Time-Optimized (TOED) and Lean (LED) decoders.
  • No non-zero padding bits are allowed in PER Aligned encodings for the SOED and LED decoders.
  • No additional unknown extensions are permitted after receiving any root components that follow the extension insertion point of a SEQUENCE type in the Space-Optimized and Lean BER decoders. In the Time-Optimized (TOED) BER decoder, receipt of such an out-of-place extension will cause a length inconsistency error.
  • Neither extension bit '1' followed by an extension root value nor extension bit '0' followed by an extension value is allowed in the Space-Optimized (SOED) decoder. The Time-Optimized (TOED) and Lean (LED) decoders always silently accept such non-standard encodings.
  • No inadmissible tag of an extensible CHOICE field is allowed; refer to Clause 29.7 of X.680 for details.
NOTE: The STRICT_ENCODING_DECODING_RULES flag overrides the OSS_RELAXED (RELAXBER, RELAXPER) flag.
When successful, the function returns 0; otherwise, it returns a non-zero error code. When "full-exception" mode is in effect, errors are signaled with C++ exceptions, so the function never returns anything but 0.
unsigned long getDecodingFlags() const;
This method gets the current decoding mode used by the OssControl object.
const char *getErrorMsg() const;
This method returns a pointer to the error message that describes the last error that occurred during the previous encoding or decoding operation with the OssControl object. If you need a text description of the error, then call this method if the encode() or decode() method returned a non-zero result.
NOTE: If you use the TOED (Time-Optimized Encoder/Decoder) library prior to version 5.0, then compile the generated code with the -DOSSDEBUG=1 or -DOSSDEBUG=2 (or greater) flag, so you can use the getErrorMsg() method. See OSSDEBUG for more information.
int printHex(const char *buffer, unsigned long length);
This method prints a hexadecimal dump of length bytes of memory pointed to by the buffer parameter. Currently the method always returns 0 as the error code.
int setOutputFile(const char *filename);
This method allows the user to redirect the diagnostic output that is printed by the encoding/decoding functions when the DEBUG_ERRORS or DEBUGPDU option is in effect. The output of the ASN1Handle::print(), ASN1Handle::printXML(), and ASN1Handle::printJSON() functions can also be redirected using this method. When the call is successful, the output of each API function that uses "this" OssControl object is redirected to the specified file. This method is available only when the underlying platform has a file system concept, which some embedded systems do not have. The method returns 0 when the operation is successful and a non-zero error code otherwise. When "full-exception" mode is in effect, errors are signaled with C++ exceptions, so the method never returns anything but 0.
int resetOutputFile();
This method is used to switch off redirection of the output. The output will go to the standard output hereafter. This method is available only if the underlying platform has a file system concept, which some embedded systems do not have. The function returns 0 when the operation is successful and a non-zero error code otherwise. When "full-exception" mode is in effect, errors are signaled with C++ exceptions, so the method never returns anything but 0.
virtual int userPrint(FILE *stream, const char *fmt, va_list ap);
This is a virtual function that is called by each output function. It has an interface analogous to the standard C function vfprintf(). You can derive your own classes from OssControl, overriding this function, as described in the following section. This way you can redirect the output to an arbitrary function, not just to another file. The output functions pass the file set by the setOutputFile() function as the stream argument of the function. The overriding function can safely ignore it or not. See Redirecting the Output for more information.
void print(const char *text);
This method prints a C null-terminated string using the current output function of the OssControl object. Usually this method simply calls printf, if you have not redirected the output. However, this could be different with some embedded systems that have no concept of standard output. This method can be used for debugging purposes.
int setXmlStylesheet(const char *xslFilePath);
This method gives you better control over the browser format of the XML output produced by the encode() method. A prior call to this method instructs the encoder to produce a reference to an XSL stylesheet in the ensuing XER encoding. The xslFilePath variable is the full path name of the XSL stylesheet that you want to be associated with the next PDU for encoding. The method returns 0 when the operation is successful and a non-zero error code otherwise. When "full-exception" mode is in effect, errors are signaled with C++ exceptions, so the method never returns anything but 0.
int setXmlDTD(const char *pduName, const char *externalID, short dtdKind);
This method allows you to specify the general data schema (DTD: Data Type Definition) that corresponds to an XER encoding. Among other things, this allows you to view and edit the output produced by the encode() method with a non-ASN.1-specific XML tool. Call this function before calling the encoder so the next XER encoding produced includes the desired DTD reference. pduName is the name of the PDU in the next XER encoding to which a DTD file will be associated, externalID is the pathname/reference to the DTD file you wish to use, and dtdKind is one of the following enumerators:
  • OSS_XDTD_SYSTEM is used for system DTD files.
  • OSS_XDTD_PUBLIC is used for public DTD files.
  • OSS_XDTD_NONE disables generation of the DTD file reference in subsequent XER encodings produced by the encode() method; the other arguments do not matter in this case.
The method returns 0 when the operation is successful and a non-zero error code otherwise. When "full-exception" mode is in effect, errors are signaled with C++ exceptions, so the method never returns anything but 0.
void printXML(const char *buffer, unsigned long length, int pretty_print);
This method allows you to print XER encodings in a well-formatted manner. buffer is a pointer to the beginning of the input XER encoding and length is the length in bytes of the XER encoding. pretty_print is an int variable that determines whether the input XER encoding should be formatted for human readability: a value of 1 indicates that such formatting will be done, 0 is otherwise. This function can be used for debugging purposes.
int getNamespacePrefix(const char *ns, const char **prefix);
This method allows you to query the namespace prefix that the encoder will use for a particular XML namespace in an E-XER encoding. The ns parameter contains the URI of the XML namespace. The namespace should be present in the input ASN.1 specification (e.g., in a NAMESPACE XER encoding instruction). When the method succeeds, the prefix parameter is assigned a pointer to a null-terminated prefix string. When the namespace is the default (unprefixed) namespace, *prefix is set to NULL. The method returns 0 when the operation is successful and a non-zero error code otherwise. When "full-exception" mode is in effect, errors are signaled with C++ exceptions, so the method never returns anything but 0.
int setNamespacePrefix(const char *ns, const char *prefix);
This method allows you to set the namespace prefix that the encoder will use for a particular XML namespace in an E-XER encoding, overriding the prefix specified in the ASN.1 specification or assigned by the ASN.1 compiler. The ns parameter contains the URI of the XML namespace. The namespace is present in the input ASN.1 specification (e.g., in a NAMESPACE XER encoding instruction). The prefix parameter points to a null-terminated C string containing the desired prefix. If you want the namespace to be the default (unprefixed) namespace, set prefix to NULL. The method returns 0 when the operation is successful and a non-zero error code otherwise. When "full-exception" mode is in effect, errors are signaled with C++ exceptions, so the method never returns anything but 0.
int setXMLEncodingRules(OssEncodingRules rules);
This method allows you to specify the XML encoding rules that the XML2Binary() and binary2XML() methods of the PDU class use when converting from XML to binary and vice versa. You can specify the Basic XML Encoding Rules (OSS_XER), XML Canonical Encoding Rules (OSS_CXER), or XML Extended Encoding Rules (OSS_EXER). If you do not use this method prior to calling either of the methods given above, the default XML rule will be used to do the conversion. When the input value of rules is OSS_XER, OSS_EXER, or OSS_CXER, then a value of zero is returned. If non-XML encoding rules are specified in rules, the method returns BAD_ENCRULES. If the rules specified are not yet supported by the current runtime (TOED), the method returns UNAVAIL_ENCRULES. When "full-exception" mode is in effect, errors are signaled with C++ exceptions.

The encoding rules option specified at ASN.1-compile time determines the default XML encoding rules:
  • When -xer is specified, OSS_XER is used.
  • When -exer is specified, OSS_EXER is used.
  • When -cxer is specified, OSS_CXER is used.
  • If more than one option is specified, the precedence is: (1) OSS_EXER, (2) OSS_XER, and (3) OSS_CXER.
  • The default XML encoding rules can be changed by calling the setXMLEncodingRules() method.
    OssEncodingRules getXMLEncodingRules() const;
    This method returns the XML encoding rules (OSS_XER, OSS_EXER, or OSS_CXER), currently used by the XML2Binary() and binary2XML() methods of the PDU class to convert from XML to binary and vice versa. This could be the default rules or those set by the setXMLEncodingRules() method.
    int setDebugFlags(unsigned long flags);
    This method sets the amount of debug information generated by the OSS runtime while encoding and decoding a PDU to be customized. The flags parameter is a logical OR ('|') with any of the following flags:
    PRINT_DECODER_INPUT, PRINT_DECODER_OUTPUT, PRINT_DECODING_DETAILS,
    PRINT_ENCODER_INPUT, PRINT_ENCODER_OUTPUT, PRINT_ENCODING_DETAILS,
    PRINT_ERROR_MESSAGES, PRINT_HEX_WITH_ASCII

    or with one of the combined "debugging level" literals:

    OSS_DEBUG_LEVEL_0, OSS_DEBUG_LEVEL_1, OSS_DEBUG_LEVEL_2, OSS_DEBUG_LEVEL_3, OSS_DEBUG_LEVEL_4

    The flags and the debugging levels (macros) are described in the following tables.

    Flag Description
    PRINT_DECODER_INPUT Print the decoder input on entry to the decoder. If the input is a binary encoding (e.g., BER or PER), printHex() is called; otherwise printXML() is called to print the input as formatted XML. This flag is not available for input from a file or socket.

    A descriptive comment, "The input to the decoder:", is printed before the decoder input.

    If the decoder input is in hexadecimal and the PRINT_HEX_WITH_ASCII flag is set, a header and footer is produced that wraps the hexadecimal and ASCII output:
    # Offset    Stream of Octets Written in Hexadecimal    Character Format
    # ======    =======================================    ================
    and
    # ======    =======================================    ================
    PRINT_DECODER_OUTPUT Print the decoder output just before the decoder exits. For the TOED, specify -DOSSPRINT and -DOSSDEBUG=x (where x is 1 or more, e.g., -DOSSDEBUG=2) when compiling the generated TOED code.

    A descriptive comment, "The decoder output:", is printed before the decoder output.
    PRINT_DECODING_DETAILS Print verbose trace messages while decoding. This flag is not available for the TOED and LED libraries.

    A descriptive comment, "The decoder trace messages:", is printed before the decoder trace.
    PRINT_ENCODER_INPUT Print the encoder input on entry to the encoder. For the TOED, specify -DOSSPRINT and -DOSSDEBUG=x (where x is 1 or more, e.g., -DOSSDEBUG=2) when compiling the generated TOED code.

    A descriptive comment, "The input to the encoder:", is printed before the encoder input.
    PRINT_ENCODER_OUTPUT Print the encoder output just before the decoder exits. If the output is a binary encoding (e.g., BER or PER), printHex() is called; otherwise printXML() is called to print the output as formatted XML. This flag is not available for output from a file or socket.

    A descriptive comment, "The encoder output:", is printed before the encoder output.

    If the encoder output is in hexadecimal and the PRINT_HEX_WITH_ASCII flag is set, a header and footer is produced that wraps the hexadecimal and ASCII output:
    # Offset    Stream of Octets Written in Hexadecimal    Character Format
    # ======    =======================================    ================
    and
    # ======    =======================================    ================
    PRINT_ENCODING_DETAILS Print verbose trace messages while encoding. This flag is not available for the TOED and LED libraries.

    A descriptive comment, "The encoder trace messages:", is printed before the encoder trace.
    PRINT_ERROR_MESSAGES Causes functions that can print error messages (e.g., encode(), decode()) to print a message when an error occurs. For the TOED, specify -DOSSDEBUG=x (where x is 1 or more, e.g., -DOSSDEBUG=2) when compiling the generated TOED code.

    One of the following descriptive comments is printed before the error message:
    The encoder error message:
    or
    The decoder error message:
    PRINT_HEX_WITH_ASCII Causes printHex() to print an ASCII translation of its input buffer on the right, with '.' substituted for unprintable characters. Following is a sample output:
    # 000000:   4200 7368 6972 7423 DC74 726F 7573 6572    B.shirt#.trouser
    # 000010:   73A5 1073 686F 6573 C648 7469 6502 9073    s..shoes.Htie..s
    # 000020:   6869 7274 4788 7469 6502 8874 6965 6290    hirtG.tie..tieb.
    # 000030:   7368 6972 74C7 9073 6869 7274 6A00         shirt..shirtj.
    This flag affects the printHex() behavior no matter how it is called: explicitly by you or implicitly by the OSS runtime when the PRINT_ENCODER_OUTPUT or PRINT_DECODER_INPUT debugging flag is processed.

    The following macros define diagnostic levels by combining the debug flags above into five commonly used groups.

    Macro Description
    OSS_DEBUG_LEVEL_0 No diagnostics are printed by the encoder/decoder. If -DOSSDEBUG=x (where x is 1 or more, e.g., -DOSSDEBUG=2), is specified for the TOED, or if the SOED library is in use, a diagnostic message is created but not printed. This level is the default.
    OSS_DEBUG_LEVEL_1 Causes functions that can print error messages (e.g., encode(), decode()) to print a message when an error occurs. For the TOED, specify -DOSSDEBUG=x (where x is 1 or more) when compiling the generated TOED code.
    OSS_DEBUG_LEVEL_2 This macro has the same effect as OSS_DEBUG_LEVEL_1, but also prints the encoder input on entry to the encoder and the decoder output just before the decoder exits. For the TOED, specify -DOSSPRINT when compiling the generated TOED code.
    OSS_DEBUG_LEVEL_3 This macro has the same effect as OSS_DEBUG_LEVEL_2, but also prints the encoder output before exiting the encoder and the decoder input on entry to the decoder.
    OSS_DEBUG_LEVEL_4 This macro has the same effect as OSS_DEBUG_LEVEL_3, but also causes the encoder and decoder to print verbose trace messages. This is not available for the TOED or LED libraries. For binary encodings (e.g., BER and PER), an ASCII translation of the encoder output and the decoder input is produced on the right, with '.' substituted for unprintable characters (instead of a HEX dump).
    The setDebugFlags() method returns an integer. When successful, the method returns 0; otherwise, it returns a non-zero error code. When "full-exception" mode is in effect, errors are signaled with C++ exceptions, so the method never returns anything but 0.
    unsigned long getDebugFlags() const;
    This method returns the debugging flags set by the setDebugFlags() method. The possible debugging flags are:
    PRINT_DECODER_INPUT, PRINT_DECODER_OUTPUT, PRINT_DECODING_DETAILS,
    PRINT_ENCODER_INPUT, PRINT_ENCODER_OUTPUT, PRINT_ENCODING_DETAILS,
    PRINT_ERROR_MESSAGES, PRINT_HEX_WITH_ASCII

    or one of the combined 'debugging level' literals:

    OSS_DEBUG_LEVEL_0, OSS_DEBUG_LEVEL_1, OSS_DEBUG_LEVEL_2, OSS_DEBUG_LEVEL_3, OSS_DEBUG_LEVEL_4

    For details about these flags, see the description of the setDebugFlags() method.

    unsigned long getCompatibilityFlags();
    This method returns the current compatibility flags, which were set by a prior call to the setCompatibilityFlags() function.
    With a successful call, the possible return values of the compatibility flags are as follows, otherwise, a value of -1 is returned.
    OSS_V85_TABLE_CONSTRAINT_FOR_EXTENSIBLE_OBJECT_SETS,
    OSS_ALLOW_MISPLACED_EXTENSION_FIELDS,
    OSS_ALLOW_NON_NR3_DER_REAL,
    OSS_ALLOW_NULL_IN_TIME,
    OSS_PACK_WIDE_STRINGS,
    OSS_EXTENDED_RESTRICTED_KMC_STRING_AS_OCTETS,
    OSS_PER_ALLOW_TRAILING_ZEROS,
    OSS_PER_NULLTERM_TIME_8BIT_CHARS
    OSS_USE_TYPE_IDENTIFICATION_ATTRIBUTE_FOR_UNION

    A detailed description of these flags can be found in the setCompatibilityFlags() section below.

    This example uses the method and tests the flag:

    OssControl ctl;
    unsigned long ret_flag = ctl.getCompatibilityFlags();
    
    if (ret_flag < 0) {
        ... error condition ...
    }
    
    if (ret_flag & OSS_PACK_WIDE_STRINGS) {
        ... OSS_PACK_WIDE_STRINGS flag is set ...
    } else {
        ... OSS_PACK_WIDE_STRINGS flag is not set ...
    }
    int setCompatibilityFlags(unsigned long flag);
    This method sets backward compatibility flags that affect the behavior of the encoding and decoding processes. Some of these flags restore slightly incorrect behavior of older versions of the OSS Tools and are needed for backward compatibility. Other flags allow your program to accept some sort of incorrectly encoded messages.

    NOTE: OSS does not guarantee compatibility between different versions of the ASN.1 Tools released more than 10 years apart.

    The parameter is a bitmask of an unsigned long type and can be one of the following flags, or a combination of these flags created with a bitwise OR (i.e., separated by a vertical bar: "|"):

    Flag Description
    OSS_V85_TABLE_CONSTRAINT_FOR
    _EXTENSIBLE_OBJECT_SETS
    Applies only to the SOED/LED runtime. Prior to version 4.3.1, the OSS Constraint Checker mishandled table/component relation constraint violations for extensible object sets. Starting with version 4.3.1, the OSS ASN.1/C++ Compiler and Runtime support X.681 Annex E.2. That is, a constraint violation error is reported if table/component relation constraints are not satisfied for an extensible object set and any of these conditions is true:
    • The value of a UNIQUE field is found in the object set.
    • The STRICT_CONSTRAINT_CHECKING runtime flag is specified.
    • The OSS_AUTO_ENCODE_WITHOUT_CHECKING_CONSTRAINT encoder flag is not specified.
    Using this flag forces the constraint checker to restore the old (pre-4.3.1 version) behavior.
    OSS_ALLOW_MISPLACED_EXTENSION
    _FIELDS
    Applies only to the SOED/LED BER decoder. Using this flag forces the decoder into relaySafe mode to accept an unknown extension field that is illegally located after additional root fields in the input encoding. Otherwise, the encoding is considered invalid and the decoder issues the "D0047E: Tag not recognized" error message.
    OSS_ALLOW_NON_NR3_DER_REAL Applies to the DER, CER and PER encoder. Using this flag directs the encoder to skip NR3 normalization of decimal REAL types, as was done in pre-4.0 versions of the OSS ASN.1/C++ Tools.
    OSS_ALLOW_NULL_IN_TIME Applies to the BER Time-Optimized decoder only. The decoder issues an error if the encoding of a GeneralizedTime type value contains superfluous trailing NULL octets. Specify the OSS_ALLOW_NULL_IN_TIME flag (via setCompatibilityFlags()) to force the decoder to silently ignore such octets in a BER encoding.
    OSS_PACK_WIDE_STRINGS Applies only to the PER Space-Optimized Encoder/Decoder. This means that wide string characters with permitted alphabet constraints are encoded relative to the zero value of the lowest cell in the permitted alphabet, not to the lowest value in the cell.
    In the following example, this flag causes value a to be encoded as 0x0140 instead of 0x0120 in aligned PER, as though the permitted alphabet is
    FROM({0,0,30,0}..{0,0,30,127}).
    A ::= BMPString (FROM({0,0,30,32}..{0,0,30,127}))
    a A ::= {0,0,30,64}
    OSS_EXTENDED_RESTRICTED_KMC
    _STRING_AS_OCTETS
    Applies only to the PER encoder/decoder. Using this flag forces the encoder/decoder to ignore PermittedAlphabet in extensible KMC string types if the actual string length exceeds that of the extension root. In this regard, the flag restores the behavior of pre-4.0 versions of the OSS ASN.1/C++ Tools.
    OSS_INTERVAL_FRACTION_1_999 Applies only to the PER runtime. Using this flag causes the encoding of a DURATION-INTERVAL fractional value to be
    INTEGER (1..999, ..., 1000..MAX)

    instead of

    INTEGER (0..999, ..., 1000..MAX)
    See Corrigendum 4 to clause 32.6.1 of the X.691 standard.
    OSS_NO_DETAIL_MM_ERROR_CODES Applies only to the Space-Optimized Encoder/Decoder (SOED). Prior to version 6.0, OSS methods returned the FATAL_ERROR (18) common error code and the
    x0087S: Undefined memory-management error #N
    message when errors specific to EncodedFile/EncodedSocket objects occurred, such as an error reading from or writing to a file/socket. Starting with version 6.0, more error codes and messages are returned in this case. Using this flag restores the old behavior.
    OSS_PER_ALLOW_TRAILING_ZEROS Applies to the PER Space-Optimized encoder only. Starting with version 4.3, the encoder strips trailing zeros from an encoded BITSTRING with named bits according to Clause 15.2 of X.691. Previously, such bits were encoded. In this regard, the flag restores the behavior of pre-4.3 versions of the OSS ASN.1/C++ Tools.
    OSS_PER_NULLTERM_TIME_8BIT_CHARS Applies only to the PER encoder/decoder. Using this flag forces the encoder/decoder to handle unaligned PER encodings of UTCTime and GeneralizedTime types as though 8 bits per character are used, which makes them identical to an aligned PER encoding. In this regard, the flag restores the behavior of pre-4.0 versions of the OSS ASN.1/C++ Tools.
    OSS_TRUNCATE_0_SECONDS_FROM
    _GENERALIZED_TIME
    Applies only to the Space_Optimized DER and PER encoders. Using this flag causes trailing zeros after the seconds field in GeneralizedTime type encodings to be truncated, e.g., 1998120311235500 is truncated to 19981293112355.
    OSS_TRUNCATE_0_SECONDS_FROM
    _UTC_TIME
    Applies only to the SOED DER and PER encoders. Using this flag causes trailing zeros after the seconds field in UTCTime type encodings to be truncated, e.g., 98120311235500Z is truncated to 981203112355Z.
    OSS_USE_TYPE_IDENTIFICATION
    _ATTRIBUTE_FOR_UNION
    Applies only to the Space_Optimized and Lean E-XER encoders. Using this flag allows the encoder to generate a type identification attribute for a choice type with a USE-UNION encoding instruction, if the type has a final UNTAGGED encoding instruction.
    After a successful return from setCompatibilityFlags(), the encoder/decoder can emulate the specified backward compatibility behavior. The setCompatibilityFlags() method returns an integer. With a successful call, a value of zero is returned; otherwise, a non-zero value is returned.

    This example sets the compatibility flag:

    OssControl ctl;
    ctl.setCompatibilityFlags(OSS_ALLOW_MISPLACED_EXTENSION_FIELDS);
    void setTimeout(long timeout);
    When the EncodedSocket class is in use, this method sets a timeout limit on the select() socket function when waiting for TCP/IP sockets during a read, write, or error. This allows the call to the recv() socket function (when decoding from a TCP/IP socket) or the send() socket function (when encoding to a TCP/IP socket) to be completed without blocking. The timeout is the maximum socket wait time in seconds.
    void setDebugStringTruncate(size_t length);
    This method controls the length of a line written when encode() or decode() traces a string (e.g., OCTET STRING, BIT STRING, etc.), or when the PDU class print() method prints a string. When the passed length equals 0, then strings are not be truncated. By default, a string is truncated when its length exceeds 35 symbols.
    size_t getDebugStringTruncate() const;
    This method returns the maximum number of symbols printed without truncation when encode() or decode() is tracing a string, or when the PDU class print() method is processing a string. When the returned value is 0, the string is not truncated.
    int valid();
    This method returns 1 when the control object is properly initialized and can be used in any ASN.1/C++ function; 0 is returned when it is not initialized. This can occur, for example, if the control information in the compiler-generated file is corrupt or if the license does not permit the OSS ASN.1/C++ Tools to run on the user's computer. Any attempt to use an uninitialized control object will result in the OSS_CONTROL_NOT_INITIALIZED error. This method is intended primarily for internal use, but the user can also use it, if needed.
    void printJSON(const char *buffer, unsigned long length, int pretty_print);
    As of version 6.3, use this method to print well-formatted JSON encodings. buffer is a pointer to the beginning of the input JSON encoding and length is the length of the JSON encoding in bytes. Set the pretty_print integer variable to 1 to format the input JSON encoding as human readable, or to 0 otherwise. This function can be used for debugging purposes.
    int setJsonFlags(unsigned long flags);
    This method, added in version 6.3, sets JSON-specific flags that affect the behavior of the encoding process. The parameter is a bitmask of an unsigned long type and can be one of the following flags, or a combination of these flags created with a bitwise OR (i.e., separated by a vertical bar: "|"):
    Flag Description
    JSON_ENC_ABSENT_COMPONENTS Instructs the JSON encoder to include the "null" token for absent optional components whose types are not NULL or open types. When the flag is not specified, absent optional components of SET and SEQUENCE types are not encoded.
    JSON_ENC_DEFAULT_VALUES Instructs the JSON encoder to encode absent SET or SEQUENCE type components defined with the DEFAULT syntax either as their default value or as "null", depending on the JSON_ENC_ABSENT_COMPONENTS flag settings. When the JSON_ENC_DEFAULT_VALUES flag is not specified, absent components are never encoded.
    JSON_USE_UNICODE_ESCAPE_SEQUENCE Instructs the encoder to encode each non-ASCII character in restricted character string type values using the \uxxxx unicode escape sequence. When the flag is not specified, non-ASCII characters are UTF-8 encoded. For example, if the flag is not specified, the COPYRIGHT SIGN character is UTF-8 encoded into two octets, 0xC2 and 0xA9. If the flag is set, it is encoded using the unicode escape sequence \u00A9.
    JSON_COMPACT_ENCODING Instructs the JSON encoder to create a compact JSON encoding with no whitespace or new lines. When the flag is not specified, the encoder inserts whitespace and newlines to improve readability.
    unsigned long getJsonFlags() const;
    This method, added in version 6.3, returns the current JSON-specific flags that were set by a prior call to the setJsonFlags() function.

    With a successful call, the possible return values of the JSON-specific flags are as follows, otherwise, a value of -1 is returned.
    JSON_ENC_ABSENT_COMPONENTS, 
    JSON_ENC_DEFAULT_VALUES,
    JSON_USE_UNICODE_ESCAPE_SEQUENCE,
    JSON_COMPACT_ENCODING
    A detailed description of these flags can be found in the setJsonFlags() section.

    The following example uses this method and tests the flag:
    OssControl ctl;
    unsigned long ret_flag = ctl.getJsonFlags();
    
    if (ret_flag == (unsigned long)-1) {
        …error condition …
    }
    
    if (ret_flag & JSON_COMPACT_ENCODING) {
        … JSON_COMPACT_ENCODING flag is set … 
    } else {
    	… JSON_COMPACT_ENCODING flag is not set …
    }
    int setJsonIndentSize(int indent_size);
    Starting with version 6.3, use this method to set the indentation size used by the JSON encoder. A negative indentation size sets the compact mode. By default, the encoder indents two spaces. With a successful call, a value of zero is returned; otherwise, a non-zero value is returned.
    int getJsonIndentSize() const;
    This method, added in version 6.3, returns the current indentation size used by the JSON encoder. By default, the encoder indents 2 spaces. The indentation size can be changed using the setJsonIndentSize() function. A negative value is returned if an error occurs.
    void setCompressor(OssCompressor *comp);
    Use this method to compress or encrypt encoded data before returning from the encoder and to decompress or decrypt decoded data before decoding begins. The comp parameter is a pointer to the OssCompressor object to be used for compression and decompression. Refer to Compressor Classes for more details.
    OssCompressor* getCompressor();
    This method returns a pointer to the OssCompressor object that was set using the set_Compressor() method.

    <projectname>_Control

    The class derived from OssControl and generated by the compiler is referred to as <projectname>_Control. This class represents control objects that are tailored to use a particular specification. Instantiate this class directly. <projectname> represents the ASN.1 specification file name, not the module name. In other words, for myfile.asn, the myfile_Control class is generated. By default, <projectname> coincides with the last ASN.1 filename specified on the command line. The name of the generated class and the generating filename can be altered using the ASN.1/C++ Compiler options.

    Methods

    <projectname>_Control();
    This constructor creates a control object that is tailored to use this particular ASN.1 specification (control table). The encoding/decoding flags are set to the default.

    NOTE: This constructor initializes the OSS Runtime but there are cases when it cannot be done properly, for example, the trial license has expired, or you use the OSS Nokalva DLLs but your PATH variable does not include their location, etc. If the constructor fails, using an improperly initialized <projectname>_Control object could cause a memory violation error. To avoid errors, use C++ exceptions to trap initialization errors. Alternatively, check the result of this constructor as it is described in Legacy "No-Exception" Error Handling Mode, as shown in the following sample code:
       asn1_clean_error();
       bcas_Control ctl;
       if (asn1_get_last_error()) {
            printf("OssControl object was not created. "
       "Error code is: %d\n", asn1_get_last_error());
            return 1;
       }
    See ASN.1/C++ Encoder/Decoder Return Codes for information about error codes returned by asn1_get_last_error().
    <projectname>_Control(const _Control &);
    This constructor creates a control object that is tailored to use this particular ASN.1 specification. It retains the same encoding/decoding flags that the control object parameter has. Note that control object classes have no assignment operators.

    Redirecting the Output

    Many functions that take an OssControl object as an argument output some text information. For example, the print() method of a PDU object prints the textual representation of the object in the ASN.1 value notation format, the encoding/decoding function can print diagnostic output, and the OssControl class printHex() utility method prints a hexadecimal dump of a memory block.

    By default, all these functions output information to standard output. (If the platform does not support the standard output concept, as with some embedded systems, it outputs information to some other designated place.) However, there could be situations when this is undesirable. The ASN.1/C++ API provides the necessary means to redirect this output to another destination.

    To simply redirect this output to a file, use the setOutputFile() function. However, this may not always be sufficient; e.g., the desired destination is not a file but a screen window, or special formatting or filtering should be applied to the output. The ASN.1/C++ API gives you the ability to redirect the output to an arbitrary function.

    To achieve this, derive a new class from the control class generated by the ASN.1/C++ compiler. Provide a new implementation of the virtual userPrint() function in the new class, which will be called when the runtime is about to print a string. This function allows you to determine the format of what is printed.


    EncodedData

    The encoder/decoder can encode/decode data to/from a memory block, a file, or a socket. These encoded data sources are represented by the EncodedBuffer, EncodedFile, or EncodedSocket classes respectively. These three classes are derived from the common ancestor, the EncodedData class. EncodedData is an abstract class. Thus, the methods described in this section should be applied to instances of the EncodedBuffer, EncodedFile, or EncodedSocket classes.

    Relation of EncodedData class and its sub-classes

    Relationship between the EncodedData class and its sub-classes

    Definition

    class EncodedData {
    public:
          void enableSkipPadBytes(unsigned char pad_byte);
          void disableSkipPadBytes();
    };

    Methods

    void enableSkipPadBytes(unsigned char pad_byte);
    This method enables the decoder to skip the "padding" bytes in an encoded message stored in the instance of an EncodedBuffer, EncodedFile, or EncodedSocket class. The pad_byte parameter specifies the value of the byte to be skipped. This mode is useful for decoding concatenated PDUs that could be separated by padding bytes. Whenever the decode() method is called, it skips the specified padding bytes and decodes the message starting from the first non-padding byte.
    void disableSkipPadBytes();
    This method disables the mode set by the enableSkipPadBytes() method described above.

    EncodedBuffer

    The EncodedBuffer class is a subclass of EncodedData. The encoded data is stored in memory. An EncodedBuffer object can be in one of these three states:

    • Uninitialized: in this state, no memory buffer is assigned to the object. If an uninitialized object is used as an output parameter for the encode() function, the runtime automatically allocates a buffer large enough to hold the resulting encoding and assigns the allocated buffer to the object.
    • Automatically allocated: in this state, the memory buffer is assigned by the runtime in a previous encode() or clone() function call. Automatically allocated buffers are owned by the runtime and are destroyed automatically by the EncodedBuffer destructor. The user must not free them explicitly.
    • Preallocated: in this state, the memory buffer is allocated by the user. Preallocated buffers are owned by the user who is also responsible for freeing them when appropriate. The runtime never frees them.

    Similar to the file pointer concept, EncodedBuffer has a current buffer pointer concept: it always points to the next available location for encoding or decoding data. A call to the encoding/decoding functions advances the current pointer, so that a subsequent encoding or decoding reads or writes data in the adjacent memory location. This allows the user to easily encode several PDUs into one preallocated buffer, as well as to decode several PDUs from one buffer. Changing the buffer mode from encoding to decoding, or vice versa, resets the current pointer to the beginning of the buffer.

    EncodedBuffer has two different concepts of length: buffer size and information size. Buffer size is the total number of bytes that was allocated to the buffer in memory. Information size is the number of bytes that is used for storing the encoded information. The sizes can differ since some part of the buffer could be currently unoccupied.

    EncodedBuffer Encoding Behavior

    The EncodedBuffer class supports encoding of several concatenated PDUs into one preallocated buffer. This feature is available only when the encoder is set to front-align mode. If the encoder is in back-align or in default mode, an attempt to encode another PDU into an occupied buffer will cause an error. See OssControl Class Methods for more information on the encoder/decoder alignment modes.

    If the EncodedBuffer that was passed as a parameter is initialized with either an automatically allocated or a preallocated buffer, this buffer is used when encoding. If the EncodedBuffer is in input mode (i.e., the last coding operation performed on it was reading from the buffer), then the current pointer is reset to the beginning of the buffer, the information size is reset to 0, and encoding starts from the beginning of the buffer (or from its end, depending on the encoder data alignment mode). Otherwise, encoding starts at the current pointer so that the data placed in the buffer by the previous decode operations are preserved. If there is no room to hold the encoded data in the buffer, an error is returned. If the EncodedBuffer is uninitialized, a buffer that can hold the encoded data is automatically allocated. The encoded data will be placed at its beginning. If the encoding process is successful, the current pointer is moved to the point immediately following the encoded data and the information size is incremented by the encoded data length.

    EncodedBuffer Decoding Behavior

    The EncodedBuffer class supports decoding of several concatenated PDUs from one preallocated buffer. If the EncodedBuffer that was passed as a parameter is uninitialized, an error occurs. If the EncodedBuffer is in output mode (i.e., the last coding operation performed on it was writing to the buffer), the current pointer is reset to the beginning of the buffer, so that decoding starts from the beginning. Otherwise, decoding starts at the current pointer. If the current pointer offset is larger than the information size (i.e., there is no more information in the buffer to decode), an error occurs. If the decoding process is successful, the current pointer is advanced accordingly.

    Decoding into a Preallocated Buffer

    ASN.1/C++ supports decoding into a preallocated memory buffer. In this case, the buffer of the EncodedBuffer object is used as output storage for the decoded value. Also, the decoding operation can be significantly faster than the usual decoding to dynamic memory. See PDU Class Methods for a detailed description. When decoding into a preallocated memory buffer, two EncodedBuffer objects are involved in the operation. The EncodedBuffer object containing the encoding is set to input mode as usual, so it acts as described in EncodedBuffer Decoding Behavior. The EncodedBuffer object used as storage for the decoded object is set to output mode, so it acts as described in EncodedBuffer Encoding Behavior.

    Definition

    class EncodedBuffer: public EncodedData {
    public:
      EncodedBuffer();
      EncodedBuffer(unsigned long length, char *value);
      EncodedBuffer(OssString & any);
      ~EncodedBuffer();
      void set_buffer(unsigned long length, char *value);
      void grab_buffer(unsigned long length, char *value);
      void clone(EncodedBuffer & orig);
      char *get_data() const;
      char *release_data();
      unsigned long get_length() const;
      unsigned long get_data_size() const;
      unsigned long get_data_offset() const;
      unsigned long get_position() const;
      int set_position(unsigned long pos);
      int is_preallocated() const;
      int print_hex(OssControl & ctl) const;
      void print_xml(OssControl & ctl, int pretty_print) const;
      void reset();
      void print_json(OssControl & ctl, int pretty_print) const;
    };

    Methods

    EncodedBuffer();
    This method is the default constructor. An uninitialized EncodedBuffer object is created.
    void set_buffer(unsigned long length, char *value);
    This method assigns a preallocated buffer to the EncodedBuffer object. The address of the buffer is specified by the value parameter; its length is specified by the length parameter. The buffer is owned by the caller; therefore, the destructor will not deallocate it. The user is responsible for freeing it. current_pointer points to the beginning of the buffer. Both the buffer size and the information size of the EncodedBuffer are set from the length parameter. The object is set to decode mode, so that if the first operation after the call is encode(), the information size is reset to 0. If the EncodedBuffer object had an automatically allocated buffer prior to the call, it is deallocated. The call:
    set_buffer(0, NULL);
    deallocates the present buffer and resets the object to the uninitialized state.
    EncodedBuffer(unsigned long length, char *value);
    The constructor creates an EncodedBuffer object with a preallocated buffer. The parameters are the same as in the previous method.
    void grab_buffer(unsigned long length, char *value);
    This method is the same as set_buffer() except that it transfers ownership of the memory buffer to the EncodedBuffer object. The buffer is allocated by the asn1Malloc() function; see Memory Allocation. After the call, the buffer is considered automatically allocated and will be destroyed automatically by the EncodedBuffer destructor. Do not explicitly deallocate this buffer.
    EncodedBuffer(OssString &any);
    This constructor creates an EncodedBuffer object and assigns a preallocated buffer to it that is taken from an instance of the OssString type. In this case, it is assumed that this is a representation of the ASN.1 ANY or OCTET STRING type, i.e., if you need to decode an ANY type value, create an EncodedBuffer object using this constructor. The EncodedBuffer object does not make a private copy of the information, so do not use the buffer when the original OssString object no longer exists. If needed, use the clone() function.
    Note: The C++ representation of the ANY type is always the OssString class.
    void clone(EncodedBuffer &orig);
    This function copies the contents of the parameter object buffer to a newly allocated block of memory and assigns the allocated block to "this" EncodedBuffer object. The resulting buffer is considered to be automatically allocated and, as such, will be owned by the runtime. The destructor will deallocate it. The size of the copied data is determined by the information size of the original buffer, i.e., only the meaningful part of the buffer is copied. If the EncodedBuffer object had an automatically allocated buffer prior to the call, it is deallocated.
    unsigned long get_length() const;
    This method returns the total length of the buffer.
    char *get_data() const;
    This method returns the address of the data in the buffer. Note that this address can differ from the initial address of the buffer, which is defined as the address of your preallocated output buffer. For example, when called after encode(), this method returns the address of the encoded data. If the encoder right-justifies the data within your preallocated output buffer, then the address of the data will almost always differ from the address of the buffer.
    char *release_data();
    This method returns the address of the buffer. This is an ownership-transferring function. The EncodedBuffer object is reset to the uninitialized state. The user now owns the buffer. If it was automatically allocated, the user is now responsible for deallocating it by means of the asn1Free() function (see Memory Allocation). Note that this function returns the address of the buffer, not the address of the meaningful data inside it. These addresses can differ because the data can be aligned differently relative to the beginning of the buffer.
    unsigned long get_data_size() const;
    This method returns the information size of the buffer, that is, the size of the meaningful data stored in the buffer.
    unsigned long get_data_offset() const;
    This function returns the offset of the meaningful data in the buffer. Note that the encoder can align the encoded data differently relative to the beginning of the buffer. In other words, use this method to get the beginning position of data in EncodedBuffer when BACK_ALIGN or DEFAULT_ALIGN is specified.
    unsigned long get_position() const;
    This function returns the offset of the current pointer from the beginning of the buffer.
    int set_position(unsigned long offset);
    This function moves the current pointer to a new position that is "offset" bytes from the beginning of the buffer. An attempt to move the pointer outside the buffer is an error. If an error occurs, the function returns a non-zero error code; with success, it returns 0.
    int is_preallocated() const;
    This method returns 1 when the buffer is user-owned and will not be destroyed by the EncodedBuffer destructor. It returns 0 when the buffer is object-owned and will be destroyed automatically.
    int print_hex(OssControl & ctl) const;
    This is an auxiliary function that prints a hexadecimal dump of data contained in the EncodedBuffer object. Currently, the function always returns 0 as the error code.
    void print_xml(OssControl & ctl, int pretty_print) const;
    This method allows you to print XER encodings contained in the EncodedBuffer object in a well-formatted manner. The pretty_print parameter determines whether the input XER encoding should be formatted for human readability: a value of 1 indicates that such formatting should be done, 0 otherwise. This method can be used for debugging purposes.
    void reset();
    This method resets the EncodedBuffer object. After the call, the buffer is considered empty and the current position is reset to 0. Use this function to reuse the memory buffer as output for several encoding/decoding operations.
    NOTE: The copy constructor and the assignment operator for the EncodedFile, EncodedBuffer, and EncodedSocket classes are private. These types of objects can only be passed by referencing the other functions.
    void print_json(OssControl & ctl, int pretty_print) const;
    Use this method to print well-formatted JSON encodings contained in the EncodedBuffer object. Set the pretty_print parameter to 1 to format the input JSON encoding as human readable, or to 0 otherwise. This function can be used for debugging.

    PEREncodedBuffer

    The PEREncodedBuffer class is a subclass of EncodedBuffer. PER encodings can consist of an arbitrary number of bits, not necessarily an integral number of octets. You might need to determine how many bits in the last byte of the encoding are unused. The EncodedBuffer class lacks such functionality; it is implemented in the PEREncodedBuffer class.

    PER is not required to use the PEREncodedBuffer class. It can also be used with any other encoding rules, in which case, the number of padding bits will be always 0. You might choose this variant, for example, when the application dynamically changes the encoding rules in use; just be sure to write generic code that works for every possible set of encoding rules.

    Definition

    class PEREncodedBuffer : public EncodedBuffer
    {
    public:
       PEREncodedBuffer();
       PEREncodedBuffer(unsigned long length, char *value);
       PEREncodedBuffer(OssString & any);
         void set_buffer(unsigned long length, char *value);
         void grab_buffer(unsigned long length, char *value);
         int get_pad_bits() const;
         void clone(EncodedBuffer &orig);
         void set_position(unsigned long pos);
    };

    Methods

    PEREncodedBuffer();
    PEREncodedBuffer(unsigned long length, char *value);
    PEREncodedBuffer(OssString & any);
    These methods are completely analogous to the corresponding constructors of the EncodedBuffer class. The number of padding bits is initially set to 0.
    void set_buffer(unsigned long length, char *value);
    void grab_buffer(unsigned long length, char *value);
    void set_position(unsigned long pos);
    These methods are completely analogous to the corresponding functions of the EncodedBuffer class. The number of padding bits is reset to 0.
    void clone(EncodedBuffer &orig);
    This method is analogous to the clone() function of the EncodedBuffer class. The number of padding bits is set to 0. Note that the input object (being cloned) can be a PEREncodedBuffer. In this case, the number of padding bits will be not copied, but set to 0 regardless of the corresponding value in the input object.
    int get_pad_bits() const;
    This method returns the current number of padding bits. Usually it will be 0, except when an encode operation has just been performed on this buffer. In that case, it will be set to the number of padding bits needed to pad the resulting encoding to an integral number of octets.

    EncodedFile

    The EncodedFile class is a subclass of EncodedData. The encoded data is stored in a file. The Lean Encoder/Decoder (LED) and the Time-Optimized Encoder/Decoder (TOED) do not support encoding to or decoding from files without using intermediate memory buffers, so use the SOED to take advantage of this class. Alignment flags are ignored when encoding/decoding to/from a file or socket; front alignment is always used.

    Definition

    class EncodedFile: public EncodedData {
    public:
      EncodedFile(const char *filename, int append = 0);
      ~EncodedFile();
      void reset();
    };

    Methods

    EncodedFile(const char *filename, int append = 0);
    This method creates an EncodedFile object referencing the file with the name passed as the parameter. The file can be opened in either overwrite mode or append mode. The mode is specified by the optional second argument of the method. In overwrite mode (the default), each encoding operation on the file starts from the beginning of the file overwriting the existing contents. In append mode, each encoding operation starts from the current end of the file. Decoding operations are always started at the point where previous decoding stopped.
    void reset();
    This method specifies that the next encoding/decoding operation will start at the beginning of the file. For encoding operations, this only makes sense when the file has been opened in append mode, since in overwrite mode the file is automatically reset to the beginning.
    NOTE: The copy constructor and assignment operator for the EncodedFile, EncodedBuffer, and EncodedSocket classes are private. These types of objects can only be passed by referencing the other functions.

    EncodedSocket

    The EncodedSocket class is a subclass of EncodedData. The encoded data is read from or written to a socket. The Lean Encoder/Decoder and the Time-Optimized Encoder/Decoder do not support encoding to or decoding from sockets without using intermediate memory buffers, so use the SOED to take advantage of this class. Alignment flags are ignored when encoding/decoding to/from a file or socket; front alignment is always used.

    NOTE: The behavior of OSS methods when encoding and decoding data using the EncodedSocket class is based on the send() and recv() socket functions and therefore is inherited from these socket functions. For example, when a socket is closed by the remote side and a subsequent send() on the local side does not report an error, an OSS encode() would also be unable to detect the closed socket and instead would accept the undeliverable packet. You can use the handler of the socket you pass to the EncodedSocket constructor to tune the socket, or to send or receive additional messages using socket functions.

    Definition

    class EncodedSocket: public EncodedData {
    public:
      EncodedSocket(SOCKET socket);
      ~EncodedSocket();
    };

    Methods

    EncodedSocket(SOCKET socket);
    This method creates an EncodedSocket object representing the socket specified as the parameter.
    NOTE: The copy constructor and assignment operator for the EncodedFile, EncodedBuffer, and EncodedSocket classes are private. These types of objects can only be passed by referencing the other functions.

    ASN1Handle

    This class acts as a common ancestor for all generated coding classes. To perform some action (e.g.,encoding, decoding, printing, constraint-checking) on a representation type value, the application programmer must use an object of the appropriate coding class. A coding class object acts as a container for the corresponding representation type. Each coding class includes a pointer to the related representation object. The object pointed to can be constant, however, it cannot be modified by any of the ASN1Handle methods or their successors.

    NOTE: The representation object is owned by the caller, that is, it is not destroyed by the ASN1Handle object destructor. The destruction of the representation object is the responsibility of the caller.

    The ASN1Handle class itself represents a non-PDU type and has no encoding/decoding functions, they are provided by its successor PDU. However, it can be used to print the contents of representation class objects, to check constraints, or to convert corresponding representation type values to/from ASN.1 value notation. When the program deals with several ASN.1 specifications at the same time, make sure to use ASN1Handle (and OssControl) objects only with the representation objects produced from the corresponding specification. Errors that arise from specification mismatches are not trapped.

    Relation of ASN1Handle class and its sub-classes

    Relationship between the ASN1Handle class and its sub-classes

    Definition

    class ASN1Handle {
    public:
      int print(OssControl &ctl) const;
      char *toString(OssControl &ctl, char *buffer = NULL, unsigned long length = 0) const;
      unsigned long toStringLength(OssControl &ctl) const;
      int check_constraints(OssControl &ctl) const;
      int setFromValueNotation(OssControl &ctl, const char *valnot);
      char *asValueNotation(OssControl &ctl) const;
      void release_data();
      int copy(OssControl &, const ASN1Handle &);
      int equals(OssControl &, const ASN1Handle &) const;
      int free_data(OssControl &);
      int is_constant() const;
    };

    Methods

    int print(OssControl &ctl) const;
    This method prints the data contained in the ASN1Type object in ASN.1 notation. The print() function accepts a reference to a valid OssControl instance that will be used when printing. If you compiled your specification with the –nodebug compiler option, this function cannot determine the type names and field names, so it will print <anonymous> instead.

    NOTE: By default, PDU printing functionality is not enabled when the TOED is used. The .cpp file generated for the TOED should be compiled with the OSSPRINT macro (i.e., the –DOSSPRINT C++ compiler option) enabled to make the ASN1Handle::print function available. See C++ Compiler Macros to Optimize Size and Speed when Using the TOED for more details about this macro and others that affect TOED code.

    The 0 value is returned when printing is successful, otherwise an error code is returned. When "full-exception" mode is in effect, errors are signaled with C++ exceptions, so the function never returns anything but 0.
    char *toString(OssControl &ctl, char *buffer = NULL, unsigned long length = 0) const;
    This method converts the data contained in the ASN1Type object into textual ASN.1 notation format. The resulting text is placed in the memory buffer. The method accepts a reference to a valid OssControl instance that will be used when printing. As for print(), if you compiled your specification with the –nodebug compiler option, this function cannot determine the type names and field names, so it will print <anonymous> instead.

    When buffer is NULL, the method allocates a new memory block in the exact length needed to hold the resulting string and returns its address. The resulting block is owned by the caller. When no longer needed, the application must deallocate the block using the asn1Free function. When the buffer is not NULL, the method places the resulting text in the specified buffer. In this case, the length of the buffer is specified in the length parameter. This parameter is ignored when using an automatically allocated buffer. The resulting text is a null-terminated string.

    NOTE: By default, PDU printing functionality is not enabled if the TOED is used. The .cpp file generated for the TOED should be compiled with the OSSPRINT macro enabled (i.e., the –DOSSPRINT C++ compiler option) to make theASN1Handle::toString function available. See C++ Compiler Macros to Optimize Size and Speed when Using the TOED for more details about this macro and others that affect TOED code.

    If printing was successful, the function returns the address of the resulting null-terminated string (i.e., for a preallocated buffer, it returns the value of the buffer argument). If any error occurs, the function returns NULL, provided C++ exceptions are not used by the error-handling function. The exact information about the error can be found using the error handling function.
    unsigned long toStringLength(OssControl &ctl) const;
    This method returns the size of the memory buffer needed to hold the result of toString() for the value currently contained in the ASN1Handle object, including the terminating zero byte. If you prefer to use preallocated memory buffers, you can call this function to determine the size of the preallocated buffer.

    If an error occurs, the error-handling function is called and the function returns 0, provided C++ exceptions are not used by the error-handling function.
    int check_constraints(OssControl &ctl) const;
    This method performs constraint checking for the current representation object. It accepts a reference to a valid OssControl instance that will be used while checking the constraints.

    The value 0 is returned if the checking succeeds, otherwise a non-zero is returned if one or more constraints are violated. This function does not throw exceptions even in "full-exception" mode, because the constraint violation is considered a normal result for this function.
    int setFromValueNotation(OssControl &ctl, const char *valnot);
    This function creates a new representation object from the ASN.1 value notation string pointed to by the valnot variable. The newly created object becomes the current representation object for the PDU object. It is owned by the caller, and the caller is responsible for destroying it when it is no longer needed. If the PDU object had some representation object prior to the call, the caller should save its address before the call, because the caller should also destroy it (the function itself does not destroy it). In order for this function to work properly, type and field names need to be generated in the control table, so you need to compile the specification with the –debug option of the ASN.1/C++ compiler.

    The value 0 is returned if the conversion was successful, otherwise a non-zero error code is returned. When "full-exception" mode is in effect, errors are signaled with C++ exceptions, so the function never returns anything but 0.
    char *asValueNotation(OssControl &ctl) const;
    This function returns a string represented by the contents of the current type in the form of a valid ASN.1 value notation. The asValueNotation() function accepts a reference to a valid OssControl instance that will be temporarily used in the conversion process. The value returned is a pointer to a newly allocated memory block. It is the responsibility of the caller to free the memory when it's no longer needed (via a call to asn1Free(), see Memory Allocation). In order for this function to work properly, type and field names need to be generated in the control table, so you need to compile the specification with the –debug option of the ASN.1/C++ compiler.

    A string containing the value notation is returned if successful, otherwise it calls the error handling function. If this function does not throw any exception (as is done in the standard mode), asValueNotation returns NULL.

    NOTE: TOED does not support the setFromValueNotation and asValueNotation functions. If you are using TOED, these functions always return an error.
    void release_data();
    This function releases the representation object used by the class by setting the data pointer to NULL. Note that it does not deallocate the representation object. Its deallocation is still the responsibility of the caller.
    int copy(OssControl & ctl, const ASN1Handle & src);
    This function makes a copy of the representation class data taken from the ASN1Handle object referenced by the src parameter. The newly created representation object is assigned to "this" object. The ctl parameter is an OssControl object that will be temporarily used by the function. Although all representation classes have assignment operators, it may be convenient to use this function when the exact type of the data being copied is unknown.

    This method makes a deep copy of the data contained in the ASN1Handle object passed as a parameter, so that the source representation object and the resulting one have no memory blocks shared between them. If the data being copied is of a type that "this" object cannot handle, no data is copied and the error code OSS_TYPE_MISMATCH is returned. The user owns the copied data. This means that the user should explicitly destroy the resulting representation object using the delete operator.

    The value 0 is returned if copying succeeds, otherwise an error code is returned. When "full-exception" mode is in effect, errors are signaled with C++ exceptions, so the function never returns anything but 0.
    int equals(OssControl & ctl, const ASN1Handle & src) const;
    This function compares the contents of the representation object taken from "this" coding object with the representation object from another instance of a coding class specified by the src parameter. The ctl parameter references an OssControl instance that will be temporarily used by the function. Although all representation classes have comparison operators, it may be convenient to use this function if the exact type of the data being copied is unknown.

    The value 1 is returned if the objects are equal, otherwise the comparison is not equal and a value of 0 is returned.

    Note: If the objects being compared are of different ASN.1 types, the function returns not equal. If neither instance contains any representation objects, the comparison is assumed equal.
    int free_data(OssControl & ctl);
    This function frees memory allocated to the current representation object (an equivalent of the delete operator of the representation object). The free_data() method accepts a reference to a valid OssControl instance that will be used by the function. If the coding class does not refer to any representation class instance, 0 is returned (freeing successful).

    The value 0 is returned if freeing succeeds, otherwise an error code is returned. When "full-exception" mode is in effect, errors are signaled with C++ exceptions, so the function never returns anything but 0.

    NOTE: To destroy the representation object manually, you can choose either: delete pdu.get_data(); or pdu.free_data(ctl); Use the first way when the PDU object contains a class instance. However, if the contained ASN.1 type is represented by a primitive C++ type such as int, you must use another form (instead of delete): asn1Free(pdu.get_data()); The second way (calling free_data) is correct regardless of the contained ASN.1 type.
    int is_constant() const;
    The value 1 is returned if the contained object is constant, otherwise, a value of 0 is returned.

    PDU

    This abstract class is derived from ASN1Handle; it acts as a common ancestor for all generated PDU types and presents encoding and decoding methods.

    Definition

    class PDU: public ASN1Handle {
    public:
      int encode(OssControl &ctl, EncodedData &buf) const;
      int decode(OssControl &ctl, EncodedData &buf);
      int decode(OssControl &ctl, EncodedData &input, EncodedBuffer &output);
      long determineEncodingLength(OssControl &ctl) const;
      int binary2XML(OssControl &ctl, OssEncodingRules rule, EncodedData &from, EncodedData &to);
      int XML2Binary(OssControl &ctl, OssEncodingRules rule, EncodedData &from, EncodedData &to);
      int binary2JSON(OssControl &ctl, OssEncodingRules rule, EncodedData &from, EncodedData &to); 
      int JSON2Binary(OssControl &ctl, OssEncodingRules rule, EncodedData &from, EncodedData &to); 
      int convertData(OssControl &ctl, EncodedBuffer &fromData, unsigned int fromFormat,
                                                          EncodedBuffer &toData, unsigned int toFormat);
    };

    Methods

    int encode(OssControl &ctl, EncodedData &buf) const;
    This function encodes the data contained in the PDU object into the buffer passed as the second parameter. The first parameter is the control object that will be used by encoding.

    The function returns 0 in the case of successful encoding and a non-zero error code when the encoding fails. When "full-exception" mode is in effect, errors are signaled with C++ exceptions, so the function never returns anything but 0.
    int decode(OssControl &ctl, EncodedData &buf;)
    This function decodes the data contained in the buffer passed as the second parameter. The decoded data will be placed into a newly created representation object. Its address will be held in the PDU object. It is the user's responsibility to delete the representation object if it is no longer needed. The first parameter is the control object that will be used in decoding.

    The function returns 0 in the case of successful decoding and a non-zero error code when the decoding fails. When "full-exception" mode is in effect, errors are signaled with C++ exceptions, so the function never returns anything but 0.
    int decode(OssControl &ctl, EncodedData &input, EncodedBuffer &output);
    This function decodes the data contained in the preallocated buffer passed as the second parameter. The decoded data will be placed into the memory buffer passed as the third parameter. The address of the created decoded object will be held in the PDU object. The decoded object is considered constant; the application cannot make any changes to it (if changes are needed, the application must make a fresh copy first). The user must make sure that the buffer used for the decoded value is not deleted or changed while the decoded value is used. The user must not deallocate the decoded value explicitly. Deallocating the memory buffer is sufficient, because the entire decoded value resides in it. The first parameter is the control object that will be used in decoding.

    This method can be significantly faster than the previous one because it does not involve dynamic memory allocation. However, the decoded object is read-only, so an additional copy operation is needed when the application needs to make any changes in the decoded data.

    The function returns 0 when decoding is successful and a non-zero error code when decoding fails. When "full-exception" mode is in effect, errors are signaled with C++ exceptions, so the function never returns anything but 0.

    NOTE: Although it's not recommended for everyone, you might consider partial decoding if you are interested in the contents of only a few fields. Rather than call the decode() method, which would decode the entire PDU, you could instead call the ConcretePDU::partialDecode() method to decode only those fields you flag with the OSS.DataCallback directive. See Partial Decoding for general information about partial decoding.
    long determineEncodingLength(OssControl &ctl) const;
    This function returns the size of the encoded data that encode() would create if it were called to encode the data contained in the PDU object. This function allows you to find the size of the buffer needed to store the encoder's output, without the extensive memory allocations done by encode(). The prime use of this function is in those applications that want to minimize the amount of memory allocated. However, calling this function instead of encode() will not give you much of a CPU cycle performance advantage; rather, if you are trying to find the size of the preallocated output buffer to provide to encode(), the most CPU-cycle conscious method is to perform empirical test calls of encode() with the expected data and to check the length after each call using get_data_size() method of the EncodedBuffer class. The parameter of determineEncodingLength() is the control object that will be used by encoding.

    The function returns a long integer. Upon a successful call, the number of octets to be occupied by the data's encoding is returned; otherwise, a length of zero is returned.

    NOTE: For the purposes of this function, we recommend that the input buffer be a minimum of 8 bytes long, unless the message is shorter than 8 bytes. This is the minimum likely size of a BER/DER-encoded buffer.
    int binary2XML(OssControl &ctl, OssEncodingRules rule, EncodedData &from, EncodedData &to);
    This method converts data in standard ASN.1 binary encoding rules (e.g., BER, CER, DER, PER) format into ASN.1:2015 XER text encoding rules format. The first parameter is the control object to be used by the encoding, rule is an enumerator specifying the encoding rules of the binary ASN.1 encoding to convert from (e.g., OSS_BER, OSS_CER, OSS_DER, OSS_PER_ALIGNED, etc.), the third parameter is the buffer that references the binary encoded ASN.1 value, and the last parameter is an empty buffer in which to store the converted XER data.

    The function returns 0 when conversion is successful and a non-zero error code when the conversion fails. When "full-exception" mode is in effect, errors are signaled with C++ exceptions, so the function never returns anything but 0.
    int XML2Binary(OssControl &ctl, OssEncodingRules rule, EncodedData &from, EncodedData &to);
    This method converts data in ASN.1:2015 XER text encoding rules format into standard ASN.1 binary encoding rules (e.g., BER, CER, DER, PER) format. The first parameter is the control object to be used by the encoding, rule is an enumerator specifying the encoding rules of the binary ASN.1 encoding to convert to (e.g., OSS_BER, OSS_CER, OSS_DER, OSS_PER_ALIGNED, etc.), the third parameter is the buffer that references the XER encoded value, and the last parameter is an empty buffer in which to store the converted binary encoded value.

    The function returns 0 when conversion is successful and a non-zero error code when the conversion fails. When "full-exception" mode is in effect, errors are signaled with C++ exceptions, so the function never returns anything but 0.
    int binary2JSON(OssControl &ctl, OssEncodingRules rule,EncodedData &from, EncodedData &to);
    This method, added in version 6.3, converts data in standard ASN.1 binary encoding rules (e.g., BER, CER, DER, PER, OER) format into JSON encoding rules format. ctl is the control object to be used by the encoding, rule is an enumerator specifying the encoding rules of the binary ASN.1 encoding to convert from (e.g., OSS_BER, OSS_CER, OSS_DER, OSS_PER_ALIGNED, etc.), from is the buffer that references the binary encoded ASN.1 value, and to is an empty buffer in which to store the converted JSON data.

    The function returns 0 when conversion is successful and a non-zero error code when the conversion fails. When "full-exception" mode is in effect, errors are signaled with C++ exceptions, so the function never returns anything but 0.
    int JSON2Binary(OssControl &ctl, OssEncodingRules rule,EncodedData &from, EncodedData &to);
    This method, added in version 6.3, converts data in JSON encoding rules format into standard ASN.1 binary encoding rules (e.g., BER, CER, DER, PER, OER) format. ctl is the control object to be used by the encoding, rule is an enumerator specifying the encoding rules of the binary ASN.1 encoding to convert to (e.g., OSS_BER, OSS_CER, OSS_DER, OSS_PER_ALIGNED, etc.), from is the buffer that references the JSON encoded value, and to is an empty buffer in which to store the converted binary encoded value.

    The function returns 0 when conversion is successful and a non-zero error code when the conversion fails. When "full-exception" mode is in effect, errors are signaled with C++ exceptions, so the function never returns anything but 0.
    int convertData(OssControl &ctl, EncodedBuffer &fromData, unsigned int fromFormat,
    EncodedBuffer &toData, unsigned int toFormat);
    This method performs data format conversion between binary, hexadecimal and BASE64 formats. The first parameter is a control object that will be used during conversion. The source and target data are passed using fromData and toData buffers. The source and target formats are defined by fromFormat and toFormat correspondingly. Supported formats are OSS_BIN_DATA, OSS_HEX_DATA, OSS_BASE64_DATA.

    The function returns 0 when conversion is successful and a non-zero error code when the conversion fails. When "full-exception" mode is in effect, errors are signaled with C++ exceptions, so the function never returns anything but 0.

    ConcretePDU

    This class is derived from the PDU class; it acts as a common ancestor for all generated specific PDU types; see Specific PDU Class <Typename>_PDU for details.

    Definition

    class ConcretePDU: public PDU {
    public:
      int decode(OssControl &ctl, EncodedData &buf);
      int decode(OssControl &ctl, EncodedData &input, EncodedBuffer &output);
      int partialDecode(OssControl &ctl, EncodedData &buf, OssCallback &callback);
    };

    Methods

    int decode(OssControl &ctl, EncodedData &buf);
    Implements the decoding interface declared in the PDU class.
    int decode(OssControl &ctl, EncodedData &input, EncodedBuffer &output);
    Implements the decoding to preallocated buffer interface declared in the PDU class.
    int partialDecode(OssControl &ctl, EncodedData &buf, OssCallback &callback);
    Provides partial decode functionality. The first two parameters are the same as those of the decode() method. The third parameter is a reference to an instance of an OssCallback object. See Partial Decoding for more information.

    See Also


    OssCallback

    The OssCallback class is a base interface that is defined in the asn1.h file:

    /* a class used as an interface by ConcretePDU::partialDecode */
    class PUBLIC OssCallback
    {
    public:
        void * userVar;
    };

    To pass data between the application and the callback methods or between callback method calls, use the userVar(void *) member within the OssCallback class. If the data to be passed fits the pointer size, it can be stored directly in the field. Otherwise, the field can store a pointer to the memory block that contains the data.

    General information about partial decoding can be found in Partial Decoding.

    Default Implementation of the Callback Method

    When -enablePartialDecode or -partialDecodeOnly is specified, the ASN.1/C++ Compiler generates a subclass of the OssCallback interface that contains the default implementation of the callback method:

    int <MethodName>(OssGlobal *_g, long offset, long length, unsigned int flags, Tvalue *value);
    MethodName is the user-defined name for the callback method.
    _g is a pointer to the OssGlobal structure, which is used internally by the ASN.1/C++ API and never modified by the user application.
    offset is the offset (in bytes) of the field.
    length is the length (in bytes) of the field encoding.
    flags indicates situations where it would be impossible to isolate the value using offset and length, that is, where it would be difficult and error-prone for you to try to modify the value in-place. Each flag is described below.
    value is a pointer to the decoded value.

    The _g, offset, length, and flags parameters are the same for all callback methods. The value parameter points to the decoded value of the field to which the directive is applied. Its actual type varies depending on the ASN.1 type. The decoded value is available only in the callback method.

    The decoder reuses the memory allocated for the value after the callback method returns. Therefore, the callback member function code should store the decoded field value for future use, if necessary. Reusing memory like this significantly reduces the amount of memory needed for decoding. For example, if the OSS.DataCallback directive is applied to an element of a SEQUENCE OF type, the decoder will not allocate more memory than needed for one element.

    The following flags can be passed to the callback method:

    OSS_ENCODING_UNDEFINED
    This flag is returned whenever the field in question is encoded using bit-oriented rules (PER, UPER), and not octet-oriented rules (BER, DER, OER, C-OER). This is of consequence if you intend to modify values in-place, since offset and length alone will not isolate the value. Do not modify the value when this flag is returned.
    OSS_COMPLEX_ENCODING
    This flag is returned whenever a BER field is fragmented. Some types, for example, OCTET STRING, could be broken into fragments where each fragment has a separate offset and length. This makes it difficult to discern what the value is, so do not modify the value when this flag is returned.
    Return Codes

    Instruct the decoder to either stop or continue decoding the message by means of a return code from your callback method.

    • If the method returns OSS_SKIP_TO_PDU_END, the decoder will skip the remaining fields until it reaches the end of the message. Note that although this process is faster than typical decoding, the speed depends on the encoding rules and the message structure.
    • If the method returns OSS_CONTINUE_DECODING, the decoder will continue to partially decode the message and, if the method is bound to a remaining field, it could call this or another callback method.

    Any other return code from the callback method signals an error to the decoder, in which case the decoder executes a longjmp() and ConcretePDU::partialDecode() returns the return code it received from the callback method. Note that returning via longjmp() is often slower than using OSS_SKIP_TO_PDU_END to skip to the end.

    The ASN.1/C++ Compiler generates the class that contains the callback methods, so you can easily derive the class and implement the methods.

    Example 1

    ASN.1 syntax (bcas.asn):

    --<OSS.DataCallback BCAS.BBCard.age "myFunc">--
    
    BCAS DEFINITIONS ::= BEGIN
    
    CareerEntry ::= SEQUENCE {
       from  INTEGER (0..MAX),
       to    INTEGER (0..MAX) OPTIONAL,
       team  VisibleString (SIZE (1..255))
    }
    
    BBCard ::= SEQUENCE {
       name      VisibleString (SIZE(1..64)),
       age       INTEGER (1..100),
       position  VisibleString (SIZE (1..64)),
       career    SEQUENCE OF CareerEntry
    }
    END

    The compiler generates the following derived class from the syntax above:

    /* Partial decoding callback class */
    
    class OSS_PUBLIC bcas_Callback : public OssCallback {
    public:
        /* user-defined data callback method for ASN.1 item(s) BCAS.BBCard.age */
        virtual int myFunc(OssGlobal *_g, long offset, long length, unsigned int flags, OSS_UINT32  *value);
    };

    The next example shows you how to derive the compiler-generated class and how to call the ConcretePDU::partialDecode() API. For the sake of readability, exception handling code is omitted from this example.

    /* the BER encoding of a BBCard PDU */
    char   ber_enc[] = {
    
        0x30, 0x34, 0x1A, 0x05, 0x43, 0x61, 0x73, 0x65, 0x79, 0x02,
        0x01, 0x20, 0x1A, 0x0A, 0x6C, 0x65, 0x66, 0x74, 0x20, 0x66,
        0x69, 0x65, 0x6C, 0x64, 0x30, 0x1C, 0x30, 0x1A, 0x02, 0x02,
        0x07, 0xD0, 0x02, 0x02, 0x07, 0xD6, 0x1A, 0x10, 0x4E, 0x65,
        0x77, 0x20, 0x59, 0x6F, 0x72, 0x6B, 0x20, 0x59, 0x61, 0x6E,
        0x6B, 0x65, 0x65, 0x73
    };
    
    /* User-defined callback class */
    class myCallbackClass : public bcas_Callback {
    public:
        int myFunc(OssGlobal *_g, long offset, long length, unsigned int flags, OSS_UINT32  *value);
    };
    
    /* User-implemented callback method */
    int myCallbackClass::myFunc(OssGlobal *_g, long offset, long length, unsigned int flags, OSS_UINT32  *value) {
        ossPrint(_g, "Age field value is: %d", *value);
        return OSS_CONTINUE_DECODING;
    };
    
    /* Invocation of ConcretePDU::partialDecode() method */
    void testDataCallback() {
        BBCard_PDU          pdu;
        bcas_Control        ctl;
        EncodedBuffer       eb;
        myCallbackClass     cback;
    
        ctl.setEncodingRules(OSS_BER);
        eb.set_buffer(sizeof(ber_enc), ber_enc);
    
        pdu.partialDecode(ctl, eb, cback);
    }

    When the OSS.DataCallback directive is applied to a field, the compiler generates code that fully decodes the field, and it passes the address of the decoded value to the specified callback function. Otherwise, the compiler generates code to skip the field.

    The method used for skipping a field depends on the field and on the encoding rules employed, as follows:

    • For definite length BER, the decoder can simply jump over the field.
    • For PER, the decoder cannot always be certain where the field ends without decoding it, and so the decoder often decodes the field and then discards the decoding.

    Regardless, the pointer to the current position is advanced to the subsequent field. If the field to be skipped is a constructed type that contains a field marked with the OSS.DataCallback directive, it cannot be entirely skipped and the procedure applies recursively.

    NOTE: During partial decoding, when the decoder is able to skip a field by jumping over it, it does not stop to examine the contents. Such skipped fields are not checked for adherence to the encoding rules.

    Effect of OSS.InfoCallback

    When an OSS.DataCallback directive is applied to a type that occurs in multiple locations and the OSS.InfoCallback directive is also specified, the following method is added to the generated callback class:

    int (OssGlobal *_g, const char *fname, unsigned int flags);
    MethodName is the user-defined name for the callback method.
    _g is a pointer to the OssGlobal structure, which is used internally by the ASN.1/C++ API and never modified by the user application.
    fname is the name of the field being decoded.
    flags indicates the decoding status of the current field. Only the OSS_DECODING_OF_COMPONENT_IN_PROGRESS value can be set.

    Possible return values and how the ASN.1 C++ Runtime handles them are the same as those of the data callback method.

    OSS.InfoCallback usage is illustrated in the following example.

    Example 2

    ASN.1 syntax (infotest.asn):

    M DEFINITIONS AUTOMATIC TAGS ::= BEGIN
    Subscriber ::= SEQUENCE {
       name         VisibleString,
       company      Company,
       homeAddress  Address
    }
    Company ::= SEQUENCE {
       name    VisibleString,
       address  Address
    }
    Address ::= SEQUENCE {
       zipcode      INTEGER( 0..99999 ),
       addressline  VisibleString( SIZE (1..64) )
    }
    END

    When the directive is applied to the zipcode field in the ASN.1 syntax above

    --<OSS.DataCallback M.Address.zipcode "myZipcode">--

    then the myZipcode() callback method is called for zipcode in both uses of Address.

    To filter out the zipcode values, use the OSS.InfoCallback directive:

    --<OSS.InfoCallback M.Subscriber.homeAddress "homeAddressField">--

    This directive instructs the compiler to generate a prototype for the homeAddressField() callback method inside the <module_name>_Callback class. This method is called by the decoder twice: once before starting the partial decoding of the homeAddress field and again after finishing its decoding. Note that the decoder only informs the application about a particular step of the decoding process. It does not pass any decoded values to the method, thus the info callbacks are faster than the data callbacks.

    The following example illustrates how data and info callback methods can be combined so that only zipcode values from homeAddress are processed and zipcode values from companyAddress are ignored.

    /* the BER encoding of a Subscriber PDU */
    char   ber_enc[] = {
    
        0x30, 0x5D, 0x80, 0x08, 0x4A, 0x6F, 0x68, 0x6E, 0x20, 0x44,
        0x6F, 0x65, 0xA1, 0x2D, 0x80, 0x10, 0x41, 0x62, 0x73, 0x75,
        0x72, 0x64, 0x20, 0x4C, 0x6F, 0x67, 0x69, 0x73, 0x74, 0x69,
        0x63, 0x73, 0xA1, 0x19, 0x80, 0x02, 0x30, 0x39, 0x81, 0x13,
        0x38, 0x30, 0x30, 0x2C, 0x20, 0x37, 0x74, 0x68, 0x20, 0x53,
        0x74, 0x72, 0x65, 0x65, 0x74, 0x2C, 0x20, 0x4E, 0x59, 0xA2,
        0x22, 0x80, 0x03, 0x01, 0x09, 0x32, 0x81, 0x1B, 0x33, 0x33,
        0x33, 0x2C, 0x20, 0x46, 0x6F, 0x6F, 0x62, 0x61, 0x72, 0x20,
        0x44, 0x72, 0x2E, 0x2C, 0x20, 0x42, 0x61, 0x79, 0x6F, 0x6E,
        0x6E, 0x65, 0x20, 0x4E, 0x4A
    };
    
    /*
        A structure for data exchange between callback function calls.
        In case of multithreading it should be allocated per thread
    */
    typedef struct {
        int    flag;
    } UserData;
    
    UserData data;
    
    /* derive the compiler generated infotest_Callback class */
    class myCallbackClass : public infotest_Callback {
    public:
        int myZipcode(OssGlobal *_g, long offset, long length, unsigned int flags, OSS_UINT32  *value);
        int homeAddressField(OssGlobal *_g, const char *fname, unsigned int flags);
    };
    
    /*
        Info callback method. It sets the flag indicating that homeAddress
        field is being decoded
    */
    int myCallbackClass::homeAddressField(OssGlobal *_g, const char *fname, unsigned int flags) {
        UserData *udP = (UserData *)this->userVar;
        if (flags & OSS_DECODING_OF_COMPONENT_IN_PROGRESS) {
            ossPrint(_g, "\n\nDecoding of homeAddressField started...");
            udP->flag = 1;
        }
        else {
            ossPrint(_g, "\nDecoding of homeAddressField completed.\n\n");
            udP->flag = 0;
        }
        return OSS_CONTINUE_DECODING;
    }
    
    /*
        myZipcode callback method implementation.
        it prints the value of zipcode field
    */
    int myCallbackClass::myZipcode(OssGlobal *_g, long offset, long length, unsigned int flags, OSS_UINT32  *value) {
        UserData *udP = (UserData *)this->userVar;
    
        ossPrint(_g, "\n!myZipcode() callback...\n");
    
        if (udP->flag != 1) {  /* we are not in homeAddress */
            ossPrint(_g, "    we are not in homeAaddress! Continue decoding...\n");
            return OSS_CONTINUE_DECODING;
        }
        /* Print homeAddress zipcode */
        ossPrint(_g, "   zipcode value is %05d\n", *value);
    
        return OSS_SKIP_TO_PDU_END;
    };
    
    void testInfoCallback()
    {
        Subscriber_PDU      pdu;
        infotest_Control    ctl;
        EncodedBuffer       eb;
        myCallbackClass     cback;
    
        cback.userVar = &data;
    
        ctl.setEncodingRules(OSS_BER);
        eb.set_buffer(sizeof(ber_enc), ber_enc);
    
        pdu.partialDecode(ctl, eb, cback);
    }

    Here is the output of the code sample:

    !myZipcode() callback...
        we are not in homeAddress! Continue decoding...
    
    Decoding of homeAddressField started...
    !myZipcode() callback...
       zipcode value is 67890

    NOTE: The above code sample is provided only for illustrative purposes. In a real-life situation, the flag in the sample code would need only one bit so that, instead of using the field as a pointer to the user data, it could be directly stored in the cback.userVar field.

    See Also


    This documentation applies to release 6.5 and later of the OSS® ASN.1 Tools for C++.

    Copyright © 2017 OSS Nokalva, Inc. All rights reserved.
    No part of this publication may be reproduced, stored in a retrieval system, or transmitted in any form or by any means electronic, mechanical, photocopying, recording or otherwise, without the prior permission of OSS Nokalva, Inc.
    Every distributed copy of the OSS® ASN.1 Tools for C++ is associated with a specific license and related unique license number. That license determines, among other things, what functions of the OSS ASN.1 Tools for C++ are available to you.