Commit | Line | Data |
---|---|---|
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 | ||
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. |