From a0d4750431b8b3328eb4b0d87c03f9d83a54812d Mon Sep 17 00:00:00 2001 From: skywind3000 Date: Wed, 11 Mar 2020 16:23:14 +0800 Subject: [PATCH 01/12] commit czmod --- czmod.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 czmod.c diff --git a/czmod.c b/czmod.c new file mode 100644 index 0000000..2cdfde9 --- /dev/null +++ b/czmod.c @@ -0,0 +1,88 @@ +#include +#include +#include +#include + +#include + +#include "imembase.c" + + +//---------------------------------------------------------------------- +// INLINE +//---------------------------------------------------------------------- +#ifndef INLINE +#if defined(__GNUC__) + +#if (__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 1)) +#define INLINE __inline__ __attribute__((always_inline)) +#else +#define INLINE __inline__ +#endif + +#elif (defined(_MSC_VER) || defined(__WATCOMC__)) +#define INLINE __inline +#else +#define INLINE +#endif +#endif + +#if (!defined(__cplusplus)) && (!defined(inline)) +#define inline INLINE +#endif + + +//--------------------------------------------------------------------- +// get environ +//--------------------------------------------------------------------- +static ib_string* os_getenv(const char *name) +{ + char *p = getenv(name); + if (p == NULL) { + return NULL; + } + ib_string *text = ib_string_new(); + ib_string_assign(text, p); + return text; +} + + +//--------------------------------------------------------------------- +// get data file +//--------------------------------------------------------------------- +static inline const char *get_data_file(void) +{ + static ib_string *text = NULL; + if (text != NULL) { + return text->ptr; + } + text = os_getenv("_ZL_DATA"); + if (text) { + return text->ptr; + } + text = os_getenv("HOME"); + if (text == NULL) { + text = os_getenv("USERPROFILE"); + } + if (text == NULL) { + return NULL; + } + ib_string_append(text, "/.zlua"); + return text->ptr; +} + +int main(int argc, char *argv[]) +{ + if (argc <= 1) { + printf("Hello, World !!\n"); + printf("data: %s\n", get_data_file()); + return 0; + } + if (strcmp(argv[1], "--add") == 0) { + if (argc >= 3) { + } + } + return 0; +} + + From ec123de01ae3d72b56434353c66ef965b25c083d Mon Sep 17 00:00:00 2001 From: skywind3000 Date: Thu, 12 Mar 2020 18:35:03 +0800 Subject: [PATCH 02/12] update --- czmod.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) diff --git a/czmod.c b/czmod.c index 2cdfde9..c100496 100644 --- a/czmod.c +++ b/czmod.c @@ -1,9 +1,20 @@ +//===================================================================== +// +// czmod.c - c module to boost z.lua +// +// Created by skywind on 2020/03/11 +// Last Modified: 2020/03/11 16:37:01 +// +//===================================================================== #include #include #include #include +#include +#ifdef __linux #include +#endif #include "imembase.c" @@ -32,6 +43,12 @@ #endif +//--------------------------------------------------------------------- +// internal functions +//--------------------------------------------------------------------- +static const char *get_data_file(void); + + //--------------------------------------------------------------------- // get environ //--------------------------------------------------------------------- @@ -50,7 +67,7 @@ static ib_string* os_getenv(const char *name) //--------------------------------------------------------------------- // get data file //--------------------------------------------------------------------- -static inline const char *get_data_file(void) +static const char *get_data_file(void) { static ib_string *text = NULL; if (text != NULL) { @@ -71,6 +88,38 @@ static inline const char *get_data_file(void) return text->ptr; } + +//--------------------------------------------------------------------- +// load file content +//--------------------------------------------------------------------- +ib_string *load_content(const char *filename) +{ + FILE *fp = fopen(filename, "r"); + if (fp == NULL) { + return NULL; + } + ib_string *text = ib_string_new(); + size_t block = 65536; + ib_string_resize(text, block); + size_t pos = 0; + while (feof(fp) == 0) { + size_t avail = text->size - pos; + if (avail < block) { + ib_string_resize(text, text->size + block); + avail = text->size - pos; + } + size_t hr = fread(&(text->ptr[pos]), 1, avail, fp); + pos += hr; + } + fclose(fp); + ib_string_resize(text, pos); + return text; +} + + +//--------------------------------------------------------------------- +// main entry +//--------------------------------------------------------------------- int main(int argc, char *argv[]) { if (argc <= 1) { From 168ec498494d7fc91fe4bac2caa234070e26445b Mon Sep 17 00:00:00 2001 From: skywind3000 Date: Mon, 16 Mar 2020 18:48:26 +0800 Subject: [PATCH 03/12] update --- czmod.c | 142 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 142 insertions(+) diff --git a/czmod.c b/czmod.c index c100496..b7a6fe5 100644 --- a/czmod.c +++ b/czmod.c @@ -117,6 +117,148 @@ ib_string *load_content(const char *filename) } +//--------------------------------------------------------------------- +// path item +//--------------------------------------------------------------------- +typedef struct +{ + ib_string *path; + int rank; + uint32_t timestamp; + uint64_t frecence; +} PathItem; + +static void item_delete(PathItem *item) +{ + if (item) { + if (item->path) { + ib_string_delete(item->path); + item->path = NULL; + } + ikmem_free(item); + } +}; + +PathItem* item_new(const char *path, int rank, uint32_t timestamp) +{ + PathItem* item = (PathItem*)ikmem_malloc(sizeof(PathItem)); + assert(item); + item->path = ib_string_new_from(path); + item->rank = rank; + item->timestamp = timestamp; + item->frecence = 0; + return item; +}; + +ib_array* ib_array_new_path(void) +{ + return ib_array_new((void (*)(void*))item_delete); +} + +int ib_string_find_size(const ib_string *str, const char *src, + int len, int start) +{ + char *text = str->ptr; + int pos = (start < 0)? 0 : start; + int endup = str->size - len; + char ch; + if (len <= 0) return pos; + for (ch = src[0]; pos <= endup; pos++) { + if (text[pos] == ch) { + if (memcmp(text + pos, src, len) == 0) + return pos; + } + } + return -1; +} + +int ib_string_find(const ib_string *str, const char *src, int start) +{ + return ib_string_find_size(str, src, (int)strlen(src), start); +} + +int ib_string_find_c(const ib_string *str, char ch, int start) +{ + const char *text = str->ptr; + int pos = (start < 0)? 0 : start; + int endup = str->size; + for (; pos < endup; pos++) { + if (text[pos] == ch) return pos; + } + return -1; +} + +ib_array* ib_string_split_size(const ib_string *str, const char *sep, + int len) +{ + if (len == 0) { + return NULL; + } + else { + ib_array *array = ib_array_new((void (*)(void*))ib_string_delete); + int start = 0; + while (0) { + int pos = ib_string_find_size(str, sep, len, start); + if (pos < 0) { + ib_string *newstr = ib_string_new(); + ib_string_assign_size(newstr, str->ptr + start, + str->size - start); + ib_array_push(array, newstr); + break; + } + else { + ib_string* newstr = ib_string_new(); + ib_string_assign_size(newstr, str->ptr + start, pos - start); + start = pos + len; + ib_array_push(array, newstr); + } + } + return array; + } +} + +ib_array* ib_string_split_c(const ib_string *str, char sep) +{ + if (str == NULL) { + return NULL; + } + else { + ib_array *array = ib_array_new((void (*)(void*))ib_string_delete); + int start = 0; + while (1) { + int pos = ib_string_find_c(str, sep, start); + if (pos < 0) { + ib_string *newstr = ib_string_new(); + ib_string_assign_size(newstr, str->ptr + start, + str->size - start); + ib_array_push(array, newstr); + break; + } + else { + ib_string *newstr = ib_string_new(); + ib_string_assign_size(newstr, str->ptr + start, pos - start); + start = pos + 1; + ib_array_push(array, newstr); + } + } + return array; + } +} + + +//--------------------------------------------------------------------- +// load data +//--------------------------------------------------------------------- +ib_array* data_load(const char *filename) +{ + ib_string *content = load_content(filename); + if (content == NULL) { + return NULL; + } + return NULL; +} + + //--------------------------------------------------------------------- // main entry //--------------------------------------------------------------------- From ebda4aa0613cf2092a1636dd2f7f10a3e01d9d90 Mon Sep 17 00:00:00 2001 From: skywind3000 Date: Mon, 16 Mar 2020 22:30:50 +0800 Subject: [PATCH 04/12] update module --- czmod.c => czmod/czmod.c | 90 -- czmod/imembase.c | 2325 ++++++++++++++++++++++++++++++++++++++ czmod/imembase.h | 916 +++++++++++++++ 3 files changed, 3241 insertions(+), 90 deletions(-) rename czmod.c => czmod/czmod.c (67%) create mode 100644 czmod/imembase.c create mode 100644 czmod/imembase.h diff --git a/czmod.c b/czmod/czmod.c similarity index 67% rename from czmod.c rename to czmod/czmod.c index b7a6fe5..6e10896 100644 --- a/czmod.c +++ b/czmod/czmod.c @@ -155,96 +155,6 @@ ib_array* ib_array_new_path(void) return ib_array_new((void (*)(void*))item_delete); } -int ib_string_find_size(const ib_string *str, const char *src, - int len, int start) -{ - char *text = str->ptr; - int pos = (start < 0)? 0 : start; - int endup = str->size - len; - char ch; - if (len <= 0) return pos; - for (ch = src[0]; pos <= endup; pos++) { - if (text[pos] == ch) { - if (memcmp(text + pos, src, len) == 0) - return pos; - } - } - return -1; -} - -int ib_string_find(const ib_string *str, const char *src, int start) -{ - return ib_string_find_size(str, src, (int)strlen(src), start); -} - -int ib_string_find_c(const ib_string *str, char ch, int start) -{ - const char *text = str->ptr; - int pos = (start < 0)? 0 : start; - int endup = str->size; - for (; pos < endup; pos++) { - if (text[pos] == ch) return pos; - } - return -1; -} - -ib_array* ib_string_split_size(const ib_string *str, const char *sep, - int len) -{ - if (len == 0) { - return NULL; - } - else { - ib_array *array = ib_array_new((void (*)(void*))ib_string_delete); - int start = 0; - while (0) { - int pos = ib_string_find_size(str, sep, len, start); - if (pos < 0) { - ib_string *newstr = ib_string_new(); - ib_string_assign_size(newstr, str->ptr + start, - str->size - start); - ib_array_push(array, newstr); - break; - } - else { - ib_string* newstr = ib_string_new(); - ib_string_assign_size(newstr, str->ptr + start, pos - start); - start = pos + len; - ib_array_push(array, newstr); - } - } - return array; - } -} - -ib_array* ib_string_split_c(const ib_string *str, char sep) -{ - if (str == NULL) { - return NULL; - } - else { - ib_array *array = ib_array_new((void (*)(void*))ib_string_delete); - int start = 0; - while (1) { - int pos = ib_string_find_c(str, sep, start); - if (pos < 0) { - ib_string *newstr = ib_string_new(); - ib_string_assign_size(newstr, str->ptr + start, - str->size - start); - ib_array_push(array, newstr); - break; - } - else { - ib_string *newstr = ib_string_new(); - ib_string_assign_size(newstr, str->ptr + start, pos - start); - start = pos + 1; - ib_array_push(array, newstr); - } - } - return array; - } -} - //--------------------------------------------------------------------- // load data diff --git a/czmod/imembase.c b/czmod/imembase.c new file mode 100644 index 0000000..182a115 --- /dev/null +++ b/czmod/imembase.c @@ -0,0 +1,2325 @@ +/********************************************************************** + * + * imembase.c - basic interface of memory operation + * skywind3000 (at) gmail.com, 2006-2016 + * + **********************************************************************/ + +#include "imembase.h" + +#include +#include +#include +#include + + +#if (defined(__BORLANDC__) || defined(__WATCOMC__)) +#if defined(_WIN32) || defined(WIN32) +#pragma warn -8002 +#pragma warn -8004 +#pragma warn -8008 +#pragma warn -8012 +#pragma warn -8027 +#pragma warn -8057 +#pragma warn -8066 +#endif +#endif + + +/*====================================================================*/ +/* IALLOCATOR */ +/*====================================================================*/ +void *(*__ihook_malloc)(size_t size) = NULL; +void (*__ihook_free)(void *) = NULL; +void *(*__ihook_realloc)(void *, size_t size) = NULL; + + +void* internal_malloc(struct IALLOCATOR *allocator, size_t size) +{ + if (allocator != NULL) { + return allocator->alloc(allocator, size); + } + if (__ihook_malloc != NULL) { + return __ihook_malloc(size); + } + return malloc(size); +} + +void internal_free(struct IALLOCATOR *allocator, void *ptr) +{ + if (allocator != NULL) { + allocator->free(allocator, ptr); + return; + } + if (__ihook_free != NULL) { + __ihook_free(ptr); + return; + } + free(ptr); +} + +void* internal_realloc(struct IALLOCATOR *allocator, void *ptr, size_t size) +{ + if (allocator != NULL) { + return allocator->realloc(allocator, ptr, size); + } + if (__ihook_realloc != NULL) { + return __ihook_realloc(ptr, size); + } + return realloc(ptr, size); +} + + +/*====================================================================*/ +/* IKMEM INTERFACE */ +/*====================================================================*/ +#ifndef IKMEM_ALLOCATOR +#define IKMEM_ALLOCATOR NULL +#endif + +struct IALLOCATOR *ikmem_allocator = IKMEM_ALLOCATOR; + + +void* ikmem_malloc(size_t size) +{ + return internal_malloc(ikmem_allocator, size); +} + +void* ikmem_realloc(void *ptr, size_t size) +{ + return internal_realloc(ikmem_allocator, ptr, size); +} + +void ikmem_free(void *ptr) +{ + internal_free(ikmem_allocator, ptr); +} + + +/*====================================================================*/ +/* IVECTOR */ +/*====================================================================*/ +void iv_init(struct IVECTOR *v, struct IALLOCATOR *allocator) +{ + if (v == 0) return; + v->data = 0; + v->size = 0; + v->capacity = 0; + v->allocator = allocator; +} + +void iv_destroy(struct IVECTOR *v) +{ + if (v == NULL) return; + if (v->data) { + internal_free(v->allocator, v->data); + } + v->data = NULL; + v->size = 0; + v->capacity = 0; +} + +int iv_capacity(struct IVECTOR *v, size_t newcap) +{ + if (newcap == v->capacity) + return 0; + if (newcap == 0) { + if (v->capacity > 0) { + internal_free(v->allocator, v->data); + } + v->data = NULL; + v->capacity = 0; + v->size = 0; + } + else { + unsigned char *ptr = (unsigned char*) + internal_malloc(v->allocator, newcap); + if (ptr == NULL) { + return -1; + } + if (v->data) { + size_t minsize = (v->size <= newcap)? v->size : newcap; + if (minsize > 0 && v->data) { + memcpy(ptr, v->data, minsize); + } + internal_free(v->allocator, v->data); + } + v->data = ptr; + v->capacity = newcap; + if (v->size > v->capacity) { + v->size = v->capacity; + } + } + return 0; +} + +int iv_resize(struct IVECTOR *v, size_t newsize) +{ + if (newsize > v->capacity) { + size_t capacity = v->capacity * 2; + if (capacity < newsize) { + capacity = sizeof(char*); + while (capacity < newsize) { + capacity = capacity * 2; + } + } + if (iv_capacity(v, capacity) != 0) { + return -1; + } + } + v->size = newsize; + return 0; +} + +int iv_reserve(struct IVECTOR *v, size_t size) +{ + return iv_capacity(v, (size >= v->size)? size : v->size); +} + +int iv_push(struct IVECTOR *v, const void *data, size_t size) +{ + size_t current = v->size; + if (iv_resize(v, current + size) != 0) + return -1; + if (data != NULL) + memcpy(v->data + current, data, size); + return 0; +} + +size_t iv_pop(struct IVECTOR *v, void *data, size_t size) +{ + size_t current = v->size; + if (size >= current) size = current; + if (data != NULL) + memcpy(data, v->data + current - size, size); + iv_resize(v, current - size); + return size; +} + +int iv_insert(struct IVECTOR *v, size_t pos, const void *data, size_t size) +{ + size_t current = v->size; + if (pos > current) + return -1; + if (iv_resize(v, current + size) != 0) + return -1; + if (pos < current) { + memmove(v->data + pos + size, v->data + pos, current - pos); + } + if (data != NULL) + memcpy(v->data + pos, data, size); + return 0; +} + +int iv_erase(struct IVECTOR *v, size_t pos, size_t size) +{ + size_t current = v->size; + if (pos >= current) return 0; + if (pos + size >= current) size = current - pos; + if (size == 0) return 0; + memmove(v->data + pos, v->data + pos + size, current - pos - size); + if (iv_resize(v, current - size) != 0) + return -1; + return 0; +} + + +/*====================================================================*/ +/* IMEMNODE */ +/*====================================================================*/ +void imnode_init(struct IMEMNODE *mn, ilong nodesize, struct IALLOCATOR *ac) +{ + struct IMEMNODE *mnode = mn; + + assert(mnode != NULL); + mnode->allocator = ac; + + iv_init(&mnode->vprev, ac); + iv_init(&mnode->vnext, ac); + iv_init(&mnode->vnode, ac); + iv_init(&mnode->vdata, ac); + iv_init(&mnode->vmem, ac); + iv_init(&mnode->vmode, ac); + + nodesize = IROUND_UP(nodesize, 8); + + mnode->node_size = nodesize; + mnode->node_free = 0; + mnode->node_used = 0; + mnode->node_max = 0; + mnode->mem_max = 0; + mnode->mem_count = 0; + mnode->list_open = -1; + mnode->list_close = -1; + mnode->total_mem = 0; + mnode->grow_limit = 0; + mnode->extra = NULL; +} + +void imnode_destroy(struct IMEMNODE *mnode) +{ + ilong i; + + assert(mnode != NULL); + if (mnode->mem_count > 0) { + for (i = 0; i < mnode->mem_count && mnode->mmem; i++) { + if (mnode->mmem[i]) { + internal_free(mnode->allocator, mnode->mmem[i]); + } + mnode->mmem[i] = NULL; + } + mnode->mem_count = 0; + mnode->mem_max = 0; + iv_destroy(&mnode->vmem); + mnode->mmem = NULL; + } + + iv_destroy(&mnode->vprev); + iv_destroy(&mnode->vnext); + iv_destroy(&mnode->vnode); + iv_destroy(&mnode->vdata); + iv_destroy(&mnode->vmode); + + mnode->mprev = NULL; + mnode->mnext = NULL; + mnode->mnode = NULL; + mnode->mdata = NULL; + mnode->mmode = NULL; + + mnode->node_free = 0; + mnode->node_used = 0; + mnode->node_max = 0; + mnode->list_open = -1; + mnode->list_close= -1; + mnode->total_mem = 0; +} + +static int imnode_node_resize(struct IMEMNODE *mnode, ilong size) +{ + size_t size1, size2; + + size1 = (size_t)(size * (ilong)sizeof(ilong)); + size2 = (size_t)(size * (ilong)sizeof(void*)); + + if (iv_resize(&mnode->vprev, size1)) return -1; + if (iv_resize(&mnode->vnext, size1)) return -2; + if (iv_resize(&mnode->vnode, size1)) return -3; + if (iv_resize(&mnode->vdata, size2)) return -5; + if (iv_resize(&mnode->vmode, size1)) return -6; + + mnode->mprev = (ilong*)((void*)mnode->vprev.data); + mnode->mnext = (ilong*)((void*)mnode->vnext.data); + mnode->mnode = (ilong*)((void*)mnode->vnode.data); + mnode->mdata =(void**)((void*)mnode->vdata.data); + mnode->mmode = (ilong*)((void*)mnode->vmode.data); + mnode->node_max = size; + + return 0; +} + +static int imnode_mem_add(struct IMEMNODE*mnode, ilong node_count, void**mem) +{ + size_t newsize; + char *mptr; + + if (mnode->mem_count >= mnode->mem_max) { + newsize = (mnode->mem_max <= 0)? 16 : mnode->mem_max * 2; + if (iv_resize(&mnode->vmem, newsize * sizeof(void*))) + return -1; + mnode->mem_max = newsize; + mnode->mmem = (char**)((void*)mnode->vmem.data); + } + newsize = node_count * mnode->node_size + 16; + mptr = (char*)internal_malloc(mnode->allocator, newsize); + if (mptr == NULL) return -2; + + mnode->mmem[mnode->mem_count++] = mptr; + mnode->total_mem += newsize; + mptr = (char*)IROUND_UP(((size_t)mptr), 16); + + if (mem) *mem = mptr; + + return 0; +} + + +static long imnode_grow(struct IMEMNODE *mnode) +{ + ilong size_start = mnode->node_max; + ilong size_endup; + ilong retval, count, i, j; + void *mptr; + char *p; + + count = (mnode->node_max <= 0)? 8 : mnode->node_max; + if (mnode->grow_limit > 0) { + if (count > mnode->grow_limit) count = mnode->grow_limit; + } + if (count > 4096) count = 4096; + size_endup = size_start + count; + + retval = imnode_node_resize(mnode, size_endup); + if (retval) return -10 + (long)retval; + + retval = imnode_mem_add(mnode, count, &mptr); + + if (retval) { + imnode_node_resize(mnode, size_start); + mnode->node_max = size_start; + return -20 + (long)retval; + } + + p = (char*)mptr; + for (i = mnode->node_max - 1, j = 0; j < count; i--, j++) { + IMNODE_NODE(mnode, i) = 0; + IMNODE_MODE(mnode, i) = 0; + IMNODE_DATA(mnode, i) = p; + IMNODE_PREV(mnode, i) = -1; + IMNODE_NEXT(mnode, i) = mnode->list_open; + if (mnode->list_open >= 0) IMNODE_PREV(mnode, mnode->list_open) = i; + mnode->list_open = i; + mnode->node_free++; + p += mnode->node_size; + } + + return 0; +} + + +ilong imnode_new(struct IMEMNODE *mnode) +{ + ilong node, next; + + assert(mnode); + if (mnode->list_open < 0) { + if (imnode_grow(mnode)) return -2; + } + + if (mnode->list_open < 0 || mnode->node_free <= 0) return -3; + + node = mnode->list_open; + next = IMNODE_NEXT(mnode, node); + if (next >= 0) IMNODE_PREV(mnode, next) = -1; + mnode->list_open = next; + + IMNODE_PREV(mnode, node) = -1; + IMNODE_NEXT(mnode, node) = mnode->list_close; + + if (mnode->list_close >= 0) IMNODE_PREV(mnode, mnode->list_close) = node; + mnode->list_close = node; + IMNODE_MODE(mnode, node) = 1; + + mnode->node_free--; + mnode->node_used++; + + return node; +} + +void imnode_del(struct IMEMNODE *mnode, ilong index) +{ + ilong prev, next; + + assert(mnode); + assert((index >= 0) && (index < mnode->node_max)); + assert(IMNODE_MODE(mnode, index) != 0); + + next = IMNODE_NEXT(mnode, index); + prev = IMNODE_PREV(mnode, index); + + if (next >= 0) IMNODE_PREV(mnode, next) = prev; + if (prev >= 0) IMNODE_NEXT(mnode, prev) = next; + else mnode->list_close = next; + + IMNODE_PREV(mnode, index) = -1; + IMNODE_NEXT(mnode, index) = mnode->list_open; + + if (mnode->list_open >= 0) IMNODE_PREV(mnode, mnode->list_open) = index; + mnode->list_open = index; + + IMNODE_MODE(mnode, index) = 0; + mnode->node_free++; + mnode->node_used--; +} + +ilong imnode_head(const struct IMEMNODE *mnode) +{ + return (mnode)? mnode->list_close : -1; +} + +ilong imnode_next(const struct IMEMNODE *mnode, ilong index) +{ + return (mnode)? IMNODE_NEXT(mnode, index) : -1; +} + +ilong imnode_prev(const struct IMEMNODE *mnode, ilong index) +{ + return (mnode)? IMNODE_PREV(mnode, index) : -1; +} + +void *imnode_data(struct IMEMNODE *mnode, ilong index) +{ + return (char*)IMNODE_DATA(mnode, index); +} + +const void* imnode_data_const(const struct IMEMNODE *mnode, ilong index) +{ + return (const char*)IMNODE_DATA(mnode, index); +} + + + + +/*====================================================================*/ +/* IVECTOR / IMEMNODE MANAGEMENT */ +/*====================================================================*/ + +ib_vector *iv_create(void) +{ + ib_vector *vec; + vec = (ib_vector*)ikmem_malloc(sizeof(ib_vector)); + if (vec == NULL) return NULL; + iv_init(vec, ikmem_allocator); + return vec; +} + +void iv_delete(ib_vector *vec) +{ + assert(vec); + iv_destroy(vec); + ikmem_free(vec); +} + +ib_memnode *imnode_create(ilong nodesize, int grow_limit) +{ + ib_memnode *mnode; + mnode = (ib_memnode*)ikmem_malloc(sizeof(ib_memnode)); + if (mnode == NULL) return NULL; + imnode_init(mnode, nodesize, ikmem_allocator); + mnode->grow_limit = grow_limit; + return mnode; +} + +void imnode_delete(ib_memnode *mnode) +{ + assert(mnode); + imnode_destroy(mnode); + ikmem_free(mnode); +} + + +/*--------------------------------------------------------------------*/ +/* Collection - Array */ +/*--------------------------------------------------------------------*/ + +struct ib_array +{ + struct IVECTOR vec; + void (*fn_destroy)(void*); + size_t size; + void **items; +}; + +ib_array *ib_array_new(void (*destroy_func)(void*)) +{ + ib_array *array = (ib_array*)ikmem_malloc(sizeof(ib_array)); + if (array == NULL) return NULL; + iv_init(&array->vec, ikmem_allocator); + array->fn_destroy = destroy_func; + array->size = 0; + return array; +}; + + +void ib_array_delete(ib_array *array) +{ + array->items = (void**)array->vec.data; +} + +void ib_array_release(ib_array *array) +{ + if (array->fn_destroy) { + size_t n = array->size; + size_t i; + for (i = 0; i < n; i++) { + array->fn_destroy(array->items[i]); + array->items[i] = NULL; + } + } + iv_destroy(&array->vec); + array->size = 0; + array->items = NULL; + ikmem_free(array); +} + +static void ib_array_update(ib_array *array) +{ + array->items = (void**)array->vec.data; +} + +void ib_array_reserve(ib_array *array, size_t new_size) +{ + int hr = iv_obj_reserve(&array->vec, char*, new_size); + if (hr != 0) { + assert(hr == 0); + } + ib_array_update(array); +} + +size_t ib_array_size(const ib_array *array) +{ + return array->size; +} + +void** ib_array_ptr(ib_array *array) +{ + return array->items; +} + +void* ib_array_index(ib_array *array, size_t index) +{ + assert(index < array->size); + return array->items[index]; +} + +const void* ib_array_const_index(const ib_array *array, size_t index) +{ + assert(index < array->size); + return array->items[index]; +} + +void ib_array_push(ib_array *array, void *item) +{ + int hr = iv_obj_push(&array->vec, void*, &item); + if (hr) { + assert(hr == 0); + } + ib_array_update(array); + array->size++; +} + +void ib_array_push_left(ib_array *array, void *item) +{ + int hr = iv_obj_insert(&array->vec, void*, 0, &item); + if (hr) { + assert(hr == 0); + } + ib_array_update(array); + array->size++; +} + +void ib_array_replace(ib_array *array, size_t index, void *item) +{ + assert(index < array->size); + if (array->fn_destroy) { + array->fn_destroy(array->items[index]); + } + array->items[index] = item; +} + +void* ib_array_pop(ib_array *array) +{ + void *item; + int hr; + assert(array->size > 0); + array->size--; + item = array->items[array->size]; + hr = iv_obj_resize(&array->vec, void*, array->size); + ib_array_update(array); + if (hr) { + assert(hr == 0); + } + return item; +} + +void* ib_array_pop_left(ib_array *array) +{ + void *item; + int hr; + assert(array->size > 0); + array->size--; + item = array->items[0]; + hr = iv_obj_erase(&array->vec, void*, 0, 1); + ib_array_update(array); + if (hr) { + assert(hr == 0); + } + return item; +} + +void ib_array_remove(ib_array *array, size_t index) +{ + assert(index < array->size); + if (array->fn_destroy) { + array->fn_destroy(array->items[index]); + } + iv_obj_erase(&array->vec, void*, index, 1); + ib_array_update(array); + array->size--; +} + +void ib_array_insert_before(ib_array *array, size_t index, void *item) +{ + int hr = iv_obj_insert(&array->vec, void*, index, &item); + if (hr) { + assert(hr == 0); + } + ib_array_update(array); + array->size++; +} + +void* ib_array_pop_at(ib_array *array, size_t index) +{ + void *item; + int hr; + assert(array->size > 0); + item = array->items[index]; + hr = iv_obj_erase(&array->vec, void*, index, 1); + if (hr) { + assert(hr == 0); + } + return item; +} + +void ib_array_sort(ib_array *array, + int (*compare)(const void*, const void*)) +{ + if (array->size) { + void **items = array->items; + size_t size = array->size; + size_t i, j; + for (i = 0; i < size - 1; i++) { + for (j = i + 1; j < size; j++) { + if (compare(items[i], items[j]) > 0) { + void *tmp = items[i]; + items[i] = items[j]; + items[j] = tmp; + } + } + } + } +} + +void ib_array_for_each(ib_array *array, void (*iterator)(void *item)) +{ + if (iterator) { + void **items = array->items; + size_t count = array->size; + for (; count > 0; count--, items++) { + iterator(items[0]); + } + } +} + +ilong ib_array_search(const ib_array *array, + int (*compare)(const void*, const void*), + const void *item, + ilong start_pos) +{ + ilong size = (ilong)array->size; + void **items = array->items; + if (start_pos < 0) { + start_pos = 0; + } + for (items = items + start_pos; start_pos < size; start_pos++) { + if (compare(items[0], item) == 0) { + return start_pos; + } + items++; + } + return -1; +} + +ilong ib_array_bsearch(const ib_array *array, + int (*compare)(const void*, const void*), + const void *item) +{ + ilong top, bottom, mid; + void **items = array->items; + if (array->size == 0) return -1; + top = 0; + bottom = (ilong)array->size - 1; + while (1) { + int hr; + mid = (top + bottom) >> 1; + hr = compare(item, items[mid]); + if (hr < 0) bottom = mid; + else if (hr > 0) top = mid; + else return mid; + if (top == bottom) break; + } + return -1; +} + + + +/*====================================================================*/ +/* Binary Search Tree */ +/*====================================================================*/ + +struct ib_node *ib_node_first(struct ib_root *root) +{ + struct ib_node *node = root->node; + if (node == NULL) return NULL; + while (node->left) + node = node->left; + return node; +} + +struct ib_node *ib_node_last(struct ib_root *root) +{ + struct ib_node *node = root->node; + if (node == NULL) return NULL; + while (node->right) + node = node->right; + return node; +} + +struct ib_node *ib_node_next(struct ib_node *node) +{ + if (node == NULL) return NULL; + if (node->right) { + node = node->right; + while (node->left) + node = node->left; + } + else { + while (1) { + struct ib_node *last = node; + node = node->parent; + if (node == NULL) break; + if (node->left == last) break; + } + } + return node; +} + +struct ib_node *ib_node_prev(struct ib_node *node) +{ + if (node == NULL) return NULL; + if (node->left) { + node = node->left; + while (node->right) + node = node->right; + } + else { + while (1) { + struct ib_node *last = node; + node = node->parent; + if (node == NULL) break; + if (node->right == last) break; + } + } + return node; +} + +static inline void +_ib_child_replace(struct ib_node *oldnode, struct ib_node *newnode, + struct ib_node *parent, struct ib_root *root) +{ + if (parent) { + if (parent->left == oldnode) + parent->left = newnode; + else + parent->right = newnode; + } else { + root->node = newnode; + } +} + +static inline struct ib_node * +_ib_node_rotate_left(struct ib_node *node, struct ib_root *root) +{ + struct ib_node *right = node->right; + struct ib_node *parent = node->parent; + node->right = right->left; + ASSERTION(node && right); + if (right->left) + right->left->parent = node; + right->left = node; + right->parent = parent; + _ib_child_replace(node, right, parent, root); + node->parent = right; + return right; +} + +static inline struct ib_node * +_ib_node_rotate_right(struct ib_node *node, struct ib_root *root) +{ + struct ib_node *left = node->left; + struct ib_node *parent = node->parent; + node->left = left->right; + ASSERTION(node && left); + if (left->right) + left->right->parent = node; + left->right = node; + left->parent = parent; + _ib_child_replace(node, left, parent, root); + node->parent = left; + return left; +} + +void ib_node_replace(struct ib_node *victim, struct ib_node *newnode, + struct ib_root *root) +{ + struct ib_node *parent = victim->parent; + _ib_child_replace(victim, newnode, parent, root); + if (victim->left) victim->left->parent = newnode; + if (victim->right) victim->right->parent = newnode; + newnode->left = victim->left; + newnode->right = victim->right; + newnode->parent = victim->parent; + newnode->height = victim->height; +} + + +/*--------------------------------------------------------------------*/ +/* avl - node manipulation */ +/*--------------------------------------------------------------------*/ + +static inline int IB_MAX(int x, int y) +{ +#if 1 + return (x < y)? y : x; /* this is faster with cmov on x86 */ +#else + return x - ((x - y) & ((x - y) >> (sizeof(int) * 8 - 1))); +#endif +} + +static inline void +_ib_node_height_update(struct ib_node *node) +{ + int h0 = IB_LEFT_HEIGHT(node); + int h1 = IB_RIGHT_HEIGHT(node); + node->height = IB_MAX(h0, h1) + 1; +} + +static inline struct ib_node * +_ib_node_fix_l(struct ib_node *node, struct ib_root *root) +{ + struct ib_node *right = node->right; + int rh0, rh1; + ASSERTION(right); + rh0 = IB_LEFT_HEIGHT(right); + rh1 = IB_RIGHT_HEIGHT(right); + if (rh0 > rh1) { + right = _ib_node_rotate_right(right, root); + _ib_node_height_update(right->right); + _ib_node_height_update(right); + /* _ib_node_height_update(node); */ + } + node = _ib_node_rotate_left(node, root); + _ib_node_height_update(node->left); + _ib_node_height_update(node); + return node; +} + +static inline struct ib_node * +_ib_node_fix_r(struct ib_node *node, struct ib_root *root) +{ + struct ib_node *left = node->left; + int rh0, rh1; + ASSERTION(left); + rh0 = IB_LEFT_HEIGHT(left); + rh1 = IB_RIGHT_HEIGHT(left); + if (rh0 < rh1) { + left = _ib_node_rotate_left(left, root); + _ib_node_height_update(left->left); + _ib_node_height_update(left); + /* _ib_node_height_update(node); */ + } + node = _ib_node_rotate_right(node, root); + _ib_node_height_update(node->right); + _ib_node_height_update(node); + return node; +} + +static inline void +_ib_node_rebalance(struct ib_node *node, struct ib_root *root) +{ + while (node) { + int h0 = (int)IB_LEFT_HEIGHT(node); + int h1 = (int)IB_RIGHT_HEIGHT(node); + int diff = h0 - h1; + int height = IB_MAX(h0, h1) + 1; + if (node->height != height) { + node->height = height; + } + else if (diff >= -1 && diff <= 1) { + break; + } + if (diff <= -2) { + node = _ib_node_fix_l(node, root); + } + else if (diff >= 2) { + node = _ib_node_fix_r(node, root); + } + node = node->parent; + } +} + +void ib_node_post_insert(struct ib_node *node, struct ib_root *root) +{ + node->height = 1; + + for (node = node->parent; node; node = node->parent) { + int h0 = (int)IB_LEFT_HEIGHT(node); + int h1 = (int)IB_RIGHT_HEIGHT(node); + int height = IB_MAX(h0, h1) + 1; + int diff = h0 - h1; + if (node->height == height) break; + node->height = height; + if (diff <= -2) { + node = _ib_node_fix_l(node, root); + } + else if (diff >= 2) { + node = _ib_node_fix_r(node, root); + } + } +} + +void ib_node_erase(struct ib_node *node, struct ib_root *root) +{ + struct ib_node *child, *parent; + ASSERTION(node); + if (node->left && node->right) { + struct ib_node *old = node; + struct ib_node *left; + node = node->right; + while ((left = node->left) != NULL) + node = left; + child = node->right; + parent = node->parent; + if (child) { + child->parent = parent; + } + _ib_child_replace(node, child, parent, root); + if (node->parent == old) + parent = node; + node->left = old->left; + node->right = old->right; + node->parent = old->parent; + node->height = old->height; + _ib_child_replace(old, node, old->parent, root); + ASSERTION(old->left); + old->left->parent = node; + if (old->right) { + old->right->parent = node; + } + } + else { + if (node->left == NULL) + child = node->right; + else + child = node->left; + parent = node->parent; + _ib_child_replace(node, child, parent, root); + if (child) { + child->parent = parent; + } + } + if (parent) { + _ib_node_rebalance(parent, root); + } +} + + +/* avl nodes destroy: fast tear down the whole tree */ +struct ib_node* ib_node_tear(struct ib_root *root, struct ib_node **next) +{ + struct ib_node *node = *next; + struct ib_node *parent; + if (node == NULL) { + if (root->node == NULL) + return NULL; + node = root->node; + } + /* sink down to the leaf */ + while (1) { + if (node->left) node = node->left; + else if (node->right) node = node->right; + else break; + } + /* tear down one leaf */ + parent = node->parent; + if (parent == NULL) { + *next = NULL; + root->node = NULL; + return node; + } + if (parent->left == node) { + parent->left = NULL; + } else { + parent->right = NULL; + } + node->height = 0; + *next = parent; + return node; +} + + + +/*--------------------------------------------------------------------*/ +/* avltree - friendly interface */ +/*--------------------------------------------------------------------*/ + +void ib_tree_init(struct ib_tree *tree, + int (*compare)(const void*, const void*), size_t size, size_t offset) +{ + tree->root.node = NULL; + tree->offset = offset; + tree->size = size; + tree->count = 0; + tree->compare = compare; +} + + +void *ib_tree_first(struct ib_tree *tree) +{ + struct ib_node *node = ib_node_first(&tree->root); + if (!node) return NULL; + return IB_NODE2DATA(node, tree->offset); +} + +void *ib_tree_last(struct ib_tree *tree) +{ + struct ib_node *node = ib_node_last(&tree->root); + if (!node) return NULL; + return IB_NODE2DATA(node, tree->offset); +} + +void *ib_tree_next(struct ib_tree *tree, void *data) +{ + struct ib_node *nn; + if (!data) return NULL; + nn = IB_DATA2NODE(data, tree->offset); + nn = ib_node_next(nn); + if (!nn) return NULL; + return IB_NODE2DATA(nn, tree->offset); +} + +void *ib_tree_prev(struct ib_tree *tree, void *data) +{ + struct ib_node *nn; + if (!data) return NULL; + nn = IB_DATA2NODE(data, tree->offset); + nn = ib_node_prev(nn); + if (!nn) return NULL; + return IB_NODE2DATA(nn, tree->offset); +} + + +/* require a temporary user structure (data) which contains the key */ +void *ib_tree_find(struct ib_tree *tree, const void *data) +{ + struct ib_node *n = tree->root.node; + int (*compare)(const void*, const void*) = tree->compare; + int offset = (int)(tree->offset); + while (n) { + void *nd = IB_NODE2DATA(n, offset); + int hr = compare(data, nd); + if (hr == 0) { + return nd; + } + else if (hr < 0) { + n = n->left; + } + else { + n = n->right; + } + } + return NULL; +} + +void *ib_tree_nearest(struct ib_tree *tree, const void *data) +{ + struct ib_node *n = tree->root.node; + struct ib_node *p = NULL; + int (*compare)(const void*, const void*) = tree->compare; + int offset = (int)(tree->offset); + while (n) { + void *nd = IB_NODE2DATA(n, offset); + int hr = compare(data, nd); + p = n; + if (n == 0) return nd; + else if (hr < 0) { + n = n->left; + } + else { + n = n->right; + } + } + return (p)? IB_NODE2DATA(p, offset) : NULL; +} + + +/* returns NULL for success, otherwise returns conflict node with same key */ +void *ib_tree_add(struct ib_tree *tree, void *data) +{ + struct ib_node **link = &tree->root.node; + struct ib_node *parent = NULL; + struct ib_node *node = IB_DATA2NODE(data, tree->offset); + int (*compare)(const void*, const void*) = tree->compare; + int offset = (int)(tree->offset); + while (link[0]) { + void *pd; + int hr; + parent = link[0]; + pd = IB_NODE2DATA(parent, offset); + hr = compare(data, pd); + if (hr == 0) { + return pd; + } + else if (hr < 0) { + link = &(parent->left); + } + else { + link = &(parent->right); + } + } + ib_node_link(node, parent, link); + ib_node_post_insert(node, &tree->root); + tree->count++; + return NULL; +} + + +void ib_tree_remove(struct ib_tree *tree, void *data) +{ + struct ib_node *node = IB_DATA2NODE(data, tree->offset); + if (!ib_node_empty(node)) { + ib_node_erase(node, &tree->root); + node->parent = node; + tree->count--; + } +} + + +void ib_tree_replace(struct ib_tree *tree, void *victim, void *newdata) +{ + struct ib_node *vicnode = IB_DATA2NODE(victim, tree->offset); + struct ib_node *newnode = IB_DATA2NODE(newdata, tree->offset); + ib_node_replace(vicnode, newnode, &tree->root); + vicnode->parent = vicnode; +} + + +void ib_tree_clear(struct ib_tree *tree, void (*destroy)(void *data)) +{ + while (1) { + void *data; + if (tree->root.node == NULL) break; + data = IB_NODE2DATA(tree->root.node, tree->offset); + ib_tree_remove(tree, data); + if (destroy) destroy(data); + } +} + + +/*--------------------------------------------------------------------*/ +/* fastbin - fixed size object allocator */ +/*--------------------------------------------------------------------*/ + +void ib_fastbin_init(struct ib_fastbin *fb, size_t obj_size) +{ + const size_t align = sizeof(void*); + size_t need; + fb->start = NULL; + fb->endup = NULL; + fb->next = NULL; + fb->pages = NULL; + fb->obj_size = (obj_size + align - 1) & (~(align - 1)); + need = fb->obj_size * 32 + sizeof(void*) + 16; + fb->page_size = (align <= 2)? 8 : 32; + while (fb->page_size < need) { + fb->page_size *= 2; + } + fb->maximum = (align <= 2)? fb->page_size : 0x10000; +} + +void ib_fastbin_destroy(struct ib_fastbin *fb) +{ + while (fb->pages) { + void *page = fb->pages; + void *next = IB_NEXT(page); + fb->pages = next; + ikmem_free(page); + } + fb->start = NULL; + fb->endup = NULL; + fb->next = NULL; + fb->pages = NULL; +} + +void* ib_fastbin_new(struct ib_fastbin *fb) +{ + size_t obj_size = fb->obj_size; + void *obj; + obj = fb->next; + if (obj) { + fb->next = IB_NEXT(fb->next); + return obj; + } + if (fb->start + obj_size > fb->endup) { + char *page = (char*)ikmem_malloc(fb->page_size); + size_t lineptr = (size_t)page; + ASSERTION(page); + IB_NEXT(page) = fb->pages; + fb->pages = page; + lineptr = (lineptr + sizeof(void*) + 15) & (~15); + fb->start = (char*)lineptr; + fb->endup = (char*)page + fb->page_size; + if (fb->page_size < fb->maximum) { + fb->page_size *= 2; + } + } + obj = fb->start; + fb->start += obj_size; + ASSERTION(fb->start <= fb->endup); + return obj; +} + +void ib_fastbin_del(struct ib_fastbin *fb, void *ptr) +{ + IB_NEXT(ptr) = fb->next; + fb->next = ptr; +} + + +/*--------------------------------------------------------------------*/ +/* string */ +/*--------------------------------------------------------------------*/ + +ib_string* ib_string_new(void) +{ + struct ib_string* str = (ib_string*)ikmem_malloc(sizeof(ib_string)); + assert(str); + str->ptr = str->sso; + str->size = 0; + str->capacity = IB_STRING_SSO; + str->ptr[0] = 0; + return str; +} + + +void ib_string_delete(ib_string *str) +{ + assert(str); + if (str) { + if (str->ptr && str->ptr != str->sso) + ikmem_free(str->ptr); + str->ptr = NULL; + str->size = str->capacity = 0; + } + ikmem_free(str); +} + +ib_string* ib_string_new_size(const char *text, int size) +{ + struct ib_string *str = ib_string_new(); + size = (size > 0)? size : 0; + if (size > 0 && text) { + ib_string_resize(str, size); + memcpy(str->ptr, text, size); + } + return str; +} + +ib_string* ib_string_new_from(const char *text) +{ + return ib_string_new_size(text, (text)? ((int)strlen(text)) : 0); +} + +static void _ib_string_set_capacity(ib_string *str, int capacity) +{ + assert(str); + assert(capacity >= 0); + if (capacity <= IB_STRING_SSO) { + capacity = IB_STRING_SSO; + if (str->ptr != str->sso) { + if (str->size > 0) { + int csize = (str->size < capacity) ? str->size : capacity; + memcpy(str->sso, str->ptr, csize); + } + ikmem_free(str->ptr); + str->ptr = str->sso; + str->capacity = IB_STRING_SSO; + } + } + else { + char *ptr = (char*)ikmem_malloc(capacity + 2); + int csize = (capacity < str->size) ? capacity : str->size; + assert(ptr); + if (csize > 0) { + memcpy(ptr, str->ptr, csize); + } + if (str->ptr != str->sso) + ikmem_free(str->ptr); + str->ptr = ptr; + str->capacity = capacity; + } + if (str->size > str->capacity) + str->size = str->capacity; + str->ptr[str->size] = 0; +} + +ib_string* ib_string_resize(ib_string *str, int newsize) +{ + assert(str && newsize >= 0); + if (newsize > str->capacity) { + int capacity = str->capacity * 2; + if (capacity < newsize) { + while (capacity < newsize) { + capacity = capacity * 2; + } + } + _ib_string_set_capacity(str, capacity); + } + str->size = newsize; + str->ptr[str->size] = 0; + return str; +} + +ib_string* ib_string_reserve(ib_string *str, int newsize) +{ + int size = (newsize >= str->size)? newsize : str->size; + _ib_string_set_capacity(str, size); + return str; +} + +ib_string* ib_string_insert(ib_string *str, int pos, + const void *data, int size) +{ + int current = str->size; + if (pos < 0 || pos > str->size) + return NULL; + ib_string_resize(str, str->size + size); + if (pos < current) { + memmove(str->ptr + pos + size, str->ptr + pos, current - pos); + } + if (data) { + memcpy(str->ptr + pos, data, size); + } + return str; +} + +ib_string* ib_string_insert_c(ib_string *str, int pos, char c) +{ + int current = str->size; + if (pos < 0 || pos > str->size) + return NULL; + ib_string_resize(str, str->size + 1); + if (pos < current) { + memmove(str->ptr + pos + 1, str->ptr + pos, current - pos); + } + str->ptr[pos] = c; + return str; +} + +ib_string* ib_string_erase(ib_string *str, int pos, int size) +{ + int current = str->size; + if (pos >= current) return 0; + if (pos + size >= current) size = current - pos; + if (size == 0) return 0; + memmove(str->ptr + pos, str->ptr + pos + size, current - pos - size); + return ib_string_resize(str, current - size); +} + +int ib_string_compare(const struct ib_string *a, const struct ib_string *b) +{ + int minsize = (a->size < b->size)? a->size : b->size; + int hr = memcmp(a->ptr, b->ptr, minsize); + if (hr < 0) return -1; + else if (hr > 0) return 1; + if (a->size < b->size) return -1; + else if (a->size > b->size) return 1; + return 0; +} + + +ib_string* ib_string_assign(ib_string *str, const char *src) +{ + return ib_string_assign_size(str, src, (int)strlen(src)); +} + +ib_string* ib_string_assign_size(ib_string *str, const char *src, int size) +{ + assert(size >= 0); + ib_string_resize(str, size); + if (src) { + memcpy(str->ptr, src, size); + } + return str; +} + + +ib_string* ib_string_append(ib_string *str, const char *src) +{ + return ib_string_append_size(str, src, (int)strlen(src)); +} + + +ib_string* ib_string_append_size(ib_string *str, const char *src, int size) +{ + return ib_string_insert(str, str->size, src, size); +} + +ib_string* ib_string_append_c(ib_string *str, char c) +{ + ib_string_resize(str, str->size + 1); + str->ptr[str->size - 1] = c; + return str; +} + +ib_string* ib_string_prepend(ib_string *str, const char *src) +{ + return ib_string_prepend_size(str, src, (int)strlen(src)); +} + +ib_string* ib_string_prepend_size(ib_string *str, const char *src, int size) +{ + return ib_string_insert(str, 0, src, size); +} + +ib_string* ib_string_prepend_c(ib_string *str, char c) +{ + int current = str->size; + ib_string_resize(str, current + 1); + if (current > 0) { + memmove(str->ptr + 1, str->ptr, current); + } + str->ptr[0] = c; + return str; +} + +ib_string* ib_string_rewrite(ib_string *str, int pos, const char *src) +{ + return ib_string_rewrite_size(str, pos, src, (int)strlen(src)); +} + +ib_string* ib_string_rewrite_size(ib_string *str, int pos, + const char *src, int size) +{ + if (pos < 0) size += pos, pos = 0; + if (pos + size >= str->size) size = str->size - pos; + if (size <= 0) return str; + if (src) { + memcpy(str->ptr + pos, src, size); + } + return str; +} + + +int ib_string_find(const ib_string *str, const char *src, int len, int start) +{ + char *text = str->ptr; + int pos = (start < 0)? 0 : start; + int length = (len >= 0)? len : ((int)strlen(src)); + int endup = str->size - length; + char ch; + if (length <= 0) return pos; + for (ch = src[0]; pos <= endup; pos++) { + if (text[pos] == ch) { + if (memcmp(text + pos, src, length) == 0) + return pos; + } + } + return -1; +} + +int ib_string_find_c(const ib_string *str, char ch, int start) +{ + const char *text = str->ptr; + int pos = (start < 0)? 0 : start; + int endup = str->size; + for (; pos < endup; pos++) { + if (text[pos] == ch) return pos; + } + return -1; +} + +ib_array* ib_string_split(const ib_string *str, const char *sep, int len) +{ + if (len == 0) { + return NULL; + } + else { + ib_array *array = ib_array_new((void (*)(void*))ib_string_delete); + int start = 0; + len = (len >= 0)? len : ((int)strlen(sep)); + while (1) { + int pos = ib_string_find(str, sep, len, start); + if (pos < 0) { + ib_string *newstr = ib_string_new(); + ib_string_assign_size(newstr, str->ptr + start, + str->size - start); + ib_array_push(array, newstr); + break; + } + else { + ib_string* newstr = ib_string_new(); + ib_string_assign_size(newstr, str->ptr + start, pos - start); + start = pos + len; + ib_array_push(array, newstr); + } + } + return array; + } +} + +ib_array* ib_string_split_c(const ib_string *str, char sep) +{ + if (str == NULL) { + return NULL; + } + else { + ib_array *array = ib_array_new((void (*)(void*))ib_string_delete); + int start = 0; + while (1) { + int pos = ib_string_find_c(str, sep, start); + if (pos < 0) { + ib_string *newstr = ib_string_new(); + ib_string_assign_size(newstr, str->ptr + start, + str->size - start); + ib_array_push(array, newstr); + break; + } + else { + ib_string *newstr = ib_string_new(); + ib_string_assign_size(newstr, str->ptr + start, pos - start); + start = pos + 1; + ib_array_push(array, newstr); + } + } + return array; + } +} + +ib_string* ib_string_strip(ib_string *str, const char *seps) +{ + const char *ptr = str->ptr; + const char *endup = str->ptr + str->size; + int off, pos; + for (; ptr < endup; ptr++) { + const char *sep = seps; + int match = 0; + for (; sep[0]; sep++) { + if (ptr[0] == sep[0]) { + match = 1; + break; + } + } + if (match == 0) break; + } + off = (int)(ptr - str->ptr); + if (off > 0) { + ib_string_erase(str, 0, off); + } + ptr = str->ptr; + pos = str->size; + for (; pos > 0; pos--) { + const char *sep = seps; + int match = 0; + for (; sep[0]; sep++) { + if (ptr[pos - 1] == sep[0]) { + match = 1; + break; + } + } + if (match == 0) break; + } + ib_string_resize(str, pos); + return str; +} + +ib_string* ib_string_replace_size(ib_string *str, int pos, int size, + const char *src, int len) +{ + ib_string_erase(str, pos, size); + ib_string_insert(str, pos, src, len); + return str; +} + + +/*--------------------------------------------------------------------*/ +/* static hash table (closed hash table with avlnode) */ +/*--------------------------------------------------------------------*/ + + +void ib_hash_init(struct ib_hash_table *ht, + size_t (*hash)(const void *key), + int (*compare)(const void *key1, const void *key2)) +{ + size_t i; + ht->count = 0; + ht->index_size = IB_HASH_INIT_SIZE; + ht->index_mask = ht->index_size - 1; + ht->hash = hash; + ht->compare = compare; + ilist_init(&ht->head); + ht->index = ht->init; + for (i = 0; i < IB_HASH_INIT_SIZE; i++) { + ht->index[i].avlroot.node = NULL; + ilist_init(&(ht->index[i].node)); + } +} + +struct ib_hash_node* ib_hash_node_first(struct ib_hash_table *ht) +{ + struct ILISTHEAD *head = ht->head.next; + if (head != &ht->head) { + struct ib_hash_index *index = + ilist_entry(head, struct ib_hash_index, node); + struct ib_node *avlnode = ib_node_first(&index->avlroot); + if (avlnode == NULL) return NULL; + return IB_ENTRY(avlnode, struct ib_hash_node, avlnode); + } + return NULL; +} + +struct ib_hash_node* ib_hash_node_last(struct ib_hash_table *ht) +{ + struct ILISTHEAD *head = ht->head.prev; + if (head != &ht->head) { + struct ib_hash_index *index = + ilist_entry(head, struct ib_hash_index, node); + struct ib_node *avlnode = ib_node_last(&index->avlroot); + if (avlnode == NULL) return NULL; + return IB_ENTRY(avlnode, struct ib_hash_node, avlnode); + } + return NULL; +} + +struct ib_hash_node* ib_hash_node_next(struct ib_hash_table *ht, + struct ib_hash_node *node) +{ + struct ib_node *avlnode; + struct ib_hash_index *index; + struct ILISTHEAD *listnode; + if (node == NULL) return NULL; + avlnode = ib_node_next(&node->avlnode); + if (avlnode) { + return IB_ENTRY(avlnode, struct ib_hash_node, avlnode); + } + index = &(ht->index[node->hash & ht->index_mask]); + listnode = index->node.next; + if (listnode == &(ht->head)) { + return NULL; + } + index = ilist_entry(listnode, struct ib_hash_index, node); + avlnode = ib_node_first(&index->avlroot); + if (avlnode == NULL) return NULL; + return IB_ENTRY(avlnode, struct ib_hash_node, avlnode); +} + +struct ib_hash_node* ib_hash_node_prev(struct ib_hash_table *ht, + struct ib_hash_node *node) +{ + struct ib_node *avlnode; + struct ib_hash_index *index; + struct ILISTHEAD *listnode; + if (node == NULL) return NULL; + avlnode = ib_node_prev(&node->avlnode); + if (avlnode) { + return IB_ENTRY(avlnode, struct ib_hash_node, avlnode); + } + index = &(ht->index[node->hash & ht->index_mask]); + listnode = index->node.prev; + if (listnode == &(ht->head)) { + return NULL; + } + index = ilist_entry(listnode, struct ib_hash_index, node); + avlnode = ib_node_last(&index->avlroot); + if (avlnode == NULL) return NULL; + return IB_ENTRY(avlnode, struct ib_hash_node, avlnode); +} + +struct ib_hash_node* ib_hash_find(struct ib_hash_table *ht, + const struct ib_hash_node *node) +{ + size_t hash = node->hash; + const void *key = node->key; + struct ib_hash_index *index = &(ht->index[hash & ht->index_mask]); + struct ib_node *avlnode = index->avlroot.node; + int (*compare)(const void *, const void *) = ht->compare; + while (avlnode) { + struct ib_hash_node *snode = + IB_ENTRY(avlnode, struct ib_hash_node, avlnode); + size_t shash = snode->hash; + if (hash == shash) { + int hc = compare(key, snode->key); + if (hc == 0) return snode; + avlnode = (hc < 0)? avlnode->left : avlnode->right; + } + else { + avlnode = (hash < shash)? avlnode->left : avlnode->right; + } + } + return NULL; +} + +void ib_hash_erase(struct ib_hash_table *ht, struct ib_hash_node *node) +{ + struct ib_hash_index *index; + ASSERTION(node && ht); + ASSERTION(!ib_node_empty(&node->avlnode)); + index = &ht->index[node->hash & ht->index_mask]; + if (index->avlroot.node == &node->avlnode && node->avlnode.height == 1) { + index->avlroot.node = NULL; + ilist_del_init(&index->node); + } + else { + ib_node_erase(&node->avlnode, &index->avlroot); + } + ib_node_init(&node->avlnode); + ht->count--; +} + +struct ib_node** ib_hash_track(struct ib_hash_table *ht, + const struct ib_hash_node *node, struct ib_node **parent) +{ + size_t hash = node->hash; + const void *key = node->key; + struct ib_hash_index *index = &(ht->index[hash & ht->index_mask]); + struct ib_node **link = &index->avlroot.node; + struct ib_node *p = NULL; + int (*compare)(const void *key1, const void *key2) = ht->compare; + parent[0] = NULL; + while (link[0]) { + struct ib_hash_node *snode; + size_t shash; + p = link[0]; + snode = IB_ENTRY(p, struct ib_hash_node, avlnode); + shash = snode->hash; + if (hash == shash) { + int hc = compare(key, snode->key); + if (hc == 0) { + parent[0] = p; + return NULL; + } + link = (hc < 0)? (&p->left) : (&p->right); + } + else { + link = (hash < shash)? (&p->left) : (&p->right); + } + } + parent[0] = p; + return link; +} + + +struct ib_hash_node* ib_hash_add(struct ib_hash_table *ht, + struct ib_hash_node *node) +{ + struct ib_hash_index *index = &(ht->index[node->hash & ht->index_mask]); + if (index->avlroot.node == NULL) { + index->avlroot.node = &node->avlnode; + node->avlnode.parent = NULL; + node->avlnode.left = NULL; + node->avlnode.right = NULL; + node->avlnode.height = 1; + ilist_add_tail(&index->node, &ht->head); + } + else { + struct ib_node **link, *parent; + link = ib_hash_track(ht, node, &parent); + if (link == NULL) { + ASSERTION(parent); + return IB_ENTRY(parent, struct ib_hash_node, avlnode); + } + ib_node_link(&node->avlnode, parent, link); + ib_node_post_insert(&node->avlnode, &index->avlroot); + } + ht->count++; + return NULL; +} + + +void ib_hash_replace(struct ib_hash_table *ht, + struct ib_hash_node *victim, struct ib_hash_node *newnode) +{ + struct ib_hash_index *index = &ht->index[victim->hash & ht->index_mask]; + ib_node_replace(&victim->avlnode, &newnode->avlnode, &index->avlroot); +} + +void ib_hash_clear(struct ib_hash_table *ht, + void (*destroy)(struct ib_hash_node *node)) +{ + while (!ilist_is_empty(&ht->head)) { + struct ib_hash_index *index = ilist_entry(ht->head.next, + struct ib_hash_index, node); + struct ib_node *next = NULL; + while (index->avlroot.node != NULL) { + struct ib_node *avlnode = ib_node_tear(&index->avlroot, &next); + ASSERTION(avlnode); + if (destroy) { + struct ib_hash_node *node = + IB_ENTRY(avlnode, struct ib_hash_node, avlnode); + destroy(node); + } + } + ilist_del_init(&index->node); + } + ht->count = 0; +} + + +void* ib_hash_swap(struct ib_hash_table *ht, void *ptr, size_t nbytes) +{ + struct ib_hash_index *old_index = ht->index; + struct ib_hash_index *new_index = (struct ib_hash_index*)ptr; + size_t index_size = 1; + struct ILISTHEAD head; + size_t i; + ASSERTION(nbytes >= sizeof(struct ib_hash_index)); + if (new_index == NULL) { + if (ht->index == ht->init) { + return NULL; + } + new_index = ht->init; + index_size = IB_HASH_INIT_SIZE; + } + else if (new_index == old_index) { + return old_index; + } + if (new_index != ht->init) { + size_t test_size = sizeof(struct ib_hash_index); + while (test_size < nbytes) { + size_t next_size = test_size * 2; + if (next_size > nbytes) break; + test_size = next_size; + index_size = index_size * 2; + } + } + ht->index = new_index; + ht->index_size = index_size; + ht->index_mask = index_size - 1; + ht->count = 0; + for (i = 0; i < index_size; i++) { + ht->index[i].avlroot.node = NULL; + ilist_init(&ht->index[i].node); + } + ilist_replace(&ht->head, &head); + ilist_init(&ht->head); + while (!ilist_is_empty(&head)) { + struct ib_hash_index *index = ilist_entry(head.next, + struct ib_hash_index, node); + #if 1 + struct ib_node *next = NULL; + while (index->avlroot.node) { + struct ib_node *avlnode = ib_node_tear(&index->avlroot, &next); + struct ib_hash_node *snode, *hr; + ASSERTION(avlnode); + snode = IB_ENTRY(avlnode, struct ib_hash_node, avlnode); + hr = ib_hash_add(ht, snode); + if (hr != NULL) { + ASSERTION(hr == NULL); + return NULL; + } + } + #else + while (index->avlroot.node) { + struct ib_node *avlnode = index->avlroot.node; + struct ib_hash_node *snode, *hr; + ib_node_erase(avlnode, &index->avlroot); + snode = IB_ENTRY(avlnode, struct ib_hash_node, avlnode); + hr = ib_hash_add(ht, snode); + ASSERTION(hr == NULL); + hr = hr; + } + #endif + ilist_del_init(&index->node); + } + return (old_index == ht->init)? NULL : old_index; +} + + +/*--------------------------------------------------------------------*/ +/* hash map, wrapper of ib_hash_table to support direct key/value */ +/*--------------------------------------------------------------------*/ + +struct ib_hash_entry* ib_map_first(struct ib_hash_map *hm) +{ + struct ib_hash_node *node = ib_hash_node_first(&hm->ht); + if (node == NULL) return NULL; + return IB_ENTRY(node, struct ib_hash_entry, node); +} + + +struct ib_hash_entry* ib_map_last(struct ib_hash_map *hm) +{ + struct ib_hash_node *node = ib_hash_node_last(&hm->ht); + if (node == NULL) return NULL; + return IB_ENTRY(node, struct ib_hash_entry, node); +} + + +struct ib_hash_entry* ib_map_next(struct ib_hash_map *hm, + struct ib_hash_entry *n) +{ + struct ib_hash_node *node = ib_hash_node_next(&hm->ht, &n->node); + if (node == NULL) return NULL; + return IB_ENTRY(node, struct ib_hash_entry, node); +} + + +struct ib_hash_entry* ib_map_prev(struct ib_hash_map *hm, + struct ib_hash_entry *n) +{ + struct ib_hash_node *node = ib_hash_node_prev(&hm->ht, &n->node); + if (node == NULL) return NULL; + return IB_ENTRY(node, struct ib_hash_entry, node); +} + + +void ib_map_init(struct ib_hash_map *hm, size_t (*hash)(const void*), + int (*compare)(const void *, const void *)) +{ + hm->count = 0; + hm->key_copy = NULL; + hm->key_destroy = NULL; + hm->value_copy = NULL; + hm->value_destroy = NULL; + hm->insert = 0; + hm->fixed = 0; + ib_hash_init(&hm->ht, hash, compare); + ib_fastbin_init(&hm->fb, sizeof(struct ib_hash_entry)); +} + +void ib_map_destroy(struct ib_hash_map *hm) +{ + void *ptr; + ib_map_clear(hm); + ptr = ib_hash_swap(&hm->ht, NULL, 0); + if (ptr) { + ikmem_free(ptr); + } + ib_fastbin_destroy(&hm->fb); +} + +struct ib_hash_entry* ib_map_find(struct ib_hash_map *hm, const void *key) +{ + struct ib_hash_table *ht = &hm->ht; + struct ib_hash_node dummy; + struct ib_hash_node *rh; + void *ptr = (void*)key; + ib_hash_node_key(ht, &dummy, ptr); + rh = ib_hash_find(ht, &dummy); + return (rh == NULL)? NULL : IB_ENTRY(rh, struct ib_hash_entry, node); +} + + +void* ib_map_lookup(struct ib_hash_map *hm, const void *key, void *defval) +{ + struct ib_hash_entry *entry = ib_map_find(hm, key); + if (entry == NULL) return defval; + return ib_hash_value(entry); +} + +static inline struct ib_hash_entry* +ib_hash_entry_allocate(struct ib_hash_map *hm, void *key, void *value) +{ + struct ib_hash_entry *entry; + entry = (struct ib_hash_entry*)ib_fastbin_new(&hm->fb); + ASSERTION(entry); + if (hm->key_copy) entry->node.key = hm->key_copy(key); + else entry->node.key = key; + if (hm->value_copy) entry->value = hm->value_copy(value); + else entry->value = value; + return entry; +} + +static inline struct ib_hash_entry* +ib_hash_update(struct ib_hash_map *hm, void *key, void *value, int update) +{ + size_t hash = hm->ht.hash(key); + struct ib_hash_index *index = &(hm->ht.index[hash & hm->ht.index_mask]); + struct ib_node **link = &index->avlroot.node; + struct ib_node *parent = NULL; + struct ib_hash_entry *entry; + int (*compare)(const void *key1, const void *key2) = hm->ht.compare; + if (index->avlroot.node == NULL) { + entry = ib_hash_entry_allocate(hm, key, value); + ASSERTION(entry); + entry->node.avlnode.height = 1; + entry->node.avlnode.left = NULL; + entry->node.avlnode.right = NULL; + entry->node.avlnode.parent = NULL; + entry->node.hash = hash; + index->avlroot.node = &(entry->node.avlnode); + ilist_add_tail(&index->node, &(hm->ht.head)); + hm->ht.count++; + hm->insert = 1; + return entry; + } + while (link[0]) { + struct ib_hash_node *snode; + size_t shash; + parent = link[0]; + snode = IB_ENTRY(parent, struct ib_hash_node, avlnode); + shash = snode->hash; + if (hash != shash) { + link = (hash < shash)? (&parent->left) : (&parent->right); + } else { + int hc = compare(key, snode->key); + if (hc == 0) { + entry = IB_ENTRY(snode, struct ib_hash_entry, node); + if (update) { + if (hm->value_destroy) { + hm->value_destroy(entry->value); + } + if (hm->value_copy == NULL) entry->value = value; + else entry->value = hm->value_copy(value); + } + hm->insert = 0; + return entry; + } else { + link = (hc < 0)? (&parent->left) : (&parent->right); + } + } + } + entry = ib_hash_entry_allocate(hm, key, value); + ASSERTION(entry); + entry->node.hash = hash; + ib_node_link(&(entry->node.avlnode), parent, link); + ib_node_post_insert(&(entry->node.avlnode), &index->avlroot); + hm->ht.count++; + hm->insert = 1; + return entry; +} + +static inline void ib_map_rehash(struct ib_hash_map *hm, size_t capacity) +{ + size_t isize = hm->ht.index_size; + size_t limit = (capacity * 6) >> 2; /* capacity * 6 / 4 */ + if (isize < limit && hm->fixed == 0) { + size_t need = isize; + size_t size; + void *ptr; + while (need < limit) need <<= 1; + size = need * sizeof(struct ib_hash_index); + ptr = ikmem_malloc(size); + ASSERTION(ptr); + ptr = ib_hash_swap(&hm->ht, ptr, size); + if (ptr) { + ikmem_free(ptr); + } + } +} + +void ib_map_reserve(struct ib_hash_map *hm, size_t capacity) +{ + ib_map_rehash(hm, capacity); +} + +struct ib_hash_entry* +ib_map_add(struct ib_hash_map *hm, void *key, void *value, int *success) +{ + struct ib_hash_entry *entry = ib_hash_update(hm, key, value, 0); + if (success) success[0] = hm->insert; + ib_map_rehash(hm, hm->ht.count); + return entry; +} + +struct ib_hash_entry* +ib_map_set(struct ib_hash_map *hm, void *key, void *value) +{ + struct ib_hash_entry *entry = ib_hash_update(hm, key, value, 0); + ib_map_rehash(hm, hm->ht.count); + return entry; +} + +void *ib_map_get(struct ib_hash_map *hm, const void *key) +{ + return ib_map_lookup(hm, key, NULL); +} + +void ib_map_erase(struct ib_hash_map *hm, struct ib_hash_entry *entry) +{ + ASSERTION(entry); + ASSERTION(!ib_node_empty(&(entry->node.avlnode))); + ib_hash_erase(&hm->ht, &entry->node); + ib_node_init(&(entry->node.avlnode)); + if (hm->key_destroy) hm->key_destroy(entry->node.key); + if (hm->value_destroy) hm->value_destroy(entry->value); + entry->node.key = NULL; + entry->value = NULL; + ib_fastbin_del(&hm->fb, entry); +} + +int ib_map_remove(struct ib_hash_map *hm, const void *key) +{ + struct ib_hash_entry *entry; + entry = ib_map_find(hm, key); + if (entry == NULL) { + return -1; + } + ib_map_erase(hm, entry); + return 0; +} + +void ib_map_clear(struct ib_hash_map *hm) +{ + while (1) { + struct ib_hash_entry *entry = ib_map_first(hm); + if (entry == NULL) break; + ib_map_erase(hm, entry); + } + ASSERTION(hm->count == 0); +} + + +/*--------------------------------------------------------------------*/ +/* common type hash and equal functions */ +/*--------------------------------------------------------------------*/ +size_t ib_hash_seed = 0x11223344; + +size_t ib_hash_func_uint(const void *key) +{ +#if 0 + size_t x = (size_t)key; + return (x * 2654435761u) ^ ib_hash_seed; +#else + return (size_t)key; +#endif +} + +size_t ib_hash_func_int(const void *key) +{ +#if 0 + size_t x = (size_t)key; + return (x * 2654435761u) ^ ib_hash_seed; +#else + return (size_t)key; +#endif +} + +size_t ib_hash_bytes_stl(const void *ptr, size_t size, size_t seed) +{ + const unsigned char *buf = (const unsigned char*)ptr; + const size_t m = 0x5bd1e995; + size_t hash = size ^ seed; + for (; size >= 4; buf += 4, size -= 4) { + size_t k = *((IUINT32*)buf); + k *= m; + k = (k >> 24) * m; + hash = (hash * m) ^ k; + } + switch (size) { + case 3: hash ^= ((IUINT32)buf[2]) << 16; + case 2: hash ^= ((IUINT32)buf[1]) << 8; + case 1: hash ^= ((IUINT32)buf[0]); hash = hash * m; break; + } + hash = (hash ^ (hash >> 13)) * m; + return hash ^ (hash >> 15); +} + +size_t ib_hash_bytes_lua(const void *ptr, size_t size, size_t seed) +{ + const unsigned char *name = (const unsigned char*)ptr; + size_t step = (size >> 5) + 1; + size_t h = size ^ seed, i; + for(i = size; i >= step; i -= step) + h = h ^ ((h << 5) + (h >> 2) + (size_t)name[i - 1]); + return h; +} + +size_t ib_hash_func_str(const void *key) +{ + ib_string *str = (ib_string*)key; +#ifndef IB_HASH_BYTES_STL + return ib_hash_bytes_lua(str->ptr, str->size, ib_hash_seed); +#else + return ib_hash_bytes_stl(str->ptr, str->size, ib_hash_seed); +#endif +} + +size_t ib_hash_func_cstr(const void *key) +{ + const char *str = (const char*)key; + size_t size = strlen(str); +#ifndef IB_HASH_BYTES_STL + return ib_hash_bytes_lua(str, size, ib_hash_seed); +#else + return ib_hash_bytes_stl(str, size, ib_hash_seed); +#endif +} + +int ib_hash_compare_uint(const void *key1, const void *key2) +{ + size_t x = (size_t)key1; + size_t y = (size_t)key2; + if (x == y) return 0; + return (x < y)? -1 : 1; +} + +int ib_hash_compare_int(const void *key1, const void *key2) +{ + ilong x = (ilong)key1; + ilong y = (ilong)key2; + if (x == y) return 0; + return (x < y)? -1 : 1; +} + +int ib_hash_compare_str(const void *key1, const void *key2) +{ + return ib_string_compare((const ib_string*)key1, (const ib_string*)key2); +} + +int ib_compare_bytes(const void *p1, size_t s1, const void *p2, size_t s2) +{ + size_t minsize = (s1 < s2)? s1 : s2; + int hr = memcmp(p1, p2, minsize); + if (hr == 0) { + if (s1 == s2) return 0; + return (s1 < s2)? -1 : 1; + } + else { + return (hr < 0)? -1 : 1; + } +} + +int ib_hash_compare_cstr(const void *key1, const void *key2) +{ + const char *x = (const char*)key1; + const char *y = (const char*)key2; + return ib_compare_bytes(x, strlen(x), y, strlen(y)); +} + + + +struct ib_hash_entry *ib_map_find_uint(struct ib_hash_map *hm, iulong key) +{ + struct ib_hash_entry *hr; + void *kk = (void*)key; + ib_map_search(hm, kk, ib_hash_func_uint, ib_hash_compare_uint, hr); + return hr; +} + +struct ib_hash_entry *ib_map_find_int(struct ib_hash_map *hm, ilong key) +{ + struct ib_hash_entry *hr; + void *kk = (void*)key; + ib_map_search(hm, kk, ib_hash_func_int, ib_hash_compare_int, hr); + return hr; +} + +struct ib_hash_entry *ib_map_find_str(struct ib_hash_map *hm, const ib_string *key) +{ + struct ib_hash_entry *hr; + void *kk = (void*)key; + ib_map_search(hm, kk, ib_hash_func_str, ib_hash_compare_str, hr); + return hr; +} + +struct ib_hash_entry *ib_map_find_cstr(struct ib_hash_map *hm, const char *key) +{ + struct ib_hash_entry *hr; + void *kk = (void*)key; + ib_map_search(hm, kk, ib_hash_func_cstr, ib_hash_compare_cstr, hr); + return hr; +} + + + + diff --git a/czmod/imembase.h b/czmod/imembase.h new file mode 100644 index 0000000..811b177 --- /dev/null +++ b/czmod/imembase.h @@ -0,0 +1,916 @@ +/********************************************************************** + * + * imembase.h - basic interface of memory operation + * skywind3000 (at) gmail.com, 2006-2016 + * + **********************************************************************/ + +#ifndef __IMEMBASE_H__ +#define __IMEMBASE_H__ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + + +/********************************************************************** + * 32BIT INTEGER DEFINITION + **********************************************************************/ +#ifndef __INTEGER_32_BITS__ +#define __INTEGER_32_BITS__ +#if defined(__UINT32_TYPE__) && defined(__UINT32_TYPE__) + typedef __UINT32_TYPE__ ISTDUINT32; + typedef __INT32_TYPE__ ISTDINT32; +#elif defined(__UINT_FAST32_TYPE__) && defined(__INT_FAST32_TYPE__) + typedef __UINT_FAST32_TYPE__ ISTDUINT32; + typedef __INT_FAST32_TYPE__ ISTDINT32; +#elif defined(_WIN64) || defined(WIN64) || defined(__amd64__) || \ + defined(__x86_64) || defined(__x86_64__) || defined(_M_IA64) || \ + defined(_M_AMD64) + typedef unsigned int ISTDUINT32; + typedef int ISTDINT32; +#elif defined(_WIN32) || defined(WIN32) || defined(__i386__) || \ + defined(__i386) || defined(_M_X86) + typedef unsigned long ISTDUINT32; + typedef long ISTDINT32; +#elif defined(__MACOS__) + typedef UInt32 ISTDUINT32; + typedef SInt32 ISTDINT32; +#elif defined(__APPLE__) && defined(__MACH__) + #include + typedef u_int32_t ISTDUINT32; + typedef int32_t ISTDINT32; +#elif defined(__BEOS__) + #include + typedef u_int32_t ISTDUINT32; + typedef int32_t ISTDINT32; +#elif (defined(_MSC_VER) || defined(__BORLANDC__)) && (!defined(__MSDOS__)) + typedef unsigned __int32 ISTDUINT32; + typedef __int32 ISTDINT32; +#elif defined(__GNUC__) && (__GNUC__ > 3) + #include + typedef uint32_t ISTDUINT32; + typedef int32_t ISTDINT32; +#else +#include +#if UINT_MAX == 0xFFFFU + typedef unsigned long ISTDUINT32; + typedef long ISTDINT32; +#else + typedef unsigned int ISTDUINT32; + typedef int ISTDINT32; +#endif +#endif +#endif + + +/********************************************************************** + * Global Macros + **********************************************************************/ +#ifndef __IUINT8_DEFINED +#define __IUINT8_DEFINED +typedef unsigned char IUINT8; +#endif + +#ifndef __IINT8_DEFINED +#define __IINT8_DEFINED +typedef signed char IINT8; +#endif + +#ifndef __IUINT16_DEFINED +#define __IUINT16_DEFINED +typedef unsigned short IUINT16; +#endif + +#ifndef __IINT16_DEFINED +#define __IINT16_DEFINED +typedef signed short IINT16; +#endif + +#ifndef __IINT32_DEFINED +#define __IINT32_DEFINED +typedef ISTDINT32 IINT32; +#endif + +#ifndef __IUINT32_DEFINED +#define __IUINT32_DEFINED +typedef ISTDUINT32 IUINT32; +#endif + + +/*--------------------------------------------------------------------*/ +/* INLINE */ +/*--------------------------------------------------------------------*/ +#ifndef INLINE +#if defined(__GNUC__) + +#if (__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 1)) +#define INLINE __inline__ __attribute__((always_inline)) +#else +#define INLINE __inline__ +#endif + +#elif (defined(_MSC_VER) || defined(__WATCOMC__)) +#define INLINE __inline +#else +#define INLINE +#endif +#endif + +#if (!defined(__cplusplus)) && (!defined(inline)) +#define inline INLINE +#endif + +/* you can change this by config.h or predefined macro */ +#ifndef ASSERTION +#define ASSERTION(x) ((void)0) +#endif + + +/*====================================================================*/ +/* IULONG/ILONG (ensure sizeof(iulong) == sizeof(void*)) */ +/*====================================================================*/ +#ifndef __IULONG_DEFINED +#define __IULONG_DEFINED +typedef ptrdiff_t ilong; +typedef size_t iulong; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + + +/*====================================================================*/ +/* IALLOCATOR */ +/*====================================================================*/ +struct IALLOCATOR +{ + void *(*alloc)(struct IALLOCATOR *, size_t); + void (*free)(struct IALLOCATOR *, void *); + void *(*realloc)(struct IALLOCATOR *, void *, size_t); + void *udata; +}; + +void* internal_malloc(struct IALLOCATOR *allocator, size_t size); +void internal_free(struct IALLOCATOR *allocator, void *ptr); +void* internal_realloc(struct IALLOCATOR *allocator, void *ptr, size_t size); + + +/*====================================================================*/ +/* IKMEM INTERFACE */ +/*====================================================================*/ +extern struct IALLOCATOR *ikmem_allocator; + +void* ikmem_malloc(size_t size); +void* ikmem_realloc(void *ptr, size_t size); +void ikmem_free(void *ptr); + + +/*====================================================================*/ +/* IVECTOR */ +/*====================================================================*/ +struct IVECTOR +{ + unsigned char *data; + size_t size; + size_t capacity; + struct IALLOCATOR *allocator; +}; + +void iv_init(struct IVECTOR *v, struct IALLOCATOR *allocator); +void iv_destroy(struct IVECTOR *v); +int iv_resize(struct IVECTOR *v, size_t newsize); +int iv_reserve(struct IVECTOR *v, size_t newsize); + +size_t iv_pop(struct IVECTOR *v, void *data, size_t size); +int iv_push(struct IVECTOR *v, const void *data, size_t size); +int iv_insert(struct IVECTOR *v, size_t pos, const void *data, size_t size); +int iv_erase(struct IVECTOR *v, size_t pos, size_t size); + +#define iv_size(v) ((v)->size) +#define iv_data(v) ((v)->data) + +#define iv_entry(v, type) ((type*)iv_data(v)) + +#define iv_obj_index(v, type, index) (iv_entry(v, type)[index]) +#define iv_obj_push(v, type, objptr) iv_push(v, objptr, sizeof(type)) +#define iv_obj_pop(v, type, objptr) iv_pop(v, objptr, sizeof(type)) +#define iv_obj_size(v, type) (((v)->size) / sizeof(type)) +#define iv_obj_capacity(v, type) (((v)->capacity) / sizeof(type)) +#define iv_obj_resize(v, type, count) iv_resize(v, (count) * sizeof(type)) +#define iv_obj_reserve(v, type, count) iv_reserve(v, (count) * sizeof(type)) + +#define iv_obj_insert(v, type, pos, objptr) \ + iv_insert(v, (pos) * sizeof(type), objptr, sizeof(type)) + +#define iv_obj_erase(v, type, pos, count) \ + iv_erase(v, (pos) * sizeof(type), (count) * sizeof(type)) + + +#define IROUND_SIZE(b) (((size_t)1) << (b)) +#define IROUND_UP(s, n) (((s) + (n) - 1) & ~(((size_t)(n)) - 1)) + + +/*====================================================================*/ +/* IMEMNODE */ +/*====================================================================*/ +struct IMEMNODE +{ + struct IALLOCATOR *allocator; /* memory allocator */ + + struct IVECTOR vprev; /* prev node link vector */ + struct IVECTOR vnext; /* next node link vector */ + struct IVECTOR vnode; /* node information data */ + struct IVECTOR vdata; /* node data buffer vector */ + struct IVECTOR vmode; /* mode of allocation */ + ilong *mprev; /* prev node array */ + ilong *mnext; /* next node array */ + ilong *mnode; /* node info array */ + void **mdata; /* node data array */ + ilong *mmode; /* node mode array */ + ilong *extra; /* extra user data */ + ilong node_free; /* number of free nodes */ + ilong node_used; /* number of allocated */ + ilong node_max; /* number of all nodes */ + ilong grow_limit; /* limit of growing */ + + ilong node_size; /* node data fixed size */ + ilong node_shift; /* node data size shift */ + + struct IVECTOR vmem; /* mem-pages in the pool */ + char **mmem; /* mem-pages array */ + ilong mem_max; /* max num of memory pages */ + ilong mem_count; /* number of mem-pages */ + + ilong list_open; /* the entry of open-list */ + ilong list_close; /* the entry of close-list */ + ilong total_mem; /* total memory size */ +}; + + +void imnode_init(struct IMEMNODE *mn, ilong nodesize, struct IALLOCATOR *ac); +void imnode_destroy(struct IMEMNODE *mnode); +ilong imnode_new(struct IMEMNODE *mnode); +void imnode_del(struct IMEMNODE *mnode, ilong index); +ilong imnode_head(const struct IMEMNODE *mnode); +ilong imnode_next(const struct IMEMNODE *mnode, ilong index); +ilong imnode_prev(const struct IMEMNODE *mnode, ilong index); +void*imnode_data(struct IMEMNODE *mnode, ilong index); +const void* imnode_data_const(const struct IMEMNODE *mnode, ilong index); + +#define IMNODE_NODE(mnodeptr, i) ((mnodeptr)->mnode[i]) +#define IMNODE_PREV(mnodeptr, i) ((mnodeptr)->mprev[i]) +#define IMNODE_NEXT(mnodeptr, i) ((mnodeptr)->mnext[i]) +#define IMNODE_DATA(mnodeptr, i) ((mnodeptr)->mdata[i]) +#define IMNODE_MODE(mnodeptr, i) ((mnodeptr)->mmode[i]) + + +/*====================================================================*/ +/* LIST DEFINITION */ +/*====================================================================*/ +#ifndef __ILIST_DEF__ +#define __ILIST_DEF__ + +struct ILISTHEAD { + struct ILISTHEAD *next, *prev; +}; + +typedef struct ILISTHEAD ilist_head; + + +/*--------------------------------------------------------------------*/ +/* list init */ +/*--------------------------------------------------------------------*/ +#define ILIST_HEAD_INIT(name) { &(name), &(name) } +#define ILIST_HEAD(name) \ + struct ILISTHEAD name = ILIST_HEAD_INIT(name) + +#define ILIST_INIT(ptr) ( \ + (ptr)->next = (ptr), (ptr)->prev = (ptr)) + +#define IOFFSETOF(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) + +#define ICONTAINEROF(ptr, type, member) ( \ + (type*)( ((char*)((type*)ptr)) - IOFFSETOF(type, member)) ) + +#define ILIST_ENTRY(ptr, type, member) ICONTAINEROF(ptr, type, member) + + +/*--------------------------------------------------------------------*/ +/* list operation */ +/*--------------------------------------------------------------------*/ +#define ILIST_ADD(node, head) ( \ + (node)->prev = (head), (node)->next = (head)->next, \ + (head)->next->prev = (node), (head)->next = (node)) + +#define ILIST_ADD_TAIL(node, head) ( \ + (node)->prev = (head)->prev, (node)->next = (head), \ + (head)->prev->next = (node), (head)->prev = (node)) + +#define ILIST_DEL_BETWEEN(p, n) ((n)->prev = (p), (p)->next = (n)) + +#define ILIST_DEL(entry) (\ + (entry)->next->prev = (entry)->prev, \ + (entry)->prev->next = (entry)->next, \ + (entry)->next = 0, (entry)->prev = 0) + +#define ILIST_DEL_INIT(entry) do { \ + ILIST_DEL(entry); ILIST_INIT(entry); } while (0) + +#define ILIST_IS_EMPTY(entry) ((entry) == (entry)->next) + +#define ilist_init ILIST_INIT +#define ilist_entry ILIST_ENTRY +#define ilist_add ILIST_ADD +#define ilist_add_tail ILIST_ADD_TAIL +#define ilist_del ILIST_DEL +#define ilist_del_init ILIST_DEL_INIT +#define ilist_is_empty ILIST_IS_EMPTY + +#define ILIST_FOREACH(iterator, head, TYPE, MEMBER) \ + for ((iterator) = ilist_entry((head)->next, TYPE, MEMBER); \ + &((iterator)->MEMBER) != (head); \ + (iterator) = ilist_entry((iterator)->MEMBER.next, TYPE, MEMBER)) + +#define ilist_foreach(iterator, head, TYPE, MEMBER) \ + ILIST_FOREACH(iterator, head, TYPE, MEMBER) + +#define ilist_foreach_entry(pos, head) \ + for( (pos) = (head)->next; (pos) != (head) ; (pos) = (pos)->next ) + + +#define __ilist_splice(list, head) do { \ + ilist_head *first = (list)->next, *last = (list)->prev; \ + ilist_head *at = (head)->next; \ + (first)->prev = (head), (head)->next = (first); \ + (last)->next = (at), (at)->prev = (last); } while (0) + +#define ilist_splice(list, head) do { \ + if (!ilist_is_empty(list)) __ilist_splice(list, head); } while (0) + +#define ilist_splice_init(list, head) do { \ + ilist_splice(list, head); ilist_init(list); } while (0) + +#define ilist_replace(oldnode, newnode) ( \ + (newnode)->next = (oldnode)->next, \ + (newnode)->next->prev = (newnode), \ + (newnode)->prev = (oldnode)->prev, \ + (newnode)->prev->next = (newnode)) + +#ifdef _MSC_VER +#pragma warning(disable:4311) +#pragma warning(disable:4312) +#pragma warning(disable:4996) +#endif + +#endif + + +/*====================================================================*/ +/* IMUTEX - mutex interfaces */ +/*====================================================================*/ +#ifndef IMUTEX_TYPE + +#ifndef IMUTEX_DISABLE +#if (defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64)) +#if ((!defined(_M_PPC)) && (!defined(_M_PPC_BE)) && (!defined(_XBOX))) +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0500 +#endif +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#include +#else +#ifndef _XBOX +#define _XBOX +#endif +#include +#endif + +#define IMUTEX_TYPE CRITICAL_SECTION +#define IMUTEX_INIT(m) InitializeCriticalSection((CRITICAL_SECTION*)(m)) +#define IMUTEX_DESTROY(m) DeleteCriticalSection((CRITICAL_SECTION*)(m)) +#define IMUTEX_LOCK(m) EnterCriticalSection((CRITICAL_SECTION*)(m)) +#define IMUTEX_UNLOCK(m) LeaveCriticalSection((CRITICAL_SECTION*)(m)) + +#elif defined(__unix) || defined(__unix__) || defined(__MACH__) +#include +#include +#define IMUTEX_TYPE pthread_mutex_t +#define IMUTEX_INIT(m) pthread_mutex_init((pthread_mutex_t*)(m), 0) +#define IMUTEX_DESTROY(m) pthread_mutex_destroy((pthread_mutex_t*)(m)) +#define IMUTEX_LOCK(m) pthread_mutex_lock((pthread_mutex_t*)(m)) +#define IMUTEX_UNLOCK(m) pthread_mutex_unlock((pthread_mutex_t*)(m)) +#endif +#endif + +#ifndef IMUTEX_TYPE +#define IMUTEX_TYPE int +#define IMUTEX_INIT(m) { (*(m)) = (*(m)); } +#define IMUTEX_DESTROY(m) { (*(m)) = (*(m)); } +#define IMUTEX_LOCK(m) { (*(m)) = (*(m)); } +#define IMUTEX_UNLOCK(m) { (*(m)) = (*(m)); } +#endif + +#endif + + + +/*====================================================================*/ +/* IVECTOR / IMEMNODE MANAGEMENT */ +/*====================================================================*/ + +typedef struct IVECTOR ib_vector; +typedef struct IMEMNODE ib_memnode; + +ib_vector *iv_create(void); +void iv_delete(ib_vector *vec); + +ib_memnode *imnode_create(ilong nodesize, int grow_limit); +void imnode_delete(ib_memnode *); + + +/*--------------------------------------------------------------------*/ +/* Collection - Array */ +/*--------------------------------------------------------------------*/ + +struct ib_array; +typedef struct ib_array ib_array; + +ib_array *ib_array_new(void (*destroy_func)(void*)); +void ib_array_delete(ib_array *array); +void ib_array_reserve(ib_array *array, size_t new_size); +size_t ib_array_size(const ib_array *array); +void** ib_array_ptr(ib_array *array); +void* ib_array_index(ib_array *array, size_t index); +const void* ib_array_const_index(const ib_array *array, size_t index); +void ib_array_push(ib_array *array, void *item); +void ib_array_push_left(ib_array *array, void *item); +void ib_array_replace(ib_array *array, size_t index, void *item); +void* ib_array_pop(ib_array *array); +void* ib_array_pop_left(ib_array *array); +void ib_array_remove(ib_array *array, size_t index); +void ib_array_insert_before(ib_array *array, size_t index, void *item); +void* ib_array_pop_at(ib_array *array, size_t index); +void ib_array_for_each(ib_array *array, void (*iterator)(void *item)); + +void ib_array_sort(ib_array *array, + int (*compare)(const void*, const void*)); + +ilong ib_array_search(const ib_array *array, + int (*compare)(const void*, const void*), + const void *item, + ilong start_pos); + +ilong ib_array_bsearch(const ib_array *array, + int (*compare)(const void*, const void*), + const void *item); + + +/*====================================================================*/ +/* ib_node - binary search tree (can be used in rbtree & avl) */ +/* color/balance won't be packed (can work without alignment) */ +/*====================================================================*/ +struct ib_node +{ + struct ib_node *left; /* left child */ + struct ib_node *right; /* right child */ + struct ib_node *parent; /* pointing to node itself for empty node */ + int height; /* equals to 1 + max height in childs */ +}; + +struct ib_root +{ + struct ib_node *node; /* root node */ +}; + + +/*--------------------------------------------------------------------*/ +/* NODE MACROS */ +/*--------------------------------------------------------------------*/ +#define IB_OFFSET(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) + +#define IB_NODE2DATA(n, o) ((void *)((size_t)(n) - (o))) +#define IB_DATA2NODE(d, o) ((struct ib_node*)((size_t)(d) + (o))) + +#define IB_ENTRY(ptr, type, member) \ + ((type*)IB_NODE2DATA(ptr, IB_OFFSET(type, member))) + +#define ib_node_init(node) do { ((node)->parent) = (node); } while (0) +#define ib_node_empty(node) ((node)->parent == (node)) + +#define IB_LEFT_HEIGHT(node) (((node)->left)? ((node)->left)->height : 0) +#define IB_RIGHT_HEIGHT(node) (((node)->right)? ((node)->right)->height : 0) + + +/*--------------------------------------------------------------------*/ +/* binary search tree - node manipulation */ +/*--------------------------------------------------------------------*/ +struct ib_node *ib_node_first(struct ib_root *root); +struct ib_node *ib_node_last(struct ib_root *root); +struct ib_node *ib_node_next(struct ib_node *node); +struct ib_node *ib_node_prev(struct ib_node *node); + +void ib_node_replace(struct ib_node *victim, struct ib_node *newnode, + struct ib_root *root); + +static inline void ib_node_link(struct ib_node *node, struct ib_node *parent, + struct ib_node **ib_link) { + node->parent = parent; + node->height = 1; + node->left = node->right = NULL; + ib_link[0] = node; +} + + +/* avl insert rebalance and erase */ +void ib_node_post_insert(struct ib_node *node, struct ib_root *root); +void ib_node_erase(struct ib_node *node, struct ib_root *root); + +/* avl nodes destroy: fast tear down the whole tree */ +struct ib_node* ib_node_tear(struct ib_root *root, struct ib_node **next); + + +/*--------------------------------------------------------------------*/ +/* avl - node templates */ +/*--------------------------------------------------------------------*/ +#define ib_node_find(root, what, compare_fn, res_node) do {\ + struct ib_node *__n = (root)->node; \ + (res_node) = NULL; \ + while (__n) { \ + int __hr = (compare_fn)(what, __n); \ + if (__hr == 0) { (res_node) = __n; break; } \ + else if (__hr < 0) { __n = __n->left; } \ + else { __n = __n->right; } \ + } \ + } while (0) + + +#define ib_node_add(root, newnode, compare_fn, duplicate_node) do { \ + struct ib_node **__link = &((root)->node); \ + struct ib_node *__parent = NULL; \ + struct ib_node *__duplicate = NULL; \ + int __hr = 1; \ + while (__link[0]) { \ + __parent = __link[0]; \ + __hr = (compare_fn)(newnode, __parent); \ + if (__hr == 0) { __duplicate = __parent; break; } \ + else if (__hr < 0) { __link = &(__parent->left); } \ + else { __link = &(__parent->right); } \ + } \ + (duplicate_node) = __duplicate; \ + if (__duplicate == NULL) { \ + ib_node_link(newnode, __parent, __link); \ + ib_node_post_insert(newnode, root); \ + } \ + } while (0) + + +/*--------------------------------------------------------------------*/ +/* avltree - friendly interface */ +/*--------------------------------------------------------------------*/ +struct ib_tree +{ + struct ib_root root; /* avl root */ + size_t offset; /* node offset in user data structure */ + size_t size; /* size of user data structure */ + size_t count; /* node count */ + /* returns 0 for equal, -1 for n1 < n2, 1 for n1 > n2 */ + int (*compare)(const void *n1, const void *n2); +}; + + +/* initialize avltree, use IB_OFFSET(type, member) for "offset" + * eg: + * ib_tree_init(&mytree, mystruct_compare, + * sizeof(struct mystruct_t), + * IB_OFFSET(struct mystruct_t, node)); + */ +void ib_tree_init(struct ib_tree *tree, + int (*compare)(const void*, const void*), size_t size, size_t offset); + +void *ib_tree_first(struct ib_tree *tree); +void *ib_tree_last(struct ib_tree *tree); +void *ib_tree_next(struct ib_tree *tree, void *data); +void *ib_tree_prev(struct ib_tree *tree, void *data); + +/* require a temporary user structure (data) which contains the key */ +void *ib_tree_find(struct ib_tree *tree, const void *data); +void *ib_tree_nearest(struct ib_tree *tree, const void *data); + +/* returns NULL for success, otherwise returns conflict node with same key */ +void *ib_tree_add(struct ib_tree *tree, void *data); + +void ib_tree_remove(struct ib_tree *tree, void *data); +void ib_tree_replace(struct ib_tree *tree, void *victim, void *newdata); + +void ib_tree_clear(struct ib_tree *tree, void (*destroy)(void *data)); + + +/*--------------------------------------------------------------------*/ +/* fastbin - fixed size object allocator */ +/*--------------------------------------------------------------------*/ +struct ib_fastbin +{ + size_t obj_size; + size_t page_size; + size_t maximum; + char *start; + char *endup; + void *next; + void *pages; +}; + + +#define IB_NEXT(ptr) (((void**)(ptr))[0]) + +void ib_fastbin_init(struct ib_fastbin *fb, size_t obj_size); +void ib_fastbin_destroy(struct ib_fastbin *fb); + +void* ib_fastbin_new(struct ib_fastbin *fb); +void ib_fastbin_del(struct ib_fastbin *fb, void *ptr); + + +/*--------------------------------------------------------------------*/ +/* string */ +/*--------------------------------------------------------------------*/ +struct ib_string; +typedef struct ib_string ib_string; + +#ifndef IB_STRING_SSO +#define IB_STRING_SSO 14 +#endif + +struct ib_string +{ + char *ptr; + int size; + int capacity; + char sso[IB_STRING_SSO + 2]; +}; + +#define ib_string_ptr(str) ((str)->ptr) +#define ib_string_size(str) ((str)->size) + +ib_string* ib_string_new(void); +ib_string* ib_string_new_from(const char *text); +ib_string* ib_string_new_size(const char *text, int size); + +void ib_string_delete(ib_string *str); + +ib_string* ib_string_resize(ib_string *str, int newsize); + +ib_string* ib_string_assign(ib_string *str, const char *src); +ib_string* ib_string_assign_size(ib_string *str, const char *src, int size); + +ib_string* ib_string_erase(ib_string *str, int pos, int size); +ib_string* ib_string_insert(ib_string *str, int pos, + const void *data, int size); + +ib_string* ib_string_append(ib_string *str, const char *src); +ib_string* ib_string_append_size(ib_string *str, const char *src, int size); +ib_string* ib_string_append_c(ib_string *str, char c); + +ib_string* ib_string_prepend(ib_string *str, const char *src); +ib_string* ib_string_prepend_size(ib_string *str, const char *src, int size); +ib_string* ib_string_prepend_c(ib_string *str, char c); + +ib_string* ib_string_rewrite(ib_string *str, int pos, const char *src); +ib_string* ib_string_rewrite_size(ib_string *str, int pos, + const char *src, int size); + +int ib_string_compare(const struct ib_string *a, const struct ib_string *b); + +int ib_string_find(const ib_string *str, const char *src, int len, int start); +int ib_string_find_c(const ib_string *str, char ch, int start); + +ib_array* ib_string_split(const ib_string *str, const char *sep, int len); +ib_array* ib_string_split_c(const ib_string *str, char sep); + +ib_string* ib_string_strip(ib_string *str, const char *seps); + + +/*--------------------------------------------------------------------*/ +/* static hash table (closed hash table with avlnode) */ +/*--------------------------------------------------------------------*/ +struct ib_hash_node +{ + struct ib_node avlnode; + void *key; + size_t hash; +}; + +struct ib_hash_index +{ + struct ILISTHEAD node; + struct ib_root avlroot; +}; + +#define IB_HASH_INIT_SIZE 8 + +struct ib_hash_table +{ + size_t count; + size_t index_size; + size_t index_mask; + size_t (*hash)(const void *key); + int (*compare)(const void *key1, const void *key2); + struct ILISTHEAD head; + struct ib_hash_index *index; + struct ib_hash_index init[IB_HASH_INIT_SIZE]; +}; + + +void ib_hash_init(struct ib_hash_table *ht, + size_t (*hash)(const void *key), + int (*compare)(const void *key1, const void *key2)); + +struct ib_hash_node* ib_hash_node_first(struct ib_hash_table *ht); +struct ib_hash_node* ib_hash_node_last(struct ib_hash_table *ht); + +struct ib_hash_node* ib_hash_node_next(struct ib_hash_table *ht, + struct ib_hash_node *node); + +struct ib_hash_node* ib_hash_node_prev(struct ib_hash_table *ht, + struct ib_hash_node *node); + +static inline void ib_hash_node_key(struct ib_hash_table *ht, + struct ib_hash_node *node, void *key) { + node->key = key; + node->hash = ht->hash(key); +} + +struct ib_hash_node* ib_hash_find(struct ib_hash_table *ht, + const struct ib_hash_node *node); + +struct ib_node** ib_hash_track(struct ib_hash_table *ht, + const struct ib_hash_node *node, struct ib_node **parent); + +struct ib_hash_node* ib_hash_add(struct ib_hash_table *ht, + struct ib_hash_node *node); + +void ib_hash_erase(struct ib_hash_table *ht, struct ib_hash_node *node); + +void ib_hash_replace(struct ib_hash_table *ht, + struct ib_hash_node *victim, struct ib_hash_node *newnode); + +void ib_hash_clear(struct ib_hash_table *ht, + void (*destroy)(struct ib_hash_node *node)); + +/* re-index nbytes must be: sizeof(struct ib_hash_index) * n */ +void* ib_hash_swap(struct ib_hash_table *ht, void *index, size_t nbytes); + + +/*--------------------------------------------------------------------*/ +/* fast inline search, compare function will be expanded inline here */ +/*--------------------------------------------------------------------*/ +#define ib_hash_search(ht, srcnode, result, compare) do { \ + size_t __hash = (srcnode)->hash; \ + const void *__key = (srcnode)->key; \ + struct ib_hash_index *__index = \ + &((ht)->index[__hash & ((ht)->index_mask)]); \ + struct ib_node *__anode = __index->avlroot.node; \ + (result) = NULL; \ + while (__anode) { \ + struct ib_hash_node *__snode = \ + IB_ENTRY(__anode, struct ib_hash_node, avlnode); \ + size_t __shash = __snode->hash; \ + if (__hash == __shash) { \ + int __hc = (compare)(__key, __snode->key); \ + if (__hc == 0) { (result) = __snode; break; } \ + __anode = (__hc < 0)? __anode->left : __anode->right; \ + } else { \ + __anode = (__hash < __shash)? __anode->left:__anode->right;\ + } \ + } \ + } while (0) + + +/*--------------------------------------------------------------------*/ +/* hash map, wrapper of ib_hash_table to support direct key/value */ +/*--------------------------------------------------------------------*/ +struct ib_hash_entry +{ + struct ib_hash_node node; + void *value; +}; + +struct ib_hash_map +{ + size_t count; + int insert; + int fixed; + int builtin; + void* (*key_copy)(void *key); + void (*key_destroy)(void *key); + void* (*value_copy)(void *value); + void (*value_destroy)(void *value); + struct ib_fastbin fb; + struct ib_hash_table ht; +}; + + +#define ib_hash_key(entry) ((entry)->node.key) +#define ib_hash_value(entry) ((entry)->value) + +void ib_map_init(struct ib_hash_map *hm, size_t (*hash)(const void*), + int (*compare)(const void *, const void *)); + +void ib_map_destroy(struct ib_hash_map *hm); + +struct ib_hash_entry* ib_map_first(struct ib_hash_map *hm); +struct ib_hash_entry* ib_map_last(struct ib_hash_map *hm); + +struct ib_hash_entry* ib_map_next(struct ib_hash_map *hm, + struct ib_hash_entry *n); +struct ib_hash_entry* ib_map_prev(struct ib_hash_map *hm, + struct ib_hash_entry *n); + +struct ib_hash_entry* ib_map_find(struct ib_hash_map *hm, const void *key); +void* ib_map_lookup(struct ib_hash_map *hm, const void *key, void *defval); + + +struct ib_hash_entry* ib_map_add(struct ib_hash_map *hm, + void *key, void *value, int *success); + +struct ib_hash_entry* ib_map_set(struct ib_hash_map *hm, + void *key, void *value); + +void* ib_map_get(struct ib_hash_map *hm, const void *key); + +void ib_map_erase(struct ib_hash_map *hm, struct ib_hash_entry *entry); + + +/* returns 0 for success, -1 for key mismatch */ +int ib_map_remove(struct ib_hash_map *hm, const void *key); + +void ib_map_clear(struct ib_hash_map *hm); + + +/*--------------------------------------------------------------------*/ +/* fast inline search template */ +/*--------------------------------------------------------------------*/ + +#define ib_map_search(hm, srckey, hash_func, cmp_func, result) do { \ + size_t __hash = (hash_func)(srckey); \ + struct ib_hash_index *__index = \ + &((hm)->ht.index[__hash & ((hm)->ht.index_mask)]); \ + struct ib_node *__anode = __index->avlroot.node; \ + (result) = NULL; \ + while (__anode) { \ + struct ib_hash_node *__snode = \ + IB_ENTRY(__anode, struct ib_hash_node, avlnode); \ + size_t __shash = __snode->hash; \ + if (__hash == __shash) { \ + int __hc = (cmp_func)((srckey), __snode->key); \ + if (__hc == 0) { \ + (result) = IB_ENTRY(__snode, \ + struct ib_hash_entry, node);\ + break; \ + } \ + __anode = (__hc < 0)? __anode->left : __anode->right; \ + } else { \ + __anode = (__hash < __shash)? __anode->left:__anode->right;\ + } \ + } \ + } while (0) + + +/*--------------------------------------------------------------------*/ +/* common type hash */ +/*--------------------------------------------------------------------*/ +size_t ib_hash_func_uint(const void *key); +int ib_hash_compare_uint(const void *key1, const void *key2); + +size_t ib_hash_func_int(const void *key); +int ib_hash_compare_int(const void *key1, const void *key2); + +size_t ib_hash_func_str(const void *key); +int ib_hash_compare_str(const void *key1, const void *key2); + +size_t ib_hash_func_cstr(const void *key); +int ib_hash_compare_cstr(const void *key1, const void *key2); + + +struct ib_hash_entry *ib_map_find_uint(struct ib_hash_map *hm, iulong key); +struct ib_hash_entry *ib_map_find_int(struct ib_hash_map *hm, ilong key); +struct ib_hash_entry *ib_map_find_str(struct ib_hash_map *hm, const ib_string *key); +struct ib_hash_entry *ib_map_find_cstr(struct ib_hash_map *hm, const char *key); + + + +#ifdef __cplusplus +} +#endif + +#endif + + + + From b7c3fbc4ee7dd6e14556d816375ed223b28cb80e Mon Sep 17 00:00:00 2001 From: skywind3000 Date: Mon, 16 Mar 2020 22:44:24 +0800 Subject: [PATCH 05/12] update new imembase.c --- czmod/imembase.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/czmod/imembase.c b/czmod/imembase.c index 182a115..f6b5b28 100644 --- a/czmod/imembase.c +++ b/czmod/imembase.c @@ -531,11 +531,6 @@ ib_array *ib_array_new(void (*destroy_func)(void*)) void ib_array_delete(ib_array *array) -{ - array->items = (void**)array->vec.data; -} - -void ib_array_release(ib_array *array) { if (array->fn_destroy) { size_t n = array->size; From 93e9715e7d64f500021a758b891a61fef5053b46 Mon Sep 17 00:00:00 2001 From: skywind3000 Date: Mon, 16 Mar 2020 23:11:09 +0800 Subject: [PATCH 06/12] commit new iposix.c/.h --- czmod/iposix.c | 1059 ++++++++++++++++++++++++++++++++++++++++++++++++ czmod/iposix.h | 401 ++++++++++++++++++ 2 files changed, 1460 insertions(+) create mode 100644 czmod/iposix.c create mode 100644 czmod/iposix.h diff --git a/czmod/iposix.c b/czmod/iposix.c new file mode 100644 index 0000000..d94fb83 --- /dev/null +++ b/czmod/iposix.c @@ -0,0 +1,1059 @@ +//===================================================================== +// +// iposix.c - posix file system accessing +// +// NOTE: +// for more information, please see the readme file. +// +//===================================================================== + +#include "iposix.h" + +#ifndef IDISABLE_FILE_SYSTEM_ACCESS +//--------------------------------------------------------------------- +// Global Definition +//--------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) +#include +#endif + +#ifdef _WIN32 +#include +#include +#include +#define ISYSNAME 'w' +#else +#ifndef __unix +#define __unix +#endif +#define ISYSNAME 'u' +#endif + + + +//--------------------------------------------------------------------- +// Posix Stat +//--------------------------------------------------------------------- +#ifdef __unix +typedef struct stat iposix_ostat_t; +#define iposix_stat_proc stat +#define iposix_lstat_proc lstat +#define iposix_fstat_proc fstat +#else +typedef struct _stat iposix_ostat_t; +#define iposix_stat_proc _stat +#define iposix_lstat_proc _stat +#define iposix_fstat_proc _fstat +#endif + + +#if defined(_WIN32) || defined(WIN32) || defined(_WIN64) || defined(WIN64) + #if defined(_S_IFMT) && (!defined(S_IFMT)) + #define S_IFMT _S_IFMT + #endif + + #if defined(_S_IFDIR) && (!defined(S_IFDIR)) + #define S_IFDIR _S_IFDIR + #endif + + #if defined(_S_IFCHR) && (!defined(S_IFCHR)) + #define S_IFCHR _S_IFCHR + #endif + + #if defined(_S_IFIFO) && (!defined(S_IFIFO)) + #define S_IFIFO _S_IFIFO + #endif + + #if defined(_S_IFREG) && (!defined(S_IFREG)) + #define S_IFREG _S_IFREG + #endif + + #if defined(_S_IREAD) && (!defined(S_IREAD)) + #define S_IREAD _S_IREAD + #endif + + #if defined(_S_IWRITE) && (!defined(S_IWRITE)) + #define S_IWRITE _S_IWRITE + #endif + + #if defined(_S_IEXEC) && (!defined(S_IEXEC)) + #define S_IEXEC _S_IEXEC + #endif +#endif + +#define IX_FMT(m, t) (((m) & S_IFMT) == (t)) + + +// convert stat structure +void iposix_stat_convert(iposix_stat_t *ostat, const iposix_ostat_t *x) +{ + ostat->st_mode = 0; + + #ifdef S_IFDIR + if (IX_FMT(x->st_mode, S_IFDIR)) ostat->st_mode |= ISTAT_IFDIR; + #endif + #ifdef S_IFCHR + if (IX_FMT(x->st_mode, S_IFCHR)) ostat->st_mode |= ISTAT_IFCHR; + #endif + #ifdef S_IFBLK + if (IX_FMT(x->st_mode, S_IFBLK)) ostat->st_mode |= ISTAT_IFBLK; + #endif + #ifdef S_IFREG + if (IX_FMT(x->st_mode, S_IFREG)) ostat->st_mode |= ISTAT_IFREG; + #endif + #ifdef S_IFIFO + if (IX_FMT(x->st_mode, S_IFIFO)) ostat->st_mode |= ISTAT_IFIFO; + #endif + #ifdef S_IFLNK + if (IX_FMT(x->st_mode, S_IFLNK)) ostat->st_mode |= ISTAT_IFLNK; + #endif + #ifdef S_IFSOCK + if (IX_FMT(x->st_mode, S_IFSOCK)) ostat->st_mode |= ISTAT_IFSOCK; + #endif + #ifdef S_IFWHT + if (IX_FMT(x->st_mode, S_IFWHT)) ostat->st_mode |= ISTAT_IFWHT; + #endif + +#ifdef S_IREAD + if (x->st_mode & S_IREAD) ostat->st_mode |= ISTAT_IRUSR; +#endif + +#ifdef S_IWRITE + if (x->st_mode & S_IWRITE) ostat->st_mode |= ISTAT_IWUSR; +#endif + +#ifdef S_IEXEC + if (x->st_mode & S_IEXEC) ostat->st_mode |= ISTAT_IXUSR; +#endif + +#ifdef S_IRUSR + if (x->st_mode & S_IRUSR) ostat->st_mode |= ISTAT_IRUSR; + if (x->st_mode & S_IWUSR) ostat->st_mode |= ISTAT_IWUSR; + if (x->st_mode & S_IXUSR) ostat->st_mode |= ISTAT_IXUSR; +#endif + +#ifdef S_IRGRP + if (x->st_mode & S_IRGRP) ostat->st_mode |= ISTAT_IRGRP; + if (x->st_mode & S_IWGRP) ostat->st_mode |= ISTAT_IWGRP; + if (x->st_mode & S_IXGRP) ostat->st_mode |= ISTAT_IXGRP; +#endif + +#ifdef S_IROTH + if (x->st_mode & S_IROTH) ostat->st_mode |= ISTAT_IROTH; + if (x->st_mode & S_IWOTH) ostat->st_mode |= ISTAT_IWOTH; + if (x->st_mode & S_IXOTH) ostat->st_mode |= ISTAT_IXOTH; +#endif + + ostat->st_size = (IUINT64)x->st_size; + + ostat->atime = (IUINT32)x->st_atime; + ostat->mtime = (IUINT32)x->st_mtime; + ostat->ctime = (IUINT32)x->st_mtime; + + ostat->st_ino = (IUINT64)x->st_ino; + ostat->st_dev = (IUINT32)x->st_dev; + ostat->st_nlink = (IUINT32)x->st_nlink; + ostat->st_uid = (IUINT32)x->st_uid; + ostat->st_gid = (IUINT32)x->st_gid; + ostat->st_rdev = (IUINT32)x->st_rdev; + +#ifdef __unix +// #define IHAVE_STAT_ST_BLKSIZE +// #define IHAVE_STAT_ST_BLOCKS +// #define IHAVE_STAT_ST_FLAGS +#endif + +#if defined(__unix) + #ifdef IHAVE_STAT_ST_BLOCKS + ostat->st_blocks = (IUINT32)x->st_blocks; + #endif + #ifdef IHAVE_STAT_ST_BLKSIZE + ostat->st_blksize = (IUINT32)x->st_blksize; + #endif + #if !defined(__CYGWIN__) && defined(IHAVE_STAT_ST_FLAGS) + ostat->st_flags = (IUINT32)x->st_flags; + #endif +#endif +} + +// returns 0 for success, -1 for error +int iposix_stat_imp(const char *path, iposix_stat_t *ostat) +{ + iposix_ostat_t xstat; + int retval; + retval = iposix_stat_proc(path, &xstat); + if (retval != 0) return -1; + iposix_stat_convert(ostat, &xstat); + return 0; +} + +// returns 0 for success, -1 for error +int iposix_lstat_imp(const char *path, iposix_stat_t *ostat) +{ + iposix_ostat_t xstat; + int retval; + retval = iposix_lstat_proc(path, &xstat); + if (retval != 0) return -1; + iposix_stat_convert(ostat, &xstat); + return 0; +} + +// returns 0 for success, -1 for error +int iposix_fstat(int fd, iposix_stat_t *ostat) +{ + iposix_ostat_t xstat; + int retval; + retval = iposix_fstat_proc(fd, &xstat); + if (retval != 0) return -1; + iposix_stat_convert(ostat, &xstat); + return 0; +} + +// normalize stat path +static void iposix_path_stat(const char *src, char *dst) +{ + int size = (int)strlen(src); + if (size > IPOSIX_MAXPATH) size = IPOSIX_MAXPATH; + memcpy(dst, src, size + 1); + if (size > 1) { + int trim = 1; + if (size == 3) { + if (isalpha((int)dst[0]) && dst[1] == ':' && + (dst[2] == '/' || dst[2] == '\\')) trim = 0; + } + if (size == 1) { + if (dst[0] == '/' || dst[0] == '\\') trim = 0; + } + if (trim) { + if (dst[size - 1] == '/' || dst[size - 1] == '\\') { + dst[size - 1] = 0; + size--; + } + } + } +} + + +// returns 0 for success, -1 for error +int iposix_stat(const char *path, iposix_stat_t *ostat) +{ + char buf[IPOSIX_MAXBUFF]; + iposix_path_stat(path, buf); + return iposix_stat_imp(buf, ostat); +} + +// returns 0 for success, -1 for error +int iposix_lstat(const char *path, iposix_stat_t *ostat) +{ + char buf[IPOSIX_MAXBUFF]; + iposix_path_stat(path, buf); + return iposix_lstat_imp(buf, ostat); +} + +// get current directory +char *iposix_getcwd(char *path, int size) +{ +#ifdef _WIN32 + return _getcwd(path, size); +#else + return getcwd(path, size); +#endif +} + +// create directory +int iposix_mkdir(const char *path, int mode) +{ +#ifdef _WIN32 + return _mkdir(path); +#else + if (mode < 0) mode = 0755; + return mkdir(path, mode); +#endif +} + +// change directory +int iposix_chdir(const char *path) +{ +#ifdef _WIN32 + return _chdir(path); +#else + return chdir(path); +#endif +} + +// check access +int iposix_access(const char *path, int mode) +{ +#ifdef _WIN32 + return _access(path, mode); +#else + return access(path, mode); +#endif +} + +// returns 1 for true 0 for false, -1 for not exist +int iposix_path_isdir(const char *path) +{ + iposix_stat_t s; + int hr = iposix_stat(path, &s); + if (hr != 0) return -1; + return (ISTAT_ISDIR(s.st_mode))? 1 : 0; +} + +// returns 1 for true 0 for false, -1 for not exist +int iposix_path_isfile(const char *path) +{ + iposix_stat_t s; + int hr = iposix_stat(path, &s); + if (hr != 0) return -1; + return (ISTAT_ISDIR(s.st_mode))? 0 : 1; +} + +// returns 1 for true 0 for false, -1 for not exist +int iposix_path_islink(const char *path) +{ + iposix_stat_t s; + int hr = iposix_stat(path, &s); + if (hr != 0) return -1; + return (ISTAT_ISLNK(s.st_mode))? 1 : 0; +} + +// returns 1 for true 0 for false +int iposix_path_exists(const char *path) +{ + iposix_stat_t s; + int hr = iposix_stat(path, &s); + if (hr != 0) return 0; + return 1; +} + +// returns file size, -1 for error +IINT64 iposix_path_getsize(const char *path) +{ + iposix_stat_t s; + int hr = iposix_stat(path, &s); + if (hr != 0) return -1; + return (IINT64)s.st_size; +} + + +//--------------------------------------------------------------------- +// Posix Path +//--------------------------------------------------------------------- + +// 是否是绝对路径,如果是的话返回1,否则返回0 +int iposix_path_isabs(const char *path) +{ + if (path == NULL) return 0; + if (path[0] == '/') return 1; + if (path[0] == 0) return 0; +#ifdef _WIN32 + if (path[0] == IPATHSEP) return 1; + if (isalpha(path[0]) && path[1] == ':') { + if (path[2] == '/' || path[2] == '\\') return 1; + } +#endif + return 0; +} + + + +//--------------------------------------------------------------------- +// iposix_string_t - basic string definition +//--------------------------------------------------------------------- +typedef struct +{ + char *p; + int l; + int m; +} iposix_string_t; + + +//--------------------------------------------------------------------- +// iposix_string_t interface +//--------------------------------------------------------------------- +#define _istrlen(s) ((s)->l) +#define _istrch(s, i) (((i) >= 0)? ((s)->p)[i] : ((s)->p)[(s)->l + (i)]) + +static char *_istrset(iposix_string_t *s, const char *p, int max) +{ + assert((max > 0) && p && s); + s->p = (char*)p; + s->l = strlen(p); + s->m = max; + return (char*)p; +} + +static char *_istrcat(iposix_string_t *s, const char *p) +{ + char *p1; + + assert(s && p); + for (p1 = (char*)p; p1[0]; p1++, s->l++) { + if (s->l >= s->m) break; + s->p[s->l] = p1[0]; + } + return s->p; +} + +static char *_istrcpy(iposix_string_t *s, const char *p) +{ + assert(s && p); + s->l = 0; + return _istrcat(s, p); +} + +static char *_istrcats(iposix_string_t *s1, const iposix_string_t *s2) +{ + int i; + assert(s1 && s2); + for (i = 0; i < s2->l; i++, s1->l++) { + if (s1->l >= s1->m) break; + s1->p[s1->l] = s2->p[i]; + } + return s1->p; +} + +static char *_icstr(iposix_string_t *s) +{ + assert(s); + if (s->l >= s->m) s->l = s->m - 1; + if (s->l < 0) s->l = 0; + s->p[s->l] = 0; + return s->p; +} + +static char _istrc(const iposix_string_t *s, int pos) +{ + if (pos >= 0) return (pos > s->l)? 0 : s->p[pos]; + return (pos < -(s->l))? 0 : s->p[s->l + pos]; +} + +static char _istrchop(iposix_string_t *s) +{ + char ch = _istrc(s, -1); + s->l--; + if (s->l < 0) s->l = 0; + return ch; +} + +static char *_istrctok(iposix_string_t *s, const char *p) +{ + int i, k; + + assert(s && p); + + for (; _istrlen(s) > 0; ) { + for (i = 0, k = 0; p[i] && k == 0; i++) { + if (_istrc(s, -1) == p[i]) k++; + } + if (k == 0) break; + _istrchop(s); + } + for (; _istrlen(s) > 0; ) { + for (i = 0, k = 0; p[i] && k == 0; i++) { + if (_istrc(s, -1) == p[i]) k++; + } + if (k) break; + _istrchop(s); + } + + return s->p; +} + +static int _istrcmp(iposix_string_t *s, const char *p) +{ + int i; + for (i = 0; i < s->l && ((char*)p)[i]; i++) + if (_istrc(s, i) != ((char*)p)[i]) break; + if (((char*)p)[i] == 0 && i == s->l) return 0; + return 1; +} + +static char *_istrcatc(iposix_string_t *s, char ch) +{ + char text[2] = " "; + assert(s); + text[0] = ch; + return _istrcat(s, text); +} + +static int istrtok(const char *p1, int *pos, const char *p2) +{ + int i, j, k, r; + + assert(p1 && pos && p2); + + for (i = *pos; p1[i]; i++) { + for (j = 0, k = 0; p2[j] && k == 0; j++) { + if (p1[i] == p2[j]) k++; + } + if (k == 0) break; + } + *pos = i; + r = i; + + if (p1[i] == 0) return -1; + for (; p1[i]; i++) { + for (j = 0, k = 0; p2[j] && k == 0; j++) { + if (p1[i] == p2[j]) k++; + } + if (k) break; + } + *pos = i; + + return r; +} + + +//--------------------------------------------------------------------- +// normalize path +//--------------------------------------------------------------------- +char *iposix_path_normal(const char *srcpath, char *path, int maxsize) +{ + int i, p, c, k, r; + iposix_string_t s1, s2; + char *p1, *p2; + char pp2[3]; + + assert(srcpath && path && maxsize > 0); + + if (srcpath[0] == 0) { + if (maxsize > 0) path[0] = 0; + return path; + } + + for (p1 = (char*)srcpath; p1[0] && isspace((int)p1[0]); p1++); + + path[0] = 0; + _istrset(&s1, path, maxsize); + + if (IPATHSEP == '\\') { + pp2[0] = '/'; + pp2[1] = '\\'; + pp2[2] = 0; + } else { + pp2[0] = '/'; + pp2[1] = 0; + } + + p2 = pp2; + + if (p1[0] && p1[1] == ':' && (ISYSNAME == 'u' || ISYSNAME == 'w')) { + _istrcatc(&s1, *p1++); + _istrcatc(&s1, *p1++); + } + + if (IPATHSEP == '/') { + if (p1[0] == '/') _istrcatc(&s1, *p1++); + } + else if (p1[0] == '/' || p1[0] == IPATHSEP) { + _istrcatc(&s1, IPATHSEP); + p1++; + } + + r = (_istrc(&s1, -1) == IPATHSEP)? 1 : 0; + srcpath = (const char*)p1; + + for (i = 0, c = 0, k = 0; (p = istrtok(srcpath, &i, p2)) >= 0; k++) { + s2.p = (char*)(srcpath + p); + s2.l = s2.m = i - p; + //_iputs(&s2); printf("*\n"); + if (_istrcmp(&s2, ".") == 0) continue; + if (_istrcmp(&s2, "..") == 0) { + if (c != 0) { + _istrctok(&s1, (IPATHSEP == '\\')? "/\\:" : "/"); + c--; + continue; + } + if (c == 0 && r) { + continue; + } + } else { + c++; + } + _istrcats(&s1, &s2); + _istrcatc(&s1, IPATHSEP); + } + if (_istrlen(&s1) == 0) { + _istrcpy(&s1, "."); + } else { + if (_istrc(&s1, -1) == IPATHSEP && c > 0) _istrchop(&s1); + } + return _icstr(&s1); +} + + +//--------------------------------------------------------------------- +// join path +//--------------------------------------------------------------------- +char *iposix_path_join(const char *p1, const char *p2, char *path, int len) +{ + iposix_string_t s; + int maxsize = len; + char *p, r; + + assert(p1 && p2 && maxsize > 0); + + for (; p1[0] && isspace((int)p1[0]); p1++); + for (; p2[0] && isspace((int)p2[0]); p2++); + r = 0; + p = (char*)p2; + if (IPATHSEP == '/') { + if (p[0] == '/') r = 1; + } else { + if (p[0] == '/' || p[0] == IPATHSEP) r = 1; + } + + if (p[0] && p[1] == ':' && (ISYSNAME == 'u' || ISYSNAME == 'w')) + return iposix_path_normal(p2, path, maxsize); + + if (r && (p1[0] == 0 || p1[1] != ':' || p1[2])) + return iposix_path_normal(p2, path, maxsize); + + p = (char*)malloc(maxsize + 10); + + if (p == NULL) { + return iposix_path_normal(p1, path, maxsize); + } + + iposix_path_normal(p1, p, maxsize); + _istrset(&s, p, maxsize); + + r = 1; + if (_istrlen(&s) <= 2 && _istrc(&s, 1) == ':') r = 0; + if (_istrc(&s, -1) == IPATHSEP) r = 0; + if (_istrlen(&s) == 0) r = 0; + if (r) _istrcatc(&s, IPATHSEP); + + _istrcat(&s, p2); + iposix_path_normal(_icstr(&s), path, maxsize); + free(p); + + return path; +} + + +// 绝对路径 +char *iposix_path_abspath_u(const char *srcpath, char *path, int maxsize) +{ + char *base; + base = (char*)malloc(IPOSIX_MAXBUFF * 2); + if (base == NULL) return NULL; + iposix_getcwd(base, IPOSIX_MAXPATH); + iposix_path_join(base, srcpath, path, maxsize); + free(base); + return path; +} + +#ifdef _WIN32 +char *iposix_path_abspath_w(const char *srcpath, char *path, int maxsize) +{ + char *fname; + DWORD hr = GetFullPathNameA(srcpath, maxsize, path, &fname); + if (hr == 0) return NULL; + return path; +} +#endif + + +// 绝对路径 +char *iposix_path_abspath(const char *srcpath, char *path, int maxsize) +{ +#ifdef _WIN32 + return iposix_path_abspath_w(srcpath, path, maxsize); +#else + return iposix_path_abspath_u(srcpath, path, maxsize); +#endif +} + +// 路径分割:从右向左找到第一个"/"分成两个字符串 +int iposix_path_split(const char *path, char *p1, int l1, char *p2, int l2) +{ + int length, i, k; + length = (int)strlen(path); + + for (i = length - 1; i >= 0; i--) { + if (IPATHSEP == '/') { + if (path[i] == '/') break; + } else { + if (path[i] == '/' || path[i] == '\\') break; + } + } + + if (p1) { + if (i < 0) { + if (l1 > 0) p1[0] = 0; + } + else if (i == 0) { + p1[0] = '/'; + p1[1] = 0; + } + else { + int size = i < l1 ? i : l1; + memcpy(p1, path, size); + if (size < l1) p1[size] = 0; + } + } + + k = length - i - 1; + + if (p2) { + if (k <= 0) { + if (l2 > 0) p2[0] = 0; + } else { + int size = k < l2 ? k : l2; + memcpy(p2, path + i + 1, k); + if (size < l2) p2[size] = 0; + } + } + + return 0; +} + + +// 扩展分割:分割文件主名与扩展名 +int iposix_path_splitext(const char *path, char *p1, int l1, + char *p2, int l2) +{ + int length, i, k, size; + length = (int)strlen(path); + for (i = length - 1, k = length; i >= 0; i--) { + if (path[i] == '.') { + k = i; + break; + } + else if (IPATHSEP == '/') { + if (path[i] == '/') break; + + } + else { + if (path[i] == '/' || path[i] == '\\') break; + } + } + + if (p1) { + + size = k < l1 ? k : l1; + if (size > 0) memcpy(p1, path, size); + if (size < l1) p1[size] = 0; + } + + size = length - k - 1; + if (size < 0) size = 0; + size = size < l2 ? size : l2; + + if (p2) { + if (size > 0) memcpy(p2, path + k + 1, size); + if (size < l2) p2[size] = 0; + } + + return 0; +} + + +//--------------------------------------------------------------------- +// platform special +//--------------------------------------------------------------------- + +// cross os GetModuleFileName, returns size for success, -1 for error +int iposix_path_exepath(char *ptr, int size) +{ + int retval = -1; +#if defined(_WIN32) + DWORD hr = GetModuleFileNameA(NULL, ptr, (DWORD)size); + if (hr > 0) retval = (int)hr; +#elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) + int mib[4]; + size_t cb = (size_t)size; + int hr; + mib[0] = CTL_KERN; + mib[1] = KERN_PROC; + mib[2] = KERN_PROC_PATHNAME; + mib[3] = -1; + hr = sysctl(mib, 4, ptr, &cb, NULL, 0); + if (hr >= 0) retval = (int)cb; +#elif defined(linux) || defined(__CYGWIN__) + FILE *fp; + fp = fopen("/proc/self/exename", "r"); + if (fp) { + retval = fread(ptr, 1, size, fp); + fclose(fp); + } else { + retval = 0; + } +#else +#endif + if (retval >= 0 && retval < size) { + ptr[retval] = '\0'; + } else if (size > 0) { + ptr[0] = '\0'; + } + + if (size > 0) ptr[size - 1] = 0; + + return retval; +} + +// 取得进程可执行文件的目录 +int iposix_path_execwd(char *ptr, int size) +{ + char *buffer; + int retval; + + if (ptr) { + if (size > 0) ptr[0] = 0; + } + + buffer = (char*)malloc(IPOSIX_MAXBUFF * 2); + if (buffer == NULL) { + return -1; + } + + retval = iposix_path_exepath(buffer, IPOSIX_MAXBUFF * 2); + + if (retval < 0) { + free(buffer); + return -2; + } + + iposix_path_split(buffer, ptr, size, NULL, IPOSIX_MAXPATH); + + free(buffer); + + return 0; +} + + +// 递归创建路径:直接从 ilog移植过来 +int iposix_path_mkdir(const char *path, int mode) +{ + int i, len; + char str[IPOSIX_MAXBUFF]; + + len = (int)strlen(path); + if (len > IPOSIX_MAXPATH) len = IPOSIX_MAXPATH; + + memcpy(str, path, len); + str[len] = 0; + +#ifdef _WIN32 + for (i = 0; i < len; i++) { + if (str[i] == '/') str[i] = '\\'; + } +#endif + + for (i = 0; i < len; i++) { + if (str[i] == '/' || str[i] == '\\') { + str[i] = '\0'; + if (iposix_access(str, F_OK) != 0) { + iposix_mkdir(str, mode); + } + str[i] = IPATHSEP; + } + } + + if (len > 0 && iposix_access(str, 0) != 0) { + iposix_mkdir(str, mode); + } + + return 0; +} + + +// 精简版取得可执行路径 +const char *iposix_get_exepath(void) +{ + static int inited = 0; + static char *ptr = NULL; + if (inited == 0) { + char *buffer = (char*)malloc(IPOSIX_MAXBUFF); + char *b2; + int size; + if (buffer == NULL) { + inited = -1; + return ""; + } + if (iposix_path_exepath(buffer, IPOSIX_MAXPATH) != 0) { + free(buffer); + inited = -1; + return ""; + } + size = (int)strlen(buffer); + b2 = (char*)malloc(size + 1); + if (b2 == NULL) { + free(buffer); + inited = -1; + return ""; + } + memcpy(b2, buffer, size + 1); + free(buffer); + ptr = b2; + inited = 1; + } + if (inited < 0) return ""; + return ptr; +} + +// 精简版取得可执行目录 +const char *iposix_get_execwd(void) +{ + static int inited = 0; + static char ptr[IPOSIX_MAXBUFF + 10]; + if (inited == 0) { + if (iposix_path_execwd(ptr, IPOSIX_MAXPATH) != 0) { + inited = -1; + return ""; + } + inited = 1; + } + if (inited < 0) return ""; + return ptr; +} + +#ifdef _MSC_VER +#pragma warning(disable:4996) +#endif + +// 文件路径格式化: +// out - 输出路径,长度不小于 IPOSIX_MAXPATH +// base - 根路径 +// ... - 后续的相对路径 +// 返回 - out +// 假设可执行路径位于 /home/abc/work,那么: +// iposix_path_format(out, iposix_get_execwd(), "images/%s", "abc.jpg") +// 结果就是 /home/abc/work/images/abc.jpg +char *iposix_path_format(char *out, const char *root, const char *fmt, ...) +{ + char buffer[IPOSIX_MAXBUFF]; + va_list argptr; + va_start(argptr, fmt); + vsprintf(buffer, fmt, argptr); + va_end(argptr); + return iposix_path_join(root, buffer, out, IPOSIX_MAXPATH); +} + + + +/*-------------------------------------------------------------------*/ +/* System Utilities */ +/*-------------------------------------------------------------------*/ +#ifndef IDISABLE_SHARED_LIBRARY + #if defined(__unix) + #include + #endif +#endif + +void *iposix_shared_open(const char *dllname) +{ +#ifndef IDISABLE_SHARED_LIBRARY + #ifdef __unix + return dlopen(dllname, RTLD_LAZY); + #else + return (void*)LoadLibraryA(dllname); + #endif +#else + return NULL; +#endif +} + +void *iposix_shared_get(void *shared, const char *name) +{ +#ifndef IDISABLE_SHARED_LIBRARY + #ifdef __unix + return dlsym(shared, name); + #else + return (void*)GetProcAddress((HINSTANCE)shared, name); + #endif +#else + return NULL; +#endif +} + +void iposix_shared_close(void *shared) +{ +#ifndef IDISABLE_SHARED_LIBRARY + #ifdef __unix + dlclose(shared); + #else + FreeLibrary((HINSTANCE)shared); + #endif +#endif +} + +/* load file content */ +void *iposix_file_load_content(const char *filename, long *size) +{ + size_t length, remain; + char *ptr, *out; + FILE *fp; + + if ((fp = fopen(filename, "rb")) == NULL) { + if (size) size[0] = 0; + return NULL; + } + + fseek(fp, 0, SEEK_END); + length = ftell(fp); + fseek(fp, 0, SEEK_SET); + + // avoid zero-size file returns null + ptr = (char*)malloc(length + 8); + + if (ptr == NULL) { + fclose(fp); + if (size) size[0] = 0; + return NULL; + } + + for (remain = length, out = ptr; remain > 0; ) { + size_t ret = fread(out, 1, remain, fp); + if (ret == 0) break; + remain -= ret; + out += ret; + } + + fclose(fp); + + if (size) size[0] = length; + + return ptr; +} + + +/* save file content */ +int iposix_file_save_content(const char *filename, const void *data, long size) +{ + const char *ptr = (const char*)data; + FILE *fp; + int hr = 0; + if ((fp = fopen(filename, "wb")) == NULL) return -1; + for (; size > 0; ) { + long written = (long)fwrite(ptr, 1, size, fp); + if (written <= 0) { + hr = -2; + break; + } + size -= written; + ptr += written; + } + fclose(fp); + return hr; +} + + + +#endif + + + + diff --git a/czmod/iposix.h b/czmod/iposix.h new file mode 100644 index 0000000..0d0f605 --- /dev/null +++ b/czmod/iposix.h @@ -0,0 +1,401 @@ +//===================================================================== +// +// iposix.h - posix file system accessing +// +// NOTE: +// for more information, please see the readme file. +// +//===================================================================== +#ifndef __IPOSIX_H__ +#define __IPOSIX_H__ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + + +/*-------------------------------------------------------------------*/ +/* C99 Compatible */ +/*-------------------------------------------------------------------*/ +#if defined(linux) || defined(__linux) || defined(__linux__) +#ifdef _POSIX_C_SOURCE +#if _POSIX_C_SOURCE < 200112L +#undef _POSIX_C_SOURCE +#endif +#endif + +#ifndef _POSIX_C_SOURCE +#define _POSIX_C_SOURCE 200112L +#endif + +#ifdef _GNU_SOURCE +#undef _GNU_SOURCE +#endif + +#ifdef _BSD_SOURCE +#undef _BSD_SOURCE +#endif + +#ifdef __BSD_VISIBLE +#undef __BSD_VISIBLE +#endif + +#ifdef _XOPEN_SOURCE +#undef _XOPEN_SOURCE +#endif + +#define _GNU_SOURCE 1 +#define _BSD_SOURCE 1 +#define __BSD_VISIBLE 1 +#define _XOPEN_SOURCE 600 +#endif + + +#ifndef IDISABLE_FILE_SYSTEM_ACCESS +//--------------------------------------------------------------------- +// Global Definition +//--------------------------------------------------------------------- +#ifndef __INTEGER_32_BITS__ +#define __INTEGER_32_BITS__ +#if defined(__UINT32_TYPE__) && defined(__UINT32_TYPE__) + typedef __UINT32_TYPE__ ISTDUINT32; + typedef __INT32_TYPE__ ISTDINT32; +#elif defined(__UINT_FAST32_TYPE__) && defined(__INT_FAST32_TYPE__) + typedef __UINT_FAST32_TYPE__ ISTDUINT32; + typedef __INT_FAST32_TYPE__ ISTDINT32; +#elif defined(_WIN64) || defined(WIN64) || defined(__amd64__) || \ + defined(__x86_64) || defined(__x86_64__) || defined(_M_IA64) || \ + defined(_M_AMD64) + typedef unsigned int ISTDUINT32; + typedef int ISTDINT32; +#elif defined(_WIN32) || defined(WIN32) || defined(__i386__) || \ + defined(__i386) || defined(_M_X86) + typedef unsigned long ISTDUINT32; + typedef long ISTDINT32; +#elif defined(__MACOS__) + typedef UInt32 ISTDUINT32; + typedef SInt32 ISTDINT32; +#elif defined(__APPLE__) && defined(__MACH__) + #include + typedef u_int32_t ISTDUINT32; + typedef int32_t ISTDINT32; +#elif defined(__BEOS__) + #include + typedef u_int32_t ISTDUINT32; + typedef int32_t ISTDINT32; +#elif (defined(_MSC_VER) || defined(__BORLANDC__)) && (!defined(__MSDOS__)) + typedef unsigned __int32 ISTDUINT32; + typedef __int32 ISTDINT32; +#elif defined(__GNUC__) && (__GNUC__ > 3) + #include + typedef uint32_t ISTDUINT32; + typedef int32_t ISTDINT32; +#else + typedef unsigned long ISTDUINT32; + typedef long ISTDINT32; +#endif +#endif + + +#if (defined(__APPLE__) && defined(__MACH__)) || defined(__MACOS__) +#ifndef __unix +#define __unix 1 +#endif +#endif + +#if defined(__unix__) || defined(unix) || defined(__linux) +#ifndef __unix +#define __unix 1 +#endif +#endif + +#include +#ifdef __unix +#include +#define IPATHSEP '/' +#else +#include +#if defined(_WIN32) +#define IPATHSEP '\\' +#else +#define IPATHSEP '/' +#endif +#endif + + +#ifndef __IINT8_DEFINED +#define __IINT8_DEFINED +typedef char IINT8; +#endif + +#ifndef __IUINT8_DEFINED +#define __IUINT8_DEFINED +typedef unsigned char IUINT8; +#endif + +#ifndef __IUINT16_DEFINED +#define __IUINT16_DEFINED +typedef unsigned short IUINT16; +#endif + +#ifndef __IINT16_DEFINED +#define __IINT16_DEFINED +typedef short IINT16; +#endif + +#ifndef __IINT32_DEFINED +#define __IINT32_DEFINED +typedef ISTDINT32 IINT32; +#endif + +#ifndef __IUINT32_DEFINED +#define __IUINT32_DEFINED +typedef ISTDUINT32 IUINT32; +#endif + +#ifndef __IINT64_DEFINED +#define __IINT64_DEFINED +#if defined(_MSC_VER) || defined(__BORLANDC__) +typedef __int64 IINT64; +#else +typedef long long IINT64; +#endif +#endif + +#ifndef __IUINT64_DEFINED +#define __IUINT64_DEFINED +#if defined(_MSC_VER) || defined(__BORLANDC__) +typedef unsigned __int64 IUINT64; +#else +typedef unsigned long long IUINT64; +#endif +#endif + +#if defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64) + #ifndef _WIN32 + #define _WIN32 + #endif +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + +//--------------------------------------------------------------------- +// Posix Stat +//--------------------------------------------------------------------- +#define ISTAT_IFMT 0170000 // file type mask +#define ISTAT_IFIFO 0010000 // named pipe (fifo) +#define ISTAT_IFCHR 0020000 // charactor special +#define ISTAT_IFDIR 0040000 // directory +#define ISTAT_IFBLK 0060000 // block special +#define ISTAT_IFREG 0100000 // regular +#define ISTAT_IFLNK 0120000 // symbolic link +#define ISTAT_IFSOCK 0140000 // socket +#define ISTAT_IFWHT 0160000 // whiteout +#define ISTAT_ISUID 0004000 // set user id on execution +#define ISTAT_ISGID 0002000 // set group id on execution +#define ISTAT_ISVXT 0001000 // swapped text even after use +#define ISTAT_IRWXU 0000700 // owner RWX mask +#define ISTAT_IRUSR 0000400 // owner read permission +#define ISTAT_IWUSR 0000200 // owner writer permission +#define ISTAT_IXUSR 0000100 // owner execution permission +#define ISTAT_IRWXG 0000070 // group RWX mask +#define ISTAT_IRGRP 0000040 // group read permission +#define ISTAT_IWGRP 0000020 // group write permission +#define ISTAT_IXGRP 0000010 // group execution permission +#define ISTAT_IRWXO 0000007 // other RWX mask +#define ISTAT_IROTH 0000004 // other read permission +#define ISTAT_IWOTH 0000002 // other writer permission +#define ISTAT_IXOTH 0000001 // other execution permission + +#define ISTAT_ISFMT(m, t) (((m) & ISTAT_IFMT) == (t)) +#define ISTAT_ISDIR(m) ISTAT_ISFMT(m, ISTAT_IFDIR) +#define ISTAT_ISCHR(m) ISTAT_ISFMT(m, ISTAT_IFCHR) +#define ISTAT_ISBLK(m) ISTAT_ISFMT(m, ISTAT_IFBLK) +#define ISTAT_ISREG(m) ISTAT_ISFMT(m, ISTAT_IFREG) +#define ISTAT_ISFIFO(m) ISTAT_ISFMT(m, ISTAT_IFIFO) +#define ISTAT_ISLNK(m) ISTAT_ISFMT(m, ISTAT_IFLNK) +#define ISTAT_ISSOCK(m) ISTAT_ISFMT(m, ISTAT_IFSOCK) +#define ISTAT_ISWHT(m) ISTAT_ISFMT(m, ISTAT_IFWHT) + +struct IPOSIX_STAT +{ + IUINT32 st_mode; + IUINT64 st_ino; + IUINT32 st_dev; + IUINT32 st_nlink; + IUINT32 st_uid; + IUINT32 st_gid; + IUINT64 st_size; + IUINT32 atime; + IUINT32 mtime; + IUINT32 ctime; + IUINT32 st_blocks; + IUINT32 st_blksize; + IUINT32 st_rdev; + IUINT32 st_flags; +}; + +typedef struct IPOSIX_STAT iposix_stat_t; + +#define IPOSIX_MAXPATH 1024 +#define IPOSIX_MAXBUFF ((IPOSIX_MAXPATH) + 8) + + +// returns 0 for success, -1 for error +int iposix_stat(const char *path, iposix_stat_t *ostat); + +// returns 0 for success, -1 for error +int iposix_lstat(const char *path, iposix_stat_t *ostat); + +// returns 0 for success, -1 for error +int iposix_fstat(int fd, iposix_stat_t *ostat); + +// get current directory +char *iposix_getcwd(char *path, int size); + +// create directory +int iposix_mkdir(const char *path, int mode); + +// change directory +int iposix_chdir(const char *path); + +#ifndef F_OK +#define F_OK 0 +#endif + +#ifndef X_OK +#define X_OK 1 +#endif + +#ifndef W_OK +#define W_OK 2 +#endif + +#ifndef R_OK +#define R_OK 4 +#endif + +// check access +int iposix_access(const char *path, int mode); + + +// returns 1 for true 0 for false, -1 for not exist +int iposix_path_isdir(const char *path); + +// returns 1 for true 0 for false, -1 for not exist +int iposix_path_isfile(const char *path); + +// returns 1 for true 0 for false, -1 for not exist +int iposix_path_islink(const char *path); + +// returns 1 for true 0 for false +int iposix_path_exists(const char *path); + +// returns file size, -1 for error +IINT64 iposix_path_getsize(const char *path); + + +//--------------------------------------------------------------------- +// Posix Path +//--------------------------------------------------------------------- + +// 是否是绝对路径,如果是的话返回1,否则返回0 +int iposix_path_isabs(const char *path); + +// 绝对路径 +char *iposix_path_abspath(const char *srcpath, char *path, int maxsize); + +// 归一化路径:去掉重复斜杠,以及处理掉".", ".."等。 +char *iposix_path_normal(const char *srcpath, char *path, int maxsize); + +// 连接路径 +char *iposix_path_join(const char *p1, const char *p2, char *path, int len); + +// 路径分割:从右向左找到第一个"/"分成两个字符串 +int iposix_path_split(const char *path, char *p1, int l1, char *p2, int l2); + +// 扩展分割:分割文件主名与扩展名 +int iposix_path_splitext(const char *path, char *p1, int l1, + char *p2, int l2); + + +//--------------------------------------------------------------------- +// platform special +//--------------------------------------------------------------------- + +// 取得进程可执行文件的文件名 +int iposix_path_exepath(char *ptr, int size); + +// 取得进程可执行文件的目录 +int iposix_path_execwd(char *ptr, int size); + +// 递归创建路径 +int iposix_path_mkdir(const char *path, int mode); + +// 精简版取得可执行路径 +const char *iposix_get_exepath(void); + +// 精简版取得可执行目录 +const char *iposix_get_execwd(void); + + +// 文件路径格式化: +// out - 输出路径,长度不小于 IPOSIX_MAXPATH +// root - 根路径 +// ... - 后续的相对路径 +// 返回 - out +// 假设可执行路径位于 /home/abc/work,那么: +// iposix_path_format(out, iposix_get_execwd(), "images/%s", "abc.jpg") +// 结果就是 /home/abc/work/images/abc.jpg +char *iposix_path_format(char *out, const char *root, const char *fmt, ...); + + + +//--------------------------------------------------------------------- +// System Utilities +//--------------------------------------------------------------------- + +#ifndef IDISABLE_SHARED_LIBRARY + +/* LoadLibraryA */ +void *iposix_shared_open(const char *dllname); + +/* GetProcAddress */ +void *iposix_shared_get(void *shared, const char *name); + +/* FreeLibrary */ +void iposix_shared_close(void *shared); + +#endif + +#ifndef IDISABLE_FILE_SYSTEM_ACCESS + +/* load file content, use free to dispose */ +void *iposix_file_load_content(const char *filename, long *size); + +/* save file content */ +int iposix_file_save_content(const char *filename, const void *data, long size); + +/* cross os GetModuleFileName, returns size for success, -1 for error */ +int iposix_get_proc_pathname(char *ptr, int size); + +#endif + + + +#ifdef __cplusplus +} +#endif + + +#endif + + +#endif + + + + From 77a917d11689f558847f22b24bab1505accf5484 Mon Sep 17 00:00:00 2001 From: skywind3000 Date: Tue, 17 Mar 2020 00:20:06 +0800 Subject: [PATCH 07/12] update czmod.z --- czmod/czmod.c | 139 +++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 133 insertions(+), 6 deletions(-) diff --git a/czmod/czmod.c b/czmod/czmod.c index 6e10896..9c29f8f 100644 --- a/czmod/czmod.c +++ b/czmod/czmod.c @@ -11,11 +11,15 @@ #include #include #include +#include -#ifdef __linux -#include +#if defined(_WIN32) || defined(_WIN64) || defined(WIN32) || defined(WIN64) +#include +#elif defined(__linux) +// #include #endif +#include "iposix.c" #include "imembase.c" @@ -73,7 +77,7 @@ static const char *get_data_file(void) if (text != NULL) { return text->ptr; } - text = os_getenv("_ZL_DATA"); + text = os_getenv("_ZL_DATA2"); if (text) { return text->ptr; } @@ -150,7 +154,7 @@ PathItem* item_new(const char *path, int rank, uint32_t timestamp) return item; }; -ib_array* ib_array_new_path(void) +ib_array* ib_array_new_items(void) { return ib_array_new((void (*)(void*))item_delete); } @@ -165,22 +169,145 @@ ib_array* data_load(const char *filename) if (content == NULL) { return NULL; } + else { + ib_array *lines = ib_string_split_c(content, '\n'); + int size = ib_array_size(lines); + int i; + ib_array *items = ib_array_new_items(); + for (i = 0; i < size; i++) { + ib_string *text = (ib_string*)ib_array_index(lines, i); + int p1 = ib_string_find_c(text, '|', 0); + if (p1 >= 0) { + int p2 = ib_string_find_c(text, '|', p1 + 1); + if (p2 >= 0) { + uint32_t timestamp; + int rank; + text->ptr[p1] = 0; + text->ptr[p2] = 0; + rank = (int)atoi(text->ptr + p1 + 1); + timestamp = (uint32_t)strtoul(text->ptr + p2 + 1, NULL, 10); + PathItem *ni = item_new(text->ptr, rank, timestamp); + ib_array_push(items, ni); + } + } + } + ib_array_delete(lines); + return items; + } return NULL; } +//--------------------------------------------------------------------- +// save data +//--------------------------------------------------------------------- +void data_save(const char *filename, ib_array *items) +{ + ib_string *tmpname = ib_string_new_from(filename); + FILE *fp; + while (1) { + char tmp[100]; + ib_string_assign(tmpname, filename); + sprintf(tmp, ".%u%03u%d", (uint32_t)time(NULL), + (uint32_t)(clock() % 1000), rand() % 10000); + ib_string_append(tmpname, tmp); + if (iposix_path_isdir(tmpname->ptr) < 0) break; + } + fp = fopen(tmpname->ptr, "w"); + if (fp) { + int size = ib_array_size(items); + int i; + for (i = 0; i < size; i++) { + PathItem *item = (PathItem*)ib_array_index(items, i); + fprintf(fp, "%s|%u|%u\n", + item->path->ptr, item->rank, item->timestamp); + } + fclose(fp); + #ifdef _WIN32 + ReplaceFileA(filename, tmpname->ptr, NULL, 2, NULL, NULL); + #else + rename(tmpname->ptr, filename); + #endif + } + ib_string_delete(tmpname); +} + + +//--------------------------------------------------------------------- +// insert data +//--------------------------------------------------------------------- +void data_add(ib_array *items, const char *path) +{ + ib_string *target = ib_string_new_from(path); + int i = 0, size, found = 0; +#if defined(_WIN32) + for (i = 0; i < target->size; i++) { + if (target->ptr[i] == '/') target->ptr[i] = '\\'; + else { + target->ptr[i] = (char)tolower(target->ptr[i]); + } + } +#endif + size = ib_array_size(items); + for (i = 0; i < size; i++) { + PathItem *item = (PathItem*)ib_array_index(items, i); + int equal = 0; + #if defined(_WIN32) + if (item->path->size == target->size) { + char *src = item->path->ptr; + char *dst = target->ptr; + int avail = target->size; + for (; avail > 0; src++, dst++, avail--) { + if (tolower(src[0]) != dst[0]) break; + } + equal = (avail == 0)? 1 : 0; + } + #else + if (ib_string_compare(item->path, target) == 0) { + equal = 1; + } + #endif + if (equal) { + found = 1; + item->rank++; + item->timestamp = (uint32_t)time(NULL); + } + } + if (!found) { + PathItem *ni = item_new(target->ptr, 1, (uint32_t)time(NULL)); + ib_array_push(items, ni); + } + ib_string_delete(target); +} + + +//--------------------------------------------------------------------- +// add to database +//--------------------------------------------------------------------- +void z_add(const char *newpath) +{ + const char *data = get_data_file(); + ib_array *items = data_load(data); + if (items == NULL) { + items = ib_array_new_items(); + } + data_add(items, newpath); + data_save(data, items); + ib_array_delete(items); +} + + //--------------------------------------------------------------------- // main entry //--------------------------------------------------------------------- int main(int argc, char *argv[]) { if (argc <= 1) { - printf("Hello, World !!\n"); - printf("data: %s\n", get_data_file()); return 0; } if (strcmp(argv[1], "--add") == 0) { if (argc >= 3) { + z_add(argv[2]); } } return 0; From a5f4cb692c2887826a4d9a2f210059244d440c85 Mon Sep 17 00:00:00 2001 From: skywind3000 Date: Tue, 17 Mar 2020 00:50:27 +0800 Subject: [PATCH 08/12] update --- czmod/czmod.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/czmod/czmod.c b/czmod/czmod.c index 9c29f8f..3105cad 100644 --- a/czmod/czmod.c +++ b/czmod/czmod.c @@ -303,6 +303,15 @@ void z_add(const char *newpath) int main(int argc, char *argv[]) { if (argc <= 1) { + int i; + printf("begin\n"); + clock_t ts = (uint64_t)clock(); + for (i = 0; i < 1000; i++) { + z_add("/tmp"); + } + ts = clock() - ts; + ts = (ts * 1000) / CLOCKS_PER_SEC; + printf("finished: %d ms\n", (int)ts); return 0; } if (strcmp(argv[1], "--add") == 0) { From 3d188ab6d9ae84497a672c9d0c27e3ab1500db23 Mon Sep 17 00:00:00 2001 From: skywind3000 Date: Tue, 17 Mar 2020 02:05:41 +0800 Subject: [PATCH 09/12] update --- czmod/czmod.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 64 insertions(+), 1 deletion(-) diff --git a/czmod/czmod.c b/czmod/czmod.c index 3105cad..1ec1dd4 100644 --- a/czmod/czmod.c +++ b/czmod/czmod.c @@ -17,8 +17,11 @@ #include #elif defined(__linux) // #include +#include #endif +#define IB_STRING_SSO 256 + #include "iposix.c" #include "imembase.c" @@ -281,6 +284,61 @@ void data_add(ib_array *items, const char *path) } +//--------------------------------------------------------------------- +// +//--------------------------------------------------------------------- +void z_insert(const char *newpath) +{ + static char tmpname[PATH_MAX + 10]; + static char text[PATH_MAX + 100]; + const char *data = get_data_file(); + FILE *fin = fopen(data, "r"); + FILE *fout; + while (1) { + char tmp[100]; + sprintf(tmp, ".%u%03u%d", (uint32_t)time(NULL), + (uint32_t)(clock() % 1000), rand() % 10000); + sprintf(tmpname, "%s%s", data, tmp); + if (iposix_path_isdir(tmpname) < 0) break; + } + fout = fopen(tmpname, "w"); + if (fin) { + int found = 0; + while (!feof(fin)) { + uint32_t rank, ts; + text[0] = 0; + fgets(text, PATH_MAX + 100, fin); + char *p1 = strchr(text, '|'); + if (p1 == NULL) continue; + *p1++ = 0; + char *p2 = strchr(p1, '|'); + if (p2 == NULL) continue; + *p2++ = 0; + if (strcmp(text, newpath) == 0) { + found = 1; + sscanf(p1, "%u", &rank); + sscanf(p2, "%u", &ts); + rank++; + ts = (uint32_t)time(NULL); + fprintf(fout, "%s|%u|%u\n", text, rank, ts); + } + else { + fprintf(fout, "%s|%s|%s\n", text, p1, p2); + } + } + if (!found) { + fprintf(fout, "%s|1|%u\n", newpath, (uint32_t)time(NULL)); + } + fclose(fin); + } + else { + fprintf(fout, "%s|1|%u\n", newpath, (uint32_t)time(NULL)); + } + fclose(fout); + rename(tmpname, data); +} + + //--------------------------------------------------------------------- // add to database //--------------------------------------------------------------------- @@ -307,7 +365,8 @@ int main(int argc, char *argv[]) printf("begin\n"); clock_t ts = (uint64_t)clock(); for (i = 0; i < 1000; i++) { - z_add("/tmp"); + // z_add("/tmp"); + z_insert("/tmp"); } ts = clock() - ts; ts = (ts * 1000) / CLOCKS_PER_SEC; @@ -316,7 +375,11 @@ int main(int argc, char *argv[]) } if (strcmp(argv[1], "--add") == 0) { if (argc >= 3) { +#if 0 z_add(argv[2]); +#else + z_insert(argv[2]); +#endif } } return 0; From 4c34e29e087fe6b6a6bb3d59b658415495612eae Mon Sep 17 00:00:00 2001 From: skywind3000 Date: Tue, 17 Mar 2020 02:26:49 +0800 Subject: [PATCH 10/12] update --- czmod/czmod.c | 40 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/czmod/czmod.c b/czmod/czmod.c index 1ec1dd4..49877da 100644 --- a/czmod/czmod.c +++ b/czmod/czmod.c @@ -18,6 +18,7 @@ #elif defined(__linux) // #include #include +#include #endif #define IB_STRING_SSO 256 @@ -105,6 +106,8 @@ ib_string *load_content(const char *filename) if (fp == NULL) { return NULL; } + int fd = fileno(fp); + flock(fd, LOCK_SH); ib_string *text = ib_string_new(); size_t block = 65536; ib_string_resize(text, block); @@ -118,6 +121,7 @@ ib_string *load_content(const char *filename) size_t hr = fread(&(text->ptr[pos]), 1, avail, fp); pos += hr; } + flock(fd, LOCK_UN); fclose(fp); ib_string_resize(text, pos); return text; @@ -236,6 +240,30 @@ void data_save(const char *filename, ib_array *items) } +//--------------------------------------------------------------------- +// save data +//--------------------------------------------------------------------- +void data_write(const char *filename, ib_array *items) +{ + FILE *fp; + int fd; + fp = fopen(filename, "w+"); + if (fp) { + int size = ib_array_size(items); + int i; + fd = fileno(fp); + flock(fd, LOCK_EX); + for (i = 0; i < size; i++) { + PathItem *item = (PathItem*)ib_array_index(items, i); + fprintf(fp, "%s|%u|%u\n", + item->path->ptr, item->rank, item->timestamp); + } + flock(fd, LOCK_UN); + fclose(fp); + } +} + + //--------------------------------------------------------------------- // insert data //--------------------------------------------------------------------- @@ -291,9 +319,10 @@ void z_insert(const char *newpath) { static char tmpname[PATH_MAX + 10]; static char text[PATH_MAX + 100]; - const char *data = get_data_file(); + const char *data = "/home/skywind/.zlua"; FILE *fin = fopen(data, "r"); FILE *fout; +#if 0 while (1) { char tmp[100]; sprintf(tmp, ".%u%03u%d", (uint32_t)time(NULL), @@ -301,6 +330,9 @@ void z_insert(const char *newpath) sprintf(tmpname, "%s%s", data, tmp); if (iposix_path_isdir(tmpname) < 0) break; } +#else + sprintf(tmpname, "%s.1", data); +#endif fout = fopen(tmpname, "w"); if (fin) { int found = 0; @@ -350,7 +382,11 @@ void z_add(const char *newpath) items = ib_array_new_items(); } data_add(items, newpath); +#if 0 data_save(data, items); +#else + data_write(data, items); +#endif ib_array_delete(items); } @@ -375,7 +411,7 @@ int main(int argc, char *argv[]) } if (strcmp(argv[1], "--add") == 0) { if (argc >= 3) { -#if 0 +#if 1 z_add(argv[2]); #else z_insert(argv[2]); From a1498c8672778221a212e5b29ff321f7cac57ec7 Mon Sep 17 00:00:00 2001 From: skywind3000 Date: Tue, 17 Mar 2020 02:35:21 +0800 Subject: [PATCH 11/12] update --- czmod/czmod.c | 1 + 1 file changed, 1 insertion(+) diff --git a/czmod/czmod.c b/czmod/czmod.c index 49877da..2e62022 100644 --- a/czmod/czmod.c +++ b/czmod/czmod.c @@ -258,6 +258,7 @@ void data_write(const char *filename, ib_array *items) fprintf(fp, "%s|%u|%u\n", item->path->ptr, item->rank, item->timestamp); } + fflush(fp); flock(fd, LOCK_UN); fclose(fp); } From 47aa86b0f9c716dd69cbcbd9f939e7aae18b4576 Mon Sep 17 00:00:00 2001 From: skywind3000 Date: Tue, 17 Mar 2020 11:37:04 +0800 Subject: [PATCH 12/12] remove files --- czmod/czmod.c | 425 --------- czmod/imembase.c | 2320 ---------------------------------------------- czmod/imembase.h | 916 ------------------ czmod/iposix.c | 1059 --------------------- czmod/iposix.h | 401 -------- 5 files changed, 5121 deletions(-) delete mode 100644 czmod/czmod.c delete mode 100644 czmod/imembase.c delete mode 100644 czmod/imembase.h delete mode 100644 czmod/iposix.c delete mode 100644 czmod/iposix.h diff --git a/czmod/czmod.c b/czmod/czmod.c deleted file mode 100644 index 2e62022..0000000 --- a/czmod/czmod.c +++ /dev/null @@ -1,425 +0,0 @@ -//===================================================================== -// -// czmod.c - c module to boost z.lua -// -// Created by skywind on 2020/03/11 -// Last Modified: 2020/03/11 16:37:01 -// -//===================================================================== -#include -#include -#include -#include -#include -#include - -#if defined(_WIN32) || defined(_WIN64) || defined(WIN32) || defined(WIN64) -#include -#elif defined(__linux) -// #include -#include -#include -#endif - -#define IB_STRING_SSO 256 - -#include "iposix.c" -#include "imembase.c" - - -//---------------------------------------------------------------------- -// INLINE -//---------------------------------------------------------------------- -#ifndef INLINE -#if defined(__GNUC__) - -#if (__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 1)) -#define INLINE __inline__ __attribute__((always_inline)) -#else -#define INLINE __inline__ -#endif - -#elif (defined(_MSC_VER) || defined(__WATCOMC__)) -#define INLINE __inline -#else -#define INLINE -#endif -#endif - -#if (!defined(__cplusplus)) && (!defined(inline)) -#define inline INLINE -#endif - - -//--------------------------------------------------------------------- -// internal functions -//--------------------------------------------------------------------- -static const char *get_data_file(void); - - -//--------------------------------------------------------------------- -// get environ -//--------------------------------------------------------------------- -static ib_string* os_getenv(const char *name) -{ - char *p = getenv(name); - if (p == NULL) { - return NULL; - } - ib_string *text = ib_string_new(); - ib_string_assign(text, p); - return text; -} - - -//--------------------------------------------------------------------- -// get data file -//--------------------------------------------------------------------- -static const char *get_data_file(void) -{ - static ib_string *text = NULL; - if (text != NULL) { - return text->ptr; - } - text = os_getenv("_ZL_DATA2"); - if (text) { - return text->ptr; - } - text = os_getenv("HOME"); - if (text == NULL) { - text = os_getenv("USERPROFILE"); - } - if (text == NULL) { - return NULL; - } - ib_string_append(text, "/.zlua"); - return text->ptr; -} - - -//--------------------------------------------------------------------- -// load file content -//--------------------------------------------------------------------- -ib_string *load_content(const char *filename) -{ - FILE *fp = fopen(filename, "r"); - if (fp == NULL) { - return NULL; - } - int fd = fileno(fp); - flock(fd, LOCK_SH); - ib_string *text = ib_string_new(); - size_t block = 65536; - ib_string_resize(text, block); - size_t pos = 0; - while (feof(fp) == 0) { - size_t avail = text->size - pos; - if (avail < block) { - ib_string_resize(text, text->size + block); - avail = text->size - pos; - } - size_t hr = fread(&(text->ptr[pos]), 1, avail, fp); - pos += hr; - } - flock(fd, LOCK_UN); - fclose(fp); - ib_string_resize(text, pos); - return text; -} - - -//--------------------------------------------------------------------- -// path item -//--------------------------------------------------------------------- -typedef struct -{ - ib_string *path; - int rank; - uint32_t timestamp; - uint64_t frecence; -} PathItem; - -static void item_delete(PathItem *item) -{ - if (item) { - if (item->path) { - ib_string_delete(item->path); - item->path = NULL; - } - ikmem_free(item); - } -}; - -PathItem* item_new(const char *path, int rank, uint32_t timestamp) -{ - PathItem* item = (PathItem*)ikmem_malloc(sizeof(PathItem)); - assert(item); - item->path = ib_string_new_from(path); - item->rank = rank; - item->timestamp = timestamp; - item->frecence = 0; - return item; -}; - -ib_array* ib_array_new_items(void) -{ - return ib_array_new((void (*)(void*))item_delete); -} - - -//--------------------------------------------------------------------- -// load data -//--------------------------------------------------------------------- -ib_array* data_load(const char *filename) -{ - ib_string *content = load_content(filename); - if (content == NULL) { - return NULL; - } - else { - ib_array *lines = ib_string_split_c(content, '\n'); - int size = ib_array_size(lines); - int i; - ib_array *items = ib_array_new_items(); - for (i = 0; i < size; i++) { - ib_string *text = (ib_string*)ib_array_index(lines, i); - int p1 = ib_string_find_c(text, '|', 0); - if (p1 >= 0) { - int p2 = ib_string_find_c(text, '|', p1 + 1); - if (p2 >= 0) { - uint32_t timestamp; - int rank; - text->ptr[p1] = 0; - text->ptr[p2] = 0; - rank = (int)atoi(text->ptr + p1 + 1); - timestamp = (uint32_t)strtoul(text->ptr + p2 + 1, NULL, 10); - PathItem *ni = item_new(text->ptr, rank, timestamp); - ib_array_push(items, ni); - } - } - } - ib_array_delete(lines); - return items; - } - return NULL; -} - - -//--------------------------------------------------------------------- -// save data -//--------------------------------------------------------------------- -void data_save(const char *filename, ib_array *items) -{ - ib_string *tmpname = ib_string_new_from(filename); - FILE *fp; - while (1) { - char tmp[100]; - ib_string_assign(tmpname, filename); - sprintf(tmp, ".%u%03u%d", (uint32_t)time(NULL), - (uint32_t)(clock() % 1000), rand() % 10000); - ib_string_append(tmpname, tmp); - if (iposix_path_isdir(tmpname->ptr) < 0) break; - } - fp = fopen(tmpname->ptr, "w"); - if (fp) { - int size = ib_array_size(items); - int i; - for (i = 0; i < size; i++) { - PathItem *item = (PathItem*)ib_array_index(items, i); - fprintf(fp, "%s|%u|%u\n", - item->path->ptr, item->rank, item->timestamp); - } - fclose(fp); - #ifdef _WIN32 - ReplaceFileA(filename, tmpname->ptr, NULL, 2, NULL, NULL); - #else - rename(tmpname->ptr, filename); - #endif - } - ib_string_delete(tmpname); -} - - -//--------------------------------------------------------------------- -// save data -//--------------------------------------------------------------------- -void data_write(const char *filename, ib_array *items) -{ - FILE *fp; - int fd; - fp = fopen(filename, "w+"); - if (fp) { - int size = ib_array_size(items); - int i; - fd = fileno(fp); - flock(fd, LOCK_EX); - for (i = 0; i < size; i++) { - PathItem *item = (PathItem*)ib_array_index(items, i); - fprintf(fp, "%s|%u|%u\n", - item->path->ptr, item->rank, item->timestamp); - } - fflush(fp); - flock(fd, LOCK_UN); - fclose(fp); - } -} - - -//--------------------------------------------------------------------- -// insert data -//--------------------------------------------------------------------- -void data_add(ib_array *items, const char *path) -{ - ib_string *target = ib_string_new_from(path); - int i = 0, size, found = 0; -#if defined(_WIN32) - for (i = 0; i < target->size; i++) { - if (target->ptr[i] == '/') target->ptr[i] = '\\'; - else { - target->ptr[i] = (char)tolower(target->ptr[i]); - } - } -#endif - size = ib_array_size(items); - for (i = 0; i < size; i++) { - PathItem *item = (PathItem*)ib_array_index(items, i); - int equal = 0; - #if defined(_WIN32) - if (item->path->size == target->size) { - char *src = item->path->ptr; - char *dst = target->ptr; - int avail = target->size; - for (; avail > 0; src++, dst++, avail--) { - if (tolower(src[0]) != dst[0]) break; - } - equal = (avail == 0)? 1 : 0; - } - #else - if (ib_string_compare(item->path, target) == 0) { - equal = 1; - } - #endif - if (equal) { - found = 1; - item->rank++; - item->timestamp = (uint32_t)time(NULL); - } - } - if (!found) { - PathItem *ni = item_new(target->ptr, 1, (uint32_t)time(NULL)); - ib_array_push(items, ni); - } - ib_string_delete(target); -} - - -//--------------------------------------------------------------------- -// -//--------------------------------------------------------------------- -void z_insert(const char *newpath) -{ - static char tmpname[PATH_MAX + 10]; - static char text[PATH_MAX + 100]; - const char *data = "/home/skywind/.zlua"; - FILE *fin = fopen(data, "r"); - FILE *fout; -#if 0 - while (1) { - char tmp[100]; - sprintf(tmp, ".%u%03u%d", (uint32_t)time(NULL), - (uint32_t)(clock() % 1000), rand() % 10000); - sprintf(tmpname, "%s%s", data, tmp); - if (iposix_path_isdir(tmpname) < 0) break; - } -#else - sprintf(tmpname, "%s.1", data); -#endif - fout = fopen(tmpname, "w"); - if (fin) { - int found = 0; - while (!feof(fin)) { - uint32_t rank, ts; - text[0] = 0; - fgets(text, PATH_MAX + 100, fin); - char *p1 = strchr(text, '|'); - if (p1 == NULL) continue; - *p1++ = 0; - char *p2 = strchr(p1, '|'); - if (p2 == NULL) continue; - *p2++ = 0; - if (strcmp(text, newpath) == 0) { - found = 1; - sscanf(p1, "%u", &rank); - sscanf(p2, "%u", &ts); - rank++; - ts = (uint32_t)time(NULL); - fprintf(fout, "%s|%u|%u\n", text, rank, ts); - } - else { - fprintf(fout, "%s|%s|%s\n", text, p1, p2); - } - } - if (!found) { - fprintf(fout, "%s|1|%u\n", newpath, (uint32_t)time(NULL)); - } - fclose(fin); - } - else { - fprintf(fout, "%s|1|%u\n", newpath, (uint32_t)time(NULL)); - } - fclose(fout); - rename(tmpname, data); -} - - -//--------------------------------------------------------------------- -// add to database -//--------------------------------------------------------------------- -void z_add(const char *newpath) -{ - const char *data = get_data_file(); - ib_array *items = data_load(data); - if (items == NULL) { - items = ib_array_new_items(); - } - data_add(items, newpath); -#if 0 - data_save(data, items); -#else - data_write(data, items); -#endif - ib_array_delete(items); -} - - -//--------------------------------------------------------------------- -// main entry -//--------------------------------------------------------------------- -int main(int argc, char *argv[]) -{ - if (argc <= 1) { - int i; - printf("begin\n"); - clock_t ts = (uint64_t)clock(); - for (i = 0; i < 1000; i++) { - // z_add("/tmp"); - z_insert("/tmp"); - } - ts = clock() - ts; - ts = (ts * 1000) / CLOCKS_PER_SEC; - printf("finished: %d ms\n", (int)ts); - return 0; - } - if (strcmp(argv[1], "--add") == 0) { - if (argc >= 3) { -#if 1 - z_add(argv[2]); -#else - z_insert(argv[2]); -#endif - } - } - return 0; -} - - diff --git a/czmod/imembase.c b/czmod/imembase.c deleted file mode 100644 index f6b5b28..0000000 --- a/czmod/imembase.c +++ /dev/null @@ -1,2320 +0,0 @@ -/********************************************************************** - * - * imembase.c - basic interface of memory operation - * skywind3000 (at) gmail.com, 2006-2016 - * - **********************************************************************/ - -#include "imembase.h" - -#include -#include -#include -#include - - -#if (defined(__BORLANDC__) || defined(__WATCOMC__)) -#if defined(_WIN32) || defined(WIN32) -#pragma warn -8002 -#pragma warn -8004 -#pragma warn -8008 -#pragma warn -8012 -#pragma warn -8027 -#pragma warn -8057 -#pragma warn -8066 -#endif -#endif - - -/*====================================================================*/ -/* IALLOCATOR */ -/*====================================================================*/ -void *(*__ihook_malloc)(size_t size) = NULL; -void (*__ihook_free)(void *) = NULL; -void *(*__ihook_realloc)(void *, size_t size) = NULL; - - -void* internal_malloc(struct IALLOCATOR *allocator, size_t size) -{ - if (allocator != NULL) { - return allocator->alloc(allocator, size); - } - if (__ihook_malloc != NULL) { - return __ihook_malloc(size); - } - return malloc(size); -} - -void internal_free(struct IALLOCATOR *allocator, void *ptr) -{ - if (allocator != NULL) { - allocator->free(allocator, ptr); - return; - } - if (__ihook_free != NULL) { - __ihook_free(ptr); - return; - } - free(ptr); -} - -void* internal_realloc(struct IALLOCATOR *allocator, void *ptr, size_t size) -{ - if (allocator != NULL) { - return allocator->realloc(allocator, ptr, size); - } - if (__ihook_realloc != NULL) { - return __ihook_realloc(ptr, size); - } - return realloc(ptr, size); -} - - -/*====================================================================*/ -/* IKMEM INTERFACE */ -/*====================================================================*/ -#ifndef IKMEM_ALLOCATOR -#define IKMEM_ALLOCATOR NULL -#endif - -struct IALLOCATOR *ikmem_allocator = IKMEM_ALLOCATOR; - - -void* ikmem_malloc(size_t size) -{ - return internal_malloc(ikmem_allocator, size); -} - -void* ikmem_realloc(void *ptr, size_t size) -{ - return internal_realloc(ikmem_allocator, ptr, size); -} - -void ikmem_free(void *ptr) -{ - internal_free(ikmem_allocator, ptr); -} - - -/*====================================================================*/ -/* IVECTOR */ -/*====================================================================*/ -void iv_init(struct IVECTOR *v, struct IALLOCATOR *allocator) -{ - if (v == 0) return; - v->data = 0; - v->size = 0; - v->capacity = 0; - v->allocator = allocator; -} - -void iv_destroy(struct IVECTOR *v) -{ - if (v == NULL) return; - if (v->data) { - internal_free(v->allocator, v->data); - } - v->data = NULL; - v->size = 0; - v->capacity = 0; -} - -int iv_capacity(struct IVECTOR *v, size_t newcap) -{ - if (newcap == v->capacity) - return 0; - if (newcap == 0) { - if (v->capacity > 0) { - internal_free(v->allocator, v->data); - } - v->data = NULL; - v->capacity = 0; - v->size = 0; - } - else { - unsigned char *ptr = (unsigned char*) - internal_malloc(v->allocator, newcap); - if (ptr == NULL) { - return -1; - } - if (v->data) { - size_t minsize = (v->size <= newcap)? v->size : newcap; - if (minsize > 0 && v->data) { - memcpy(ptr, v->data, minsize); - } - internal_free(v->allocator, v->data); - } - v->data = ptr; - v->capacity = newcap; - if (v->size > v->capacity) { - v->size = v->capacity; - } - } - return 0; -} - -int iv_resize(struct IVECTOR *v, size_t newsize) -{ - if (newsize > v->capacity) { - size_t capacity = v->capacity * 2; - if (capacity < newsize) { - capacity = sizeof(char*); - while (capacity < newsize) { - capacity = capacity * 2; - } - } - if (iv_capacity(v, capacity) != 0) { - return -1; - } - } - v->size = newsize; - return 0; -} - -int iv_reserve(struct IVECTOR *v, size_t size) -{ - return iv_capacity(v, (size >= v->size)? size : v->size); -} - -int iv_push(struct IVECTOR *v, const void *data, size_t size) -{ - size_t current = v->size; - if (iv_resize(v, current + size) != 0) - return -1; - if (data != NULL) - memcpy(v->data + current, data, size); - return 0; -} - -size_t iv_pop(struct IVECTOR *v, void *data, size_t size) -{ - size_t current = v->size; - if (size >= current) size = current; - if (data != NULL) - memcpy(data, v->data + current - size, size); - iv_resize(v, current - size); - return size; -} - -int iv_insert(struct IVECTOR *v, size_t pos, const void *data, size_t size) -{ - size_t current = v->size; - if (pos > current) - return -1; - if (iv_resize(v, current + size) != 0) - return -1; - if (pos < current) { - memmove(v->data + pos + size, v->data + pos, current - pos); - } - if (data != NULL) - memcpy(v->data + pos, data, size); - return 0; -} - -int iv_erase(struct IVECTOR *v, size_t pos, size_t size) -{ - size_t current = v->size; - if (pos >= current) return 0; - if (pos + size >= current) size = current - pos; - if (size == 0) return 0; - memmove(v->data + pos, v->data + pos + size, current - pos - size); - if (iv_resize(v, current - size) != 0) - return -1; - return 0; -} - - -/*====================================================================*/ -/* IMEMNODE */ -/*====================================================================*/ -void imnode_init(struct IMEMNODE *mn, ilong nodesize, struct IALLOCATOR *ac) -{ - struct IMEMNODE *mnode = mn; - - assert(mnode != NULL); - mnode->allocator = ac; - - iv_init(&mnode->vprev, ac); - iv_init(&mnode->vnext, ac); - iv_init(&mnode->vnode, ac); - iv_init(&mnode->vdata, ac); - iv_init(&mnode->vmem, ac); - iv_init(&mnode->vmode, ac); - - nodesize = IROUND_UP(nodesize, 8); - - mnode->node_size = nodesize; - mnode->node_free = 0; - mnode->node_used = 0; - mnode->node_max = 0; - mnode->mem_max = 0; - mnode->mem_count = 0; - mnode->list_open = -1; - mnode->list_close = -1; - mnode->total_mem = 0; - mnode->grow_limit = 0; - mnode->extra = NULL; -} - -void imnode_destroy(struct IMEMNODE *mnode) -{ - ilong i; - - assert(mnode != NULL); - if (mnode->mem_count > 0) { - for (i = 0; i < mnode->mem_count && mnode->mmem; i++) { - if (mnode->mmem[i]) { - internal_free(mnode->allocator, mnode->mmem[i]); - } - mnode->mmem[i] = NULL; - } - mnode->mem_count = 0; - mnode->mem_max = 0; - iv_destroy(&mnode->vmem); - mnode->mmem = NULL; - } - - iv_destroy(&mnode->vprev); - iv_destroy(&mnode->vnext); - iv_destroy(&mnode->vnode); - iv_destroy(&mnode->vdata); - iv_destroy(&mnode->vmode); - - mnode->mprev = NULL; - mnode->mnext = NULL; - mnode->mnode = NULL; - mnode->mdata = NULL; - mnode->mmode = NULL; - - mnode->node_free = 0; - mnode->node_used = 0; - mnode->node_max = 0; - mnode->list_open = -1; - mnode->list_close= -1; - mnode->total_mem = 0; -} - -static int imnode_node_resize(struct IMEMNODE *mnode, ilong size) -{ - size_t size1, size2; - - size1 = (size_t)(size * (ilong)sizeof(ilong)); - size2 = (size_t)(size * (ilong)sizeof(void*)); - - if (iv_resize(&mnode->vprev, size1)) return -1; - if (iv_resize(&mnode->vnext, size1)) return -2; - if (iv_resize(&mnode->vnode, size1)) return -3; - if (iv_resize(&mnode->vdata, size2)) return -5; - if (iv_resize(&mnode->vmode, size1)) return -6; - - mnode->mprev = (ilong*)((void*)mnode->vprev.data); - mnode->mnext = (ilong*)((void*)mnode->vnext.data); - mnode->mnode = (ilong*)((void*)mnode->vnode.data); - mnode->mdata =(void**)((void*)mnode->vdata.data); - mnode->mmode = (ilong*)((void*)mnode->vmode.data); - mnode->node_max = size; - - return 0; -} - -static int imnode_mem_add(struct IMEMNODE*mnode, ilong node_count, void**mem) -{ - size_t newsize; - char *mptr; - - if (mnode->mem_count >= mnode->mem_max) { - newsize = (mnode->mem_max <= 0)? 16 : mnode->mem_max * 2; - if (iv_resize(&mnode->vmem, newsize * sizeof(void*))) - return -1; - mnode->mem_max = newsize; - mnode->mmem = (char**)((void*)mnode->vmem.data); - } - newsize = node_count * mnode->node_size + 16; - mptr = (char*)internal_malloc(mnode->allocator, newsize); - if (mptr == NULL) return -2; - - mnode->mmem[mnode->mem_count++] = mptr; - mnode->total_mem += newsize; - mptr = (char*)IROUND_UP(((size_t)mptr), 16); - - if (mem) *mem = mptr; - - return 0; -} - - -static long imnode_grow(struct IMEMNODE *mnode) -{ - ilong size_start = mnode->node_max; - ilong size_endup; - ilong retval, count, i, j; - void *mptr; - char *p; - - count = (mnode->node_max <= 0)? 8 : mnode->node_max; - if (mnode->grow_limit > 0) { - if (count > mnode->grow_limit) count = mnode->grow_limit; - } - if (count > 4096) count = 4096; - size_endup = size_start + count; - - retval = imnode_node_resize(mnode, size_endup); - if (retval) return -10 + (long)retval; - - retval = imnode_mem_add(mnode, count, &mptr); - - if (retval) { - imnode_node_resize(mnode, size_start); - mnode->node_max = size_start; - return -20 + (long)retval; - } - - p = (char*)mptr; - for (i = mnode->node_max - 1, j = 0; j < count; i--, j++) { - IMNODE_NODE(mnode, i) = 0; - IMNODE_MODE(mnode, i) = 0; - IMNODE_DATA(mnode, i) = p; - IMNODE_PREV(mnode, i) = -1; - IMNODE_NEXT(mnode, i) = mnode->list_open; - if (mnode->list_open >= 0) IMNODE_PREV(mnode, mnode->list_open) = i; - mnode->list_open = i; - mnode->node_free++; - p += mnode->node_size; - } - - return 0; -} - - -ilong imnode_new(struct IMEMNODE *mnode) -{ - ilong node, next; - - assert(mnode); - if (mnode->list_open < 0) { - if (imnode_grow(mnode)) return -2; - } - - if (mnode->list_open < 0 || mnode->node_free <= 0) return -3; - - node = mnode->list_open; - next = IMNODE_NEXT(mnode, node); - if (next >= 0) IMNODE_PREV(mnode, next) = -1; - mnode->list_open = next; - - IMNODE_PREV(mnode, node) = -1; - IMNODE_NEXT(mnode, node) = mnode->list_close; - - if (mnode->list_close >= 0) IMNODE_PREV(mnode, mnode->list_close) = node; - mnode->list_close = node; - IMNODE_MODE(mnode, node) = 1; - - mnode->node_free--; - mnode->node_used++; - - return node; -} - -void imnode_del(struct IMEMNODE *mnode, ilong index) -{ - ilong prev, next; - - assert(mnode); - assert((index >= 0) && (index < mnode->node_max)); - assert(IMNODE_MODE(mnode, index) != 0); - - next = IMNODE_NEXT(mnode, index); - prev = IMNODE_PREV(mnode, index); - - if (next >= 0) IMNODE_PREV(mnode, next) = prev; - if (prev >= 0) IMNODE_NEXT(mnode, prev) = next; - else mnode->list_close = next; - - IMNODE_PREV(mnode, index) = -1; - IMNODE_NEXT(mnode, index) = mnode->list_open; - - if (mnode->list_open >= 0) IMNODE_PREV(mnode, mnode->list_open) = index; - mnode->list_open = index; - - IMNODE_MODE(mnode, index) = 0; - mnode->node_free++; - mnode->node_used--; -} - -ilong imnode_head(const struct IMEMNODE *mnode) -{ - return (mnode)? mnode->list_close : -1; -} - -ilong imnode_next(const struct IMEMNODE *mnode, ilong index) -{ - return (mnode)? IMNODE_NEXT(mnode, index) : -1; -} - -ilong imnode_prev(const struct IMEMNODE *mnode, ilong index) -{ - return (mnode)? IMNODE_PREV(mnode, index) : -1; -} - -void *imnode_data(struct IMEMNODE *mnode, ilong index) -{ - return (char*)IMNODE_DATA(mnode, index); -} - -const void* imnode_data_const(const struct IMEMNODE *mnode, ilong index) -{ - return (const char*)IMNODE_DATA(mnode, index); -} - - - - -/*====================================================================*/ -/* IVECTOR / IMEMNODE MANAGEMENT */ -/*====================================================================*/ - -ib_vector *iv_create(void) -{ - ib_vector *vec; - vec = (ib_vector*)ikmem_malloc(sizeof(ib_vector)); - if (vec == NULL) return NULL; - iv_init(vec, ikmem_allocator); - return vec; -} - -void iv_delete(ib_vector *vec) -{ - assert(vec); - iv_destroy(vec); - ikmem_free(vec); -} - -ib_memnode *imnode_create(ilong nodesize, int grow_limit) -{ - ib_memnode *mnode; - mnode = (ib_memnode*)ikmem_malloc(sizeof(ib_memnode)); - if (mnode == NULL) return NULL; - imnode_init(mnode, nodesize, ikmem_allocator); - mnode->grow_limit = grow_limit; - return mnode; -} - -void imnode_delete(ib_memnode *mnode) -{ - assert(mnode); - imnode_destroy(mnode); - ikmem_free(mnode); -} - - -/*--------------------------------------------------------------------*/ -/* Collection - Array */ -/*--------------------------------------------------------------------*/ - -struct ib_array -{ - struct IVECTOR vec; - void (*fn_destroy)(void*); - size_t size; - void **items; -}; - -ib_array *ib_array_new(void (*destroy_func)(void*)) -{ - ib_array *array = (ib_array*)ikmem_malloc(sizeof(ib_array)); - if (array == NULL) return NULL; - iv_init(&array->vec, ikmem_allocator); - array->fn_destroy = destroy_func; - array->size = 0; - return array; -}; - - -void ib_array_delete(ib_array *array) -{ - if (array->fn_destroy) { - size_t n = array->size; - size_t i; - for (i = 0; i < n; i++) { - array->fn_destroy(array->items[i]); - array->items[i] = NULL; - } - } - iv_destroy(&array->vec); - array->size = 0; - array->items = NULL; - ikmem_free(array); -} - -static void ib_array_update(ib_array *array) -{ - array->items = (void**)array->vec.data; -} - -void ib_array_reserve(ib_array *array, size_t new_size) -{ - int hr = iv_obj_reserve(&array->vec, char*, new_size); - if (hr != 0) { - assert(hr == 0); - } - ib_array_update(array); -} - -size_t ib_array_size(const ib_array *array) -{ - return array->size; -} - -void** ib_array_ptr(ib_array *array) -{ - return array->items; -} - -void* ib_array_index(ib_array *array, size_t index) -{ - assert(index < array->size); - return array->items[index]; -} - -const void* ib_array_const_index(const ib_array *array, size_t index) -{ - assert(index < array->size); - return array->items[index]; -} - -void ib_array_push(ib_array *array, void *item) -{ - int hr = iv_obj_push(&array->vec, void*, &item); - if (hr) { - assert(hr == 0); - } - ib_array_update(array); - array->size++; -} - -void ib_array_push_left(ib_array *array, void *item) -{ - int hr = iv_obj_insert(&array->vec, void*, 0, &item); - if (hr) { - assert(hr == 0); - } - ib_array_update(array); - array->size++; -} - -void ib_array_replace(ib_array *array, size_t index, void *item) -{ - assert(index < array->size); - if (array->fn_destroy) { - array->fn_destroy(array->items[index]); - } - array->items[index] = item; -} - -void* ib_array_pop(ib_array *array) -{ - void *item; - int hr; - assert(array->size > 0); - array->size--; - item = array->items[array->size]; - hr = iv_obj_resize(&array->vec, void*, array->size); - ib_array_update(array); - if (hr) { - assert(hr == 0); - } - return item; -} - -void* ib_array_pop_left(ib_array *array) -{ - void *item; - int hr; - assert(array->size > 0); - array->size--; - item = array->items[0]; - hr = iv_obj_erase(&array->vec, void*, 0, 1); - ib_array_update(array); - if (hr) { - assert(hr == 0); - } - return item; -} - -void ib_array_remove(ib_array *array, size_t index) -{ - assert(index < array->size); - if (array->fn_destroy) { - array->fn_destroy(array->items[index]); - } - iv_obj_erase(&array->vec, void*, index, 1); - ib_array_update(array); - array->size--; -} - -void ib_array_insert_before(ib_array *array, size_t index, void *item) -{ - int hr = iv_obj_insert(&array->vec, void*, index, &item); - if (hr) { - assert(hr == 0); - } - ib_array_update(array); - array->size++; -} - -void* ib_array_pop_at(ib_array *array, size_t index) -{ - void *item; - int hr; - assert(array->size > 0); - item = array->items[index]; - hr = iv_obj_erase(&array->vec, void*, index, 1); - if (hr) { - assert(hr == 0); - } - return item; -} - -void ib_array_sort(ib_array *array, - int (*compare)(const void*, const void*)) -{ - if (array->size) { - void **items = array->items; - size_t size = array->size; - size_t i, j; - for (i = 0; i < size - 1; i++) { - for (j = i + 1; j < size; j++) { - if (compare(items[i], items[j]) > 0) { - void *tmp = items[i]; - items[i] = items[j]; - items[j] = tmp; - } - } - } - } -} - -void ib_array_for_each(ib_array *array, void (*iterator)(void *item)) -{ - if (iterator) { - void **items = array->items; - size_t count = array->size; - for (; count > 0; count--, items++) { - iterator(items[0]); - } - } -} - -ilong ib_array_search(const ib_array *array, - int (*compare)(const void*, const void*), - const void *item, - ilong start_pos) -{ - ilong size = (ilong)array->size; - void **items = array->items; - if (start_pos < 0) { - start_pos = 0; - } - for (items = items + start_pos; start_pos < size; start_pos++) { - if (compare(items[0], item) == 0) { - return start_pos; - } - items++; - } - return -1; -} - -ilong ib_array_bsearch(const ib_array *array, - int (*compare)(const void*, const void*), - const void *item) -{ - ilong top, bottom, mid; - void **items = array->items; - if (array->size == 0) return -1; - top = 0; - bottom = (ilong)array->size - 1; - while (1) { - int hr; - mid = (top + bottom) >> 1; - hr = compare(item, items[mid]); - if (hr < 0) bottom = mid; - else if (hr > 0) top = mid; - else return mid; - if (top == bottom) break; - } - return -1; -} - - - -/*====================================================================*/ -/* Binary Search Tree */ -/*====================================================================*/ - -struct ib_node *ib_node_first(struct ib_root *root) -{ - struct ib_node *node = root->node; - if (node == NULL) return NULL; - while (node->left) - node = node->left; - return node; -} - -struct ib_node *ib_node_last(struct ib_root *root) -{ - struct ib_node *node = root->node; - if (node == NULL) return NULL; - while (node->right) - node = node->right; - return node; -} - -struct ib_node *ib_node_next(struct ib_node *node) -{ - if (node == NULL) return NULL; - if (node->right) { - node = node->right; - while (node->left) - node = node->left; - } - else { - while (1) { - struct ib_node *last = node; - node = node->parent; - if (node == NULL) break; - if (node->left == last) break; - } - } - return node; -} - -struct ib_node *ib_node_prev(struct ib_node *node) -{ - if (node == NULL) return NULL; - if (node->left) { - node = node->left; - while (node->right) - node = node->right; - } - else { - while (1) { - struct ib_node *last = node; - node = node->parent; - if (node == NULL) break; - if (node->right == last) break; - } - } - return node; -} - -static inline void -_ib_child_replace(struct ib_node *oldnode, struct ib_node *newnode, - struct ib_node *parent, struct ib_root *root) -{ - if (parent) { - if (parent->left == oldnode) - parent->left = newnode; - else - parent->right = newnode; - } else { - root->node = newnode; - } -} - -static inline struct ib_node * -_ib_node_rotate_left(struct ib_node *node, struct ib_root *root) -{ - struct ib_node *right = node->right; - struct ib_node *parent = node->parent; - node->right = right->left; - ASSERTION(node && right); - if (right->left) - right->left->parent = node; - right->left = node; - right->parent = parent; - _ib_child_replace(node, right, parent, root); - node->parent = right; - return right; -} - -static inline struct ib_node * -_ib_node_rotate_right(struct ib_node *node, struct ib_root *root) -{ - struct ib_node *left = node->left; - struct ib_node *parent = node->parent; - node->left = left->right; - ASSERTION(node && left); - if (left->right) - left->right->parent = node; - left->right = node; - left->parent = parent; - _ib_child_replace(node, left, parent, root); - node->parent = left; - return left; -} - -void ib_node_replace(struct ib_node *victim, struct ib_node *newnode, - struct ib_root *root) -{ - struct ib_node *parent = victim->parent; - _ib_child_replace(victim, newnode, parent, root); - if (victim->left) victim->left->parent = newnode; - if (victim->right) victim->right->parent = newnode; - newnode->left = victim->left; - newnode->right = victim->right; - newnode->parent = victim->parent; - newnode->height = victim->height; -} - - -/*--------------------------------------------------------------------*/ -/* avl - node manipulation */ -/*--------------------------------------------------------------------*/ - -static inline int IB_MAX(int x, int y) -{ -#if 1 - return (x < y)? y : x; /* this is faster with cmov on x86 */ -#else - return x - ((x - y) & ((x - y) >> (sizeof(int) * 8 - 1))); -#endif -} - -static inline void -_ib_node_height_update(struct ib_node *node) -{ - int h0 = IB_LEFT_HEIGHT(node); - int h1 = IB_RIGHT_HEIGHT(node); - node->height = IB_MAX(h0, h1) + 1; -} - -static inline struct ib_node * -_ib_node_fix_l(struct ib_node *node, struct ib_root *root) -{ - struct ib_node *right = node->right; - int rh0, rh1; - ASSERTION(right); - rh0 = IB_LEFT_HEIGHT(right); - rh1 = IB_RIGHT_HEIGHT(right); - if (rh0 > rh1) { - right = _ib_node_rotate_right(right, root); - _ib_node_height_update(right->right); - _ib_node_height_update(right); - /* _ib_node_height_update(node); */ - } - node = _ib_node_rotate_left(node, root); - _ib_node_height_update(node->left); - _ib_node_height_update(node); - return node; -} - -static inline struct ib_node * -_ib_node_fix_r(struct ib_node *node, struct ib_root *root) -{ - struct ib_node *left = node->left; - int rh0, rh1; - ASSERTION(left); - rh0 = IB_LEFT_HEIGHT(left); - rh1 = IB_RIGHT_HEIGHT(left); - if (rh0 < rh1) { - left = _ib_node_rotate_left(left, root); - _ib_node_height_update(left->left); - _ib_node_height_update(left); - /* _ib_node_height_update(node); */ - } - node = _ib_node_rotate_right(node, root); - _ib_node_height_update(node->right); - _ib_node_height_update(node); - return node; -} - -static inline void -_ib_node_rebalance(struct ib_node *node, struct ib_root *root) -{ - while (node) { - int h0 = (int)IB_LEFT_HEIGHT(node); - int h1 = (int)IB_RIGHT_HEIGHT(node); - int diff = h0 - h1; - int height = IB_MAX(h0, h1) + 1; - if (node->height != height) { - node->height = height; - } - else if (diff >= -1 && diff <= 1) { - break; - } - if (diff <= -2) { - node = _ib_node_fix_l(node, root); - } - else if (diff >= 2) { - node = _ib_node_fix_r(node, root); - } - node = node->parent; - } -} - -void ib_node_post_insert(struct ib_node *node, struct ib_root *root) -{ - node->height = 1; - - for (node = node->parent; node; node = node->parent) { - int h0 = (int)IB_LEFT_HEIGHT(node); - int h1 = (int)IB_RIGHT_HEIGHT(node); - int height = IB_MAX(h0, h1) + 1; - int diff = h0 - h1; - if (node->height == height) break; - node->height = height; - if (diff <= -2) { - node = _ib_node_fix_l(node, root); - } - else if (diff >= 2) { - node = _ib_node_fix_r(node, root); - } - } -} - -void ib_node_erase(struct ib_node *node, struct ib_root *root) -{ - struct ib_node *child, *parent; - ASSERTION(node); - if (node->left && node->right) { - struct ib_node *old = node; - struct ib_node *left; - node = node->right; - while ((left = node->left) != NULL) - node = left; - child = node->right; - parent = node->parent; - if (child) { - child->parent = parent; - } - _ib_child_replace(node, child, parent, root); - if (node->parent == old) - parent = node; - node->left = old->left; - node->right = old->right; - node->parent = old->parent; - node->height = old->height; - _ib_child_replace(old, node, old->parent, root); - ASSERTION(old->left); - old->left->parent = node; - if (old->right) { - old->right->parent = node; - } - } - else { - if (node->left == NULL) - child = node->right; - else - child = node->left; - parent = node->parent; - _ib_child_replace(node, child, parent, root); - if (child) { - child->parent = parent; - } - } - if (parent) { - _ib_node_rebalance(parent, root); - } -} - - -/* avl nodes destroy: fast tear down the whole tree */ -struct ib_node* ib_node_tear(struct ib_root *root, struct ib_node **next) -{ - struct ib_node *node = *next; - struct ib_node *parent; - if (node == NULL) { - if (root->node == NULL) - return NULL; - node = root->node; - } - /* sink down to the leaf */ - while (1) { - if (node->left) node = node->left; - else if (node->right) node = node->right; - else break; - } - /* tear down one leaf */ - parent = node->parent; - if (parent == NULL) { - *next = NULL; - root->node = NULL; - return node; - } - if (parent->left == node) { - parent->left = NULL; - } else { - parent->right = NULL; - } - node->height = 0; - *next = parent; - return node; -} - - - -/*--------------------------------------------------------------------*/ -/* avltree - friendly interface */ -/*--------------------------------------------------------------------*/ - -void ib_tree_init(struct ib_tree *tree, - int (*compare)(const void*, const void*), size_t size, size_t offset) -{ - tree->root.node = NULL; - tree->offset = offset; - tree->size = size; - tree->count = 0; - tree->compare = compare; -} - - -void *ib_tree_first(struct ib_tree *tree) -{ - struct ib_node *node = ib_node_first(&tree->root); - if (!node) return NULL; - return IB_NODE2DATA(node, tree->offset); -} - -void *ib_tree_last(struct ib_tree *tree) -{ - struct ib_node *node = ib_node_last(&tree->root); - if (!node) return NULL; - return IB_NODE2DATA(node, tree->offset); -} - -void *ib_tree_next(struct ib_tree *tree, void *data) -{ - struct ib_node *nn; - if (!data) return NULL; - nn = IB_DATA2NODE(data, tree->offset); - nn = ib_node_next(nn); - if (!nn) return NULL; - return IB_NODE2DATA(nn, tree->offset); -} - -void *ib_tree_prev(struct ib_tree *tree, void *data) -{ - struct ib_node *nn; - if (!data) return NULL; - nn = IB_DATA2NODE(data, tree->offset); - nn = ib_node_prev(nn); - if (!nn) return NULL; - return IB_NODE2DATA(nn, tree->offset); -} - - -/* require a temporary user structure (data) which contains the key */ -void *ib_tree_find(struct ib_tree *tree, const void *data) -{ - struct ib_node *n = tree->root.node; - int (*compare)(const void*, const void*) = tree->compare; - int offset = (int)(tree->offset); - while (n) { - void *nd = IB_NODE2DATA(n, offset); - int hr = compare(data, nd); - if (hr == 0) { - return nd; - } - else if (hr < 0) { - n = n->left; - } - else { - n = n->right; - } - } - return NULL; -} - -void *ib_tree_nearest(struct ib_tree *tree, const void *data) -{ - struct ib_node *n = tree->root.node; - struct ib_node *p = NULL; - int (*compare)(const void*, const void*) = tree->compare; - int offset = (int)(tree->offset); - while (n) { - void *nd = IB_NODE2DATA(n, offset); - int hr = compare(data, nd); - p = n; - if (n == 0) return nd; - else if (hr < 0) { - n = n->left; - } - else { - n = n->right; - } - } - return (p)? IB_NODE2DATA(p, offset) : NULL; -} - - -/* returns NULL for success, otherwise returns conflict node with same key */ -void *ib_tree_add(struct ib_tree *tree, void *data) -{ - struct ib_node **link = &tree->root.node; - struct ib_node *parent = NULL; - struct ib_node *node = IB_DATA2NODE(data, tree->offset); - int (*compare)(const void*, const void*) = tree->compare; - int offset = (int)(tree->offset); - while (link[0]) { - void *pd; - int hr; - parent = link[0]; - pd = IB_NODE2DATA(parent, offset); - hr = compare(data, pd); - if (hr == 0) { - return pd; - } - else if (hr < 0) { - link = &(parent->left); - } - else { - link = &(parent->right); - } - } - ib_node_link(node, parent, link); - ib_node_post_insert(node, &tree->root); - tree->count++; - return NULL; -} - - -void ib_tree_remove(struct ib_tree *tree, void *data) -{ - struct ib_node *node = IB_DATA2NODE(data, tree->offset); - if (!ib_node_empty(node)) { - ib_node_erase(node, &tree->root); - node->parent = node; - tree->count--; - } -} - - -void ib_tree_replace(struct ib_tree *tree, void *victim, void *newdata) -{ - struct ib_node *vicnode = IB_DATA2NODE(victim, tree->offset); - struct ib_node *newnode = IB_DATA2NODE(newdata, tree->offset); - ib_node_replace(vicnode, newnode, &tree->root); - vicnode->parent = vicnode; -} - - -void ib_tree_clear(struct ib_tree *tree, void (*destroy)(void *data)) -{ - while (1) { - void *data; - if (tree->root.node == NULL) break; - data = IB_NODE2DATA(tree->root.node, tree->offset); - ib_tree_remove(tree, data); - if (destroy) destroy(data); - } -} - - -/*--------------------------------------------------------------------*/ -/* fastbin - fixed size object allocator */ -/*--------------------------------------------------------------------*/ - -void ib_fastbin_init(struct ib_fastbin *fb, size_t obj_size) -{ - const size_t align = sizeof(void*); - size_t need; - fb->start = NULL; - fb->endup = NULL; - fb->next = NULL; - fb->pages = NULL; - fb->obj_size = (obj_size + align - 1) & (~(align - 1)); - need = fb->obj_size * 32 + sizeof(void*) + 16; - fb->page_size = (align <= 2)? 8 : 32; - while (fb->page_size < need) { - fb->page_size *= 2; - } - fb->maximum = (align <= 2)? fb->page_size : 0x10000; -} - -void ib_fastbin_destroy(struct ib_fastbin *fb) -{ - while (fb->pages) { - void *page = fb->pages; - void *next = IB_NEXT(page); - fb->pages = next; - ikmem_free(page); - } - fb->start = NULL; - fb->endup = NULL; - fb->next = NULL; - fb->pages = NULL; -} - -void* ib_fastbin_new(struct ib_fastbin *fb) -{ - size_t obj_size = fb->obj_size; - void *obj; - obj = fb->next; - if (obj) { - fb->next = IB_NEXT(fb->next); - return obj; - } - if (fb->start + obj_size > fb->endup) { - char *page = (char*)ikmem_malloc(fb->page_size); - size_t lineptr = (size_t)page; - ASSERTION(page); - IB_NEXT(page) = fb->pages; - fb->pages = page; - lineptr = (lineptr + sizeof(void*) + 15) & (~15); - fb->start = (char*)lineptr; - fb->endup = (char*)page + fb->page_size; - if (fb->page_size < fb->maximum) { - fb->page_size *= 2; - } - } - obj = fb->start; - fb->start += obj_size; - ASSERTION(fb->start <= fb->endup); - return obj; -} - -void ib_fastbin_del(struct ib_fastbin *fb, void *ptr) -{ - IB_NEXT(ptr) = fb->next; - fb->next = ptr; -} - - -/*--------------------------------------------------------------------*/ -/* string */ -/*--------------------------------------------------------------------*/ - -ib_string* ib_string_new(void) -{ - struct ib_string* str = (ib_string*)ikmem_malloc(sizeof(ib_string)); - assert(str); - str->ptr = str->sso; - str->size = 0; - str->capacity = IB_STRING_SSO; - str->ptr[0] = 0; - return str; -} - - -void ib_string_delete(ib_string *str) -{ - assert(str); - if (str) { - if (str->ptr && str->ptr != str->sso) - ikmem_free(str->ptr); - str->ptr = NULL; - str->size = str->capacity = 0; - } - ikmem_free(str); -} - -ib_string* ib_string_new_size(const char *text, int size) -{ - struct ib_string *str = ib_string_new(); - size = (size > 0)? size : 0; - if (size > 0 && text) { - ib_string_resize(str, size); - memcpy(str->ptr, text, size); - } - return str; -} - -ib_string* ib_string_new_from(const char *text) -{ - return ib_string_new_size(text, (text)? ((int)strlen(text)) : 0); -} - -static void _ib_string_set_capacity(ib_string *str, int capacity) -{ - assert(str); - assert(capacity >= 0); - if (capacity <= IB_STRING_SSO) { - capacity = IB_STRING_SSO; - if (str->ptr != str->sso) { - if (str->size > 0) { - int csize = (str->size < capacity) ? str->size : capacity; - memcpy(str->sso, str->ptr, csize); - } - ikmem_free(str->ptr); - str->ptr = str->sso; - str->capacity = IB_STRING_SSO; - } - } - else { - char *ptr = (char*)ikmem_malloc(capacity + 2); - int csize = (capacity < str->size) ? capacity : str->size; - assert(ptr); - if (csize > 0) { - memcpy(ptr, str->ptr, csize); - } - if (str->ptr != str->sso) - ikmem_free(str->ptr); - str->ptr = ptr; - str->capacity = capacity; - } - if (str->size > str->capacity) - str->size = str->capacity; - str->ptr[str->size] = 0; -} - -ib_string* ib_string_resize(ib_string *str, int newsize) -{ - assert(str && newsize >= 0); - if (newsize > str->capacity) { - int capacity = str->capacity * 2; - if (capacity < newsize) { - while (capacity < newsize) { - capacity = capacity * 2; - } - } - _ib_string_set_capacity(str, capacity); - } - str->size = newsize; - str->ptr[str->size] = 0; - return str; -} - -ib_string* ib_string_reserve(ib_string *str, int newsize) -{ - int size = (newsize >= str->size)? newsize : str->size; - _ib_string_set_capacity(str, size); - return str; -} - -ib_string* ib_string_insert(ib_string *str, int pos, - const void *data, int size) -{ - int current = str->size; - if (pos < 0 || pos > str->size) - return NULL; - ib_string_resize(str, str->size + size); - if (pos < current) { - memmove(str->ptr + pos + size, str->ptr + pos, current - pos); - } - if (data) { - memcpy(str->ptr + pos, data, size); - } - return str; -} - -ib_string* ib_string_insert_c(ib_string *str, int pos, char c) -{ - int current = str->size; - if (pos < 0 || pos > str->size) - return NULL; - ib_string_resize(str, str->size + 1); - if (pos < current) { - memmove(str->ptr + pos + 1, str->ptr + pos, current - pos); - } - str->ptr[pos] = c; - return str; -} - -ib_string* ib_string_erase(ib_string *str, int pos, int size) -{ - int current = str->size; - if (pos >= current) return 0; - if (pos + size >= current) size = current - pos; - if (size == 0) return 0; - memmove(str->ptr + pos, str->ptr + pos + size, current - pos - size); - return ib_string_resize(str, current - size); -} - -int ib_string_compare(const struct ib_string *a, const struct ib_string *b) -{ - int minsize = (a->size < b->size)? a->size : b->size; - int hr = memcmp(a->ptr, b->ptr, minsize); - if (hr < 0) return -1; - else if (hr > 0) return 1; - if (a->size < b->size) return -1; - else if (a->size > b->size) return 1; - return 0; -} - - -ib_string* ib_string_assign(ib_string *str, const char *src) -{ - return ib_string_assign_size(str, src, (int)strlen(src)); -} - -ib_string* ib_string_assign_size(ib_string *str, const char *src, int size) -{ - assert(size >= 0); - ib_string_resize(str, size); - if (src) { - memcpy(str->ptr, src, size); - } - return str; -} - - -ib_string* ib_string_append(ib_string *str, const char *src) -{ - return ib_string_append_size(str, src, (int)strlen(src)); -} - - -ib_string* ib_string_append_size(ib_string *str, const char *src, int size) -{ - return ib_string_insert(str, str->size, src, size); -} - -ib_string* ib_string_append_c(ib_string *str, char c) -{ - ib_string_resize(str, str->size + 1); - str->ptr[str->size - 1] = c; - return str; -} - -ib_string* ib_string_prepend(ib_string *str, const char *src) -{ - return ib_string_prepend_size(str, src, (int)strlen(src)); -} - -ib_string* ib_string_prepend_size(ib_string *str, const char *src, int size) -{ - return ib_string_insert(str, 0, src, size); -} - -ib_string* ib_string_prepend_c(ib_string *str, char c) -{ - int current = str->size; - ib_string_resize(str, current + 1); - if (current > 0) { - memmove(str->ptr + 1, str->ptr, current); - } - str->ptr[0] = c; - return str; -} - -ib_string* ib_string_rewrite(ib_string *str, int pos, const char *src) -{ - return ib_string_rewrite_size(str, pos, src, (int)strlen(src)); -} - -ib_string* ib_string_rewrite_size(ib_string *str, int pos, - const char *src, int size) -{ - if (pos < 0) size += pos, pos = 0; - if (pos + size >= str->size) size = str->size - pos; - if (size <= 0) return str; - if (src) { - memcpy(str->ptr + pos, src, size); - } - return str; -} - - -int ib_string_find(const ib_string *str, const char *src, int len, int start) -{ - char *text = str->ptr; - int pos = (start < 0)? 0 : start; - int length = (len >= 0)? len : ((int)strlen(src)); - int endup = str->size - length; - char ch; - if (length <= 0) return pos; - for (ch = src[0]; pos <= endup; pos++) { - if (text[pos] == ch) { - if (memcmp(text + pos, src, length) == 0) - return pos; - } - } - return -1; -} - -int ib_string_find_c(const ib_string *str, char ch, int start) -{ - const char *text = str->ptr; - int pos = (start < 0)? 0 : start; - int endup = str->size; - for (; pos < endup; pos++) { - if (text[pos] == ch) return pos; - } - return -1; -} - -ib_array* ib_string_split(const ib_string *str, const char *sep, int len) -{ - if (len == 0) { - return NULL; - } - else { - ib_array *array = ib_array_new((void (*)(void*))ib_string_delete); - int start = 0; - len = (len >= 0)? len : ((int)strlen(sep)); - while (1) { - int pos = ib_string_find(str, sep, len, start); - if (pos < 0) { - ib_string *newstr = ib_string_new(); - ib_string_assign_size(newstr, str->ptr + start, - str->size - start); - ib_array_push(array, newstr); - break; - } - else { - ib_string* newstr = ib_string_new(); - ib_string_assign_size(newstr, str->ptr + start, pos - start); - start = pos + len; - ib_array_push(array, newstr); - } - } - return array; - } -} - -ib_array* ib_string_split_c(const ib_string *str, char sep) -{ - if (str == NULL) { - return NULL; - } - else { - ib_array *array = ib_array_new((void (*)(void*))ib_string_delete); - int start = 0; - while (1) { - int pos = ib_string_find_c(str, sep, start); - if (pos < 0) { - ib_string *newstr = ib_string_new(); - ib_string_assign_size(newstr, str->ptr + start, - str->size - start); - ib_array_push(array, newstr); - break; - } - else { - ib_string *newstr = ib_string_new(); - ib_string_assign_size(newstr, str->ptr + start, pos - start); - start = pos + 1; - ib_array_push(array, newstr); - } - } - return array; - } -} - -ib_string* ib_string_strip(ib_string *str, const char *seps) -{ - const char *ptr = str->ptr; - const char *endup = str->ptr + str->size; - int off, pos; - for (; ptr < endup; ptr++) { - const char *sep = seps; - int match = 0; - for (; sep[0]; sep++) { - if (ptr[0] == sep[0]) { - match = 1; - break; - } - } - if (match == 0) break; - } - off = (int)(ptr - str->ptr); - if (off > 0) { - ib_string_erase(str, 0, off); - } - ptr = str->ptr; - pos = str->size; - for (; pos > 0; pos--) { - const char *sep = seps; - int match = 0; - for (; sep[0]; sep++) { - if (ptr[pos - 1] == sep[0]) { - match = 1; - break; - } - } - if (match == 0) break; - } - ib_string_resize(str, pos); - return str; -} - -ib_string* ib_string_replace_size(ib_string *str, int pos, int size, - const char *src, int len) -{ - ib_string_erase(str, pos, size); - ib_string_insert(str, pos, src, len); - return str; -} - - -/*--------------------------------------------------------------------*/ -/* static hash table (closed hash table with avlnode) */ -/*--------------------------------------------------------------------*/ - - -void ib_hash_init(struct ib_hash_table *ht, - size_t (*hash)(const void *key), - int (*compare)(const void *key1, const void *key2)) -{ - size_t i; - ht->count = 0; - ht->index_size = IB_HASH_INIT_SIZE; - ht->index_mask = ht->index_size - 1; - ht->hash = hash; - ht->compare = compare; - ilist_init(&ht->head); - ht->index = ht->init; - for (i = 0; i < IB_HASH_INIT_SIZE; i++) { - ht->index[i].avlroot.node = NULL; - ilist_init(&(ht->index[i].node)); - } -} - -struct ib_hash_node* ib_hash_node_first(struct ib_hash_table *ht) -{ - struct ILISTHEAD *head = ht->head.next; - if (head != &ht->head) { - struct ib_hash_index *index = - ilist_entry(head, struct ib_hash_index, node); - struct ib_node *avlnode = ib_node_first(&index->avlroot); - if (avlnode == NULL) return NULL; - return IB_ENTRY(avlnode, struct ib_hash_node, avlnode); - } - return NULL; -} - -struct ib_hash_node* ib_hash_node_last(struct ib_hash_table *ht) -{ - struct ILISTHEAD *head = ht->head.prev; - if (head != &ht->head) { - struct ib_hash_index *index = - ilist_entry(head, struct ib_hash_index, node); - struct ib_node *avlnode = ib_node_last(&index->avlroot); - if (avlnode == NULL) return NULL; - return IB_ENTRY(avlnode, struct ib_hash_node, avlnode); - } - return NULL; -} - -struct ib_hash_node* ib_hash_node_next(struct ib_hash_table *ht, - struct ib_hash_node *node) -{ - struct ib_node *avlnode; - struct ib_hash_index *index; - struct ILISTHEAD *listnode; - if (node == NULL) return NULL; - avlnode = ib_node_next(&node->avlnode); - if (avlnode) { - return IB_ENTRY(avlnode, struct ib_hash_node, avlnode); - } - index = &(ht->index[node->hash & ht->index_mask]); - listnode = index->node.next; - if (listnode == &(ht->head)) { - return NULL; - } - index = ilist_entry(listnode, struct ib_hash_index, node); - avlnode = ib_node_first(&index->avlroot); - if (avlnode == NULL) return NULL; - return IB_ENTRY(avlnode, struct ib_hash_node, avlnode); -} - -struct ib_hash_node* ib_hash_node_prev(struct ib_hash_table *ht, - struct ib_hash_node *node) -{ - struct ib_node *avlnode; - struct ib_hash_index *index; - struct ILISTHEAD *listnode; - if (node == NULL) return NULL; - avlnode = ib_node_prev(&node->avlnode); - if (avlnode) { - return IB_ENTRY(avlnode, struct ib_hash_node, avlnode); - } - index = &(ht->index[node->hash & ht->index_mask]); - listnode = index->node.prev; - if (listnode == &(ht->head)) { - return NULL; - } - index = ilist_entry(listnode, struct ib_hash_index, node); - avlnode = ib_node_last(&index->avlroot); - if (avlnode == NULL) return NULL; - return IB_ENTRY(avlnode, struct ib_hash_node, avlnode); -} - -struct ib_hash_node* ib_hash_find(struct ib_hash_table *ht, - const struct ib_hash_node *node) -{ - size_t hash = node->hash; - const void *key = node->key; - struct ib_hash_index *index = &(ht->index[hash & ht->index_mask]); - struct ib_node *avlnode = index->avlroot.node; - int (*compare)(const void *, const void *) = ht->compare; - while (avlnode) { - struct ib_hash_node *snode = - IB_ENTRY(avlnode, struct ib_hash_node, avlnode); - size_t shash = snode->hash; - if (hash == shash) { - int hc = compare(key, snode->key); - if (hc == 0) return snode; - avlnode = (hc < 0)? avlnode->left : avlnode->right; - } - else { - avlnode = (hash < shash)? avlnode->left : avlnode->right; - } - } - return NULL; -} - -void ib_hash_erase(struct ib_hash_table *ht, struct ib_hash_node *node) -{ - struct ib_hash_index *index; - ASSERTION(node && ht); - ASSERTION(!ib_node_empty(&node->avlnode)); - index = &ht->index[node->hash & ht->index_mask]; - if (index->avlroot.node == &node->avlnode && node->avlnode.height == 1) { - index->avlroot.node = NULL; - ilist_del_init(&index->node); - } - else { - ib_node_erase(&node->avlnode, &index->avlroot); - } - ib_node_init(&node->avlnode); - ht->count--; -} - -struct ib_node** ib_hash_track(struct ib_hash_table *ht, - const struct ib_hash_node *node, struct ib_node **parent) -{ - size_t hash = node->hash; - const void *key = node->key; - struct ib_hash_index *index = &(ht->index[hash & ht->index_mask]); - struct ib_node **link = &index->avlroot.node; - struct ib_node *p = NULL; - int (*compare)(const void *key1, const void *key2) = ht->compare; - parent[0] = NULL; - while (link[0]) { - struct ib_hash_node *snode; - size_t shash; - p = link[0]; - snode = IB_ENTRY(p, struct ib_hash_node, avlnode); - shash = snode->hash; - if (hash == shash) { - int hc = compare(key, snode->key); - if (hc == 0) { - parent[0] = p; - return NULL; - } - link = (hc < 0)? (&p->left) : (&p->right); - } - else { - link = (hash < shash)? (&p->left) : (&p->right); - } - } - parent[0] = p; - return link; -} - - -struct ib_hash_node* ib_hash_add(struct ib_hash_table *ht, - struct ib_hash_node *node) -{ - struct ib_hash_index *index = &(ht->index[node->hash & ht->index_mask]); - if (index->avlroot.node == NULL) { - index->avlroot.node = &node->avlnode; - node->avlnode.parent = NULL; - node->avlnode.left = NULL; - node->avlnode.right = NULL; - node->avlnode.height = 1; - ilist_add_tail(&index->node, &ht->head); - } - else { - struct ib_node **link, *parent; - link = ib_hash_track(ht, node, &parent); - if (link == NULL) { - ASSERTION(parent); - return IB_ENTRY(parent, struct ib_hash_node, avlnode); - } - ib_node_link(&node->avlnode, parent, link); - ib_node_post_insert(&node->avlnode, &index->avlroot); - } - ht->count++; - return NULL; -} - - -void ib_hash_replace(struct ib_hash_table *ht, - struct ib_hash_node *victim, struct ib_hash_node *newnode) -{ - struct ib_hash_index *index = &ht->index[victim->hash & ht->index_mask]; - ib_node_replace(&victim->avlnode, &newnode->avlnode, &index->avlroot); -} - -void ib_hash_clear(struct ib_hash_table *ht, - void (*destroy)(struct ib_hash_node *node)) -{ - while (!ilist_is_empty(&ht->head)) { - struct ib_hash_index *index = ilist_entry(ht->head.next, - struct ib_hash_index, node); - struct ib_node *next = NULL; - while (index->avlroot.node != NULL) { - struct ib_node *avlnode = ib_node_tear(&index->avlroot, &next); - ASSERTION(avlnode); - if (destroy) { - struct ib_hash_node *node = - IB_ENTRY(avlnode, struct ib_hash_node, avlnode); - destroy(node); - } - } - ilist_del_init(&index->node); - } - ht->count = 0; -} - - -void* ib_hash_swap(struct ib_hash_table *ht, void *ptr, size_t nbytes) -{ - struct ib_hash_index *old_index = ht->index; - struct ib_hash_index *new_index = (struct ib_hash_index*)ptr; - size_t index_size = 1; - struct ILISTHEAD head; - size_t i; - ASSERTION(nbytes >= sizeof(struct ib_hash_index)); - if (new_index == NULL) { - if (ht->index == ht->init) { - return NULL; - } - new_index = ht->init; - index_size = IB_HASH_INIT_SIZE; - } - else if (new_index == old_index) { - return old_index; - } - if (new_index != ht->init) { - size_t test_size = sizeof(struct ib_hash_index); - while (test_size < nbytes) { - size_t next_size = test_size * 2; - if (next_size > nbytes) break; - test_size = next_size; - index_size = index_size * 2; - } - } - ht->index = new_index; - ht->index_size = index_size; - ht->index_mask = index_size - 1; - ht->count = 0; - for (i = 0; i < index_size; i++) { - ht->index[i].avlroot.node = NULL; - ilist_init(&ht->index[i].node); - } - ilist_replace(&ht->head, &head); - ilist_init(&ht->head); - while (!ilist_is_empty(&head)) { - struct ib_hash_index *index = ilist_entry(head.next, - struct ib_hash_index, node); - #if 1 - struct ib_node *next = NULL; - while (index->avlroot.node) { - struct ib_node *avlnode = ib_node_tear(&index->avlroot, &next); - struct ib_hash_node *snode, *hr; - ASSERTION(avlnode); - snode = IB_ENTRY(avlnode, struct ib_hash_node, avlnode); - hr = ib_hash_add(ht, snode); - if (hr != NULL) { - ASSERTION(hr == NULL); - return NULL; - } - } - #else - while (index->avlroot.node) { - struct ib_node *avlnode = index->avlroot.node; - struct ib_hash_node *snode, *hr; - ib_node_erase(avlnode, &index->avlroot); - snode = IB_ENTRY(avlnode, struct ib_hash_node, avlnode); - hr = ib_hash_add(ht, snode); - ASSERTION(hr == NULL); - hr = hr; - } - #endif - ilist_del_init(&index->node); - } - return (old_index == ht->init)? NULL : old_index; -} - - -/*--------------------------------------------------------------------*/ -/* hash map, wrapper of ib_hash_table to support direct key/value */ -/*--------------------------------------------------------------------*/ - -struct ib_hash_entry* ib_map_first(struct ib_hash_map *hm) -{ - struct ib_hash_node *node = ib_hash_node_first(&hm->ht); - if (node == NULL) return NULL; - return IB_ENTRY(node, struct ib_hash_entry, node); -} - - -struct ib_hash_entry* ib_map_last(struct ib_hash_map *hm) -{ - struct ib_hash_node *node = ib_hash_node_last(&hm->ht); - if (node == NULL) return NULL; - return IB_ENTRY(node, struct ib_hash_entry, node); -} - - -struct ib_hash_entry* ib_map_next(struct ib_hash_map *hm, - struct ib_hash_entry *n) -{ - struct ib_hash_node *node = ib_hash_node_next(&hm->ht, &n->node); - if (node == NULL) return NULL; - return IB_ENTRY(node, struct ib_hash_entry, node); -} - - -struct ib_hash_entry* ib_map_prev(struct ib_hash_map *hm, - struct ib_hash_entry *n) -{ - struct ib_hash_node *node = ib_hash_node_prev(&hm->ht, &n->node); - if (node == NULL) return NULL; - return IB_ENTRY(node, struct ib_hash_entry, node); -} - - -void ib_map_init(struct ib_hash_map *hm, size_t (*hash)(const void*), - int (*compare)(const void *, const void *)) -{ - hm->count = 0; - hm->key_copy = NULL; - hm->key_destroy = NULL; - hm->value_copy = NULL; - hm->value_destroy = NULL; - hm->insert = 0; - hm->fixed = 0; - ib_hash_init(&hm->ht, hash, compare); - ib_fastbin_init(&hm->fb, sizeof(struct ib_hash_entry)); -} - -void ib_map_destroy(struct ib_hash_map *hm) -{ - void *ptr; - ib_map_clear(hm); - ptr = ib_hash_swap(&hm->ht, NULL, 0); - if (ptr) { - ikmem_free(ptr); - } - ib_fastbin_destroy(&hm->fb); -} - -struct ib_hash_entry* ib_map_find(struct ib_hash_map *hm, const void *key) -{ - struct ib_hash_table *ht = &hm->ht; - struct ib_hash_node dummy; - struct ib_hash_node *rh; - void *ptr = (void*)key; - ib_hash_node_key(ht, &dummy, ptr); - rh = ib_hash_find(ht, &dummy); - return (rh == NULL)? NULL : IB_ENTRY(rh, struct ib_hash_entry, node); -} - - -void* ib_map_lookup(struct ib_hash_map *hm, const void *key, void *defval) -{ - struct ib_hash_entry *entry = ib_map_find(hm, key); - if (entry == NULL) return defval; - return ib_hash_value(entry); -} - -static inline struct ib_hash_entry* -ib_hash_entry_allocate(struct ib_hash_map *hm, void *key, void *value) -{ - struct ib_hash_entry *entry; - entry = (struct ib_hash_entry*)ib_fastbin_new(&hm->fb); - ASSERTION(entry); - if (hm->key_copy) entry->node.key = hm->key_copy(key); - else entry->node.key = key; - if (hm->value_copy) entry->value = hm->value_copy(value); - else entry->value = value; - return entry; -} - -static inline struct ib_hash_entry* -ib_hash_update(struct ib_hash_map *hm, void *key, void *value, int update) -{ - size_t hash = hm->ht.hash(key); - struct ib_hash_index *index = &(hm->ht.index[hash & hm->ht.index_mask]); - struct ib_node **link = &index->avlroot.node; - struct ib_node *parent = NULL; - struct ib_hash_entry *entry; - int (*compare)(const void *key1, const void *key2) = hm->ht.compare; - if (index->avlroot.node == NULL) { - entry = ib_hash_entry_allocate(hm, key, value); - ASSERTION(entry); - entry->node.avlnode.height = 1; - entry->node.avlnode.left = NULL; - entry->node.avlnode.right = NULL; - entry->node.avlnode.parent = NULL; - entry->node.hash = hash; - index->avlroot.node = &(entry->node.avlnode); - ilist_add_tail(&index->node, &(hm->ht.head)); - hm->ht.count++; - hm->insert = 1; - return entry; - } - while (link[0]) { - struct ib_hash_node *snode; - size_t shash; - parent = link[0]; - snode = IB_ENTRY(parent, struct ib_hash_node, avlnode); - shash = snode->hash; - if (hash != shash) { - link = (hash < shash)? (&parent->left) : (&parent->right); - } else { - int hc = compare(key, snode->key); - if (hc == 0) { - entry = IB_ENTRY(snode, struct ib_hash_entry, node); - if (update) { - if (hm->value_destroy) { - hm->value_destroy(entry->value); - } - if (hm->value_copy == NULL) entry->value = value; - else entry->value = hm->value_copy(value); - } - hm->insert = 0; - return entry; - } else { - link = (hc < 0)? (&parent->left) : (&parent->right); - } - } - } - entry = ib_hash_entry_allocate(hm, key, value); - ASSERTION(entry); - entry->node.hash = hash; - ib_node_link(&(entry->node.avlnode), parent, link); - ib_node_post_insert(&(entry->node.avlnode), &index->avlroot); - hm->ht.count++; - hm->insert = 1; - return entry; -} - -static inline void ib_map_rehash(struct ib_hash_map *hm, size_t capacity) -{ - size_t isize = hm->ht.index_size; - size_t limit = (capacity * 6) >> 2; /* capacity * 6 / 4 */ - if (isize < limit && hm->fixed == 0) { - size_t need = isize; - size_t size; - void *ptr; - while (need < limit) need <<= 1; - size = need * sizeof(struct ib_hash_index); - ptr = ikmem_malloc(size); - ASSERTION(ptr); - ptr = ib_hash_swap(&hm->ht, ptr, size); - if (ptr) { - ikmem_free(ptr); - } - } -} - -void ib_map_reserve(struct ib_hash_map *hm, size_t capacity) -{ - ib_map_rehash(hm, capacity); -} - -struct ib_hash_entry* -ib_map_add(struct ib_hash_map *hm, void *key, void *value, int *success) -{ - struct ib_hash_entry *entry = ib_hash_update(hm, key, value, 0); - if (success) success[0] = hm->insert; - ib_map_rehash(hm, hm->ht.count); - return entry; -} - -struct ib_hash_entry* -ib_map_set(struct ib_hash_map *hm, void *key, void *value) -{ - struct ib_hash_entry *entry = ib_hash_update(hm, key, value, 0); - ib_map_rehash(hm, hm->ht.count); - return entry; -} - -void *ib_map_get(struct ib_hash_map *hm, const void *key) -{ - return ib_map_lookup(hm, key, NULL); -} - -void ib_map_erase(struct ib_hash_map *hm, struct ib_hash_entry *entry) -{ - ASSERTION(entry); - ASSERTION(!ib_node_empty(&(entry->node.avlnode))); - ib_hash_erase(&hm->ht, &entry->node); - ib_node_init(&(entry->node.avlnode)); - if (hm->key_destroy) hm->key_destroy(entry->node.key); - if (hm->value_destroy) hm->value_destroy(entry->value); - entry->node.key = NULL; - entry->value = NULL; - ib_fastbin_del(&hm->fb, entry); -} - -int ib_map_remove(struct ib_hash_map *hm, const void *key) -{ - struct ib_hash_entry *entry; - entry = ib_map_find(hm, key); - if (entry == NULL) { - return -1; - } - ib_map_erase(hm, entry); - return 0; -} - -void ib_map_clear(struct ib_hash_map *hm) -{ - while (1) { - struct ib_hash_entry *entry = ib_map_first(hm); - if (entry == NULL) break; - ib_map_erase(hm, entry); - } - ASSERTION(hm->count == 0); -} - - -/*--------------------------------------------------------------------*/ -/* common type hash and equal functions */ -/*--------------------------------------------------------------------*/ -size_t ib_hash_seed = 0x11223344; - -size_t ib_hash_func_uint(const void *key) -{ -#if 0 - size_t x = (size_t)key; - return (x * 2654435761u) ^ ib_hash_seed; -#else - return (size_t)key; -#endif -} - -size_t ib_hash_func_int(const void *key) -{ -#if 0 - size_t x = (size_t)key; - return (x * 2654435761u) ^ ib_hash_seed; -#else - return (size_t)key; -#endif -} - -size_t ib_hash_bytes_stl(const void *ptr, size_t size, size_t seed) -{ - const unsigned char *buf = (const unsigned char*)ptr; - const size_t m = 0x5bd1e995; - size_t hash = size ^ seed; - for (; size >= 4; buf += 4, size -= 4) { - size_t k = *((IUINT32*)buf); - k *= m; - k = (k >> 24) * m; - hash = (hash * m) ^ k; - } - switch (size) { - case 3: hash ^= ((IUINT32)buf[2]) << 16; - case 2: hash ^= ((IUINT32)buf[1]) << 8; - case 1: hash ^= ((IUINT32)buf[0]); hash = hash * m; break; - } - hash = (hash ^ (hash >> 13)) * m; - return hash ^ (hash >> 15); -} - -size_t ib_hash_bytes_lua(const void *ptr, size_t size, size_t seed) -{ - const unsigned char *name = (const unsigned char*)ptr; - size_t step = (size >> 5) + 1; - size_t h = size ^ seed, i; - for(i = size; i >= step; i -= step) - h = h ^ ((h << 5) + (h >> 2) + (size_t)name[i - 1]); - return h; -} - -size_t ib_hash_func_str(const void *key) -{ - ib_string *str = (ib_string*)key; -#ifndef IB_HASH_BYTES_STL - return ib_hash_bytes_lua(str->ptr, str->size, ib_hash_seed); -#else - return ib_hash_bytes_stl(str->ptr, str->size, ib_hash_seed); -#endif -} - -size_t ib_hash_func_cstr(const void *key) -{ - const char *str = (const char*)key; - size_t size = strlen(str); -#ifndef IB_HASH_BYTES_STL - return ib_hash_bytes_lua(str, size, ib_hash_seed); -#else - return ib_hash_bytes_stl(str, size, ib_hash_seed); -#endif -} - -int ib_hash_compare_uint(const void *key1, const void *key2) -{ - size_t x = (size_t)key1; - size_t y = (size_t)key2; - if (x == y) return 0; - return (x < y)? -1 : 1; -} - -int ib_hash_compare_int(const void *key1, const void *key2) -{ - ilong x = (ilong)key1; - ilong y = (ilong)key2; - if (x == y) return 0; - return (x < y)? -1 : 1; -} - -int ib_hash_compare_str(const void *key1, const void *key2) -{ - return ib_string_compare((const ib_string*)key1, (const ib_string*)key2); -} - -int ib_compare_bytes(const void *p1, size_t s1, const void *p2, size_t s2) -{ - size_t minsize = (s1 < s2)? s1 : s2; - int hr = memcmp(p1, p2, minsize); - if (hr == 0) { - if (s1 == s2) return 0; - return (s1 < s2)? -1 : 1; - } - else { - return (hr < 0)? -1 : 1; - } -} - -int ib_hash_compare_cstr(const void *key1, const void *key2) -{ - const char *x = (const char*)key1; - const char *y = (const char*)key2; - return ib_compare_bytes(x, strlen(x), y, strlen(y)); -} - - - -struct ib_hash_entry *ib_map_find_uint(struct ib_hash_map *hm, iulong key) -{ - struct ib_hash_entry *hr; - void *kk = (void*)key; - ib_map_search(hm, kk, ib_hash_func_uint, ib_hash_compare_uint, hr); - return hr; -} - -struct ib_hash_entry *ib_map_find_int(struct ib_hash_map *hm, ilong key) -{ - struct ib_hash_entry *hr; - void *kk = (void*)key; - ib_map_search(hm, kk, ib_hash_func_int, ib_hash_compare_int, hr); - return hr; -} - -struct ib_hash_entry *ib_map_find_str(struct ib_hash_map *hm, const ib_string *key) -{ - struct ib_hash_entry *hr; - void *kk = (void*)key; - ib_map_search(hm, kk, ib_hash_func_str, ib_hash_compare_str, hr); - return hr; -} - -struct ib_hash_entry *ib_map_find_cstr(struct ib_hash_map *hm, const char *key) -{ - struct ib_hash_entry *hr; - void *kk = (void*)key; - ib_map_search(hm, kk, ib_hash_func_cstr, ib_hash_compare_cstr, hr); - return hr; -} - - - - diff --git a/czmod/imembase.h b/czmod/imembase.h deleted file mode 100644 index 811b177..0000000 --- a/czmod/imembase.h +++ /dev/null @@ -1,916 +0,0 @@ -/********************************************************************** - * - * imembase.h - basic interface of memory operation - * skywind3000 (at) gmail.com, 2006-2016 - * - **********************************************************************/ - -#ifndef __IMEMBASE_H__ -#define __IMEMBASE_H__ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include -#include - - -/********************************************************************** - * 32BIT INTEGER DEFINITION - **********************************************************************/ -#ifndef __INTEGER_32_BITS__ -#define __INTEGER_32_BITS__ -#if defined(__UINT32_TYPE__) && defined(__UINT32_TYPE__) - typedef __UINT32_TYPE__ ISTDUINT32; - typedef __INT32_TYPE__ ISTDINT32; -#elif defined(__UINT_FAST32_TYPE__) && defined(__INT_FAST32_TYPE__) - typedef __UINT_FAST32_TYPE__ ISTDUINT32; - typedef __INT_FAST32_TYPE__ ISTDINT32; -#elif defined(_WIN64) || defined(WIN64) || defined(__amd64__) || \ - defined(__x86_64) || defined(__x86_64__) || defined(_M_IA64) || \ - defined(_M_AMD64) - typedef unsigned int ISTDUINT32; - typedef int ISTDINT32; -#elif defined(_WIN32) || defined(WIN32) || defined(__i386__) || \ - defined(__i386) || defined(_M_X86) - typedef unsigned long ISTDUINT32; - typedef long ISTDINT32; -#elif defined(__MACOS__) - typedef UInt32 ISTDUINT32; - typedef SInt32 ISTDINT32; -#elif defined(__APPLE__) && defined(__MACH__) - #include - typedef u_int32_t ISTDUINT32; - typedef int32_t ISTDINT32; -#elif defined(__BEOS__) - #include - typedef u_int32_t ISTDUINT32; - typedef int32_t ISTDINT32; -#elif (defined(_MSC_VER) || defined(__BORLANDC__)) && (!defined(__MSDOS__)) - typedef unsigned __int32 ISTDUINT32; - typedef __int32 ISTDINT32; -#elif defined(__GNUC__) && (__GNUC__ > 3) - #include - typedef uint32_t ISTDUINT32; - typedef int32_t ISTDINT32; -#else -#include -#if UINT_MAX == 0xFFFFU - typedef unsigned long ISTDUINT32; - typedef long ISTDINT32; -#else - typedef unsigned int ISTDUINT32; - typedef int ISTDINT32; -#endif -#endif -#endif - - -/********************************************************************** - * Global Macros - **********************************************************************/ -#ifndef __IUINT8_DEFINED -#define __IUINT8_DEFINED -typedef unsigned char IUINT8; -#endif - -#ifndef __IINT8_DEFINED -#define __IINT8_DEFINED -typedef signed char IINT8; -#endif - -#ifndef __IUINT16_DEFINED -#define __IUINT16_DEFINED -typedef unsigned short IUINT16; -#endif - -#ifndef __IINT16_DEFINED -#define __IINT16_DEFINED -typedef signed short IINT16; -#endif - -#ifndef __IINT32_DEFINED -#define __IINT32_DEFINED -typedef ISTDINT32 IINT32; -#endif - -#ifndef __IUINT32_DEFINED -#define __IUINT32_DEFINED -typedef ISTDUINT32 IUINT32; -#endif - - -/*--------------------------------------------------------------------*/ -/* INLINE */ -/*--------------------------------------------------------------------*/ -#ifndef INLINE -#if defined(__GNUC__) - -#if (__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 1)) -#define INLINE __inline__ __attribute__((always_inline)) -#else -#define INLINE __inline__ -#endif - -#elif (defined(_MSC_VER) || defined(__WATCOMC__)) -#define INLINE __inline -#else -#define INLINE -#endif -#endif - -#if (!defined(__cplusplus)) && (!defined(inline)) -#define inline INLINE -#endif - -/* you can change this by config.h or predefined macro */ -#ifndef ASSERTION -#define ASSERTION(x) ((void)0) -#endif - - -/*====================================================================*/ -/* IULONG/ILONG (ensure sizeof(iulong) == sizeof(void*)) */ -/*====================================================================*/ -#ifndef __IULONG_DEFINED -#define __IULONG_DEFINED -typedef ptrdiff_t ilong; -typedef size_t iulong; -#endif - -#ifdef __cplusplus -extern "C" { -#endif - - -/*====================================================================*/ -/* IALLOCATOR */ -/*====================================================================*/ -struct IALLOCATOR -{ - void *(*alloc)(struct IALLOCATOR *, size_t); - void (*free)(struct IALLOCATOR *, void *); - void *(*realloc)(struct IALLOCATOR *, void *, size_t); - void *udata; -}; - -void* internal_malloc(struct IALLOCATOR *allocator, size_t size); -void internal_free(struct IALLOCATOR *allocator, void *ptr); -void* internal_realloc(struct IALLOCATOR *allocator, void *ptr, size_t size); - - -/*====================================================================*/ -/* IKMEM INTERFACE */ -/*====================================================================*/ -extern struct IALLOCATOR *ikmem_allocator; - -void* ikmem_malloc(size_t size); -void* ikmem_realloc(void *ptr, size_t size); -void ikmem_free(void *ptr); - - -/*====================================================================*/ -/* IVECTOR */ -/*====================================================================*/ -struct IVECTOR -{ - unsigned char *data; - size_t size; - size_t capacity; - struct IALLOCATOR *allocator; -}; - -void iv_init(struct IVECTOR *v, struct IALLOCATOR *allocator); -void iv_destroy(struct IVECTOR *v); -int iv_resize(struct IVECTOR *v, size_t newsize); -int iv_reserve(struct IVECTOR *v, size_t newsize); - -size_t iv_pop(struct IVECTOR *v, void *data, size_t size); -int iv_push(struct IVECTOR *v, const void *data, size_t size); -int iv_insert(struct IVECTOR *v, size_t pos, const void *data, size_t size); -int iv_erase(struct IVECTOR *v, size_t pos, size_t size); - -#define iv_size(v) ((v)->size) -#define iv_data(v) ((v)->data) - -#define iv_entry(v, type) ((type*)iv_data(v)) - -#define iv_obj_index(v, type, index) (iv_entry(v, type)[index]) -#define iv_obj_push(v, type, objptr) iv_push(v, objptr, sizeof(type)) -#define iv_obj_pop(v, type, objptr) iv_pop(v, objptr, sizeof(type)) -#define iv_obj_size(v, type) (((v)->size) / sizeof(type)) -#define iv_obj_capacity(v, type) (((v)->capacity) / sizeof(type)) -#define iv_obj_resize(v, type, count) iv_resize(v, (count) * sizeof(type)) -#define iv_obj_reserve(v, type, count) iv_reserve(v, (count) * sizeof(type)) - -#define iv_obj_insert(v, type, pos, objptr) \ - iv_insert(v, (pos) * sizeof(type), objptr, sizeof(type)) - -#define iv_obj_erase(v, type, pos, count) \ - iv_erase(v, (pos) * sizeof(type), (count) * sizeof(type)) - - -#define IROUND_SIZE(b) (((size_t)1) << (b)) -#define IROUND_UP(s, n) (((s) + (n) - 1) & ~(((size_t)(n)) - 1)) - - -/*====================================================================*/ -/* IMEMNODE */ -/*====================================================================*/ -struct IMEMNODE -{ - struct IALLOCATOR *allocator; /* memory allocator */ - - struct IVECTOR vprev; /* prev node link vector */ - struct IVECTOR vnext; /* next node link vector */ - struct IVECTOR vnode; /* node information data */ - struct IVECTOR vdata; /* node data buffer vector */ - struct IVECTOR vmode; /* mode of allocation */ - ilong *mprev; /* prev node array */ - ilong *mnext; /* next node array */ - ilong *mnode; /* node info array */ - void **mdata; /* node data array */ - ilong *mmode; /* node mode array */ - ilong *extra; /* extra user data */ - ilong node_free; /* number of free nodes */ - ilong node_used; /* number of allocated */ - ilong node_max; /* number of all nodes */ - ilong grow_limit; /* limit of growing */ - - ilong node_size; /* node data fixed size */ - ilong node_shift; /* node data size shift */ - - struct IVECTOR vmem; /* mem-pages in the pool */ - char **mmem; /* mem-pages array */ - ilong mem_max; /* max num of memory pages */ - ilong mem_count; /* number of mem-pages */ - - ilong list_open; /* the entry of open-list */ - ilong list_close; /* the entry of close-list */ - ilong total_mem; /* total memory size */ -}; - - -void imnode_init(struct IMEMNODE *mn, ilong nodesize, struct IALLOCATOR *ac); -void imnode_destroy(struct IMEMNODE *mnode); -ilong imnode_new(struct IMEMNODE *mnode); -void imnode_del(struct IMEMNODE *mnode, ilong index); -ilong imnode_head(const struct IMEMNODE *mnode); -ilong imnode_next(const struct IMEMNODE *mnode, ilong index); -ilong imnode_prev(const struct IMEMNODE *mnode, ilong index); -void*imnode_data(struct IMEMNODE *mnode, ilong index); -const void* imnode_data_const(const struct IMEMNODE *mnode, ilong index); - -#define IMNODE_NODE(mnodeptr, i) ((mnodeptr)->mnode[i]) -#define IMNODE_PREV(mnodeptr, i) ((mnodeptr)->mprev[i]) -#define IMNODE_NEXT(mnodeptr, i) ((mnodeptr)->mnext[i]) -#define IMNODE_DATA(mnodeptr, i) ((mnodeptr)->mdata[i]) -#define IMNODE_MODE(mnodeptr, i) ((mnodeptr)->mmode[i]) - - -/*====================================================================*/ -/* LIST DEFINITION */ -/*====================================================================*/ -#ifndef __ILIST_DEF__ -#define __ILIST_DEF__ - -struct ILISTHEAD { - struct ILISTHEAD *next, *prev; -}; - -typedef struct ILISTHEAD ilist_head; - - -/*--------------------------------------------------------------------*/ -/* list init */ -/*--------------------------------------------------------------------*/ -#define ILIST_HEAD_INIT(name) { &(name), &(name) } -#define ILIST_HEAD(name) \ - struct ILISTHEAD name = ILIST_HEAD_INIT(name) - -#define ILIST_INIT(ptr) ( \ - (ptr)->next = (ptr), (ptr)->prev = (ptr)) - -#define IOFFSETOF(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) - -#define ICONTAINEROF(ptr, type, member) ( \ - (type*)( ((char*)((type*)ptr)) - IOFFSETOF(type, member)) ) - -#define ILIST_ENTRY(ptr, type, member) ICONTAINEROF(ptr, type, member) - - -/*--------------------------------------------------------------------*/ -/* list operation */ -/*--------------------------------------------------------------------*/ -#define ILIST_ADD(node, head) ( \ - (node)->prev = (head), (node)->next = (head)->next, \ - (head)->next->prev = (node), (head)->next = (node)) - -#define ILIST_ADD_TAIL(node, head) ( \ - (node)->prev = (head)->prev, (node)->next = (head), \ - (head)->prev->next = (node), (head)->prev = (node)) - -#define ILIST_DEL_BETWEEN(p, n) ((n)->prev = (p), (p)->next = (n)) - -#define ILIST_DEL(entry) (\ - (entry)->next->prev = (entry)->prev, \ - (entry)->prev->next = (entry)->next, \ - (entry)->next = 0, (entry)->prev = 0) - -#define ILIST_DEL_INIT(entry) do { \ - ILIST_DEL(entry); ILIST_INIT(entry); } while (0) - -#define ILIST_IS_EMPTY(entry) ((entry) == (entry)->next) - -#define ilist_init ILIST_INIT -#define ilist_entry ILIST_ENTRY -#define ilist_add ILIST_ADD -#define ilist_add_tail ILIST_ADD_TAIL -#define ilist_del ILIST_DEL -#define ilist_del_init ILIST_DEL_INIT -#define ilist_is_empty ILIST_IS_EMPTY - -#define ILIST_FOREACH(iterator, head, TYPE, MEMBER) \ - for ((iterator) = ilist_entry((head)->next, TYPE, MEMBER); \ - &((iterator)->MEMBER) != (head); \ - (iterator) = ilist_entry((iterator)->MEMBER.next, TYPE, MEMBER)) - -#define ilist_foreach(iterator, head, TYPE, MEMBER) \ - ILIST_FOREACH(iterator, head, TYPE, MEMBER) - -#define ilist_foreach_entry(pos, head) \ - for( (pos) = (head)->next; (pos) != (head) ; (pos) = (pos)->next ) - - -#define __ilist_splice(list, head) do { \ - ilist_head *first = (list)->next, *last = (list)->prev; \ - ilist_head *at = (head)->next; \ - (first)->prev = (head), (head)->next = (first); \ - (last)->next = (at), (at)->prev = (last); } while (0) - -#define ilist_splice(list, head) do { \ - if (!ilist_is_empty(list)) __ilist_splice(list, head); } while (0) - -#define ilist_splice_init(list, head) do { \ - ilist_splice(list, head); ilist_init(list); } while (0) - -#define ilist_replace(oldnode, newnode) ( \ - (newnode)->next = (oldnode)->next, \ - (newnode)->next->prev = (newnode), \ - (newnode)->prev = (oldnode)->prev, \ - (newnode)->prev->next = (newnode)) - -#ifdef _MSC_VER -#pragma warning(disable:4311) -#pragma warning(disable:4312) -#pragma warning(disable:4996) -#endif - -#endif - - -/*====================================================================*/ -/* IMUTEX - mutex interfaces */ -/*====================================================================*/ -#ifndef IMUTEX_TYPE - -#ifndef IMUTEX_DISABLE -#if (defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64)) -#if ((!defined(_M_PPC)) && (!defined(_M_PPC_BE)) && (!defined(_XBOX))) -#ifndef _WIN32_WINNT -#define _WIN32_WINNT 0x0500 -#endif -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN -#endif -#include -#else -#ifndef _XBOX -#define _XBOX -#endif -#include -#endif - -#define IMUTEX_TYPE CRITICAL_SECTION -#define IMUTEX_INIT(m) InitializeCriticalSection((CRITICAL_SECTION*)(m)) -#define IMUTEX_DESTROY(m) DeleteCriticalSection((CRITICAL_SECTION*)(m)) -#define IMUTEX_LOCK(m) EnterCriticalSection((CRITICAL_SECTION*)(m)) -#define IMUTEX_UNLOCK(m) LeaveCriticalSection((CRITICAL_SECTION*)(m)) - -#elif defined(__unix) || defined(__unix__) || defined(__MACH__) -#include -#include -#define IMUTEX_TYPE pthread_mutex_t -#define IMUTEX_INIT(m) pthread_mutex_init((pthread_mutex_t*)(m), 0) -#define IMUTEX_DESTROY(m) pthread_mutex_destroy((pthread_mutex_t*)(m)) -#define IMUTEX_LOCK(m) pthread_mutex_lock((pthread_mutex_t*)(m)) -#define IMUTEX_UNLOCK(m) pthread_mutex_unlock((pthread_mutex_t*)(m)) -#endif -#endif - -#ifndef IMUTEX_TYPE -#define IMUTEX_TYPE int -#define IMUTEX_INIT(m) { (*(m)) = (*(m)); } -#define IMUTEX_DESTROY(m) { (*(m)) = (*(m)); } -#define IMUTEX_LOCK(m) { (*(m)) = (*(m)); } -#define IMUTEX_UNLOCK(m) { (*(m)) = (*(m)); } -#endif - -#endif - - - -/*====================================================================*/ -/* IVECTOR / IMEMNODE MANAGEMENT */ -/*====================================================================*/ - -typedef struct IVECTOR ib_vector; -typedef struct IMEMNODE ib_memnode; - -ib_vector *iv_create(void); -void iv_delete(ib_vector *vec); - -ib_memnode *imnode_create(ilong nodesize, int grow_limit); -void imnode_delete(ib_memnode *); - - -/*--------------------------------------------------------------------*/ -/* Collection - Array */ -/*--------------------------------------------------------------------*/ - -struct ib_array; -typedef struct ib_array ib_array; - -ib_array *ib_array_new(void (*destroy_func)(void*)); -void ib_array_delete(ib_array *array); -void ib_array_reserve(ib_array *array, size_t new_size); -size_t ib_array_size(const ib_array *array); -void** ib_array_ptr(ib_array *array); -void* ib_array_index(ib_array *array, size_t index); -const void* ib_array_const_index(const ib_array *array, size_t index); -void ib_array_push(ib_array *array, void *item); -void ib_array_push_left(ib_array *array, void *item); -void ib_array_replace(ib_array *array, size_t index, void *item); -void* ib_array_pop(ib_array *array); -void* ib_array_pop_left(ib_array *array); -void ib_array_remove(ib_array *array, size_t index); -void ib_array_insert_before(ib_array *array, size_t index, void *item); -void* ib_array_pop_at(ib_array *array, size_t index); -void ib_array_for_each(ib_array *array, void (*iterator)(void *item)); - -void ib_array_sort(ib_array *array, - int (*compare)(const void*, const void*)); - -ilong ib_array_search(const ib_array *array, - int (*compare)(const void*, const void*), - const void *item, - ilong start_pos); - -ilong ib_array_bsearch(const ib_array *array, - int (*compare)(const void*, const void*), - const void *item); - - -/*====================================================================*/ -/* ib_node - binary search tree (can be used in rbtree & avl) */ -/* color/balance won't be packed (can work without alignment) */ -/*====================================================================*/ -struct ib_node -{ - struct ib_node *left; /* left child */ - struct ib_node *right; /* right child */ - struct ib_node *parent; /* pointing to node itself for empty node */ - int height; /* equals to 1 + max height in childs */ -}; - -struct ib_root -{ - struct ib_node *node; /* root node */ -}; - - -/*--------------------------------------------------------------------*/ -/* NODE MACROS */ -/*--------------------------------------------------------------------*/ -#define IB_OFFSET(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) - -#define IB_NODE2DATA(n, o) ((void *)((size_t)(n) - (o))) -#define IB_DATA2NODE(d, o) ((struct ib_node*)((size_t)(d) + (o))) - -#define IB_ENTRY(ptr, type, member) \ - ((type*)IB_NODE2DATA(ptr, IB_OFFSET(type, member))) - -#define ib_node_init(node) do { ((node)->parent) = (node); } while (0) -#define ib_node_empty(node) ((node)->parent == (node)) - -#define IB_LEFT_HEIGHT(node) (((node)->left)? ((node)->left)->height : 0) -#define IB_RIGHT_HEIGHT(node) (((node)->right)? ((node)->right)->height : 0) - - -/*--------------------------------------------------------------------*/ -/* binary search tree - node manipulation */ -/*--------------------------------------------------------------------*/ -struct ib_node *ib_node_first(struct ib_root *root); -struct ib_node *ib_node_last(struct ib_root *root); -struct ib_node *ib_node_next(struct ib_node *node); -struct ib_node *ib_node_prev(struct ib_node *node); - -void ib_node_replace(struct ib_node *victim, struct ib_node *newnode, - struct ib_root *root); - -static inline void ib_node_link(struct ib_node *node, struct ib_node *parent, - struct ib_node **ib_link) { - node->parent = parent; - node->height = 1; - node->left = node->right = NULL; - ib_link[0] = node; -} - - -/* avl insert rebalance and erase */ -void ib_node_post_insert(struct ib_node *node, struct ib_root *root); -void ib_node_erase(struct ib_node *node, struct ib_root *root); - -/* avl nodes destroy: fast tear down the whole tree */ -struct ib_node* ib_node_tear(struct ib_root *root, struct ib_node **next); - - -/*--------------------------------------------------------------------*/ -/* avl - node templates */ -/*--------------------------------------------------------------------*/ -#define ib_node_find(root, what, compare_fn, res_node) do {\ - struct ib_node *__n = (root)->node; \ - (res_node) = NULL; \ - while (__n) { \ - int __hr = (compare_fn)(what, __n); \ - if (__hr == 0) { (res_node) = __n; break; } \ - else if (__hr < 0) { __n = __n->left; } \ - else { __n = __n->right; } \ - } \ - } while (0) - - -#define ib_node_add(root, newnode, compare_fn, duplicate_node) do { \ - struct ib_node **__link = &((root)->node); \ - struct ib_node *__parent = NULL; \ - struct ib_node *__duplicate = NULL; \ - int __hr = 1; \ - while (__link[0]) { \ - __parent = __link[0]; \ - __hr = (compare_fn)(newnode, __parent); \ - if (__hr == 0) { __duplicate = __parent; break; } \ - else if (__hr < 0) { __link = &(__parent->left); } \ - else { __link = &(__parent->right); } \ - } \ - (duplicate_node) = __duplicate; \ - if (__duplicate == NULL) { \ - ib_node_link(newnode, __parent, __link); \ - ib_node_post_insert(newnode, root); \ - } \ - } while (0) - - -/*--------------------------------------------------------------------*/ -/* avltree - friendly interface */ -/*--------------------------------------------------------------------*/ -struct ib_tree -{ - struct ib_root root; /* avl root */ - size_t offset; /* node offset in user data structure */ - size_t size; /* size of user data structure */ - size_t count; /* node count */ - /* returns 0 for equal, -1 for n1 < n2, 1 for n1 > n2 */ - int (*compare)(const void *n1, const void *n2); -}; - - -/* initialize avltree, use IB_OFFSET(type, member) for "offset" - * eg: - * ib_tree_init(&mytree, mystruct_compare, - * sizeof(struct mystruct_t), - * IB_OFFSET(struct mystruct_t, node)); - */ -void ib_tree_init(struct ib_tree *tree, - int (*compare)(const void*, const void*), size_t size, size_t offset); - -void *ib_tree_first(struct ib_tree *tree); -void *ib_tree_last(struct ib_tree *tree); -void *ib_tree_next(struct ib_tree *tree, void *data); -void *ib_tree_prev(struct ib_tree *tree, void *data); - -/* require a temporary user structure (data) which contains the key */ -void *ib_tree_find(struct ib_tree *tree, const void *data); -void *ib_tree_nearest(struct ib_tree *tree, const void *data); - -/* returns NULL for success, otherwise returns conflict node with same key */ -void *ib_tree_add(struct ib_tree *tree, void *data); - -void ib_tree_remove(struct ib_tree *tree, void *data); -void ib_tree_replace(struct ib_tree *tree, void *victim, void *newdata); - -void ib_tree_clear(struct ib_tree *tree, void (*destroy)(void *data)); - - -/*--------------------------------------------------------------------*/ -/* fastbin - fixed size object allocator */ -/*--------------------------------------------------------------------*/ -struct ib_fastbin -{ - size_t obj_size; - size_t page_size; - size_t maximum; - char *start; - char *endup; - void *next; - void *pages; -}; - - -#define IB_NEXT(ptr) (((void**)(ptr))[0]) - -void ib_fastbin_init(struct ib_fastbin *fb, size_t obj_size); -void ib_fastbin_destroy(struct ib_fastbin *fb); - -void* ib_fastbin_new(struct ib_fastbin *fb); -void ib_fastbin_del(struct ib_fastbin *fb, void *ptr); - - -/*--------------------------------------------------------------------*/ -/* string */ -/*--------------------------------------------------------------------*/ -struct ib_string; -typedef struct ib_string ib_string; - -#ifndef IB_STRING_SSO -#define IB_STRING_SSO 14 -#endif - -struct ib_string -{ - char *ptr; - int size; - int capacity; - char sso[IB_STRING_SSO + 2]; -}; - -#define ib_string_ptr(str) ((str)->ptr) -#define ib_string_size(str) ((str)->size) - -ib_string* ib_string_new(void); -ib_string* ib_string_new_from(const char *text); -ib_string* ib_string_new_size(const char *text, int size); - -void ib_string_delete(ib_string *str); - -ib_string* ib_string_resize(ib_string *str, int newsize); - -ib_string* ib_string_assign(ib_string *str, const char *src); -ib_string* ib_string_assign_size(ib_string *str, const char *src, int size); - -ib_string* ib_string_erase(ib_string *str, int pos, int size); -ib_string* ib_string_insert(ib_string *str, int pos, - const void *data, int size); - -ib_string* ib_string_append(ib_string *str, const char *src); -ib_string* ib_string_append_size(ib_string *str, const char *src, int size); -ib_string* ib_string_append_c(ib_string *str, char c); - -ib_string* ib_string_prepend(ib_string *str, const char *src); -ib_string* ib_string_prepend_size(ib_string *str, const char *src, int size); -ib_string* ib_string_prepend_c(ib_string *str, char c); - -ib_string* ib_string_rewrite(ib_string *str, int pos, const char *src); -ib_string* ib_string_rewrite_size(ib_string *str, int pos, - const char *src, int size); - -int ib_string_compare(const struct ib_string *a, const struct ib_string *b); - -int ib_string_find(const ib_string *str, const char *src, int len, int start); -int ib_string_find_c(const ib_string *str, char ch, int start); - -ib_array* ib_string_split(const ib_string *str, const char *sep, int len); -ib_array* ib_string_split_c(const ib_string *str, char sep); - -ib_string* ib_string_strip(ib_string *str, const char *seps); - - -/*--------------------------------------------------------------------*/ -/* static hash table (closed hash table with avlnode) */ -/*--------------------------------------------------------------------*/ -struct ib_hash_node -{ - struct ib_node avlnode; - void *key; - size_t hash; -}; - -struct ib_hash_index -{ - struct ILISTHEAD node; - struct ib_root avlroot; -}; - -#define IB_HASH_INIT_SIZE 8 - -struct ib_hash_table -{ - size_t count; - size_t index_size; - size_t index_mask; - size_t (*hash)(const void *key); - int (*compare)(const void *key1, const void *key2); - struct ILISTHEAD head; - struct ib_hash_index *index; - struct ib_hash_index init[IB_HASH_INIT_SIZE]; -}; - - -void ib_hash_init(struct ib_hash_table *ht, - size_t (*hash)(const void *key), - int (*compare)(const void *key1, const void *key2)); - -struct ib_hash_node* ib_hash_node_first(struct ib_hash_table *ht); -struct ib_hash_node* ib_hash_node_last(struct ib_hash_table *ht); - -struct ib_hash_node* ib_hash_node_next(struct ib_hash_table *ht, - struct ib_hash_node *node); - -struct ib_hash_node* ib_hash_node_prev(struct ib_hash_table *ht, - struct ib_hash_node *node); - -static inline void ib_hash_node_key(struct ib_hash_table *ht, - struct ib_hash_node *node, void *key) { - node->key = key; - node->hash = ht->hash(key); -} - -struct ib_hash_node* ib_hash_find(struct ib_hash_table *ht, - const struct ib_hash_node *node); - -struct ib_node** ib_hash_track(struct ib_hash_table *ht, - const struct ib_hash_node *node, struct ib_node **parent); - -struct ib_hash_node* ib_hash_add(struct ib_hash_table *ht, - struct ib_hash_node *node); - -void ib_hash_erase(struct ib_hash_table *ht, struct ib_hash_node *node); - -void ib_hash_replace(struct ib_hash_table *ht, - struct ib_hash_node *victim, struct ib_hash_node *newnode); - -void ib_hash_clear(struct ib_hash_table *ht, - void (*destroy)(struct ib_hash_node *node)); - -/* re-index nbytes must be: sizeof(struct ib_hash_index) * n */ -void* ib_hash_swap(struct ib_hash_table *ht, void *index, size_t nbytes); - - -/*--------------------------------------------------------------------*/ -/* fast inline search, compare function will be expanded inline here */ -/*--------------------------------------------------------------------*/ -#define ib_hash_search(ht, srcnode, result, compare) do { \ - size_t __hash = (srcnode)->hash; \ - const void *__key = (srcnode)->key; \ - struct ib_hash_index *__index = \ - &((ht)->index[__hash & ((ht)->index_mask)]); \ - struct ib_node *__anode = __index->avlroot.node; \ - (result) = NULL; \ - while (__anode) { \ - struct ib_hash_node *__snode = \ - IB_ENTRY(__anode, struct ib_hash_node, avlnode); \ - size_t __shash = __snode->hash; \ - if (__hash == __shash) { \ - int __hc = (compare)(__key, __snode->key); \ - if (__hc == 0) { (result) = __snode; break; } \ - __anode = (__hc < 0)? __anode->left : __anode->right; \ - } else { \ - __anode = (__hash < __shash)? __anode->left:__anode->right;\ - } \ - } \ - } while (0) - - -/*--------------------------------------------------------------------*/ -/* hash map, wrapper of ib_hash_table to support direct key/value */ -/*--------------------------------------------------------------------*/ -struct ib_hash_entry -{ - struct ib_hash_node node; - void *value; -}; - -struct ib_hash_map -{ - size_t count; - int insert; - int fixed; - int builtin; - void* (*key_copy)(void *key); - void (*key_destroy)(void *key); - void* (*value_copy)(void *value); - void (*value_destroy)(void *value); - struct ib_fastbin fb; - struct ib_hash_table ht; -}; - - -#define ib_hash_key(entry) ((entry)->node.key) -#define ib_hash_value(entry) ((entry)->value) - -void ib_map_init(struct ib_hash_map *hm, size_t (*hash)(const void*), - int (*compare)(const void *, const void *)); - -void ib_map_destroy(struct ib_hash_map *hm); - -struct ib_hash_entry* ib_map_first(struct ib_hash_map *hm); -struct ib_hash_entry* ib_map_last(struct ib_hash_map *hm); - -struct ib_hash_entry* ib_map_next(struct ib_hash_map *hm, - struct ib_hash_entry *n); -struct ib_hash_entry* ib_map_prev(struct ib_hash_map *hm, - struct ib_hash_entry *n); - -struct ib_hash_entry* ib_map_find(struct ib_hash_map *hm, const void *key); -void* ib_map_lookup(struct ib_hash_map *hm, const void *key, void *defval); - - -struct ib_hash_entry* ib_map_add(struct ib_hash_map *hm, - void *key, void *value, int *success); - -struct ib_hash_entry* ib_map_set(struct ib_hash_map *hm, - void *key, void *value); - -void* ib_map_get(struct ib_hash_map *hm, const void *key); - -void ib_map_erase(struct ib_hash_map *hm, struct ib_hash_entry *entry); - - -/* returns 0 for success, -1 for key mismatch */ -int ib_map_remove(struct ib_hash_map *hm, const void *key); - -void ib_map_clear(struct ib_hash_map *hm); - - -/*--------------------------------------------------------------------*/ -/* fast inline search template */ -/*--------------------------------------------------------------------*/ - -#define ib_map_search(hm, srckey, hash_func, cmp_func, result) do { \ - size_t __hash = (hash_func)(srckey); \ - struct ib_hash_index *__index = \ - &((hm)->ht.index[__hash & ((hm)->ht.index_mask)]); \ - struct ib_node *__anode = __index->avlroot.node; \ - (result) = NULL; \ - while (__anode) { \ - struct ib_hash_node *__snode = \ - IB_ENTRY(__anode, struct ib_hash_node, avlnode); \ - size_t __shash = __snode->hash; \ - if (__hash == __shash) { \ - int __hc = (cmp_func)((srckey), __snode->key); \ - if (__hc == 0) { \ - (result) = IB_ENTRY(__snode, \ - struct ib_hash_entry, node);\ - break; \ - } \ - __anode = (__hc < 0)? __anode->left : __anode->right; \ - } else { \ - __anode = (__hash < __shash)? __anode->left:__anode->right;\ - } \ - } \ - } while (0) - - -/*--------------------------------------------------------------------*/ -/* common type hash */ -/*--------------------------------------------------------------------*/ -size_t ib_hash_func_uint(const void *key); -int ib_hash_compare_uint(const void *key1, const void *key2); - -size_t ib_hash_func_int(const void *key); -int ib_hash_compare_int(const void *key1, const void *key2); - -size_t ib_hash_func_str(const void *key); -int ib_hash_compare_str(const void *key1, const void *key2); - -size_t ib_hash_func_cstr(const void *key); -int ib_hash_compare_cstr(const void *key1, const void *key2); - - -struct ib_hash_entry *ib_map_find_uint(struct ib_hash_map *hm, iulong key); -struct ib_hash_entry *ib_map_find_int(struct ib_hash_map *hm, ilong key); -struct ib_hash_entry *ib_map_find_str(struct ib_hash_map *hm, const ib_string *key); -struct ib_hash_entry *ib_map_find_cstr(struct ib_hash_map *hm, const char *key); - - - -#ifdef __cplusplus -} -#endif - -#endif - - - - diff --git a/czmod/iposix.c b/czmod/iposix.c deleted file mode 100644 index d94fb83..0000000 --- a/czmod/iposix.c +++ /dev/null @@ -1,1059 +0,0 @@ -//===================================================================== -// -// iposix.c - posix file system accessing -// -// NOTE: -// for more information, please see the readme file. -// -//===================================================================== - -#include "iposix.h" - -#ifndef IDISABLE_FILE_SYSTEM_ACCESS -//--------------------------------------------------------------------- -// Global Definition -//--------------------------------------------------------------------- -#include -#include -#include -#include -#include -#include -#include -#include - -#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) -#include -#endif - -#ifdef _WIN32 -#include -#include -#include -#define ISYSNAME 'w' -#else -#ifndef __unix -#define __unix -#endif -#define ISYSNAME 'u' -#endif - - - -//--------------------------------------------------------------------- -// Posix Stat -//--------------------------------------------------------------------- -#ifdef __unix -typedef struct stat iposix_ostat_t; -#define iposix_stat_proc stat -#define iposix_lstat_proc lstat -#define iposix_fstat_proc fstat -#else -typedef struct _stat iposix_ostat_t; -#define iposix_stat_proc _stat -#define iposix_lstat_proc _stat -#define iposix_fstat_proc _fstat -#endif - - -#if defined(_WIN32) || defined(WIN32) || defined(_WIN64) || defined(WIN64) - #if defined(_S_IFMT) && (!defined(S_IFMT)) - #define S_IFMT _S_IFMT - #endif - - #if defined(_S_IFDIR) && (!defined(S_IFDIR)) - #define S_IFDIR _S_IFDIR - #endif - - #if defined(_S_IFCHR) && (!defined(S_IFCHR)) - #define S_IFCHR _S_IFCHR - #endif - - #if defined(_S_IFIFO) && (!defined(S_IFIFO)) - #define S_IFIFO _S_IFIFO - #endif - - #if defined(_S_IFREG) && (!defined(S_IFREG)) - #define S_IFREG _S_IFREG - #endif - - #if defined(_S_IREAD) && (!defined(S_IREAD)) - #define S_IREAD _S_IREAD - #endif - - #if defined(_S_IWRITE) && (!defined(S_IWRITE)) - #define S_IWRITE _S_IWRITE - #endif - - #if defined(_S_IEXEC) && (!defined(S_IEXEC)) - #define S_IEXEC _S_IEXEC - #endif -#endif - -#define IX_FMT(m, t) (((m) & S_IFMT) == (t)) - - -// convert stat structure -void iposix_stat_convert(iposix_stat_t *ostat, const iposix_ostat_t *x) -{ - ostat->st_mode = 0; - - #ifdef S_IFDIR - if (IX_FMT(x->st_mode, S_IFDIR)) ostat->st_mode |= ISTAT_IFDIR; - #endif - #ifdef S_IFCHR - if (IX_FMT(x->st_mode, S_IFCHR)) ostat->st_mode |= ISTAT_IFCHR; - #endif - #ifdef S_IFBLK - if (IX_FMT(x->st_mode, S_IFBLK)) ostat->st_mode |= ISTAT_IFBLK; - #endif - #ifdef S_IFREG - if (IX_FMT(x->st_mode, S_IFREG)) ostat->st_mode |= ISTAT_IFREG; - #endif - #ifdef S_IFIFO - if (IX_FMT(x->st_mode, S_IFIFO)) ostat->st_mode |= ISTAT_IFIFO; - #endif - #ifdef S_IFLNK - if (IX_FMT(x->st_mode, S_IFLNK)) ostat->st_mode |= ISTAT_IFLNK; - #endif - #ifdef S_IFSOCK - if (IX_FMT(x->st_mode, S_IFSOCK)) ostat->st_mode |= ISTAT_IFSOCK; - #endif - #ifdef S_IFWHT - if (IX_FMT(x->st_mode, S_IFWHT)) ostat->st_mode |= ISTAT_IFWHT; - #endif - -#ifdef S_IREAD - if (x->st_mode & S_IREAD) ostat->st_mode |= ISTAT_IRUSR; -#endif - -#ifdef S_IWRITE - if (x->st_mode & S_IWRITE) ostat->st_mode |= ISTAT_IWUSR; -#endif - -#ifdef S_IEXEC - if (x->st_mode & S_IEXEC) ostat->st_mode |= ISTAT_IXUSR; -#endif - -#ifdef S_IRUSR - if (x->st_mode & S_IRUSR) ostat->st_mode |= ISTAT_IRUSR; - if (x->st_mode & S_IWUSR) ostat->st_mode |= ISTAT_IWUSR; - if (x->st_mode & S_IXUSR) ostat->st_mode |= ISTAT_IXUSR; -#endif - -#ifdef S_IRGRP - if (x->st_mode & S_IRGRP) ostat->st_mode |= ISTAT_IRGRP; - if (x->st_mode & S_IWGRP) ostat->st_mode |= ISTAT_IWGRP; - if (x->st_mode & S_IXGRP) ostat->st_mode |= ISTAT_IXGRP; -#endif - -#ifdef S_IROTH - if (x->st_mode & S_IROTH) ostat->st_mode |= ISTAT_IROTH; - if (x->st_mode & S_IWOTH) ostat->st_mode |= ISTAT_IWOTH; - if (x->st_mode & S_IXOTH) ostat->st_mode |= ISTAT_IXOTH; -#endif - - ostat->st_size = (IUINT64)x->st_size; - - ostat->atime = (IUINT32)x->st_atime; - ostat->mtime = (IUINT32)x->st_mtime; - ostat->ctime = (IUINT32)x->st_mtime; - - ostat->st_ino = (IUINT64)x->st_ino; - ostat->st_dev = (IUINT32)x->st_dev; - ostat->st_nlink = (IUINT32)x->st_nlink; - ostat->st_uid = (IUINT32)x->st_uid; - ostat->st_gid = (IUINT32)x->st_gid; - ostat->st_rdev = (IUINT32)x->st_rdev; - -#ifdef __unix -// #define IHAVE_STAT_ST_BLKSIZE -// #define IHAVE_STAT_ST_BLOCKS -// #define IHAVE_STAT_ST_FLAGS -#endif - -#if defined(__unix) - #ifdef IHAVE_STAT_ST_BLOCKS - ostat->st_blocks = (IUINT32)x->st_blocks; - #endif - #ifdef IHAVE_STAT_ST_BLKSIZE - ostat->st_blksize = (IUINT32)x->st_blksize; - #endif - #if !defined(__CYGWIN__) && defined(IHAVE_STAT_ST_FLAGS) - ostat->st_flags = (IUINT32)x->st_flags; - #endif -#endif -} - -// returns 0 for success, -1 for error -int iposix_stat_imp(const char *path, iposix_stat_t *ostat) -{ - iposix_ostat_t xstat; - int retval; - retval = iposix_stat_proc(path, &xstat); - if (retval != 0) return -1; - iposix_stat_convert(ostat, &xstat); - return 0; -} - -// returns 0 for success, -1 for error -int iposix_lstat_imp(const char *path, iposix_stat_t *ostat) -{ - iposix_ostat_t xstat; - int retval; - retval = iposix_lstat_proc(path, &xstat); - if (retval != 0) return -1; - iposix_stat_convert(ostat, &xstat); - return 0; -} - -// returns 0 for success, -1 for error -int iposix_fstat(int fd, iposix_stat_t *ostat) -{ - iposix_ostat_t xstat; - int retval; - retval = iposix_fstat_proc(fd, &xstat); - if (retval != 0) return -1; - iposix_stat_convert(ostat, &xstat); - return 0; -} - -// normalize stat path -static void iposix_path_stat(const char *src, char *dst) -{ - int size = (int)strlen(src); - if (size > IPOSIX_MAXPATH) size = IPOSIX_MAXPATH; - memcpy(dst, src, size + 1); - if (size > 1) { - int trim = 1; - if (size == 3) { - if (isalpha((int)dst[0]) && dst[1] == ':' && - (dst[2] == '/' || dst[2] == '\\')) trim = 0; - } - if (size == 1) { - if (dst[0] == '/' || dst[0] == '\\') trim = 0; - } - if (trim) { - if (dst[size - 1] == '/' || dst[size - 1] == '\\') { - dst[size - 1] = 0; - size--; - } - } - } -} - - -// returns 0 for success, -1 for error -int iposix_stat(const char *path, iposix_stat_t *ostat) -{ - char buf[IPOSIX_MAXBUFF]; - iposix_path_stat(path, buf); - return iposix_stat_imp(buf, ostat); -} - -// returns 0 for success, -1 for error -int iposix_lstat(const char *path, iposix_stat_t *ostat) -{ - char buf[IPOSIX_MAXBUFF]; - iposix_path_stat(path, buf); - return iposix_lstat_imp(buf, ostat); -} - -// get current directory -char *iposix_getcwd(char *path, int size) -{ -#ifdef _WIN32 - return _getcwd(path, size); -#else - return getcwd(path, size); -#endif -} - -// create directory -int iposix_mkdir(const char *path, int mode) -{ -#ifdef _WIN32 - return _mkdir(path); -#else - if (mode < 0) mode = 0755; - return mkdir(path, mode); -#endif -} - -// change directory -int iposix_chdir(const char *path) -{ -#ifdef _WIN32 - return _chdir(path); -#else - return chdir(path); -#endif -} - -// check access -int iposix_access(const char *path, int mode) -{ -#ifdef _WIN32 - return _access(path, mode); -#else - return access(path, mode); -#endif -} - -// returns 1 for true 0 for false, -1 for not exist -int iposix_path_isdir(const char *path) -{ - iposix_stat_t s; - int hr = iposix_stat(path, &s); - if (hr != 0) return -1; - return (ISTAT_ISDIR(s.st_mode))? 1 : 0; -} - -// returns 1 for true 0 for false, -1 for not exist -int iposix_path_isfile(const char *path) -{ - iposix_stat_t s; - int hr = iposix_stat(path, &s); - if (hr != 0) return -1; - return (ISTAT_ISDIR(s.st_mode))? 0 : 1; -} - -// returns 1 for true 0 for false, -1 for not exist -int iposix_path_islink(const char *path) -{ - iposix_stat_t s; - int hr = iposix_stat(path, &s); - if (hr != 0) return -1; - return (ISTAT_ISLNK(s.st_mode))? 1 : 0; -} - -// returns 1 for true 0 for false -int iposix_path_exists(const char *path) -{ - iposix_stat_t s; - int hr = iposix_stat(path, &s); - if (hr != 0) return 0; - return 1; -} - -// returns file size, -1 for error -IINT64 iposix_path_getsize(const char *path) -{ - iposix_stat_t s; - int hr = iposix_stat(path, &s); - if (hr != 0) return -1; - return (IINT64)s.st_size; -} - - -//--------------------------------------------------------------------- -// Posix Path -//--------------------------------------------------------------------- - -// 是否是绝对路径,如果是的话返回1,否则返回0 -int iposix_path_isabs(const char *path) -{ - if (path == NULL) return 0; - if (path[0] == '/') return 1; - if (path[0] == 0) return 0; -#ifdef _WIN32 - if (path[0] == IPATHSEP) return 1; - if (isalpha(path[0]) && path[1] == ':') { - if (path[2] == '/' || path[2] == '\\') return 1; - } -#endif - return 0; -} - - - -//--------------------------------------------------------------------- -// iposix_string_t - basic string definition -//--------------------------------------------------------------------- -typedef struct -{ - char *p; - int l; - int m; -} iposix_string_t; - - -//--------------------------------------------------------------------- -// iposix_string_t interface -//--------------------------------------------------------------------- -#define _istrlen(s) ((s)->l) -#define _istrch(s, i) (((i) >= 0)? ((s)->p)[i] : ((s)->p)[(s)->l + (i)]) - -static char *_istrset(iposix_string_t *s, const char *p, int max) -{ - assert((max > 0) && p && s); - s->p = (char*)p; - s->l = strlen(p); - s->m = max; - return (char*)p; -} - -static char *_istrcat(iposix_string_t *s, const char *p) -{ - char *p1; - - assert(s && p); - for (p1 = (char*)p; p1[0]; p1++, s->l++) { - if (s->l >= s->m) break; - s->p[s->l] = p1[0]; - } - return s->p; -} - -static char *_istrcpy(iposix_string_t *s, const char *p) -{ - assert(s && p); - s->l = 0; - return _istrcat(s, p); -} - -static char *_istrcats(iposix_string_t *s1, const iposix_string_t *s2) -{ - int i; - assert(s1 && s2); - for (i = 0; i < s2->l; i++, s1->l++) { - if (s1->l >= s1->m) break; - s1->p[s1->l] = s2->p[i]; - } - return s1->p; -} - -static char *_icstr(iposix_string_t *s) -{ - assert(s); - if (s->l >= s->m) s->l = s->m - 1; - if (s->l < 0) s->l = 0; - s->p[s->l] = 0; - return s->p; -} - -static char _istrc(const iposix_string_t *s, int pos) -{ - if (pos >= 0) return (pos > s->l)? 0 : s->p[pos]; - return (pos < -(s->l))? 0 : s->p[s->l + pos]; -} - -static char _istrchop(iposix_string_t *s) -{ - char ch = _istrc(s, -1); - s->l--; - if (s->l < 0) s->l = 0; - return ch; -} - -static char *_istrctok(iposix_string_t *s, const char *p) -{ - int i, k; - - assert(s && p); - - for (; _istrlen(s) > 0; ) { - for (i = 0, k = 0; p[i] && k == 0; i++) { - if (_istrc(s, -1) == p[i]) k++; - } - if (k == 0) break; - _istrchop(s); - } - for (; _istrlen(s) > 0; ) { - for (i = 0, k = 0; p[i] && k == 0; i++) { - if (_istrc(s, -1) == p[i]) k++; - } - if (k) break; - _istrchop(s); - } - - return s->p; -} - -static int _istrcmp(iposix_string_t *s, const char *p) -{ - int i; - for (i = 0; i < s->l && ((char*)p)[i]; i++) - if (_istrc(s, i) != ((char*)p)[i]) break; - if (((char*)p)[i] == 0 && i == s->l) return 0; - return 1; -} - -static char *_istrcatc(iposix_string_t *s, char ch) -{ - char text[2] = " "; - assert(s); - text[0] = ch; - return _istrcat(s, text); -} - -static int istrtok(const char *p1, int *pos, const char *p2) -{ - int i, j, k, r; - - assert(p1 && pos && p2); - - for (i = *pos; p1[i]; i++) { - for (j = 0, k = 0; p2[j] && k == 0; j++) { - if (p1[i] == p2[j]) k++; - } - if (k == 0) break; - } - *pos = i; - r = i; - - if (p1[i] == 0) return -1; - for (; p1[i]; i++) { - for (j = 0, k = 0; p2[j] && k == 0; j++) { - if (p1[i] == p2[j]) k++; - } - if (k) break; - } - *pos = i; - - return r; -} - - -//--------------------------------------------------------------------- -// normalize path -//--------------------------------------------------------------------- -char *iposix_path_normal(const char *srcpath, char *path, int maxsize) -{ - int i, p, c, k, r; - iposix_string_t s1, s2; - char *p1, *p2; - char pp2[3]; - - assert(srcpath && path && maxsize > 0); - - if (srcpath[0] == 0) { - if (maxsize > 0) path[0] = 0; - return path; - } - - for (p1 = (char*)srcpath; p1[0] && isspace((int)p1[0]); p1++); - - path[0] = 0; - _istrset(&s1, path, maxsize); - - if (IPATHSEP == '\\') { - pp2[0] = '/'; - pp2[1] = '\\'; - pp2[2] = 0; - } else { - pp2[0] = '/'; - pp2[1] = 0; - } - - p2 = pp2; - - if (p1[0] && p1[1] == ':' && (ISYSNAME == 'u' || ISYSNAME == 'w')) { - _istrcatc(&s1, *p1++); - _istrcatc(&s1, *p1++); - } - - if (IPATHSEP == '/') { - if (p1[0] == '/') _istrcatc(&s1, *p1++); - } - else if (p1[0] == '/' || p1[0] == IPATHSEP) { - _istrcatc(&s1, IPATHSEP); - p1++; - } - - r = (_istrc(&s1, -1) == IPATHSEP)? 1 : 0; - srcpath = (const char*)p1; - - for (i = 0, c = 0, k = 0; (p = istrtok(srcpath, &i, p2)) >= 0; k++) { - s2.p = (char*)(srcpath + p); - s2.l = s2.m = i - p; - //_iputs(&s2); printf("*\n"); - if (_istrcmp(&s2, ".") == 0) continue; - if (_istrcmp(&s2, "..") == 0) { - if (c != 0) { - _istrctok(&s1, (IPATHSEP == '\\')? "/\\:" : "/"); - c--; - continue; - } - if (c == 0 && r) { - continue; - } - } else { - c++; - } - _istrcats(&s1, &s2); - _istrcatc(&s1, IPATHSEP); - } - if (_istrlen(&s1) == 0) { - _istrcpy(&s1, "."); - } else { - if (_istrc(&s1, -1) == IPATHSEP && c > 0) _istrchop(&s1); - } - return _icstr(&s1); -} - - -//--------------------------------------------------------------------- -// join path -//--------------------------------------------------------------------- -char *iposix_path_join(const char *p1, const char *p2, char *path, int len) -{ - iposix_string_t s; - int maxsize = len; - char *p, r; - - assert(p1 && p2 && maxsize > 0); - - for (; p1[0] && isspace((int)p1[0]); p1++); - for (; p2[0] && isspace((int)p2[0]); p2++); - r = 0; - p = (char*)p2; - if (IPATHSEP == '/') { - if (p[0] == '/') r = 1; - } else { - if (p[0] == '/' || p[0] == IPATHSEP) r = 1; - } - - if (p[0] && p[1] == ':' && (ISYSNAME == 'u' || ISYSNAME == 'w')) - return iposix_path_normal(p2, path, maxsize); - - if (r && (p1[0] == 0 || p1[1] != ':' || p1[2])) - return iposix_path_normal(p2, path, maxsize); - - p = (char*)malloc(maxsize + 10); - - if (p == NULL) { - return iposix_path_normal(p1, path, maxsize); - } - - iposix_path_normal(p1, p, maxsize); - _istrset(&s, p, maxsize); - - r = 1; - if (_istrlen(&s) <= 2 && _istrc(&s, 1) == ':') r = 0; - if (_istrc(&s, -1) == IPATHSEP) r = 0; - if (_istrlen(&s) == 0) r = 0; - if (r) _istrcatc(&s, IPATHSEP); - - _istrcat(&s, p2); - iposix_path_normal(_icstr(&s), path, maxsize); - free(p); - - return path; -} - - -// 绝对路径 -char *iposix_path_abspath_u(const char *srcpath, char *path, int maxsize) -{ - char *base; - base = (char*)malloc(IPOSIX_MAXBUFF * 2); - if (base == NULL) return NULL; - iposix_getcwd(base, IPOSIX_MAXPATH); - iposix_path_join(base, srcpath, path, maxsize); - free(base); - return path; -} - -#ifdef _WIN32 -char *iposix_path_abspath_w(const char *srcpath, char *path, int maxsize) -{ - char *fname; - DWORD hr = GetFullPathNameA(srcpath, maxsize, path, &fname); - if (hr == 0) return NULL; - return path; -} -#endif - - -// 绝对路径 -char *iposix_path_abspath(const char *srcpath, char *path, int maxsize) -{ -#ifdef _WIN32 - return iposix_path_abspath_w(srcpath, path, maxsize); -#else - return iposix_path_abspath_u(srcpath, path, maxsize); -#endif -} - -// 路径分割:从右向左找到第一个"/"分成两个字符串 -int iposix_path_split(const char *path, char *p1, int l1, char *p2, int l2) -{ - int length, i, k; - length = (int)strlen(path); - - for (i = length - 1; i >= 0; i--) { - if (IPATHSEP == '/') { - if (path[i] == '/') break; - } else { - if (path[i] == '/' || path[i] == '\\') break; - } - } - - if (p1) { - if (i < 0) { - if (l1 > 0) p1[0] = 0; - } - else if (i == 0) { - p1[0] = '/'; - p1[1] = 0; - } - else { - int size = i < l1 ? i : l1; - memcpy(p1, path, size); - if (size < l1) p1[size] = 0; - } - } - - k = length - i - 1; - - if (p2) { - if (k <= 0) { - if (l2 > 0) p2[0] = 0; - } else { - int size = k < l2 ? k : l2; - memcpy(p2, path + i + 1, k); - if (size < l2) p2[size] = 0; - } - } - - return 0; -} - - -// 扩展分割:分割文件主名与扩展名 -int iposix_path_splitext(const char *path, char *p1, int l1, - char *p2, int l2) -{ - int length, i, k, size; - length = (int)strlen(path); - for (i = length - 1, k = length; i >= 0; i--) { - if (path[i] == '.') { - k = i; - break; - } - else if (IPATHSEP == '/') { - if (path[i] == '/') break; - - } - else { - if (path[i] == '/' || path[i] == '\\') break; - } - } - - if (p1) { - - size = k < l1 ? k : l1; - if (size > 0) memcpy(p1, path, size); - if (size < l1) p1[size] = 0; - } - - size = length - k - 1; - if (size < 0) size = 0; - size = size < l2 ? size : l2; - - if (p2) { - if (size > 0) memcpy(p2, path + k + 1, size); - if (size < l2) p2[size] = 0; - } - - return 0; -} - - -//--------------------------------------------------------------------- -// platform special -//--------------------------------------------------------------------- - -// cross os GetModuleFileName, returns size for success, -1 for error -int iposix_path_exepath(char *ptr, int size) -{ - int retval = -1; -#if defined(_WIN32) - DWORD hr = GetModuleFileNameA(NULL, ptr, (DWORD)size); - if (hr > 0) retval = (int)hr; -#elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) - int mib[4]; - size_t cb = (size_t)size; - int hr; - mib[0] = CTL_KERN; - mib[1] = KERN_PROC; - mib[2] = KERN_PROC_PATHNAME; - mib[3] = -1; - hr = sysctl(mib, 4, ptr, &cb, NULL, 0); - if (hr >= 0) retval = (int)cb; -#elif defined(linux) || defined(__CYGWIN__) - FILE *fp; - fp = fopen("/proc/self/exename", "r"); - if (fp) { - retval = fread(ptr, 1, size, fp); - fclose(fp); - } else { - retval = 0; - } -#else -#endif - if (retval >= 0 && retval < size) { - ptr[retval] = '\0'; - } else if (size > 0) { - ptr[0] = '\0'; - } - - if (size > 0) ptr[size - 1] = 0; - - return retval; -} - -// 取得进程可执行文件的目录 -int iposix_path_execwd(char *ptr, int size) -{ - char *buffer; - int retval; - - if (ptr) { - if (size > 0) ptr[0] = 0; - } - - buffer = (char*)malloc(IPOSIX_MAXBUFF * 2); - if (buffer == NULL) { - return -1; - } - - retval = iposix_path_exepath(buffer, IPOSIX_MAXBUFF * 2); - - if (retval < 0) { - free(buffer); - return -2; - } - - iposix_path_split(buffer, ptr, size, NULL, IPOSIX_MAXPATH); - - free(buffer); - - return 0; -} - - -// 递归创建路径:直接从 ilog移植过来 -int iposix_path_mkdir(const char *path, int mode) -{ - int i, len; - char str[IPOSIX_MAXBUFF]; - - len = (int)strlen(path); - if (len > IPOSIX_MAXPATH) len = IPOSIX_MAXPATH; - - memcpy(str, path, len); - str[len] = 0; - -#ifdef _WIN32 - for (i = 0; i < len; i++) { - if (str[i] == '/') str[i] = '\\'; - } -#endif - - for (i = 0; i < len; i++) { - if (str[i] == '/' || str[i] == '\\') { - str[i] = '\0'; - if (iposix_access(str, F_OK) != 0) { - iposix_mkdir(str, mode); - } - str[i] = IPATHSEP; - } - } - - if (len > 0 && iposix_access(str, 0) != 0) { - iposix_mkdir(str, mode); - } - - return 0; -} - - -// 精简版取得可执行路径 -const char *iposix_get_exepath(void) -{ - static int inited = 0; - static char *ptr = NULL; - if (inited == 0) { - char *buffer = (char*)malloc(IPOSIX_MAXBUFF); - char *b2; - int size; - if (buffer == NULL) { - inited = -1; - return ""; - } - if (iposix_path_exepath(buffer, IPOSIX_MAXPATH) != 0) { - free(buffer); - inited = -1; - return ""; - } - size = (int)strlen(buffer); - b2 = (char*)malloc(size + 1); - if (b2 == NULL) { - free(buffer); - inited = -1; - return ""; - } - memcpy(b2, buffer, size + 1); - free(buffer); - ptr = b2; - inited = 1; - } - if (inited < 0) return ""; - return ptr; -} - -// 精简版取得可执行目录 -const char *iposix_get_execwd(void) -{ - static int inited = 0; - static char ptr[IPOSIX_MAXBUFF + 10]; - if (inited == 0) { - if (iposix_path_execwd(ptr, IPOSIX_MAXPATH) != 0) { - inited = -1; - return ""; - } - inited = 1; - } - if (inited < 0) return ""; - return ptr; -} - -#ifdef _MSC_VER -#pragma warning(disable:4996) -#endif - -// 文件路径格式化: -// out - 输出路径,长度不小于 IPOSIX_MAXPATH -// base - 根路径 -// ... - 后续的相对路径 -// 返回 - out -// 假设可执行路径位于 /home/abc/work,那么: -// iposix_path_format(out, iposix_get_execwd(), "images/%s", "abc.jpg") -// 结果就是 /home/abc/work/images/abc.jpg -char *iposix_path_format(char *out, const char *root, const char *fmt, ...) -{ - char buffer[IPOSIX_MAXBUFF]; - va_list argptr; - va_start(argptr, fmt); - vsprintf(buffer, fmt, argptr); - va_end(argptr); - return iposix_path_join(root, buffer, out, IPOSIX_MAXPATH); -} - - - -/*-------------------------------------------------------------------*/ -/* System Utilities */ -/*-------------------------------------------------------------------*/ -#ifndef IDISABLE_SHARED_LIBRARY - #if defined(__unix) - #include - #endif -#endif - -void *iposix_shared_open(const char *dllname) -{ -#ifndef IDISABLE_SHARED_LIBRARY - #ifdef __unix - return dlopen(dllname, RTLD_LAZY); - #else - return (void*)LoadLibraryA(dllname); - #endif -#else - return NULL; -#endif -} - -void *iposix_shared_get(void *shared, const char *name) -{ -#ifndef IDISABLE_SHARED_LIBRARY - #ifdef __unix - return dlsym(shared, name); - #else - return (void*)GetProcAddress((HINSTANCE)shared, name); - #endif -#else - return NULL; -#endif -} - -void iposix_shared_close(void *shared) -{ -#ifndef IDISABLE_SHARED_LIBRARY - #ifdef __unix - dlclose(shared); - #else - FreeLibrary((HINSTANCE)shared); - #endif -#endif -} - -/* load file content */ -void *iposix_file_load_content(const char *filename, long *size) -{ - size_t length, remain; - char *ptr, *out; - FILE *fp; - - if ((fp = fopen(filename, "rb")) == NULL) { - if (size) size[0] = 0; - return NULL; - } - - fseek(fp, 0, SEEK_END); - length = ftell(fp); - fseek(fp, 0, SEEK_SET); - - // avoid zero-size file returns null - ptr = (char*)malloc(length + 8); - - if (ptr == NULL) { - fclose(fp); - if (size) size[0] = 0; - return NULL; - } - - for (remain = length, out = ptr; remain > 0; ) { - size_t ret = fread(out, 1, remain, fp); - if (ret == 0) break; - remain -= ret; - out += ret; - } - - fclose(fp); - - if (size) size[0] = length; - - return ptr; -} - - -/* save file content */ -int iposix_file_save_content(const char *filename, const void *data, long size) -{ - const char *ptr = (const char*)data; - FILE *fp; - int hr = 0; - if ((fp = fopen(filename, "wb")) == NULL) return -1; - for (; size > 0; ) { - long written = (long)fwrite(ptr, 1, size, fp); - if (written <= 0) { - hr = -2; - break; - } - size -= written; - ptr += written; - } - fclose(fp); - return hr; -} - - - -#endif - - - - diff --git a/czmod/iposix.h b/czmod/iposix.h deleted file mode 100644 index 0d0f605..0000000 --- a/czmod/iposix.h +++ /dev/null @@ -1,401 +0,0 @@ -//===================================================================== -// -// iposix.h - posix file system accessing -// -// NOTE: -// for more information, please see the readme file. -// -//===================================================================== -#ifndef __IPOSIX_H__ -#define __IPOSIX_H__ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - - -/*-------------------------------------------------------------------*/ -/* C99 Compatible */ -/*-------------------------------------------------------------------*/ -#if defined(linux) || defined(__linux) || defined(__linux__) -#ifdef _POSIX_C_SOURCE -#if _POSIX_C_SOURCE < 200112L -#undef _POSIX_C_SOURCE -#endif -#endif - -#ifndef _POSIX_C_SOURCE -#define _POSIX_C_SOURCE 200112L -#endif - -#ifdef _GNU_SOURCE -#undef _GNU_SOURCE -#endif - -#ifdef _BSD_SOURCE -#undef _BSD_SOURCE -#endif - -#ifdef __BSD_VISIBLE -#undef __BSD_VISIBLE -#endif - -#ifdef _XOPEN_SOURCE -#undef _XOPEN_SOURCE -#endif - -#define _GNU_SOURCE 1 -#define _BSD_SOURCE 1 -#define __BSD_VISIBLE 1 -#define _XOPEN_SOURCE 600 -#endif - - -#ifndef IDISABLE_FILE_SYSTEM_ACCESS -//--------------------------------------------------------------------- -// Global Definition -//--------------------------------------------------------------------- -#ifndef __INTEGER_32_BITS__ -#define __INTEGER_32_BITS__ -#if defined(__UINT32_TYPE__) && defined(__UINT32_TYPE__) - typedef __UINT32_TYPE__ ISTDUINT32; - typedef __INT32_TYPE__ ISTDINT32; -#elif defined(__UINT_FAST32_TYPE__) && defined(__INT_FAST32_TYPE__) - typedef __UINT_FAST32_TYPE__ ISTDUINT32; - typedef __INT_FAST32_TYPE__ ISTDINT32; -#elif defined(_WIN64) || defined(WIN64) || defined(__amd64__) || \ - defined(__x86_64) || defined(__x86_64__) || defined(_M_IA64) || \ - defined(_M_AMD64) - typedef unsigned int ISTDUINT32; - typedef int ISTDINT32; -#elif defined(_WIN32) || defined(WIN32) || defined(__i386__) || \ - defined(__i386) || defined(_M_X86) - typedef unsigned long ISTDUINT32; - typedef long ISTDINT32; -#elif defined(__MACOS__) - typedef UInt32 ISTDUINT32; - typedef SInt32 ISTDINT32; -#elif defined(__APPLE__) && defined(__MACH__) - #include - typedef u_int32_t ISTDUINT32; - typedef int32_t ISTDINT32; -#elif defined(__BEOS__) - #include - typedef u_int32_t ISTDUINT32; - typedef int32_t ISTDINT32; -#elif (defined(_MSC_VER) || defined(__BORLANDC__)) && (!defined(__MSDOS__)) - typedef unsigned __int32 ISTDUINT32; - typedef __int32 ISTDINT32; -#elif defined(__GNUC__) && (__GNUC__ > 3) - #include - typedef uint32_t ISTDUINT32; - typedef int32_t ISTDINT32; -#else - typedef unsigned long ISTDUINT32; - typedef long ISTDINT32; -#endif -#endif - - -#if (defined(__APPLE__) && defined(__MACH__)) || defined(__MACOS__) -#ifndef __unix -#define __unix 1 -#endif -#endif - -#if defined(__unix__) || defined(unix) || defined(__linux) -#ifndef __unix -#define __unix 1 -#endif -#endif - -#include -#ifdef __unix -#include -#define IPATHSEP '/' -#else -#include -#if defined(_WIN32) -#define IPATHSEP '\\' -#else -#define IPATHSEP '/' -#endif -#endif - - -#ifndef __IINT8_DEFINED -#define __IINT8_DEFINED -typedef char IINT8; -#endif - -#ifndef __IUINT8_DEFINED -#define __IUINT8_DEFINED -typedef unsigned char IUINT8; -#endif - -#ifndef __IUINT16_DEFINED -#define __IUINT16_DEFINED -typedef unsigned short IUINT16; -#endif - -#ifndef __IINT16_DEFINED -#define __IINT16_DEFINED -typedef short IINT16; -#endif - -#ifndef __IINT32_DEFINED -#define __IINT32_DEFINED -typedef ISTDINT32 IINT32; -#endif - -#ifndef __IUINT32_DEFINED -#define __IUINT32_DEFINED -typedef ISTDUINT32 IUINT32; -#endif - -#ifndef __IINT64_DEFINED -#define __IINT64_DEFINED -#if defined(_MSC_VER) || defined(__BORLANDC__) -typedef __int64 IINT64; -#else -typedef long long IINT64; -#endif -#endif - -#ifndef __IUINT64_DEFINED -#define __IUINT64_DEFINED -#if defined(_MSC_VER) || defined(__BORLANDC__) -typedef unsigned __int64 IUINT64; -#else -typedef unsigned long long IUINT64; -#endif -#endif - -#if defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64) - #ifndef _WIN32 - #define _WIN32 - #endif -#endif - - -#ifdef __cplusplus -extern "C" { -#endif - -//--------------------------------------------------------------------- -// Posix Stat -//--------------------------------------------------------------------- -#define ISTAT_IFMT 0170000 // file type mask -#define ISTAT_IFIFO 0010000 // named pipe (fifo) -#define ISTAT_IFCHR 0020000 // charactor special -#define ISTAT_IFDIR 0040000 // directory -#define ISTAT_IFBLK 0060000 // block special -#define ISTAT_IFREG 0100000 // regular -#define ISTAT_IFLNK 0120000 // symbolic link -#define ISTAT_IFSOCK 0140000 // socket -#define ISTAT_IFWHT 0160000 // whiteout -#define ISTAT_ISUID 0004000 // set user id on execution -#define ISTAT_ISGID 0002000 // set group id on execution -#define ISTAT_ISVXT 0001000 // swapped text even after use -#define ISTAT_IRWXU 0000700 // owner RWX mask -#define ISTAT_IRUSR 0000400 // owner read permission -#define ISTAT_IWUSR 0000200 // owner writer permission -#define ISTAT_IXUSR 0000100 // owner execution permission -#define ISTAT_IRWXG 0000070 // group RWX mask -#define ISTAT_IRGRP 0000040 // group read permission -#define ISTAT_IWGRP 0000020 // group write permission -#define ISTAT_IXGRP 0000010 // group execution permission -#define ISTAT_IRWXO 0000007 // other RWX mask -#define ISTAT_IROTH 0000004 // other read permission -#define ISTAT_IWOTH 0000002 // other writer permission -#define ISTAT_IXOTH 0000001 // other execution permission - -#define ISTAT_ISFMT(m, t) (((m) & ISTAT_IFMT) == (t)) -#define ISTAT_ISDIR(m) ISTAT_ISFMT(m, ISTAT_IFDIR) -#define ISTAT_ISCHR(m) ISTAT_ISFMT(m, ISTAT_IFCHR) -#define ISTAT_ISBLK(m) ISTAT_ISFMT(m, ISTAT_IFBLK) -#define ISTAT_ISREG(m) ISTAT_ISFMT(m, ISTAT_IFREG) -#define ISTAT_ISFIFO(m) ISTAT_ISFMT(m, ISTAT_IFIFO) -#define ISTAT_ISLNK(m) ISTAT_ISFMT(m, ISTAT_IFLNK) -#define ISTAT_ISSOCK(m) ISTAT_ISFMT(m, ISTAT_IFSOCK) -#define ISTAT_ISWHT(m) ISTAT_ISFMT(m, ISTAT_IFWHT) - -struct IPOSIX_STAT -{ - IUINT32 st_mode; - IUINT64 st_ino; - IUINT32 st_dev; - IUINT32 st_nlink; - IUINT32 st_uid; - IUINT32 st_gid; - IUINT64 st_size; - IUINT32 atime; - IUINT32 mtime; - IUINT32 ctime; - IUINT32 st_blocks; - IUINT32 st_blksize; - IUINT32 st_rdev; - IUINT32 st_flags; -}; - -typedef struct IPOSIX_STAT iposix_stat_t; - -#define IPOSIX_MAXPATH 1024 -#define IPOSIX_MAXBUFF ((IPOSIX_MAXPATH) + 8) - - -// returns 0 for success, -1 for error -int iposix_stat(const char *path, iposix_stat_t *ostat); - -// returns 0 for success, -1 for error -int iposix_lstat(const char *path, iposix_stat_t *ostat); - -// returns 0 for success, -1 for error -int iposix_fstat(int fd, iposix_stat_t *ostat); - -// get current directory -char *iposix_getcwd(char *path, int size); - -// create directory -int iposix_mkdir(const char *path, int mode); - -// change directory -int iposix_chdir(const char *path); - -#ifndef F_OK -#define F_OK 0 -#endif - -#ifndef X_OK -#define X_OK 1 -#endif - -#ifndef W_OK -#define W_OK 2 -#endif - -#ifndef R_OK -#define R_OK 4 -#endif - -// check access -int iposix_access(const char *path, int mode); - - -// returns 1 for true 0 for false, -1 for not exist -int iposix_path_isdir(const char *path); - -// returns 1 for true 0 for false, -1 for not exist -int iposix_path_isfile(const char *path); - -// returns 1 for true 0 for false, -1 for not exist -int iposix_path_islink(const char *path); - -// returns 1 for true 0 for false -int iposix_path_exists(const char *path); - -// returns file size, -1 for error -IINT64 iposix_path_getsize(const char *path); - - -//--------------------------------------------------------------------- -// Posix Path -//--------------------------------------------------------------------- - -// 是否是绝对路径,如果是的话返回1,否则返回0 -int iposix_path_isabs(const char *path); - -// 绝对路径 -char *iposix_path_abspath(const char *srcpath, char *path, int maxsize); - -// 归一化路径:去掉重复斜杠,以及处理掉".", ".."等。 -char *iposix_path_normal(const char *srcpath, char *path, int maxsize); - -// 连接路径 -char *iposix_path_join(const char *p1, const char *p2, char *path, int len); - -// 路径分割:从右向左找到第一个"/"分成两个字符串 -int iposix_path_split(const char *path, char *p1, int l1, char *p2, int l2); - -// 扩展分割:分割文件主名与扩展名 -int iposix_path_splitext(const char *path, char *p1, int l1, - char *p2, int l2); - - -//--------------------------------------------------------------------- -// platform special -//--------------------------------------------------------------------- - -// 取得进程可执行文件的文件名 -int iposix_path_exepath(char *ptr, int size); - -// 取得进程可执行文件的目录 -int iposix_path_execwd(char *ptr, int size); - -// 递归创建路径 -int iposix_path_mkdir(const char *path, int mode); - -// 精简版取得可执行路径 -const char *iposix_get_exepath(void); - -// 精简版取得可执行目录 -const char *iposix_get_execwd(void); - - -// 文件路径格式化: -// out - 输出路径,长度不小于 IPOSIX_MAXPATH -// root - 根路径 -// ... - 后续的相对路径 -// 返回 - out -// 假设可执行路径位于 /home/abc/work,那么: -// iposix_path_format(out, iposix_get_execwd(), "images/%s", "abc.jpg") -// 结果就是 /home/abc/work/images/abc.jpg -char *iposix_path_format(char *out, const char *root, const char *fmt, ...); - - - -//--------------------------------------------------------------------- -// System Utilities -//--------------------------------------------------------------------- - -#ifndef IDISABLE_SHARED_LIBRARY - -/* LoadLibraryA */ -void *iposix_shared_open(const char *dllname); - -/* GetProcAddress */ -void *iposix_shared_get(void *shared, const char *name); - -/* FreeLibrary */ -void iposix_shared_close(void *shared); - -#endif - -#ifndef IDISABLE_FILE_SYSTEM_ACCESS - -/* load file content, use free to dispose */ -void *iposix_file_load_content(const char *filename, long *size); - -/* save file content */ -int iposix_file_save_content(const char *filename, const void *data, long size); - -/* cross os GetModuleFileName, returns size for success, -1 for error */ -int iposix_get_proc_pathname(char *ptr, int size); - -#endif - - - -#ifdef __cplusplus -} -#endif - - -#endif - - -#endif - - - -