The ASN.1 OCTET STRING type is converted into a C structured type containing an integer to hold the number of octets and an array of unsigned characters (OCTETs) to hold the octet string contents. The number of octets integer specifies the actual number of octets in the contents field.
The allocation for the contents field depends on how the octet string is specified in the ASN.1 definition. If a size constraint is used, a static array of that size is generated; otherwise, a pointer variable is generated to hold a dynamically allocated string. The decoder will automatically allocate memory to hold a parsed string based on the received length of the string.
For C++, constructors and assignment operators are generated to make assigning variables to the structures easier. In addition to the default constructor, a constructor is provided for string or binary data. An assignment operator is generated for direct assignment of a null-terminated string to the structure (note: this assignment operator copies the null terminator at the end of the string to the data).
ASN.1 production:
<name> ::= OCTET STRING
Generated C code:
typedef ASN1DynOctStr <name>;
Generated C++ code:
typedef ASN1TDynOctStr ASN1T_<name>;
In this case, different base types are used for C and C++. The difference between the two is the C++ version includes constructors, assignment operators, and other helper methods that make it easier to manipulate binary data.
The ASN1DynOctStr type (i.e., the type used in the C mapping) is defined in the asn1type.h header file as follows:
typedef struct ASN1DynOctStr { OSUINT32 numocts; const OSOCTET* data; } ASN1DynOctStr;
The ASN1TDynOctStr type is defined in the ASN1TOctStr.h header file. This class extends the C ASN1DynOctStr class and adds many additional constructors and methods. See the C/C++ Common Run-time Reference Manual for a complete description of this class.
ASN.1 production:
<name> ::= OCTET STRING (SIZE (<len>))
Generated C code:
typedef struct { OSUINT32 numocts; OSOCTET data[<len>]; } <name>;
If the -strict-size command-line option is used, the numocts component within this type definition may be of a different type (OSUINT8 or OSUINT16) or eliminated completely if the type is constrained to be a fixed-size.
Generated C++ code:
typedef struct { OSUINT32 numocts; OSOCTET data[<len>]; // ctors ASN1T_<name> (); ASN1T_<name> (OSUINT32 _numocts, const OSOCTET* _data); ASN1T_<name> (const char* cstring); // assignment operators ASN1T_<name>& operator= (const char* cstring); } ASN1T_<name>;
If the -strict-size command-line option is used, the numocts component within this type definition may be of a different type (OSUINT8 or OSUINT16) or eliminated completely if the type is constrained to be a fixed-size.
It is possible to specify a contents constraint on an OCTET STRING type using the CONTAINING keyword. This indicates that the encoded contents of the specified type should be packed within the OCTET STRING container. An example of this type of constraint is as follows:
ContainingOS ::= OCTET STRING (CONTAINING INTEGER)
ASN1C will generate a type definition that references the type that is within the containing constraint. In this case, that would be INTEGER; therefore, the generated type definition would be as follows:
typedef OSINT32 ContainingOS;
The generated encoders and decoders would handle the extra packing and unpacking required to get this to and from an OCTET STRING container. This direct use of the containing type can be suppressed through the use of the -noContaining command-line argument. In this case, a normal OCTET STRING type will be used and it will be the users responsibility to do the necessary packing and unpacking operations to encode and decode the variable correctly.