SEQUENCE OF

Dynamic SEQUENCE OF Type
Static (sized) SEQUENCE OF Type
List-based SEQUENCE OF Type
Populating Linked-List Structures
Generation of Temporary Types for SEQUENCE OF Elements
SEQUENCE OF Type Elements in Other Constructed Types

The ASN.1 SEQUENCE OF type is converted into one of the following C/C++ types:

The linked list option is the default for constructed types. An array is used for a sequence of primitive types. The allocation for the contents field of the array depends on how the SEQUENCE OF 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 array of values. The decoder will automatically allocate memory to hold parsed SEQUENCE OF data values.

The type used for a given SEQUENCE OF construct can be modified by the use of a configuration item. The <storage> qualifier is used for this purpose. The dynamicArray keyword can be used at the global, module, or production level to specify that dynamic memory (i.e., a pointer) is used for the array. The syntax of this qualifier is as follows:

   <storage>dynamicArray</storage>

The array keyword is used to specify that a static array is to be generated to hold the data. In this case, if the SEQUENCE OF production does not contain a size constraint, the maxSize attribute must be used to specify the maximum size of the array. For example:

   <storage maxSize="100">array</storage>

If maxSize is not specified and the ASN.1 production contains no size constraint, then a dynamic array is used.

The list keyword can also be used in a similar fashion to specify the use of a linked-linked structure to hold the elements:

   <storage>list</storage>

See the section entitled Compiler Configuration File for further details on setting up a configuration file.

Dynamic SEQUENCE OF Type

ASN.1 production:

   <name> ::= SEQUENCE OF <type>

Generated C code:

   typedef struct {
      OSUINT32 n;
      <type>* elem;
   } <name>;

Generated C++ code:

   typedef struct [ : public ASN1TPDU ] {
      OSUINT32 n;
      <type>* elem;
      ASN1T_<name>();
      [~ASN1T_<name>();]
   } ASN1T_<name>;

Note that parsed values can be accessed from the dynamic data variable just as they would be from a static array variable; i.e., an array subscript can be used (ex: elem[0], elem[1]...).

In the case of C++, a constructor is generated to initialize the element count to zero. If the type represents a PDU type (either by default by not referencing any other types or explicitly via the -pdu command-line option), the ASN1TPDU base class is extended and a destructor is added. This destructor ensures that memory allocated for elements is freed upon destruction of the object.

Static (sized) SEQUENCE OF Type

ASN.1 production:

   <name> ::= SEQUENCE (SIZE (<len>)) OF <type>

Generated C code:

   typedef struct {
      OSUINT32 n;
      <type> elem[<len>];
   } <name>;

Generated C++ code:

   typedef struct {
      OSUINT32 n;
      <type> elem[<len>];
      } ASN1T_<name>;

List-based SEQUENCE OF Type

A doubly-linked list header type (OSRTDList) is used for the type definition if the list storage configuration setting is used (see above). This can be used for either a sized or unsized SEQUENCE OF construct. The generated C or C++ code is as follows:

Generated C code:

   typedef OSRTDList <name>;

Generated C++ code:

   typedef ASN1TSeqOfList ASN1T_<name>;

The type definition of the OSRTDList structure can be found in the osSysTypes.h header file. The common run-time utility functions beginning with the prefix rtxDList are available for initializing and adding elements to the list. See the C/C++ Common Run-time Reference Manual for a full description of these functions.

For C++, the ASN1TSeqOfList class is used, or, in the case of PDU types, the ASN1TPDUSeqOfList class. The ASN1TSeqOfList extends the C OSRTDList structure and adds constructors and other helper methods. The ASN1TPDUSeqOfList is similar except that it also extends the ASN1TPDU base class to add additional memory management capabilities needed by PDU types to automatically release memory on destruction. See the ASN1CSeqOfList section in the C/C++ Common Run-time Reference Manual for details on all of the methods available in this class.

Populating Linked-List Structures

Populating generated list-based SEQUENCE OF structures for the most part requires the use of dynamic memory to allocate elements to be added to the list (note that it is possible to use static elements for this, but this is unusual). The recommended method is to use the built in run-time memory management facilities available within the ASN1C runtime library. This allows all list memory to be freed with one call after encoding is complete.

