Ignore zoomst10
[yaz-moved-to-github.git] / doc / odr.xml
index 9a8e406..6a135e9 100644 (file)
@@ -1,4 +1,4 @@
-<!-- $Id: odr.xml,v 1.7 2001-10-26 20:13:44 adam Exp $ -->
+<!-- $Id: odr.xml,v 1.18 2006-04-25 11:25:08 marc Exp $ -->
  <chapter id="odr"><title>The ODR Module</title>
   
   <sect1 id="odr.introduction"><title>Introduction</title>
    <para>
     If you are only interested in writing a Z39.50 implementation based on
     the PDUs that are already provided with &yaz;, you only need to concern
-    yourself with the section on managing ODR streams (section
-    <link linkend="odr-use">Using ODR</link>). Only if you need to
+    yourself with the section on managing ODR streams
+    (<xref linkend="odr.use"/>). Only if you need to
     implement ASN.1 beyond that which has been provided, should you
     worry about the second half of the documentation
-    (section <link linkend="odr-prog">Programming with ODR</link>).
+    (<xref linkend="odr.programming"/>).
     If you use one of the higher-level interfaces, you can skip this
     section entirely.
    </para>
 
    <para>
     This is important, so we'll repeat it for emphasis: <emphasis>You do
-    not need to read section <link linkend="odr-prog">Programming with
-    ODR</link> to implement Z39.50 with &yaz;.</emphasis>
+     not need to read <xref linkend="odr.programming"/>
+     to implement Z39.50 with &yaz;.</emphasis>
    </para>
 
    <para>
@@ -37,7 +37,7 @@
    </para>
 
   </sect1>
-  <sect1 id="odr.use"><title id="odr-use">Using ODR</title>
+  <sect1 id="odr.use"><title>Using ODR</title>
 
    <sect2><title>ODR Streams</title>
 
     <para>
      The memory subsystem of &odr; is fairly efficient at allocating and
      releasing little bits of memory. Rather than managing the individual,
-     small bits of space, the system maintains a freelist of larger chunks
+     small bits of space, the system maintains a free-list of larger chunks
      of memory, which are handed out in small bits. This scheme is
      generally known as a <emphasis>nibble memory</emphasis> system.
      It is very useful for maintaining short-lived constructions such
      data you wish to decode (eg, <function>odr_integer()</function> odr
      <function>z_APDU()</function>).
     </para>
