File: odr.programming.html

package info (click to toggle)
yaz 3.0.34-2
  • links: PTS, VCS
  • area: main
  • in suites: lenny
  • size: 13,404 kB
  • ctags: 12,108
  • sloc: xml: 116,075; ansic: 52,205; sh: 9,746; tcl: 2,043; makefile: 1,141; yacc: 347
file content (494 lines) | stat: -rw-r--r-- 27,369 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
<html><head><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><title>3.�Programming with ODR</title><meta name="generator" content="DocBook XSL Stylesheets V1.73.2"><link rel="start" href="index.html" title="YAZ User's Guide and Reference"><link rel="up" href="odr.html" title="Chapter�8.�The ODR Module"><link rel="prev" href="odr.use.html" title="2.�Using ODR"><link rel="next" href="odr.debugging.html" title="4.�Debugging"></head><body><link rel="stylesheet" type="text/css" href="common/style1.css"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">3.�Programming with ODR</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="odr.use.html">Prev</a>�</td><th width="60%" align="center">Chapter�8.�The ODR Module</th><td width="20%" align="right">�<a accesskey="n" href="odr.debugging.html">Next</a></td></tr></table><hr></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="odr.programming"></a>3.�Programming with ODR</h2></div></div></div><p>
    The API of <acronym class="acronym">ODR</acronym> is designed to reflect the structure of ASN.1, rather
    than BER itself. Future releases may be able to represent data in
    other external forms.
   </p><div class="tip" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Tip</h3><p>
     There is an ASN.1 tutorial available at
     <a class="ulink" href="http://asn1.elibel.tm.fr/en/introduction/" target="_top">this site</a>.
     This site also has standards for ASN.1 (X.680) and BER (X.690) 
     <a class="ulink" href="http://asn1.elibel.tm.fr/en/standards/" target="_top">online</a>.
    </p></div><p>
    The ODR interface is based loosely on that of the Sun Microsystems
    XDR routines.
    Specifically, each function which corresponds to an ASN.1 primitive
    type has a dual function. Depending on the settings of the ODR
    stream which is supplied as a parameter, the function may be used
    either to encode or decode data. The functions that can be built
    using these primitive functions, to represent more complex data types,
    share this quality. The result is that you only have to enter the
    definition for a type once - and you have the functionality of encoding,
    decoding (and pretty-printing) all in one unit.
    The resulting C source code is quite compact, and is a pretty
    straightforward representation of the source ASN.1 specification. 
   </p><p>
    In many cases, the model of the XDR functions works quite well in this
    role.
    In others, it is less elegant. Most of the hassle comes from the optional
    SEQUENCE members which don't exist in XDR.
   </p><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="odr.primitive.asn1.types"></a>3.1.�The Primitive ASN.1 Types</h3></div></div></div><p>
     ASN.1 defines a number of primitive types (many of which correspond
     roughly to primitive types in structured programming languages, such as C).
    </p><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="odr.integer"></a>3.1.1.�INTEGER</h4></div></div></div><p>
      The <acronym class="acronym">ODR</acronym> function for encoding or decoding (or printing) the ASN.1
      INTEGER type looks like this:
     </p><pre class="synopsis">
      int odr_integer(ODR o, int **p, int optional, const char *name);
     </pre><p>
      (we don't allow values that can't be contained in a C integer.)
     </p><p>
      This form is typical of the primitive <acronym class="acronym">ODR</acronym> functions. They are named
      after the type of data that they encode or decode. They take an <acronym class="acronym">ODR</acronym>
      stream, an indirect reference to the type in question, and an
      <code class="literal">optional</code> flag (corresponding to the OPTIONAL keyword
      of ASN.1) as parameters. They all return an integer value of either one
      or zero.
      When you use the primitive functions to construct encoders for complex
      types of your own, you should follow this model as well. This
      ensures that your new types can be reused as elements in yet more
      complex types.
     </p><p>
      The <code class="literal">o</code> parameter should obviously refer to a properly
      initialized <acronym class="acronym">ODR</acronym> stream of the right type (encoding/decoding/printing)
      for the operation that you wish to perform.
     </p><p>
      When encoding or printing, the function first looks at
      <code class="literal">* p</code>. If <code class="literal">* p</code> (the pointer pointed
      to by <code class="literal">p</code>) is a null pointer, this is taken to mean that
      the data element is absent. If the <code class="literal">optional</code> parameter
      is nonzero, the function will return one (signifying success) without
      any further processing. If the <code class="literal">optional</code> is zero, an
      internal error flag is set in the <acronym class="acronym">ODR</acronym> stream, and the function will
      return 0. No further operations can be carried out on the stream without
      a call to the function <code class="function">odr_reset()</code>.
     </p><p>
      If <code class="literal">*p</code> is not a null pointer, it is expected to
      point to an instance of the data type. The data will be subjected to
      the encoding rules, and the result will be placed in the buffer held
      by the <acronym class="acronym">ODR</acronym> stream.
     </p><p>
      The other ASN.1 primitives have similar functions that operate in
      similar manners:
     </p></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="odr.boolean"></a>3.1.2.�BOOLEAN</h4></div></div></div><pre class="synopsis">
