The ASN.1 ENUMERATED type is converted into different types depending on whether C or C++ code is being generated. The C mapping is either a C enum or integer type depending on whether or not the ASN.1 type is extensible or not. The C++ mapping adds a struct wrapper around this type to provide a namespace to aid in making the enumerated values unique across all modules.
C Mapping
ASN.1 production:
<name> ::= ENUMERATED (<id1>(<val1>), <id2>(<val2>), ...)
Generated code :
typedef enum { id1 = val1, id2 = val2, ... } <name>_Root typedef OSUINT32 <name>;
The compiler will automatically generate a new identifier value if it detects a duplicate within the source specification. The format of this generated identifier is 'id_n' where id is the original identifier and n is a sequential number. The compiler will output an informational message when this is done. This message is only displayed if the -warnings qualifier is specified on the command line.
A configuration setting is also available to further disambiguate duplicate enumerated item names. This is the "enum prefix" setting that is available at both the module and production levels. For example, the following would cause the prefix "h225" to be added to all enumerated identifiers within the H225 module:
<module> <name>H225</name> <enumPrefix>h225</enumPrefix> </module>
The -fqenum (fully-qualified enum) option may also be used to make C names unique. When specified, enumerated identifiers will be automatically prefixed with the enclosing type name. In the specification above, each of the identifiers would have the form "<name>_<id>". This can be useful in situations where common identifiers are often repeated in different types. This is not a problem in C++ because the identifiers are wrapped in a struct declaration which provides a namespace for the values (see the C++ section below for more details).
In addition to the generated type definition, helper functions are also generated to make it easier to convert to/from enumerated and string format. The signatures of these functions are as follows:
const OSUTF8CHAR* <name>_ToString (OSINT32 value); int <name>_ToEnum (OSCTXT* pctxt, const OSUTF8CHAR* value, <name>* pvalue);
The first function would be used to convert an enumerated value into string form. The second would do the opposite - convert from string to enumerated.
C++ Mapping
ASN.1 production:
<name> ::= ENUMERATED (<id1>(<val1>), <id2>(<val2>), ...)
Generated code :
struct <name> { enum Root { id1 = val1, id2 = val2, ... } [ enum Ext { extid1 = extval1, ... } ] } ; typedef OSUINT32 ASN1T_<name>
The struct type provides a namespace for the enumerated elements. This allows the same enumerated constant names to be used in different productions within the ASN.1 specification. An enumerated item is specified in the code using the <name>::<id> form.
Every generated definition contains a Root enumerated specification and, optionally, an Ext specification. The Root specification contains the root elements of the type (or all of the elements if it is not an extended type), and the Ext specification contains the extension enumerated items.
The form of the typedef following the struct specification depends on whether or not the enumerated type contains an extension marker or not. If a marker is present, it means the type can contain values outside the root enumeration. An OSUINT32 is always used in the final typedef to ensure a consistent size of an enumerated variable and to handle the case of unknown extension values.