-
-    <para>
-     Examples of encoding/decoding functions:
-    </para>
-
-    <synopsis>
-     int odr_integer(ODR o, int **p, int optional, const char *name);
-
-     int z_APDU(ODR o, Z_APDU **p, int optional, const char *name);
-    </synopsis>
+    
+    <example><title>Encoding and decoding functions</title>
+     <synopsis>
+      int odr_integer(ODR o, int **p, int optional, const char *name);
+      
+      int z_APDU(ODR o, Z_APDU **p, int optional, const char *name);
+     </synopsis>
+    </example>
 
     <para>
      If the data is absent (or doesn't match the tag corresponding to
      last call to <function>odr_reset()</function> will be released.
     </para>
 
-    <para>
-     The use of the double indirection can be a little confusing at first
-     (its purpose will become clear later on, hopefully),
-     so an example is in order. We'll encode an integer value, and
-     immediately decode it again using a different stream. A useless, but
-     informative operation.
-    </para>
-
-    <programlisting>
-
+    <example><title>Encoding and decoding of an integer</title>
+     <para>
+      The use of the double indirection can be a little confusing at first
+      (its purpose will become clear later on, hopefully),
+      so an example is in order. We'll encode an integer value, and
+      immediately decode it again using a different stream. A useless, but
+      informative operation.
+     </para>
+     <programlisting><![CDATA[
 void do_nothing_useful(int value)
 {
     ODR encode, decode;
@@ -345,18 +342,70 @@ void do_nothing_useful(int value)
     odr_destroy(encode);
     odr_destroy(decode);
 }
-    </programlisting>
+]]>
+     </programlisting>
+     <para>
+      This looks like a lot of work, offhand. In practice, the &odr; streams
+      will typically be allocated once, in the beginning of your program
+      (or at the beginning of a new network session), and the encoding
+      and decoding will only take place in a few, isolated places in your
+      program, so the overhead is quite manageable.
+     </para>
+    </example>
+    
+   </sect2>
 
+   <sect2><title>Printing</title>
     <para>
-     This looks like a lot of work, offhand. In practice, the &odr; streams
-     will typically be allocated once, in the beginning of your program
-     (or at the beginning of a new network session), and the encoding
-     and decoding will only take place in a few, isolated places in your
-     program, so the overhead is quite manageable.
+     When an ODR stream is created of type <literal>ODR_PRINT</literal>
+     the ODR module will print the contents of a PDU in a readable format.
+     By default output is written to the <literal>stderr</literal> stream.
+     This behavior can be changed, however, by calling the function
+     <synopsis>
+      odr_setprint(ODR o, FILE *file);
+     </synopsis>
+     before encoders or decoders are being invoked.
+     It is also possible to direct the output to a buffer (of indeed
+     another file), by using the more generic mechanism:
+     <synopsis>
+      void odr_set_stream(ODR o, void *handle,
+                         void (*stream_write)(ODR o, void *handle, int type,
+                                              const char *buf, int len),
+                         void (*stream_close)(void *handle));
+     </synopsis>
+     Here the user provides an opaque handle and two handlers,
+     <replaceable>stream_write</replaceable> for writing,
+     and <replaceable>stream_close</replaceable> which is supposed
+     to close/free resources associated with handle. 
+     The <replaceable>stream_close</replaceable> handler is optional and
+     if NULL for the function is provided, it will not be invoked.
+     The <replaceable>stream_write</replaceable> takes the ODR handle
+     as parameter, the user defined handle, a type 
+     <literal>ODR_OCTETSTRING</literal>, <literal>ODR_VISIBLESTRING</literal>
+     which indicates the type of contents is being written.
     </para>
-
+    <para>
+     Another utility useful for diagnostics (error handling) or as
+     part of the printing facilities is:
+     <synopsis>
+      const char **odr_get_element_path(ODR o);
+     </synopsis>
+     which returns a list of current elements that ODR deals with at the 
+     moment. For the returned array, say <literal>ar</literal>, 
+     <literal>ar[0]</literal> is the top level element,
+     <literal>ar[n]</literal> is the last. The last element has the
+     property that <literal>ar[n+1] == NULL</literal>.
+    </para>
+    <example>
+     <title>Element Path for record</title>
+     <para>
+      For a database record part of a PresentResponse the
+      array returned by <function>odr_get_element</function>
+      is <literal>presentResponse</literal>, <literal>databaseOrSurDiagnostics</literal>, <literal>?</literal>, <literal>record</literal>, <literal>?</literal>, <literal>databaseRecord</literal> . The question mark appears due to 
+      unnamed constructions.
+     </para>
+     </example>
    </sect2>
-
    <sect2><title>Diagnostics</title>
 
     <para>
@@ -480,7 +529,7 @@ void do_nothing_useful(int value)
    </sect2>
   </sect1>
 
-  <sect1 id="odr.programming"><title id="odr-prog">Programming with ODR</title>
+  <sect1 id="odr.programming"><title>Programming with ODR</title>
 
    <para>
     The API of &odr; is designed to reflect the structure of ASN.1, rather
@@ -488,9 +537,18 @@ void do_nothing_useful(int value)
     other external forms.
    </para>
 
+   <tip>
+    <para>
+     There is an ASN.1 tutorial available at
+     <ulink url="&url.asn.1.tutorial;">this site</ulink>.
+     This site also has standards for ASN.1 (X.680) and BER (X.690) 
+     <ulink url="&url.asn.1.standards;">online</ulink>.
+    </para>
+   </tip>
+   
    <para>
-    The interface is based loosely on that of the Sun Microsystems XDR
-    routines.
+    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
@@ -502,7 +560,7 @@ void do_nothing_useful(int value)
     The resulting C source code is quite compact, and is a pretty
     straightforward representation of the source ASN.1 specification. 
    </para>
-
+   
    <para>
     In many cases, the model of the XDR functions works quite well in this
     role.
@@ -525,13 +583,13 @@ void do_nothing_useful(int value)
      </para>
 
      <synopsis>
-int odr_integer(ODR o, int **p, int optional, const char *name);
+      int odr_integer(ODR o, int **p, int optional, const char *name);
      </synopsis>
 
      <para>
       (we don't allow values that can't be contained in a C integer.)
      </para>
-
+     
      <para>
       This form is typical of the primitive &odr; functions. They are named
       after the type of data that they encode or decode. They take an &odr;
@@ -679,7 +737,7 @@ int ODR_MASK_GET(Odr_bitmask *b, int bitno);
      </synopsis>
 
      <para>
-      The functions are modelled after the manipulation functions that
+      The functions are modeled after the manipulation functions that
       accompany the <literal>fd_set</literal> type used by the
       <function>select(2)</function> call.
       <literal>ODR_MASK_ZERO</literal> should always be called first on a
@@ -697,14 +755,14 @@ int odr_oid(ODR o, Odr_oid **p, int optional, const char *name);
       The C OID representation is simply an array of integers, terminated by
       the value -1 (the <literal>Odr_oid</literal> type is synonymous with
       the <literal>int</literal> type).
-      We suggest that you use the OID database module (see section
-      <link linkend="oid">Object Identifiers</link>) to handle object identifiers
+      We suggest that you use the OID database module (see
+      <xref linkend="asn.oid"/>) to handle object identifiers
       in your application.
      </para>
 
     </sect3>
    </sect2>
-   <sect2><title id="tag-prim">Tagging Primitive Types</title>
+   <sect2 id="tag.prim"><title>Tagging Primitive Types</title>
 
     <para>
      The simplest way of tagging a type is to use the
@@ -744,8 +802,8 @@ int myInt(ODR o, int **p, int optional, const char *name)
     <para>
      The function <function>myInt()</function> can then be used like any of
      the primitive functions provided by &odr;. Note that the behavior of
-     <function>odr_explicit()</function>
-     and <function>odr_implicit()</function> macros
+     <function>odr_explicit_tag()</function>
+     and <function>odr_implicit_tag()</function> 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
@@ -826,7 +884,8 @@ int mySequence(ODR o, MySequence **p, int optional, const char *name)
      Note the 1 in the call to <function>odr_bool()</function>, to mark
      that the sequence member is optional.
      If either of the member types had been tagged, the macros
-     <function>odr_implicit()</function> or <function>odr_explicit()</function>
+     <function>odr_implicit_tag()</function> or
+     <function>odr_explicit_tag()</function>
      could have been used.
      The new function can be used exactly like the standard functions provided
      with &odr;. It will encode, decode or pretty-print a data value of the
@@ -845,9 +904,8 @@ int mySequence(ODR o, MySequence **p, int optional, const char *name)
 
     <note>
      <para>
-      See section <link linkend="tag-prim">Tagging Primitive types</link>
-      for information on how to tag the primitive types, as well as types
-      that are already defined.
+      See <xref linkend="tag.prim"/> for information on how to tag
+      the primitive types, as well as types that are already defined.
      </para>
     </note>
 
@@ -874,7 +932,7 @@ int odr_implicit_settag(ODR o, int class, int tag);
 
      <para>
       which overrides the tag of the type immediately following it. The
-      macro <function>odr_implicit()</function> works by calling
+      macro <function>odr_implicit_tag()</function> works by calling
       <function>odr_implicit_settag()</function> immediately
       before calling the function pointer argument.
       Your type function could look like this:
@@ -964,7 +1022,7 @@ int mySequence(ODR o, MySequence **p, int optional, const char *name)
       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 <function>odr_explicit()</function> macro to
+      be to simply apply the <function>odr_explicit_tag()</function> macro to
       the first function, and not
       have to worry about <function>odr_constructed_*</function> yourself.
       Incidentally, as you might have guessed, the