# HG changeset patch # User David Demelier # Date 1385546000 -3600 # Node ID 5f75779cc7eb3229cd962d892db513f2e9da4fb3 # Parent d263f85f43a42eb3355e792b87acb7d78caff4a4 Deprecate C diff -r d263f85f43a4 -r 5f75779cc7eb C/array.c --- a/C/array.c Wed Nov 27 10:25:58 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,382 +0,0 @@ -/* - * array.c -- manipulate dynamic arrays - * - * Copyright (c) 2011, 2012, David Demelier - * - * Permission to use, copy, modify, and/or 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. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include -#include -#include - -#include "array.h" - -#define OFFSET(x) (arr->unit * (x)) - -static int grow(struct array *); - -int -array_init(struct array *arr, size_t unit) -{ - if (unit == 0) - return -1; - - arr->unit = unit; - arr->size = OFFSET(arr->chksize); - - /* Set defaults if needed */ - arr->chksize = (arr->chksize <= 0) ? ARRAY_DEFAULT_CHKSIZE : arr->chksize; - arr->malloc = (arr->malloc == NULL) ? &malloc : arr->malloc; - arr->realloc = (arr->realloc == NULL) ? &realloc : arr->realloc; - - if ((arr->data = arr->malloc(arr->size)) == NULL) - return -1; - - if (arr->flags & ARRAY_CLEARBITS) - memset(arr->data, 0, arr->size); - - return 0; -} - -/* - * Valid options that can be set for an array : - * l -> optional array block size of type int - * m -> malloc function that must matches void * (*malloc)(size_t) - * r -> realloc function that must matches void * (*realloc)(void *, size_t) - * f -> array flags of type int - */ -void -array_set(struct array *arr, const char *fmt, ...) -{ - va_list ap; - const char *p; - - va_start(ap, fmt); - for (p = fmt; *p != '\0'; ++p) - switch (*p) { - case 'l': - arr->chksize = va_arg(ap, int); - break; - case 'm': - arr->malloc = va_arg(ap, void *(*)(size_t)); - break; - case 'r': - arr->realloc = va_arg(ap, void *(*)(void *, size_t)); - break; - case 'f': - arr->flags = va_arg(ap, int); - break; - default: - break; - } -} - -/* - * Add to the head of array. NOTE: this may be very slow when adding a lot - * of object (about 100000). If you need to add a lot of data please consider - * using linked list instead. Returns -1 on failure or 0 on success. - */ -int -array_push(struct array *arr, const void *data) -{ - if (grow(arr) < 0) - return -1; - - memmove((char *)arr->data + arr->unit, arr->data, OFFSET(arr->length++)); - memcpy((char *)arr->data, data, arr->unit); - - return 0; -} - -/* - * Insert the data at the specified index. The function returns -1 on - * allocation failure or the position of the added element. - */ -int -array_insert(struct array *arr, const void *data, int index) -{ - if (arr->flags & ARRAY_INSERTSAFE) - if (index < 0 || index > arr->length) - return -1; - - if (index < 0) - return array_push(arr, data); - if (index >= arr->length) - return array_append(arr, data); - - /* Good place */ - memmove((char *)arr->data + OFFSET(index + 1), - (char *)arr->data + OFFSET(index), OFFSET(arr->length++ - index)); - memcpy((char *)arr->data + OFFSET(index), data, arr->unit); - - return index; -} - -/* - * Append the data to the end of array. Returns -1 on failure or the position - * of the added element. - */ -int -array_append(struct array *arr, const void *data) -{ - if (grow(arr) < 0) - return -1; - - memcpy((char *)arr->data + OFFSET(arr->length++), data, arr->unit); - - return (arr->length - 1); -} - -/* - * Remove the array's head. - */ -void -array_pop(struct array *arr) -{ - array_iremove(arr, 0); -} - -/* - * Remove the array's tail. - */ -void -array_unqueue(struct array *arr) -{ - array_iremove(arr, arr->length - 1); -} - -/* - * Remove the data at the specified index. Bounds are checked. - */ -void -array_iremove(struct array *arr, int index) -{ - if (arr->length > 0 && index >= 0 && index < arr->length) { - if (arr->flags & ARRAY_FASTREMOVE) - memmove((char *)arr->data + OFFSET(index), - (char *)arr->data + OFFSET(--arr->length), - arr->unit); - else - memmove((char *)arr->data + OFFSET(index), - (char *)arr->data + OFFSET(index + 1), - OFFSET(arr->length-- - index - 1)); - } - - if (arr->flags & ARRAY_CLEARBITS) - memset((char *)arr->data + OFFSET(arr->length), 0, arr->unit); -} - -/* - * Remove the object referenced by the `data' argument. Useful when you - * don't know the index. - */ -void -array_premove(struct array *arr, const void *data) -{ - void *elm; - int i; - - for (i = 0; i < arr->length; ++i) { - elm = (char *)arr->data + OFFSET(i); - - if (memcmp(elm, data, arr->unit) == 0) { - array_iremove(arr, i); - break; - } - } -} - -/* - * Swap the two elements referenced by index `i1' and `i2'. This function needs - * to allocate data to swap elements thus if the functions fails it returns -1 - * otherwise 0 is returned. - */ -int -array_iswap(struct array *arr, int i1, int i2) -{ - void *tmp; - - /* Out of bounds */ - if (i1 >= arr->length || i1 < 0 || i2 >= arr->length || i2 < 0) - return -1; - - if ((tmp = arr->malloc(arr->unit)) == NULL) - return -1; - - memcpy((char *)tmp, (char *)arr->data + OFFSET(i1), arr->unit); - memcpy((char *)arr->data + OFFSET(i1), (char *)arr->data + OFFSET(i2), - arr->unit); - memcpy((char *)arr->data + OFFSET(i2), (char *)tmp, arr->unit); - - /* - * Clear bytes for safety you probably don't want a password or - * secure data to be left somewhere in the memory. - */ - - if (arr->flags & ARRAY_CLEARBITS) - memset(tmp, 0, arr->unit); - free(tmp); - - return 0; -} - -/* - * Swap the two elements referenced by data `o1' and `o2'. This function - * may be slow on large arrays since it must travel all the object - * to find the indexes. - */ -int -array_pswap(struct array *arr, const void *o1, const void *o2) -{ - int found, i1, i2; - - for (i1 = found = 0; !found && i1 < arr->length; ++i1) - found = memcmp((char *)arr->data + OFFSET(i1), o1, arr->unit) == 0; - - if (!found) - return -1; - - for (i2 = found = 0; !found && i2 < arr->length; ++i2) - found = memcmp((char *)arr->data + OFFSET(i2), o2, arr->unit) == 0; - - if (!found) - return -1; - - return array_iswap(arr, --i1, --i2); -} - -/* - * Apply the function `fn' on each object and give the optional `udata' - * argument to the function too. - */ -void -array_map(const struct array *arr, array_map_t fn, void *udata) -{ - int i; - - for (i = 0; i < arr->length; ++i) - fn((char *)arr->data + OFFSET(i), udata); -} - -/* - * Call qsort function to sort the array. - */ -void -array_sort(struct array *arr, array_cmp_t fn) -{ - qsort(arr->data, arr->length, arr->unit, fn); -} - -/* - * Compare each object with the user supplied function. If the `fn' function - * returns 1, 1 is returned and dst points to the correct object, dst should - * be a pointer to a pointer of object, like (int **) for a array of int. - */ -int -array_find(const struct array *arr, array_cmp_t fn, void *dst, void *u) -{ - int st, i; - - for (i = st = 0; i < arr->length && st != 1; ++i) - st = fn((char *)arr->data + OFFSET(i), u); - - if (st && dst) - *(char **)dst = (char *)arr->data + OFFSET(i - 1); - - return (st) ? i - 1 : -1; -} - -void * -array_first(const struct array *arr) -{ - return arr->data; -} - -void * -array_last(const struct array *arr) -{ - if (arr->length == 0) - return array_first(arr); - - return (char *)arr->data + OFFSET(arr->length - 1); - -} - -void * -array_get(const struct array *arr, int idx) -{ - if (idx < 0) - return array_first(arr); - if (idx >= arr->length) - return array_last(arr); - - return (char *)arr->data + OFFSET(idx); -} - -/* - * Erase every bytes and set the length to 0. - */ -void -array_clear(struct array *arr) -{ - memset(arr->data, 0, arr->size); - arr->length = 0; -} - -/* - * Same as array_clear except it also free the array object. - */ -void -array_free(struct array *arr) -{ - array_clear(arr); - free(arr->data); - - arr->data = NULL; - arr->size = 0; -} - -/* - * Trim down the array to the correct size. - */ -void * -array_trim(struct array *arr) -{ - return arr->realloc(arr->data, arr->length * arr->unit); -} - -/* - * Increate the array storage when it is full. If the buffer is fixed size - * it returns -1 on full buffer otherwise 0 is returned if allocation - * succeeded. - */ -static int -grow(struct array *arr) -{ - if ((arr->size / arr->unit) > (size_t)arr->length) - return 0; - - if (!(arr->flags & ARRAY_FIXED)) { - if ((arr->data = arr->realloc(arr->data, arr->size + - OFFSET(arr->chksize))) == NULL) { - arr->size = arr->length = 0; - return -1; - } - - arr->size += OFFSET(arr->chksize); - } else - return -1; - - return 0; -} diff -r d263f85f43a4 -r 5f75779cc7eb C/array.h --- a/C/array.h Wed Nov 27 10:25:58 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,125 +0,0 @@ -/* - * array.h -- manipulate dynamic arrays - * - * Copyright (c) 2011, 2012, David Demelier - * - * Permission to use, copy, modify, and/or 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. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef _ARRAY_H_ -#define _ARRAY_H_ - -#include - -#ifndef ARRAY_DEFAULT_CHKSIZE -#define ARRAY_DEFAULT_CHKSIZE 128 -#endif - -enum array_flags { - ARRAY_AUTO = 0, /* array grows automatically */ - ARRAY_FIXED = (1 << 0), /* fixed size length */ - ARRAY_FASTREMOVE = (1 << 1), /* use last object when removing */ - ARRAY_CLEARBITS = (1 << 2), /* clear data when inserting/removing */ - ARRAY_INSERTSAFE = (1 << 3) /* insertion must have valid indexes */ -}; - -struct array { - int flags; /* (ro) array flags (default AUTO) */ - void *data; /* (rw) array of data */ - int length; /* (ro) number of element inside */ - size_t size; /* (ro) current buffer size (allocated memory) */ - size_t unit; /* (ro) unit size (sizeof the object) */ - int chksize; /* (rw) chunk size (used when growing array) */ - - /* Own allocation functions */ - void * (*malloc)(size_t); - void * (*realloc)(void *, size_t); -}; - -typedef void (*array_map_t)(void *, void *); -typedef int (*array_cmp_t)(const void *, const void *); - -#ifdef __cplusplus -extern "C" { -#endif - -int -array_init(struct array *, size_t); - -void -array_set(struct array *, const char *, ...); - -int -array_push(struct array *, const void *); - -int -array_insert(struct array *, const void *, int); - -int -array_append(struct array *, const void *); - -void -array_pop(struct array *); - -void -array_unqueue(struct array *); - -void -array_iremove(struct array *, int); - -void -array_premove(struct array *, const void *); - -int -array_iswap(struct array *, int, int); - -int -array_pswap(struct array *, const void *, const void *); - -void -array_map(const struct array *, array_map_t, void *); - -void -array_sort(struct array *, array_cmp_t); - -int -array_find(const struct array *, array_cmp_t, void *, void *); - -void * -array_first(const struct array *); - -void * -array_get(const struct array *, int); - -void * -array_last(const struct array *); - -void -array_clear(struct array *); - -void -array_free(struct array *); - -void * -array_trim(struct array *); - -#define ARRAY_FOREACH(a, var, i) \ - for (i = 0, (var) = array_first((a)); \ - i < (a)->length; \ - (var) = array_get(a, ++i)) - -#ifdef __cplusplus -} -#endif - -#endif /* _ARRAY_H_ */ diff -r d263f85f43a4 -r 5f75779cc7eb C/buf.c --- a/C/buf.c Wed Nov 27 10:25:58 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,268 +0,0 @@ -/* - * buf.c -- easy way to manipulate strings - * - * Copyright (c) 2011, 2012, David Demelier - * - * Permission to use, copy, modify, and/or 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. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include -#include -#include - -#include "buf.h" - -#define BUF_AVAIL(buf) ((buf)->alsize - (buf)->length) -#define BUF_SAFE(buf) (!((buf)->flags & BUF_UNSAFE)) -#define BUF_FIXED(buf) ((buf)->flags & BUF_FIXED) -#define BUF_AUTO(buf) (buf->flags == 0) - -static void copy(struct buf *, const void *, size_t); -static int grow(struct buf *, size_t); - -int -buf_init(struct buf *buf, const char *txt) -{ - /* Set defaults if needed */ - buf->chksize = (buf->chksize <= 0) ? 128 : buf->chksize; - buf->alsize = buf->chksize + 1; - buf->malloc = (buf->malloc == NULL) ? &malloc : buf->malloc; - buf->realloc = (buf->realloc == NULL) ? &realloc : buf->realloc; - - if ((buf->text = buf->malloc(buf->alsize)) == NULL) - return -1; - - if (txt != NULL) - buf_cat(buf, txt); - - memset(buf->text, 0, buf->alsize); - - return 0; -} - -void -buf_set(struct buf *buf, const char *fmt, ...) -{ - va_list ap; - const char *p; - - va_start(ap, fmt); - for (p = fmt; *p != '\0'; ++p) - switch (*p) { - case 'l': - buf->chksize = va_arg(ap, int); - break; - case 'm': - buf->malloc = va_arg(ap, void *(*)(size_t)); - break; - case 'r': - buf->realloc = va_arg(ap, void *(*)(void *, size_t)); - break; - case 'f': - case 't': - buf->flags = va_arg(ap, int); - break; - default: - break; - } -} - -/* - * This function appends not more than max characters from str. - */ -int -buf_ncat(struct buf *buf, const char *str, size_t max) -{ - size_t tocopy = max; - - for (tocopy = 0; str[tocopy] != '\0' && tocopy < max; ++tocopy) - continue; - - if (BUF_AVAIL(buf) <= tocopy) { - /* Can't add more */ - if (BUF_SAFE(buf) && BUF_FIXED(buf)) - return -1; - - if (BUF_AUTO(buf)) { - if (grow(buf, tocopy) < 0) - return -1; - } else { - /* String is unsafe, truncate to the available size */ - tocopy = BUF_AVAIL(buf) - 1; - } - } - - copy(buf, str, tocopy); - - return 0; -} - -/* - * Append the string str to the end of the string buffer. - */ -int -buf_cat(struct buf *buf, const char *str) -{ - return buf_ncat(buf, str, strlen(str)); -} - -/* - * Append the caracter c to the end of buffer - */ -int -buf_putc(struct buf *buf, int c) -{ - char str[2] = { c, '\0' }; - - return buf_ncat(buf, str, 1); -} - -/* - * Concatenate the printf(3) like call to the string buffer, this function - * returns -1 on fixed safe buffer, otherwise 0 is returned if there - * is no allocation failure. - */ -int -buf_vprintf(struct buf *buf, const char *fmt, va_list ap) -{ - int copied, rv = 0, done = 0; - - if (BUF_FIXED(buf) && BUF_SAFE(buf)) - return -1; - - do { - copied = vsnprintf(&buf->text[buf->length], - BUF_AVAIL(buf), fmt, ap); - - if (copied >= (signed int)BUF_AVAIL(buf) || copied == -1) { - if (BUF_FIXED(buf)) - done = 1; - - /* - * vsnprintf returns -1 on windows, we need to grow - * the buffer by block size. - */ - if (grow(buf, buf->alsize + buf->chksize) < 0) { - done = 1; - rv = -1; - } - } else { - done = 1; - } - } while (!done); - - buf->length = strlen(buf->text); - - return rv; -} - -int -buf_printf(struct buf *buf, const char *fmt, ...) -{ - va_list ap; - int rv; - - va_start(ap, fmt); - rv = buf_vprintf(buf, fmt, ap); - va_end(ap); - - return rv; -} - -/* - * Realloc the string to it's size and remove useless bytes. - */ -int -buf_trim(struct buf *buf) -{ - if ((buf->text = realloc(buf->text, buf->length + 1)) == NULL) { - buf->alsize = 0; - return -1; - } - - buf->alsize = buf->length + 1; - - return 0; -} - -/* - * Remove `n' characters from the buffer, a positive value will cut the string - * from beginning, negative value will cut from end. - */ -void -buf_cut(struct buf *buf, int start) -{ - if ((start > 0 && start >= buf->length) || - (start < 0 && (int)buf->length + start < 0)) - return; - - if (start < 0 && (int)buf->length + start >= 0) - start = buf->length + start; - - buf->text[start] = '\0'; - buf->length -= buf->length - start; -} - -/* - * Clear the string buffer. - */ -void -buf_clear(struct buf *buf) -{ - memset(buf->text, 0, buf->alsize); - - buf->length = 0; -} - -void -buf_free(struct buf *buf) -{ - if (buf != NULL) { - buf_clear(buf); - free(buf->text); - - buf->text = NULL; - buf->alsize = 0; - } -} - -/* - * Append to the end of buffer the void ptr of count size. - */ -static void -copy(struct buf *buf, const void *ptr, size_t count) -{ - memcpy(buf->text + buf->length, ptr, count); - - buf->text[buf->length + count] = '\0'; - buf->length += count; -} - -/* - * Grow the text buffer until the available size fit the needed - * size. This function may return -1 on allocation failure. - */ -static int -grow(struct buf *buf, size_t needed) -{ - while (BUF_AVAIL(buf) <= needed) { - buf->text = buf->realloc(buf->text, buf->alsize + buf->chksize); - - if (buf->text == NULL) - return -1; - - buf->alsize += buf->chksize; - } - - return 0; -} diff -r d263f85f43a4 -r 5f75779cc7eb C/buf.h --- a/C/buf.h Wed Nov 27 10:25:58 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,88 +0,0 @@ -/* - * buf.h -- easy way to manipulate strings - * - * Copyright (c) 2011, 2012, David Demelier - * - * Permission to use, copy, modify, and/or 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. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef _BUF_H_ -#define _BUF_H_ - -#include - -#ifdef __GNUC__ -# define _buf_at_printf(i1, i2) __attribute__ ((format (printf, i1, i2))) -#else -# define _buf_at_printf(i1, i2) -#endif - -enum buf_flags { - BUF_UNSAFE = (1 << 0), /* string may be truncated */ - BUF_FIXED = (1 << 1), /* string has fixed length */ -}; - -struct buf { - enum buf_flags flags; /* string flags */ - char *text; /* string text */ - size_t length; /* string length */ - size_t alsize; /* allocated size */ - int chksize; /* chunk size */ - int maxsize; /* max fixed length size */ - - void * (*malloc)(size_t); /* alternate malloc */ - void * (*realloc)(void *, size_t); /* alternate realloc */ -}; - -#ifdef __cplusplus -extern "C" { -#endif - -int -buf_init(struct buf *, const char *); - -void -buf_set(struct buf *, const char *, ...); - -int -buf_ncat(struct buf *, const char *, size_t); - -int -buf_cat(struct buf *, const char *); - -int -buf_putc(struct buf *, int); - -int -buf_vprintf(struct buf *, const char *, va_list); - -int -buf_printf(struct buf *, const char *, ...) _buf_at_printf(2, 3); - -int -buf_trim(struct buf *); - -void -buf_cut(struct buf *, int); - -void -buf_clear(struct buf *); - -void -buf_free(struct buf *); - -#ifdef __cplusplus -} -#endif - -#endif /* _BUF_H_ */ diff -r d263f85f43a4 -r 5f75779cc7eb C/directory.c --- a/C/directory.c Wed Nov 27 10:25:58 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,144 +0,0 @@ -/* - * directory.c -- portable way to open directories - * - * Copyright (c) 2011, 2012 David Demelier - * - * Permission to use, copy, modify, and/or 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. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include -#include -#include - -#include "directory.h" - -#if defined(_WIN32) /* WINDOWS */ - -struct directory * -directory_open(const char *path) -{ - WIN32_FIND_DATA fdata; - HANDLE h; - struct directory *res; - char respath[FILENAME_MAX + 1]; - - if (!(res = calloc(1, sizeof (struct directory)))) - return NULL; - - snprintf(respath, sizeof (respath), "%s/*", path); - - if ((h = FindFirstFile(respath, &fdata)) == INVALID_HANDLE_VALUE) { - free(res); - return NULL; - } - - do { - res->ents = realloc(res->ents, - sizeof (*res->ents) * (res->nents + 1)); - - /* Fail to reallocate */ - if (!res->ents) { - free(res); - res = NULL; - break; - } - - res->ents[res->nents].name = strdup(fdata.cFileName); - res->ents[res->nents].type = fdata.dwFileAttributes; - res->ents[res->nents++].length = strlen(fdata.cFileName); - } while (FindNextFile(h, &fdata) != 0); - - return res; -} - -const char * -directory_error(void) -{ - static char msg[1024]; - DWORD num; - - num = GetLastError(); - - FormatMessage( - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - num, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - msg, - sizeof (msg), - NULL - ); - - return msg; -} - -#else /* UNIX */ - -# include - -struct directory * -directory_open(const char *path) -{ - DIR *dp; - struct dirent *ent; - struct directory *res; - - if (!(res = calloc(1, sizeof (struct directory)))) - return NULL; - - if (!(dp = opendir(path))) { - free(res); - return NULL; - } - - while ((ent = readdir(dp))) { - res->ents = realloc(res->ents, - sizeof (*res->ents) * (res->nents + 1)); - - /* Fail to reallocate */ - if (!res->ents) { - free(res); - res = NULL; - break; - } - - res->ents[res->nents].name = strdup(ent->d_name); - res->ents[res->nents].type = ent->d_type; - res->ents[res->nents++].length = ent->d_namlen; - } - - (void)closedir(dp); - - return res; -} - -const char * -directory_error(void) -{ - return strerror(errno); -} - -#endif - -void -directory_free(struct directory *dir) -{ - int i; - - for (i = 0; i < dir->nents; ++i) - free(dir->ents[i].name); - - free(dir->ents); - free(dir); -} diff -r d263f85f43a4 -r 5f75779cc7eb C/directory.h --- a/C/directory.h Wed Nov 27 10:25:58 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,61 +0,0 @@ -/* - * directory.h -- portable way to open directories - * - * Copyright (c) 2011, 2012 David Demelier - * - * Permission to use, copy, modify, and/or 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. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef _DIRECTORY_H_ -#define _DIRECTORY_H_ - -struct directory { - int nents; /* number of entries */ - - struct { - char *name; /* entry name */ - int length; /* length of entry */ - int type; /* type of entry */ - } *ents; -}; - -#if defined(_WIN32) - -# include - -enum { - DIRECTORY_DIR = FILE_ATTRIBUTE_DIRECTORY, - DIRECTORY_FILE = FILE_ATTRIBUTE_NORMAL -}; - -#else - -# include - -enum { - DIRECTORY_DIR = DT_DIR, - DIRECTORY_FILE = DT_REG -}; - -#endif - -struct directory * -directory_open(const char *); - -const char * -directory_error(void); - -void -directory_free(struct directory *); - -#endif /* _DIRECTORY_H_ */ diff -r d263f85f43a4 -r 5f75779cc7eb C/ini.c --- a/C/ini.c Wed Nov 27 10:25:58 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,555 +0,0 @@ -/* - * ini.c -- parse .ini like files - * - * Copyright (c) 2011, 2012, David Demelier - * - * Permission to use, copy, modify, and/or 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. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include -#include -#include -#include -#include -#include - -#include "ini.h" - -/* - * sys/queue.h bits. - */ - -#if !defined(TAILQ_FIRST) -#define TAILQ_FIRST(head) ((head)->tqh_first) -#endif - -#if !defined(TAILQ_FOREACH) -#define TAILQ_FOREACH(var, head, field) \ - for ((var) = TAILQ_FIRST((head)); \ - (var); \ - (var) = TAILQ_NEXT((var), field)) -#endif - -#if !defined(TAILQ_FOREACH_SAFE) -#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \ - for ((var) = TAILQ_FIRST((head)); \ - (var) && ((tvar) = TAILQ_NEXT((var), field), 1); \ - (var) = (tvar)) -#endif - -#if !defined(TAILQ_INIT) -#define TAILQ_INIT(head) do { \ - TAILQ_FIRST((head)) = NULL; \ - (head)->tqh_last = &TAILQ_FIRST((head)); \ -} while (0) -#endif - -#if !defined(TAILQ_INSERT_TAIL) -#define TAILQ_INSERT_TAIL(head, elm, field) do { \ - TAILQ_NEXT((elm), field) = NULL; \ - (elm)->field.tqe_prev = (head)->tqh_last; \ - *(head)->tqh_last = (elm); \ - (head)->tqh_last = &TAILQ_NEXT((elm), field); \ -} while (0) -#endif - -#if !defined(TAILQ_NEXT) -#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) -#endif - -#if !defined(TAILQ_REMOVE) -#define TAILQ_REMOVE(head, elm, field) do { \ - if ((TAILQ_NEXT((elm), field)) != NULL) \ - TAILQ_NEXT((elm), field)->field.tqe_prev = \ - (elm)->field.tqe_prev; \ - else { \ - (head)->tqh_last = (elm)->field.tqe_prev; \ - } \ - *(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \ -} while (0) -#endif - -/* -------------------------------------------------------- - * Structure definitions - * -------------------------------------------------------- */ - -struct ini_private { - struct ini_section *current; /* current working section */ - int ignore; /* must ignore (no redefine) */ - FILE *fp; /* file pointer to read */ - - /* Line buffer */ - char *line; /* line data */ - int linesize; /* line allocated size */ - int lineno; /* number of line in file */ - - /* Error reporting */ - char error[1024]; -}; - -/* -------------------------------------------------------- - * Prototypes - * -------------------------------------------------------- */ - -#define F_VERBOSE(cg) ((cg)->flags & INI_VERBOSE) -#define F_NOREDEFINE(cg) ((cg)->flags & INI_NOREDEFINE) -#define F_FAILERROR(cg) ((cg)->flags & INI_FAILERROR) - -static char * -sstrndup(const char *src, size_t max) -{ - char *res; - size_t length; - - for (length = 0; length < max && src[length] != '\0'; ++length) - continue; - - if ((res = malloc(length + 1)) == NULL) - return NULL; - - memcpy(res, src, length); - res[length] = '\0'; - - return res; -} - -static void -sskip(char **lp) -{ - while (isspace (**lp) && **lp != '\0') - ++(*lp); -} - -static void -sseek(char **lp) -{ - while (!isspace(**lp) && **lp != '\0') - ++(*lp); -} - -static void -ini_set_error(struct ini_config *cg, const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - if (cg->pv->error) - vsnprintf(cg->pv->error, sizeof (cg->pv->error), fmt, ap); - va_end(ap); -} - -static void -ini_warn(struct ini_config *cg, const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - if (F_VERBOSE(cg)) { - vprintf(fmt, ap); - fputc('\n', stdout); - } - - if (F_FAILERROR(cg)) { - va_start(ap, fmt); - vsnprintf(cg->pv->error, sizeof (cg->pv->error), fmt, ap); - va_end(ap); - } - - va_end(ap); -} - -/* - * Add a new section, this function only returns -1 on fatal error that may - * be impossible to continue parsing for the current line. - */ - -static int -ini_add_section(struct ini_config *cg, char **lp) -{ - char *begin = *lp, *end; - size_t length; - struct ini_section *section = NULL; - - if (!(end = strchr(begin, ']'))) { - ini_warn(cg, "line %d: syntax error after [", cg->pv->lineno); - goto bad; - } - - length = end - begin; - - /* May not redefine? */ - if (cg->pv->current && F_NOREDEFINE(cg)) - if (strncmp(cg->pv->current->key, begin, length) == 0) { - ini_warn(cg, "line %d: redefining %s", cg->pv->lineno, - cg->pv->current->key); - goto bad; - } - - /* Allocate a new section and add it */ - if (!(section = calloc(1, sizeof (*section)))) - goto bad; - - if (!(section->key = sstrndup(begin, length))) - goto bad; - - TAILQ_INIT(§ion->options); - TAILQ_INSERT_TAIL(&cg->sections, section, link); - cg->pv->current = section; - cg->pv->ignore = 0; - - /* Trigger an event for the new section */ - if (cg->open) - cg->open(cg->data, section->key); - - *lp = &end[1]; - - return 0; - -bad: if (section) - free(section->key); - free(section); - - cg->pv->ignore = 1; - *lp = strchr(*lp, '\0'); - - return F_FAILERROR(cg) ? -1 : 0; -} - -/* - * Add a new option, the returns value is same as ini_add_section. - */ - -static int -ini_add_option(struct ini_config *cg, char **lp) -{ - char *begin = *lp, *equal, *end; - struct ini_option *option = NULL; - - if (!cg->pv->current) { - ini_warn(cg, "line %d: option within no section", cg->pv->lineno); - goto bad; - } - - if (cg->pv->ignore || - !(option = calloc(1, sizeof (*option)))) - goto bad; - - /* Not valid */ - if (!(equal = strchr(begin, '='))) { - ini_warn(cg, "line %d: missing =", cg->pv->lineno); - goto bad; - } - - /* End of option */ - end = begin; - sskip(&end); - sseek(&end); - - option->key = sstrndup(begin, end - begin); - - /* End of value */ - begin = &equal[1]; - sskip(&begin); - end = begin; - - if (*end == '\'' || *end == '"') { - for (++end; *end != *begin && *end != '\0'; ++end) - continue; - if (*end != *begin) { - ini_warn(cg, "line %d: missing %c", - cg->pv->lineno, *begin); - *lp = end; - goto bad; - } else - ++ begin; - } else - sseek(&end); - - option->value = sstrndup(begin, end - begin); - - if (!option->key || !option->value) { - ini_warn(cg, "line %d: syntax error", cg->pv->lineno); - goto bad; - } - - TAILQ_INSERT_TAIL(&cg->pv->current->options, option, link); - - /* Trigger an event for the new section */ - if (cg->get) - cg->get(cg->data, cg->pv->current->key, option); - - *lp = &end[1]; - - return 0; - -bad: if (option) { - free(option->key); - free(option->value); - } - free(option); - - *lp = strchr(*lp, '\0'); - - return F_FAILERROR(cg) ? -1 : 0; -} - -static int -ini_read_line(struct ini_config *cg) -{ - char *lp = cg->pv->line; - int rv; - - /* Ignore empty line */ - if (*lp == '\0' || *lp == '#' || *lp == ';') - return 0; - - while (*lp != '\0') { - sskip(&lp); - - if (*lp == '\0' || *lp == '#' || *lp == ';') - return 0; - - /* Begin of section */ - if (*lp == '[') { - ++ lp; - rv = ini_add_section(cg, &lp); - /* Begin of option */ - } else { - rv = ini_add_option(cg, &lp); - } - - if (rv < 0) - return -1; - } - - return 0; -} - -/* - * Read the next line until the next '\n' character is found. Returns 0 - * if the system had enough memory or -1 on allocation failure or on - * end of file. Only for mode == INI_LINEAR - */ - -static int -ini_get_line(struct ini_config *cg) -{ - int ch, pos; - - memset(cg->pv->line, 0, cg->pv->linesize); - pos = 0; - - while ((ch = fgetc(cg->pv->fp)) != '\n') { - if (feof(cg->pv->fp) || ferror(cg->pv->fp)) - return -1; - - /* End of buffer, realloc */ - if (pos == cg->pv->linesize) { - cg->pv->line = realloc(cg->pv->line, cg->pv->linesize + 512); - if (!cg->pv->line) - return -1; - - cg->pv->linesize += 512; - } - - cg->pv->line[pos++] = ch; - } - - return 0; -} - -static int -ini_open_file(struct ini_config *cg) -{ - if (!(cg->pv->fp = fopen(cg->path, "r"))) { - ini_set_error(cg, "open: %s", cg->path); - return -1; - } - - cg->pv->linesize = INI_DEFAULT_LINESIZE; - cg->pv->line = calloc(sizeof (char), cg->pv->linesize); - - if (!cg->pv->line) { - ini_set_error(cg, "malloc: %s", strerror(errno)); - return -1; - } - - return 0; -} - -/* -------------------------------------------------------- - * Public functions - * -------------------------------------------------------- */ - -struct ini_config * -ini_create(const char *path, enum ini_flags flags) -{ - struct ini_config *cg; - - cg = calloc(1, sizeof (*cg)); - if (!cg) - return NULL; - - cg->pv = calloc(1, sizeof (struct ini_private)); - if (!cg->pv) - return NULL; - - cg->path = path; - cg->flags = flags; - - return cg; -} - -void -ini_set_handlers(struct ini_config *cg, void *data, ini_open_t open, - ini_get_t get) -{ - if (!cg) - return; - - cg->data = data; - cg->open = open; - cg->get = get; -} - -int -ini_open(struct ini_config *cg) -{ - int rv = 0; - - /* Open the file and prepare data for reading */ - if (ini_open_file(cg) < 0) - return -1; - - cg->pv->ignore = 1; - cg->pv->lineno = 1; - - TAILQ_INIT(&cg->sections); - - while (ini_get_line(cg) != -1 && !rv) { - rv = ini_read_line(cg); - ++ cg->pv->lineno; - } - - fclose(cg->pv->fp); - - return rv; -} - -/* - * Search the section `sectname' in the config structure. If the section - * is not found, this function returns NULL. - */ - -struct ini_section * -ini_select_section(const struct ini_config *cg, const char *sectname) -{ - struct ini_section *s; - - TAILQ_FOREACH(s, &cg->sections, link) - if (strcmp(s->key, sectname) == 0) - return s; - - return NULL; -} - -/* - * Search the option `optname' in the section structure, argument - * section mustn't be NULL. If the option is not found, this function - * returns NULL. - */ - -struct ini_option * -ini_select_option(const struct ini_section *sc, const char *name) -{ - struct ini_option *o; - - TAILQ_FOREACH(o, &sc->options, link) - if (strcmp(o->key, name) == 0) - return o; - - return NULL; -} - -/* - * Find an option from the config, by section and option names. - * Returns the option or NULL if not found. - */ - -struct ini_option * -ini_find(const struct ini_config *cg, const char *scname, const char *optname) -{ - struct ini_section *sc; - - if ((sc = ini_select_section(cg, scname))) - return ini_select_option(sc, optname); - - return NULL; -} - -/* - * Return the last error or "No error" if there is no error. - */ - -const char * -ini_get_error(const struct ini_config *cg) -{ - if (!cg && errno != 0) - return strerror(errno); - - if (cg->pv->error[0] == '\0') { - if (errno != 0) - return strerror(errno); - - return "No error"; - } - - return cg->pv->error; -} - -/* - * Free everything, level may be set like this: - * 0, only free parser and private resources. - * 1, free all sections and their keys, - * 2, free all sections and options keys and values. - */ - -void -ini_free(struct ini_config *cg, int level) -{ - struct ini_section *s, *stmp; - struct ini_option *o, *otmp; - - if (level >= 1) { - TAILQ_FOREACH_SAFE(s, &cg->sections, link, stmp) { - if (level >= 2) { - TAILQ_FOREACH_SAFE(o, &s->options, link, otmp) { - TAILQ_REMOVE(&s->options, o, link); - free(o->key); - free(o->value); - free(o); - } - } - - TAILQ_REMOVE(&cg->sections, s, link); - free(s->key); - free(s); - } - } - - if (level >= 0) { - free(cg->pv->line); - free(cg->pv); - free(cg); - } -} diff -r d263f85f43a4 -r 5f75779cc7eb C/ini.h --- a/C/ini.h Wed Nov 27 10:25:58 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,131 +0,0 @@ -/* - * ini.h -- parse .ini like files - * - * Copyright (c) 2011, 2012, David Demelier - * - * Permission to use, copy, modify, and/or 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. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef _INI_H_ -#define _INI_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#if !defined(INI_DEFAULT_LINESIZE) -# define INI_DEFAULT_LINESIZE 1024 -#endif - -/* - * sys/queue.h bits. - */ - -#if !defined(TAILQ_ENTRY) -#define TAILQ_ENTRY(type) \ -struct { \ - struct type *tqe_next; /* next element */ \ - struct type **tqe_prev; /* address of previous next element */ \ -} -#endif - -#if !defined(TAILQ_HEAD) -#define TAILQ_HEAD(name, type) \ -struct name { \ - struct type *tqh_first; /* first element */ \ - struct type **tqh_last; /* addr of last next element */ \ -} -#endif - -enum ini_flags { - INI_VERBOSE = (1 << 0), /* be verbose */ - INI_NOREDEFINE = (1 << 1), /* do not allow redefinitions */ - INI_FAILERROR = (1 << 2) /* abort parsing on first error */ -}; - -typedef struct ini_config ini_config_t; -typedef struct ini_section ini_section_t; -typedef struct ini_option ini_option_t; -typedef struct ini_handler ini_handler_t; - -typedef void (*ini_open_t)(void *, const char *); -typedef void (*ini_get_t)(void *, const char *, const ini_option_t *); - -/* -------------------------------------------------------- - * Structure definitions - * -------------------------------------------------------- */ - -struct ini_private; - -struct ini_config { - const char *path; /* (ro) file path */ - enum ini_flags flags; /* (ro) optional flags */ - void *data; /* (rw) user data */ - - TAILQ_HEAD(, ini_section) sections; /* (ro) linked-list of sections */ - - /* Event driven method */ - void (*open)(void *, const char *); - void (*get)(void *, const char *, const struct ini_option *); - - /* Private data */ - struct ini_private *pv; -}; - -struct ini_option { - char *key; /* (rw) option name */ - char *value; /* (rw) option value */ - - TAILQ_ENTRY(ini_option) link; -}; - -struct ini_section { - char *key; /* (rw) section key */ - TAILQ_HEAD(, ini_option) options; /* (rw) list of options */ - - TAILQ_ENTRY(ini_section) link; -}; - -/* -------------------------------------------------------- - * Main functions - * -------------------------------------------------------- */ - -struct ini_config * -ini_create(const char *, enum ini_flags); - -void -ini_set_handlers(struct ini_config *, void *, ini_open_t, ini_get_t); - -int -ini_open(struct ini_config *); - -struct ini_section * -ini_select_section(const struct ini_config *, const char *); - -struct ini_option * -ini_select_option(const struct ini_section *, const char *); - -struct ini_option * -ini_find(const struct ini_config *, const char *, const char *); - -const char * -ini_get_error(const struct ini_config *); - -void -ini_free(struct ini_config *, int); - -#ifdef __cplusplus -} -#endif - -#endif /* _INI_H_ */ diff -r d263f85f43a4 -r 5f75779cc7eb C/nsock.c --- a/C/nsock.c Wed Nov 27 10:25:58 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,661 +0,0 @@ -/* - * nsock.c -- portable BSD sockets wrapper - * - * Copyright (c) 2013 David Demelier - * - * Permission to use, copy, modify, and/or 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. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -# include -# include - -#if defined(_WIN32) - - typedef SOCKET nsock_socket_t; - typedef const char * nsock_carg_t; - typedef char * nsock_arg_t; - -#else -# include -# include - -# define ioctlsocket(s) ioctl(s) -# define closesocket(s) close(s) - -# define gai_strerrorA gai_strerror - -# define INVALID_SOCKET -1 -# define SOCKET_ERROR -1 - - typedef int nsock_socket_t; - typedef const void * nsock_carg_t; - typedef void * nsock_arg_t; - -#endif - -#include "nsock.h" - -#define TAILQ_HEAD(name, type) \ -struct name { \ - struct type *tqh_first; /* first element */ \ - struct type **tqh_last; /* addr of last next element */ \ - size_t noclients; \ -} - -#define TAILQ_ENTRY(type) \ -struct { \ - struct type *tqe_next; /* next element */ \ - struct type **tqe_prev; /* address of previous next element */ \ -} - -#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL) - -#define TAILQ_FIRST(head) ((head)->tqh_first) - -#define TAILQ_FOREACH(var, head, field) \ - for ((var) = TAILQ_FIRST((head)); \ - (var); \ - (var) = TAILQ_NEXT((var), field)) - -#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \ - for ((var) = TAILQ_FIRST((head)); \ - (var) && ((tvar) = TAILQ_NEXT((var), field), 1); \ - (var) = (tvar)) - -#define TAILQ_INIT(head) do { \ - TAILQ_FIRST((head)) = NULL; \ - (head)->tqh_last = &TAILQ_FIRST((head)); \ -} while (0) - -#define TAILQ_INSERT_HEAD(head, elm, field) do { \ - if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL) \ - TAILQ_FIRST((head))->field.tqe_prev = \ - &TAILQ_NEXT((elm), field); \ - else \ - (head)->tqh_last = &TAILQ_NEXT((elm), field); \ - TAILQ_FIRST((head)) = (elm); \ - (elm)->field.tqe_prev = &TAILQ_FIRST((head)); \ - (head)->noclients ++; \ -} while (0) - -#define TAILQ_INSERT_TAIL(head, elm, field) do { \ - TAILQ_NEXT((elm), field) = NULL; \ - (elm)->field.tqe_prev = (head)->tqh_last; \ - *(head)->tqh_last = (elm); \ - (head)->tqh_last = &TAILQ_NEXT((elm), field); \ - (head)->noclients ++; \ -} while (0) - -#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) - -#define TAILQ_REMOVE(head, elm, field) do { \ - if ((TAILQ_NEXT((elm), field)) != NULL) \ - TAILQ_NEXT((elm), field)->field.tqe_prev = \ - (elm)->field.tqe_prev; \ - else { \ - (head)->tqh_last = (elm)->field.tqe_prev; \ - } \ - *(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \ - (head)->noclients --; \ -} while (0) - -struct nsock { - nsock_socket_t fd; - char error[128]; -}; - -struct nsock_address { - struct sockaddr_storage addr; - socklen_t addrlen; - char error[128]; -}; - -struct nsock_listener { - const struct nsock *sock; - char error[128]; - TAILQ_HEAD(, nsock_clt) head; -}; - -struct nsock_clt { - const struct nsock *sock; - TAILQ_ENTRY(nsock_clt) link; -}; - -/* -------------------------------------------------------- - * Private helpers - * -------------------------------------------------------- */ - -static void -nsock_set_error(char *buffer, size_t bufsize) -{ - memset(buffer, 0, bufsize); - -#if defined(_WIN32) - LPSTR str; - - FormatMessageA( - FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, - NULL, - WSAGetLastError(), - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPSTR)&str, 0, NULL); - - if (str) { - strncpy(buffer, str, bufsize); - LocalFree(str); - } -#else - strncpy(buffer, strerror(errno), bufsize); -#endif -} - -static void -nsock_set_errno(char *buffer, size_t bufsize, int no) -{ - memset(buffer, 0, bufsize); - strncpy(buffer, strerror(no), bufsize - 1); -} - -static struct nsock_clt * -nsock_clt_new(const struct nsock *ns) -{ - struct nsock_clt *clt; - - if ((clt = malloc(sizeof (struct nsock_clt))) == NULL) - return NULL; - - clt->sock = ns; - - return clt; -} - -/* -------------------------------------------------------- - * Sockets functions - * -------------------------------------------------------- */ - -void -nsock_init(void) -{ -#if defined(_WIN32) - WSADATA wsa; - WSAStartup(MAKEWORD(2, 2), &wsa); -#endif -} - -struct nsock * -nsock_new(void) -{ - struct nsock *ns; - - if ((ns = malloc(sizeof (struct nsock))) == NULL) - return NULL; - - return ns; -} - -int -nsock_create(struct nsock *ns, int domain, int type, int protocol) -{ - ns->fd = socket(domain, type, protocol); - - if (ns->fd == INVALID_SOCKET) - nsock_set_error(ns->error, sizeof (ns->error)); - - return ns->fd == INVALID_SOCKET ? -1 : 0; -} - -const char * -nsock_error(struct nsock *ns) -{ - if (ns == NULL) - return strerror(ENOMEM); - - return ns->error; -} - -int -nsock_bind(struct nsock *ns, const struct nsock_address *ep) -{ - int ret; - - ret = bind(ns->fd, (const struct sockaddr *)&ep->addr, ep->addrlen); - - if (ret == SOCKET_ERROR) - nsock_set_error(ns->error, sizeof (ns->error)); - - return ret == SOCKET_ERROR ? -1 : 0; -} - -int -nsock_listen(struct nsock *ns, int max) -{ - int ret; - - ret = listen(ns->fd, max); - - if (ret == SOCKET_ERROR) - nsock_set_error(ns->error, sizeof (ns->error)); - - return ret == SOCKET_ERROR ? -1 : 0; -} - -int -nsock_accept(struct nsock *ns, struct nsock **client, struct nsock_address **clientinfo) -{ - struct sockaddr_storage *st = NULL; - socklen_t *len = NULL; - int ret; - - if ((*client = malloc(sizeof (struct nsock))) == NULL) { - nsock_set_errno(ns->error, sizeof (ns->error), ENOMEM); - return -1; - } - - if (clientinfo != NULL) { - if ((*clientinfo = malloc(sizeof (struct nsock_address))) == NULL) { - free(client); - nsock_set_errno(ns->error, sizeof (ns->error), ENOMEM); - return -1; - } - - st = &(*clientinfo)->addr; - len = &(*clientinfo)->addrlen; - - /* Set the addrlen to sockaddr_storage first */ - *len = sizeof (struct sockaddr_storage); - } - - /* Prepare client */ - memset((*client)->error, 0, sizeof ((*client)->error)); - (*client)->fd = accept(ns->fd, (struct sockaddr *)st, len); - - if ((*client)->fd == INVALID_SOCKET) { - nsock_set_error(ns->error, sizeof (ns->error)); - - /* free clients and set to NULL so user will not use it */ - free(*client); - *client = NULL; - - if (clientinfo != NULL) { - free(*clientinfo); - *clientinfo = NULL; - } - - ret = -1; - } else - ret = 0; - - return ret; -} - -int -nsock_connect(struct nsock *ns, const struct nsock_address *ep) -{ - int ret; - - ret = connect(ns->fd, (const struct sockaddr *)&ep->addr, ep->addrlen); - - if (ret == SOCKET_ERROR) - nsock_set_error(ns->error, sizeof (ns->error)); - - return ret == SOCKET_ERROR ? -1 : 0; -} - -int -nsock_set(struct nsock *ns, int level, int name, const void *arg, unsigned arglen) -{ - int ret; - - ret = setsockopt(ns->fd, level, name, (nsock_carg_t)arg, arglen); - - if (ret == SOCKET_ERROR) - nsock_set_error(ns->error, sizeof (ns->error)); - - return ret == SOCKET_ERROR ? -1 : 0; -} - -long -nsock_recv(struct nsock *ns, void *data, size_t datasz, int flags) -{ - long nbread; - - nbread = recv(ns->fd, data, datasz, flags); - - if (nbread == -1) - nsock_set_error(ns->error, sizeof (ns->error)); - - return nbread; -} - -long -nsock_recvfrom(struct nsock *ns, struct nsock_address *ep, void *data, size_t datasz, int flags) -{ - struct sockaddr_storage *st = NULL; - socklen_t *len = NULL; - long nbread; - - if (ep != NULL) { - st = &ep->addr; - len = &ep->addrlen; - - /* Set the addrlen to sockaddr_storage first */ - *len = sizeof (struct sockaddr_storage); - } - - nbread = recvfrom(ns->fd, data, datasz, flags, - (struct sockaddr *)st, len); - - if (nbread == SOCKET_ERROR) - nsock_set_error(ns->error, sizeof (ns->error)); - - return nbread; -} - -long -nsock_send(struct nsock *ns, const void *data, size_t datasz, int flags) -{ - long nbsent; - - nbsent = send(ns->fd, data, datasz, flags); - - if (nbsent == -1) - nsock_set_error(ns->error, sizeof (ns->error)); - - return nbsent; -} - -long -nsock_sendto(struct nsock *ns, const struct nsock_address *ep, const void *data, size_t datasz, int flags) -{ - long nbsent; - - nbsent = sendto(ns->fd, data, datasz, flags, - (const struct sockaddr *)&ep->addr, ep->addrlen); - - if (nbsent == SOCKET_ERROR) - nsock_set_error(ns->error, sizeof (ns->error)); - - return nbsent; -} - -void -nsock_close(struct nsock *ns) -{ - closesocket(ns->fd); -} - -void -nsock_free(struct nsock *ns) -{ - free(ns); -} - -void -nsock_finish(void) -{ -#if defined(_WIN32) - WSACleanup(); -#endif -} - -/* -------------------------------------------------------- - * End point functions - * -------------------------------------------------------- */ - -struct nsock_address * -nsock_addr_new(void) -{ - struct nsock_address *ep; - - if ((ep = calloc(1, sizeof (struct nsock_address))) == NULL) - return NULL; - - return ep; -} - -const char * -nsock_addr_error(struct nsock_address *ep) -{ - if (ep == NULL) - return strerror(ENOMEM); - - return ep->error; -} - -int -nsock_addr_bind_ip(struct nsock_address *ep, const char *iface, unsigned port, int family) -{ - if (family == AF_INET6) { - struct sockaddr_in6 *ptr = (struct sockaddr_in6 *)&ep->addr; - - memset(ptr, 0, sizeof (struct sockaddr_in6)); - ptr->sin6_family = AF_INET6; - ptr->sin6_port = htons(port); - - if (iface == NULL || strcmp(iface, "*") == 0) - ptr->sin6_addr = in6addr_any; - else if (inet_pton(AF_INET6, iface, &ptr->sin6_addr) <= 0) { - nsock_set_error(ep->error, sizeof (ep->error)); - return -1; - } - - ep->addrlen = sizeof (struct sockaddr_in6); - } else { - struct sockaddr_in *ptr = (struct sockaddr_in *)&ep->addr; - - memset(ptr, 0, sizeof (struct sockaddr_in)); - ptr->sin_family = AF_INET; - ptr->sin_port = htons(port); - - if (iface == NULL || strcmp(iface, "*") == 0) - ptr->sin_addr.s_addr = INADDR_ANY; - else if (inet_pton(AF_INET, iface, &ptr->sin_addr) <= 0) { - nsock_set_error(ep->error, sizeof (ep->error)); - return -1; - } - - ep->addrlen = sizeof (struct sockaddr_in); - } - - return 0; -} - -int -nsock_addr_connect_ip(struct nsock_address *ep, const char *host, unsigned port, int family) -{ - struct addrinfo hints, *res; - char portstr[32]; - int error; - - memset(&hints, 0, sizeof (hints)); - hints.ai_family = family; - hints.ai_socktype = SOCK_STREAM; - - memset(portstr, 0, sizeof (portstr)); - sprintf(portstr, "%u", port); - - error = getaddrinfo(host, portstr, &hints, &res); - if (error) { - memset(ep->error, 0, sizeof (ep->error)); - strncpy(ep->error, gai_strerrorA(error), sizeof (ep->error) - 1); - return -1; - } - - memcpy(&ep->addr, res->ai_addr, res->ai_addrlen); - ep->addrlen = res->ai_addrlen; - - freeaddrinfo(res); - - return 0; -} - -#if !defined(_WIN32) - -void -nsock_addr_unix(struct nsock_address *ep, const char *path) -{ - struct sockaddr_un *ptr= (struct sockaddr_un *)&ep->addr; - - /* Path */ - memset(ptr, 0, sizeof (struct sockaddr_un)); - strncpy(ptr->sun_path, path, sizeof (ptr->sun_path) - 1); - ptr->sun_family = AF_UNIX; - - /* Len is computed with SUN_LEN */ - ep->addrlen = SUN_LEN(ptr); -} - -#endif - -struct sockaddr * -nsock_addr_getaddr(struct nsock_address *ep) -{ - return (struct sockaddr *)&ep->addr; -} - -socklen_t -nsock_addr_getaddrlen(const struct nsock_address *ep) -{ - return ep->addrlen; -} - -void -nsock_addr_free(struct nsock_address *ep) -{ - free(ep); -} - -/* -------------------------------------------------------- - * listener functions - * -------------------------------------------------------- */ - -struct nsock_listener * -nsock_lst_new(const struct nsock *ns) -{ - struct nsock_listener *ls; - - if ((ls = malloc(sizeof (struct nsock_listener))) == NULL) - return NULL; - - ls->sock = ns; - TAILQ_INIT(&ls->head); - - return ls; -} - -const char * -nsock_lst_error(struct nsock_listener *ls) -{ - if (ls == NULL) - return strerror(ENOMEM); - - return ls->error; -} - -int -nsock_lst_push(struct nsock_listener *ls, struct nsock *ns) -{ - struct nsock_clt *clt; - - if ((clt = nsock_clt_new(ns)) == NULL) - return -1; - - TAILQ_INSERT_HEAD(&ls->head, clt, link); - - return 0; -} - -int -nsock_lst_append(struct nsock_listener *ls, struct nsock *ns) -{ - struct nsock_clt *clt; - - if ((clt = nsock_clt_new(ns)) == NULL) - return -1; - - TAILQ_INSERT_TAIL(&ls->head, clt, link); - - return 0; -} - -size_t -nsock_lst_count(const struct nsock_listener *ls) -{ - return ls->head.noclients; -} - -void -nsock_lst_remove(struct nsock_listener *ls, const struct nsock *ns) -{ - struct nsock_clt *clt, *tmp; - - TAILQ_FOREACH_SAFE(clt, &ls->head, link, tmp) { - if (clt->sock == ns) { - TAILQ_REMOVE(&ls->head, clt, link); - free(clt); - break; - } - } -} - -struct nsock * -nsock_lst_select(struct nsock_listener *ls, long sec, long usec) -{ - fd_set fds; - struct timeval maxwait, *towait; - int error; - int fdmax; - struct nsock_clt *clt; - - fdmax = TAILQ_FIRST(&ls->head)->sock->fd; - - FD_ZERO(&fds); - TAILQ_FOREACH(clt, &ls->head, link) { - FD_SET(clt->sock->fd, &fds); - if ((int)clt->sock->fd > fdmax) - fdmax = clt->sock->fd; - } - - maxwait.tv_sec = sec; - maxwait.tv_usec = usec; - - // Set to NULL for infinite timeout. - towait = (sec == 0 && usec == 0) ? NULL : &maxwait; - error = select(fdmax + 1, &fds, NULL, NULL, towait); - - TAILQ_FOREACH(clt, &ls->head, link) - if (FD_ISSET(clt->sock->fd, &fds)) - return (struct nsock *)clt->sock; - - return NULL; -} - -void -nsock_lst_map(struct nsock_listener *ls, nsock_lst_map_t map, void *data) -{ - const struct nsock_clt *clt; - - TAILQ_FOREACH(clt, &ls->head, link) - map(clt->sock, data); -} - -void -nsock_lst_free(struct nsock_listener *ls) -{ - struct nsock_clt *clt, *tmp; - - TAILQ_FOREACH_SAFE(clt, &ls->head, link, tmp) - free(clt); - - free(ls); -} diff -r d263f85f43a4 -r 5f75779cc7eb C/nsock.h --- a/C/nsock.h Wed Nov 27 10:25:58 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,161 +0,0 @@ -/* - * nsock.h -- portable BSD sockets wrapper - * - * Copyright (c) 2013 David Demelier - * - * Permission to use, copy, modify, and/or 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. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef _NSOCK_H_ -#define _NSOCK_H_ - -#if !defined(NSOCK_NOINCLUDES) -# if defined(_WIN32) -# include -# include -# else -# include -# include -# include - -# include - -# include - -# include -# include -# endif -#endif - -struct nsock; -struct nsock_address; -struct nsock_listener; - -/* -------------------------------------------------------- - * Sockets functions - * -------------------------------------------------------- */ - -void -nsock_init(void); - -struct nsock * -nsock_new(void); - -int -nsock_create(struct nsock *, int, int, int); - -const char * -nsock_error(struct nsock *); - -int -nsock_bind(struct nsock *, const struct nsock_address *); - -int -nsock_listen(struct nsock *, int); - -int -nsock_accept(struct nsock *, struct nsock **, struct nsock_address **); - -int -nsock_connect(struct nsock *, const struct nsock_address *); - -int -nsock_set(struct nsock *, int, int, const void *, unsigned); - -long -nsock_recv(struct nsock *, void *, size_t, int); - -long -nsock_recvfrom(struct nsock *, struct nsock_address *, void *, size_t, int); - -long -nsock_send(struct nsock *, const void *, size_t, int); - -long -nsock_sendto(struct nsock *, const struct nsock_address *, const void *, size_t, int); - -void -nsock_close(struct nsock *); - -void -nsock_free(struct nsock *); - -void -nsock_finish(void); - -/* -------------------------------------------------------- - * End point functions - * -------------------------------------------------------- */ - -struct nsock_address * -nsock_addr_new(void); - -const char * -nsock_addr_error(struct nsock_address *); - -int -nsock_addr_bind_ip(struct nsock_address *, const char *, unsigned, int); - -int -nsock_addr_connect_ip(struct nsock_address *, const char *, unsigned, int); - -#if !defined(_WIN32) - -void -nsock_addr_unix(struct nsock_address *, const char *); - -#endif - -struct sockaddr * -nsock_addr_getaddr(struct nsock_address *); - -socklen_t -nsock_addr_getaddrlen(const struct nsock_address *); - -void -nsock_addr_free(struct nsock_address *); - -/* -------------------------------------------------------- - * listener functions - * -------------------------------------------------------- */ - -typedef void (*nsock_lst_map_t)(const struct nsock *, void *); - -struct nsock_listener * -nsock_lst_new(const struct nsock *); - -const char * -nsock_lst_error(struct nsock_listener *); - -int -nsock_lst_push(struct nsock_listener *, struct nsock *); - -int -nsock_lst_append(struct nsock_listener *, struct nsock *); - -size_t -nsock_lst_count(const struct nsock_listener *); - -void -nsock_lst_remove(struct nsock_listener *, const struct nsock *); - -struct nsock * -nsock_lst_select(struct nsock_listener *, long, long); - -void -nsock_lst_map(struct nsock_listener *, nsock_lst_map_t, void *); - -void -nsock_lst_free(struct nsock_listener *); - -#endif /* !_NSOCK_H_ */ diff -r d263f85f43a4 -r 5f75779cc7eb C/pack.c --- a/C/pack.c Wed Nov 27 10:25:58 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,477 +0,0 @@ -/* - * pack.c -- endian dependant binary file reader - * - * Copyright (c) 2011, 2012, David Demelier - * - * Permission to use, copy, modify, and/or 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. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include -#include -#include -#include - -#include "pack.h" - -/* Compilation tunables */ -#if !defined(PACK_CHKSIZE) -# define PACK_CHKSIZE (256) /* default chunk size */ -#endif - -/* Type */ -enum pack_type { - TYPE_FP, - TYPE_FIXEDBUF, - TYPE_AUTOBUF -}; - -struct pack_sc { - enum pack_type type; /* which kind of work */ - short endian; /* endian */ - - /* if TYPE_FP */ - FILE * fp; /* file to write */ - - /* else */ - char * buf; /* bytes converted */ - size_t size; /* current length */ - size_t allocated; /* allocated size */ - - /* for reading */ - unsigned int position; /* position where to read */ -}; - -struct pack_value { - /* for writing */ - int nelem; /* number of element */ - int size; /* size of elements */ - uint64_t value; /* direct value */ - char * array; /* array of values */ - - /* for reading */ - char * dst; /* destination */ -}; - -#define SC_SET(s, tp, ed, f, b, al) do { \ - memset((s), 0, sizeof (struct pack_sc)); \ - (s)->type = tp; \ - (s)->endian = ed; \ - (s)->fp = f; \ - (s)->buf = b; \ - (s)->allocated = al; \ -} while (/* CONSTCOND */ 0) - -#define TOKNARG(tok, nelem) do { \ - if (p[1] == '[') { \ - char *end; \ - \ - /* Can statically write the number, or pass it */ \ - if (p[2] != ']') { \ - nelem = (int)strtol(&p[2], &end, 10); \ - p = end; \ - } else { \ - nelem = va_arg(ap, int); \ - while (!isspace(*p) && *p != ']' && *p != '\0') \ - ++p; \ - } \ - } else \ - nelem = 1; \ -} while (/* CONSTCOND */ 0) - -#define TOKSIZE(tok, size) do { \ - switch (tok) { \ - case 'c': \ - size = sizeof (uint8_t); \ - break; \ - case 's': \ - size = sizeof (uint16_t); \ - break; \ - case 'i': \ - size = sizeof (uint32_t); \ - break; \ - case 'l': \ - size = sizeof (uint64_t); \ - break; \ - default: \ - size = 0; \ - break; \ - } \ -} while (/* CONSTCOND */ 0) - -#define TOKGETARG(serv, tok, val, ap) do { \ - if ((val)->nelem == 1 && serv == writeto) { \ - uint64_t item; \ - switch (tok) { \ - case 'c': case 's': case 'i': \ - item = va_arg(ap, int); \ - break; \ - case 'l': \ - item = va_arg(ap, uint64_t); \ - break; \ - default: \ - item = 0; \ - break; \ - } \ - \ - memset(&(val)->value, 0, sizeof (uint64_t)); \ - memcpy(&(val)->value, &item, (val)->size); \ - (val)->array = (char *)&(val)->value; \ - } else { /* read is always a pointer */ \ - (val)->array = va_arg(ap, void *); \ - (val)->dst = (val)->array; \ - } \ -} while (/* CONSTCOND */ 0) - -#define GETCONV(ed, size, conv) do { \ - if (ed != PACK_HOST_BYTEORDER) { \ - switch ((size)) { \ - case (sizeof (uint16_t)): \ - conv = conv16; break; \ - case (sizeof (uint32_t)): \ - conv = conv32; break; \ - case (sizeof (uint64_t)): \ - conv = conv64; break; \ - default: \ - conv = NULL; \ - } \ - } else \ - conv = NULL; \ -} while (/* CONSTCOND */ 0) - -static void -conv16(void *item) -{ - *(uint16_t *)item = pack_swap16(*(uint16_t *)item); -} - -static void -conv32(void *item) -{ - *(uint32_t *)item = pack_swap32(*(uint32_t *)item); -} - -static void -conv64(void *item) -{ - *(uint64_t *)item = pack_swap64(*(uint64_t *)item); -} - -/* - * Function that write content into the buffer or file depending - * on the calling function. Returns the number of bytes written - * or -1 on failure. - */ -static long -writeto(struct pack_sc *sc, struct pack_value *val) -{ - void (*conv)(void *); - int i; - uint64_t item; - long nbytes = 0; - - /* Get converter */ - GETCONV(sc->endian, val->size, conv); - - for (i = 0; i < val->nelem; ++i) { - item = 0; - memcpy(&item, &val->array[i * val->size], val->size); - - if (conv != NULL) - conv(&item); - - switch (sc->type) { - case TYPE_FP: - fwrite(&item, val->size, 1, sc->fp); - break; - case TYPE_AUTOBUF: - if (sc->size + val->size >= sc->allocated) { - sc->allocated += PACK_CHKSIZE; - sc->buf = realloc(sc->buf, sc->allocated); - - if (sc->buf == NULL) - return -1; - } - /* FALLTHROUGH */ - case TYPE_FIXEDBUF: - if (sc->size + val->size <= sc->allocated) { - memcpy(&sc->buf[sc->size], &item, val->size); - sc->size += val->size; - } else - continue; - default: - break; - } - - nbytes += val->size; - } - - return nbytes; -} - -/* - * Function that read the file or buffer and fill array. - */ -static long -readfrom(struct pack_sc *sc, struct pack_value *val) -{ - void (*conv)(void *); - int i, oktoread; - uint64_t item; - long nbytes = 0; - - /* Get converter */ - GETCONV(sc->endian, val->size, conv); - - for (i = 0; i < val->nelem; ++i) { - item = oktoread = 0; - - switch (sc->type) { - case TYPE_FP: - fread(&item, val->size, 1, sc->fp); - oktoread = 1; - break; - case TYPE_FIXEDBUF: - if (sc->position + val->size <= sc->allocated) { - memcpy(&item, &sc->buf[sc->position], val->size); - sc->position += val->size; - oktoread = 1; - } - break; - default: - break; - } - - if (conv != NULL) - conv(&item); - - if (oktoread) { - memcpy(&val->dst[i * val->size], &item, val->size); - nbytes += val->size; - } - } - - return nbytes; -} - -/* - * Function that analyses the format, write or read the values depending - * on the calling functions. - */ -static long -packit(struct pack_sc *sc, long (*func)(struct pack_sc *, struct pack_value *), - const char *fmt, va_list ap) -{ - struct pack_value val; - const char *p; - int tok; - long nbytes = 0, rv; - - for (p = fmt; *p != '\0'; ++p) { - tok = *p; - - if (isspace(*p)) - continue; - - TOKNARG(tok, val.nelem); - TOKSIZE(tok, val.size); - - if (val.size == 0 || val.nelem == 0) - continue; - - TOKGETARG(func, tok, &val, ap); - if ((rv = func(sc, &val)) == -1) - return -1; - - nbytes += rv; - } - - return nbytes; -} - -long -pack_write(short ed, const char *path, const char *fmt, ...) -{ - va_list ap; - long rv; - - va_start(ap, fmt); - rv = pack_vwrite(ed, path, fmt, ap); - va_end(ap); - - return rv; -} - -long -pack_vwrite(short ed, const char *path, const char *fmt, va_list ap) -{ - FILE *fp; - long rv; - - if ((fp = fopen(path, "wb")) == NULL) - return -1; - - rv = pack_vfwrite(ed, fp, fmt, ap); - fclose(fp); - - return rv; -} - -long -pack_fwrite(short ed, FILE *fp, const char *fmt, ...) -{ - va_list ap; - long rv; - - va_start(ap, fmt); - rv = pack_vfwrite(ed, fp, fmt, ap); - va_end(ap); - - return rv; -} - -long -pack_vfwrite(short ed, FILE *fp, const char *fmt, va_list ap) -{ - struct pack_sc sc; - - SC_SET(&sc, TYPE_FP, ed, fp, NULL, 0); - - return packit(&sc, writeto, fmt, ap); -} - -long -pack_swrite(short ed, char *buf, size_t max, const char *fmt, ...) -{ - va_list ap; - long rv; - - va_start(ap, fmt); - rv = pack_vswrite(ed, buf, max, fmt, ap); - va_end(ap); - - return rv; -} - -long -pack_vswrite(short ed, char *buf, size_t max, const char *fmt, va_list ap) -{ - struct pack_sc sc; - - SC_SET(&sc, TYPE_FIXEDBUF, ed, NULL, buf, max); - - return packit(&sc, writeto, fmt, ap); -} - -long -pack_aswrite(short ed, char **bufp, const char *fmt, ...) -{ - va_list ap; - long rv; - - va_start(ap, fmt); - rv = pack_vaswrite(ed, bufp, fmt, ap); - va_end(ap); - - return rv; -} - -long -pack_vaswrite(short ed, char **bufp, const char *fmt, va_list ap) -{ - struct pack_sc sc; - int rv; - - SC_SET(&sc, TYPE_AUTOBUF, ed, NULL, NULL, PACK_CHKSIZE); - - if ((sc.buf = malloc(PACK_CHKSIZE)) == NULL) - return -1; - - rv = packit(&sc, writeto, fmt, ap); - *bufp = sc.buf; - - return rv; -} - -long -pack_read(short ed, const char *path, const char *fmt, ...) -{ - va_list ap; - long rv; - - va_start(ap, fmt); - rv = pack_vread(ed, path, fmt, ap); - va_end(ap); - - return rv; -} - -long -pack_vread(short ed, const char *path, const char *fmt, va_list ap) -{ - FILE *fp; - long rv; - - if ((fp = fopen(path, "rb")) == NULL) - return -1; - - rv = pack_vfread(ed, fp, fmt, ap); - fclose(fp); - - return rv; -} - -long -pack_fread(short ed, FILE *fp, const char *fmt, ...) -{ - va_list ap; - long rv; - - va_start(ap, fmt); - rv = pack_vfread(ed, fp, fmt, ap); - va_end(ap); - - return rv; -} - -long -pack_vfread(short ed, FILE *fp, const char *fmt, va_list ap) -{ - struct pack_sc sc; - - SC_SET(&sc, TYPE_FP, ed, fp, NULL, 0); - - return packit(&sc, readfrom, fmt, ap); -} - -long -pack_sread(short ed, const char *buf, size_t max, const char *fmt, ...) -{ - va_list ap; - long rv; - - va_start(ap, fmt); - rv = pack_vsread(ed, buf, max, fmt, ap); - va_end(ap); - - return rv; -} - -long -pack_vsread(short ed, const char *buf, size_t max, const char *fmt, va_list ap) -{ - struct pack_sc sc; - - SC_SET(&sc, TYPE_FIXEDBUF, ed, NULL, (char *)buf, max); - - return packit(&sc, readfrom, fmt, ap); -} diff -r d263f85f43a4 -r 5f75779cc7eb C/pack.h --- a/C/pack.h Wed Nov 27 10:25:58 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,80 +0,0 @@ -/* - * pack.h -- endian dependant binary file reader - * - * Copyright (c) 2011, 2012, David Demelier - * - * Permission to use, copy, modify, and/or 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. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef _PACK_H_ -#define _PACK_H_ - -#include -#include - -#define PACK_LE 1234 -#define PACK_BE 4321 - -/* - * Endian detection based on SDL_endian.h - */ - -#undef PACK_HOST_BYTEORDER - -#if defined(__hppa__) || \ - defined(__m68k__) || defined(mc68000) || defined(_M_M68K) || \ - (defined(__MIPS__) && defined(__MISPEB__)) || \ - defined(__ppc__) || defined(__POWERPC__) || defined(_M_PPC) || \ - defined(__sparc__) -# define PACK_HOST_BYTEORDER PACK_BE -#else -# define PACK_HOST_BYTEORDER PACK_LE -#endif - -#define pack_swap16(x) \ - ((((x) >> 8) & 0x00FFL) | (((x) << 8) & 0xFF00L)) - -#define pack_swap32(x) ((((x) >> 24) & 0x000000FFL) \ - | (((x) >> 8) & 0x0000FF00L) \ - | (((x) << 8) & 0x00FF0000L) \ - | (((x) << 24) & 0xFF000000L)) - -#define pack_swap64(x) (((long) \ - ((int) pack_swap32((int) (((x) << 32) >> 32))) << 32) \ - | (int) pack_swap32((int) ((x) >> 32))) - -#ifdef __cplusplus -extern "C" { -#endif - -long pack_write(short, const char *, const char *, ...); -long pack_vwrite(short, const char *, const char *, va_list); -long pack_fwrite(short, FILE *, const char *, ...); -long pack_vfwrite(short, FILE *, const char *, va_list); -long pack_swrite(short, char *, size_t, const char *, ...); -long pack_vswrite(short, char *, size_t, const char *, va_list); -long pack_aswrite(short, char **, const char *, ...); -long pack_vaswrite(short, char **, const char *, va_list); - -long pack_read(short, const char *, const char *, ...); -long pack_vread(short, const char *, const char *, va_list); -long pack_fread(short, FILE *, const char *, ...); -long pack_vfread(short, FILE *, const char *, va_list); -long pack_sread(short, const char *, size_t, const char *, ...); -long pack_vsread(short, const char *, size_t, const char *, va_list); - -#ifdef __cplusplus -} -#endif - -#endif /* _PACK_H_ */ diff -r d263f85f43a4 -r 5f75779cc7eb C/parray.c --- a/C/parray.c Wed Nov 27 10:25:58 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,366 +0,0 @@ -/* - * parray.c -- manipulate dynamic pointer arrays - * - * Copyright (c) 2011, 2012, David Demelier - * - * Permission to use, copy, modify, and/or 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. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include -#include -#include - -#include "parray.h" - -#define LENGTH(x) ((x) * (sizeof (void *))) - -static int grow(struct parray *); - -int -parray_init(struct parray *arr) -{ - /* Set defaults if needed */ - arr->bsize = (arr->bsize <= 0) ? PARRAY_DEFAULT_BSIZE : arr->bsize; - arr->malloc = (arr->malloc == NULL) ? &malloc : arr->malloc; - arr->realloc = (arr->realloc == NULL) ? &realloc : arr->realloc; - - arr->bsize += (arr->flags & PARRAY_NULLEND) ? 1 : 0; - arr->size = LENGTH(arr->bsize); - - if ((arr->data = arr->malloc(arr->size)) == NULL) - return -1; - - memset(arr->data, 0, arr->size); - - return 0; -} - -/* - * Valid options that can be set for an array : - * l -> optional array block size of type int - * m -> malloc function that must matches void * (*malloc)(size_t) - * r -> realloc function that must matches void * (*realloc)(void *, size_t) - * f -> parray flags of type int - */ -void -parray_set(struct parray *arr, const char *fmt, ...) -{ - va_list ap; - const char *p; - - va_start(ap, fmt); - for (p = fmt; *p != '\0'; ++p) - switch (*p) { - case 'l': - arr->bsize = va_arg(ap, int); - break; - case 'm': - arr->malloc = va_arg(ap, void * (*)(size_t)); - break; - case 'r': - arr->realloc = va_arg(ap, void * (*)(void *, size_t)); - break; - case 'f': - arr->flags = va_arg(ap, int); - break; - default: - break; - } -} - -/* - * Add to the head of array. NOTE: this may be very slow when adding a lot - * of object (about 100000). If you need to add a lot of data please consider - * using linked list instead. Returns -1 on failure or 0 on success. - */ -int -parray_push(struct parray *arr, void *data) -{ - if (grow(arr) < 0) - return -1; - - memmove(&arr->data[1], &arr->data[0], LENGTH(arr->length++)); - arr->data[0] = data; - - if (arr->flags & PARRAY_NULLEND) - arr->data[arr->length] = NULL; - - return 0; -} - -/* - * Insert the data at the specified index. The function returns -1 on - * allocation failure or the position of the added element. - */ -int -parray_insert(struct parray *arr, void *data, int index) -{ - if (arr->flags & PARRAY_INSERTSAFE) - if (index < 0 || index > arr->length) - return -1; - - if (index < 0) - return parray_push(arr, data); - if (index >= arr->length) - return parray_append(arr, data); - - /* Good place */ - memmove(&arr->data[index + 1], &arr->data[index], - LENGTH(arr->length++ - index)); - arr->data[index] = data; - - if (arr->flags & PARRAY_NULLEND) - arr->data[arr->length] = NULL; - - return index; -} - -/* - * Append the data to the end of array. Returns -1 on failure or the position - * of the added element. - */ -int -parray_append(struct parray *arr, void *data) -{ - if (grow(arr) < 0) - return -1; - - arr->data[arr->length++] = data; - - if (arr->flags & PARRAY_NULLEND) - arr->data[arr->length] = NULL; - - return (arr->length - 1); -} - -/* - * Remove the array's head. - */ -void -parray_pop(struct parray *arr) -{ - parray_iremove(arr, 0); -} - -/* - * Remove the array's tail. - */ -void -parray_unqueue(struct parray *arr) -{ - parray_iremove(arr, arr->length - 1); -} - -/* - * Remove the data at the specified index. Bounds are checked. - */ -void -parray_iremove(struct parray *arr, int index) -{ - if (arr->length > 0 && index >= 0 && index < arr->length) { - if (arr->flags & PARRAY_FASTREMOVE) - arr->data[index] = arr->data[--arr->length]; - else - memmove(&arr->data[index], &arr->data[index + 1], - LENGTH(arr->length-- - index - 1)); - } - - arr->data[arr->length] = NULL; -} - -/* - * Remove the object referenced by the `data' argument. Useful when you - * don't know the index. - */ -void -parray_premove(struct parray *arr, const void *data) -{ - void *elm; - int i; - - PARRAY_FOREACH(arr, elm, i) { - if (elm == data) { - parray_iremove(arr, i); - break; - } - } -} - -/* - * Swap the two elements referenced by index `i1' and `i2'. This function needs - * to allocate data to swap elements thus if the functions fails it returns -1 - * otherwise 0 is returned. - */ -int -parray_iswap(struct parray *arr, int i1, int i2) -{ - void *tmp; - - /* Out of bounds */ - if (i1 >= arr->length || i1 < 0 || i2 >= arr->length || i2 < 0) - return -1; - - tmp = arr->data[i1]; - arr->data[i1] = arr->data[i2]; - arr->data[i2] = tmp; - - return 0; -} - -/* - * Swap the two elements referenced by data `o1' and `o2'. This function - * may be slow on large arrays since it must travel all the object - * to find the indexes. - */ -int -parray_pswap(struct parray *arr, const void *o1, const void *o2) -{ - int found, i1, i2; - - for (i1 = found = 0; !found && i1 < arr->length; ++i1) - found = arr->data[i1] == o1; - - if (!found) - return -1; - - for (i2 = found = 0; !found && i2 < arr->length; ++i2) - found = arr->data[i2] == o2; - - if (!found) - return -1; - - return parray_iswap(arr, --i1, --i2); -} - -/* - * Apply the function `fn' on each object and give the optional `udata' - * argument to the function too. - */ -void -parray_map(const struct parray *arr, parray_map_t fn, void *udata) -{ - int i; - - for (i = 0; i < arr->length; ++i) - fn(arr->data[i], udata); -} - -/* - * Compare each object with the user supplied function. If the `fn' function - * returns 1 then the index of the data position is returned and the parameter - * data points to the array data at the correct index. If the comparison - * function nevers returns 1, array_find returns -1. - */ -int -parray_find(const struct parray *arr, parray_cmp_t fn, void *ptr, void *u) -{ - int st, i; - - for (i = st = 0; i < arr->length && st != 1; ++i) - st = fn(arr->data[i], u); - - if (st && ptr) - *(void **)ptr = arr->data[i - 1]; - - return (st) ? i - 1 : -1; -} - -void * -parray_first(const struct parray *arr) -{ - return arr->data[0]; -} - -void * -parray_get(const struct parray *arr, int idx) -{ - if (idx < 0) - return parray_first(arr); - if (idx >= arr->length) - return parray_last(arr); - - return arr->data[idx]; -} - -void * -parray_last(const struct parray *arr) -{ - if (arr->length == 0) - return parray_first(arr); - - return arr->data[arr->length - 1]; -} - -/* - * Reset the array by setting each pointer to NULL and the length to 0. - */ -void -parray_clear(struct parray *arr) -{ - arr->data[0] = NULL; - arr->length = 0; -} - -/* - * Same as parray_clear except it also free the array object. - */ -void -parray_free(struct parray *arr) -{ - parray_clear(arr); - free(arr->data); - - arr->data = NULL; - arr->size = 0; -} - -/* - * Trim down the array to the correct size. - */ -void * -parray_trim(struct parray *arr) -{ - int count = arr->length; - - if (arr->flags & PARRAY_NULLEND) - ++ count; - - return arr->realloc(arr->data, count * sizeof (void *)); -} - -/* - * Increate the array storage when it is full. If the buffer is fixed size - * it returns -1 on full buffer otherwise 0 is returned if allocation - * succeeded. - */ -static int -grow(struct parray *arr) -{ - unsigned int toadd = (arr->flags & PARRAY_NULLEND) ? 2 : 1; - - if ((arr->size / sizeof (void *)) - arr->length >= toadd) - return 0; - - if (!(arr->flags & PARRAY_FIXED)) { - if ((arr->data = arr->realloc(arr->data, arr->size + - LENGTH(arr->bsize))) == NULL) { - arr->size = arr->length = 0; - return -1; - } - - arr->size += LENGTH(arr->bsize); - } else - return -1; - - return 0; -} diff -r d263f85f43a4 -r 5f75779cc7eb C/parray.h --- a/C/parray.h Wed Nov 27 10:25:58 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,121 +0,0 @@ -/* - * parray.h -- manipulate dynamic pointer arrays - * - * Copyright (c) 2011, 2012, David Demelier - * - * Permission to use, copy, modify, and/or 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. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef _PARRAY_H_ -#define _PARRAY_H_ - -#include - -#ifndef PARRAY_DEFAULT_BSIZE -#define PARRAY_DEFAULT_BSIZE 128 -#endif - -enum parray_flags { - PARRAY_AUTO = 0, /* array grows automatically */ - PARRAY_FIXED = (1 << 0), /* fixed size length */ - PARRAY_FASTREMOVE = (1 << 1), /* use last object when removing */ - PARRAY_NULLEND = (1 << 2), /* always has a NULL pointer at end */ - PARRAY_INSERTSAFE = (1 << 3) /* insertion must have valid indexes */ -}; - -struct parray { - enum parray_flags flags; /* (ro) array flags (default AUTO) */ - void **data; /* (rw) array of data */ - int length; /* (ro) number of element inside */ - size_t size; /* (ro) current buffer size (allocated memory) */ - int bsize; /* (rw) block size (used when growing array) */ - - /* Own allocation functions */ - void * (*malloc)(size_t); - void * (*realloc)(void *, size_t); -}; - -typedef void (*parray_map_t)(void *, void *); -typedef int (*parray_cmp_t)(void *, void *); - -#ifdef __cplusplus -extern "C" { -#endif - -int -parray_init(struct parray *); - -void -parray_set(struct parray *, const char *, ...); - -int -parray_push(struct parray *, void *); - -int -parray_insert(struct parray *, void *, int); - -int -parray_append(struct parray *, void *); - -void -parray_pop(struct parray *); - -void -parray_unqueue(struct parray *); - -void -parray_iremove(struct parray *, int); - -void -parray_premove(struct parray *, const void *); - -int -parray_iswap(struct parray *, int, int); - -int -parray_pswap(struct parray *, const void *, const void *); - -void -parray_map(const struct parray *, parray_map_t, void *); - -int -parray_find(const struct parray *, parray_cmp_t, void *, void *); - -void * -parray_first(const struct parray *); - -void * -parray_get(const struct parray *, int); - -void * -parray_last(const struct parray *); - -void -parray_clear(struct parray *); - -void -parray_free(struct parray *); - -void * -parray_trim(struct parray *); - -#define PARRAY_FOREACH(a, o, i) \ - for (i = 0, o = (a)->data[i]; \ - i < (a)->length; \ - ++i, o = (a)->data[i]) - -#ifdef __cplusplus -} -#endif - -#endif /* _PARRAY_H_ */