Index: ossp-pkg/xds/xds.pod RCS File: /v/ossp/cvs/ossp-pkg/xds/xds.pod,v rcsdiff -q -kk '-r1.13' '-r1.14' -u '/v/ossp/cvs/ossp-pkg/xds/xds.pod,v' 2>/dev/null --- xds.pod 2002/01/02 17:13:44 1.13 +++ xds.pod 2002/01/02 18:35:51 1.14 @@ -31,141 +31,148 @@ =head1 NAME -xds - OSSP Extensible Data Serialization +B - eXtensible Data Serialization =head1 SYNOPSIS +xds_init, +xds_destroy, +xds_register, +xds_unregister, +xds_setbuffer, +xds_getbuffer, +xds_encode, +xds_decode, +xds_vencode, +xds_vdecode. + =head1 DESCRIPTION -The purpose of XDS is to encode data in a way that allows this data to -be exchanged between different computer systems. Assume you'd want to -transfer the value $1234 from host A to host B. Then you would encode -it using XDS, transfer the encoded data over the network, and decode -the value again at the other end. Every program that follows this -process will read the correct value no matter what native -representation is used internally. - -XDS consists of three components: The generic encoding and decoding -framework, a set of engines to encode and decode values in a certain -format, and a run-time context, which is used to manage buffers, +The purpose of B is to encode data in a way that allows this +data to be exchanged between different computer systems. Assume you +would want to transfer the value 0x1234 from host A to host B. Then you +would encode it using B, transfer the encoded data over the +network, and decode the value again at the other end. Every program that +follows this process will read the correct value no matter what native +representation is uses internally. + +B consists of three components: The generic encoding and +decoding framework, a set of engines to encode and decode values in a +certain format, and a run-time context, which is used to manage buffers, registered engines, etc. -In order to use the library, the first thing the developer has to do -is to create a valid XDS context by calling xds_init(). The -routine requires one parameter that determines whether to operate in -encoding- or decoding mode. A context can be used for encoding or -decoding only; it is not possible to use the same context for both -operations. Once a valid XDS context has been obtained, the routine -xds_register() can be used to register an arbitrary number -of encoding or decoding engines within the context. - -Two sets of engines are included in the library. These routines will -handle any elementary datatype defined by the ISO-C language, such as -32-bit integers, 64-bit integers, unsigned integers (of both 32- and -64-bit), floating point numbers, strings and octet streams. +In order to use B, the first thing the developer has to +do is to create a valid context by calling xds_init(). The function +requires one parameter that determines whether to operate in encoding- +or decoding mode. A context can be used for encoding or decoding only; +it is not possible to use the same context for both operations. Once a +valid context has been obtained, the function xds_register() can be used +to register an arbitrary number of encoding (or decoding) engines within +the context. + +Two sets of engines are included in the library, additional ones can be +easily programmed. These functions will handle any elementary datatype +defined by the ISO-C language, such as 32-bit integers, 64-bit integers, +unsigned integers (of both 32 and 64-bit), floating point numbers, +strings and octet streams. Once all required encoding/decoding engines are registered, the -routines xds_encode() or xds_decode() may be -used to actually perform the encoding or decoding process. Any data -type for which an engine has been registered can be handled by the -library. - -This means, that it is possible for the developer to write custom -engines for any data type he desires to use and to register them in -the context -- as long as these engines adhere to the -xds_engine_t interface defined in xds.h. - -In particular, it is possible to register meta engines. That is an -engine designed to encode or decode data types, which consist of -several elementary data types. Such an engine will simply re-use the -existing engines to encode or decode the elements of the structure. - -The following example program will encode an unsigend integer into the -XDR format, decode it back into the native host format, and compare -the result to make sure it is the original value again: - - #include - #include - #include - - int main() - { - xds_t* xds; - xds_uint32_t uint32 = 0x12345678; - xds_uint32_t new_uint32; - char* buffer; - size_t buffer_size; - - if ((xds = xds_init(XDS_ENCODE)) == NULL || - xds_register(xds, "uint32", &xdr_encode_uint32, NULL) != XDS_OK || - xds_encode(xds, "uint32", uint32) != XDS_OK || - xds_getbuffer(xds, XDS_GIFT, (void**)&buffer, &buffer_size) != XDS_OK) - { - printf("Encoding failed.\n"); - exit(1); - } - xds_destroy(xds); - - if ((xds = xds_init(XDS_DECODE)) == NULL || - xds_register(xds, "uint32", &xdr_decode_uint32, NULL) != XDS_OK || - xds_setbuffer(xds, XDS_LOAN, buffer, buffer_size) != XDS_OK || - xds_decode(xds, "uint32", &new_uint32) != XDS_OK) - { - printf("Decoding failed.\n"); - exit(1); - } - xds_destroy(xds); - - if (uint32 == new_uint32) - printf("OK\n"); - else - printf("Failure\n"); - - return 0; - } +functions xds_encode() or xds_decode() may be used to actually perform +the encoding or decoding process. Any data type for which an engine has +been registered before can be handled by the library. + +This means, it is possible for the developer to write custom engines for +any data type he desires to use and to register them in the context -- +as long as these engines adhere to the C interface defined +in F. + +In particular, it is possible to register meta engines. This is an +engine designed to encode or decode data types which consist of several +elementary data types. Such an engine will simply re-use the existing +engines to encode or decode the elements of the structure. + +The following example program (without error checking for simplicity) +will encode the unsigned integer 0x1234 into the XDR format (known from +Sun RPC), decode it back into the native host format, and compare the +result to make sure it is the original value again: + + #include + #include + + #include "xds.h" + + int main(int argc, char *argv[]) + { + xds_t *xds; + xds_uint32_t uint32 = 0x1234; + xds_uint32_t uint32_new; + char *buffer; + size_t buffer_size; + + /* encoding */ + xds = xds_init(XDS_ENCODE); + xds_register(xds, "uint32", &xdr_encode_uint32, NULL); + xds_encode(xds, "uint32", uint32); + xds_getbuffer(xds, XDS_GIFT, (void**)&buffer, &buffer_size); + xds_destroy(xds); + + /* ...usually buffer is now transferred to a remote system... */ + + /* decoding */ + xds = xds_init(XDS_DECODE); + xds_register(xds, "uint32", &xdr_decode_uint32, NULL); + xds_setbuffer(xds, XDS_LOAN, buffer, buffer_size); + xds_decode(xds, "uint32", &uint32_new); + xds_destroy(xds); + + /* comparison */ + if (uint32 == uint32_new) + printf("OK\n"); + else + printf("Failure\n"); + return 0; + } =head1 THE XDS FRAMEWORK +B provides a generic framework for encoding and decoding. +The corresponding API is described here. + =over 4 -=item xds_t* xds_init(xds_mode_t I); +=item xds_t *B(xds_mode_t I); + +This function creates and initializes a context. The I parameter +may be either C or C, depending on whether you +want to encode or decode data. If successful, xds_init() returns a +pointer to the context. In case of failure, xds_init() returns C +and sets errno to C (failed to allocate internal memory buffers) +or C (I parameter was invalid). -This routine creates and initializes a context for use with the XDS -library. The `mode' parameter may be either XDS_ENCODE or -XDS_DECODE, depending on whether you want to encode or to decode -data. If successful, xds_init() returns a pointer to the XDS -context structure. In case of failure, xds_init() returns -NULL and sets errno to ENOMEM (failed to allocate -internal memory buffers) or EINVAL (`mode' parameter was invalid). - -A context obtained from xds_init() must be destroyed by -xds_destroy() when it is not needed any more. - -=item void xds_destroy(xds_t* I); - -xds_destroy() will destroy an XDS context created by -xds_init(). Doing so will return all resources associated with -this context -- most notably the memory used to buffer the results of -encoding or decoding any values. A context may not be used after it has -been destroyed. +A context obtained from xds_init() must be destroyed by xds_destroy() if +it is no longer needed. -=item int xds_register(xds_t* I, const char* I, xds_engine_t I, void* I); +=item void B(xds_t *I); -This routine will register an engine in the provided XDS context. An -`engine' is potentially any function that fullfils the following +xds_destroy() will destroy the context I, created by xds_init(). +Doing so will return all resources associated with this context -- most +notably the memory used to buffer the results of encoding or decoding +any values. A context may not be used after it has been destroyed. + +=item int B(xds_t *I, const char *I, xds_engine_t I, void *I); + +This function will register an engine in the provided context. An +I is potentially any function that fullfils the following interface: - int engine(xds_t* xds, void* engine_context, - void* buffer, size_t buffer_size, - size_t* used_buffer_size, - va_list* args); - -By calling xds_register(), the engine `engine' will be -registered under the name `name' in the XDS context `xds'. The last -parameter `engine_context' may be used as the user sees fit: It will be -passed when the engine is actually called and may be used to implement an -engine-specific context. Most engines will not need a context of their own, -in which case NULL should be specified here. +int B(xds_t *I, void *I, void *I, size_t I, size_t *I, va_list *I); + +By calling xds_register(), the I will be registered under the +name I in the context I. The last parameter I +may be used as the user sees fit: It will be passed when the engine is +actually called and may be used to implement an engine-specific context. +Most engines will not need a context of their own, in which case C +should be specified here. Please note that until the user calls xds_register() for an XDS context he obtained from xds_init(), no engines are registered @@ -194,7 +201,7 @@ =item int xds_setbuffer(xds_t* I, xds_scope_t I, void* I, size_t I); -This routine allows the user to control XDS' buffer handling: Calling it +This function allows the user to control XDS' buffer handling: Calling it will replace the buffer currently used in `xds'. The address and size of that buffer are passed to xds_setbuffer() via the `buffer' and `buffer_len' parameters. The `xds' parameter determines for which XDS @@ -217,7 +224,7 @@ =item int xds_getbuffer(xds_t* I, xds_scope_t I, void** I, size_t* I); -This routine is the counterpart to xds_setbuffer(): It will get +This function is the counterpart to xds_setbuffer(): It will get the buffer currently used in the XDS context `xds'. The address of that buffer is stored in the location `buffer' points to; the length of the buffer's content will be stored in the location `buffer_len' points to. @@ -236,7 +243,7 @@ xds_getbuffer() may change after any other xds_xxx() function call! -The routine will return XDS_OK (everything went fine) or +The function will return XDS_OK (everything went fine) or XDS_ERR_INVALID_ARG (`xds', `buffer' or `buffer_len' are NULL or `flag' is invalid) signifying success or failure respectively. @@ -248,7 +255,7 @@ =item int xds_vencode(xds_t* I, const char* I, va_list I); -This routine will encode one or several values using the appropriate +This function will encode one or several values using the appropriate encoding engines registered in XDS context `xds'. The parameter `fmt' contains a sprintf(3)-alike descriptions of the values to be encoded; the actual values are provided in the varadic parameter `args'. @@ -297,12 +304,12 @@ =item int xds_encode(xds_t* I, const char* I, ...); -This routine is basically identical to xds_vencode(), only that +This function is basically identical to xds_vencode(), only that it uses a different prototype syntax. =item int xds_vdecode(xds_t* I, const char* I, va_list I); -This routine is almost identical to xds_vencode(): It expects an +This function is almost identical to xds_vencode(): It expects an XDS context, a format string and a set of parameters for the engines, but xds_vdecode() does not encode any data, it decodes the data back into the native format. The format string determines which engines are to @@ -326,7 +333,7 @@ =item int xds_decode(xds_t* I, const char* I, ...); -This routine is basically identical to xds_vdecode(), only that +This function is basically identical to xds_vdecode(), only that it uses a different prototype syntax. =back @@ -352,7 +359,7 @@ xdr_encode_string() char* variable variable xdr_decode_string() char** variable variable -Please note that the routines xdr_decode_octetstream() and +Please note that the functions xdr_decode_octetstream() and xdr_decode_string() return a pointer to a buffer holding the decoded data. This buffer has been allocated with malloc(3) and must be free(3)ed by the application when it is not required @@ -382,7 +389,7 @@ xml_encode_string() char* variable variable xml_decode_string() char** variable variable -Please note that the routines xml_decode_octetstream() and +Please note that the functions xml_decode_octetstream() and xml_decode_string() return a pointer to a buffer holding the decoded data. This buffer has been allocated with malloc(3) and must be free(3)ed by the application when it is not required anymore. All @@ -399,12 +406,12 @@ defined as follows: struct mystruct - { - xds_int32_t small; - xds_int64_t big; - xds_uint32_t positive; - char text[16]; - }; + { + xds_int32_t small; + xds_int64_t big; + xds_uint32_t positive; + char text[16]; + }; Some readers might wonder why the structure is defined using these weird data types rather than the familiar ones like int, long, etc. @@ -420,16 +427,16 @@ engine: static int encode_mystruct(xds_t* xds, void* engine_context, - void* buffer, size_t buffer_size, - size_t* used_buffer_size, - va_list* args) - { - struct mystruct* ms; - ms = va_arg(*args, struct mystruct*); - return xds_encode(xds, "int32 int64 uint32 octetstream", - ms->small, ms->big, ms->positive, - ms->text, sizeof(ms->text)); - } + void* buffer, size_t buffer_size, + size_t* used_buffer_size, + va_list* args) + { + struct mystruct* ms; + ms = va_arg(*args, struct mystruct*); + return xds_encode(xds, "int32 int64 uint32 octetstream", + ms->small, ms->big, ms->positive, + ms->text, sizeof(ms->text)); + } This engine takes the address of the `mystruct' structure from the stack and then uses xds_encode() to handle all elements of @@ -535,28 +542,28 @@ Let's take a look at the corresponding decoding engine now: static int decode_mystruct(xds_t* xds, void* engine_context, - void* buffer, size_t buffer_size, - size_t* used_buffer_size, - va_list* args) - { - struct mystruct* ms; - size_t i; - char* tmp; - int rc; - ms = va_arg(*args, struct mystruct*); - rc = xds_decode(xds, "int32 int64 uint32 octetstream", - &(ms->small), &(ms->big), &(ms->positive), - &tmp, &i); - if (rc == XDS_OK) - { - if (i == sizeof(ms->text)) - memmove(ms->text, tmp, i); - else - rc = XDS_ERR_TYPE_MISMATCH; - free(tmp); - } - return rc; - } + void* buffer, size_t buffer_size, + size_t* used_buffer_size, + va_list* args) + { + struct mystruct* ms; + size_t i; + char* tmp; + int rc; + ms = va_arg(*args, struct mystruct*); + rc = xds_decode(xds, "int32 int64 uint32 octetstream", + &(ms->small), &(ms->big), &(ms->positive), + &tmp, &i); + if (rc == XDS_OK) + { + if (i == sizeof(ms->text)) + memmove(ms->text, tmp, i); + else + rc = XDS_ERR_TYPE_MISMATCH; + free(tmp); + } + return rc; + } The engine simply calls xds_decode() to handle the separate data types. The only complication is that the octet stream decoding engines