Repeating Elements

Elements within a sequence definition may be declared to be repeating by using the minOccurs and/or maxOccurs facets. In this case, a C or C++ list or array container type structure is used instead of a C/ C++ element type definition. This container holds a series of objects of the element type.

If the C element type is a simple type and the maximum number of elements (maxOccurs) is less than or equal to 10,000, then an array type of the following form is used:

   struct {
      OSUINT32 n;
      ElemType elem[maxOccurs];
   }

In this definition, n is used to hold the count of element occurrences to be encoded (or that were decoded), and elem holds the actual element data values.

If either of the above conditions is not true, a linked list type is used to hold a dynamic list of the data objects. This type is OSRTDList (run-time doubly linked list). It is defined in rtxDList.h as follows:

       /* Doubly-linked list types */

       typedef struct _OSRTDListNode {
          const void* data;
          struct _OSRTDListNode* next;
          struct _OSRTDListNode* prev;
       } OSRTDListNode;
       typedef struct _OSRTDList {
          OSUINT32 count;
          OSRTDListNode* head;
          OSRTDListNode* tail;
       } OSRTDList;

There is a complete set of functions available for adding, deleting, and traversing lists of this type available in the run-time library. See the Doubly-Linked List Utility Functions section for documentation on these functions.

For C++, there are corresponding class definitions (OSRTDListClass and OSRTObjListClass) that extend the OSRTDList structure and contain constructors and methods for adding, removing, and finding items in the list.

The following example shows a sequence with two repeating elements. The first will cause an array type to be generated, the second, a list:

       <xsd:complexType name=”SeqWithArrayAndList”>
          <xsd:sequence>
             <xsd:element name=”anArray” type=”xsd:integer”
                maxOccurs=”10”/>
             <xsd:element name=”aList” type=”SomeOtherType”
                maxOccurs=”unbounded”/>
          </xsd:sequence>
       </xsd:complexType>

The C type that is generated for this XSD type is as follows:

       typedef struct SeqWithArrayAndList {
          struct {
             OSUINT32 n;
            OSINT32 elem[10];
          } anArray;
          /* List of SomeOtherType */
          OSRTDList aList;
       } SeqWithOptElem;

Note that a comment is added to the generated C structure before the list declaration to indicate what type of objects the list is to contain.

In the case of C++, a constructor is added to the generated array structure to initialize the number of elements to zero. An inline class is generated for the list variable that extends the OSRTDListClass or OSRTObjListClass and adds methods to append items to the list and retrieve items from the list:

      class SeqWithArrayAndList : public OSRTBaseType { 
         public: 
         struct anArray_array { 
            OSUINT32 n; 
            OSINT32 elem[10]; 
            anArray_array() { n = 0; } 
         } anArray; 
         /* List of SomeOtherType */ 
         class aList_list : public OSXSDComplexType { 
            public: 
            OSRTObjListClass mElemList; 
            void append (SomeOtherType* pdata); 
            void appendCopy (const SomeOtherType* pdata); 
            const SomeOtherType* getItem (int idx); 
         } aList; 
         ... 
      } ;

The linked list memory management policy is as follows:

1. If an item is appended to a list using the append method, the pointer to the item is stored directly in the list node structure (i.e. a deep-copy is not done). It is assumed that this memory was dynamically allocated using the C++ new operator. The list will assume ownership of this memory upon assignment and delete the object when the list is destroyed.

2. If an item is appended to an object list using the appendCopy method, a copy is made of the original item using the object’s built-in clone method. The list will own the memory of the cloned item and destroy it at the time the list is destroyed.

3. If a copy is made of the list, the list’s copy constructor will make a full copy of all items in the list and delete all memory upon destruction.

If the -usestl option is specified on the command line, a std::vector will be generated instead of an inner list class. The vector’s type parameter will be a pointer to the repeating type. The outer class’ copy operator, copy constructor, and destructor will copy and delete items from the vector as needed. The vector should be populated with items allocated on the free store using operator new.