In the case of C, the rtxMemAlloc or rtxMemAllocType function would first be used to allocate a record of the element type. This element would then be initialized and populated with data. The rtxDListAppend function would then be called to append it to the given list.

For C++, the compiler generates the helper methods NewElement and Append in the generated control class for a SEQUENCE OF type. An instance of this class can be created using the list element within a generated structure as a parameter. The helper methods can then be used to allocate and initialize an element and then append it to the list after it is populated.

See the cpp/sample_ber/employee/writer.cpp file for an example of how these methods are used. In this program, the following logic is used to populate one of the elements in the children list for encoding:

   ASN1T_ChildInformation* pChildInfo;
   ASN1C__SeqOfChildInformation listHelper (encodeBuffer, msgData.children);
   ...
   pChildInfo = listHelper.NewElement();
   fill_Name (&pChildInfo->name, "Ralph", "T", "Smith");
   pChildInfo->dateOfBirth = "19571111";
   listHelper.Append (pChildInfo);

In this example, msgData is an instance of the main PDU class being encoded (PersonnelRecord). This object contains an element called children which is a linked-list of ChildInformation records. The code snippet illustrates how to use the generated control class for the list to allocate a record, populate it, and append it to the list.

ASN1C also generates helper methods in SEQUENCE, SET, and CHOICE control classes to assist in allocating and adding elements to inline SEQUENCE OF lists. These methods are named new_<elem>_element and append_to_<elem> where <elem> would be replaced with the name of the element they apply to.

Generation of Temporary Types for SEQUENCE OF Elements

As with other constructed types, the <type> variable can reference any ASN.1 type, including other ASN.1 constructed types. Therefore, it is possible to have a SEQUENCE OF SEQUENCE, SEQUENCE OF CHOICE, etc.

When a constructed type or type that maps to a C structured type is referenced, a temporary type is generated for use in the final production. The format of this temporary type name is as follows:

   <prodName>_element

In this definition, <prodName> refers to the name of the production containing the SEQUENCE OF type.

For example, a simple (and very common) single level nested SEQUENCE OF construct might be as follows:

   A ::= SEQUENCE OF SEQUENCE { a INTEGER, b BOOLEAN }

In this case, a temporary type is generated for the element of the SEQUENCE OF production. This results in the following two equivalent ASN.1 types:

   A-element ::= SEQUENCE { a INTEGER, b BOOLEAN }

   A ::= SEQUENCE OF A-element

These types are then converted into the equivalent C or C++ typedefs using the standard mapping that was previously described.

SEQUENCE OF Type Elements in Other Constructed Types

Frequently, a SEQUENCE OF construct is used to define an array of some common type in an element in some other constructed type (for example, a SEQUENCE). An example of this is as follows:

   SomePDU ::= SEQUENCE {
      addresses SEQUENCE OF AliasAddress,
      ...
   }

Normally, this would result in the addresses element being pulled out and used to create a temporary type with a name equal to SomePDU-addresses as follows:

   SomePDU-addresses ::= SEQUENCE OF AliasAddress

   SomePDU ::= SEQUENCE {
      addresses SomePDU-addresses,
      ...
   }

However, when the SEQUENCE OF element references a simple defined type as above with no additional tagging or constraint information, an optimization is done to reduce the size of the generated code. This optimization is to generate a common name for the new temporary type that can be used for other similar references. The form of this common name is as follows:

   _SeqOf<elementProdName>

So instead of this:

   SomePDU-addresses ::= SEQUENCE OF AliasAddress

The following equivalent type would be generated:

   _SeqOfAliasAddress ::= SEQUENCE OF AliasAddress

The advantage is that the new type can now be easily reused if SEQUENCE OF AliasAddress is used in any other element declarations. Note the (illegal) use of an underscore in the first position. This is to ensure that no name collisions occur with other ASN.1 productions defined within the specification.

Some SEQUENCE OF elements in constructed types are inlined. In other words, no temporary type is created; instead, either the OSRTDList reference (for linked list) or the array definition is inserted directly into the generated C structure. This is particularly true when XSD files are being compiled.