TOP

Important Concepts

Transferring Ownership

A representation object always owns its entire contents (unlike coding objects discussed in the previous chapter). This means that if a representation object is complex and has other representation objects inside, these component objects are automatically destroyed when the container object is destroyed. Pointer aliasing between component objects (i.e., sharing common parts between representation objects) is not allowed. The basic constructors and mutators of the representation classes ensure this by always making a deep copy of the input object. The input object itself remains intact. If you do not use ownership-transferring functions (see below), the ownership rule for representation objects is simple: if you allocated it, you must deallocate it; if you did not allocate it, you must not deallocate it.

Although this rule is simple to observe, always making deep copies may result in unsatisfactory performance, especially when the structures being copied are large and complex. To help improve the performance, we provide ownership-transferring functions for most types. These functions allow you to set a component of a constructed object, without deep copying, simply by pointer assignment. You may continue to reference the input object and to change it. All changes in the input object will be automatically reflected to the container object, because the input object becomes a part of it. You must not deallocate the input object even if you have allocated it yourself. It is now owned by the container object and will be deallocated when the container object is destroyed.

If you plan to use an object as an input object of an ownership-transferring function, this object must be allocated dynamically with the C++ new operator. An attempt to use a static or automatic variable as an input object in an ownership-transferring function will give unpredictable results.

There are also reverse ownership-transferring functions that allow you to grab the ownership of a complex object component, so it becomes independent of the container object. You become responsible for deallocating the component object when it is no longer needed. The delete operator must do the deallocation.

Ownership-transferring functions for predefined classes (such as OssString) are readily available. To have the compiler generate ownership-transferring methods for some component of a constructed type (SEQUENCE, SET, CHOICE, SEQUENCE OF, or SET OF) defined in your ASN.1 specification, you should apply the --<POINTER>-- directive to this component (see The Effect of the POINTER Directive). When an ASN.1 type is used as a component of several constructed types, it is usually useful to apply the --<POINTER>-- directive to the definition of the component type, for example

A ::= OCTET STRING --<POINTER>--
B ::= SEQUENCE {
    a A,
    b INTEGER
   }
C ::= SET OF A

This is equivalent to applying the --<POINTER>-- directive to each occurrence of A as a component of some constructed type, as follows.

A ::= OCTET STRING
B ::= SEQUENCE {
    a A --<POINTER>--,
    b INTEGER
    }
C ::= SET OF A --<POINTER>--

This feature is useful because the main purpose of the ownership-transferring methods is to avoid copying large structures. If you want to avoid this copying somewhere, you probably want to avoid it everywhere.

NOTE: The --<POINTER>-- directive has an effect only when the type is used as a component of a constructed type. It does not affect the representation of the type itself (unlike the representation in the OSS ASN.1/C Tools).

Note that the --<POINTER>-- directive is ignored for the simple types BOOLEAN, ENUMERATED, INTEGER, NULL, REAL, and time (GeneralizedTime, UTCTime, and ISO 8601 time types). There is no sense in having ownership-transferring functions for these types because copying the values of these types is equally fast or perhaps even faster than copying pointers.

typedef Declarations

Whenever an ASN.1 module's type refers to a basic type defined in the asn1.h file, the compiler uses a typedef declaration to create a new synonym for the basic type. There may be cases when two or more ASN.1 types are of identical structure. In this case, to reduce the generated code size, the ASN.1 C++ compiler can also use a typedef to define the duplicate classes as 'synonyms'.

Memory Allocation

The ASN.1/C++ Runtime performs memory allocation and deallocation for representation types via calls to asn1Malloc(), asn1Realloc(), and asn1Free(). By default, these functions are defined to simply call malloc(), realloc(), or free(), respectively, but you can define different behaviors for them using Memory Management Classes if you prefer non-standard memory management. For all representation classes (i.e., not built-in types such as int), the new and delete operators are redefined to use asn1Malloc() and asn1Free(), so you can (and should) use these operators.

Be careful when using the ownership-transferring functions (see Transferring Ownership). Objects that will be used as the input objects of the ownership-transferring functions must be suitable for subsequent runtime operations, i.e., they must be dynamically allocated by the new operator.

If an object is not to be used as an input object for the ownership-transferring functions, there are no additional requirements on it. So, it can be static, automatic, or dynamically allocated by any means (in the last case the user is responsible for deallocating it appropriately).

Several functions return pointers to char (i.e., string values). It is explicitly stated for each function of such a kind whether the user is responsible for freeing memory blocks referred to by such pointers or the function returns a pointer to an internal buffer that must not be explicitly freed.

As said above, the C++ new operator for representation classes is redefined to call asn1Malloc(). Some C++ compilers (e.g., older versions of g++) do not tolerate the new operator returning 0. If such a situation occurs, they call the constructor with this == 0, which results in a core dump. If you are using such a C++ compiler and want to make your application be robust in insufficient memory situations, we strongly suggest you implement your own error processing using C++ exceptions (see Compatibility Error Handling Mode).

Note: Decoding into a preallocated memory buffer creates unusual representation objects, each part of the objects uses memory from the same contiguous memory buffer. However, these unusual objects are handled as constants, so the application is prevented from changing them.The application can corrupt these objects only by using unsafe methods, such as typecasts.

Interaction between Coding and Representation Classes

Below is an explanation of the general way a user program should be written. The Sample Encoding Program is used to illustrate this.

  1. The very first step is to create an encoding/decoding environment and to properly tune it. The lines
    bcas_Control ctl;          /* Control table object */
    [...]
    ctl.setEncodingFlags(DEBUGPDU);
    ctl.setDecodingFlags(DEBUGPDU);
    serve this goal. The corresponding control object is instantiated; the encoding and decoding flags are explicitly set.
  2. The next step is to create the representation class instance and the corresponding coding object, as well as a buffer to hold the encoded data. It is not important which is allocated first. The sample source lines show that:
    BBCard_PDU pdu;           /* PDU object for data */
    [...]
    /* Create a copy of value notation */
    BBCard myCard_copy(myCard);
    [...]
    EncodedBuffer encodedData;     /* a buffer for encoded data */
    
    Here the representation object is created by copying an existing (constant) value. However, one can create an instance of a representation class and assign the necessary values to the fields. In this case, the code would look like
    BBCard_PDU pdu;           /* PDU object for data */
    
    BBCard myCard_copy;     /* Creating empty instance (all fields are set to zero) */
    myCard_copy.get_name().set("Casey");
     /* get_name() returns 'name&' - 'OssString&'; the last
              function call sets its contents from the C string specified */
    myCard_copy.set_age( 32 );
    
    and so on. In the example above, the two fields set explicitly are set to non-zero values; the rest of the BBCard fields are zero (or equivalent, NULL, and so on).
  3. The next step illustrates how the data (contents) of a representation object are encoded. The following lines from the Sample Encoding Program
    if (pdu.encode(ctl, encodedData)) {
      /* an error occurred, print errmsg */
      printf("%s\n", ctl.getErrorMsg());
      return 1;
    } else
      printf("\nCard encoded.\n"); /* card was successfully encoded */
    
    show how it's done. Note that in real life the error handling code (the 'if' block of the code above) should correctly deallocate dynamically allocated objects.
  4. Decoding of the encoded data (in this case, residing in the same buffer) is also performed simply:
    if (pduDecoded.decode(ctl, encodedData)) {
      /* an error occurred, print errmsg */
      printf("%s\n", ctl.getErrorMsg());
      return 1;
    } else
      printf("\nCard decoded.\n");  /* card was successfully decoded */
    
    /* Get data from PDU object */
    BBCard *myCardPtr = pduDecoded.get_data(); /* address of decoded data */
    
    Note that the representation class instance is created by a PDU coding class get_data() method. Also, the user owns the object pointed to by myCardPtr; this object should be manually deleted.

A representation class is used to store the data for ASN.1 type, making the data available for user applications. The corresponding coding classes are used to encode/decode these data. The type of buffer used varies from application to application (if, for example, encoded data is to be transmitted via Internet, the EncodedSocket type of buffer might be used).

Methods Common to all Representation Classes

Each representation class (generated or defined in asn1.h) has the following methods:

  • The default constructor creates a representation object whose value is a zero-byte pattern. Such a value is guaranteed to be destroyed properly, but there is no guarantee that it represents a valid ASN.1 value as this depends on the exact ASN.1 type that the object represents. If it is not valid, set the created object to any valid value before trying to use it.
  • The copy constructor creates a copy of the source value. The copy constructor makes a deep copy of the source information; the source and the destination objects share no common parts. The source object remains intact.
  • The assignment operator makes a deep copy of the source object, like the copy constructor. The old value of the destination object is deallocated. Although some memory may be reused, you should not rely on this facility.
  • The destructor deallocates all components of the object (if there are any). Representation classes always own their components.
  • The equality operator (=) can be used to compare two objects of the same representation type. It returns 1 if both objects represent the same value and 0 if the represented values are different or some error occurred during the comparison.
  • The inequality operator (!=) is simply a logical negation of the equality operator.

For brevity, we will not specifically state their existence for each class throughout this document.

NOTE: For implementation efficiency, the equality operator compares binary representations in memory rather than abstract ASN.1 values. This means that in some cases different representations of the same ASN.1 value could be considered different. For example, SET OFs are compared as if they were SEQUENCE OFs, with the order of the elements taken into account. The ASN1Handle::equals function does a more correct comparison from the ASN.1 point of view. However, it is much less efficient than the equality operator.

Constraint Checking

Representation classes do not perform constraint checking. Constraints are checked only when you are trying to encode or decode a value using coding types; the ASN1Handle::check_constraints() function exists just for this purpose. In addition, alphabet restrictions for OssString types will be checked only at encoding/decoding time. You can set any byte string to an OssString object, regardless of the ASN.1 character string type it represents. This allows the compiler to share one representation class for several ASN.1 types differing by constraints. As a result, the size of the generated code is reduced.

NOTE: Keep in mind that you can set an object to a value that is invalid, according to the source ASN.1 specification, and be sure to check the validity of the value when necessary.

Integer Types

ASN.1/C++ defines the following integer types, which are guaranteed to have the same size on any platform:

Integer Type Size
OSS_INT16 16-bit signed integer (short on most platforms)
OSS_UINT16 16-bit unsigned integer (unsigned short on most platforms)
OSS_INT32 32-bit signed integer (long on most platforms)
OSS_UINT32 32-bit unsigned integer (unsigned long on most platforms)
LONG_LONG 64-bit signed integer on platforms that support it
ULONG_LONG 64-bit unsigned integer on platforms that support it

These types are used for representing the ASN.1 INTEGER type in C++. They are also used as parameters for some ASN.1/C++ API functions.


Simple Types

Simple ASN.1 types are represented in ASN.1/C++ with primitive C++ types. This helps to avoid unnecessarily bloating the generated code. The following table provides a list of ASN.1 types represented with primitive C++ types.

ASN.1 Type Corresponding C++ Built-in Type
BOOLEAN ossBoolean (a typedef of char)
ENUMERATED enum
INTEGER (without OSS.HUGE) OSS_INT32, OSS_UINT32, OSS_INT16, OSS_UINT16, LONG_LONG, ULONG_LONG
NULL Nulltype (a typedef of char)
REAL (without OSS.DECIMAL) double

All other ASN.1 types are represented by C++ classes.

The ASN.1/C++ Runtime allocates and deallocates values of primitive types using explicit asn1Malloc() and asn1Free() calls, respectively. The new and delete operators for primitive types are not redefined. You need to keep this in mind, e.g., if a primitive type is used as a PDU.


SEQUENCE and SET Types

For each field the compiler generates an inner type definition named after the field. It will be a typedef of either a primitive type (see above) or the corresponding class. This class represents the ASN.1 type that is a value type of this field. For example, given the following ASN.1 definition:

ASN.1 C++
A ::= SEQUENCE {
       a INTEGER,
       b SEQUENCE {
            c INTEGER,
            d IA5String
       }
}
class OSS_PUBLIC __seq1    /* SEQUENCE */
{
public:
        . . .
  typedef OSS_INT32 c;
  typedef OssString d;
        . . .
}

class OSS_PUBLIC A   /* SEQUENCE */
{
public:
        . . .
    typedef OSS_INT32 a;
    typedef __seq1 b;
        . . .
}

The user is supposed to reference the anonymous SEQUENCE type as A::b. The _seq1 name is for internal use and the user should not use it explicitly. This generated name can be different in different versions of the ASN.1/C++ compiler. The user can also reference INTEGER as A::a or B::c.

For brevity, the interfaces of the generated methods are written below under the assumption that the components are of complex types. If a component is of a primitive type (such as int), the interface to the generated methods is slightly different: whenever const FieldType & is written in the document, FieldType is used in the generated code (for greater efficiency). For example, if you have the following ASN.1 specification: Note the difference between the methods generated for a and b.

ASN.1 C++
A ::= SEQUENCE {
     a INTEGER,
     b IA5String
}
class OSS_PUBLIC A   /* SEQUENCE */
{
public:
        . . .
    typedef OSS_INT32 a;
    typedef OssString b;

    A();
    A(const A &);
    A(a, const b &);
        . . .
    a & get_a();
    a get_a() const;
    void set_a(a);

    b & get_b();
    const b & get_b() const;
    void set_b(const b &);
        . . .
};

Definition

The following definition is a list of all possible functions that can be generated for a SEQUENCE Type. The name SeqType is derived from the name of the ASN.1 SEQUENCE type.

class SeqType {
public:
  // new and delete operators
  void * operator new(size_t size);
  void operator delete(void *ptr);


  // Typedef'ed fields list
  typedef Field1Type field1;
  typedef Field2Type field2;
   …
  typedef FieldNType fieldn;

  // Constructors [and destructor if needed]
  SeqType(const SeqType &that);
  SeqType(const Field1Type & field1, const Field2Type & field2, ..., const FieldNType & fieldN);
  ~SeqType();

  // Operators: assignment, equality, inequality
  SeqType & operator = (const SeqType &that);
  SeqType & operator == (const SeqType &that);
  SeqType & operator != (const SeqType &that);

  // For each field: methods to access and/or modify it
  // (when OPTIONAL and DEFAULT are not used)
  FieldType & get_<field>();
  const FieldType & get_<field>() const;
  void set_<field>(const FieldType &);

  // Methods for each OPTIONAL field
  FieldType * get_<field>();
  const FieldType * get_<field>() const;
  int <field>_is_present() const;
  void set_<field>(const FieldType &);
  void omit_<field>();

  // Methods for each DEFAULT field
  FieldType * get_<field>();
  const FieldType * get_<field>() const;
  static const FieldType & get_default_<field>() const;
  int <field>_is_default() const;
  void set_<field>(const FieldType &);
  void set_default_<field>();

  // Additional functions generated when field
  // defined with POINTER directive
  void set_<field>(FieldType *);
  FieldType *release_<field>();

  // Additional functions generated when the field is extensible
  // and the -relaySafe option is specified
  OssExtensions * get_UnknownExt();
  const OssExtensions * get_UnknownExt() const;
  void set_UnknownExt(const OssExtensions &);
  int UnknownExt_is_present() const;
  void omit_UnknownExt();
};

Constructors and Destructor

Additional constructors (except the standard default and copy constructor) are generated for each SEQUENCE or SET:

SeqType(const Field1Type & field1, const Field2Type & field2, ..., const FieldNType & fieldN);
This method creates an initialized SEQUENCE/SET. The parameter values are copied into the corresponding SEQUENCE/SET fields. The parameter objects remain unchanged.

The following constructor is generated if the SEQUENCE/SET has any OPTIONAL or DEFAULT components:

SeqType(const Field1Type & field1, const Field2Type & field2, ..., const FieldMType & fieldM);
This method creates an initialized SEQUENCE/SET. The parameters are copied into the corresponding SEQUENCE/SET fields. The parameter objects remain unchanged. Each OPTIONAL component is marked as absent; each component with a DEFAULT value is set to the default. Only non-OPTIONAL and non-DEFAULT fields are present in the parameter list.

The following constructors are generated if the SEQUENCE or SET has any components with the --<POINTER>-- directive applied:

SeqType(const Field1Type & field1, Field2Type * field2, ..., const FieldNType & fieldN);
This method creates an initialized SEQUENCE/SET. The const-reference parameter values are copied into the corresponding SEQUENCE/SET fields. The pointer parameters become the corresponding SEQUENCE/SET fields without copying. The pointer parameters must point to dynamically allocated objects (allocated by the user using the new operator or obtained by a decode() or release_<field>() call). This is an ownership-transferring constructor. After return, the objects passed as "pointer" parameters become owned by the SEQUENCE/SET object. The user must not explicitly deallocate them or use them in any other ownership-transferring functions. If a field has the --<POINTER>-- directive applied, the corresponding parameter has the FieldType *type, otherwise it has the const FieldType &type.
SeqType(const Field1Type & field1, Field2Type * field2, ..., const FieldMType & fieldM);
This method is similar to the previous constructor but only non-OPTIONAL and non-DEFAULT fields are set from the parameters. Each OPTIONAL component is marked as absent; each component with a DEFAULT value is set to the default. Only non-OPTIONAL and non-DEFAULT fields are present in the parameter list; if a field has the --<POINTER>-- directive applied, the corresponding parameter has the FieldType * type, otherwise it has the const FieldType &type.

Methods

Non-OPTIONAL, Non-DEFAULT Fields
FieldType & get_<field>();
const FieldType & get_<field>() const;
These methods return a reference to the field value. The returned object is a part of the SEQUENCE/SET. The user should not delete it.

