X-Git-Url: http://git.indexdata.com/?p=yaz-moved-to-github.git;a=blobdiff_plain;f=doc%2Fodr.xml;h=6a135e9881d0f0a50a73fcce81ee821c31641f02;hp=dbba5ddbf20bd379a520c307c3d03a02007bdaec;hb=df6700d5c88cff54c491ad2a1ae7d8426f92f044;hpb=33c05384cfbca55da4ff97e5b2047b16596c72f7 diff --git a/doc/odr.xml b/doc/odr.xml index dbba5dd..6a135e9 100644 --- a/doc/odr.xml +++ b/doc/odr.xml @@ -1,4 +1,4 @@ - + The ODR Module Introduction @@ -13,19 +13,19 @@ 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 - Using ODR). Only if you need to + yourself with the section on managing ODR streams + (). 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 Programming with ODR). + (). If you use one of the higher-level interfaces, you can skip this section entirely. - This is important, so we'll repeat it for emphasis: You do not - need to read section Programming with ODR to - implement Z39.50 with &yaz;. + This is important, so we'll repeat it for emphasis: You do + not need to read + to implement Z39.50 with &yaz;. @@ -37,7 +37,7 @@ - Using ODR + Using ODR ODR Streams @@ -132,7 +132,7 @@ 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 nibble memory system. It is very useful for maintaining short-lived constructions such @@ -259,16 +259,14 @@ data you wish to decode (eg, odr_integer() odr z_APDU()). - - - Examples of encoding/decoding functions: - - - - 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); - + + Encoding and decoding functions + + 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); + + If the data is absent (or doesn't match the tag corresponding to @@ -300,16 +298,15 @@ last call to odr_reset() will be released. - - 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. - - - - + Encoding and decoding of an integer + + 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. + + +]]> + + + 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. + + + + + Printing - 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 ODR_PRINT + the ODR module will print the contents of a PDU in a readable format. + By default output is written to the stderr stream. + This behavior can be changed, however, by calling the function + + odr_setprint(ODR o, FILE *file); + + 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: + + 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)); + + Here the user provides an opaque handle and two handlers, + stream_write for writing, + and stream_close which is supposed + to close/free resources associated with handle. + The stream_close handler is optional and + if NULL for the function is provided, it will not be invoked. + The stream_write takes the ODR handle + as parameter, the user defined handle, a type + ODR_OCTETSTRING, ODR_VISIBLESTRING + which indicates the type of contents is being written. - + + Another utility useful for diagnostics (error handling) or as + part of the printing facilities is: + + const char **odr_get_element_path(ODR o); + + which returns a list of current elements that ODR deals with at the + moment. For the returned array, say ar, + ar[0] is the top level element, + ar[n] is the last. The last element has the + property that ar[n+1] == NULL. + + + Element Path for record + + For a database record part of a PresentResponse the + array returned by odr_get_element + is presentResponse, databaseOrSurDiagnostics, ?, record, ?, databaseRecord . The question mark appears due to + unnamed constructions. + + - Diagnostics @@ -480,7 +529,7 @@ void do_nothing_useful(int value) - Programming with ODR + Programming with ODR The API of &odr; is designed to reflect the structure of ASN.1, rather @@ -488,24 +537,30 @@ void do_nothing_useful(int value) other external forms. + + + There is an ASN.1 tutorial available at + this site. + This site also has standards for ASN.1 (X.680) and BER (X.690) + online. + + + - 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 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. Although no ASN.1 compiler is supplied - with &odr; at this time, it shouldn't be too difficult to write one, or - perhaps even to adapt an existing compiler to output &odr; routines - (not surprisingly, writing encoders/decoders using &odr; turns out - to be boring work). + 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. - + In many cases, the model of the XDR functions works quite well in this role. @@ -528,13 +583,13 @@ void do_nothing_useful(int value) -int odr_integer(ODR o, int **p, int optional, const char *name); + int odr_integer(ODR o, int **p, int optional, const char *name); (we don't allow values that can't be contained in a C integer.) - + 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; @@ -682,7 +737,7 @@ int ODR_MASK_GET(Odr_bitmask *b, int bitno); - The functions are modelled after the manipulation functions that + The functions are modeled after the manipulation functions that accompany the fd_set type used by the select(2) call. ODR_MASK_ZERO should always be called first on a @@ -700,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 Odr_oid type is synonymous with the int type). - We suggest that you use the OID database module (see section - Object Identifiers) to handle object identifiers + We suggest that you use the OID database module (see + ) to handle object identifiers in your application. - Tagging Primitive Types + Tagging Primitive Types The simplest way of tagging a type is to use the @@ -747,8 +802,8 @@ int myInt(ODR o, int **p, int optional, const char *name) The function myInt() can then be used like any of the primitive functions provided by &odr;. Note that the behavior of - odr_explicit() - and odr_implicit() macros + odr_explicit_tag() + and odr_implicit_tag() 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 @@ -829,7 +884,8 @@ int mySequence(ODR o, MySequence **p, int optional, const char *name) Note the 1 in the call to odr_bool(), to mark that the sequence member is optional. If either of the member types had been tagged, the macros - odr_implicit() or odr_explicit() + odr_implicit_tag() or + odr_explicit_tag() 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 @@ -848,9 +904,8 @@ int mySequence(ODR o, MySequence **p, int optional, const char *name) - See section Tagging Primitive types - for information on how to tag the primitive types, as well as types - that are already defined. + See for information on how to tag + the primitive types, as well as types that are already defined. @@ -877,7 +932,7 @@ int odr_implicit_settag(ODR o, int class, int tag); which overrides the tag of the type immediately following it. The - macro odr_implicit() works by calling + macro odr_implicit_tag() works by calling odr_implicit_settag() immediately before calling the function pointer argument. Your type function could look like this: @@ -967,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 odr_explicit() macro to + be to simply apply the odr_explicit_tag() macro to the first function, and not have to worry about odr_constructed_* yourself. Incidentally, as you might have guessed, the @@ -1244,7 +1299,7 @@ void odr_choice_bias(ODR o, int what); sgml-indent-step:1 sgml-indent-data:t sgml-parent-document: "yaz.xml" - sgml-local-catalogs: "../../docbook/docbook.cat" + sgml-local-catalogs: nil sgml-namecase-general:t End: -->