diff options
author | Stef Walter <stef@memberwebs.com> | 2007-04-27 03:19:46 +0000 |
---|---|---|
committer | Stef Walter <stef@memberwebs.com> | 2007-04-27 03:19:46 +0000 |
commit | 3d8ed01d2653c45e52821ba00ac72099a12600e1 (patch) | |
tree | ad13d6df465ef1a4f143109f04c35991ddb1efba /ckcapi-util.c |
Diffstat (limited to 'ckcapi-util.c')
-rw-r--r-- | ckcapi-util.c | 167 |
1 files changed, 167 insertions, 0 deletions
diff --git a/ckcapi-util.c b/ckcapi-util.c new file mode 100644 index 0000000..d8d182b --- /dev/null +++ b/ckcapi-util.c @@ -0,0 +1,167 @@ + +#include "cryptoki-capi-util.h" + +#include <string.h> + + + + + +#define MIN_ARRAY_SIZE 16 + +typedef struct _RealArray +{ + Array pub; + size_t alloc; + size_t elt_size; + int zero_terminated : 1; + int clear : 1; +} +RealArray; + +#define array_elt_len(array, i) ((array)->elt_size * (i)) +#define array_elt_pos(array, i) (((char*)(array)->pub.data) + array_elt_len((array),(i))) +#define array_elt_zero(array, pos, len) \ + (memset(array_elt_pos((array), pos), 0, array_elt_len((array), len))) +#define array_zero_terminate(array) \ + { if ((array)->zero_terminated) \ + array_elt_zero((array), (array)->pub.len, 1); } + +static unsigned int +nearest_pow(unsigned int num) +{ + unsigned int n = 1; + while(n < num) + n <<= 1; + return n; +} + +static int +maybe_expand(RealArray *array, size_t len) +{ + void* mem; + size_t want_alloc = array_elt_len(array, array->pub.len + len + + array->zero_terminated); + + if(want_alloc > array->alloc) + { + want_alloc = nearest_pow(want_alloc); + want_alloc = want_alloc > MIN_ARRAY_SIZE ? want_alloc : MIN_ARRAY_SIZE; + + mem = realloc(array->pub.data, want_alloc); + if(!mem) + return 0; + array->pub.data = mem; + + memset((char*)array->pub.data + array->alloc, 0, want_alloc - array->alloc); + array->alloc = want_alloc; + } + + return 1; +} + +Array* +ckcapi_util_array_new(int zero_terminated, int clear, size_t elt_size) +{ + return ckcapi_util_array_sized_new(zero_terminated, clear, elt_size, 0); +} + +Array* +ckcapi_util_array_sized_new(int zero_terminated, int clear, size_t elt_size, + size_t reserved_size) +{ + RealArray *array = malloc(sizeof(RealArray)); + if(!array) + return NULL; + + array->pub.data = NULL; + array->pub.len = 0; + array->alloc = 0; + array->zero_terminated = (zero_terminated ? 1 : 0); + array->clear = (clear ? 1 : 0); + array->elt_size = elt_size; + + if(array->zero_terminated || reserved_size != 0) + { + maybe_expand(array, reserved_size); + array_zero_terminate(array); + } + + return (Array*)array; +} + +void* +ckcapi_util_array_free(Array* array, int free_segment) +{ + void* segment; + + if(array == NULL) + return NULL; + + if(free_segment) + { + free(array->data); + segment = NULL; + } + else + segment = array->data; + + free(array); + return segment; +} + +int +ckcapi_util_array_append_vals(Array* parray, const void* data, size_t len) +{ + RealArray* array = (RealArray*)parray; + if(!maybe_expand(array, len)) + return 0; + + memcpy(array_elt_pos(array, array->pub.len), data, + array_elt_len(array, len)); + + array->pub.len += len; + array_zero_terminate(array); + + return 1; +} + +void +ckcapi_util_array_remove_index(Array* parray, unsigned int index) +{ + RealArray* array = (RealArray*)parray; + + if(index >= array->pub.len) + return; + + if(index != array->pub.len - 1) + memmove(array_elt_pos (array, index), + array_elt_pos (array, index + 1), + array_elt_len (array, array->pub.len - index - 1)); + + array->pub.len -= 1; + + array_elt_zero (array, array->pub.len, 1); +} + +void +ckcapi_util_array_remove_range(Array* parray, unsigned int index, size_t length) +{ + RealArray *array = (RealArray*)parray; + + if(index >= array->pub.len) + return; + if(index + length > array->pub.len); + length = array->pub.len - index; + if(length == 0) + return; + + if(index + length != array->pub.len) + memmove(array_elt_pos (array, index), + array_elt_pos (array, index + length), + (array->pub.len - (index + length)) * array->elt_size); + + array->pub.len -= length; + array_elt_zero(array, array->pub.len, length); +} + |