TOC PREV NEXT INDEX


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.

Dynamic BIT STRING

      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 initialize the value and methods for setting the value.

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 {
 
   OSUINT32 numbits;
 
   const OSOCTET* data;
 
} ASN1DynBitStr;
 


The ASN1TDynBitStr type is defined in the asn1CppTypes.h header file as follows:

struct ASN1TDynBitStr : public ASN1DynBitStr {
 
   // ctors
 
   ASN1TDynBitStr () : numbits(0) {}
 
   ASN1TDynBitStr (OSUINT32 _numbits, OSOCTET* _data);
 
   ASN1TDynBitStr (ASN1DynBitStr& _bs);
 
} ASN1TDynBitStr;
 

Note that memory management of the byte array containing the bit string data is the responsibility of the user. The wrapper class does not free the memory on destruction nor deep-copy the data when a string is copied.

Static (sized) BIT STRING

    ASN.1 production:   <name> ::= BIT STRING (SIZE (<len>))
 

    Generated C code:    typedef struct {
 
 		            OSUINT32 numbits;
 
		            OSOCTET  data[<adjusted_len>*];
 
		         } <name>;
 

    Generated C++ code:  typedef struct {
 
		            OSUINT32 numbits;
 
		            OSOCTET  data[<adjusted_len>*];
 
		            // ctors
 
		            ASN1T_<name> ();
 
		            ASN1T_<name> (OSUINT32 _numbits, const OSOCTET* _data);
 
		         } ASN1T_<name>;
 

 
             * <adjusted_len> = ((<len> - 1)/8) + 1
 

For example, the following ASN.1 production:

	BS ::= [PRIVATE 220] BIT STRING (SIZE (18))
 

Would translate to the following C typedef:

typedef struct ASN1T_BS {
 
   OSUINT32 numbits;
 
   OSOCTET  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.


Named Bits

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 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 bits 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.

For example, the following ASN.1 production:

	NamedBS ::= BIT STRING { bitOne(1), bitTen(10) }


 
Would translate to the following if -genBitMacros was specified:

 
/* 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 {
 
   OSUINT32 numbits;
 
   OSOCTET 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);
 

The statement to clear the bit using rtClearBit would be as follows:

	rtClearBit (bs.data, 10, NamedBS_bitOne);
 

Finally, the bit could be tested using rtTestBit with the following statement:

	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.

ASN1CBitStr Control Class

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:

ASN1CBitStr bs (<seqVar>.<element>);
bs.set (0);

In this example, <seqVar> would represent a generated SEQUENCE variable type and <element> would represent a bit string element within this type.

See the section on the ASN1CBitStr class in the ASN1C C/C++ Common Run-time User's Manual for details on all of the methods available in this class.



Objective Systems, Inc.

102 Pickering Way, Suite #506
Exton, 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
TOC PREV NEXT INDEX