
BIT STRING
The ASN.1 BIT STRING type is converted into a C or C++ structured type containing an integer to hold the number of bits and an array of unsigned characters ("OCTETs") to hold the bit string contents. The number of bits integer specifies the actual number of bits used in the bit string and takes into account any unused bits in the last byte.
The type definition of the contents field depends on how the bit string is specified in the ASN.1 definition. If a size constraint is used, a static array is generated; otherwise, a pointer variable is generated to hold a dynamically allocated string. The decoder will automatically allocate memory to hold a parsed string based on the received length of the string.
In the static case, the length of the character array is determined by adjusting the given size value (which represents the number of bits) into the number of bytes required to hold the bits.
ASN.1 production: <name> ::= BIT STRING Generated C code: typedef ASN1DynBitStr <name>; Generated C++ code: typedef ASN1TDynBitStr ASN1T_<name>;In this case, different base types are used for C and C++. The difference between the two is the C++ version includes constructors that make setting the value a bit easier.
The ASN1DynBitStr type (i.e., the type used in the C mapping) is defined in the asn1type.h header file as follows:
typedef struct ASN1DynBitStr { ASN1UINT numbits; ASN1OCTET* data; } ASN1DynBitStr;struct ASN1TDynBitStr : public ASN1DynBitStr { // ctors ASN1TDynBitStr () : numbits(0) {} ASN1TDynBitStr (ASN1UINT _numbits, ASN1OCTET* _data); ASN1TDynBitStr (ASN1DynBitStr& _bs); } ASN1TDynBitStr;ASN.1 production: <name> ::= BIT STRING (SIZE (<len>))Generated C code: typedef struct { int numbits; ASN1OCTET data[<adjusted_len>*]; } <name>;Generated C++ code: typedef struct { int numbits; ASN1OCTET data[<adjusted_len>*]; // ctors ASN1T_<name> (); ASN1T_<name> (ASN1UINT _numbits, ASN1OCTET* _data); } ASN1T_<name>; * <adjusted_len> = ((<len> - 1)/8) + 1BS ::= [PRIVATE 220] BIT STRING (SIZE (18))typedef struct ASN1T_BS { ASN1UINT numbits; ASN1OCTET data[3]; } ASN1T_BS;In this case, three octets would be required to hold the 18 bits: eight in the first two bytes, and two in the third.
Note that for C++, ASN1C generates special constructors and assignment operators to make populating a structure easier. In this case, two constructors were generated: a default constructor and one that takes numbits and data as arguments.
In the ASN.1 standard, it is possible to define an enumerated bit string that specifies named constants for different bit positions. ASN1C provides support for this type of construct by generating symbolic constants and optional macros that can be used to set, clear, or test these named bits. These symbolic constants equate the bit name to the bit number defined in the specification. They can be used with the rtBitSet, rtBitClear, and rtBitTest run-time functions to set, clear, and test the named bits. In addition, generated C++ code contains an enumerated constant added to the control class with an entry for each of the bit numbers. These entries can be used in calls to the methods of the ASN1CBitStr class to set, clear, and test bits.
The -genBitMacros command line option can be used to generate macros to set, clear, or test the named bit in a bit string structure. These macros offer better performance then using the run-time functions because all calculations of mask and index values are done at compile time. The drawback is they can result in a large amount of additional generated code.
NamedBS ::= BIT STRING { bitOne(1), bitTen(10) }/* Named bit constants */ #define NamedBS_bitOne 1 #define SET_BS3_bitOne(bs) \ <code to set bit..> #define CLEAR_BS3_bitOne(bs) \ <code to clear bit..> #define TEST_BS3_bitOne(bs) \ <code to test bit..> #define NamedBS_bitTen 10 #define SET_BS3_bitTen(bs) \ <code to set bit..> #define CLEAR_BS3_bitTen(bs) \ <code to clear bit..> #define TEST_BS3_bitTen(bs) \ <code to test bit..> /* Type definitions */ typedef struct ASN1T_NamedBS { ASN1UINT numbits; ASN1OCTET data[2]; } NamedBS;The named bit constants would be used to access the data array within the ASN1T_NamedBS type. If bit macros were not generated, the rtSetBit function could be used to set the named bit `bitOne' with the following code:
NamedBS bs; memset (&bs, 0, sizeof(bs)); rtSetBit (bs.data, 10, NamedBS_bitOne);rtClearBit (bs.data, 10, NamedBS_bitOne);if (rtTestBit (bs.data, 10, NamedBS_bitOne) { ... bit is set }Note that the compiler generated a fixed length data array for this specification. It did this because the maximum size of the string is known due to the named bits - it must only be large enough to hold the maximum valued named bit constant.
When C++ code generation is specified, a control class is generated for operating on the target bit string. This class is derived from the ASN1CBitStr class. This class contains methods for operating on bits within the string.
Objects of this class can also be declared inline to make operating on bits within other ASN.1 constructs easier. For example, in a SEQUENCE containing a bit string element the generated type will contain a public member variable containing the `ASN1T' type that holds the message data. If one wanted to operate on the bit string contained within that element, they could do so by using the ASN1CBitStr class inline as follows:
In this example, <seqVar> would represent a generated SEQUENCE variable type and <element> would represent a bit string element within this type.
Objective Systems, Inc.102 Pickering Way, Suite #506Exton, Pennsylvania 19341 http://www.obj-sys.com Phone: (484) 875-9841 Toll-free: (877) 307-6855 (US only) Fax: (484) 875-9830 info@obj-sys.com |