head 1.13; access; symbols XDS_0_9_3:1.13 XDS_0_9_2:1.13 XDS_0_9_1:1.12 XDS_0_9_0:1.11; locks; strict; comment @ * @; 1.13 date 2005.06.02.18.51.44; author rse; state Exp; branches; next 1.12; 1.12 date 2004.09.12.17.32.14; author rse; state Exp; branches; next 1.11; 1.11 date 2003.02.17.12.36.02; author rse; state Exp; branches; next 1.10; 1.10 date 2003.02.17.12.27.51; author rse; state Exp; branches; next 1.9; 1.9 date 2002.03.17.10.25.53; author rse; state Exp; branches; next 1.8; 1.8 date 2002.01.02.17.13.44; author rse; state Exp; branches; next 1.7; 1.7 date 2001.08.13.19.48.02; author rse; state Exp; branches; next 1.6; 1.6 date 2001.08.12.11.31.45; author rse; state Exp; branches; next 1.5; 1.5 date 2001.08.09.21.00.10; author rse; state Exp; branches; next 1.4; 1.4 date 2001.08.09.20.59.05; author rse; state Exp; branches; next 1.3; 1.3 date 2001.08.09.19.58.35; author rse; state Exp; branches; next 1.2; 1.2 date 2001.08.08.19.33.55; author rse; state Exp; branches; next 1.1; 1.1 date 2001.08.08.19.15.23; author rse; state Exp; branches; next ; desc @@ 1.13 log @Bumped year in copyright messages for year 2005. @ text @/* ** OSSP xds - Extensible Data Serialization ** Copyright (c) 2001-2005 Ralf S. Engelschall ** Copyright (c) 2001-2005 The OSSP Project ** Copyright (c) 2001-2005 Cable & Wireless ** ** This file is part of OSSP xds, an extensible data serialization ** library which can be found at http://www.ossp.org/pkg/lib/xds/. ** ** Permission to use, copy, modify, and distribute this software for ** any purpose with or without fee is hereby granted, provided that ** the above copyright notice and this permission notice appear in all ** copies. ** ** THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED ** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF ** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ** IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR ** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF ** USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, ** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ** OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ** SUCH DAMAGE. ** ** xds.c: XDS library framework */ #include #include #include #include "xds_p.h" int xds_init(xds_t **xds, xds_mode_t mode) { xds_t *ctx; /* Sanity check parameter. */ assert(xds != NULL); if (xds == NULL) return XDS_ERR_INVALID_ARG; assert(mode == XDS_ENCODE || mode == XDS_DECODE); if (mode != XDS_ENCODE && mode != XDS_DECODE) return XDS_ERR_INVALID_ARG; /* Allocate context structure. */ if ((ctx = malloc(sizeof (struct xds_context))) == NULL) return XDS_ERR_SYSTEM; /* errno set by malloc(3) */ /* Set mode of operation in context. */ ctx->mode = mode; /* Initialize buffer handling. */ ctx->buffer = NULL; ctx->buffer_len = 0; ctx->buffer_capacity = 0; ctx->we_own_buffer = XDS_FALSE; /* Initialize engines map. */ ctx->engines = NULL; ctx->engines_len = 0; ctx->engines_capacity = 0; *xds = ctx; return XDS_OK; } int xds_destroy(xds_t *xds) { size_t i; /* Sanity check parameter. */ assert(xds != NULL); if (xds == NULL) return XDS_ERR_INVALID_ARG; /* Free allocated memory. */ assert(xds->buffer != NULL || (xds->buffer_capacity == 0 && xds->buffer_len == 0)); if (xds->buffer != NULL && xds->we_own_buffer) free(xds->buffer); assert(xds->engines != NULL || xds->engines_capacity == 0); if (xds->engines != NULL) { for (i = 0; i < xds->engines_len; i++) { assert(xds->engines[i].name != NULL); free(xds->engines[i].name); } free(xds->engines); } free(xds); return XDS_OK; } int xds_setbuffer(xds_t *xds, xds_scope_t flag, void *buffer, size_t buffer_len) { /* Sanity check parameters. */ xds_check_parameter(xds != NULL); xds_check_parameter(flag == XDS_GIFT || flag == XDS_LOAN); xds_check_parameter((buffer != NULL && buffer_len != 0) || flag == XDS_GIFT); /* Free the old buffer if there is one. */ if (xds->buffer != NULL && xds->we_own_buffer) free(xds->buffer); xds->buffer_len = 0; if (flag == XDS_GIFT) { xds->buffer = buffer; if (buffer == NULL) xds->buffer_capacity = 0; else xds->buffer_capacity = buffer_len; xds->we_own_buffer = XDS_TRUE; } else { xds->buffer = buffer; xds->buffer_capacity = buffer_len; xds->we_own_buffer = XDS_FALSE; } return XDS_OK; } int xds_getbuffer(xds_t *xds, xds_scope_t flag, void **buffer, size_t *buffer_len) { /* Sanity check parameters. */ xds_check_parameter(xds != NULL); xds_check_parameter(flag == XDS_GIFT || flag == XDS_LOAN); xds_check_parameter(buffer != NULL); xds_check_parameter(buffer_len != NULL); /* Return the buffer to the caller. */ *buffer = xds->buffer; *buffer_len = xds->buffer_len; if (flag == XDS_GIFT) { xds->buffer = NULL; xds->buffer_capacity = 0; xds->buffer_len = 0; } else xds->buffer_len = 0; return XDS_OK; } static int xds_set_capacity(void **array, size_t *array_capacity, size_t new_capacity, size_t elem_size, size_t initial_capacity) { void *buf; size_t size; /* Sanity checks. */ xds_check_parameter(array != NULL); xds_check_parameter(array_capacity != NULL); xds_check_parameter(elem_size != 0); xds_check_parameter(initial_capacity != 0); /* Do we need to re-allocate? */ if (*array_capacity > new_capacity) return XDS_OK; /* Find the correct capacity. */ size = (*array_capacity != 0) ? (*array_capacity * 2) : initial_capacity; while (size < new_capacity) size *= 2; /* Allocate the array and store the new values. */ if ((buf = realloc(*array, size * elem_size)) == NULL) return XDS_ERR_NO_MEM; *array = buf; *array_capacity = size; return XDS_OK; } static int xds_find_engine(const engine_map_t *engines, size_t last, const char *name, size_t *pos) { size_t first; /* Sanity checks. */ xds_check_parameter(engines != NULL || last == 0); xds_check_parameter(name != NULL); xds_check_parameter(pos != NULL); /* Use binary search to find "name" in "engines". */ for (first = 0; (last - first) > 0; ) { size_t half = first + ((last - first) / 2); int rc = strcmp(engines[half].name, name); if (rc < 0) first = half + 1; else if (rc == 0) { /* found it */ *pos = half; return XDS_TRUE; } else last = half; assert(first <= last); } *pos = first; return XDS_FALSE; } int xds_register(xds_t *xds, const char *name, xds_engine_t engine, void *engine_context) { size_t pos; /* Sanity checks. */ xds_check_parameter(xds != NULL); xds_check_parameter(name != NULL); xds_check_parameter(engine != NULL); for (pos = 0; name[pos] != '\0'; ++pos) { if (!isalnum((int)name[pos]) && name[pos] != '-' && name[pos] != '_') return XDS_ERR_INVALID_ARG; } /* Copy the name argument into our own memory. */ name = strdup(name); if (name == NULL) return XDS_ERR_NO_MEM; /* Search engines for the entry. */ if (xds_find_engine(xds->engines, xds->engines_len, name, &pos)) { /* overwrite existing entry */ free(xds->engines[pos].name); } else { /* insert new entry */ int rc = xds_set_capacity((void **)&xds->engines, &xds->engines_capacity, xds->engines_len + 1, sizeof (engine_map_t), XDS_INITIAL_ENGINES_CAPACITY); assert(rc == XDS_OK || rc == XDS_ERR_NO_MEM); if (rc != XDS_OK) return rc; memmove(&xds->engines[pos + 1], &xds->engines[pos], (xds->engines_len - pos) * sizeof (engine_map_t)); xds->engines_len++; } /* Insert entry. */ xds->engines[pos].name = (char *)name; xds->engines[pos].engine = engine; xds->engines[pos].context = engine_context; /* Everything is fine. */ return XDS_OK; } int xds_unregister(xds_t *xds, const char *name) { size_t pos; int rc; /* Sanity checks. */ xds_check_parameter(xds != NULL); xds_check_parameter(name != NULL); for (pos = 0; name[pos] != '\0'; pos++) { if (!isalnum((int)name[pos]) && name[pos] != '-' && name[pos] != '_') return XDS_ERR_INVALID_ARG; } /* Find the entry we're supposed to delete. */ if (!xds_find_engine(xds->engines, xds->engines_len, name, &pos)) return XDS_ERR_UNKNOWN_ENGINE; /* Free the memory allocated for this entry and move the entries behind it back if necessary. */ assert(xds->engines[pos].name != NULL); free(xds->engines[pos].name); memmove(&xds->engines[pos], &xds->engines[pos + 1], (xds->engines_len - (pos + 1)) * sizeof (engine_map_t)); xds->engines_len--; /* Lower capacity if necessary. */ rc = xds_set_capacity((void **)&xds->engines, &xds->engines_capacity, xds->engines_len, sizeof (engine_map_t), XDS_INITIAL_ENGINES_CAPACITY); assert(rc == XDS_OK || rc == XDS_ERR_NO_MEM); if (rc != XDS_OK) return rc; return XDS_OK; } int xds_encode(xds_t *xds, const char *fmt, ...) { int rc; va_list args; /* Sanity checks. */ xds_check_parameter(xds != NULL); xds_check_parameter(fmt != NULL); va_start(args, fmt); rc = xds_vencode(xds, fmt, args); va_end(args); return rc; } int xds_vencode(xds_t *xds, const char *fmt_arg, va_list args) { va_list args_backup; size_t buffer_len_backup; char *name; char *p; char *fmt; int rc; /* Sanity checks. */ xds_check_parameter(xds != NULL); xds_check_parameter(fmt_arg != NULL); assert(xds->mode == XDS_ENCODE); if (xds->mode != XDS_ENCODE) return XDS_ERR_INVALID_MODE; /* Ensure we have a buffer allocated ready for use. */ if (xds->buffer == NULL) { /* allocate a new buffer */ rc = xds_set_capacity((void **)&xds->buffer, &xds->buffer_capacity, XDS_INITIAL_BUFFER_CAPACITY, sizeof (char), XDS_INITIAL_BUFFER_CAPACITY); assert(rc == XDS_OK || rc == XDS_ERR_NO_MEM); if (rc != XDS_OK) return rc; xds->buffer_len = 0; xds->we_own_buffer = XDS_TRUE; } /* Iterate through items in format string and execute apropriate engines. */ fmt = p = strdup(fmt_arg); if (fmt == NULL) return XDS_ERR_NO_MEM; buffer_len_backup = xds->buffer_len; for (name = p; *p != '\0'; name = p) { while (isalnum((int)*p) || *p == '-' || *p == '_') p++; if (*p != '\0') *p++ = '\0'; else *p = '\0'; if (strlen(name) > 0) { int restart_engine; size_t used_buffer_size; size_t pos; if (xds_find_engine(xds->engines, xds->engines_len, name, &pos) == XDS_FALSE) { rc = XDS_ERR_UNKNOWN_ENGINE; goto leave; } do { /* Ensure the buffer has free space. */ assert(xds->buffer_len <= xds->buffer_capacity); if (xds->buffer_len == xds->buffer_capacity) { if (xds->we_own_buffer) { rc = xds_set_capacity((void **)&xds->buffer, &xds->buffer_capacity, xds->buffer_len + 1, sizeof (char), XDS_INITIAL_BUFFER_CAPACITY); assert(rc == XDS_OK || rc == XDS_ERR_NO_MEM); if (rc != XDS_OK) goto leave; } else { rc = XDS_ERR_OVERFLOW; goto leave; } } /* Execute the engine. */ used_buffer_size = 0; args_backup = args; rc = (*xds->engines[pos].engine)( xds, xds->engines[pos].context, xds->buffer + xds->buffer_len, xds->buffer_capacity - xds->buffer_len, &used_buffer_size, &args); assert(rc <= 0); if (rc == XDS_OK) { restart_engine = XDS_FALSE; xds->buffer_len += used_buffer_size; } else if (rc == XDS_ERR_OVERFLOW) { /* enlarge buffer */ if (!xds->we_own_buffer) goto leave; restart_engine = XDS_TRUE; args = args_backup; rc = xds_set_capacity( (void **)&xds->buffer, &xds->buffer_capacity, xds->buffer_capacity + ((used_buffer_size == 0) ? 1 : used_buffer_size), sizeof (char), XDS_INITIAL_BUFFER_CAPACITY); assert(rc == XDS_OK || rc == XDS_ERR_NO_MEM); if (rc != XDS_OK) goto leave; } else goto leave; } while (restart_engine); } } rc = XDS_OK; /* Clean up and leave. */ leave: free(fmt); if (rc != XDS_OK) xds->buffer_len = buffer_len_backup; return rc; } int xds_decode(xds_t *xds, const char *fmt, ...) { int rc; va_list args; /* Sanity checks. */ xds_check_parameter(xds != NULL); xds_check_parameter(fmt != NULL); va_start(args, fmt); rc = xds_vdecode(xds, fmt, args); va_end(args); return rc; } int xds_vdecode(xds_t *xds, const char *fmt_arg, va_list args) { size_t buffer_len_backup; char *name; char *p; char *fmt; int rc; /* Sanity checks. */ xds_check_parameter(xds != NULL); xds_check_parameter(fmt_arg != NULL); assert(xds->mode == XDS_DECODE); if (xds->mode != XDS_DECODE) return XDS_ERR_INVALID_MODE; /* Ensure we have a buffer to decode. */ if (xds->buffer == NULL || xds->buffer_capacity == 0) return XDS_ERR_UNDERFLOW; /* Iterate through the items in the format string and execute the apropriate engines. */ fmt = p = strdup(fmt_arg); if (fmt == NULL) return XDS_ERR_NO_MEM; buffer_len_backup = xds->buffer_len; for (name = p; *p != '\0'; name = p) { while (isalnum((int)*p) || *p == '-' || *p == '_') p++; if (*p != '\0') *p++ = '\0'; else *p = '\0'; if (strlen(name) > 0) { size_t pos; size_t used_buffer_size = 0; if (xds_find_engine(xds->engines, xds->engines_len, name, &pos)) { rc = (*xds->engines[pos].engine)( xds, xds->engines[pos].context, xds->buffer + xds->buffer_len, xds->buffer_capacity - xds->buffer_len, &used_buffer_size, &args); assert(rc <= 0); if (rc == XDS_OK) xds->buffer_len += used_buffer_size; else goto leave; } else { rc = XDS_ERR_UNKNOWN_ENGINE; goto leave; } } } rc = XDS_OK; /* Clean up and leave. */ leave: free(fmt); if (rc != XDS_OK) xds->buffer_len = buffer_len_backup; return rc; } @ 1.12 log @Bumped year in copyright messages for year 2004. @ text @d3 3 a5 3 ** Copyright (c) 2001-2004 Ralf S. Engelschall ** Copyright (c) 2001-2004 The OSSP Project ** Copyright (c) 2001-2004 Cable & Wireless @ 1.11 log @upgrade to standard OSSP copyright and bump year to 2003 @ text @d3 3 a5 3 ** Copyright (c) 2001-2003 Ralf S. Engelschall ** Copyright (c) 2001-2003 The OSSP Project ** Copyright (c) 2001-2003 Cable & Wireless Germany @ 1.10 log @cleanup API by returning xds_rc_t in xds_init, too @ text @d3 3 a5 2 ** Copyright (c) 2001-2002 The OSSP Project (http://www.ossp.org/) ** Copyright (c) 2001-2002 Cable & Wireless Deutschland (http://www.cw.com/de/) @ 1.9 log @update texts @ text @d36 1 a36 1 xds_t *xds_init(xds_mode_t mode) d41 3 d45 2 a46 4 if (mode != XDS_ENCODE && mode != XDS_DECODE) { errno = EINVAL; return NULL; } d50 1 a50 1 return NULL; /* errno set by malloc(3) */ d66 3 a68 1 return ctx; d71 1 a71 1 void xds_destroy(xds_t *xds) d78 1 a78 1 return; d95 1 a95 1 return; @ 1.8 log @bump copyright year @ text @d2 1 a2 1 ** XDS - OSSP Extensible Data Serialization Library d6 2 a7 2 ** This file is part of OSSP XDS, an extensible data serialization ** library which can be found at http://www.ossp.org/pkg/xds/. @ 1.7 log @Remove trailing whitespaces on all non-generated files. @ text @d3 2 a4 2 ** Copyright (c) 2001 The OSSP Project (http://www.ossp.org/) ** Copyright (c) 2001 Cable & Wireless Deutschland (http://www.cw.com/de/) @ 1.6 log @Hhmm... who has introduced ossp.com?! Our project's domain is ossp.org, of course. @ text @d167 1 a167 1 size = (*array_capacity != 0) ? (*array_capacity * 2) : initial_capacity; d229 1 a229 1 if (xds_find_engine(xds->engines, xds->engines_len, name, &pos)) { d325 1 a325 1 if (xds->buffer == NULL) { d328 1 a328 1 XDS_INITIAL_BUFFER_CAPACITY, sizeof (char), d355 1 a355 1 if (xds_find_engine(xds->engines, xds->engines_len, name, &pos) @ 1.5 log @Add still missing parameter sanity checks @ text @d7 1 a7 1 ** library which can be found at http://www.ossp.com/pkg/xds/. @ 1.4 log @Final adjustments to coding style in order to make OSSP XDS look equal in style to all other OSSP parts. This should remove most of the strangeness GNU indent usually introduces. @ text @d298 4 d429 4 @ 1.3 log @Use the license consistently. @ text @d48 2 a49 3 ctx = malloc(sizeof (struct xds_context)); if (ctx == NULL) return NULL; /* errno is set by calloc() */ d70 3 a72 1 /* Sanity checks. */ a81 1 d84 1 a84 2 size_t i; for (i = 0; i < xds->engines_len; ++i) { d90 1 a91 1 free(xds); d98 1 a98 1 /* Sanity checks. */ d129 1 a129 2 /* Sanity checks. */ d140 2 a141 1 xds->buffer_capacity = xds->buffer_len = 0; d150 2 a151 2 size_t new_capacity, size_t elem_size, size_t initial_capacity) d167 1 a167 1 size = (*array_capacity != 0) ? *array_capacity * 2 : initial_capacity; d172 1 a172 2 buf = realloc(*array, size * elem_size); if (buf == NULL) d191 1 a191 1 for (first = 0; (last - first) > 0;) { d204 1 a205 1 *pos = first; d245 1 a245 1 ++xds->engines_len; d249 2 a250 2 xds->engines[pos].name = (char *)name; xds->engines[pos].engine = engine; d265 1 a265 1 for (pos = 0; name[pos] != '\0'; ++pos) { d280 1 a280 1 --xds->engines_len; d283 2 a284 4 rc = xds_set_capacity((void **)&xds->engines, &xds->engines_capacity, xds->engines_len, sizeof (engine_map_t), d297 1 d321 5 a325 5 if (xds->buffer == NULL) { /* allocate a new buffer */ rc = xds_set_capacity((void **)&xds->buffer, &xds->buffer_capacity, XDS_INITIAL_BUFFER_CAPACITY, sizeof (char), XDS_INITIAL_BUFFER_CAPACITY); d333 1 a333 2 /* Iterate through the items in the format string and execute the apropriate engines. */ d340 2 a341 2 ++p; if (*p) d351 2 a352 2 if (xds_find_engine(xds->engines, xds->engines_len, name, &pos) == XDS_FALSE) { d364 1 a364 2 xds->buffer_len + 1, sizeof (char), d379 5 a383 7 rc = (*xds->engines[pos].engine)(xds, xds->engines[pos].context, xds->buffer + xds->buffer_len, xds->buffer_capacity - xds->buffer_len, &used_buffer_size, &args); d396 5 a400 7 rc = xds_set_capacity((void **)&xds->buffer, &xds->buffer_capacity, xds->buffer_capacity + ((used_buffer_size == 0) ? 1 : used_buffer_size), sizeof (char), XDS_INITIAL_BUFFER_CAPACITY); d425 1 d459 2 a460 2 ++p; if (*p) d468 1 d470 5 a474 7 rc = (*xds->engines[pos].engine)(xds, xds->engines[pos].context, xds->buffer + xds->buffer_len, xds->buffer_capacity - xds->buffer_len, &used_buffer_size, &args); @ 1.2 log @Do not export internal functions, too. @ text @d1 28 a28 23 /* * XDS - OSSP Extensible Data Serialization Library Copyright (c) 2001 The * OSSP Project (http://www.ossp.org/) Copyright (c) 2001 Cable & Wireless * Deutschland (http://www.cw.com/de/) * * This file is part of OSSP XDS, an extensible data serialization library * which can be found at http://www.ossp.com/pkg/xds/. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ @ 1.1 log @First cut of the ruthless style adjustments to OSSP XDS: o adjust source tree to follow OSSP source tree style by heavily combining sources into smaller sets (needs more work when still missing parts are added later) o automatic re-indentation of sources with GNU indent (still needs manual review and adjustments; will follow) These two heavy steps were mostly done automatically with the help of two helper scripts written in Perl. So expect more manual adjustments to follow... @ text @d145 1 a145 1 int xds_set_capacity(void **array, size_t *array_capacity, d177 1 a177 1 int xds_find_engine(const engine_map_t *engines, size_t last, @