
CHOICE
The ASN.1 CHOICE type is converted into a C or C++ structured type containing an integer for the choice tag value (t) followed by a union (u) of all of the equivalent types that make up the CHOICE elements.
The tag value is simply a sequential number starting at one for each alternative in the CHOICE. A #define constant is generated for each of these values. The format of this constant is "T_<name>_<element-name>" where <name> is the name of the ASN.1 production and <element-name> is the name of the CHOICE alternative. If a CHOICE alternative is not given an explicit name, then <element-name> is automatically generated by taking the type name and making the first letter lowercase (this is the same as was done for the ASN.1 SEQUENCE type with unnamed elements). If the generated name is not unique, a sequential number is appended to make it unique.
The union of choice alternatives is made of the equivalent C or C++ type definition followed by the element name for each of the elements. The rules for element generation are essentially the same as was described for SEQUENCE above. Constructed types or elements that map to C structured types are pulled out and temporary types are created. Unnamed elements names are automatically generated from the type name by making the first character of the name lowercase.
One difference between temporary types used in a SEQUENCE and in a CHOICE is that a pointer variable will be generated for use within the CHOICE union construct.
ASN.1 production: <name> ::= CHOICE { <element1-name> <element1-type>, <element2-name> <element2-type>, ... }Generated C code: #define T_<name>_<element1-name> 1 #define T_<name>_<element2-name> 2 ... typedef struct { int t; union { <type1> <element1-name>; <type2> <element2-name>; ... } u; } <name>;typedef struct { ... } <tempName1>; typedef struct { ... } <tempName2>; typedef struct { int t; union { <tempName1>* <element1-name>; <tempName2>* <element2-name>; ... } u; } <name>;If the -static command line option or <storage> static </storage> configuration variable is set for the given production, then pointers will not be used for the variable declarations. This is true for the C case only - for C++, pointers must be used due to the fact that the generated code will not compile if constructors are used in a non-pointer variable within a union construct.
The C++ mapping is the same with the exception that the `ASN1T_' prefix is added to the generated type name.
<type1> and <type2> are the equivalent C types representing the ASN.1 types <element1-type> and <element2-type> respectively. <tempName1> and <tempName2> represent the names of temporary types that may have been generated as the result of using constructed types within the definition.
Choice alternatives may be unnamed, in which case <element-name> is derived from <element-type> by making the first letter lowercase. One needs to be careful when nesting CHOICE structures at different levels within other nested ASN.1 structures (SEQUENCEs, SETs, or other CHOICEs). A problem arises when CHOICE element names at different levels are not unique (this is likely when elements are unnamed). The problem is that generated tag constants are not guaranteed to be unique since only the production and end element names are used.
The compiler gets around this problem by checking for duplicates. If the generated name is not unique, a sequential number is appended to make it unique. The compiler outputs an informational message when it does this.
C ::= CHOICE { [0] INTEGER, [1] CHOICE { [0] INTEGER, [1] BOOLEAN } }#define T_C_aInt 1 #define T_C_aChoice 2 #define T_C_aInt_1 1 #define T_C_aBool 2 typedef struct { int t; union { ASN1INT aInt; struct { int t; union { ASN1INT aInt; ASN1BOOL aBool; } u; } aChoice; } C;
Objective Systems, Inc.102 Pickering Way, Suite #506Exton, Pennsylvania 19341 http://www.obj-sys.com Phone: (484) 875-9841 Toll-free: (877) 307-6855 (US only) Fax: (484) 875-9830 info@obj-sys.com |