Security-54.1.9.tar.gz
[apple/security.git] / SecuritySNACCRuntime / doc / c++-lib.tex
CommitLineData
bac41a7b
A
1% file: .../doc/c++-lib.tex
2
a66d0d4a 3% $Header: /cvs/root/Security/SecuritySNACCRuntime/doc/Attic/c++-lib.tex,v 1.1.1.1 2001/05/18 23:14:10 mb Exp $
bac41a7b
A
4% $Log: c++-lib.tex,v $
5% Revision 1.1.1.1 2001/05/18 23:14:10 mb
6% Move from private repository to open source repository
7%
8% Revision 1.1.1.1 1999/03/16 18:05:51 aram
9% Originals from SMIME Free Library.
10%
11% Revision 1.1 1997/01/01 22:47:37 rj
12% first check-in
13%
14
15\chapter{\label{lib-C++-chapter}C++ ASN.1 Library}
16\section{\label{libover-C++-section}Overview}
17
18The following sections describe the C++ representation of the
19non-aggregate ASN.1 types, ANY and ANY DEFINED BY types and
20the buffer and memory management. These classes and routines make
21up the C++ ASN.1 runtime library. Every aggregate ASN.1 type will be
22composed of these library types. The source files for this library
23are in {\ufn \dots/c++-lib/inc/} and {\ufn \dots/c++-lib/src/}.
24
25As mentioned in the last chapter, each ASN.1 type is represented by a
26C++ class which inherits from the {\C AsnType} base class. In
27addition to the standard encode, decode, print and clone methods
28described in the last chapter, each ASN.1 type class in the library
29may also have special constructors and other routines that simplify
30their use.
31
32Unlike the classes generated for some of the aggregate types such as
33SETs and SEQUENCEs, the library types' data members are typically
34protected and accessed via methods.
35
36All of the library classes' {\C BDec} routines will report tagging errors
37via {\C longjmp()} as described in section~\ref{type-gen-C++-section}.
38
39The top level PDU encode and decode methods are the same for all
40library types so they are defined as macros in
41{\ufn \dots/c++-lib/inc/asn-config.h}. For clarity's sake, the macro
42that is used to define these methods in the library type class
43definitions will be replaced with the actual prototypes.
44
45Run the {\ufn test-lib} program in {\ufn \dots/c++-examples/test-lib/}
46to make sure the library routines are working properly for your
47architecture. The testing is not exhaustive but should point out
48obvious problems.
49
50
51\section{\label{tag-C++-section}Tags}
52
53The C++ tags are identical to those used in snacc's C ASN.1
54environment. While it would have been nice to define a tag class, the
55performance cost would likely have been noticeable. Also, the snacc
56users usually do not have to muck around with tags directly, so the
57lack of a class interface will probably not be missed. The C ASN.1
58tags are described in Section~\ref{tag-C-section}.
59
60Initially I defined a C++ class for tags, but close examination of the
61produced assembly code led me to reject it. The C++ class for tags
62used the C tag representation internally and had constructor, encode
63and decode methods. The constructor could not be used as
64{\C switch} statement case labels like {\C MAKE\_TAG\_ID} because it
65did not reduce to an integer constant; this caused problems in the
66generated decoders.
67
68As with the C representation of tags, 4 byte long integers limit the
69maximum representable tag code to $2^{21}$. Again, this should not be
70a problem.
71
72
73\section{\label{len-C++-section}Lengths}
74
75The C++ representation of lengths is the same at the C representation
76described in Section~\ref{len-C-section}. The length type was not given
77its own C++ class for reasons similar to those of tags.
78
79
80\section{\label{asntype-C++-section}The AsnType Base Class}
81
82Every ASN.1 type's C++ class uses the {\C AsnType} as its base class.
83The {\C AsnType} base class provides the following virtual functions:
84\begin{itemize}
85 \item the destructor
86 \item {\C Clone()}
87 \item {\C BDec()}
88 \item {\C BEnc()}
89 \item {\C Print()}
90 \item {\C \_getdesc()} (metacode)
91 \item {\C \_getref()} (metacode)
92 \item {\C TclGetDesc()} (Tcl interface)
93 \item {\C TclGetVal()} (Tcl interface)
94 \item {\C TclSetVal()} (Tcl interface)
95 \item {\C TclUnsetVal()} (Tcl interface)
96\end{itemize}
97
98The {\C AsnType} class is defined as follows:
99\begin{Ccode}
100class AsnType\\
101\{\\
102public:\+\\
103 virtual \>\>\~{}AsnType();\\
104\\
105\<\#ifdef SUPPORT\_ANY\_TYPE\\
106 virtual AsnType \>\>*Clone() const;\\
107 virtual void \>\>BDec (BUF\_TYPE b, AsnLen \&bytesDecoded, ENV\_TYPE env);\\
108 virtual AsnLen \>\>BEnc (BUF\_TYPE b);\\
109\<\#else\\
110 void \>\>BDec (BUF\_TYPE b, AsnLen \&bytesDecoded, ENV\_TYPE env) \{\}\\
111 AsnLen \>\>BEnc (BUF\_TYPE b) \{ return 0; \}\\
112\<\#endif\\
113 virtual void \>\>Print (ostream \&os) const;\\
114\\
115\<\#if META\\
116 static const AsnTypeDesc \>\>\_desc;\\
117\\
118 virtual const AsnTypeDesc \>\>*\_getdesc() const;\\
119 virtual AsnType \>\>*\_getref (const char *membername, bool create=false);\\
120\\
121\<private:\\
122 const char \>\>*\_typename() const;\\
123\-\\
124\#if TCL\\
125public:\+\\
126 virtual int \>\>TclGetDesc (Tcl\_DString *) const;\\
127 virtual int \>\>TclGetVal (Tcl\_Interp *) const;\\
128 virtual int \>\>TclSetVal (Tcl\_Interp *, const char *val);\\
129 virtual int \>\>TclUnsetVal (Tcl\_Interp *, const char *membernames);\-\\
130\#endif // TCL\\
131\#endif // META\\
132\};
133\end{Ccode}
134
135The {\C AsnType} class and its virtual functions were added to
136support the ANY DEFINED BY type handling mechanism. This mechanism is
137described in Section~\ref{any-C++-section}.
138
139Even if you do not use the ANY or ANY DEFINED BY types, the
140{\C AsnType} base class may be useful for adding features that are
141common to all of the types, such as changing the {\C new} and
142{\C delete} functions to improve performance.
143
144Virtual functions provide the simplest method of handling ANY DEFINED
145BY and ANY types. Unfortunately, calls to virtual functions are slower
146than calls to normal functions due to their indirect nature. If you
147do not need support for the ANY DEFINED BY or ANY types you can remove
148most of the virtual functions to improve performance by undefining the
149{\C SUPPORT\_ANY\_TYPE} symbol (see the
150{\ufn asn-type.h} file).
151
152Note that a virtual destructor is included in the {\C AsnType} base
153class as well. This is done to make sure the {\C delete} routine
154always gets the correct size. See pages 215--217 of Stroustrup
155\cite{stroustrup} for a discussion of this.
156
157\section{\label{bool-C++-section}BOOLEAN}
158
159The BOOLEAN type is represented by the {\C AsnBool} class. The
160following is the class definition of {\C AsnBool} from the
161{\ufn \dots/c++-lib/inc/asn-bool.h} file.
162
163\begin{Ccode}
164class AsnBool: public AsnType\\
165\{\\
166protected:\+\\
167 bool \>\>value;\\
168\\
169\<public:\\
170 \>\>AsnBool (const bool val): value (val) \{\};\\
171 \>\>AsnBool() \{\};\\
172 AsnType \>\>*Clone() const;\\
173 \>\>operator bool() const \{ return value; \}\\
174 AsnBool \>\>\&operator = (bool newvalue) \{ value = newvalue; return *this; \}\\
175\\
176 AsnLen \>\>BEnc (BUF\_TYPE b);\\
177 void \>\>BDec (BUF\_TYPE b, AsnLen \&bytesDecoded, ENV\_TYPE env);\\
178\\
179 AsnLen \>\>BEncContent (BUF\_TYPE b);\\
180 void \>\>BDecContent (BUF\_TYPE b, AsnTag tagId, AsnLen elmtLen,\\
181 \`AsnLen \&bytesDecoded, ENV\_TYPE env);\\
182\\
183 int \>\>BEncPdu (BUF\_TYPE b, AsnLen \&bytesEncoded);\\
184 int \>\>BDecPdu (BUF\_TYPE b, AsnLen \&bytesDecoded);\\
185\\
186 void \>\>Print (ostream \&os) const;\\
187\\
188\<\#if META\\
189 static const AsnBoolTypeDesc \>\>\_desc;\\
190\\
191 const AsnTypeDesc \>\>*\_getdesc() const;\\
192\\
193\<\#if TCL\\
194 int \>\>TclGetVal (Tcl\_Interp *) const;\\
195 int \>\>TclSetVal (Tcl\_Interp *, const char *val);\-\\
196\#endif // TCL\\
197\#endif // META\\
198\};
199\end{Ccode}
200
201The upcoming C++ standard \cite{c++-draft} defines a type {\C bool} accompanied by {\C false} and {\C true} to denote the boolean values.
202The Snacc configuration script checks whether the C++ compiler already supplies this new type and defines a look-alike if it does not.
203
204For backwards compatibility, {\C AsnBool::true} and {\C AsnBool::false} are still valid.
205
206The {\C operator bool()} is defined such that when an {\C AsnBool}
207value is cast to a boolean, it returns the C++ style boolean
208value of the {\C AsnBool}s value. There is also a constructor for {\C AsnBool}
209that builds an {\C AsnBool} value from the given C++ style boolean
210value. These two methods allow you to manipulate and access
211{\C AsnBool} values in a straight forward way as the following code
212illustrates.
213\begin{Ccode}
214Message::Send()\\
215\{\+\\
216 AsnBool \>\>okToSend;\\
217 bool \>\>connectionOpen;\\
218 bool \>\>pduOk;\\
219 \dots\\
220 okToSend = connectionOpen \&\& pduOk; // assign AsnBool from bool\\
221 if (okToSend) // cast AsnBool to bool\\
222 \>\dots\\
223\<\}
224\end{Ccode}
225
226The {\C AsnBool} class contains the standard encode and decode
227methods that were described in Chapter~\ref{c++-code-gen-chapter}.
228
229{\C BDecContent} will report an error via {\C longjmp} if the
230length of an encoded BOOLEAN value's content is not exactly 1 octet.
231
232Note that the {\C Clone} method returns an {\C AsnType~*} value
233instead of an {\C AsnBool~*}. It might be more obvious to return an
234{\C AsnBool~*} since due to single inheritance an {\C AsnBool} is also
235an {\C AsnType}. However, it must return an {\C AsnType~*} for it
236to override the virtual function {\C Clone} defined in the
237{\C AsnType}.
238
239The {\C Print} method will print either ``TRUE'' or ``FALSE''
240depending on the {\C AsnBool} value. No newline or other formatting
241characters are printed. The global indent information does not affect
242the output from this method.
243
244
245\section{\label{int-C++-section}INTEGER}
246
247The INTEGER type is represented by the {\C AsnInt} class. The
248following is the class definition of {\C AsnInt} from the
249{\ufn \dots/c++-lib/inc/asn-int.h} file.
250\begin{Ccode}
251class AsnInt: public AsnType\\
252\{\\
253protected:\+\\
254 AsnIntType \>\>value;\\
255\\
256\<public:\\
257 \>\>AsnInt() \{\}\\
258 \>\>AsnInt (AsnIntType val): value (val) \{\}\\
259\\
260 AsnType \>\>*Clone() const;\\
261\\
262 \>\>operator AsnIntType() \{ return value; \}\\
263 AsnInt \>\>\&operator = (AsnIntType newvalue) \{ value = newvalue; return *this; \}
264\\
265 void \>\>Set (AsnIntType i) \{ value = i; \}\\
266 void \>\>ReSet (AsnIntType i) \{ value = i; \}\\
267\\
268 AsnLen \>\>BEnc (BUF\_TYPE b);\\
269 void \>\>BDec (BUF\_TYPE b, AsnLen \&bytesDecoded, ENV\_TYPE env);\\
270\\
271 AsnLen \>\>BEncContent (BUF\_TYPE b);\\
272 void \>\>BDecContent (BUF\_TYPE b, AsnTag tagId, AsnLen elmtLen,\\
273 \`AsnLen \&bytesDecoded, ENV\_TYPE env);\\
274\\
275 int \>\>BEncPdu (BUF\_TYPE b, AsnLen \&bytesEncoded);\\
276 int \>\>BDecPdu (BUF\_TYPE b, AsnLen \&bytesDecoded);\\
277\\
278 void \>\>Print (ostream \&os) const \{ os <\/< value; \}\\
279\\
280\<\#if META\\
281 static const AsnIntTypeDesc \>\>\_desc;\\
282\\
283 const AsnTypeDesc \>\>*\_getdesc() const;\\
284\\
285\<\#if TCL\\
286 int \>\>TclGetVal (Tcl\_Interp *) const;\\
287 int \>\>TclSetVal (Tcl\_Interp *, const char *val);\-\\
288\#endif /* TCL */\\
289\#endif /* META */\\
290\};
291\end{Ccode}
292
293The internal representation of an ASN.1 INTEGER value is a {\C AsnIntType}.
294This is a {\C typedef}, the real type may be {\C int}, {\C long} or {\C short}, whatever is found to be 32 bits in size.
295The types' sizes depend on the machine and compiler and are determined at configuration time.
296The {\C BDecContent} routine will signal an error if the integer
297value being decoded will not fit into the {\C AsnIntType}
298representation.
299
300Unlike the C ASN.1 library, the non-negative
301%{\C unsigned long int}
302version of
303INTEGER is not provided. If you need it, it should be relatively
304trivial to combine the C unsigned version with the existing C++ class.
305The unsigned version of an integer is useful if your ASN.1 source uses
306subtyping similar to:
307\begin{ASNcode}
308Counter ::= [APPLICATION 1] IMPLICIT INTEGER (0..4294967295)
309\end{ASNcode}
310
311\section{\label{enum-C++-section}ENUMERATED}
312
313The ENUMERATED type is represented by the {\C AsnEnum} class. The
314following is the class definition of {\C AsnEnum} from the
315{\ufn \dots/c++-lib/inc/asn-enum.h} file.
316\begin{Ccode}
317class AsnEnum: public AsnInt\\
318\{\\
319public:\+\\
320\<\#if !TCL\\
321 \>\>AsnEnum(): AsnInt() \{\}\\
322\<\#endif\\
323 \>\>AsnEnum (int i): AsnInt (i) \{\}\\
324\\
325 AsnType \>\>*Clone() const;\\
326\\
327 AsnLen \>\>BEnc (BUF\_TYPE b);\\
328 void \>\>BDec (BUF\_TYPE b, AsnLen \&bytesDecoded, ENV\_TYPE env);\\
329\\
330 AsnLen \>\>BEncContent (BUF\_TYPE b);\\
331 void \>\>BDecContent (BUF\_TYPE b, AsnTag tagId, AsnLen elmtLen,\\
332 \`AsnLen \&bytesDecoded, ENV\_TYPE env);\\
333\\
334 int \>\>BEncPdu (BUF\_TYPE b, AsnLen \&bytesEncoded);\\
335 int \>\>BDecPdu (BUF\_TYPE b, AsnLen \&bytesDecoded);\\
336\\
337\<\#if META\\
338 static const AsnEnumTypeDesc \>\>\_desc;\\
339\\
340 const AsnTypeDesc \>\>*\_getdesc() const;\-\\
341\#endif /* META */\\
342\};
343\end{Ccode}
344
345Note that it is not derived from {\C class AsnType} directly but from {\C class AsnInt} instead.
346
347\section{\label{null-C++-section}NULL}
348
349The NULL type is provided by the {\C AsnNull} class. This class has
350no data members and includes only the standard methods.
351\begin{Ccode}
352class AsnNull: public AsnType\\
353\{\\
354public:\+\\
355 \>\>AsnNull() \{\}\\
356 AsnType \>\>*Clone() const;\\
357\\
358 AsnLen \>\>BEnc (BUF\_TYPE b);\\
359 void \>\>BDec (BUF\_TYPE b, AsnLen \&bytesDecoded, ENV\_TYPE env);\\
360\\
361 AsnLen \>\>BEncContent (BUF\_TYPE b);\\
362 void \>\>BDecContent (BUF\_TYPE b, AsnTag tagId, AsnLen elmtLen,\\
363 \`AsnLen \&bytesDecoded, ENV\_TYPE env);\\
364\\
365 int \>\>BEncPdu (BUF\_TYPE b, AsnLen \&bytesEncoded);\\
366 int \>\>BDecPdu (BUF\_TYPE b, AsnLen \&bytesDecoded);\\
367\\
368 void \>\>Print (ostream \&os) const \{ os <\/< "NULL"; \}\\
369\\
370\<\#if META\\
371 static const AsnNullTypeDesc \>\>\_desc;\\
372\\
373 const AsnTypeDesc \>\>*\_getdesc() const;\\
374\\
375\<\#if TCL\\
376 int \>\>TclGetVal (Tcl\_Interp *) const;\\
377 int \>\>TclSetVal (Tcl\_Interp *, const char *val);\-\\
378\#endif /* TCL */\\
379\#endif /* META */\\
380\};
381\end{Ccode}
382
383\section{\label{real-C++-section}REAL}
384
385REAL types are represented by the {\C AsnReal} class. Internally, a
386{\C double} is used to hold the real value. The following is from
387{\ufn \dots/c++-lib/inc/asn-real.h}:
388\begin{Ccode}
389class AsnReal: public AsnType\\
390\{\\
391protected:\\
392 \>double \>\>value;\\
393\\
394public:\+\\
395 \>\>AsnReal(): value (0.0) \{\}\\
396 \>\>AsnReal (double val): value (val) \{\}\\
397 AsnType \>\>*Clone() const;\\
398 \>\>operator double() const \{ return value; \}\\
399 AsnReal \>\>\&operator = (double newvalue) \{ value = newvalue; return *this; \}\\
400\\
401 AsnLen \>\>BEnc (BUF\_TYPE b);\\
402 void \>\>BDec (BUF\_TYPE b, AsnLen \&bytesDecoded, ENV\_TYPE env);\\
403\\
404 AsnLen \>\>BEncContent (BUF\_TYPE b);\\
405 void \>\>BDecContent (BUF\_TYPE b, AsnTag tagId, AsnLen elmtLen,\\
406 \`AsnLen \&bytesDecoded, ENV\_TYPE env);\\
407\\
408 int \>\>BEncPdu (BUF\_TYPE b, AsnLen \&bytesEncoded);\\
409 int \>\>BDecPdu (BUF\_TYPE b, AsnLen \&bytesDecoded);\\
410\\
411 void \>\>Print (ostream \&os) const \{ os <\/< value; \}\\
412\\
413\<\#if META\\
414 static const AsnRealTypeDesc \>\>\_desc;\\
415\\
416 const AsnTypeDesc \>\>*\_getdesc() const;\\
417\\
418\<\#if TCL\\
419 int \>\>TclGetVal (Tcl\_Interp *) const;\\
420 int \>\>TclSetVal (Tcl\_Interp *, const char *val);\-\\
421\#endif /* TCL */\\
422\#endif /* META */\\
423\};\\
424\\
425extern const AsnReal \>\>\>PLUS\_INFINITY;\\
426extern const AsnReal \>\>\>MINUS\_INFINITY;
427\end{Ccode}
428
429The {\C double} representation and support routines can depend on
430the compiler or system you are using so several different encoding
431routines are provided. Even so, you may need to modify the code.
432
433There are three content encoding routines included and they can be selected by defining one of {\C IEEE\_REAL\_FMT}, {\C IEEE\_REAL\_LIB} or nothing.
434Defining {\C IEEE\_REAL\_FMT} uses the encode routine that assumes the double representation is the standard IEEE double \cite{68881}.
435Defining {\C IEEE\_REAL\_LIB} uses the encode routine that assumes the IEEE functions library (isinf, scalbn, signbit etc.) is available.
436If neither are defined, the default encode routine uses {\C frexp}.
437%The {\ufn \dots/configure} script tries to find the {\C isinf} and {\C finite} functions
438%Look at the related comments in {\ufn \dots/c++-lib/inc/asn-config.h}.
439Currently, the {\ufn \dots/configure} script has not got any checks for the IEEE format or library and therefore does not define any of the symbols. (This should be fixed.)
440
441{\C AsnReal} constants are used to hold {\C PLUS\_INFINITY} and
442{\C MINUS\_INFINITY} values. These values are initialized using the
443{\C AsnReal} constructor mechanism with the {\C AsnPlusInfinity}
444and {\C AsnMinusInfinity} routines. If you do not define
445{\C IEEE\_REAL\_FMT} or {\C IEEE\_REAL\_LIB}, you should rewrite the
446{\C AsnPlusInfinity} routine such that it is correct for your system.
447
448There is only one content decoding routine and it builds the value
449through multiplication and the {\C pow} routine (requires the math
450library). The content decoding routine only supports the binary
451encoding of a REAL, not the decimal encoding.
452
453\section{\label{bits-C++-section}BIT STRING}
454
455The BIT STRING type is represented by the {\C AsnBits} class. From\linebreak
456{\ufn \dots/c++-lib/inc/asn-bits.h}:
457\begin{Ccode}
458class AsnBits: public AsnType\\
459\{\\
460private:\+\\
461 int \>\>BitsEquiv (AsnBits \&ab);\\
462 void \>\>BDecConsBits (BUF\_TYPE b, AsnLen elmtLen,\\
463 \`AsnLen \&bytesDecoded, ENV\_TYPE env);\\
464 void \>\>FillBitStringStk (BUF\_TYPE b, AsnLen elmtLen0,\\
465 \`AsnLen \&bytesDecoded, ENV\_TYPE env);\\
466\<protected:\\
467 size\_t \>\>bitLen;\\
468 char \>\>*bits;\\
469\\
470\<public:\\
471 \>\>AsnBits() \{ bits = NULL; bitLen = 0; \}\\
472 \>\>AsnBits (const size\_t numBits) \{ Set (numBits); \}\\
473 \>\>AsnBits (const char *bitOcts, const size\_t numBits) \\
474 \`\{ Set (bitOcts, numBits); \}\\
475 \>\>AsnBits (const AsnBits \&b) \{ Set (b); \}\\
476 \>\>\~{}AsnBits() \{ delete bits; \}\\
477\\
478 AsnType \>\>*Clone() const;\\
479\\
480 AsnBits \>\>\&operator = (const AsnBits \&b) \{ ReSet (b); return *this; \}\\
481\\
482 size\_t \>\>BitLen() \{ return bitLen; \}\\
483\\
484 bool \>\>operator == (AsnBits \&ab) const \{ return BitsEquiv (ab); \}\\
485 bool \>\>operator != (AsnBits \&ab) const \{ return !BitsEquiv (ab); \}\\
486\\
487 // overwrite existing bits and bitLen values\\
488 void \>\>Set (size\_t numBits);\\
489 void \>\>Set (const char *bitOcts, size\_t numBits);\\
490 void \>\>Set (const AsnBits \&b);\\
491\\
492 // free old bits value, the reset bits and bitLen values\\
493 void \>\>ReSet (const size\_t numBits);\\
494 void \>\>ReSet (const char *bitOcts, size\_t numBits);\\
495 void \>\>ReSet (const AsnBits \&b);\\
496\\
497 void \>\>SetBit (size\_t);\\
498 void \>\>ClrBit (size\_t);\\
499 int \>\>GetBit (size\_t) const;\\
500\\
501 AsnLen \>\>BEnc (BUF\_TYPE b);\\
502 void \>\>BDec (BUF\_TYPE b, AsnLen \&bytesDecoded, ENV\_TYPE env);\\
503\\
504 AsnLen \>\>BEncContent (BUF\_TYPE b);\\
505 void \>\>BDecContent (BUF\_TYPE b, AsnTag tagId, AsnLen elmtLen,\\
506 \`AsnLen \&bytesDecoded, ENV\_TYPE env);\\
507\\
508 int \>\>BEncPdu (BUF\_TYPE b, AsnLen \&bytesEncoded);\\
509 int \>\>BDecPdu (BUF\_TYPE b, AsnLen \&bytesDecoded);\\
510\\
511 void \>\>Print (ostream \&os) const;\\
512\\
513\<\#if META\\
514 static const AsnBitsTypeDesc \>\>\_desc;\\
515\\
516 const AsnTypeDesc \>\>*\_getdesc() const;\\
517\\
518\<\#if TCL\\
519 int \>\>TclGetVal (Tcl\_Interp *) const;\\
520 int \>\>TclSetVal (Tcl\_Interp *, const char *val);\-\\
521\#endif /* TCL */\\
522\#endif /* META */\\
523\};
524\end{Ccode}
525
526The {\C AsnBits} class contains a pointer to the bits and an
527integer that holds the length in bits of the BIT STRING\@.
528
529In addition to the standard methods, the {\C AsnBits} class has
530methods for initializing and comparing bit string values and methods
531for setting and getting individual bits in a value.
532
533An {\C AsnBits} value can be created three ways: from the number of
534bits, from a {\C char~*} and its bit length or from another
535{\C AsnBits} value. Look at the constructors and the {\C Set} and
536{\C ReSet} methods.
537
538{\C SetBit} and {\C ClrBit} can be used for setting the values of
539individual bits in the BIT STRING value. Given the bit's index,
540{\C SetBits} sets that bit to one. {\C ClrBit} sets the bit
541of the given index to zero. The bit indexes start at zero, with zero
542being the first (most signficant) bit in the BIT STRING\@. {\C GetBit}
543will return {\C true} if the specified bit is one and {\C false} if the bit is
544zero. If the given bit index is too large, {\C SetBit} and
545{\C ClrBit} do nothing and {\C GetBit} returns {\C false}\@.
546
547The {\C ==} and {\C !=} operators have been overloaded such that
548given two {\C AsnBits} values, they will behave as expected.
549
550Each {\C AsnBits} value stores its bit string in a single contiguous
551block of memory. Received BIT STRING values that were encoded in the
552constructed form are converted to the simple, flat form (see Section
553\ref{bits-C-section}). Snacc provides no facility for encoding or
554internally representing constructed BIT STRING values.
555
556\section{\label{octets-C++-section}OCTET STRING}
557OCTET STRING values are represented with the {\C AsnOcts} class.
558From\linebreak {\ufn \dots/c++-lib/inc/asn-octs.h}:
559\begin{Ccode}
560class AsnOcts: public AsnType\\
561\{\\
562private:\+\\
563 int \>\>OctsEquiv (const AsnOcts \&o);\\
564 void \>\>FillBitStringStk (BUF\_TYPE b, AsnLen elmtLen0,\\
565 \`AsnLen \&bytesDecoded, ENV\_TYPE env);\\
566 void \>\>BDecConsOcts (BUF\_TYPE b, AsnLen elmtLen,\\
567 \`AsnLen \&bytesDecoded, ENV\_TYPE env);\\
568\\
569\<protected:\\
570 size\_t \>\>octetLen;\\
571 char \>\>*octs;\\
572\\
573\<public:\\
574 // constructor and Set alway copy strings so destructor can always delete\\
575 \>\>AsnOcts(): octs (NULL), octetLen (0) \{\}\\
576 \>\>AsnOcts (const char *str) \{ Set (str); \}\\
577 \>\>AsnOcts (const char *str, const size\_t len) \{ Set (str, len); \}\\
578 \>\>AsnOcts (const AsnOcts \&o) \{ Set (o); \}\\
579 \>\>\~{}AsnOcts() \{ delete octs; \}\\
580 AsnType \>\>*Clone() const;\\
581\\
582 AsnOcts \>\>\&operator = (const AsnOcts \&o) \{ ReSet (o); return *this; \}\\
583 AsnOcts \>\>\&operator = (const char *str) \{ ReSet (str); return *this; \}\\
584\\
585 size\_t \>\>Len() const \{ return octetLen; \}\\
586 \>\>operator const char *() const \{ return octs; \}\\
587 \>\>operator char *() \{ return octs; \}\\
588\\
589 bool \>\>operator == (const AsnOcts \&o) const \{ return OctsEquiv (o); \}\\
590 bool \>\>operator != (const AsnOcts \&o) const \{ return !OctsEquiv (o); \}\\
591\\
592 // these set the octs and octetLen values\\
593 void \>\>Set (const char *str, size\_t len);\\
594 void \>\>Set (const AsnOcts \&o);\\
595 void \>\>Set (const char *str);\\
596\\
597 // these free the old octs value and then reset the octs and octetLen values\\
598 void \>\>ReSet (const char *str, size\_t len);\\
599 void \>\>ReSet (const AsnOcts \&o);\\
600 void \>\>ReSet (const char *str);\\
601\\
602 AsnLen \>\>BEnc (BUF\_TYPE b);\\
603 void \>\>BDec (BUF\_TYPE b, AsnLen \&bytesDecoded, ENV\_TYPE env);\\
604\\
605 AsnLen \>\>BEncContent (BUF\_TYPE b);\\
606 void \>\>BDecContent (BUF\_TYPE b, AsnTag tagId, AsnLen elmtLen,\\
607 \`AsnLen \&bytesDecoded, ENV\_TYPE env);\\
608\\
609 int \>\>BEncPdu (BUF\_TYPE b, AsnLen \&bytesEncoded);\\
610 int \>\>BDecPdu (BUF\_TYPE b, AsnLen \&bytesDecoded);\\
611\\
612 void \>\>Print (ostream \&os) const;\\
613\\
614\<\#if META\\
615 static const AsnOctsTypeDesc \>\>\_desc;\\
616\\
617 const AsnTypeDesc \>\>*\_getdesc() const;\\
618\\
619\<\#if TCL\\
620 int \>\>TclGetVal (Tcl\_Interp *) const;\\
621 int \>\>TclSetVal (Tcl\_Interp *, const char *val);\-\\
622\#endif /* TCL */\\
623\#endif /* META */\\
624\};
625\end{Ccode}
626
627The {\C AsnOcts} class contains a pointer to the octets and an
628integer that holds the length in octets of the OCTET STRING\@.
629
630There are four constructors for {\C AsnOcts}. The parameterless
631constructor will initialize the octet string to zero length with a
632{\C NULL} octets pointer. The constructor that takes a single {\C char~*}
633assumes that the given string is NUL terminated and initializes the octet
634pointer with a pointer to a copy of the given string and sets the
635{\C octetLen} to the {\C strlen} of the string (this does not usually
636include the NUL terminator). The constructor that takes
637{\C char~*} and a length, {\C len}, initializes the octets pointer
638to point to a copy of {\C len} characters from the given string and
639sets the {\C octetLen} to {\C len}. The last constructor will initialize
640an {\C AsnOcts} value by copying the given {\C AsnOcts} value.
641
642As with the BIT STRING content decoder, OCTET STRING content decoder
643can handle constructed values. These are handled in the same way as
644the constructed BIT STRING values; they are converted to the simple
645contiguous representation. Every OCTET STRING value will
646automatically have a NUL terminator appended to it; this extra
647character will not be included in the string's length and will make
648some strings easier to deal with for printing etc.
649
650The {\C operator char~*()} is defined for the {\C AsnOcts} class to
651return a pointer to the octets. The {\C Len}
652method returns the length in bytes of the string value.
653These may be useful for passing the
654octets to other functions such as {\C memcpy} etc.
655
656The {\C ==} and {\C !=} operators have been overloaded such that
657given two {\C AsnOcts} values, they will behave as expected.
658
659
660
661\section{\label{oid-C++-section}OBJECT IDENTIFIER}
662OBJECT IDENTIFIER values are represented with the {\C AsnOid} class.
663From\linebreak {\ufn \dots/c++-lib/inc/asn-oid.h}:
664\begin{Ccode}
665class AsnOid: public AsnType\\
666\{\\
667private:\\
668 \>int \>\>OidEquiv (AsnOid o);\\
669\\
670protected:\+\\
671 size\_t \>\>octetLen;\\
672 char \>\>*oid;\\
673\\
674\<public:\\
675 \>\>AsnOid(): oid (NULL), octetLen (0) \{\}\\
676 \>\>AsnOid (const char *encOid, size\_t len) \{ Set (encOid, len); \}\\
677 \>\>AsnOid (const AsnOid \&o) \{ Set (o); \}\\
678 \>\>AsnOid (unsigned long int a1, unsigned long int a2, long int a3 = -1,\\
679 \`long int a4 = -1, long int a5 = -1, long int a6 = -1, long int a7 = -1,\\
680 \`long int a8 = -1, long int a9 = -1, long int a10 = -1, long int a11 = -1);\\
681 \>\>\~{}AsnOid() \{ delete oid; \}\\
682 AsnType \>\>*Clone() const;\\
683\\
684 AsnOid \>\>\&operator = (const AsnOid \&o) \{ ReSet (o); return *this; \}\\
685\\
686 size\_t \>\>Len() \{ return octetLen; \}\\
687 const char \>\>*Str() const \{ return oid; \}\\
688 \>\>operator const char * () const \{ return oid; \}\\
689 \>\>operator char * () \{ return oid; \}\\
690 unsigned long int \>\>NumArcs() const;\\
691\\
692 bool \>\>operator == (AsnOid \&o) const \{ return OidEquiv (o); \}\\
693 bool \>\>operator != (AsnOid \&o) const \{ return !OidEquiv (o); \}\\
694\\
695 // Set methods overwrite oid and octetLen values\\
696 void \>\>Set (const char *encOid, const size\_t len);\\
697 void \>\>Set (const AsnOid \&o);\\
698\\
699 // first two arc numbers are mandatory. rest are optional since negative arc nums are not allowed in the\\
700 // encodings, use them to indicate the 'end of arc numbers' in the optional parameters\\
701 void \>\>Set (unsigned long int a1, unsigned long int a2, long int a3 = -1,\\
702 \`long int a4 = -1, long int a5 = -1, long int a6 = -1, long int a7 = -1,\\
703 \`long int a8 = -1, long int a9 = -1, long int a10 = -1, long int a11 = -1);\\
704\\
705 // ReSet routines are like Set except the old oid value is freed\\
706 void \>\>ReSet (const char *encOid, const size\_t len);\\
707 void \>\>ReSet (const AsnOid \&o);\\
708 void \>\>ReSet (unsigned long int a1, unsigned long int a2, long int a3 = -1,\\
709 \`long int a4 = -1, long int a5 = -1, long int a6 = -1, long int a7 = -1,\\
710 \`long int a8 = -1, long int a9 = -1, long int a10 = -1, long int a11 = -1);\\
711\\
712 AsnLen \>\>BEnc (BUF\_TYPE b);\\
713 void \>\>BDec (BUF\_TYPE b, AsnLen \&bytesDecoded, ENV\_TYPE env);\\
714\\
715 AsnLen \>\>BEncContent (BUF\_TYPE b);\\
716 void \>\>BDecContent (BUF\_TYPE b, AsnTag tagId, AsnLen elmtLen,\\
717 \`AsnLen \&bytesDecoded, ENV\_TYPE env);\\
718\\
719 int \>\>BEncPdu (BUF\_TYPE b, AsnLen \&bytesEncoded);\\
720 int \>\>BDecPdu (BUF\_TYPE b, AsnLen \&bytesDecoded);\\
721\\
722 void \>\>Print (ostream \&os) const;\\
723\\
724\<\#if META\\
725 static const AsnOidTypeDesc \>\>\_desc;\\
726\\
727 const AsnTypeDesc \>\>*\_getdesc() const;\\
728\\
729\<\#if TCL\\
730 int \>\>TclGetVal (Tcl\_Interp *) const;\\
731 int \>\>TclSetVal (Tcl\_Interp *, const char *val);\-\\
732\#endif /* TCL */\\
733\#endif /* META */\\
734\};
735\end{Ccode}
736
737The {\C AsnOid} stores OBJECT IDENTIFIER values in their encoded form
738to improve performance. It seems that the most common operation with
739OBJECT IDENTIFIERs is to compare for equality, for which the encoded
740representation (which is canonical) works well.
741
742The {\C AsnOid} is very similar to the {\C AsnOcts} class in all
743respects, except that its content decoding routine does not need to
744handle constructed encodings.
745
746The {\C AsnOid} class has four constructors which are similiar to
747those of the {\C AsnOcts} class. A special constructor that takes
748arc numbers as parameters and uses default parameters is provided. An
749OBJECT IDENTIFIER value must have at least two arc numbers so the
750first two parameters do not have default values. All of the other
751parameters are optional; since their default value of {\C --1} is an
752invalid arc number (they must be positive) they will not be used in the
753value. For example to build the value {\C \{1 2 3\}} you simply use
754{\C AsnOid (1, 2, 3)}. This constructor is convenient but is more
755expensive in terms of CPU time than the others.
756
757The {\C operator char~*()} is defined for the {\C AsnOid} class to
758return a pointer to the encoded OBJECT IDENTIFIER value. The {\C Len}
759method returns the length in bytes of the encode OBJECT IDENTIFIER
760value (NOT the number arcs in the value). These may be useful for
761passing the octets to other functions such as {\C memcpy} etc.
762{\C NumArcs} returns the number of arcs that the value is comprised of.
763
764The {\C ==} and {\C !=} operators have been overloaded such that
765given two {\C AsnOcts} values, they will behave as expected.
766
767
768
769\section{\label{list-C++-section}SET OF and SEQUENCE OF}
770
771In the C ASN.1 library, the list type was in the library because it
772was generic and every SET OF and SEQUENCE OF was defined as an
773{\C AsnList}. In C++, a new class is defined every list, providing
774a type safe list mechanism. This was described in the previous chapter.
775
776
777\section{\label{any-C++-section}ANY and ANY DEFINED BY}
778
779The ANY DEFINED BY type can be handled automatically by snacc
780provided you use the SNMP OBJECT-TYPE macro to specify the identifier
781to type mappings. The identifier can be an INTEGER or OBJECT
782IDENTIFIER\@. Handling ANY types properly will require modifications to
783the generated code since there is no identifier associated with the
784type.
785
786Look at the C and C++ ANY examples and the {\ufn any.asn1} file
787included with this release for information on using the OBJECT-TYPE
788macro. Note that the OBJECT-TYPE macro has been modified slightly to
789allow INTEGER values (identifiers).
790
791An ANY DEFINED BY type is represented by the {\C AsnAny} class.
792The following is from {\ufn \dots/c++-lib/inc/asn-any.h}.
793\begin{Ccode}
794/* AnyInfo is a hash table entry */\\
795class AnyInfo\\
796\{\\
797public:\+\\
798 int \>\>anyId; // will be a value from the AnyId enum\\
799 AsnOid \>\>oid; // will be zero len/null if intId is valid\\
800 AsnInt \>\>intId;\\
801 AsnType \>\>*typeToClone;\-\\
802\};\\
803\\
804class AsnAny: public AsnType\\
805\{\\
806public:\+\\
807 static Table \>\>*oidHashTbl; // all AsnAny class instances\\
808 static Table \>\>*intHashTbl; // share these tables\\
809 AnyInfo \>\>*ai; // points to entry in hash tbl for this type\\
810 AsnType \>\>*value;\\
811\\
812 \>\>AsnAny() \{ ai = NULL; value = NULL; \}\\
813\\
814 // class level methods\\
815 static void \>\>InstallAnyByInt (AsnInt intId, int anyId, AsnType *type);\\
816 static void \>\>InstallAnyByOid (AsnOid \&oid, int anyId, AsnType *type);\\
817\\
818 int \>\>GetId() \{ return ai ? ai-->anyId : -1; \}\\
819 void \>\>SetTypeByInt (AsnInt id);\\
820 void \>\>SetTypeByOid (AsnOid \&id);\\
821\\
822 AsnLen \>\>BEnc (BUF\_TYPE b);\\
823 void \>\>BDec (BUF\_TYPE b, AsnLen \&bytesDecoded, ENV\_TYPE env);\\
824\\
825 int \>\>BEncPdu (BUF\_TYPE b, AsnLen \&bytesEncoded);\\
826 int \>\>BDecPdu (BUF\_TYPE b, AsnLen \&bytesDecoded);\\
827\\
828 void \>\>Print (ostream \&os) const \{ value-->Print (os); \}\\
829\<\};
830\end{Ccode}
831
832The C++ mechanism is similar to the C mechanism which uses hash tables
833to hold the identifier to type mappings. In this section we will
834discuss the main differences of the C++ ANY DEFINED BY handling
835mechanism. You should read Section~\ref{any-C-section} for caveats and
836other important information.
837
838In C, the hash table entry held the size of the type and pointers to
839its encode, decode, free etc. routines to describe the type. In C++
840these have been replaced with a pointer to an instance of the type. A
841hash table entry contains:
842\begin{itemize}
843\item {the {\C anyId}}
844\item {the INTEGER or OBJECT IDENTIFIER that maps to it}
845\item {a pointer to an instance of the identified type}
846\end{itemize}
847
848All C++ ASN.1 types use the {\C AsnType} base class which designates the following functions as virtual:
849\begin{itemize}
850 \item the destructor
851 \item {\C Clone()}
852 \item {\C BDec()}
853 \item {\C BEnc()}
854 \item {\C Print()}
855 \item {\C \_getdesc()} (metacode)
856 \item {\C \_getref()} (metacode)
857 \item {\C TclGetDesc()} (Tcl interface)
858 \item {\C TclGetVal()} (Tcl interface)
859 \item {\C TclSetVal()} (Tcl interface)
860 \item {\C TclUnsetVal()} (Tcl interface)
861\end{itemize}
862
863This allows the ANY DEFINED BY handling routines to treat a value of
864any ASN.1 type as an {\C AsnType}. So, for each type the ANY
865DEFINED BY handling code has access to the virtual methods. Note
866that the {\C value} field in the {\C AsnAny} class and the
867{\C typeToClone} field in the {\C AnyInfo} class are both
868{\C AsnType~*}.
869
870To build an ANY DEFINED BY value, simply set the value field in the
871{\C AsnAny} object to point to the object you want to encode. Then
872set the identifier field for that ANY DEFINED BY value to the correct
873identifier (as generated for its OBJECT-TYPE macro value). It is very
874important to do this correctly because the encoder will simply call
875the virtual {\C BEnc} routine for the object pointed to by the
876{\C AsnAny}'s value field. There is no attempt to make sure that
877the identifier field's value matches the object that was encoded.
878
879A potential solution to the last identifier problem is to add a type
880id field to the {\C AsnType} base class. Snacc could generate a
881unique identifier (that would be stored in the base class) for each
882type. The encoder could then check identifiers between the value
883being encoded and the value stored in the hash table. The identifier
884in the base class could easily be automatically set (correctly) from
885the constructors for each type (constructors are snacc generated). It
886would be difficult to ensure unique identifiers for each type between
887modules if the ASN.1 modules were compiled separately.
888
889Before an ANY DEFINED BY value can be decoded, the field that contains
890its identifier must have been decoded and used with the {\C AsnAny}
891value's {\C SetTypeByInt} or {\C SetTypeByOid} methods. Then the
892ANY DEFINED BY value can be decoded by calling its ({\C AsnAny})
893{\C BDec} routine. This in turn calls the {\C Clone} routine on
894the type in the hash table entry to generate the correct object. Then
895the {\C BDec} method of the newly created object is called.
896
897When the C ANY DEFINED BY decoder allocates a value, it uses the size
898information for the identified type. This is not safe for C++ so the
899virtual {\C Clone} routine was added to the {\C AsnType} base
900class. This allows the proper constructor mechanism to be used when
901allocating the value.
902
903The virtual {\C Clone} routine simply calls its type's parameterless
904constructor via {\C new} (hence every ASN.1 type's class must have a
905parameterless constructor). {\C Clone} is a poor name since
906the routine only produces a new instance of the given type without
907copying the original's data.
908
909The hash tables are automatically initialized using the C++ constructor
910mechanism. You do not need to call any initialization routines as
911described in the C chapter.
912
913
914\section{\label{buffer-C++-section}Buffer Management}
915
916The C++ buffer management provided with snacc is similar to that of
917the C {\C SBuf}s. The following is from
918{\ufn \dots/c++-lib/inc/asn-buf.h}:
919\begin{Ccode}
920class AsnBuf\\
921\{\\
922protected:\+\\
923 char \>\>*dataStart;\\
924 char \>\>*dataEnd;\\
925 char \>\>*blkStart;\\
926 char \>\>*blkEnd;\\
927 char \>\>*readLoc;\\
928 bool \>\>writeError;\\
929 bool \>\>readError;\\
930\\
931\<public:\\
932 void \>\>Init (char *data, size\_t dataLen);\\
933 void \>\>ResetInReadMode();\\
934 void \>\>ResetInWriteRvsMode();\\
935 void \>\>InstallData (char *data, size\_t dataLen);\\
936 size\_t \>\>DataLen();\\
937 char \>\>*DataPtr();\\
938 size\_t \>\>BlkLen();\\
939 char \>\>*BlkPtr();\\
940 bool \>\>Eod();\\
941\\
942 /* the following 9 methods are required */\\
943 bool \>\>ReadError();\\
944 bool \>\>WriteError();\\
945 void \>\>Skip (size\_t skipLen);\\
946 size\_t \>\>CopyOut (char *dst, size\_t copyLen);\\
947 unsigned char \>\>PeekByte();\\
948 char \>\>*GetSeg (size\_t *lenPtr);\\
949 void \>\>PutSegRvs (char *seg, size\_t segLen);\\
950 unsigned char \>\>GetByte();\\
951 void \>\>PutByteRvs (unsigned char byte);\\
952\<\};
953\end{Ccode}
954
955This is the only buffer type provided with the C++ library.
956
957\section{\label{mem-C++-section}Dynamic Memory Management}
958
959The built-in C++ memory management system is used by snacc ({\C new}
960and {\C delete}). Better performance might be gained by using a
961different management scheme.
962
963To change {\C new} and {\C delete} to use your own memory
964management scheme the best way to start is by defining them as virtual
965in the {\C AsnType} base class. More information on providing your
966own memory management can be found in Stroustrup \cite{stroustrup}.
967
968\section{\label{error-C++-section}Error Management}
969
970The C++ ASN.1 error management is identical to that of the C ASN.1
971model. C++ exception handling ({\C try} and {\C throw}) were not
972used to replace {\C setjmp()} and {\C longjmp()} because they were not
973implemented by the C++ compiler we used.