Mercurial > code
changeset 103:7fefa3a34461
pack.c now directly write to the file
author | David Demelier <markand@malikania.fr> |
---|---|
date | Tue, 17 Jan 2012 13:38:54 +0100 |
parents | 735d6c774f7a |
children | c66fb578a7c4 |
files | pack.c |
diffstat | 1 files changed, 88 insertions(+), 122 deletions(-) [+] |
line wrap: on
line diff
--- a/pack.c Tue Jan 17 12:01:22 2012 +0100 +++ b/pack.c Tue Jan 17 13:38:54 2012 +0100 @@ -16,7 +16,6 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include <sys/queue.h> #include <stdio.h> #include <stdlib.h> #include <stdint.h> @@ -30,41 +29,20 @@ * structure definitions * -------------------------------------------------------- */ -/* - * Conversion function pointer. - */ -typedef void (*convert_fn)(void *); - -/* - * Item structure store the integer into the largest data type - * uint64_t. - */ - -struct item { - size_t size; /* 8, 16, 32 or 64 bits? */ - uint64_t i; /* the data */ - convert_fn conv; /* conversion function */ - STAILQ_ENTRY(item) next; -}; - -/* - * List of item structure. - */ - -STAILQ_HEAD(item_list, item); +typedef void (*ConvertFn)(void *); /* -------------------------------------------------------- * prototypes * -------------------------------------------------------- */ -static int pack_item_add(struct item_list *, const struct item *); -static int pack_parse(struct item_list *, const char *, va_list); static size_t pack_getsize(char); -static convert_fn pack_getconvert(char); +static ConvertFn pack_getconvert_by_tok(char); +static ConvertFn pack_getconvert_by_size(size_t); static void pack_convert16(void *); static void pack_convert32(void *); static void pack_convert64(void *); -static int pack_fatal(struct item_list *); +static void pack_write_one(int, FILE *, uint64_t, size_t); +static void pack_write_multiple(int, FILE *, uint8_t *, int, size_t); /* -------------------------------------------------------- * private functions @@ -81,7 +59,7 @@ static struct integer { char tok; /* format char */ size_t tocopy; /* size */ - convert_fn convert; /* conversion function */ + ConvertFn convert; /* conversion function */ } sizes[] = { { 'c', sizeof (uint8_t), NULL }, { 's', sizeof (uint16_t), &pack_convert16 }, @@ -90,29 +68,6 @@ }; /* - * Try to append a new item to the list. The function create a new item - * object since the pack_parse() use a stack'ed item and not an - * allocated object. Returns 0 or -1 on failure. - */ - -static int -pack_item_add(struct item_list *list, const struct item *item) -{ - struct item *res; - - if ((res = malloc(sizeof (struct item))) == NULL) - return -1; - - res->size = item->size; - res->i = item->i; - res->conv = item->conv; - - STAILQ_INSERT_TAIL(list, res, next); - - return 0; -} - -/* * Parse the format, return 0 on success or -1 on failure. */ @@ -151,56 +106,6 @@ nelem = 1; \ } while (/* CONSTCOND */ 0) -static int -pack_parse(struct item_list *list, const char *fmt, va_list ap) -{ - const char *p; - char tok; - struct item item; - int nelem; - - STAILQ_INIT(list); - - for (p = fmt; *p != '\0'; ++p) { - if (isspace(*p)) - continue; - - tok = *p; - item.size = pack_getsize(tok); - - /* Bad character */ - if (item.size == 0) - continue; - - PACK_GETNELEM(nelem, p); - if (nelem == 0) - continue; - - /* - * If i is 1, then we only have one integer, if it's more - * than one, user may have given an array of something else. - */ - if (nelem == 1) { - PACK_GETARG(item.i, ap, tok); - item.conv = pack_getconvert(tok); - - if (pack_item_add(list, &item) < 0) - return pack_fatal(list); - } else { - uint8_t *arr = va_arg(ap, void *); - int i; - - for (i = 0; i < nelem; ++i) { - memcpy(&item.i, &arr[i * item.size], item.size); - if (pack_item_add(list, &item) < 0) - return pack_fatal(list); - } - } - } - - return 0; -} - /* * Get the appropriate size associated with the `tok' character. If * the token is not found the result is 0. @@ -223,8 +128,8 @@ * Return the conversion function. */ -static convert_fn -pack_getconvert(char tok) +static ConvertFn +pack_getconvert_by_tok(char tok) { struct integer *s; unsigned int i; @@ -237,6 +142,23 @@ } /* + * Same but by size. + */ + +static ConvertFn +pack_getconvert_by_size(size_t size) +{ + struct integer *s; + unsigned int i; + + for (s = sizes, i = 0; i < LENGTH(sizes); ++s, ++i) + if (s->tocopy == size) + return s->convert; + + return NULL; +} + +/* * Conversion functions. They reverse the bytes without any * check. */ @@ -265,17 +187,41 @@ *x = pack_swap64(*x); } -static int -pack_fatal(struct item_list *list) +static void +pack_write_one(int ptype, FILE *fp, uint64_t it, size_t size) { - struct item *item, *tmp; + uint64_t cv = it; + + if (ptype != PACK_HOST_BYTEORDER) { + ConvertFn conv = pack_getconvert_by_size(size); + + if (conv != NULL) + conv(&cv); + } + + fwrite(&cv, size, 1, fp); +} - STAILQ_FOREACH_SAFE(item, list, next, tmp) - free(item); +static void +pack_write_multiple(int ptype, FILE *fp, uint8_t *arr, int length, size_t size) +{ + uint64_t cv; + int i; + ConvertFn conv = NULL; + + if (ptype != PACK_HOST_BYTEORDER) + conv = pack_getconvert_by_size(size); - return -1; + for (i = 0; i < length; ++i) { + cv = arr[i * size]; + if (conv != NULL) + conv(&cv); + + fwrite(&cv, size, 1, fp); + } } + /* -------------------------------------------------------- * public functions * -------------------------------------------------------- */ @@ -336,24 +282,44 @@ int pack_vfwrite(int ptype, FILE *fp, const char *fmt, va_list ap) { - struct item_list list; - int status; + int nelem; + size_t size; + char tok; + const char *p; - if ((status = pack_parse(&list, fmt, ap)) == 0) { - struct item *item, *tmp; + for (p = fmt; *p != '\0'; ++p) { + if (isspace(*p)) + continue; + + tok = *p; + size = pack_getsize(tok); + + /* Bad character */ + if (size == 0) + continue; - STAILQ_FOREACH_SAFE(item, &list, next, tmp) { - /* 8 bits does not need to be converted */ - if (ptype != PACK_HOST_BYTEORDER && item->conv != NULL) - item->conv(&item->i); + PACK_GETNELEM(nelem, p); + if (nelem == 0) + continue; - fwrite(&item->i, item->size, 1, fp); + /* + * If i is 1, then we only have one integer, if it's more + * than one, user may have given an array of something else. + */ + if (nelem == 1) { + uint64_t item; - free(item); + PACK_GETARG(item, ap, tok); + pack_write_one(ptype, fp, item, size); + } else { + uint8_t *arr; + + arr = va_arg(ap, uint8_t *); + pack_write_multiple(ptype, fp, arr, nelem, size); } } - return status; + return 0; } /* @@ -410,7 +376,7 @@ const char *p; void *ptr; size_t tocopy; - convert_fn convert; + ConvertFn convert; for (p = fmt; *p != '\0'; ++p) { char tok; @@ -438,7 +404,7 @@ fread((char *) ptr + (tocopy * i), tocopy, 1, fp); /* Convert if needed */ - convert = pack_getconvert(tok); + convert = pack_getconvert_by_tok(tok); if (ptype != PACK_HOST_BYTEORDER && convert != NULL) convert((char *) ptr + (tocopy * i)); }