int odr_bool(ODR o, bool_t **p, int optional, const char *name);
     </pre></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="odr.real"></a>3.1.3.�REAL</h4></div></div></div><p>
      Not defined.
     </p></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="odr.null"></a>3.1.4.�NULL</h4></div></div></div><pre class="synopsis">
int odr_null(ODR o, bool_t **p, int optional, const char *name);
     </pre><p>
      In this case, the value of **p is not important. If <code class="literal">*p</code>
      is different from the null pointer, the null value is present, otherwise
      it's absent.
     </p></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="odr.octet.string"></a>3.1.5.�OCTET STRING</h4></div></div></div><pre class="synopsis">
typedef struct odr_oct
{
    unsigned char *buf;
    int len;
    int size;
} Odr_oct;

int odr_octetstring(ODR o, Odr_oct **p, int optional,
                    const char *name);
     </pre><p>
      The <code class="literal">buf</code> field should point to the character array
      that holds the octetstring. The <code class="literal">len</code> field holds the
      actual length, while the <code class="literal">size</code> field gives the size
      of the allocated array (not of interest to you, in most cases).
      The character array need not be null terminated.
     </p><p>
      To make things a little easier, an alternative is given for string
      types that are not expected to contain embedded NULL characters (eg.
      VisibleString):
     </p><pre class="synopsis">
      int odr_cstring(ODR o, char **p, int optional, const char *name);
     </pre><p>
      Which encoded or decodes between OCTETSTRING representations and
      null-terminates C strings.
     </p><p>
      Functions are provided for the derived string types, eg:
     </p><pre class="synopsis">
int odr_visiblestring(ODR o, char **p, int optional,
                      const char *name);
     </pre></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="odr.bit.string"></a>3.1.6.�BIT STRING</h4></div></div></div><pre class="synopsis">
int odr_bitstring(ODR o, Odr_bitmask **p, int optional,
                  const char *name);
     </pre><p>
      The opaque type <code class="literal">Odr_bitmask</code> is only suitable for
      holding relatively brief bit strings, eg. for options fields, etc.
      The constant <code class="literal">ODR_BITMASK_SIZE</code> multiplied by 8
      gives the maximum possible number of bits.
     </p><p>
      A set of macros are provided for manipulating the
      <code class="literal">Odr_bitmask</code> type:
     </p><pre class="synopsis">
void ODR_MASK_ZERO(Odr_bitmask *b);

void ODR_MASK_SET(Odr_bitmask *b, int bitno);

void ODR_MASK_CLEAR(Odr_bitmask *b, int bitno);

int ODR_MASK_GET(Odr_bitmask *b, int bitno);
     </pre><p>
      The functions are modeled after the manipulation functions that
      accompany the <code class="literal">fd_set</code> type used by the
      <code class="function">select(2)</code> call.
      <code class="literal">ODR_MASK_ZERO</code> should always be called first on a
      new bitmask, to initialize the bits to zero.
     </p></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="odr.object.identifier"></a>3.1.7.�OBJECT IDENTIFIER</h4></div></div></div><pre class="synopsis">
