
SEQUENCE
This section discusses the mapping of an ASN.1 SEQUENCE type to C. The C++ mapping is similar but there are some differences. These are discusses in the C++ Mapping of SEQUENCE subsection at the end of this section.
An ASN.1 SEQUENCE is a constructed type consisting of a series of element definitions. These elements can be of any ASN.1 type including other constructed types. For example, it is possible to nest a SEQUENCE definition within another SEQUENCE definition as follows:
A ::= SEQUENCE { x SEQUENCE { a1 INTEGER, a2 BOOLEAN }, y OCTET STRING SIZE (10) }In this example, the production has two elements - x and y. The nested SEQUENCE x has two additional elements - a1 and a2.
The ASN1C compiler first recursively pulls all of the embedded constructed elements out of the SEQUENCE and forms new temporary types. The names of the temporary types are of the form <name>_<element-name1>_<element-name2>_ ... <element-nameN>. For example, in the definition above, two temporary types would be generated: A_x and A_y (A_y is generated because a static OCTET STRING maps to a C++ struct type).
ASN.1 production: <name> ::= SEQUENCE { <element1-name> <element1-type>, <element2-name> <element2-type>, ... }Generated C code: typedef struct { <type1> <element1-name>; <type2> <element2-name>; ... } <name>;typedef struct { ... } <tempName1> typedef struct { ... } <tempName2> typedef struct { <tempName1> <element1-name>; <tempName2> <element2-name>; ... } <name>;The <type1> and <type2> placeholders represent the equivalent C types for the ASN.1 types <element1-type> and <element2-type> respectively. This form of the structure will be generated if the internal types are primitive. <tempName1> and <tempName2> are formed using the algorithm described above for pulling structured types out of the definition. This form is used for constructed elements and elements that map to structured C types.
typedef struct _A_x { ASN1INT a1; ASN1BOOL a2; } A_x; typedef struct A_y { ASN1UINT numocts; ASN1OCTET data[10]; } A_y; typedef struct _A { A_x x; A_y y; } A;In the case of nesting levels greater than two, all of the intermediate element names are used to form the final name. For example, consider the following type definition that contains three nesting levels:
X ::= SEQUENCE { a SEQUENCE { aa SEQUENCE { x INTEGER, y BOOLEAN }, bb INTEGER } }In this case, the generation of temporary types results in the following equivalent type definitions:
X-a-aa ::= SEQUENCE { x INTEGER, y BOOLEAN } X-a ::= SEQUENCE { aa X-a-aa, bb INTEGER } X ::= SEQUENCE { X-a a }Note that the name for the aa element type is X-a-aa. It contains both the name for a (at level 1) and aa (at level 2). This is a change from v5.1x and lower where only that production name and last element name would be used (i.e., X-aa). The change was made to ensure uniqueness of the generated names when multiple nesting levels are used.
Note that although the compiler can handle embedded constructed types within productions, it is generally not considered good style to define productions this way. It is much better to manually define the constructed types for use in the final production definition. For example, the production defined at the start of this section can be rewritten as the following set of productions:
X ::= SEQUENCE { a1 INTEGER, a2 BOOLEAN } Y ::= OCTET STRING A ::= SEQUENCE { X x, Y y }Note: as of X.680, unnamed elements are not allowed - elements must be named. ASN1C still provides backward compatibility support for this syntax however.
In an ASN.1 SEQUENCE definition, the <element-name> tokens at the beginning of element declarations are optional. It is possible to include only a type name without a field identifier to define an element. This is normally done with defined type elements, but can be done with built-in types as well. An example of a SEQUENCE with unnamed elements would be as follows:
AnInt ::= [PRIVATE 1] INTEGER Aseq ::= [PRIVATE 2] SEQUENCE { x INTEGER, AnInt }ASN1C handles this by generating an element name using the type name with the first character set to lower case. For built-in types, a constant element name is used for each type (for example, aInt is used for INTEGER). There is one caveat, however. ASN1C cannot handle multiple unnamed elements in a SEQUENCE or SET with the same type names. Element names must be used in this case to distinguish the elements.
typedef ASN1INT AnInt; typedef struct Aseq { ASN1INT x; AnInt anInt; } Aseq;Elements within a sequence can be declared to be optional using the OPTIONAL keyword. This indicates that the element is not required in the encoded message. An additional construct is added to the generated code to indicate whether an optional element is present in the message or not. This construct is a bit structure placed at the beginning of the generated sequence structure. This structure always has variable name `m' and contains single-bit elements of the form `<element-name>Present' as follows:
struct { unsigned <element-name1>Present : 1, unsigned <element-name2>Present : 1, ... } m;In this case, the elements included in this construct correspond to only those elements marked as OPTIONAL within the production. If a production contains no optional elements, the entire construct is omitted.
Aseq ::= [PRIVATE 2] SEQUENCE { x INTEGER OPTIONAL, AnInt OPTIONAL }typedef struct Aseq { struct { unsigned xPresent : 1, unsigned anIntPresent : 1 } m; ASN1INT x; AnInt anInt; } Aseq;When this structure is populated for encoding, the developer must set the xPresent and anIntPresent flags accordingly to indicate whether the elements are to be included in the encoded message or not. Conversely, when a message is decoded into this structure, the developer must test the flags to determine if the element was provided in the message or not.
The C++ version of the compiler will generate a constructor for the structured type for a SEQUENCE if OPTIONAL elements are present. This constructor will set all optional bits to zero when a variable of the structured type is declared. The programmer therefore does not have to be worried about clearing bits for elements that are not used; only with setting bits for the elements that are to be encoded.
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 |