--- libelwix/src/index.c 2022/01/04 22:32:34 1.1 +++ libelwix/src/index.c 2022/01/06 15:13:01 1.2 @@ -0,0 +1,358 @@ +/************************************************************************* +* (C) 2022 AITNET ltd - Sofia/Bulgaria - +* by Michael Pounov +* +* $Author: misho $ +* $Id: index.c,v 1.2 2022/01/06 15:13:01 misho Exp $ +* +************************************************************************** +The ELWIX and AITNET software is distributed under the following +terms: + +All of the documentation and software included in the ELWIX and AITNET +Releases is copyrighted by ELWIX - Sofia/Bulgaria + +Copyright 2004 - 2022 + by Michael Pounov . All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. All advertising materials mentioning features or use of this software + must display the following acknowledgement: +This product includes software developed by Michael Pounov +ELWIX - Embedded LightWeight unIX and its contributors. +4. Neither the name of AITNET nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY AITNET AND CONTRIBUTORS ``AS IS'' AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. +*/ +#include "global.h" + + +/* + * index_Init() - Init index structure + * + * @idx = index, if it is NULL then it will be allocate + * return: NULL is error and !=NULL index ready for use + */ +index_t * +index_Init(index_t * __restrict idx) +{ + if (!idx) { + idx = e_malloc(sizeof(index_t)); + if (!idx) + return NULL; + } + memset(idx, 0, sizeof(index_t)); + + return idx; +} + +static inline void +index_FreeList(index_list_t __restrict lst) +{ + index_list_t n, l = lst; + + while (l) { + n = l->il_next; + e_free(l); + l = n; + } +} + +/* + * index_FreeLists() - Free linked lists with data + * + * @idx = index + * return: none + */ +void +index_FreeLists(index_t *idx) +{ + register int i; + + for (i = 0; i < 65536; i++) + index_FreeList(idx->i_hash[i]); + memset(idx->i_hash, 0, sizeof idx->i_hash); +} + +/* + * index_Destroy() - Destroy index + * + * @idx = index + * return: none + */ +void +index_Destroy(index_t **idx) +{ + if (idx && *idx) { + index_FreeLists(*idx); + e_free(*idx); + *idx = NULL; + } +} + +/* + * index_getArray() - Get list behind key into array + * + * @idx = index + * @key = Hash value + * return: NULL is error and !=NULL allocated array. It must be free after use + */ +array_t * +index_getArray(index_t *idx, u_short key) +{ + array_t *arr = NULL; + index_list_t lst; + register int n = 0; + + if (!idx) + return NULL; + + for (n = 0, lst = index_getList(idx, key); lst; n++, lst = lst->il_next); + arr = array_Init(n); + if (!arr) + return NULL; + for (n = 0, lst = index_getList(idx, key); lst; n++, lst = lst->il_next) + array_Set(arr, n, lst); + + return arr; +} + +/* + * index_add() - Adds item to index hash + * + * @idx = index + * @key = hash key + * @data = data + * @datlen = data length + * @hash = return calculated hash of data + * return: -1 error or 0 ok + */ +int +index_add(index_t *idx, u_short key, void *data, int datlen, u_int *hash) +{ + index_list_t lst, item; + + if (!idx || !data) + return -1; + + item = e_malloc(sizeof(struct tagIndexList)); + if (!item) + return -1; + else + memset(item, 0, sizeof(struct tagIndexList)); + + lst = idx->i_hash[key]; + + item->il_hash = crcAdler(data, datlen); + item->il_ptr = data; + item->il_len = datlen; + item->il_next = lst; + idx->i_hash[key] = item; + + if (hash) + *hash = item->il_hash; + + return 0; +} + +/* + * index_del() - Dels item from index hash + * + * @idx = index + * @key = hash key + * @data = data + * @datlen = data length + * return: -1 error, 0 nothing deleted and 1 item deleted + */ +int +index_del(index_t *idx, u_short key, void *data, int datlen) +{ + index_list_t lst, prev; + u_int hash; + + if (!idx || !data) + return -1; + + lst = idx->i_hash[key]; + if (!lst) + return 0; + + hash = crcAdler(data, datlen); + + if (lst->il_len == datlen && lst->il_hash == hash) { + idx->i_hash[key] = lst->il_next; + e_free(lst); + return 1; /* deleted item */ + } else { + prev = lst; + lst = lst->il_next; + } + while (lst) { + if (lst->il_len == datlen && lst->il_hash == hash) { + prev->il_next = lst->il_next; + e_free(lst); + return 1; /* deleted item */ + } else { + prev = lst; + lst = lst->il_next; + } + } + + return 0; +} + +/* + * index_delList() - Delete list behind key + * + * @idx = index + * @key = Hash value + * return: -1 is error and 0 is ok + */ +int +index_delList(index_t *idx, u_short key) +{ + if (!idx) + return -1; + + index_FreeList(idx->i_hash[key]); + idx->i_hash[key] = NULL; + return 0; +} + +/* + * index_del2() - Dels item with index key and hash + * + * @idx = index + * @key = hash key + * @hash = calculated hash of item when its added to index + * return: -1 error, 0 nothing deleted and 1 item deleted + */ +int +index_del2(index_t *idx, u_short key, u_int hash) +{ + index_list_t lst, prev; + + if (!idx) + return -1; + + lst = idx->i_hash[key]; + if (!lst) + return 0; + + if (lst->il_hash == hash) { + idx->i_hash[key] = lst->il_next; + e_free(lst); + return 1; /* deleted item */ + } else { + prev = lst; + lst = lst->il_next; + } + while (lst) { + if (lst->il_hash == hash) { + prev->il_next = lst->il_next; + e_free(lst); + return 1; /* deleted item */ + } else { + prev = lst; + lst = lst->il_next; + } + } + + return 0; +} + +/* + * index_get2() - Get item by key and hash + * + * @idx = index + * @key = hash key + * @hash = calculated hash of item when its added to index + * return: NULL error or not found and !=NULL returned item + */ +index_list_t +index_get2(index_t *idx, u_short key, u_int hash) +{ + index_list_t lst; + + if (!idx) + return NULL; + + lst = idx->i_hash[key]; + if (!lst) + return NULL; + + while (lst) + if (lst->il_hash == hash) + break; /* found */ + else + lst = lst->il_next; + + return lst; +} + +/* + * index_getVar() - Get item by key and hash as Var + * + * @idx = index + * @key = hash key + * @hash = calculated hash of item when its added to index + * return: NULL error or not found and !=NULL returned variable. Must be free after use! + */ +ait_val_t * +index_getVar(index_t *idx, u_short key, u_int hash) +{ + index_list_t lst; + ait_val_t *v = NULL; + + lst = index_get2(idx, key, hash); + if (!lst) + return NULL; + + v = ait_allocVar(); + if (!v) + return NULL; + + AIT_SET_PTR(v, lst->il_ptr, lst->il_len); + return v; +} + +/* + * index_dump() - Debug routine about index hashes + * + * @idx = index + * return: none + */ +void +index_dump(index_t *idx) +{ + index_list_t lst; + register int i; + + for (i = 0; i < 65536; i++) { + lst = idx->i_hash[i]; + while (lst) { + printf("index[%hu/0x%x]=%s length=%lu\n", (u_short) i, index_Hash(lst), + (const char*) index_Ptr(lst), index_Len(lst)); + lst = lst->il_next; + } + } +}