If the --<POINTER>-- directive is applied to the component, there may be situations when the value of the component is a NULL pointer. Such a value does not represent a valid ASN.1 value, but it may occur, for example, when the object has just been created with the default constructor, or an attempt to allocate a memory block for the component has failed. In such a situation, an attempt to access the value of the component with the get_<field> function is incorrect, and the function signals the OSS_DATA_MISSING error using the ASN.1/C++ error reporting mechanism (see Error Handling).
void set_<field>(const FieldType &);
This method copies the object passed as the parameter to the SEQUENCE/SET field. A deep copy is performed; the original object remains unchanged and owned by the caller. The previous value of the field is deallocated.
OPTIONAL Fields
FieldType * get_<field>();
const FieldType * get_<field>() const;
These methods return a pointer to the field value. The returned object is a part of the SEQUENCE/SET. The user should not delete it. If the field is absent, a NULL pointer is returned.
void set_<field>(const FieldType &);
This method copies the object passed as the parameter to the SEQUENCE/SET field. A deep copy is performed; the original object remains unchanged and owned by the caller. The field is marked as present (if it wasn't before the call). The previous value of the field is deallocated.
int <field>_is_present() const;
This method returns 0 if the field is absent, and 1 otherwise.
void omit_<field>();
This method marks the field as absent. If it was present before the call, the previous value of the field is deallocated.
DEFAULT Fields

Although it contradicts ASN.1 semantics, the OSS ASN.1 Tools for C++ makes a distinction between a field value having the DEFAULT value and a field value having a non-DEFAULT value equal to the DEFAULT value (see below for details). This distinction is made for implementation efficiency.

static const FieldType & get_default_<field>() const;
This method returns a reference to a constant object that represents the DEFAULT value for the field.
FieldType * get_<field>();
const FieldType * get_<field>() const;
These methods return a pointer to the field value. The returned object is a part of the SEQUENCE/SET. The user should not delete it. If the field has a DEFAULT value, a NULL pointer is returned. If the user wants to access the default value, he/she can obtain it by the get_default_<field>() function.
void set_<field>(const FieldType &);
This method copies the object passed as the parameter to the SEQUENCE/SET field. A deep copy is performed; the original object remains unchanged and owned by the caller. The field is marked as non-DEFAULT (if it wasn't before the call), even if the value being assigned is equal to the default value. The previous value of the field is deallocated.
int <field>_is_default() const;
This method returns 1 if the field has the DEFAULT value, 0 otherwise. Note that if the value was set by, say, the set_<field>(<field_default>) call, it is not considered a DEFAULT value, and the function returns 0. The only way to mark a field as DEFAULT is to call the set_default_<field>() function.
void set_default_<field>();
This method marks the field as DEFAULT. The previous value of the field is deallocated.
The Effect of the --<POINTER>-- Directive

The --<POINTER>-- directive does not affect the representation of the type to which the directive is applied. However, when a type with such a directive is used as a field of a SEQUENCE/SET, two extra ownership-transferring methods are generated for this field.

void set_<field>(FieldType *);
This method assumes that the object the parameter points to is a dynamic object owned by the caller (e.g., allocated by the user using the new operator, or obtained by a decode() or release_<field>() call). If the parameter points to a static or automatic object, the result will be unpredictable. The field is set to the value pointed to by the pointer. The previous value of the field is deallocated. The operation is done by simple pointer assignment, without deep copying. The object passed to the function becomes owned by the SEQUENCE/SET object. The pointer remains valid, the user can use it to access the field but must not deallocate it or pass it to any ownership-transferring function.
FieldType *release_<field>();
This method extracts the field value from the container and returns a pointer to the extracted value. The value becomes owned by the caller; the caller is responsible for deallocating it using the delete operator. The field value is removed from the container. If the field is OPTIONAL, it is marked as absent. If the field has a DEFAULT value, it is marked as the default. If the field is defined as non-OPTIONAL, it is set to a NULL pointer. Note that NULL is not a valid value for the field in this case. You should set it to a valid value before trying to use the SEQUENCE object. If the field is absent (in the case of an OPTIONAL field) or has the DEFAULT value (in the case of a DEFAULT field), the function returns a NULL pointer and the SEQUENCE/SET value is unchanged.
Effect of the Extensibility Marker and the -relaySafe Option

If a SEQUENCE/SET is extensible, the input encoding may contain extension additions that are not mentioned in the input ASN.1 specification. By default, such additions are simply ignored by the decoder. However, the -relaySafe compiler option instructs the decoder to save these unknown extension additions in a special field of the binary object in the undecoded form, so they will be copied into the encoder's output if the decoded binary object is passed to the encoder (see the OSS ASN.1 Compiler for C++ Reference Manual). Usually, there is no need to access these unknown additions in the application code, because they are unknown by definition and the application can only pass them to the encoder without any modifications. However, the ASN.1/C++ API permits the user to access the unknown extension additions if needed.

If a SEQUENCE/SET is extensible, and the –relaySafe compiler option is specified, the compiler generates an additional set of methods for the corresponding class:

OssExtensions * get_UnknownExt();
const OssExtensions * get_UnknownExt() const;
These methods return a pointer to the OssExtensions object. The returned object is a part of the SEQUENCE/SET. The user should not delete it. If there are no unknown extension additions, a NULL pointer is returned.
void set_UnknownExt(const OssExtensions &);
This method copies the object passed as the parameter to the SEQUENCE/SET as unknown extensions. A deep copy is performed; the original object remains unchanged and owned by the caller. This way the user can copy unknown extension additions from one decoded object to another one.

Note: If you want to remove the unknown extension additions from a SEQUENCE/SET, you should use the omit_UnknownExt method. Using set_UnknownExt with an empty OssExtensions object does not work – the encoder will give an error on the resulting object.
int UnknownExt_is_present() const;
This method returns 1 if unknown extension additions are present in the object, and 0 otherwise.
void omit_UnknownExt();
Removes all the unknown extension additions from the object.

CHOICE Types

Similar to SEQUENCE/SET, the compiler generates a class for each CHOICE type in the input specification. An inner typedef is created inside the class for each CHOICE alternative.

For this example ASN.1

A ::= CHOICE {
    a INTEGER,
    b IA5String
   }

The following typedefs are generated inside the A class:

class A {
  typedef OSS_INT32 a;
  typedef OssString b;
  ...
};

For each CHOICE, an enumerated is generated:

enum {
  unselected,
<alt1>_chosen,
    ...
<altn>_chosen

};

Where <alt1>...<altn> are names of the CHOICE alternatives. Members of the above enumeration are used to denote the currently selected alternative.

Similar to SEQUENCE/SET, the interfaces of generated methods are written below assuming that the components are of complex types. If a component is of a simple type (such as int), the interfaces of generated methods are slightly different: whenever const FieldType & is written in the document, FieldType is used in the generated code for greater efficiency. For example, the the following class is generated for the ASN.1 specification above. Note that code irrelevant to the issues being discussed is omitted.

class A : public OssChoice {
public:
  enum Id {
    unselected,
    a_chosen = 1,
    b_chosen = 2
  };
  typedef OSS_INT32 a;
  typedef OssString b;

  A();
  A(const A &);
  ~A();

  a * get_a();
  const a * get_a() const;
  void set_a(a);

  b * get_b();
  const b * get_b() const;
  void set_b(const b &);
};

Note the difference between the set_a and set_b method interfaces.

Definition

The following definition is a list of all the possible functions that can be generated for a CHOICE Type. The name ChoiceType is derived from the name of the ASN.1 CHOICE type. The definition below refers to AltType and altname as the type and the name of a particular CHOICE alternative. For example, AltType would be OSS_INT32 or OssString in the example above, and altname would be a or b.

class ChoiceType : public OssChoice {
public:
// Enumeration and Typedef'ed members list
enum Id {
        unselected,
<altname1>_chosen = 1,
<altname2>_chosen = 2,
        ...
<altnamen>_chosen = n
     }
typedef AltType1 <altname1>;
typedef AltType2 <altname2>;
...
typedef AltTypen <altnamen>;

  // Constructors [and destructor]
  ChoiceType();
  ChoiceType(const ChoiceType & that);
  ~ChoiceType();

  // Operators: assignment, equality, inequality
  ChoiceType & operator = (const ChoiceType & that);
  int operator == (const ChoiceType & that) const;
  int operator != (const ChoiceType & that) const;

  // Selection/access methods for each field
  AltType * get_<altname>();
  const AltType * get_<altname>() const;
  void set_<altname>(const AltType &);

  // Additional methods for each field with POINTER directive
  void set_<altname>(AltType *);
  AltType *release_<altname>();

  // Additional methods generated when the field is extensible
  // and the -relaySafe option is specified
  OssAlternative * get_UnknownAlt();
  const OssAlternative * get_UnknownAlt() const;
  void set_UnknownAlt(const OssAlternative &);
};
OssChoice Class

The OssChoice class is a common ancestor for all the CHOICE classes generated by the compiler. It has a private constructor and cannot be instantiated by the user. It contains common code used for all CHOICE types and provides implementation for the new and delete operator (so the compiler does not generate them separately for each CHOICE type). Besides those operators, it has only one user-accessible function:

OSS_UINT32 get_selection() const;
This method returns an integer value, which signifies the currently selected alternative. The meaning of the values is defined by the inner enumeration generated inside any specific CHOICE class. I.e., a_chosen means that the alternative a is currently selected, etc.
Methods
const AltType * get_<altname>() const;
AltType * get_<altname>();
This method returns a pointer to the current alternative value assuming that the alternative altname is currently selected. If any other alternative is selected, NULL is returned. The returned pointer points inside the CHOICE object, so that the returned object is still owned by the CHOICE object. You must not delete the returned object or pass it to any ownership-transferring function.
void set_<altname>(const AltType &);
Copies the object passed as a parameter to the SEQUENCE/SET field. A deep copy is performed; the original object remains unchanged and owned by the caller. The altname alternative becomes selected. The previously selected alternative value is deallocated.

If the --<POINTER>-- directive is applied to an alternative, the following two additional methods are generated for this alternative:
void set_<alt>(AltType *);
It is assumed that the object that the parameter points to is a dynamic object owned by the caller (e.g., allocated by the user using the new operator, or obtained by a decode() or release_<alt>() call). If the parameter points to a static or automatic object, the result will be unpredictable. The alt alternative becomes selected and is set to the value pointed to by the pointer. The previously selected alternative value is deallocated. The operation is done by simple pointer assignment, without deep copying. The object passed to the function becomes owned by the CHOICE object. The pointer remains valid. The user can access the alternative value via the pointer but must not deallocate the alternative value or pass it to any ownership-transferring function.
AltType *release_<alt>();
This method extracts the current value of the alt alternative from the CHOICE and returns a pointer to the extracted alternative. The object returned by the call is owned by the caller. The caller is responsible for deallocating it using the delete operator. The CHOICE value is set to the unselected state. If any alternative other than alt is currently selected, the NULL pointer is returned and the CHOICE value is unchanged.
Effect of the Extensibility Marker and the -relaySafe Option

If a CHOICE is extensible, the input encoding may contain an alternative that is not mentioned in the input ASN.1 specification. If the -relaySafe compiler option was specified, the decoder saves this unknown alternative in the binary object in the undecoded form, so it will be copied into the encoder's output if the decoded binary object is passed to the encoder (see the OSS ASN.1 Compiler for C++ Reference Manual). Usually, there is no need to access this unknown alternative in the application code, because it is unknown by definition and the application can only pass it to the encoder without any modifications. However, the ASN.1/C++ API permits the user to access the unknown alternative if needed.

If a CHOICE is extensible, and the –relaySafe compiler option is specified, the compiler generates an additional set of methods for the corresponding class:

OssAlternative * get_UnknownAlt();
const OssAlternative * get_UnknownAlt() const;
These methods return a pointer to the OssAlternative object. The returned object is a part of the CHOICE. The user should not delete it. If a known alternative is selected, a NULL pointer is returned.
void set_UnknownAlt(const OssAlternative &);
This method copies the object passed as the parameter to the CHOICE as the unknown alternative. A deep copy is performed; the original object remains unchanged and owned by the caller. This way the user can copy the unknown alternative from one decoded object to another one.

SEQUENCE OF and SET OF Types

For brevity, we are using SEQUENCE OF in this chapter. the OSS ASN.1 Tools for C++ presents an identical interface for both SET OF and SEQUENCE OF types, so the entire contents of this chapter are valid for SEQUENCE OF as well as for SET OF types. Note that the encodings of SET OF and SEQUENCE OF types may probably be still different depending on the encoding rules used.

NOTE: A general note about the interface of generated methods: like the SEQUENCE/SET, they are written under the assumption that the components are of complex types. If a component is of a simple type (such as int), whenever const FieldType & is written in the document, FieldType is generated instead for better efficiency.

To access components of a SEQUENCE OF type, the user can use an iterator-like type named OssIndex. It can be created and manipulated only by methods of SEQUENCE OF types. OssIndex objects can be copied and tested for equality. No other actions with OssIndex objects are allowed to the user. We can say that an OssIndex "belongs" to a particular SEQUENCE OF if it was created by its method. It is an error to use an OssIndex object with a SEQUENCE OF other than one to which it belongs. The result of such an attempt is unpredictable.

There is a special OssIndex value named OSS_NOINDEX that is used to signal that a SEQUENCE OF operation has failed. It is an error to use an OSS_NOINDEX value in any SEQUENCE OF operation unless explicitly stated otherwise.

OssIndex represents some position in a particular SEQUENCE OF. Operations that change the contents of a SEQUENCE OF can invalidate certain OssIndex values. In particular, the assignment of a new value to the SEQUENCE OF as a whole invalidates all OssIndex values belonging to the destination SEQUENCE OF.

On the other hand, setting a SEQUENCE OF component to a new value does not invalidate any OssIndexes. An attempt to use an invalidated OssIndex value has unpredictable results, like an attempt to use an invalidated pointer.

Definition

The following definition is a list of all the possible functions that can be generated for a SEQUENCE OF Type. The name SeqOfType is derived from the name of the ASN.1 SEQUENCE OF type.

class SeqOfType : public OssList {
public:
  typedef Type component;


  // Constructors and destructor
  SeqOfType();
  SeqOfType(const SeqIntType & that);
  ~ SeqOfType();

  // Operators: assignment, equality, inequality
  SeqOfType & operator = (const SeqOfType & that);
  int operator == (const SeqOfType & that) const;
  int operator != (const SeqOfType & that) const;

  // Component methods
  component * at(OssIndex pos);
  const component * at(OssIndex pos) const;
  OssIndex prepend(const component &val);
  OssIndex prepend(SeqOfType * seq);
  OssIndex insert_after(OssIndex pos, const component &val);
  OssIndex insert_after(OssIndex pos, SeqOfType * seq);
  int remove_front();
  int remove_after(OssIndex pos);
  SeqOfType * extract_after(OssIndex begin, OssIndex end);

  // Additional component methods when POINTER directive is used
  int replace(OssIndex, component *);
  component * extract_after(OssIndex);
  component * extract_front();
};

An inner typedef is generated for the component type of the SEQUENCE OF, so you can reference the component type as SeqofType::component. This is especially useful if the component has an anonymous type. In this case, a compiler-constructed name is generated for the component class, but it is not guaranteed to be the same for different versions of the ASN.1/C++ compiler. It is recommended that such anonymous types be referenced as Seqof::component instead of by using the compiler-constructed name.

OssList Class

The OssList class is a common ancestor for all the SEQUENCE OF/SET OF classes generated by the compiler. It has a private constructor and cannot be instantiated by the user. It contains common code used for all SEQUENCE OF/SET OF classes and provides implementation of the new and delete operators (so the compiler does not generate them separately for each SEQUENCE OF/SET OF type). In addition to those operators, it has the following user-accessible functions:

int empty() const;
This method returns 1 if the SEQUENCE OF is empty, and 0 otherwise.
OssIndex first() const;
This method returns an OssIndex value for the first SEQUENCE OF element. If the SEQUENCE OF is empty, OSS_NOINDEX is returned.
OssIndex next(OssIndex) const;
This method returns an OssIndex value that represents the next position relative to the OssIndex value passed as the parameter. If the parameter points to the last SEQUENCE OF element, OSS_NOINDEX is returned.

Methods

Any function preserves all OssIndex values. No invalidation occurs, except for functions deleting elements from the SEQUENCE OF. These functions naturally invalidate OssIndexes for the deleted elements but nothing else.

component * at(OssIndex);
const component * at(OssIndex) const;
These methods return the pointer to the component of the SEQUENCE OF pointed to by the OssIndex object passed as the parameter. Note that an attempt to use an invalidat or incorrect OssIndex value (including OSS_NOINDEX) has unpredictable results.
OssIndex prepend(const component &val);
This method creates a new SEQUENCE OF element, copies the contents of the parameter (using deep copy) to the newly created element, and prepends the SEQUENCE OF with this element (so it becomes the first element of the SEQUENCE OF). The OssIndex value for the newly created element is returned. All other OssIndex values for this SEQUENCE OF remain valid. The original value remains unchanged.
OssIndex prepend(SeqOfType *);
This method prepends a SEQUENCE OF with the entire contents of another SEQUENCE OF of the same type (so the last element of the parameter object will precede the first element of "this" object before the call). The object passed as a parameter becomes empty; all its components are transferred to "this" SEQUENCE OF. No copying is involved. All OssIndexes for "this" SEQUENCE OF remain valid. The OssIndex value for the first one of the inserted elements is returned by the function. Note: When there is insufficient memory, this method fails and ownership of corresponding memory is not transferred. The return value should be deleted under those circumstances.
OssIndex insert_after(OssIndex, const component &);
This method inserts a deep copy of the object passed as the second parameter after the position represented by the first parameter. If the first parameter is OSS_NOINDEX, the object is inserted at the beginning of the SEQUENCE OF. The second parameter is unchanged. The OssIndex value for the newly inserted element is returned. If the OssIndex passed as the first parameter is invalid, no changes are made and OSS_NOINDEX is returned.
OssIndex insert_after(OssIndex, SequenceType *);
This method inserts a SEQUENCE OF of the same type passed as the second parameter after the position specified by the first parameter. If the first parameter is OSS_NOINDEX, the object is inserted at the very beginning of the SEQUENCE OF. The second parameter becomes empty; all its components are transferred to "this" SEQUENCE OF. No copying is involved. All OssIndexes for "this" SEQUENCE OF remain valid. The OssIndex value for the first of the inserted elements is returned by the function. If the OssIndex passed as the first element is invalid, no changes are made and OSS_NOINDEX is returned. Note: When there is insufficient memory, this method fails and ownership of corresponding memory is not transferred. The return value should be deleted under those circumstances.
int remove_front();
This method deletes the first element of the SEQUENCE OF. This method returns 0 if the delete operation was successful, and a non-zero error code if not (the SEQUENCE OF was empty). Any existing pointers or OssIndexes to the deleted element are invalidated.
int remove_after(OssIndex);
This method deletes the element following the position specified by OssIndex from the SEQUENCE OF. If the parameter is OSS_NOINDEX, the first element is deleted. It returns 0 if the delete operation was successful, and a non-zero error code if not (the SEQUENCE OF was empty or the OssIndex passed as the parameter was wrong). Any existing pointers or OssIndexes to the deleted element are invalidated.
SeqOfType * extract_after(OssIndex, OssIndex);
This method extracts the subset of "this" SEQUENCE OF, i.e., removes it from "this" SEQUENCE OF and makes a new SEQUENCE OF out of the removed components. The first parameter is the OssIndex for the element which precedes the element to be moved, and the second parameter is the OssIndex for the last element to be moved. If the first parameter is OSS_NOINDEX, the first element of the SEQUENCE OF is the first element to be moved. If the last parameter is OSS_NOINDEX, the last element of the SEQUENCE OF is the last element to be moved. The function returns a pointer to the newly created SEQUENCE OF, which is owned by the user. The user is responsible for deallocating it with the delete operator when it is no longer needed.

If the --<POINTER>-- directive is applied to the component type of the SEQUENCE OF, the following additional methods are generated:

int replace(OssIndex, Type *);
This is an ownership-transferring function. It replaces the contents of the element at the position specified by the OssIndex with the object passed as the second parameter. The old element is deleted. No deep copying occurs; the object simply becomes part of the SEQUENCE OF. The pointer remains valid but the user must not delete it or pass it to another ownership-transferring function because it becomes owned by the SEQUENCE OF object. All OssIndexes remain valid and the OssIndex passed as the first parameter is now a valid OssIndex of the new element. The function returns 0 if the operation was successful, and a non-zero error code otherwise (no changes are made in this case).
OssIndex prepend(Type *);
OssIndex insert_after(OssIndex, Type *);
These methods look the same as the already described prepend() and insert_after() methods but behave differently in that they are ownership-transferring functions. No deep copying occurs, the object passed as a parameter becomes part of "this" SEQUENCE OF. The pointer remains valid, but the user should not delete it or use it in another ownership-transferring function. Note that if the function fails (this can occur if there is insufficient memory for the operation), the parameter remains untouched and owned by the caller. You should take this into account if you want your program to be robust in memory-constrained situations.
Type * extract_after(OssIndex);
This is an ownership-transferring function. The element following the OssIndex position passed as the parameter is removed from "this" SEQUENCE OF and becomes an independent object that is owned by the caller. If the parameter is OSS_NOINDEX, the first element is extracted. The caller is now responsible for deallocating it using the delete operator. All OssIndexes referring to the extracted element are invalidated. In the case of any error, the SEQUENCE OF is unchanged and a NULL pointer is returned.
Type * extract_front();
This method is similar to the previous one, except that no position is specified. The first element of the SEQUENCE OF is extracted.

Open Types with Table Constraints

When a table constraint that limits the possible set of contained types is applied to an open type, the ASN.1/C++ compiler (starting with version 6.0) generates a class derived from the OssConstrainedOpenType runtime class by default, unless the -useGenericOpenTypes is specified. It acts as a container that can contain a value of an arbitrary type from the specified set or some value in the encoded form. The decoded value can contain both the encoded and decoded forms, if the DONT_FREE_ENCODED flag was specified during the decoding.

Definition

The following definition is a list of all possible functions that can be generated for a constrained open type. The name OpenType is derived from the name of the open type. Note, however, that open types usually occur in the ASN.1 specification as anonymous components of SEQUENCE. In this case, they are called after the information object set name used in the table constraint and the name of the information class field that is used as the open type. As usual, you can also refer to the open type with the <sequence name>::<component name> notation.

class OpenType: public OssConstrainedOpenType {
public:
    OpenType();
    OpenType(const OpenType &);
    ~OpenType();
    OpenType & operator = (const OpenType &);
    int operator == (const OpenType &) const;
    int operator != (const OpenType &) const;
    int set_decoded(PDU &);
    int grab_decoded(PDU &);
    int set_encoded(const EncodedBuffer &);
    int grab_encoded(EncodedBuffer &);
    int encode(OssControl &);

    // For each type that can be contained
<Type1> *get_<Type1>();
    const <Type1> *get_<Type1>() const;
    void set_<Type1>(const <Type1>&);
<Type1> *release_<Type1>();
    void set_<Type1>(<Type1> *);
    ...
};

OssConstrainedOpenType Class

The OssConstrainedOpenType class is a common ancestor for all the open type classes generated by the compiler. It has a private constructor and cannot be instantiated by the user. It contains common code used for all compiler-generated open type classes and provides implementation of the new and delete operators (so the compiler does not generate them separately for each open type). In addition to those operators, it has the following user-accessible functions:

int get_decoded(PDU &);
int get_decoded(PDU &) const;
These methods set the representation object pointer of a PDU type from the open type value. The open type is assumed to contain decoded data. If the PDU type is a specific PDU, the function will succeed only if the decoded data is of the same type that the PDU can handle. If the PDU object is of a universal PDU type, it will succeed regardless of the exact decoded data type. The function returns 0 if successful, and a non-zero error code if not (when the open type does not contain decoded data). If the open type object is constant, the representation object pointer is set to also be constant, which makes impossible to accidentally delete or corrupt it. The decoded data is owned by the open type object and will be destroyed when the open type object is destroyed. You must not destroy it explicitly. When "full-exception" mode is in effect, errors are signaled with C++ exceptions, so the function never returns anything but 0.

Therefore, if you know what type the open type object currently contains, you can use the corresponding coding (PDU) class and then use the get_data() function (or the get_const_data() function, if the open type object was constant):
ConcreteType_PDU pdu;
if (open.get_decoded(pdu))
     ... /* the object is of another type */
else
     ConcreteType *type = pdu.get_data();
However, in this case you can usually use a more convenient function from the derived compiler-generated class that returns the value of the contained type directly, without involving a coding type object.

If you do not know the exact type of the contained information, you can use the universal PDU type:
spec_PDU pdu;
if (open.get_decoded(pdu))
      ... /* the object does not contain any decoded info */
else if (type1 = pdu.get_Type1())
      ... /* type1 points to a value of the Type1 type */
else if (type2 = pdu.get_Type2())
      ... /* type2 points to a value of the Type2 type */
else if (…)	/* etc. */
else
      ... /* the type is unknown; something is probably wrong */
int release_decoded(PDU &);
This method is the same as the previous one, except that it is an ownership-transferring method. The ownership of the decoded data is given to the caller. When it is time to deallocate the decoded data, the caller is responsible for it. The open type object will not contain any decoded data after this call.

Note: A PDU class does not own (i.e., does not automatically deallocate) the representation object it contains. So you need to destroy the representation object returned by release_decoded() manually. You can choose either:
delete pdu.get_data();
or:
pdu.free_data(ctl);
Use the first action when the PDU object contains a class instance. However, if the contained ASN.1 type is represented by a primitive C++ type such as int, you must use another form (instead of delete):
asn1Free(pdu.get_data());
The second action (calling free_data) is correct regardless of the contained ASN.1 type.
EncodedBuffer * get_encoded() const;
This method creates a new EncodedBuffer object from the open type value. The open type object is assumed to contain encoded data. The returned EncodedBuffer object itself is owned by the caller and must be deallocated using the delete operator, when needed. However, the encoded data buffer is owned by the open data object and will be destroyed when the open type object is destroyed, i.e., the returned EncodedBuffer object is in the preallocated state, see Decoding into a Preallocated Buffer. The function returns a NULL pointer if the open type object does not currently contain any encoded data. In "full-exception" mode, the function signals the OSS_DATA_MISSING error code in this case.
EncodedBuffer * release_encoded();
This is the same as the previous function except that it is an ownership-transferring function. The ownership of the encoded data buffer is given to the EncodedBuffer object and the buffer will be automatically destroyed by the EncodedBuffer object's destructor, i.e., the EncodedBuffer object is in the automatically allocated state, see EncodedBuffer Decoding Behavior. The open type object will not contain any encoded data after this call.
int has_encoded() const;
This method returns 1 if the open type object contains encoded data; otherwise it returns 0.
int has_decoded() const;
This method returns 1 if the open type object contains decoded data; otherwise it returns 0.

Methods

int set_decoded(PDU &);
This method sets the open type object from a PDU object. The data contained in the PDU object is copied to the open type, using deep copy. The PDU object can be of any PDU type (universal or specific). The old decoded data and the encoded data that were contained in the open type are destroyed. The object will contain a copy of the data taken from the first parameter in the decoded form, and no encoded data. If the table constraint that constrains the open type references an inextensible information object set, the PDU object must contain one of the types specified in the information object set, otherwise the function fails with the OSS_TYPE_MISMATCH code. If the information object set is extensible, the PDU can contain any type. The function returns 0 if copying was successful, and a non-zero error code otherwise. When "full-exception" mode is in effect, errors are signaled with C++ exceptions, so the function never returns anything but 0.
int grab_decoded(PDU &);
This method is the same as the previous one, but it is an ownership-transferring function. It does not copy the data. Instead, it transfers the ownership of the representation object contained in the PDU to the open data object. The PDU object must contain a dynamically allocated representation object owned by the user, otherwise the results are unpredictable. The function resets the PDU object's value pointer to NULL. The function returns 0 if the operation was successful, and a non-zero error code otherwise. When "full-exception" mode is in effect, errors are signaled with C++ exceptions, so the function never returns anything but 0.
int set_encoded(const EncodedBuffer &);
This method sets the open type object from an EncodedBuffer object. The encoded data is copied to the open type. The old encoded data and the decoded data that were contained in the open type are destroyed. The function returns 0 if copying was successful, and a non-zero error code otherwise. When "full-exception" mode is in effect, errors are signaled with C++ exceptions, so the function never returns anything but 0.
int grab_encoded(EncodedBuffer &);
The same as the previous function, except that it is an ownership-transferring function. It does not copy the data. Instead, it transfers the ownership of the encoded data object passed as a parameter to the open type object. The ownership of the EncodedBuffer's buffer is transferred to the open type object. If the EncodedBuffer's buffer is owned by the user, it must be dynamically allocated using the asn1Malloc() function. After the call, the encoded data buffer is owned by the open type object and will be automatically deallocated by its destructor. The EncodedBuffer is reset to the uninitialized state.
int encode(OssControl &);
The function assumes that the open type object contains decoded data. It encodes the decoded data and stores the resulting encoded data in the open type object. The function returns 0 if successful, and a non-zero error code if it failed. When "full-exception" mode is in effect, errors are signaled with C++ exceptions, so the function never returns anything but 0. The encoded data is owned by the open type object. The decoded data is destroyed. If you have a complex type containing open type components, you can encode the whole complex value with one call of the encode() function if you specify the AUTOMATIC_ENCDEC flag in the OssControl object. However, if you have not specified this flag, you will need to use the encode() function to convert all the inner open type values to the encoded form before encoding the whole structure.
const <Type1> * get_<Type1>() const;
<Type1> * get_<Type1>();
This method returns a pointer to the contained value, assuming that the open type value contains a value of the <Type1> type. If the open type value does not contain the decoded value, or contains a value of a different type,
NULL is returned. The returned pointer points inside the open type object, so that the returned object is still owned by the open type object. You must not delete the returned object or pass it to any ownership-transferring function.
void set_<Type1>(const <Type1>&);
This method sets the open type object from a value of the <Type1> type. The data is copied to the open type, using deep copy. The old decoded data and the encoded data that were contained in the open type are destroyed. The object will contain a copy of the data taken from the first parameter in the decoded form, and no encoded data. The source data object is unchanged.
<Type1> *release_<Type1>();
This method returns a pointer to the contained value, assuming that the open type value contains a value of the <Type1> type. If the open type value does not contain the decoded value, or contains a value of a different type, NULL is returned. This is an ownership-transferring function. The returned object is now owned by the caller, and the caller must deallocate it using the delete operator, or the asn1Free() function if it is a primitive type value, when it is no longer needed. After the function call, the open type object will contain no decoded and no encoded data.
void set_<Type1>(<Type1> *);
This method sets the open type object from a value of the <Type1> type. The object passed as the parameter must be allocated dynamically, using the new operator or, for primitive types, the asn1Malloc() function. The old decoded data and the encoded data that were contained in the open type are destroyed. The open type object will contain the object taken from the first parameter in the decoded form, and no encoded data. This is an ownership-transferring function. After the call the object passed as the parameter will be owned by the open type object. You can use this function to avoid time-consuming deep copying of large objects.

OssOpen

This class is used to manage open type cases that are not covered with the previous section. In particular, it is used for any open type if the –useGenericOpenType compiler option is specified. It acts as a container that may contain an ASN.1 type in the decoded form (in the form of a representation class object) or in the encoded form (as a byte array containing an encoding). The class provides a means for conversion between both forms.

Definition

class OssOpen {
public:
  void *operator new(size_t);
  void operator delete(void *);
  OssOpen();
  OssOpen(const OssOpen &);
  OssOpen & operator = (const OssOpen &);
  ~OssOpen();
  int operator == (const OssOpen &) const;
  int operator != (const OssOpen &) const;
  int get_decoded(PDU &) const;
  int get_decoded_data(PDU &);
  int get_decoded_data(PDU &) const;
  int release_decoded(PDU &);
  int set_decoded(PDU &, OssControl &);
  int grab_decoded(PDU &, OssControl &);
  EncodedBuffer *get_encoded() const;
  EncodedBuffer *release_encoded();
  int set_encoded(const EncodedBuffer &);
int grab_encoded(EncodedBuffer &);
  int encode(OssControl &);
int decode(OssControl &);
  int has_decoded() const;
  int has_encoded() const;
  int has_type_info() const;
};

Methods

int get_decoded(PDU &) const;
Note: This method is unsafe and has been deprecated. It exists only for compatibility with earlier versions of ASN.1/C++. We strongly recommend against using it in new applications. Use the new get_decoded_data method instead.

This method sets the representation object pointer of a PDU type from the open type value. The open type is assumed to contain decoded data. If the PDU type is a specific PDU, the function will succeed only if the decoded data is of the same type that the PDU can handle. If the PDU object is of a universal PDU type, it will succeed regardless of the exact decoded data type. The function returns 0 if it was successful and a non-zero error code if not (when the open type does not contain decoded data). The decoded data is owned by the open type object and will be destroyed when the open type object is destroyed. You must not destroy it explicitly. When "full-exception" mode is in effect, errors are signaled with C++ exceptions, so the function never returns anything but 0.

Therefore, if you know what type the OssOpen object currently contains, you can use the corresponding coding (PDU) class and then use the get_data() function:
ConcreteType_PDU pdu;
if (open.get_decoded(pdu))
     ... /* the object is of another type */
else
     ConcreteType *type = pdu.get_data();
If you do not know the exact type of the contained information, you can use the universal PDU type:
spec_PDU pdu;
if (open.get_decoded(pdu))
      ... /* the object does not contain any decoded info */
else if (type1 = pdu.get_Type1())
      ... /* type1 points to a value of the Type1 type */
else if (type2 = pdu.get_Type2())
      ... /* type2 points to a value of the Type2 type */
else if (...) /* etc. */
else
      ... /* the type is unknown; something is probably wrong */
Note that this method always sets the representation object pointer in the PDU object as non-constant, even if the object from which it is extracted ("this" object) is constant. Therefore, this method allows changing part of a constant object, so it is potentially unsafe. We recommend using the new get_decoded_data method (introduced in version 6.0) instead.
int get_decoded_data(PDU &);
int get_decoded_data(PDU &) const;
These methods present a safer version of the previous method. They set the representation object pointer of a PDU type from the open type value. The open type is assumed to contain decoded data. If the PDU type is a specific PDU, the function will succeed only if the decoded data is of the same type that the PDU can handle. If the PDU object is of a universal PDU type, it will succeed regardless of the exact decoded data type. If the OssOpen object is constant, the representation object pointer is set to also be constant, which makes it impossible to accidentally delete or corrupt it, making these methods safer than the earlier get_decoded method. The function returns 0 if successful and a non-zero error code if not (when the open type does not contain decoded data). The decoded data is owned by the open type object and will be destroyed when the open type object is destroyed. You must not destroy it explicitly. When "full-exception" mode is in effect, errors are signaled with C++ exceptions, so the function never returns anything but 0.

Therefore, if you know what type the OssOpen object currently contains, you can use the corresponding coding (PDU) class and then use the get_data() function (or the get_const_data() function, if the OssOpen object was constant):
ConcreteType_PDU pdu;
if (open.get_decoded_data(pdu))
     ... /* the object is of another type */
else
     ConcreteType *type = pdu.get_data();
If you do not know the exact type of the contained information, you can use the universal PDU type:
spec_PDU pdu;
if (open.get_decoded_data(pdu))
      ... /* the object does not contain any decoded info */
else if (type1 = pdu.get_Type1())
      ... /* type1 points to a value of the Type1 type */
else if (type2 = pdu.get_Type2())
      ... /* type2 points to a value of the Type2 type */
else if (...) /* etc. */
else
      ... /* the type is unknown; something is probably wrong */
int release_decoded(PDU &);
This method is the same as the previous one, except that it is an ownership-transferring method. The ownership of the decoded data is given to the caller. When it is time to deallocate the decoded data, the caller is responsible for it. The open type object will not contain any decoded data after this call.

NOTE: A PDU class does not own (i.e., does not automatically deallocate) the representation object it contains. So you need to destroy the representation object returned by release_decoded() manually. You may choose either:
delete pdu.get_data();
or:
pdu.free_data(ctl);
Use the first action when the PDU object contains a class instance. However, if the contained ASN.1 type is represented by a primitive C++ type such as int, you must use another form (instead of delete):
asn1Free(pdu.get_data());
The second action (calling free_data) is correct regardless of the contained ASN.1 type.
int set_decoded(PDU &, OssControl &);
This method sets the open type object from a PDU object. The data contained in the PDU object are copied to the open type (using deep copy). The PDU object can be of any PDU type (universal or specific). The old decoded data and the encoded data that were contained in the open type are destroyed. The object will contain a copy of the data taken from the first parameter in the decoded form, and no encoded data. The second parameter is an OssControl instance that will be temporarily used by the function. The function returns 0 if copying was successful and a non-zero error code otherwise. When "full-exception" mode is in effect, errors are signaled with C++ exceptions, so the function never returns anything but 0.
int grab_decoded(PDU &, OssControl &);
This method is the same as the previous method but it is an ownership-transferring function. It does not copy the data. Instead, it transfers the ownership of the representation object contained in the PDU to the open data object. The PDU object must contain a dynamically allocated representation object owned by the user, otherwise the results are unpredictable. The function resets the PDU object's value pointer to NULL. The second parameter is an OssControl instance that will be temporarily used by the function. The function returns 0 if copying was successful and a non-zero error code otherwise. When "full-exception" mode is in effect, errors are signaled with C++ exceptions, so the function never returns anything but 0.
EncodedBuffer * get_encoded() const;
This method creates a new EncodedBuffer object from the open type value. The open type object is assumed to contain encoded data. The returned EncodedBuffer object itself is owned by the caller and must be deallocated by using the delete operator when needed. However, the encoded data buffer is owned by the open data object and will be destroyed when the open type object is destroyed; i.e., the returned EncodedBuffer object is in the preallocated state, see Decoding into a Preallocated Buffer.The function returns a NULL pointer if the open type object does not currently contain any encoded data. In "full-exception" mode, the function signals the OSS_DATA_MISSING error code in this case.
EncodedBuffer * release_encoded();
The same as the previous function except that it is an ownership-transferring function. The ownership of the encoded data buffer is given to the EncodedBuffer object and the buffer will be automatically destroyed by the EncodedBuffer object's destructor (the EncodedBuffer object is in the automatically allocated state, see EncodedBuffer Decoding Behavior). The open type object will not contain any encoded data after this call.
int set_encoded(const EncodedBuffer &);
This method sets the open type object from an EncodedBuffer object. The encoded data is copied to the open type. The old encoded data and the decoded data that were contained in the open type are destroyed. The function returns 0 if copying was successful and a non-zero error code otherwise. When "full-exception" mode is in effect, errors are signaled with C++ exceptions, so the function never returns anything but 0.
int grab_encoded(EncodedBuffer &);
The same as the previous function except that it is an ownership-transferring function. It does not copy the data. Instead, it transfers the ownership of the encoded data object passed as a parameter to the open type object. The ownership of the EncodedBuffer's buffer is transferred to the open type object. If the EncodedBuffer's buffer is owned by the user, it must be dynamically allocated using the asn1Malloc() function. After the call, the encoded data buffer is owned by the open type object and will be automatically deallocated by its destructor. The EncodedBuffer is reset to the uninitialized state.
int encode(OssControl &);
The function assumes that the open type object contains decoded data. It encodes the decoded data and stores the resulting encoded data in the open type object. The function returns 0 if successful and a non-zero error code if it failed. When "full-exception" mode is in effect, errors are signaled with C++ exceptions, so the function never returns anything but 0. The encoded data is owned by the open type object. The decoded data is destroyed. If you have a complex type containing open type components, you can encode the whole complex value with one call of the encode() function, provided you specify the AUTOMATIC_ENCDEC flag in the OssControl object. However, if you haven't specified this flag, you'll need to use the OssOpen::encode() function to convert all the inner open type values to the encoded form before encoding the whole structure.
int decode(OssControl &);
The function assumes that the open type object contains encoded data. It decodes the encoded data and stores the resulting decoded data in the open type object. The function returns 0 if successful and a non-zero error code if it failed. When "full-exception" mode is in effect, errors are signaled with C++ exceptions, so the function never returns anything but 0. The decoded data is owned by the open type object. In order for this function to succeed, the open type object must contain enough information to determine the ASN.1 type of the data it contains. This information can be set by either the set_decoded() or grab_decoded() methods, determined in the decoding process based on component relation constraints, or figured out from the BER or XML tags of the encoded data (the latter case is supported only by the SOED or TOED; the LED does not support it). Note that if you have a complex type containing open type components, you can decode the whole complex value with one PDU::decode() call if you specify the AUTOMATIC_ENCDEC flag in the OssControl object (provided the component relation constraints in your specification allow automatic determination of the contents of all the inner open types). So you may avoid using this function in this case.
int has_encoded() const;
This method returns 1 if the open type object contains encoded data; otherwise it returns 0.
int has_decoded() const;
This method returns 1 if the open type object contains decoded data; otherwise it returns 0.
int has_type_info() const;
This method returns 1 if the open type object has information about the ASN.1 type of the data it contains. This information can be either set by the set_decoded() or grab_decoded() methods or determined in the decoding process based on component relation constraints.

OssString

This class is used for all one-byte character strings (all restricted character string types except for BMPString and UniversalString), OCTET STRING, OID-IRI, RELATIVE-OID-IRI, and ANY.

Definition

class OssString {
public:
  OssString();
  OssString(const OssString &);
  OssString & operator = (const OssString &);
  ~OssString();
  int operator == (const OssString &) const;
  int operator != (const OssString &) const;
  void *operator new(size_t);
  void operator delete(void *);
  OssString(const char *);
  OssString(OSS_UINT32 length, const char *);
  OSS_UINT32 length() const;
  char *get_buffer();
  const char *get_buffer() const;
  void resize(OSS_UINT32);
  void set(const char *);
  void set(OSS_UINT32 length, const char *);
  // ownership-transferring functions
   char *release_buffer(OSS_UINT32 & length);
  void grab(OSS_UINT32 length, char *);
  // higher level functions
  char & operator [] (OSS_UINT32 pos);
  const char & operator [] (OSS_UINT32 pos) const;
  char elem(OSS_UINT32 pos);
  OssString & operator += (const OssString &);
  OssString & operator += (const char *);
};

Methods

OssString(const char *);
The string is initialized with a C null-terminated string. The data is copied to the OssString object. The string passed as a parameter remains unchanged.
OssString(OSS_UINT32 length, const char *);
The string is initialized with an array of chars. The length of the array is determined by the first parameter. The data is copied to the OssString object. The initial array remains unchanged. This function can initialize the OssString object with a char sequence that contains zero-value bytes.
OSS_UINT32 length() const;
This method returns the current length of the string. Note that no extra zero byte is appended to the string value.
char * get_buffer();
const char * get_buffer() const;
These methods return the address of the internal character array of the
OssString object. No copying occurs. If the user makes any changes to the array, they will automatically affect the value of the
OssString. Note that there is no zero byte at the end of the byte sequence, its length can be determined by the length() function. I.e., the user needs to be careful while trying to print the byte sequence returned by these two methods as a simple null-terminated string: '\0' should be added to the end of it.
void resize(OSS_UINT32);
This method changes the length of the OssString object. If the current length is greater than the new length, the character array is shrunk, if it is less, the character array is expanded. The address of the character array is invalidated (because the array may be moved to another place in memory). If the array was expanded, the values of the expansion bytes are unpredictable. You should set them later to anything you need.
void set(const char *);
The new value of the OssString is set from a C null-terminated string. The string is copied to the OssString object; the input array is unchanged. The old value of the OssString object is destroyed; the address of its old internal character array is invalidated.
void set(OSS_UINT32 length, const char *);
The new value of the OssString is set from a character array. The length of the array is determined by the first parameter. The array is copied to the OssString object. The source array is unchanged. The old OssString value is destroyed. This function can set a value that contains zero bytes.
char & operator [] (OSS_UINT32 pos);
const char & operator [] (OSS_UINT32 pos) const;
These methods return a reference to the character at the position specified by the parameter. If the position lies outside the current bounds, the result is unpredictable. See note box below.
char elem(OSS_UINT32 pos) const;
This method returns a character at the position specified by the parameter. If the position lies outside the current bounds, the result is unpredictable. See note box below.
OssString & operator += (const OssString &);
OssString & operator += (const char *);
These methods append the value of the parameter to the OssString value. In the second form, the parameter is a null-terminated C string. All pointers inside the OssString buffer are invalidated because the internal character array may be moved to another place in memory.

The following two functions are ownership-transferring functions:

char * release_buffer(OSS_UINT32 &);
This method returns a pointer of the internal character array. The length of the array is assigned to the first parameter. The OssString object is reset to the empty string value. The returned value is now owned by the caller. The caller is responsible for deallocating it using the asn1Free() function when needed.
void grab(OSS_UINT32 length, char *);
This method sets a new value to the OssString object. The address of the character array is defined with the second parameter; its length is defined with the first parameter. The character array must be dynamically allocated with the asn1Malloc() function. After the call, this array becomes owned by the OssString object. No data copying occurs. The user should not deallocate the array or use it in another ownership-transferring function. Note that the source array should not contain any extra bytes (such as a trailing zero byte), its size is determined by the length parameter.

NOTE: The indexing operators of the OssString class do not check whether the specified number of characters is within the bounds of the string. If it is out of bounds, the behavior of the function is unpredictable. Use the length() method, which tells the exact number of characters in the OssString. Make sure not to pass any value greater than the length in the indexing operators.


OCTET STRING with Contents Constraint

If a contents constraint is applied to an OCTET STRING type, this type is represented by a compiler-generated class derived from the OssString class. Logically this class can be thought of as a container storing the value either in the encoded form (OssString) or in the decoded form (the corresponding representation type). For manipulations with the encoded form, the user can use any of the member functions of the OssString class, since the representation class is publicly derived from OssString. The compiler generates the necessary methods to handle the value in the decoded form.

These are the possible cases:

  1. The contents constraint contains only the CONTAINING clause without the ENCODED BY clause, e.g., OCTET STRING (CONTAINING INTEGER). The user can specify the encoder's input value either in the encoded form or in the decoded form. If the value is specified in the decoded form, it is automatically encoded using the current encoding rules. The user can specify both the encoded and the decoded values. This is not considered an error, but the encoded value takes precedence in this case; the decoded value is ignored by the encoder. The decoder usually decodes such contents constraints automatically; the output value of the decoder contains only the decoded form. If you want the decoder to leave the value in the encoded form, you can apply the --<OSS.NOPDU>-- compiler directive to the contained type. This will prevent the decoder from decoding the contents constraint.
  2. The contents constraint contains both the CONTAINING clause and the ENCODED BY clause specified by any of the encoding rules supported by OSS, e.g., OCTET STRING (CONTAINING INTEGER ENCODED BY {joint-iso-itu-t asn1(1) basic-encoding(1)}). This case is processed like the previous one, but the encoder/decoder always uses the specified encoding rules to encode/decode the contents constraint, regardless of the current encoding rules. The encoding rules specified in the contents constraint should also be specified in the ASN.1 Compiler command line, otherwise the encoding/decoding operation will fail.
  3. The contents constraint contains both the CONTAINING clause and the ENCODED BY clause specified by any unknown or unsupported encoding rules, e.g., OCTET STRING (CONTAINING INTEGER ENCODED BY myOwnPrivateRules). This case is processed exactly like case 1. The ENCODED BY clause is simply ignored and the current encoding rules are used for encoding/decoding.
  4. The contents constraint contains only the ENCODED BY clause, e.g.: OCTET STRING (ENCODED BY {joint-iso-itu-t asn1(1) basic-encoding(1)}). Since the encoded type is unknown, it is not possible to automatically decode the contents constraint or to specify the value in the decoded form. In this case, the user can only specify the encoded form as the encoder's input value, and the decoder also stores the value in the encoded form.

Definition

class OSS_ContentConstraint : public OssString
{
public:
    typedef <contained type> contained;

    ContentConstraint();
    ContentConstraint(const ContentConstraint &);
    ContentConstraint & operator = (const ContentConstraint &);
    ~ContentConstraint();
    int operator == (const ContentConstraint &) const;
    int operator != (const ContentConstraint &) const;
    ContentConstraint(const char *);
    ContentConstraint(OSS_UINT32 length, const char *);
    contained *get_decoded();
    const contained *get_decoded() const;
    contained *release_decoded();
    void set_decoded(const contained &);
    void grab_decoded(contained *);
    int has_encoded() const;
    int has_decoded() const;
};

If the contained type is represented by a primitive C++ type (such as int or double) rather than a C++ class, the generated interface of the set_decoded function differs slightly. Instead of a constant reference to the value, it contains the value itself to improve efficiency, e.g.:

void set_decoded(int);

If the type of the contained type is unknown (no CONTAINING clause is present), the functions handling the decoded value (get_decoded, release_decoded, set_decoded, grab_decoded) are not generated.

Methods

ContentConstraint(const char *);
The encoded value is initialized with a C null-terminated string. The data is copied to the object. The string passed as a parameter remains unchanged.
ContentConstraint(OSS_UINT32 length, const char *);
The encoded value is initialized with an array of chars. The length of the array is determined by the first parameter. The data is copied to the object. The initial array remains unchanged. This function can initialize the object with a char sequence that contains zero-value bytes.
contained *get_decoded();
const contained *get_decoded() const;
These functions return a pointer to the decoded value if one is present. The returned object remains owned by the contents constraint object. You may change it if needed but you should not deallocate it or use it in an ownership-transferring function. If the decoded value is not present, the function returns NULL.
contained *release_decoded();
This is an ownership-transferring function. It returns a pointer to the decoded value if one is present. The returned object is now owned by the caller. The caller must deallocate it when it is no longer needed or insert it into another object using an ownership-transferring function. The deallocation must be done using the delete operator (if the contained type is represented by a C++ class) or by the asn1Free function (if the contained type is represented by a primitive C++ type). If the decoded value is not present, the function returns NULL.
void set_decoded(const contained &);
This function copies the parameter to the contents constraint object as the decoded value member. The old value of the contents constraint object is deleted. The parameter itself remains unchanged.
void grab_decoded(contained *);
This function sets the decoded value member of the contents constraint object. The old value of the contents constraint object is deleted. This is an ownership-transferring function. No deep copying occurs; the operation is done by a simple pointer assignment. The object passed as the parameter must be allocated dynamically, using the new operator (if the contained type is represented is by a C++ class) or the asn1Malloc function (if the contained type is represented by a primitive C++ type). Passing a static or automatic object to this function may lead to unpredictable results.
int has_encoded() const;
This function returns 1 if the object has a non-null encoded value member and 0 otherwise. It is equivalent to length() != 0.
int has_decoded() const;
This function returns 1 if the object has a non-null decoded value member and 0 otherwise.

OssBitString

This class implements ASN.1 BIT STRING types.

Definition

class OssBitString {
public:
  void *operator new(size_t);
  void operator delete(void *);
  OssBitString();
  OssBitString(const OssBitString &);
  OssBitString & operator = (const OssBitString &);
  ~OssBitString();
  int operator == (const OssBitString &) const;
  int operator != (const OssBitString &) const;
  OssBitString(OSS_UINT32 length, const unsigned char *);
  OSS_UINT32 length() const;
  unsigned char *get_buffer();
  const unsigned char *get_buffer() const;
  void resize(OSS_UINT32);
  void set(OSS_UINT32 length, const unsigned char *);
  // ownership-transferring functions
  unsigned char *release_buffer(OSS_UINT32 & length);
  void grab(OSS_UINT32 length, unsigned char *);
  // higher level functions
  void set(OSS_UINT32 pos);
  void clear(OSS_UINT32 pos);
  void invert(OSS_UINT32 pos);
  void set(OSS_UINT32 pos, OSS_UINT32 length);
  void clear(OSS_UINT32 pos, OSS_UINT32 length);
  void invert(OSS_UINT32 pos, OSS_UINT32 length);
  void assign(OSS_UINT32 pos, int bit);
  int test(OSS_UINT32 pos) const;
  OssBit operator [] (OSS_UINT32 pos);
  const OssBit operator [] (OSS_UINT32 pos) const;
};

Methods

OssBitString(OSS_UINT32 length, const unsigned char *);
The bit string is initialized with an array of chars. The length of the array (in bits) is determined by the first parameter. The data is copied to the OssBitString object. The initial array remains unchanged.
OSS_UINT32 length() const;
This method returns the current length of the bit string in bits.
unsigned char * get_buffer();
const unsigned char * get_buffer() const;
These methods return the address of the internal character array of the OssBitString object. No copying occurs. If the user makes any changes to the array, they will automatically affect the value of the OssBitString. The length of the buffer in bits can be determined by the length() function. The bits in the character array are numbered with the most significant bit first, i.e., the most significant bit of the first byte represents bit 0, the least significant bit of the first byte represents bit 7, the most significant bit of the second byte represents bit 8, etc.
void resize(OSS_UINT32);
This method changes the length of the OssBitString object. If the current length is greater than the new length, the buffer has shrunk, if it is less, the buffer has expanded (in this case, the additional bits will have undefined values; you should explicitly set them as you need). The address of the buffer is invalidated because it may be moved to another place.
void set(OSS_UINT32 length, const unsigned char *);
The new value of the OssBitString is set from a character array. The length of the array (in bits) is determined by the first parameter. The old OssBitString value is destroyed.
void set(OSS_UINT32 pos);
void clear(OSS_UINT32 pos);
void invert(OSS_UINT32 pos);
These methods set, clear, and invert the bit in
OssBitString at the specified position. If the specified position is outside the current bounds, the result is unpredictable. Also see the note box below.
void set(OSS_UINT32 pos, OSS_UINT32 length);
void clear(OSS_UINT32 pos, OSS_UINT32 length);
void invert(OSS_UINT32 pos, OSS_UINT32 length);
These functions set, clear, and invert a substring of the bit string. The substring starts at the pos position and has a length of length bits. Also see the note box below.
void assign(OSS_UINT32 pos, int bit);
If bit is 0, this method clears the bit at the pos position. Otherwise, it sets bit to 1. Also see the note box below.
int test(OSS_UINT32 pos) const;
This method returns the value of the bit at the pos position. Also see the note box below.
OssBit operator[] (OSS_UINT32 pos);
const OssBit operator[] (OSS_UINT32 pos) const;
These methods return an OssBit object that serves as a reference to an individual bit inside the OssBitString. OssBit is a utility class. An OssBit object can be set from an integer and converted to an integer. Setting an OssBit object from an integer will set the corresponding bit in the bit string, converting it to an integer will return the corresponding bit in the bit string. The pos parameter must be inside the current bounds of the OssBitString; otherwise, the behavior of the function is unpredictable. Also, see the note box below.

The following two functions are ownership-transferring functions:

unsigned char * release_buffer(OSS_UINT32 &);
This method returns a pointer to the internal character array. The length of the array (in bits) is assigned to the first parameter. The OssBitString object is reset to the empty value. The returned value is now owned by the caller. The caller is responsible for deallocating it using the asn1Free() function when needed.
void grab(OSS_UINT32 length, unsigned char *);
This method sets a new value to the OssBitString object. The address of the character array is defined with the second parameter; its length (in bits) is defined with the first parameter. The character array must be dynamically allocated with the asn1Malloc() function. After the call, this array becomes owned by the OssBitString object. No data copying occurs. The user should not deallocate the input array or use it in another ownership-transferring function.

NOTE: The functions of the OssBitString class do not check whether the specified number of the bit is within the bounds of the bit string. If it is out of bounds, the behavior of the function is unpredictable. Use the length() method, which tells the exact number of bits in the bitstring, to make sure not to pass any value greater than length to any of the methods.


BIT STRING with Contents Constraint

If a contents constraint is applied to a BIT STRING type, this type is represented by a compiler-generated class derived from the OssBitString class. Logically this class can be thought of as a container containing the value either in the encoded form (OssBitString) or in the decoded form (the corresponding representation type). For manipulations with the encoded form, the user may use all of the member functions of the OssBitString class (since the representation class is derived from OssBitString. The compiler generates the necessary methods to handle the value in the decoded form.

These are the possible cases:

  1. The contents constraint contains only the CONTAINING clause without the ENCODED BY clause, e.g., OCTET STRING (CONTAINING INTEGER). The user can specify the encoder's input value either in the encoded form or in the decoded form. If the value is specified in the decoded form, it is automatically encoded using the current encoding rules. The user can specify both the encoded and the decoded values. This is not considered an error, but the encoded value takes precedence in this case; the decoded value is ignored by the encoder. The decoder usually decodes such contents constraints automatically; the output value of the decoder contains only the decoded form. If you want the decoder to leave the value in the encoded form, you can apply the --<OSS.NOPDU>-- compiler directive to the contained type. This will prevent the decoder from decoding the contents constraint.
  2. The contents constraint contains both the CONTAINING clause and the ENCODED BY clause specified any of the encoding rules supported by OSS, e.g., OCTET STRING (CONTAINING INTEGER ENCODED BY {joint-iso-itu-t asn1(1) basic-encoding(1)}). This case is processed like the previous one, but the encoder/decoder always uses the specified encoding rules to encode/decode the contents constraint, regardless of the current encoding rules. The encoding rules specified in the contents constraint should also be specified in the ASN.1 Compiler command line, otherwise the encoding/decoding operation will fail.
  3. The contents constraint contains both the CONTAINING clause and the ENCODED BY clause specified any unknown or unsupported encoding rules, e.g., OCTET STRING (CONTAINING INTEGER ENCODED BY myOwnPrivateRules). This case is processed exactly like case 1. The ENCODED BY clause is simply ignored and the current encoding rules are used for encoding/decoding.
  4. The contents constraint contains only the ENCODED BY clause, e.g.: OCTET STRING (ENCODED BY {joint-iso-itu-t asn1(1) basic-encoding(1)}). Since the encoded type is unknown, there is no possibility to automatically decode the contents constraint or to specify the value in the decoded form. In this case, the user can only specify the encoded form as the encoder's input value, and the decoder also stores the value in the encoded form.

Definition

class ContentConstraint : public OssBitString
{
public:
    typedef <contained type> contained;

    ContentConstraint();
    ContentConstraint(const ContentConstraint &);
    ContentConstraint & operator = (const ContentConstraint &);
    ~ContentConstraint();
    int operator == (const ContentConstraint &) const;
    int operator != (const ContentConstraint &) const;
    ContentConstraint(OSS_UINT32 length, const unsigned char *);
    contained *get_decoded();
    const contained *get_decoded() const;
    contained *release_decoded();
    void set_decoded(const contained &);
    void grab_decoded(contained *);
    int has_encoded() const;
    int has_decoded() const;
};

If the contained type is represented by a primitive C++ type (such as int or double) rather than a C++ class, the generated interface of the set_decoded function differs slightly. Instead of a constant reference to the value, it contains the value itself to improve efficiency, e.g.:

void set_decoded(int);

If the type of the contained type is unknown (no CONTAINING clause is present), the functions handling the decoded value (get_decoded, release_decoded, set_decoded, grab_decoded) are not generated.

Methods

ContentConstraint(OSS_UINT32 length, const unsigned char *);
The encoded value is initialized with an array of chars. The length of the array (in bits) is determined by the first parameter. The data is copied to the object. The initial array remains unchanged.
contained *get_decoded();
const contained *get_decoded() const;
These functions return a pointer to the decoded value if one is present. The returned object remains owned by the contents constraint object. You may change it if needed but you should not deallocate it or use it in an ownership-transferring function. If the decoded value is not present, the function returns NULL.
contained *release_decoded();
This is an ownership-transferring function. It returns a pointer to the decoded value if one is present. The returned object is now owned by the caller. The caller must deallocate it when it is no longer needed or insert it into another object using an ownership-transferring function. The deallocation must be done using the delete operator (if the contained type is represented by a C++ class) or by the asn1Free function (if the contained type is represented by a primitive C++ type). If the decoded value is not present, the function returns NULL.
void set_decoded(const contained &);
This function copies the parameter to the contents constraint object as the decoded value member. The old value of the contents constraint object is deleted. The parameter itself remains unchanged.
void grab_decoded(contained *);
This function sets the decoded value member of the contents constraint object. The old value of the contents constraint object is deleted. This is an ownership-transferring function. No deep copying occurs; the operation is done by a simple pointer assignment. The object passed as the parameter must be allocated dynamically, using the new operator (if the contained type is represented is by a C++ class) or the asn1Malloc function (if the contained type is represented by a primitive C++ type). Passing a static or automatic object to this function may lead to unpredictable results.
int has_encoded() const;
This function returns 1 if the object has a non-null encoded value member and 0 otherwise. It is equivalent to length() != 0.
int has_decoded() const;
This function returns 1 if the object has a non-null decoded value member and 0 otherwise.

OssBMPString

This type is generated for two-byte character strings (BMPString and UTF8String in the presence of the --<BMPSTRING>-- directive). OSS_CHAR16 is an unsigned integer type that takes 2 bytes of memory (for most platforms, unsigned short).

Definition

class OssBMPString {
public:
  void *operator new(size_t);
  void operator delete(void *);
  OssBMPString();
  OssBMPString(const OssBMPString &);
  OssBMPString & operator = (const OssBMPString &);
  ~OssBMPString();
  int operator == (const OssBMPString &) const;
  int operator != (const OssBMPString &) const;
  OssBMPString(OSS_UINT32 length, const OSS_CHAR16 *);
  OSS_UINT32 length() const;
  OSS_CHAR16 *get_buffer();
  const OSS_CHAR16 *get_buffer() const;
  void resize(OSS_UINT32);
  void set(OSS_UINT32 length, const OSS_CHAR16 *);
  // ownership-transferring functions
  OSS_CHAR16 *release_buffer(OSS_UINT32 & length);
  void grab(OSS_UINT32 length, OSS_CHAR16 *);
  // higher level functions
  OSS_CHAR16 & operator [] (OSS_UINT32 pos);
  const OSS_CHAR16 & operator [] (OSS_UINT32 pos) const;
  OSS_CHAR16 elem(OSS_UINT32 pos);
  OssBMPString & operator += (const OssBMPString &);
};

Methods

OssBMPString(OSS_UINT32 length, const OSS_CHAR16 *);
The string is initialized with an array of OSS_CHAR16. The length of the array (in 2-byte elements) is determined by the first parameter. The data is copied to the OssBMPString object. The initial array remains unchanged.
OSS_UINT32 length() const;
This method returns the current length of the string (in 2-byte characters).
OSS_CHAR16 * get_buffer();
const OSS_CHAR16 * get_buffer() const;
These methods return the address of the internal character array of the OssBMPString object. No copying occurs. If the user makes any changes to the array, they will automatically affect the value of the OssBMPString. The array has no terminating character. The length of the array can be determined by the length() function.
void resize(OSS_UINT32);
This method changes the length of the OssBMPString object. If the current length is greater than the new length, the character array is shrunk, if it is less, the character array is expanded (in this case, the additional array elements will have undefined values; you should set them as you need). The address of the character array is invalidated because the array may be moved to another memory location.
void set(OSS_UINT32 length, const OSS_CHAR16 *);
The new value of the OssBMPString is set from an OSS_CHAR16 array. The length of the array (in 2-byte elements) is determined by the first parameter. The old OssBMPString value is destroyed.
OSS_CHAR16 & operator [] (OSS_UINT32 pos);
const OSS_CHAR16 & operator [] (OSS_UINT32 pos) const;
These methods return a reference to the 2-byte character at the position specified by the parameter. If the position is incorrect, the result is unpredictable.
OSS_CHAR16 elem(OSS_UINT32 pos) const;
This method returns a 2-byte character at the position specified by the parameter. If the position is incorrect, the result is unpredictable.
OssBMPString & operator += (const OssBMPString &);
This method appends an OssBMPString value to "this" OssBMPString. All pointers inside the OssBMPString buffer are invalidated because the character array may be moved to another place in memory.

The following two functions are ownership-transferring functions:

OSS_CHAR16 * release_buffer(OSS_UINT32 &);
This method returns a pointer of the internal character array. The length of the array (in 2-byte elements) is assigned to the first parameter. The OssBMPString object is reset to the empty string value. The returned array is now owned by the caller. The caller is responsible for deallocating it using the asn1Free() function when needed.
void grab(OSS_UINT32 length, OSS_CHAR16 *);
This method sets a new value to the OssBMPString object. The address of the character array is defined by the second parameter; its length (in 2-byte elements) is defined by the first parameter. The character array must be dynamically allocated with the asn1Malloc() function. After the call, this array becomes owned by the OssBMPString object. No data copying occurs. The user should not deallocate the input array or use it in another ownership-transferring function.

OssUniversalString

This type is generated for four-byte character strings (UniversalString and UTF8String with the --<UNIVERSALSTRING>-- directive applied). OSS_CHAR32 is an unsigned integer type that takes 4 bytes of memory (for most platforms - unsigned long).

Definition

class OssUniversalString {
public:
  void *operator new(size_t);
  void operator delete(void *);
  OssUniversalString();
  OssUniversalString(const OssUniversalString &);
  OssUniversalString & operator = (const OssUniversalString &);
  ~OssUniversalString();
  int operator == (const OssUniversalString &) const;
  int operator != (const OssUniversalString &) const;
  OssUniversalString(OSS_UINT32 length, const OSS_CHAR32 *);
  OSS_UINT32 length() const;
  OSS_CHAR32 *get_buffer();
  const OSS_CHAR32 *get_buffer() const;
  void resize(OSS_UINT32);
  void set(OSS_UINT32 length, const OSS_CHAR32 *);
  // ownership-transferring functions
  OSS_CHAR32 *release_buffer(OSS_UINT32 & length);
  void grab(OSS_UINT32 length, OSS_CHAR32 *);
  // higher level functions
  OSS_CHAR32 & operator [] (OSS_UINT32 pos);
  const OSS_CHAR32 & operator [] (OSS_UINT32 pos) const;
  OSS_CHAR32 elem(OSS_UINT32 pos);
  OssUniversalString & operator += (const OssUniversalString &);
};

Methods

OssUniversalString(OSS_UINT32 length, const OSS_CHAR32 *);
The string is initialized with an array of OSS_CHAR32. The length of the array (in 4-byte elements) is determined by the first parameter. The data is copied to the OssUniversalString object. The initial array remains unchanged.
OSS_UINT32 length() const;
This method returns the current length of the string (in 4-byte characters).
OSS_CHAR32 * get_buffer();
const OSS_CHAR32 * get_buffer() const;
This method returns the address of the internal character array of the OssUniversalString object. No copying occurs. If the user makes any changes to the array, they will automatically affect the value of the OssUniversalString. The array has no terminating character. The length of the array can be determined by the length() function.
void resize(OSS_UINT32);
This method changes the length of the OssUniversalString object. If the current length is greater than the new length, the character array is shrunk, if it is less, the character array is expanded (in this case the additional characters have unpredictable values; you should explicitly set them as you need). The old address of the internal character array is invalidated because it could be moved to another place in memory.
void set(OSS_UINT32 length, const OSS_CHAR32 *);
The new value of the OssUniversalString is set from an OSS_CHAR32 array. The length of the array (in 4-byte elements) is determined by the first parameter. The old OssUniversalString value is destroyed.
OSS_CHAR32 & operator [] (OSS_UINT32 pos);
const OSS_CHAR32 & operator [] (OSS_UINT32 pos) const;
This method returns the reference to the 4-byte character at the position specified by the parameter. If the position is incorrect, the result is unpredictable.
OSS_CHAR32 elem(OSS_UINT32 pos) const;
This method returns a 4-byte character at the position specified by the parameter. If the position is incorrect, the result is unpredictable.
OssUniversalString & operator += (const OssUniversalString &);
This method appends an OssUniversalString value to "this" OssUniversalString. All pointers inside the OssUniversalString buffer are invalidated because the buffer may be moved to another place in memory.

The following two functions are ownership-transferring functions:

OSS_CHAR32 * release_buffer(OSS_UINT32 &);
This method returns a pointer of the internal character array. The length of the array (in 4-byte elements) is assigned to the first parameter. The OssUniversalString object is reset to the empty string value. The returned value is now owned by the caller. The caller is responsible for deallocating it using the asn1Free() function when needed.
void grab(OSS_UINT32 length, OSS_CHAR32 *);
This method sets a new value to the OssUniversalString object. The address of the character array is defined by the second parameter; its length (in 4-byte elements) is defined by the first parameter. The character array must be dynamically allocated with the asn1Malloc() function. After the call, this array becomes owned by the OssUniversalString object. No data copying occurs. The user should not deallocate the input array or use it in another ownership-transferring function.

OssEncOID

The OssEncOID class implements the ASN.1 OBJECT IDENTIFIER type. This representation does not allow access to individual arcs of the OBJECT IDENTIFIER. The internal representation is a BER-encoded byte string.

Definition

class OssEncOID {
public:
  void *operator new(size_t);
  void operator delete(void *);
  OssEncOID();
  OssEncOID(const OssEncOID &);
  OssEncOID & operator = (const OssEncOID &);
  ~OssEncOID();
  int operator == (const OssEncOID &) const;
  int operator != (const OssEncOID &) const;
  OssEncOID(const char *);
  OssEncOID & operator = (const char *);
  void replace(OssEncOID &);
  char *get_value() const;
  char *getDotValNotation() const;
  int setDotValNotation(const char *);

};

Methods

OssEncOID(const char *);
This constructor takes a C null-terminated string (ASN.1 value notation of an OBJECT IDENTIFIER value) and converts it to an encoded OBJECT IDENTIFIER value.
OssEncOID & operator = (const char *);
The assignment operator takes a C null-terminated string (ASN.1 value notation of an OBJECT IDENTIFIER value) and converts it to an encoded OBJECT IDENTIFIER value. The old value of the OssEncOID object is deallocated.
void replace(OssEncOID & src);
This is an ownership-transferring function. The value of the src encoded OBJECT IDENTIFIER object is transferred to "this" OBJECT IDENTIFIER object. The src object is emptied, i.e., assigned a zero-length value (note: this is not a legal ASN.1 OBJECT IDENTIFIER value!). The old value of "this" is deallocated.
char *get_value();
Converts the encoded OBJECT IDENTIFIER to ASN.1 value notation and returns the address of the newly allocated character string containing it. The character string is owned by the caller and must be deallocated by the caller using the asn1Free() function when it is no longer needed.
char *getDotValNotation() const;
Converts the representation of an OBJECT IDENTIFIER value from encoded format to dot notation (for example, "1.2.3.4.5") and returns the address of the newly allocated character string containing it. The character string is owned by the caller and must be deallocated by the caller using the asn1Free() function when it is no longer needed.
int setDotValNotation(const char *)
This method takes a C null-terminated string (dot notation of an OBJECT IDENTIFIER value) and converts it to an encoded OBJECT IDENTIFIER value. The old value of the OssEncOID object is deallocated.

OssHugeInt

The --<HUGE>-- directive is used when an ASN.1 INTEGER type should handle very large integer values that cannot be represented by integer types of the underlying computer platform. A specific runtime class named OssHugeInt is used to handle these ASN.1 types. This class has limited capabilities, in particular, it has no arithmetic functions. Values of this type are stored in the form of BER-encoded octet arrays.

NOTE: If your application is creating messages then you will have to initialize values of the OssHugeInt class manually using the class member functions. Generation of initialized C++ values for INTEGER types with the --<HUGE>-- directive is currently not supported.

Definition

class OssHugeInt {
public:
  void *operator new(size_t);
  void operator delete(void *);
  OssHugeInt();
  OssHugeInt(const OssHugeInt &);
  OssHugeInt & operator = (const OssHugeInt &);
  ~OssHugeInt();
  int operator == (const OssHugeInt &) const;
  int operator != (const OssHugeInt &) const;
  OssHugeInt(OSS_UINT32 length, const unsigned char *);
  OSS_UINT32 length() const;
  unsigned char *get_buffer();
  const unsigned char *get_buffer() const;
  void set(OSS_UINT32 length, const unsigned char *);
  // ownership-transferring functions
  unsigned char *release_buffer(OSS_UINT32 & length);
  void grab(OSS_UINT32 length, unsigned char *);
  // higher level functions
  unsigned char & operator [] (OSS_UINT32 pos);
  const unsigned char & operator [] (OSS_UINT32 pos) const;
  unsigned char elem(OSS_UINT32 pos);
};

Methods

OssHugeInt(OSS_UINT32 length, const unsigned char *);
The string is initialized with an unsigned octet array that is supposed to contain a valid BER encoding of the value. The length of the array is determined by the first parameter. The data is copied to the OssHugeInt object. The initial array remains unchanged.
OSS_UINT32 length() const;
This method returns the current length of the OssHugeInt value.
unsigned char * get_buffer();
const unsigned char * get_buffer() const;
These methods return the address of the internal buffer of the object storing the BER encoding. No copying occurs. If the user makes any changes to the array, they will automatically affect the value of the OssHugeInt object. The length of the array can be determined by the length() function.
void set(OSS_UINT32 length, const unsigned char *);
The new value of the OssHugeInt is set from an unsigned char array holding a valid BER encoding. The length of the array is determined by the first parameter. The old OssHugeInt value is destroyed.
unsigned char & operator [] (OSS_UINT32 pos);
const unsigned char & operator [] (OSS_UINT32 pos) const;
These methods return a reference to the octet at the position specified by the parameter. If the position is incorrect, the result is unpredictable.
unsigned char elem(OSS_UINT32 pos) const;
This method returns the octet at the position specified by the parameter. If the position is incorrect, the result is unpredictable.

The following two functions are ownership-transferring functions:

unsigned char * release_buffer(OSS_UINT32 &);
This method returns a pointer of the internal buffer holding the BER encoding. The length of the array is assigned to the first parameter. The OssHugeInt object is reset to a zero-length value. The returned value is now owned by the caller. The caller is responsible for deallocating it using the asn1Free() function when needed.
void grab(OSS_UINT32 length, unsigned char *);
This method sets a new value to the OssHugeInt object. The address of the encoding is defined by the second parameter; its length is defined by the first parameter. The source array must be dynamically allocated with the asn1Malloc() function. After the call, this array becomes owned by the OssHugeInt object. No data copying occurs. The user should not deallocate it or use it in another ownership-transferring function.

OssDecimal

This class represents the ASN.1 REAL type with the --<DECIMAL>-- compiler directive applied.

Definition

class OssDecimal {
public:
  void *operator new(size_t);
  void operator delete(void *);
  static const OssDecimal & PlusInfinity;
  static const OssDecimal & MinusInfinity;
  OssDecimal();
  OssDecimal(const OssDecimal &);
  OssDecimal & operator = (const OssDecimal &);
  ~OssDecimal();
  int operator == (const OssDecimal &) const;
  int operator != (const OssDecimal &) const;
  OssDecimal(const char *);
  void set(const char *);
  void grab(char *);
  char *get_value();
  const char *get_value() const;
  char *release_value();
  int isPlusInfinity() const;
  int isMinusInfinity() const;
};

Methods

OssDecimal(const char *);
void set(const char *);
These methods set an OssDecimal value from a C null-terminated string. The string is copied to the object's internal buffer. The original string remains unchanged.
void grab(char *);
This method sets an OssDecimal value from a C null-terminated string. This is an ownership-transferring function. Memory for the string must be allocated using the asn1Malloc() function. No copying occurs. After the call, the string becomes owned by the OssDecimal object. The user should not deallocate the source string or use it in any other ownership-transferring function after the call.
char * get_value();
const char * get_value() const;
These methods return the address of the C null-terminated string that represents the value of the OssDecimal object. No copying occurs. If the user makes any changes to the string, they will automatically affect the value of the OssDecimal object.
char * release_value();
This method returns the address of the C null-terminated string that represents the value of the OssDecimal object. This is an ownership-transferring function. The OssDecimal object is reset to an empty value; the returned string is considered to be owned by the caller after the call. The caller is responsible for deallocating it using the asn1Free() function when needed.
const OssDecimal OssDecimal::PlusInfinity;
const OssDecimal OssDecimal::MinusInfinity;
These special static objects represent special OssDecimal values.
int isPlusInfinity() const;
int isMinusInfinity() const;
These methods return 1 if "this" has a value of PLUS-INFINITY or MINUS-INFINITY respectively, and 0 otherwise.

OssGeneralizedTime

This class is generated for the GeneralizedTime type. The internal representation of the value is merely a character string, so manipulations with individual components of the value (such as year, month, day, etc.) are slow, but the encoding/decoding is fast. Besides encoding/decoding efficiency, this representation has an additional advantage: you can set its value to an arbitrary character string. This feature is useful for representing times that cannot be set with the component mutator functions, e.g., times with resolution finer than 1 millisecond. Note, however, that if you set a time value to some non-standard string, component mutators and accessors are not guaranteed to work with this value. All manipulations are your own responsibility. The component accessor/mutators regard an OssGeneralizedTime value as consisting of the following components:

  • year - the year; the type uses full four-digit values for the year
  • month - the month (between 1 and 12)
  • day - the day (between 1 and 31)
  • hour - the hour (between 0 and 23)
  • minute - the minute (between 0 and 59)
  • second - the second (between 0 and 59)
  • millisec - the number of milliseconds (between 0 and 999)
  • mindiff - the time zone difference in minutes; significant only if the UTC flag is not set
  • utc - the UTC flag; it acts as a Boolean value; if it has a non-zero value, the OssGeneralizedTime value represents UTC time; otherwise it represents the time of the time zone specified by the mindiff component.

Definition

class OssGeneralizedTime {
public:
  void *operator new(size_t);
  void operator delete(void *);
  OssGeneralizedTime();
  OssGeneralizedTime(const OssGeneralizedTime &);
  OssGeneralizedTime & operator = (const OssGeneralizedTime &);
  ~OssGeneralizedTime();
  int operator == (const OssGeneralizedTime &) const;
  int operator != (const OssGeneralizedTime &) const;
  OssGeneralizedTime(unsigned short year, unsigned short month,
    unsigned short day,
    unsigned short hour = 0, unsigned short minute = 0,
    unsigned short second = 0, unsigned short millisec = 0,
    short mindiff = 0, int utc = 0);
  OssGeneralizedTime(const char *);
  void set_value(const char *);
  const char *get_value() const;
  int set_components(unsigned year, unsigned month, unsigned day,
    unsigned hour = 0, unsigned minute = 0,
    unsigned second = 0, unsigned fraction = 0, unsigned short precision = 3,
    int mindiff = 0, int utc = 0);
  int get_components(unsigned &year, unsigned &month, unsigned &day,
    unsigned &hour, unsigned &minute,
    unsigned &second, unsigned &fraction, unsigned short &precision,
    int &mindiff, int &utc);

  int set_year(unsigned short year);
  unsigned short get_year() const;
  int set_month(unsigned short month);
  unsigned short get_month() const;
  int set_day(unsigned short day);
  unsigned short get_day() const;
  int set_hour(unsigned short hour);
  unsigned short get_hour() const;
  int set_minute(unsigned short minute);
  unsigned short get_minute() const;
  int set_second(unsigned short second);
  unsigned short get_second() const;
  int set_millisec(unsigned short millisec);
  unsigned short get_millisec() const;
  int set_mindiff(short mindiff);
  short get_mindiff() const;
  int set_utc(int utc);
  int get_utc() const;
};

Methods

OssGeneralizedTime(unsigned short year, unsigned short month, unsigned short day, unsigned short hour = 0, unsigned short minute = 0, unsigned short second = 0, unsigned short millisec = 0, short mindiff = 0, int utc = 0);
This constructor allows creation of an OssGeneralizedTime object from a list of components. Note that all fields except year, month, and day are zero by default so you do not need to specify them explicitly.
OssGeneralizedTime(const char *);
This method sets the value of the OssGeneralizedTime object to an arbitrary null-terminated C character string passed as the parameter. The string is copied to the internal buffer of the object. No checks for validity of the string are made.
void set_value(const char *);
The same as the previous constructor but sets the value of an already existing object instead of creating a new one. The old value of the object is deallocated.
const char * get_value() const;
This method returns the pointer to the internal buffer of the OssGeneralizedTime value. The buffer contains a null-terminated C character string. If you want to manipulate the string, you can copy it to another place.
int set_components(unsigned year, unsigned month, unsigned day, unsigned hour = 0, unsigned minute = 0, unsigned second = 0, unsigned fraction = 0, unsigned short precision = 3, int mindiff = 0, int utc = 0);
This method assigns a new value to an OssGeneralizedTime object. The new value is defined by a set of components. This is more efficient than changing the components one at a time. Note that all fields except year, month, and day are zero by default so you do not need to specify them explicitly. The fraction parameter is used to hold the fractional part of the seconds (e.g., milliseconds), the precision parameter specifies the number of decimal digits in the fractional part (i.e., if the fractional part is specified in milliseconds, precision should be set to 3). Note that you can specify the fractional part with any precision. Other parameters specify other logical components of the time value (i.e., year, month, etc.) Note that if utc is not 0, mindiff is ignored. The method returns 0 if successful; otherwise, it returns a non-zero error code.
int get_components(unsigned &year, unsigned &month, unsigned &day, unsigned &hour, unsigned &minute, unsigned &second, unsigned &fraction, unsigned short &precision, int &mindiff, int &utc);
This method extracts components from an OssGeneralizedTime object. The components are placed into variables passed as parameters. This is more efficient than getting one component at a time. The function returns 0 if successful; otherwise, it returns a non-zero error code.
int set_year(unsigned short year);
This method sets the year component of the OssGeneralizedTime value. All the other components retain their values. It returns 0 if the setting was successful; otherwise a non-zero error code is returned (e.g., the old value has been set to a non-standard character string).
unsigned short get_year() const;
This method returns the year component of the OssGeneralizedTime value. It returns the year component of the value. If the runtime was not able to split the value into components, 0 is returned (if you don't use exception throwing from the error handling function).
int set_month(unsigned short month);
This method sets the month component of the OssGeneralizedTime value. All the other components retain their values. It returns 0 if the setting was successful; otherwise a non-zero error code is returned (e.g., the old value has been set to a non-standard character string).
unsigned short get_month() const;
This method returns the month component of the OssGeneralizedTime value. If the runtime was not able to split the value into components, then the value 0 is returned (if you don't use exception throwing from the error handling function).
int set_day(unsigned short day);
This method sets the day component of the OssGeneralizedTime value. All the other components retain their values. It returns 0 if the setting was successful; otherwise a non-zero error code is returned (e.g., the old value has been set to a non-standard character string).
unsigned short get_day() const;
This method returns the day component of the OssGeneralizedTime value. If the runtime was not able to split the value into components, 0 is returned (if you don't use exception throwing from the error handling function).
int set_hour(unsigned short hour);
This method sets the hour component of the OssGeneralizedTime value. All the other components retain their values. It returns 0 if the setting was successful; otherwise a non-zero error code is returned (e.g., the old value has been set to a non-standard character string).
unsigned short get_hour() const;
This method returns the hour component of the OssGeneralizedTime value. If the runtime was not able to split the value into components, 0 is returned (if you don't use exception throwing from the error handling function).
int set_minute(unsigned short minute);
This method sets the minute component of the OssGeneralizedTime value. All the other components retain their values. It returns 0 if the setting was successful; otherwise a non-zero error code is returned (e.g., the old value has been set to a non-standard character string).
unsigned short get_minute() const;
This method returns the minute component of the OssGeneralizedTime value. If the runtime was not able to split the value into components, 0 is returned (if you don't use exception throwing from the error handling function).
int set_second(unsigned short second);
This method sets the second component of the OssGeneralizedTime value. All the other components retain their values. It returns 0 if the setting was successful; otherwise a non-zero error code is returned (e.g., the old value has been set to a non-standard character string).
unsigned short get_second() const;
This method returns the second component of the OssGeneralizedTime value. If the runtime was not able to split the value into components, 0 is returned (if you don't use exception throwing from the error handling function).
int set_millisec(unsigned short millisec);
This method sets the millisec component of the OssGeneralizedTime value. All the other components retain their values. It returns 0 if the setting was successful; otherwise a non-zero error code is returned (e.g., the old value has been set to a non-standard character string).
unsigned short get_millisec() const;
This method returns the millisec component of the OssGeneralizedTime value. If the runtime was not able to split the value into components, 0 is returned (if you don't use exception throwing from the error handling function).
int set_mindiff(short mindiff);
This method sets the mindiff component of the OssGeneralizedTime value. All the other components retain their values. Note that if the utc component of the value is non-zero, the mindiff component is ignored. It returns 0 if the setting was successful; otherwise a non-zero error code is returned (e.g., the old value has been set to a non-standard character string).
short get_mindiff() const;
This method returns the mindiff component of the OssGeneralizedTime value. If the runtime was not able to split the value into its components, 0 is returned (if you don't use exception throwing from the error handling function).
int set_utc(int utc);
This method sets the utc component of the OssGeneralizedTime value. All the other components retain their values except that the mindiff component is automatically set to 0 when the utc component is set to 1. The parameter is a Boolean value; all non-zero values are considered equivalent and mean that the value represents UTC time. A zero value of the parameter means that the value is the time of the time zone specified by the mindiff component. It returns 0 if the setting was successful; otherwise a non-zero error code is returned (e.g., when the object has been set to a non-standard character string).
int get_utc() const;
This method returns the utc component of the OssGeneralizedTime value. It returns 0 or 1 depending on the utc component of the value (if you don't use exception throwing from the error handling function).

OssUTCTime

This class is generated for the UTCTime type. The internal representation of the value is merely a character string, so manipulations with individual components of the value (such as year, month, day, etc.) are slow, but the encoding/decoding is fast. Besides encoding/decoding efficiency, this representation has an additional advantage: you can set its value to an arbitrary character string. This feature is useful for representing times that cannot be set with the component mutator functions, e.g., times with resolution finer than 1 millisecond. Note, however, that if you set a time value to some non-standard string, component mutators and accessors are not guaranteed to work with this value. All manipulations are your responsibility. The component accessor/mutators regard an OssUTCTime value as consisting of the following components:

  • year - the year; UTCTime uses two-digit values for the year but the ASN.1/C++ Runtime does not check or use this facility;
  • month - the month (between 1 and 12);
  • day - the day (between 1 and 31);
  • hour - the hour (between 0 and 23);
  • minute - the minute (between 0 and 59);
  • second - the second (between 0 and 59);
  • mindiff - the time zone difference in minutes; significant only if the UTC flag is not set;
  • utc - the UTC flag; it acts as a Boolean value; if it has a non-zero value, the OssUTCTime value represents UTC time; otherwise it represents the time of the time zone specified by the mindiff component.

Definition

class OssUTCTime {
public:
  void *operator new(size_t);
  void operator delete(void *);
  OssUTCTime();
  OssUTCTime(const OssUTCTime &);
  OssUTCTime & operator = (const OssUTCTime &);
  ~OssUTCTime();
  int operator == (const OssUTCTime &) const;
  int operator != (const OssUTCTime &) const;
  OssUTCTime(unsigned short year, unsigned short month, unsigned short day,
        unsigned short hour = 0, unsigned short minute = 0,
        unsigned short second = 0, short mindiff = 0, int utc = 0);
  OssUTCTime(const char *);
  void set_value(const char *);
  const char *get_value() const;
  int set_components(unsigned year, unsigned month, unsigned day,
            unsigned hour = 0, unsigned minute = 0,
            unsigned second = 0, int mindiff = 0, int utc = 0);
  int get_components(unsigned &year, unsigned &month, unsigned &day,
            unsigned &hour, unsigned &minute,
            unsigned &second, int &mindiff, int &utc);
  int set_year(unsigned short year);
  unsigned short get_year() const;
  int set_month(unsigned short month);
  unsigned short get_month() const;
  int set_day(unsigned short day);
  unsigned short get_day() const;
  int set_hour(unsigned short hour);
  unsigned short get_hour() const;
  int set_minute(unsigned short minute);
  unsigned short get_minute() const;
  int set_second(unsigned short second);
  unsigned short get_second() const;
  int set_mindiff(short mindiff);
  short get_mindiff() const;
  int set_utc(int utc);
  int get_utc() const;
};

Methods

OssUTCTime(unsigned short year, unsigned short month, unsigned short day, unsigned short hour = 0, unsigned short minute = 0, unsigned short second = 0, short mindiff = 0, int utc = 0);
This constructor allows the creation of an OssUTCTime object from a list of components. Note that all fields except year, month, and day are zero by default, so you need not specify them explicitly.
OssUTCTime(const char *);
This constructor sets the value of the OssUTCTime object to an arbitrary null-terminated C character string passed as the parameter. The string is copied to the internal buffer of the object. No checks for validity of the string are made.
void set_value(const char *);
The same as the previous constructor but sets the value of an already existing object instead of creating a new one. The old value of the object is deallocated.
const char * get_value() const;
This method returns a pointer to the internal buffer of the OssUTCTime value. The buffer contains a null-terminated C character string. If you want to manipulate the string, you can copy it to another place.
int set_components(unsigned year, unsigned month, unsigned day, unsigned hour = 0, unsigned minute = 0, unsigned second = 0, int mindiff = 0, int utc = 0);
This method assigns a new value to an OssUTCTime object. The new value is defined by a set of components. This is more efficient than changing the components one at a time. Note that all fields except year, month, and day are zero by default so you do not need to specify them explicitly. Note also that if utc is not 0, mindiff is ignored. The function returns 0 if successful; otherwise, it returns a non-zero error code.
int get_components(unsigned &year, unsigned &month, unsigned &day, unsigned &hour, unsigned &minute, unsigned &second, int &mindiff, int &utc);
This method extracts components from an OssUTCTime object. The components are placed into variables passed as parameters. This is more efficient than getting one component at a time. The function returns 0 if successful; otherwise, it returns a non-zero error code.
int set_year(unsigned short year);
This method sets the year component of the OssUTCTime value. All the other components retain their values. It returns 0 if the setting was successful; otherwise a non-zero error code is returned (e.g., the old value has been set to a non-standard character string).
unsigned short get_year() const;
This method returns the year component of the OssUTCTime value. If the runtime was not able to split the value into components, 0 is returned (if you don't use exception throwing from the error handling function).
int set_month(unsigned short month);
This method sets the month component of the OssUTCTime value. All the other components retain their values. It returns 0 if the setting was successful; otherwise a non-zero error code is returned (e.g., the old value has been set to a non-standard character string).
unsigned short get_month() const;
This method returns the month component of the OssUTCTime value. If the runtime was not able to split the value into components, 0 is returned (if you don't use exception throwing from the error handling function).
int set_day(unsigned short day);
This method sets the day component of the OssUTCTime value. All the other components retain their values. It returns 0 if the setting was successful; otherwise a non-zero error code is returned (e.g., the old value has been set to a non-standard character string).
unsigned short get_day() const;
This method returns the day component of the OssUTCTime value. If the runtime was not able to split the value into components, 0 is returned (if you don't use exception throwing from the error handling function).
int set_hour(unsigned short hour);
This method sets the hour component of the OssUTCTime value. All the other components retain their values. It returns 0 if the setting was successful; otherwise a non-zero error code is returned (e.g., the old value has been set to a non-standard character string).
unsigned short get_hour() const;
This method returns the hour component of the OssUTCTime value. If the runtime was not able to split the value into components, 0 is returned (if you don't use exception throwing from the error handling function).
int set_minute(unsigned short minute);
This method sets the minute component of the OssUTCTime value. All the other components retain their values. It returns 0 if the setting was successful; otherwise a non-zero error code is returned (e.g., the old value has been set to a non-standard character string).
unsigned short get_minute() const;
This method returns the minute component of the OssUTCTime value. If the runtime was not able to split the value into components, 0 is returned (if you don't use exception throwing from the error handling function).
int set_second(unsigned short second);
This method sets the second component of the OssUTCTime value. All the other components retain their values. It returns 0 if the setting was successful; otherwise a non-zero error code is returned (e.g., the old value has been set to a non-standard character string).
unsigned short get_second() const;
This method returns the second component of the OssUTCTime value. If the runtime was not able to split the value into components, 0 is returned (if you don't use exception throwing from the error handling function).
int set_mindiff(short mindiff);
This method sets the mindiff component of the OssUTCTime value. All the other components retain their values. Note that if the utc component of the value is non-zero, the mindiff component is ignored. It returns 0 if the setting was successful; otherwise a non-zero error code is returned (e.g., the old value has been set to a non-standard character string).
short get_mindiff() const;
This method returns the mindiff component of the OssUTCTime value. If the runtime was not able to split the value into its components, 0 is returned (if you don't use exception throwing from the error handling function).
int set_utc(int utc);
This method sets the utc component of the OssUTCTime value. All the other components retain their values except that the mindiff component is automatically set to 0 when the utc component is set to 1. The parameter is a Boolean value; all non-zero values are considered equivalent and mean that the value represents UTC time. The zero value of the parameter means that the value is the time of the time zone specified by the mindiff component. It returns 0 if the setting was successful; otherwise a non-zero error code is returned (e.g., when the object has been set to a non-standard character string).
int get_utc() const;
This method returns the utc component of the OssUTCTime value. It returns 0 or 1 depending on the utc component of the value (if you don't use exception throwing from the error handling function).

OssRelOID

The OssRelOID class implements the ASN.1 RELATIVE-OID type. This representation does not allow access to individual arcs of the RELATIVE-OID type. The internal representation is a BER-encoded byte string.

Definition

class OssRelOID {
public:
  void *operator new(size_t);
  void operator delete(void *);
  OssRelOID();
  OssRelOID(const OssRelOID &);
  OssRelOID(const char *);
  ~OssRelOID();
  OssRelOID & operator = (const OssRelOID &);
  OssRelOID & operator = (const char *);
  int operator == (const OssRelOID &) const;
  int operator != (const OssRelOID &) const;
  void replace(OssRelOID &);
  char *get_value() const;
  char *getDotValNotation() const;
  int setDotValNotation(const char *);
};

Methods

OssRelOID(const char *);
This constructor takes a C null-terminated string (ASN.1 value notation of an RELATIVE-OID value) and converts it to an encoded RELATIVE-OID value. The input string is unchanged after the call.
OssRelOID & operator = (const char *);
The assignment operator takes a null-terminated C string (ASN.1 value notation of an RELATIVE-OID value) and converts it to an encoded RELATIVE-OID value. The old value of the OssRelOID object is deallocated.
void replace(OssRelOID & src);
This is an ownership-transferring function. The value of src, an encoded RELATIVE-OID object, is transferred to "this" RELATIVE-OID object. The src object is emptied, i.e., assigned a zero-length value (note: this is not a legal ASN.1 RELATIVE-OID value!). The old value of "this" is deallocated.
char *get_value() const;
Converts the encoded RELATIVE-OID to ASN.1 value notation and returns the address of the newly allocated character string containing it. The character string is owned by the caller and must be deallocated by the caller using the asn1Free() function when it is no longer needed.
char *getDotValNotation() const;
Converts the representation of a RELATIVE-OID value from encoded format to dot notation (for example, "200.300.400") and returns the address of the newly allocated character string containing it. The character string is owned by the caller and must be deallocated by the caller using the asn1Free() function when it is no longer needed.
int setDotValNotation(const char *)
The method takes a C null-terminated string (dot notation of a RELATIVE-OID value) and converts it to an encoded RELATIVE-OID value. The old value of the OssRelOID object is deallocated.

OssExtensions

The OssExtensions class represents unknown extension additions in an extensible SEQUENCE/SET if the -relaySafe compiler option is specified in the compiler command line (see Effect of the Extensibility Marker and the -relaySafe Option). Logically, it is a collection of OCTET STRINGs. Each OCTET STRING contains an encoding of an extension addition that was not decoded by the decoder.

Note: The existing API provides only the simplest accessor functions. Currently, you cannot change OssExtensions objects. The only way to create a non-empty OssExtensions object is to decode some PDU with unknown extension additions. If you need the ability to manually specify unknown extension additions, contact OSS Nokalva.

Definition

class OssExtensions {
public:
    void *operator new(size_t);
    void operator delete(void *);
    int operator == (const OssExtensions &) const;
    int operator != (const OssExtensions &) const;
    OSS_UINT32 size() const;
    OssString * get_ext(OSS_UINT32 num);
    const OssString * get_ext(OSS_UINT32 num) const;
};

Methods

OSS_UINT32 size() const;
Returns the number of extension additions present in the object.
OssString *get_ext(OSS_UINT32 num);
const OssString *get_ext(OSS_UINT32 num) const;
Returns a pointer to the extension addition with the specified number. The returned object remains owned by the OssExtensions object. You should not delete it. If num >= size, there is no extension addition with the specified number, and the function returns NULL.

Note: Unknown extension additions are stored differently depending on the encoding rules used. For BER, each extension addition is stored separately in the TLV form. For PER, an extension group is stored as a single extension addition, starting from the optional mask of the extension group. XER does not support -relaySafe in versions prior to 4.1.

OssAlternative

The OssAlternative class represents unknown alternatives in an extensible CHOICE type if the -relaySafe compiler option is specified in the compiler command line (see Effect of the Extensibility Marker and the -relaySafe Option). Logically, it consists of an integer alternative index and an OCTET STRING. The OCTET STRING contains an encoding of the alternative that was not decoded by the decoder.

Note: The existing API provides only the simplest accessor functions. Currently, you cannot change OssAlternative objects. The only way to create a non-empty OssAlternative object is to decode some PDU containing a CHOICE with an unknown alternative. If you need the ability to manually specify unknown alternatives, contact OSS Nokalva.

Definition

class OssAlternative {
public:
    void *operator new(size_t);
    void operator delete(void *);
    int operator == (const OssAlternative &) const;
    int operator != (const OssAlternative &) const;
    ~OssAlternative();
    OSS_UINT32 index() const;
    OssString & value();
    const OssString & value() const;
};

Methods

OSS_UINT32 index() const;
Returns the index of the unknown alternative. For BER, it is the BER tag. For PER, it is the PER index.
OssString & value();
const OssString &value() const;
Returns a pointer to the encoded unknown alternative value. The returned object remains owned by the OssExtensions object. You should not delete it.

OssTime

This class is generated for the ISO 8601 time types (TIME and the retagged useful types – DATE, DATE-TIME, TIME-OF-DAY, and DURATION). The OssTime type is just a container for a character string. You can assign any string to it. The validity of the string as a time value representation is checked only by the encoder/decoder. To access subcomponents of the time value, use the ISO 8601 Time Utility Classes.

Definition

class OssTime
{
public:
    void *operator new(size_t);
    void operator delete(void *);
    OssTime();
    OssTime(const OssTime &);
    OssTime & operator = (const OssTime &);
    ~OssTime();
    int operator == (const OssTime &) const;
    int operator != (const OssTime &) const;
    OssTime(const OssTimePoint &);
    OssTime(const OssDuration &);
    OssTime(const OssTimeInterval &);
    OssTime(const char *);
    void set_value(const char *);
    const char *get_value() const;
    int is_time_point() const;
    int is_duration() const;
    int is_interval() const;
    int get_time_point(OssTimePoint &) const;
    int get_duration(OssDuration &) const;
    int get_interval(OssTimeInterval &) const;
    int set_time_point(const OssTimePoint &);
    int set_duration(const OssDuration &);
    int set_interval(const OssTimeInterval &);
};

Methods

OssTime(const OssTimePoint &);
This constructor allows the creation of an OssTime object from an OssTimePoint utility class value, which represents a particular time point. The constructor converts the OssTimePoint value to string form and stores the result in the object being created. If the input value is invalid per ITU-T Recommendation X.680:2015, the constructor fails with an error reported by the ASN.1/C++ mechanism; see Error Handling.
OssTime(const OssDuration &);
This constructor allows the creation of an OssTime object from an OssDuration utility class value, which represents a certain duration of time. The constructor converts the OssDuration value to string form and stores the result in the object being created. If the input value is invalid per ITU-T Recommendation X.680:2015, the constructor fails with an error reported by the ASN.1/C++ mechanism; see Error Handling.
OssTime(const OssTimeInterval &);
This constructor allows the creation of an OssTime object from an OssTimeInterval utility class value, which represents a particular time interval. The constructor converts the OssTimeInterval value to string form and stores the result in the object being created. If the input value is invalid per ITU-T Recommendation X.680:2015, the constructor fails with an error reported by the ASN.1/C++ mechanism; see Error Handling.
OssTime(const char *);
This constructor sets the value of the OssTime object to an arbitrary null-terminated C character string that is passed as the parameter. The string is copied to the internal buffer of the object. No checks for the validity of the string are made.
void set_value(const char *);
This function sets the value of the OssTime object to an arbitrary null-terminated C character string that is passed as the parameter. The string is copied to the internal buffer of the object. The old value is deallocated. No checks for the validity of the input string are made.
const char *get_value() const;
This function returns the current value of the OssTime object in the form of a null-terminated C character string.
int is_time_point() const;
This function returns 1 if the current value of the OssTime object is a time point, which can be represented as an OssTimePoint value, and 0 otherwise.
int is_duration() const;
This function returns 1 if the current value of the OssTime object is a duration of time, which can be represented as an OssDuration value, and 0 otherwise.
int is_interval() const;
This function returns 1 if the current value of the OssTime object is a time interval, which can be represented as an OssTimeInterval value, and 0 otherwise. Note that a duration value is also a valid instance of a time interval, so if is_duration() returns 1 for some object, is_interval() also returns 1 for that object.
int get_time_point(OssTimePoint &) const;
This function parses the character string contained in the OssTime object and fills the OssTimePoint object passed as the parameter according to the string. If the parsing is successful, the function returns 0. If the current value of the object is not a time point, the function returns a non-zero error code (if the error handling function is not set to throw exceptions) and the parameter object is unchanged.
int get_duration(OssDuration &) const;
This function parses the character string contained in the OssTime object and fills the OssDuration object passed as the parameter according to the string. If the parsing is successful, the function returns 0. If the current value of the object is not a duration of time, the function returns a non-zero error code (if the error handling function is not set to throw exceptions) and the parameter object is unchanged.
int get_interval(OssTimeInterval &) const;
This function parses the character string contained in the OssTime object and fills the OssTimeInterval object passed as the parameter according to the string. If the parsing is successful, the function returns 0. If the current value of the object is not a time interval, the function returns a non-zero error code (if the error handling function is not set to throw exceptions) and the parameter object is unchanged.
int set_time_point(const OssTimePoint &);
This function converts the OssTimePoint object passed as the parameter to the string form and assigns the resulting string to the OssTime object. If the conversion is successful, the function returns 0. If the conversion is unsuccessful (e.g., the input object contains an invalid value for a time point), the function returns a non-zero error code (if the error handling function is not set to throw exceptions) and the OssTime object is unchanged.
int set_duration(const OssDuration &);
This function converts the OssDuration object passed as the parameter to the string form and assigns the resulting string to the OssTime object. If the conversion is successful, the function returns 0. If the conversion is unsuccessful (e.g., the input object contains an invalid value for a duration of time), the function returns a non-zero error code (if the error handling function is not set to throw exceptions) and the OssTime object is unchanged.
int set_interval(const OssTimeInterval &);
This function converts the OssTimeInterval object passed as the parameter to the string form and assigns the resulting string to the OssTime object. If the conversion is successful, the function returns 0. If the conversion is unsuccessful (e.g., the input object contains an invalid value for a time interval), the function returns a non-zero error code (if the error handling function is not set to throw exceptions) and the OssTime object is unchanged.

This documentation applies to release 6.5 and later of the OSS® ASN.1 Tools for C++.

Copyright © 2017 OSS Nokalva, Inc. All rights reserved.
No part of this publication may be reproduced, stored in a retrieval system, or transmitted in any form or by any means electronic, mechanical, photocopying, recording or otherwise, without the prior permission of OSS Nokalva, Inc.
Every distributed copy of the OSS® ASN.1 Tools for C++ is associated with a specific license and related unique license number. That license determines, among other things, what functions of the OSS ASN.1 Tools for C++ are available to you.