]> git.saurik.com Git - apple/security.git/blob - SecuritySNACCRuntime/doc/c++-lib.tex
Security-28.tar.gz
[apple/security.git] / SecuritySNACCRuntime / doc / c++-lib.tex
1 % file: .../doc/c++-lib.tex
2
3 % $Header: /cvs/Darwin/Security/SecuritySNACCRuntime/doc/c++-lib.tex,v 1.1.1.1 2001/05/18 23:14:10 mb Exp $
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
18 The following sections describe the C++ representation of the
19 non-aggregate ASN.1 types, ANY and ANY DEFINED BY types and
20 the buffer and memory management. These classes and routines make
21 up the C++ ASN.1 runtime library. Every aggregate ASN.1 type will be
22 composed of these library types. The source files for this library
23 are in {\ufn \dots/c++-lib/inc/} and {\ufn \dots/c++-lib/src/}.
24
25 As mentioned in the last chapter, each ASN.1 type is represented by a
26 C++ class which inherits from the {\C AsnType} base class. In
27 addition to the standard encode, decode, print and clone methods
28 described in the last chapter, each ASN.1 type class in the library
29 may also have special constructors and other routines that simplify
30 their use.
31
32 Unlike the classes generated for some of the aggregate types such as
33 SETs and SEQUENCEs, the library types' data members are typically
34 protected and accessed via methods.
35
36 All of the library classes' {\C BDec} routines will report tagging errors
37 via {\C longjmp()} as described in section~\ref{type-gen-C++-section}.
38
39 The top level PDU encode and decode methods are the same for all
40 library types so they are defined as macros in
41 {\ufn \dots/c++-lib/inc/asn-config.h}. For clarity's sake, the macro
42 that is used to define these methods in the library type class
43 definitions will be replaced with the actual prototypes.
44
45 Run the {\ufn test-lib} program in {\ufn \dots/c++-examples/test-lib/}
46 to make sure the library routines are working properly for your
47 architecture. The testing is not exhaustive but should point out
48 obvious problems.
49
50
51 \section{\label{tag-C++-section}Tags}
52
53 The C++ tags are identical to those used in snacc's C ASN.1
54 environment. While it would have been nice to define a tag class, the
55 performance cost would likely have been noticeable. Also, the snacc
56 users usually do not have to muck around with tags directly, so the
57 lack of a class interface will probably not be missed. The C ASN.1
58 tags are described in Section~\ref{tag-C-section}.
59
60 Initially I defined a C++ class for tags, but close examination of the
61 produced assembly code led me to reject it. The C++ class for tags
62 used the C tag representation internally and had constructor, encode
63 and decode methods. The constructor could not be used as
64 {\C switch} statement case labels like {\C MAKE\_TAG\_ID} because it
65 did not reduce to an integer constant; this caused problems in the
66 generated decoders.
67
68 As with the C representation of tags, 4 byte long integers limit the
69 maximum representable tag code to $2^{21}$. Again, this should not be
70 a problem.
71
72
73 \section{\label{len-C++-section}Lengths}
74
75 The C++ representation of lengths is the same at the C representation
76 described in Section~\ref{len-C-section}. The length type was not given
77 its own C++ class for reasons similar to those of tags.
78
79
80 \section{\label{asntype-C++-section}The AsnType Base Class}
81
82 Every ASN.1 type's C++ class uses the {\C AsnType} as its base class.
83 The {\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
98 The {\C AsnType} class is defined as follows:
99 \begin{Ccode}
100 class AsnType\\
101 \{\\
102 public:\+\\
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\\
125 public:\+\\
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
135 The {\C AsnType} class and its virtual functions were added to
136 support the ANY DEFINED BY type handling mechanism. This mechanism is
137 described in Section~\ref{any-C++-section}.
138
139 Even 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
141 common to all of the types, such as changing the {\C new} and
142 {\C delete} functions to improve performance.
143
144 Virtual functions provide the simplest method of handling ANY DEFINED
145 BY and ANY types. Unfortunately, calls to virtual functions are slower
146 than calls to normal functions due to their indirect nature. If you
147 do not need support for the ANY DEFINED BY or ANY types you can remove
148 most 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
152 Note that a virtual destructor is included in the {\C AsnType} base
153 class as well. This is done to make sure the {\C delete} routine
154 always 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
159 The BOOLEAN type is represented by the {\C AsnBool} class. The
160 following is the class definition of {\C AsnBool} from the
161 {\ufn \dots/c++-lib/inc/asn-bool.h} file.
162
163 \begin{Ccode}
164 class AsnBool: public AsnType\\
165 \{\\
166 protected:\+\\
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
201 The upcoming C++ standard \cite{c++-draft} defines a type {\C bool} accompanied by {\C false} and {\C true} to denote the boolean values.
202 The Snacc configuration script checks whether the C++ compiler already supplies this new type and defines a look-alike if it does not.
203
204 For backwards compatibility, {\C AsnBool::true} and {\C AsnBool::false} are still valid.
205
206 The {\C operator bool()} is defined such that when an {\C AsnBool}
207 value is cast to a boolean, it returns the C++ style boolean
208 value of the {\C AsnBool}s value. There is also a constructor for {\C AsnBool}
209 that builds an {\C AsnBool} value from the given C++ style boolean
210 value. These two methods allow you to manipulate and access
211 {\C AsnBool} values in a straight forward way as the following code
212 illustrates.
213 \begin{Ccode}
214 Message::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
226 The {\C AsnBool} class contains the standard encode and decode
227 methods that were described in Chapter~\ref{c++-code-gen-chapter}.
228
229 {\C BDecContent} will report an error via {\C longjmp} if the
230 length of an encoded BOOLEAN value's content is not exactly 1 octet.
231
232 Note that the {\C Clone} method returns an {\C AsnType~*} value
233 instead 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
235 an {\C AsnType}. However, it must return an {\C AsnType~*} for it
236 to override the virtual function {\C Clone} defined in the
237 {\C AsnType}.
238
239 The {\C Print} method will print either ``TRUE'' or ``FALSE''
240 depending on the {\C AsnBool} value. No newline or other formatting
241 characters are printed. The global indent information does not affect
242 the output from this method.
243
244
245 \section{\label{int-C++-section}INTEGER}
246
247 The INTEGER type is represented by the {\C AsnInt} class. The
248 following is the class definition of {\C AsnInt} from the
249 {\ufn \dots/c++-lib/inc/asn-int.h} file.
250 \begin{Ccode}
251 class AsnInt: public AsnType\\
252 \{\\
253 protected:\+\\
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
293 The internal representation of an ASN.1 INTEGER value is a {\C AsnIntType}.
294 This 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.
295 The types' sizes depend on the machine and compiler and are determined at configuration time.
296 The {\C BDecContent} routine will signal an error if the integer
297 value being decoded will not fit into the {\C AsnIntType}
298 representation.
299
300 Unlike the C ASN.1 library, the non-negative
301 %{\C unsigned long int}
302 version of
303 INTEGER is not provided. If you need it, it should be relatively
304 trivial to combine the C unsigned version with the existing C++ class.
305 The unsigned version of an integer is useful if your ASN.1 source uses
306 subtyping similar to:
307 \begin{ASNcode}
308 Counter ::= [APPLICATION 1] IMPLICIT INTEGER (0..4294967295)
309 \end{ASNcode}
310
311 \section{\label{enum-C++-section}ENUMERATED}
312
313 The ENUMERATED type is represented by the {\C AsnEnum} class. The
314 following is the class definition of {\C AsnEnum} from the
315 {\ufn \dots/c++-lib/inc/asn-enum.h} file.
316 \begin{Ccode}
317 class AsnEnum: public AsnInt\\
318 \{\\
319 public:\+\\
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
345 Note 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
349 The NULL type is provided by the {\C AsnNull} class. This class has
350 no data members and includes only the standard methods.
351 \begin{Ccode}
352 class AsnNull: public AsnType\\
353 \{\\
354 public:\+\\
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
385 REAL 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}
389 class AsnReal: public AsnType\\
390 \{\\
391 protected:\\
392 \>double \>\>value;\\
393 \\
394 public:\+\\
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 \\
425 extern const AsnReal \>\>\>PLUS\_INFINITY;\\
426 extern const AsnReal \>\>\>MINUS\_INFINITY;
427 \end{Ccode}
428
429 The {\C double} representation and support routines can depend on
430 the compiler or system you are using so several different encoding
431 routines are provided. Even so, you may need to modify the code.
432
433 There 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.
434 Defining {\C IEEE\_REAL\_FMT} uses the encode routine that assumes the double representation is the standard IEEE double \cite{68881}.
435 Defining {\C IEEE\_REAL\_LIB} uses the encode routine that assumes the IEEE functions library (isinf, scalbn, signbit etc.) is available.
436 If 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}.
439 Currently, 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}
444 and {\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
448 There is only one content decoding routine and it builds the value
449 through multiplication and the {\C pow} routine (requires the math
450 library). The content decoding routine only supports the binary
451 encoding of a REAL, not the decimal encoding.
452
453 \section{\label{bits-C++-section}BIT STRING}
454
455 The BIT STRING type is represented by the {\C AsnBits} class. From\linebreak
456 {\ufn \dots/c++-lib/inc/asn-bits.h}:
457 \begin{Ccode}
458 class AsnBits: public AsnType\\
459 \{\\
460 private:\+\\
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
526 The {\C AsnBits} class contains a pointer to the bits and an
527 integer that holds the length in bits of the BIT STRING\@.
528
529 In addition to the standard methods, the {\C AsnBits} class has
530 methods for initializing and comparing bit string values and methods
531 for setting and getting individual bits in a value.
532
533 An {\C AsnBits} value can be created three ways: from the number of
534 bits, 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
539 individual bits in the BIT STRING value. Given the bit's index,
540 {\C SetBits} sets that bit to one. {\C ClrBit} sets the bit
541 of the given index to zero. The bit indexes start at zero, with zero
542 being the first (most signficant) bit in the BIT STRING\@. {\C GetBit}
543 will return {\C true} if the specified bit is one and {\C false} if the bit is
544 zero. If the given bit index is too large, {\C SetBit} and
545 {\C ClrBit} do nothing and {\C GetBit} returns {\C false}\@.
546
547 The {\C ==} and {\C !=} operators have been overloaded such that
548 given two {\C AsnBits} values, they will behave as expected.
549
550 Each {\C AsnBits} value stores its bit string in a single contiguous
551 block of memory. Received BIT STRING values that were encoded in the
552 constructed form are converted to the simple, flat form (see Section
553 \ref{bits-C-section}). Snacc provides no facility for encoding or
554 internally representing constructed BIT STRING values.
555
556 \section{\label{octets-C++-section}OCTET STRING}
557 OCTET STRING values are represented with the {\C AsnOcts} class.
558 From\linebreak {\ufn \dots/c++-lib/inc/asn-octs.h}:
559 \begin{Ccode}
560 class AsnOcts: public AsnType\\
561 \{\\
562 private:\+\\
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
627 The {\C AsnOcts} class contains a pointer to the octets and an
628 integer that holds the length in octets of the OCTET STRING\@.
629
630 There are four constructors for {\C AsnOcts}. The parameterless
631 constructor will initialize the octet string to zero length with a
632 {\C NULL} octets pointer. The constructor that takes a single {\C char~*}
633 assumes that the given string is NUL terminated and initializes the octet
634 pointer 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
636 include the NUL terminator). The constructor that takes
637 {\C char~*} and a length, {\C len}, initializes the octets pointer
638 to point to a copy of {\C len} characters from the given string and
639 sets the {\C octetLen} to {\C len}. The last constructor will initialize
640 an {\C AsnOcts} value by copying the given {\C AsnOcts} value.
641
642 As with the BIT STRING content decoder, OCTET STRING content decoder
643 can handle constructed values. These are handled in the same way as
644 the constructed BIT STRING values; they are converted to the simple
645 contiguous representation. Every OCTET STRING value will
646 automatically have a NUL terminator appended to it; this extra
647 character will not be included in the string's length and will make
648 some strings easier to deal with for printing etc.
649
650 The {\C operator char~*()} is defined for the {\C AsnOcts} class to
651 return a pointer to the octets. The {\C Len}
652 method returns the length in bytes of the string value.
653 These may be useful for passing the
654 octets to other functions such as {\C memcpy} etc.
655
656 The {\C ==} and {\C !=} operators have been overloaded such that
657 given two {\C AsnOcts} values, they will behave as expected.
658
659
660
661 \section{\label{oid-C++-section}OBJECT IDENTIFIER}
662 OBJECT IDENTIFIER values are represented with the {\C AsnOid} class.
663 From\linebreak {\ufn \dots/c++-lib/inc/asn-oid.h}:
664 \begin{Ccode}
665 class AsnOid: public AsnType\\
666 \{\\
667 private:\\
668 \>int \>\>OidEquiv (AsnOid o);\\
669 \\
670 protected:\+\\
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
737 The {\C AsnOid} stores OBJECT IDENTIFIER values in their encoded form
738 to improve performance. It seems that the most common operation with
739 OBJECT IDENTIFIERs is to compare for equality, for which the encoded
740 representation (which is canonical) works well.
741
742 The {\C AsnOid} is very similar to the {\C AsnOcts} class in all
743 respects, except that its content decoding routine does not need to
744 handle constructed encodings.
745
746 The {\C AsnOid} class has four constructors which are similiar to
747 those of the {\C AsnOcts} class. A special constructor that takes
748 arc numbers as parameters and uses default parameters is provided. An
749 OBJECT IDENTIFIER value must have at least two arc numbers so the
750 first two parameters do not have default values. All of the other
751 parameters are optional; since their default value of {\C --1} is an
752 invalid arc number (they must be positive) they will not be used in the
753 value. 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
755 expensive in terms of CPU time than the others.
756
757 The {\C operator char~*()} is defined for the {\C AsnOid} class to
758 return a pointer to the encoded OBJECT IDENTIFIER value. The {\C Len}
759 method returns the length in bytes of the encode OBJECT IDENTIFIER
760 value (NOT the number arcs in the value). These may be useful for
761 passing 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
764 The {\C ==} and {\C !=} operators have been overloaded such that
765 given two {\C AsnOcts} values, they will behave as expected.
766
767
768
769 \section{\label{list-C++-section}SET OF and SEQUENCE OF}
770
771 In the C ASN.1 library, the list type was in the library because it
772 was 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
774 a 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
779 The ANY DEFINED BY type can be handled automatically by snacc
780 provided you use the SNMP OBJECT-TYPE macro to specify the identifier
781 to type mappings. The identifier can be an INTEGER or OBJECT
782 IDENTIFIER\@. Handling ANY types properly will require modifications to
783 the generated code since there is no identifier associated with the
784 type.
785
786 Look at the C and C++ ANY examples and the {\ufn any.asn1} file
787 included with this release for information on using the OBJECT-TYPE
788 macro. Note that the OBJECT-TYPE macro has been modified slightly to
789 allow INTEGER values (identifiers).
790
791 An ANY DEFINED BY type is represented by the {\C AsnAny} class.
792 The following is from {\ufn \dots/c++-lib/inc/asn-any.h}.
793 \begin{Ccode}
794 /* AnyInfo is a hash table entry */\\
795 class AnyInfo\\
796 \{\\
797 public:\+\\
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 \\
804 class AsnAny: public AsnType\\
805 \{\\
806 public:\+\\
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
832 The C++ mechanism is similar to the C mechanism which uses hash tables
833 to hold the identifier to type mappings. In this section we will
834 discuss the main differences of the C++ ANY DEFINED BY handling
835 mechanism. You should read Section~\ref{any-C-section} for caveats and
836 other important information.
837
838 In C, the hash table entry held the size of the type and pointers to
839 its encode, decode, free etc. routines to describe the type. In C++
840 these have been replaced with a pointer to an instance of the type. A
841 hash 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
848 All 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
863 This allows the ANY DEFINED BY handling routines to treat a value of
864 any ASN.1 type as an {\C AsnType}. So, for each type the ANY
865 DEFINED BY handling code has access to the virtual methods. Note
866 that 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
870 To 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
872 set the identifier field for that ANY DEFINED BY value to the correct
873 identifier (as generated for its OBJECT-TYPE macro value). It is very
874 important to do this correctly because the encoder will simply call
875 the 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
877 the identifier field's value matches the object that was encoded.
878
879 A potential solution to the last identifier problem is to add a type
880 id field to the {\C AsnType} base class. Snacc could generate a
881 unique identifier (that would be stored in the base class) for each
882 type. The encoder could then check identifiers between the value
883 being encoded and the value stored in the hash table. The identifier
884 in the base class could easily be automatically set (correctly) from
885 the constructors for each type (constructors are snacc generated). It
886 would be difficult to ensure unique identifiers for each type between
887 modules if the ASN.1 modules were compiled separately.
888
889 Before an ANY DEFINED BY value can be decoded, the field that contains
890 its identifier must have been decoded and used with the {\C AsnAny}
891 value's {\C SetTypeByInt} or {\C SetTypeByOid} methods. Then the
892 ANY DEFINED BY value can be decoded by calling its ({\C AsnAny})
893 {\C BDec} routine. This in turn calls the {\C Clone} routine on
894 the type in the hash table entry to generate the correct object. Then
895 the {\C BDec} method of the newly created object is called.
896
897 When the C ANY DEFINED BY decoder allocates a value, it uses the size
898 information for the identified type. This is not safe for C++ so the
899 virtual {\C Clone} routine was added to the {\C AsnType} base
900 class. This allows the proper constructor mechanism to be used when
901 allocating the value.
902
903 The virtual {\C Clone} routine simply calls its type's parameterless
904 constructor via {\C new} (hence every ASN.1 type's class must have a
905 parameterless constructor). {\C Clone} is a poor name since
906 the routine only produces a new instance of the given type without
907 copying the original's data.
908
909 The hash tables are automatically initialized using the C++ constructor
910 mechanism. You do not need to call any initialization routines as
911 described in the C chapter.
912
913
914 \section{\label{buffer-C++-section}Buffer Management}
915
916 The C++ buffer management provided with snacc is similar to that of
917 the C {\C SBuf}s. The following is from
918 {\ufn \dots/c++-lib/inc/asn-buf.h}:
919 \begin{Ccode}
920 class AsnBuf\\
921 \{\\
922 protected:\+\\
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
955 This is the only buffer type provided with the C++ library.
956
957 \section{\label{mem-C++-section}Dynamic Memory Management}
958
959 The built-in C++ memory management system is used by snacc ({\C new}
960 and {\C delete}). Better performance might be gained by using a
961 different management scheme.
962
963 To change {\C new} and {\C delete} to use your own memory
964 management scheme the best way to start is by defining them as virtual
965 in the {\C AsnType} base class. More information on providing your
966 own memory management can be found in Stroustrup \cite{stroustrup}.
967
968 \section{\label{error-C++-section}Error Management}
969
970 The C++ ASN.1 error management is identical to that of the C ASN.1
971 model. C++ exception handling ({\C try} and {\C throw}) were not
972 used to replace {\C setjmp()} and {\C longjmp()} because they were not
973 implemented by the C++ compiler we used.