Prior to calling a compiler generated encode function, an instance of the class generated by the compiler must be populated. All member variables within the generated classes are declared to be public, it is therefore possible to do direct assignments to populate the variables. Sometimes the variables are more complicated, however, and special assignment methods are generated to assist the use in populating the variables. These special cases are described below.
Atomic simple types include boolean, integer, double, decimal, and types derived from these base types. The classes generated for these types include a value member that can be assigned to directly. They also include a parameterized constructor that allows assignment through construction and an assignment operator that makes it possible to do assignment directly through the ‘=’ sign without having to use the value member. This makes assignment compatible with the C case.
For example, the following simple integer type declaration:
<xsd:simpleType name="EmployeeNumber"> <xsd:restriction base="xsd:integer"/> </xsd:simpleType>
causes a class with the following constructors and assignment operator to be generated:
class EmployeeNumber : public OSRTBaseType { public: OSINT32 value; EmployeeNumber (); EmployeeNumber (OSINT32 value); EmployeeNumber& operator= (OSINT32 value);
This makes it possible to assign an employee number in any of the following ways:
EmployeeNumber empno (33);
or
EmployeeNumber empno; empno.value = 33;
or
EmployeeNumber empno; empno = 33;
Character string types are derived from the built-in base class OSXMLStringClass. This class is in turn derived from the OSXMLSTRING C struct type which contains a value member character pointer variable.
An example of the constructors and assignment operators generated for a character string type is shown for the following definition:
<xsd:simpleType name="Date"> <xsd:restriction base="xsd:string"/> </xsd:simpleType>
The C++ constructors and assignment operators generated for this definition are as follows:
class EXTERN Date : public OSXMLStringClass { public: Date (); Date (const OSUTF8CHAR* value); Date (const char* value); Date& operator= (const OSUTF8CHAR* value); Date& operator= (const char* value);
Note that constructors and operators are available that allow strings to be specified as either standard C character strings or as UTF-8 strings.
Assignment of strings always causes a deep-copy of the character data to be done.
Classes generated for enumerated types contain setValue methods[2] that allow the contained value member variable to be set. Two overloaded forms of this method are present: one that takes the enumerated identifier and one that takes a string representation of the value. A method is also generated to allow the value to be retrieved as a number (getValue) or as a string (toString).
The signatures for these methods is as follows:
normal | with -noenumvars |
---|---|
inline Enum getValue () const { return value; } int setValue (Enum enumval); int setValue (const OSUTF8CHAR* strval); const OSUTF8CHAR* toString () const; |
inline OSUINT16 getValue () const { return value; } int setValue (OSUINT16 enumval); int setValue (const OSUTF8CHAR* strval); const OSUTF8CHAR* toString () const; |
Binary string are used to represent XSD hexBinary and base64Binary data types. A dynamic binary string type (i.e. one that is not constrained by a length facet) is derived from the OSDynOctStrClass base class. This class allows value assignment through constructors and copyValue and setValue methods.
The constructors allow a binary string to be specified using data pointer and number of octets arguments. The copyValue method is used to make a copy of the given string and assign it to the class. The setValue method also makes a deep-copy of the given data string.
Classes generated for <xsd:sequence> or <xsd:all> complex types contain a series of public element declarations for each of the elements in the declaration. These are populated using either direct assignment or the methods available in the element type classes. If atomic types are used for elements, the primitive type itself is used in the generated class, not a class derived from the type. For example, if a sequence contains an element declared to be an <xsd:integer>, the OSINT32 type is used for the member variable.
Classes generated for the <xsd:choice> complex type will contain methods to get, set, or query each of the choice selection elements. The format of these methods is get_<name>, set_<name>, or is_<name> where <name> would be replaced with the actual element name as defined in the schema.
Content model groups that repeat (i.e. have a maxOccurs facet with a value greater than one) cause a class to be generated that is derived from the OSRTObjListClass base class. This class contains append and appendCopy methods for adding elements to the list. An example of what these methods look like is given in the ‘Dynamic Memory Management’ section above. This method allows memory ownership for the object being added to the list to be tranferred to the list object. Note that this can be done on a per-element basis making it possible to mix and match dynamic and static element declarations in a given list.
Message buffer or stream classes are used to describe the source from which a message is being decoded or the target to which a message is being encoded. The base interface for these classes is OSRTMessageBufferIF. Classes for message buffers or streams specific to encoding or decoding and for different encoding rules (for example, XML) are derived from this base class. An instance of one of these derived classes along with an instance of the class generated for a particular XSD type are needed to encode or decode a message.
Message buffers for encoding can be either static or dynamic. A static buffer is simply a byte array in memory. It is generally the better performing case because no dynamic memory allocations are required. However, the user must know in advance the amount of memory that will be required to hold an encoded message. There is no fixed formula to determine this number. XML encoding involves the additions of tags and attributes and other decorations to the provided data that will increase the size beyond the initial size of the populated data structures. The way to find out is either by trial-and-error (an error will be signaled if the provided buffer is not large enough) or by using a very large buffer in comparison to the size of the data. A static buffer is described using a message buffer class object by passing the byte array address and size to the constructor.
A dynamic buffer is specified by using the default constructor. This tells the encoder that it is to allocate memory for the message. It does this by allocating an initial amount of memory and when this is used up, it expands the buffer by reallocating. This can be an expensive operation in terms of performance, especially if a large number of reallocations are required. Special methods are provided that allow the initial and incremental allocation sizes to be tuned for better performance. See the runtime class reference guide for further details on this.
In either case, after a message is encoded, it is necessary to get the start address and length of the message. In the static buffer case for XML, the start address of the message is simply the start address of the buffer. But in the dynamic case, a function call is required to get the start address of the message after encoding is complete. The getMsgPtr method is provided for this purpose.
[2] The method signatures have changed in version 2.2.2 See the discussion of Enumerated Types for more information.