int odr_oid(ODR o, Odr_oid **p, int optional, const char *name);
     </pre><p>
      The C OID representation is simply an array of integers, terminated by
      the value -1 (the <code class="literal">Odr_oid</code> type is synonymous with
      the <code class="literal">short</code> type).
      We suggest that you use the OID database module (see
      <a class="xref" href="tools.oid.html#tools.oid.database" title="2.1.�OID database">Section�2.1, &#8220;OID database&#8221;</a>) to handle object identifiers
      in your application.
     </p></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="odr.tagging.primitive.types"></a>3.2.�Tagging Primitive Types</h3></div></div></div><p>
     The simplest way of tagging a type is to use the
     <code class="function">odr_implicit_tag()</code> or 
     <code class="function">odr_explicit_tag()</code> macros:
    </p><pre class="synopsis">
int odr_implicit_tag(ODR o, Odr_fun fun, int class, int tag,
                     int optional, const char *name);

int odr_explicit_tag(ODR o, Odr_fun fun, int class, int tag,
                     int optional, const char *name);
    </pre><p>
     To create a type derived from the integer type by implicit tagging, you
     might write:
    </p><pre class="screen">
     MyInt ::= [210] IMPLICIT INTEGER
    </pre><p>
     In the <acronym class="acronym">ODR</acronym> system, this would be written like:
    </p><pre class="screen">
int myInt(ODR o, int **p, int optional, const char *name)
{
    return odr_implicit_tag(o, odr_integer, p,
			    ODR_CONTEXT, 210, optional, name);
}
    </pre><p>
     The function <code class="function">myInt()</code> can then be used like any of
     the primitive functions provided by <acronym class="acronym">ODR</acronym>. Note that the behavior of
     <code class="function">odr_explicit_tag()</code>
     and <code class="function">odr_implicit_tag()</code> macros
     act exactly the same as the functions they are applied to - they
     respond to error conditions, etc, in the same manner - they
     simply have three extra parameters. The class parameter may
     take one of the values: <code class="literal">ODR_CONTEXT</code>,
     <code class="literal">ODR_PRIVATE</code>, <code class="literal">ODR_UNIVERSAL</code>, or
     <code class="literal">/ODR_APPLICATION</code>.
    </p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="odr.constructed.types"></a>3.3.�Constructed Types</h3></div></div></div><p>
     Constructed types are created by combining primitive types. The
      <acronym class="acronym">ODR</acronym> system only implements the SEQUENCE and SEQUENCE OF constructions
     (although adding the rest of the container types should be simple
     enough, if the need arises).
    </p><p>
     For implementing SEQUENCEs, the functions
    </p><pre class="synopsis">
int odr_sequence_begin(ODR o, void *p, int size, const char *name);
int odr_sequence_end(ODR o);
    </pre><p>
     are provided.
    </p><p>
     The <code class="function">odr_sequence_begin()</code> function should be
     called in the beginning of a function that implements a SEQUENCE type.
     Its parameters are the <acronym class="acronym">ODR</acronym> stream, a pointer (to a pointer to the type
     you're implementing), and the <code class="literal">size</code> of the type
     (typically a C structure). On encoding, it returns 1 if
     <code class="literal">* p</code> is a null pointer. The <code class="literal">size</code>
     parameter is ignored. On decoding, it returns 1 if the type is found in
     the data stream. <code class="literal">size</code> bytes of memory are allocated,
     and <code class="literal">*p</code> is set to point to this space.
     <code class="function">odr_sequence_end()</code> is called at the end of the
     complex function. Assume that a type is defined like this:
    </p><pre class="screen">
MySequence ::= SEQUENCE {
     intval INTEGER,
     boolval BOOLEAN OPTIONAL
}
    </pre><p>
     The corresponding <acronym class="acronym">ODR</acronym> encoder/decoder function and the associated data
     structures could be written like this:
    </p><pre class="screen">
typedef struct MySequence
{
    int *intval;
    bool_t *boolval;
} MySequence;
     
int mySequence(ODR o, MySequence **p, int optional, const char *name)
{
    if (odr_sequence_begin(o, p, sizeof(**p), name) == 0)
        return optional &amp;&amp; odr_ok(o);
    return
        odr_integer(o, &amp;(*p)-&gt;intval, 0, "intval") &amp;&amp;
        odr_bool(o, &amp;(*p)-&gt;boolval, 1, "boolval") &amp;&amp;
        odr_sequence_end(o);
}

    </pre><p>
     Note the 1 in the call to <code class="function">odr_bool()</code>, to mark
     that the sequence member is optional.
     If either of the member types had been tagged, the macros
     <code class="function">odr_implicit_tag()</code> or
     <code class="function">odr_explicit_tag()</code>
     could have been used.
     The new function can be used exactly like the standard functions provided
     with <acronym class="acronym">ODR</acronym>. It will encode, decode or pretty-print a data value of the
     <code class="literal">MySequence</code> type. We like to name types with an
     initial capital, as done in ASN.1 definitions, and to name the
     corresponding function with the first character of the name in lower case.
     You could, of course, name your structures, types, and functions any way
     you please - as long as you're consistent, and your code is easily readable.
     <code class="literal">odr_ok</code> is just that - a predicate that returns the
     state of the stream. It is used to ensure that the behavior of the new
     type is compatible with the interface of the primitive types.
    </p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="odr.tagging.constructed.types"></a>3.4.�Tagging Constructed Types</h3></div></div></div><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3><p>
      See <a class="xref" href="odr.programming.html#odr.tagging.primitive.types" title="3.2.�Tagging Primitive Types">Section�3.2, &#8220;Tagging Primitive Types&#8221;</a> for information on how to tag
      the primitive types, as well as types that are already defined.
     </p></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="odr.implicit.tagging"></a>3.4.1.�Implicit Tagging</h4></div></div></div><p>
      Assume the type above had been defined as
     </p><pre class="screen">
MySequence ::= [10] IMPLICIT SEQUENCE {
      intval INTEGER,
      boolval BOOLEAN OPTIONAL
}
     </pre><p>
      You would implement this in <acronym class="acronym">ODR</acronym> by calling the function
     </p><pre class="synopsis">
int odr_implicit_settag(ODR o, int class, int tag);
     </pre><p>
      which overrides the tag of the type immediately following it. The
      macro <code class="function">odr_implicit_tag()</code> works by calling
      <code class="function">odr_implicit_settag()</code> immediately
      before calling the function pointer argument.
      Your type function could look like this:
     </p><pre class="screen">
int mySequence(ODR o, MySequence **p, int optional, const char *name)
{
    if (odr_implicit_settag(o, ODR_CONTEXT, 10) == 0 ||
        odr_sequence_begin(o, p, sizeof(**p), name) == 0)
        return optional &amp;&amp; odr_ok(o);
    return
        odr_integer(o, &amp;(*p)-&gt;intval, 0, "intval") &amp;&amp;
        odr_bool(o, &amp;(*p)-&gt;boolval, 1, "boolval") &amp;&amp;
        odr_sequence_end(o);
}
     </pre><p>
      The definition of the structure <code class="literal">MySequence</code> would be
      the same.
     </p></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="odr.explicit.tagging"></a>3.4.2.�Explicit Tagging</h4></div></div></div><p>
      Explicit tagging of constructed types is a little more complicated,
      since you are in effect adding a level of construction to the data.
     </p><p>
      Assume the definition:
     </p><pre class="screen">
MySequence ::= [10] IMPLICIT SEQUENCE {
   intval INTEGER,
   boolval BOOLEAN OPTIONAL
}
     </pre><p>
      Since the new type has an extra level of construction, two new functions
      are needed to encapsulate the base type:
     </p><pre class="synopsis">
int odr_constructed_begin(ODR o, void *p, int class, int tag,
                          const char *name);

int odr_constructed_end(ODR o);
     </pre><p>
      Assume that the IMPLICIT in the type definition above were replaced
      with EXPLICIT (or that the IMPLICIT keyword were simply deleted, which
      would be equivalent). The structure definition would look the same,
      but the function would look like this:
     </p><pre class="screen">
int mySequence(ODR o, MySequence **p, int optional, const char *name)
{
    if (odr_constructed_begin(o, p, ODR_CONTEXT, 10, name) == 0)
        return optional &amp;&amp; odr_ok(o);
    if (o-&gt;direction == ODR_DECODE)
        *p = odr_malloc(o, sizeof(**p));
    if (odr_sequence_begin(o, p, sizeof(**p), 0) == 0)
    {
        *p = 0; /* this is almost certainly a protocol error */
        return 0;
    }
    return
        odr_integer(o, &amp;(*p)-&gt;intval, 0, "intval") &amp;&amp;
        odr_bool(o, &amp;(*p)-&gt;boolval, 1, "boolval") &amp;&amp;
        odr_sequence_end(o) &amp;&amp;
        odr_constructed_end(o);
}
     </pre><p>
      Notice that the interface here gets kind of nasty. The reason is
      simple: Explicitly tagged, constructed types are fairly rare in
      the protocols that we care about, so the
      esthetic annoyance (not to mention the dangers of a cluttered
      interface) is less than the time that would be required to develop a
      better interface. Nevertheless, it is far from satisfying, and it's a
      point that will be worked on in the future. One option for you would
      be to simply apply the <code class="function">odr_explicit_tag()</code> macro to
      the first function, and not
      have to worry about <code class="function">odr_constructed_*</code> yourself.
      Incidentally, as you might have guessed, the
      <code class="function">odr_sequence_</code> functions are themselves
      implemented using the <code class="function">/odr_constructed_</code> functions.
     </p></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="odr.sequence.of"></a>3.5.�SEQUENCE OF</h3></div></div></div><p>
     To handle sequences (arrays) of a specific type, the function
    </p><pre class="synopsis">
int odr_sequence_of(ODR o, int (*fun)(ODR o, void *p, int optional),
                    void *p, int *num, const char *name);
    </pre><p>
     The <code class="literal">fun</code> parameter is a pointer to the decoder/encoder
     function of the type. <code class="literal">p</code> is a pointer to an array of
     pointers to your type. <code class="literal">num</code> is the number of elements
     in the array.
    </p><p>
     Assume a type
    </p><pre class="screen">
MyArray ::= SEQUENCE OF INTEGER
    </pre><p>
     The C representation might be
    </p><pre class="screen">
typedef struct MyArray
{
    int num_elements;
    int **elements;
} MyArray;
    </pre><p>
     And the function might look like
    </p><pre class="screen">
int myArray(ODR o, MyArray **p, int optional, const char *name)
{
    if (o-&gt;direction == ODR_DECODE)
        *p = odr_malloc(o, sizeof(**p));
    if (odr_sequence_of(o, odr_integer, &amp;(*p)-&gt;elements,
        &amp;(*p)-&gt;num_elements, name))
        return 1;
    *p = 0;
        return optional &amp;&amp; odr_ok(o);
}
    </pre></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="odr.choice.types"></a>3.6.�CHOICE Types</h3></div></div></div><p>
     The choice type is used fairly often in some ASN.1 definitions, so
     some work has gone into streamlining its interface.
    </p><p>
     CHOICE types are handled by the function:
    </p><pre class="synopsis">
int odr_choice(ODR o, Odr_arm arm[], void *p, void *whichp,
               const char *name);
    </pre><p>
     The <code class="literal">arm</code> array is used to describe each of the possible
     types that the CHOICE type may assume. Internally in your application,
     the CHOICE type is represented as a discriminated union. That is, a
     C union accompanied by an integer (or enum) identifying the active
     'arm' of the union.
     <code class="literal">whichp</code> is a pointer to the union discriminator.
     When encoding, it is examined to determine the current type.
     When decoding, it is set to reference the type that was found in
     the input stream.
    </p><p>
     The Odr_arm type is defined thus:
    </p><pre class="screen">
typedef struct odr_arm
{
    int tagmode;
    int class;
    int tag;
    int which;
    Odr_fun fun;
    char *name;
} Odr_arm;
    </pre><p>
     The interpretation of the fields are:
    </p><div class="variablelist"><dl><dt><span class="term">tagmode</span></dt><dd><p>Either <code class="literal">ODR_IMPLICIT</code>,
	<code class="literal">ODR_EXPLICIT</code>, or <code class="literal">ODR_NONE</code> (-1)
	to mark	no tagging.</p></dd><dt><span class="term">which</span></dt><dd><p>The value of the discriminator that corresponds to
	this CHOICE element. Typically, it will be a #defined constant, or
	an enum member.</p></dd><dt><span class="term">fun</span></dt><dd><p>A pointer to a function that implements the type of
	the CHOICE member. It may be either a standard <acronym class="acronym">ODR</acronym> type or a type
	defined by yourself.</p></dd><dt><span class="term">name</span></dt><dd><p>Name of tag.</p></dd></dl></div><p>
     A handy way to prepare the array for use by the
     <code class="function">odr_choice()</code> function is to
     define it as a static, initialized array in the beginning of your
     decoding/encoding function. Assume the type definition:
    </p><pre class="screen">
MyChoice ::= CHOICE {
    untagged INTEGER,
    tagged   [99] IMPLICIT INTEGER,
    other    BOOLEAN
}
    </pre><p>
     Your C type might look like
    </p><pre class="screen">
typedef struct MyChoice
{
    enum
    {
        MyChoice_untagged,
        MyChoice_tagged,
        MyChoice_other
    } which;
    union
    {
        int *untagged;
        int *tagged;
        bool_t *other;
    } u;
};
    </pre><p>
     And your function could look like this:
    </p><pre class="screen">
int myChoice(ODR o, MyChoice **p, int optional, const char *name)
{
    static Odr_arm arm[] =
    {
      {-1, -1, -1, MyChoice_untagged, odr_integer, "untagged"},
      {ODR_IMPLICIT, ODR_CONTEXT, 99, MyChoice_tagged, odr_integer,
      "tagged"},
      {-1, -1, -1, MyChoice_other, odr_boolean, "other"},
      {-1, -1, -1, -1, 0}
    };

    if (o-&gt;direction == ODR_DECODE)
        *p = odr_malloc(o, sizeof(**p);
    else if (!*p)
        return optional &amp;&amp; odr_ok(o);

    if (odr_choice(o, arm, &amp;(*p)-&gt;u, &amp;(*p)-&gt;which), name)
        return 1;
    *p = 0;
        return optional &amp;&amp; odr_ok(o);
}
    </pre><p>
     In some cases (say, a non-optional choice which is a member of a
     sequence), you can "embed" the union and its discriminator in the
     structure belonging to the enclosing type, and you won't need to
     fiddle with memory allocation to create a separate structure to
     wrap the discriminator and union.
    </p><p>
     The corresponding function is somewhat nicer in the Sun XDR interface.
     Most of the complexity of this interface comes from the possibility of
     declaring sequence elements (including CHOICEs) optional.
    </p><p>
     The ASN.1 specifications naturally requires that each member of a
     CHOICE have a distinct tag, so they can be told apart on decoding.
     Sometimes it can be useful to define a CHOICE that has multiple types
     that share the same tag. You'll need some other mechanism, perhaps
     keyed to the context of the CHOICE type. In effect, we would like to
     introduce a level of context-sensitiveness to our ASN.1 specification.
     When encoding an internal representation, we have no problem, as long
     as each CHOICE member has a distinct discriminator value. For
     decoding, we need a way to tell the choice function to look for a
     specific arm of the table. The function
    </p><pre class="synopsis">
void odr_choice_bias(ODR o, int what);
    </pre><p>
     provides this functionality. When called, it leaves a notice for the next
     call to <code class="function">odr_choice()</code> to be called on the decoding
     stream <code class="literal">o</code> that only the <code class="literal">arm</code> entry with
     a <code class="literal">which</code> field equal to <code class="literal">what</code>
     should be tried.
    </p><p>
     The most important application (perhaps the only one, really) is in
     the definition of application-specific EXTERNAL encoders/decoders
     which will automatically decode an ANY member given the direct or
     indirect reference.
    </p></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="odr.use.html">Prev</a>�</td><td width="20%" align="center"><a accesskey="u" href="odr.html">Up</a></td><td width="40%" align="right">�<a accesskey="n" href="odr.debugging.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">2.�Using ODR�</td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top">�4.�Debugging</td></tr></table></div></body></html>