-<!-- $Header: /home/cvsroot/yaz/doc/odr.xml,v 1.1 2001-01-04 13:36:24 adam Exp $ -->
-<chapter><title id="odr">The ODR Module</title>
-
-<sect1><title>Introduction</title>
-
-<para>
-&odr; is the BER-encoding/decoding subsystem of &yaz;. Care as been taken
-to isolate &odr; from the rest of the package - specifically from the
-transport interface. &odr; may be used in any context where basic
-ASN.1/BER representations are used.
-</para>
-
-<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
-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>).
-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>
-</para>
-
-<para>
-If you need a part of the protocol that isn't already in &yaz;, you
-should contact the authors before going to work on it yourself: We
-might already be working on it. Conversely, if you implement a useful
-part of the protocol before us, we'd be happy to include it in a
-future release.
-</para>
-
-</sect1>
-<sect1><title id="odr-use">Using ODR</title>
-
-<sect2><title>ODR Streams</title>
-
-<para>
-Conceptually, the ODR stream is the source of encoded data in the
-decoding mode; when encoding, it is the receptacle for the encoded
-data. Before you can use an ODR stream it must be allocated. This is
-done with the function
-</para>
-
-<synopsis>
- ODR odr_createmem(int direction);
-</synopsis>
-
-<para>
-The <function>odr_createmem()</function> function takes as argument one
-of three manifest constants: <literal>ODR_ENCODE</literal>,
-<literal>ODR_DECODE</literal>, or <literal>ODR_PRINT</literal>.
-An &odr; stream can be in only one mode - it is not possible to change
-its mode once it's selected. Typically, your program will allocate
-at least two ODR streams - one for decoding, and one for encoding.
-</para>
-
-<para>
-When you're done with the stream, you can use
-</para>
-
-<synopsis>
- void odr_destroy(ODR o);
-</synopsis>
-
-<para>
-to release the resources allocated for the stream.
-</para>
-</sect2>
-
-<sect2><title id="memory">Memory Management</title>
-
-<para>
-Two forms of memory management take place in the &odr; system. The first
-one, which has to do with allocating little bits of memory (sometimes
-quite large bits of memory, actually) when a protocol package is
-decoded, and turned into a complex of interlinked structures. This
-section deals with this system, and how you can use it for your own
-purposes. The next section deals with the memory management which is
-required when encoding data - to make sure that a large enough buffer is
-available to hold the fully encoded PDU.
-</para>
-
-<para>
-The &odr; module has its own memory management system, which is
-used whenever memory is required. Specifically, it is used to allocate
-space for data when decoding incoming PDUs. You can use the memory
-system for your own purposes, by using the function
-</para>
-
-<synopsis>
-void *odr_malloc(ODR o, int size);
-</synopsis>
-
-<para>
-You can't use the normal <function>free(2)</function> routine to free
-memory allocated by this function, and &odr; doesn't provide a parallel
-function. Instead, you can call
-</para>
-
-<synopsis>
- void odr_reset(ODR o, int size);
-</synopsis>
-
-<para>
-when you are done with the
-memory: Everything allocated since the last call to
-<function>odr_reset()</function> is released.
-The <function>odr_reset()</function> call is also required to clear
-up an error condition on a stream.
-</para>
-
-<para>
-The function
-</para>
-
-<synopsis>
- int odr_total(ODR o);
-</synopsis>
-
-<para>
-returns the number of bytes allocated on the stream since the last call to
-<function>odr_reset()</function>.
-</para>
-
-<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
-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 maintaing short-lived constructions such
-as protocol PDUs.
-</para>
-
-<para>
-If you want to retain a bit of memory beyond the next call to
-<function>odr_reset()</function>, you can use the function
-</para>
-
-<synopsis>
- ODR_MEM odr_extract_mem(ODR o);
-</synopsis>
-
-<para>
-This function will give you control of the memory recently allocated
-on the ODR stream. The memory will live (past calls to
-<function>odr_reset()</function>), until you call the function
-</para>
-
-<synopsis>
- void odr_release_mem(ODR_MEM p);
-</synopsis>
-
-<para>
-The opaque <literal>ODR_MEM</literal> handle has no other purpose than
-referencing the memory block for you until you want to release it.
-</para>
-
-<para>
-You can use <function>odr_extract_mem()</function> repeatedly between
-allocating data, to retain individual control of separate chunks of data.
-</para>
-
-</sect2>
-<sect2><title>Encoding and Decoding Data</title>
-
-<para>
-When encoding data, the ODR stream will write the encoded octet string
-in an internal buffer. To retrieve the data, use the function
-</para>
-
-<synopsis>
- char *odr_getbuf(ODR o, int *len, int *size);
-</synopsis>
-
-<para>
-The integer pointed to by len is set to the length of the encoded
-data, and a pointer to that data is returned. <literal>*size</literal>
-is set to the size of the buffer (unless <literal>size</literal> is null,
-signalling that you are not interested in the size). The next call to
-a primitive function using the same &odr; stream will overwrite the
-data, unless a different buffer has been supplied using the call
-</para>
-
-<synopsis>
- void odr_setbuf(ODR o, char *buf, int len, int can_grow);
-</synopsis>
-
-<para>
-which sets the encoding (or decoding) buffer used by <literal>o</literal> to
-<literal>buf</literal>, using the length <literal>len</literal>.
-Before a call to an encoding function, you can use
-<function>odr_setbuf()</function> to provide the stream with an encoding
-buffer of sufficient size (length). The <literal>can_grow</literal>
-parameter tells the encoding &odr; stream whether it is allowed to use
-<function>realloc(2)</function> to increase the size of the buffer when
-necessary. The default condition of a new encoding stream is equivalent
-to the results of calling
-</para>
-
-<synopsis>
-odr_setbuf(stream, 0, 0, 1);
-</synopsis>
-
-<para>
-In this case, the stream will allocate and reallocate memory as
-necessary. The stream reallocates memory by repeatedly doubling the
-size of the buffer - the result is that the buffer will typically
-reach its maximum, working size with only a small number of reallocation
-operations. The memory is freed by the stream when the latter is destroyed,
-unless it was assigned by the user with the <literal>can_grow</literal>
-parameter set to zero (in this case, you are expected to retain
-control of the memory yourself).
-</para>
-
-<para>
-To assume full control of an encoded buffer, you must first call
-<function>odr_getbuf()</function> to fetch the buffer and its length.
-Next, you should call <function>odr_setbuf()</function> to provide a
-different buffer (or a null pointer) to the stream. In the simplest
-case, you will reuse the same buffer over and over again, and you
-will just need to call <function>odr_getbuf()</function> after each
-encoding operation to get the length and address of the buffer.
-Note that the stream may reallocate the buffer during an encoding
-operation, so it is necessary to retrieve the correct address after
-each encoding operation.
-</para>
-
-<para>
-It is important to realise that the ODR stream will not release this
-memory when you call <function>odr_reset()</function>: It will
-merely update its internal pointers to prepare for the encoding of a
-new data value.
-When the stream is released by the <function>odr_destroy()</function>
-function, the memory given to it by <function>odr_setbuf</function> will
-be released <emphasis>only</emphasis> if the <literal>can_grow</literal>
-parameter to <function>odr_setbuf()</function> was nonzero. The
-<literal>can_grow</literal> parameter, in other words, is a way of
-signalling who is to own the buffer, you or the ODR stream. If you never call
-<function>odr_setbuf()</function> on your encoding stream, which is
-typically the case, the buffer allocated by the stream will belong to
-the stream by default.
-</para>
-
-<para>
-When you wish to decode data, you should first call
-<function>odr_setbuf()</function>, to tell the decoding stream
-where to find the encoded data, and how long the buffer is
-(the <literal>can_grow</literal> parameter is ignored by a decoding
-stream). After this, you can call the function corresponding to the
-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>
-
-<para>
-If the data is absent (or doesn't match the tag corresponding to the type),
-the return value will be either 0 or 1 depending on the
-<literal>optional</literal> flag. If <literal>optional</literal>
-is 0 and the data is absent, an error flag will be raised in the
-stream, and you'll need to call <function>odr_reset()</function> before
-you can use the stream again. If <literal>optional</literal> is
-nonzero, the pointer <emphasis>pointed</emphasis> to/ by <literal>p</literal>
-will be set to the null value, and the function will return 1.
-The <literal>name</literal> argument is used to pretty-print the
-tag in question. It may be set to <literal>NULL</literal> if
-pretty-printing is not desired.
-</para>
-
-<para>
-If the data value is found where it's expected, the pointer
-<emphasis>pointed to</emphasis> by the <literal>p</literal> argument
-will be set to point to the decoded type.
-The space for the type will be allocated and owned by the &odr; stream, and
-it will live until you call <function>odr_reset()</function> on the
-stream. You cannot use <function>free(2)</function> to release the memory.
-You can decode several data elements (by repeated calls to
-<function>odr_setbuf()</function> and your decoding function), and
-new memory will be allocated each time. When you do call
-<function>odr_reset()</function>, everything decoded since the
-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>
+<!-- $Id: odr.xml,v 1.13 2004-08-11 12:47:35 adam Exp $ -->
+ <chapter id="odr"><title>The ODR Module</title>
+
+ <sect1 id="odr.introduction"><title>Introduction</title>
+
+ <para>
+ &odr; is the BER-encoding/decoding subsystem of &yaz;. Care as been taken
+ to isolate &odr; from the rest of the package - specifically from the
+ transport interface. &odr; may be used in any context where basic
+ ASN.1/BER representations are used.
+ </para>
+
+ <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
+ (<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
+ (<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 <xref linkend="odr.programming"/>
+ to implement Z39.50 with &yaz;.</emphasis>
+ </para>
+
+ <para>
+ If you need a part of the protocol that isn't already in &yaz;, you
+ should contact the authors before going to work on it yourself: We
+ might already be working on it. Conversely, if you implement a useful
+ part of the protocol before us, we'd be happy to include it in a
+ future release.
+ </para>
+
+ </sect1>
+ <sect1 id="odr.use"><title>Using ODR</title>
+
+ <sect2><title>ODR Streams</title>
+
+ <para>
+ Conceptually, the ODR stream is the source of encoded data in the
+ decoding mode; when encoding, it is the receptacle for the encoded
+ data. Before you can use an ODR stream it must be allocated. This is
+ done with the function
+ </para>
+
+ <synopsis>
+ ODR odr_createmem(int direction);
+ </synopsis>
+
+ <para>
+ The <function>odr_createmem()</function> function takes as argument one
+ of three manifest constants: <literal>ODR_ENCODE</literal>,
+ <literal>ODR_DECODE</literal>, or <literal>ODR_PRINT</literal>.
+ An &odr; stream can be in only one mode - it is not possible to change
+ its mode once it's selected. Typically, your program will allocate
+ at least two ODR streams - one for decoding, and one for encoding.
+ </para>
+
+ <para>
+ When you're done with the stream, you can use
+ </para>
+
+ <synopsis>
+ void odr_destroy(ODR o);
+ </synopsis>
+
+ <para>
+ to release the resources allocated for the stream.
+ </para>
+ </sect2>
+
+ <sect2><title id="memory">Memory Management</title>
+
+ <para>
+ Two forms of memory management take place in the &odr; system. The first
+ one, which has to do with allocating little bits of memory (sometimes
+ quite large bits of memory, actually) when a protocol package is
+ decoded, and turned into a complex of interlinked structures. This
+ section deals with this system, and how you can use it for your own
+ purposes. The next section deals with the memory management which is
+ required when encoding data - to make sure that a large enough buffer is
+ available to hold the fully encoded PDU.
+ </para>
+
+ <para>
+ The &odr; module has its own memory management system, which is
+ used whenever memory is required. Specifically, it is used to allocate
+ space for data when decoding incoming PDUs. You can use the memory
+ system for your own purposes, by using the function
+ </para>
+
+ <synopsis>
+ void *odr_malloc(ODR o, int size);
+ </synopsis>
+
+ <para>
+ You can't use the normal <function>free(2)</function> routine to free
+ memory allocated by this function, and &odr; doesn't provide a parallel
+ function. Instead, you can call
+ </para>
+
+ <synopsis>
+ void odr_reset(ODR o, int size);
+ </synopsis>
+
+ <para>
+ when you are done with the
+ memory: Everything allocated since the last call to
+ <function>odr_reset()</function> is released.
+ The <function>odr_reset()</function> call is also required to clear
+ up an error condition on a stream.
+ </para>
+
+ <para>
+ The function
+ </para>
+
+ <synopsis>
+ int odr_total(ODR o);
+ </synopsis>
+
+ <para>
+ returns the number of bytes allocated on the stream since the last call to
+ <function>odr_reset()</function>.
+ </para>
+
+ <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 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
+ as protocol PDUs.
+ </para>
+
+ <para>
+ If you want to retain a bit of memory beyond the next call to
+ <function>odr_reset()</function>, you can use the function
+ </para>
+
+ <synopsis>
+ ODR_MEM odr_extract_mem(ODR o);
+ </synopsis>
+
+ <para>
+ This function will give you control of the memory recently allocated
+ on the ODR stream. The memory will live (past calls to
+ <function>odr_reset()</function>), until you call the function
+ </para>
+
+ <synopsis>
+ void odr_release_mem(ODR_MEM p);
+ </synopsis>
+
+ <para>
+ The opaque <literal>ODR_MEM</literal> handle has no other purpose than
+ referencing the memory block for you until you want to release it.
+ </para>
+
+ <para>
+ You can use <function>odr_extract_mem()</function> repeatedly between
+ allocating data, to retain individual control of separate chunks of data.
+ </para>
+
+ </sect2>
+ <sect2><title>Encoding and Decoding Data</title>
+
+ <para>
+ When encoding data, the ODR stream will write the encoded octet string
+ in an internal buffer. To retrieve the data, use the function
+ </para>
+
+ <synopsis>
+ char *odr_getbuf(ODR o, int *len, int *size);
+ </synopsis>
+
+ <para>
+ The integer pointed to by len is set to the length of the encoded
+ data, and a pointer to that data is returned. <literal>*size</literal>
+ is set to the size of the buffer (unless <literal>size</literal> is null,
+ signaling that you are not interested in the size). The next call to
+ a primitive function using the same &odr; stream will overwrite the
+ data, unless a different buffer has been supplied using the call
+ </para>
+
+ <synopsis>
+ void odr_setbuf(ODR o, char *buf, int len, int can_grow);
+ </synopsis>
+
+ <para>
+ which sets the encoding (or decoding) buffer used by
+ <literal>o</literal> to <literal>buf</literal>, using the length
+ <literal>len</literal>.
+ Before a call to an encoding function, you can use
+ <function>odr_setbuf()</function> to provide the stream with an encoding
+ buffer of sufficient size (length). The <literal>can_grow</literal>
+ parameter tells the encoding &odr; stream whether it is allowed to use
+ <function>realloc(2)</function> to increase the size of the buffer when
+ necessary. The default condition of a new encoding stream is equivalent
+ to the results of calling
+ </para>
+
+ <synopsis>
+ odr_setbuf(stream, 0, 0, 1);
+ </synopsis>
+
+ <para>
+ In this case, the stream will allocate and reallocate memory as
+ necessary. The stream reallocates memory by repeatedly doubling the
+ size of the buffer - the result is that the buffer will typically
+ reach its maximum, working size with only a small number of reallocation
+ operations. The memory is freed by the stream when the latter is destroyed,
+ unless it was assigned by the user with the <literal>can_grow</literal>
+ parameter set to zero (in this case, you are expected to retain
+ control of the memory yourself).
+ </para>
+
+ <para>
+ To assume full control of an encoded buffer, you must first call
+ <function>odr_getbuf()</function> to fetch the buffer and its length.
+ Next, you should call <function>odr_setbuf()</function> to provide a
+ different buffer (or a null pointer) to the stream. In the simplest
+ case, you will reuse the same buffer over and over again, and you
+ will just need to call <function>odr_getbuf()</function> after each
+ encoding operation to get the length and address of the buffer.
+ Note that the stream may reallocate the buffer during an encoding
+ operation, so it is necessary to retrieve the correct address after
+ each encoding operation.
+ </para>
+
+ <para>
+ It is important to realize that the ODR stream will not release this
+ memory when you call <function>odr_reset()</function>: It will
+ merely update its internal pointers to prepare for the encoding of a
+ new data value.
+ When the stream is released by the <function>odr_destroy()</function>
+ function, the memory given to it by <function>odr_setbuf</function> will
+ be released <emphasis>only</emphasis> if the <literal>can_grow</literal>
+ parameter to <function>odr_setbuf()</function> was nonzero. The
+ <literal>can_grow</literal> parameter, in other words, is a way of
+ signaling who is to own the buffer, you or the ODR stream. If you never call
+ <function>odr_setbuf()</function> on your encoding stream, which is
+ typically the case, the buffer allocated by the stream will belong to
+ the stream by default.
+ </para>
+
+ <para>
+ When you wish to decode data, you should first call
+ <function>odr_setbuf()</function>, to tell the decoding stream
+ where to find the encoded data, and how long the buffer is
+ (the <literal>can_grow</literal> parameter is ignored by a decoding
+ stream). After this, you can call the function corresponding to the
+ data you wish to decode (eg, <function>odr_integer()</function> odr
+ <function>z_APDU()</function>).
+ </para>
+
+ <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
+ the type), the return value will be either 0 or 1 depending on the
+ <literal>optional</literal> flag. If <literal>optional</literal>
+ is 0 and the data is absent, an error flag will be raised in the
+ stream, and you'll need to call <function>odr_reset()</function> before
+ you can use the stream again. If <literal>optional</literal> is
+ nonzero, the pointer <emphasis>pointed</emphasis> to/ by
+ <literal>p</literal> will be set to the null value, and the function
+ will return 1.
+ The <literal>name</literal> argument is used to pretty-print the
+ tag in question. It may be set to <literal>NULL</literal> if
+ pretty-printing is not desired.
+ </para>
+
+ <para>
+ If the data value is found where it's expected, the pointer
+ <emphasis>pointed to</emphasis> by the <literal>p</literal> argument
+ will be set to point to the decoded type.
+ The space for the type will be allocated and owned by the &odr;
+ stream, and it will live until you call
+ <function>odr_reset()</function> on the stream. You cannot use
+ <function>free(2)</function> to release the memory.
+ You can decode several data elements (by repeated calls to
+ <function>odr_setbuf()</function> and your decoding function), and
+ new memory will be allocated each time. When you do call
+ <function>odr_reset()</function>, everything decoded since the
+ last call to <function>odr_reset()</function> will be released.
+ </para>
+
+ <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[