<chapter id="odr"><title>The ODR Module</title>
-
+
<sect1 id="odr.introduction"><title>Introduction</title>
<para>
</para>
<synopsis>
- void *odr_malloc(ODR o, int size);
+ void *odr_malloc(ODR o, size_t size);
</synopsis>
<para>
</para>
<synopsis>
- int odr_total(ODR o);
+ size_t odr_total(ODR o);
</synopsis>
<para>
data you wish to decode (eg, <function>odr_integer()</function> odr
<function>z_APDU()</function>).
</para>
-
+
<example id="example.odr.encoding.and.decoding.functions">
<title>Encoding and decoding functions</title>
<synopsis>
- int odr_integer(ODR o, int **p, int optional, const char *name);
-
+ int odr_integer(ODR o, Odr_int **p, int optional, const char *name);
+
int z_APDU(ODR o, Z_APDU **p, int optional, const char *name);
</synopsis>
</example>
<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
+ 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>
informative operation.
</para>
<programlisting><![CDATA[
-void do_nothing_useful(int value)
+void do_nothing_useful(Odr_int value)
{
ODR encode, decode;
- int *valp, *resvalp;
+ Odr_int *valp, *resvalp;
char *bufferp;
int len;
-
+
/* allocate streams */
if (!(encode = odr_createmem(ODR_ENCODE)))
return;
if (!(decode = odr_createmem(ODR_DECODE)))
return;
- valp = &value;
- if (odr_integer(encode, &valp, 0, 0) == 0)
+ valp = &value;
+ if (odr_integer(encode, &valp, 0, 0) == 0)
{
printf("encoding went bad\n");
return;
}
- bufferp = odr_getbuf(encode, &len);
- printf("length of encoded data is %d\n", len);
+ bufferp = odr_getbuf(encode, &len, 0);
+ printf("length of encoded data is %d\n", len);
/* now let's decode the thing again */
- odr_setbuf(decode, bufferp, len);
- if (odr_integer(decode, &resvalp, 0, 0) == 0)
+ odr_setbuf(decode, bufferp, len, 0);
+ if (odr_integer(decode, &resvalp, 0, 0) == 0)
{
printf("decoding went bad\n");
return;
}
- printf("the value is %d\n", *resvalp);
+ /* ODR_INT_PRINTF format for printf (such as %d) */
+ printf("the value is " ODR_INT_PRINTF "\n", *resvalp);
/* clean up */
odr_destroy(encode);
program, so the overhead is quite manageable.
</para>
</example>
-
+
</sect2>
<sect2 id="odr.printing"><title>Printing</title>
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.
+ 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
+ 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>
<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>,
+ 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>
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
+ 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>
<title>Summary and Synopsis</title>
<synopsis>
- #include <odr.h>
+ #include <yaz/odr.h>
ODR odr_createmem(int direction);
void odr_reset(ODR o);
- char *odr_getbuf(ODR o, int *len);
+ char *odr_getbuf(ODR o, int *len, int *size);
- void odr_setbuf(ODR o, char *buf, int len);
+ void odr_setbuf(ODR o, char *buf, int len, int can_grow);
void *odr_malloc(ODR o, int size);
- ODR_MEM odr_extract_mem(ODR o);
-
- void odr_release_mem(ODR_MEM r);
+ NMEM odr_extract_mem(ODR o);
int odr_geterror(ODR o);
- void odr_perror(char *message);
+ void odr_perror(ODR o, const char *message);
extern char *odr_errlist[];
</synopsis>
<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)
+ 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 ODR interface is based loosely on that of the Sun Microsystems
XDR routines.
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.
+ 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.
</para>
<synopsis>
- int odr_integer(ODR o, int **p, int optional, const char *name);
+ int odr_integer(ODR o, Odr_int **p, int optional, const char *name);
</synopsis>
<para>
- (we don't allow values that can't be contained in a C integer.)
+ The <literal>Odr_int</literal> is just a simple 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;
<sect3 id="odr.boolean"><title>BOOLEAN</title>
<synopsis>
-int odr_bool(ODR o, bool_t **p, int optional, const char *name);
+int odr_bool(ODR o, Odr_bool **p, int optional, const char *name);
</synopsis>
</sect3>
<sect3 id="odr.null"><title>NULL</title>
<synopsis>
-int odr_null(ODR o, bool_t **p, int optional, const char *name);
+int odr_null(ODR o, Odr_null **p, int optional, const char *name);
</synopsis>
<para>
{
unsigned char *buf;
int len;
- int size;
} Odr_oct;
int odr_octetstring(ODR o, Odr_oct **p, int optional,
<para>
The <literal>buf</literal> field should point to the character array
that holds the octetstring. The <literal>len</literal> field holds the
- actual length, while the <literal>size</literal> field gives the size
- of the allocated array (not of interest to you, in most cases).
+ actual length.
The character array need not be null terminated.
</para>
<para>
The simplest way of tagging a type is to use the
- <function>odr_implicit_tag()</function> or
+ <function>odr_implicit_tag()</function> or
<function>odr_explicit_tag()</function> macros:
</para>
</para>
<screen>
-int myInt(ODR o, int **p, int optional, const char *name)
+int myInt(ODR o, Odr_int **p, int optional, const char *name)
{
return odr_implicit_tag(o, odr_integer, p,
ODR_CONTEXT, 210, optional, name);
<screen>
typedef struct MySequence
{
- int *intval;
- bool_t *boolval;
+ Odr_int *intval;
+ Odr_bool *boolval;
} MySequence;
-
+
int mySequence(ODR o, MySequence **p, int optional, const char *name)
{
if (odr_sequence_begin(o, p, sizeof(**p), name) == 0)
typedef struct MyArray
{
int num_elements;
- int **elements;
+ Odr_int **elements;
} MyArray;
</screen>
} which;
union
{
- int *untagged;
- int *tagged;
- bool_t *other;
+ Odr_int *untagged;
+ Odr_int *tagged;
+ Odr_bool *other;
} u;
};
</screen>