TOC PREV NEXT INDEX


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>;
 

- or -

                   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.

An example of this can be found in the following production:

	C ::= CHOICE {
 
	   [0] INTEGER,
 
	   [1] CHOICE {
 
	      [0] INTEGER,
 
		[1] BOOLEAN
 
	   }
 
	}
 

This will produce the following C code:

 
	#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;
 

Note that `_1' was appended to the second instance of `T_C_aInt'. Developers must take care to ensure they are using the correct tag constant value when this happens.


Objective Systems, Inc.

102 Pickering Way, Suite #506
Exton, 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
TOC PREV NEXT INDEX