rsys

Basic data structures and low-level features
git clone git://git.meso-star.fr/rsys.git
Log | Files | Refs | README | LICENSE

commit 701dcd26c847e003cccb6ce8410a5dfd9fb532ad
parent 93ad86974a4ffa9907a66a7ca441bfb54d95250e
Author: vaplv <vaplv@free.fr>
Date:   Wed, 18 Nov 2020 11:06:31 +0100

Merge branch 'release_0.11'

Diffstat:
MREADME.md | 7+++++++
Mcmake/CMakeLists.txt | 3++-
Msrc/hash_table.h | 33+++++++++++++++++++++++++++++----
Msrc/rsys.h | 12++++++++++++
Msrc/test_hash_table.c | 109+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
Asrc/test_vmacros.c | 35+++++++++++++++++++++++++++++++++++
6 files changed, 192 insertions(+), 7 deletions(-)

diff --git a/README.md b/README.md @@ -17,6 +17,13 @@ project can be now edited, built, tested and installed as any CMake project. ## Release notes +### Version 0.11 + +- Add the `find_iterator` function to the hash table data structure. This + function returns an iterator toward the hash table entry corresponding to the + submitted key. +- Increase the capacity of the "variadic macros" up to 9 arguments. + ### Version 0.10 - Add the `str_vprintf` and `str_append_[v]printf` functions to the string API diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -38,7 +38,7 @@ include(rcmake) # Configure and define targets ################################################################################ set(VERSION_MAJOR 0) -set(VERSION_MINOR 10) +set(VERSION_MINOR 11) set(VERSION_PATCH 0) set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}) @@ -237,6 +237,7 @@ if(NOT NO_TEST) new_test(test_stretchy_array rsys) new_test(test_text_reader rsys) new_test(test_time rsys) + new_test(test_vmacros) add_library(test_lib SHARED ${RSYS_SOURCE_DIR}/test_library.c) set_target_properties(test_lib PROPERTIES diff --git a/src/hash_table.h b/src/hash_table.h @@ -233,14 +233,14 @@ HTABLE_FUNC__(pair_copy_and_release__) struct HTABLE__ { struct HTABLE_DATA__ table; struct darray_char table_slot_is_used; - size_t table_size_in_use; + size_t table_size_in_use; /* #slots in used */ struct mem_allocator* allocator; }; struct HTABLE_ITERATOR__ { struct HTABLE__* hash_table; size_t slot; - size_t entries_scanned; + size_t entries_scanned; /* Used to early stop the next procedure */ }; /******************************************************************************* @@ -307,6 +307,7 @@ HTABLE_FUNC__(clear)(struct HTABLE__* htbl) * subsequent uses */ HTABLE_FUNC__(pair_release__)(pair); HTABLE_FUNC__(pair_init__)(htbl->allocator, pair); + ++in_use; } htbl->table_size_in_use = 0; } @@ -617,13 +618,36 @@ HTABLE_FUNC__(end) } static INLINE void +HTABLE_FUNC__(find_iterator) + (struct HTABLE__* htbl, + HTABLE_KEY const* key, + struct HTABLE_ITERATOR__* it) +{ + size_t i = 0; + ASSERT(htbl && key && it); + if(HTABLE_FUNC__(is_empty)(htbl)) { + HTABLE_FUNC__(end)(htbl, it); + return; + } + + i = HTABLE_FUNC__(find_slot__)(htbl, key); + if(!darray_char_cdata_get(&htbl->table_slot_is_used)[i]) { + HTABLE_FUNC__(end)(htbl, it); + } else { + it->slot = i; + it->hash_table = htbl; + it->entries_scanned = 0; + } +} + +static INLINE void HTABLE_FUNC__(iterator_next)(struct HTABLE_ITERATOR__* it) { size_t tbl_size = 0; ASSERT(it); tbl_size = HTABLE_DATA_FUNC__(size_get)(&it->hash_table->table); - if(it->entries_scanned >= it->hash_table->table_size_in_use) { + if(it->entries_scanned >= it->hash_table->table_size_in_use) {/* Early stop */ it->slot = tbl_size; } else { size_t i = 0; @@ -640,9 +664,10 @@ HTABLE_FUNC__(iterator_eq) const struct HTABLE_ITERATOR__* it1) { ASSERT(it0 && it1); + /* Do not compare the 'entries_scanned' field used only to early stop the + * iterator_next function in some situations */ return it0->slot == it1->slot - && it0->entries_scanned == it1->entries_scanned && it0->hash_table == it1->hash_table; } diff --git a/src/rsys.h b/src/rsys.h @@ -315,6 +315,10 @@ static INLINE DEPRECATED void macro_NCHECK(void) { (void)0; } #define ARG3(A, B, C) #define ARG4(A, B, C, D) #define ARG5(A, B, C, D, E) +#define ARG6(A, B, C, D, E, F) +#define ARG7(A, B, C, D, E, F, G) +#define ARG8(A, B, C, D, E, F, G, H) +#define ARG9(A, B, C, D, E, F, G, H, I) #define LIST_ARG0() #define LIST_ARG1(A) A @@ -322,6 +326,10 @@ static INLINE DEPRECATED void macro_NCHECK(void) { (void)0; } #define LIST_ARG3(A, B, C) A, B, C #define LIST_ARG4(A, B, C, D) A, B, C, D #define LIST_ARG5(A, B, C, D, E) A, B, C, D, E +#define LIST_ARG6(A, B, C, D, E, F) A, B, C, D, E, F +#define LIST_ARG7(A, B, C, D, E, F, G) A, B, C, D, E, F, G +#define LIST_ARG8(A, B, C, D, E, F, G, H) A, B, C, D, E, F, G, H +#define LIST_ARG9(A, B, C, D, E, F, G, H, I) A, B, C, D, E, F, G, H, I #define COMMA_ARG0() #define COMMA_ARG1(A) , @@ -329,6 +337,10 @@ static INLINE DEPRECATED void macro_NCHECK(void) { (void)0; } #define COMMA_ARG3(A, B, C) , #define COMMA_ARG4(A, B, C, D) , #define COMMA_ARG5(A, B, C, D, E) , +#define COMMA_ARG6(A, B, C, D, E, F) , +#define COMMA_ARG7(A, B, C, D, E, F, G) , +#define COMMA_ARG8(A, B, C, D, E, F, G, H) , +#define COMMA_ARG9(A, B, C, D, E, F, G, H, I) , /******************************************************************************* * Result constants diff --git a/src/test_hash_table.c b/src/test_hash_table.c @@ -48,8 +48,15 @@ test_htbl_int_float(void) FOR_EACH(i, 0, n) { float* p = htable_int_float_find(&htbl, &i); + struct htable_int_float_iterator it; + struct htable_int_float_iterator end; + htable_int_float_find_iterator(&htbl, &i, &it); + htable_int_float_end(&htbl, &end); CHK(p != NULL); CHK(*p == (float) i); + CHK(!htable_int_float_iterator_eq(&it, &end)); + CHK(*htable_int_float_iterator_key_get(&it) == i); + CHK(*htable_int_float_iterator_data_get(&it) == (float)i); } CHK(htable_int_float_size_get(&htbl) == (size_t)n); FOR_EACH(i, 0, n / 2) { @@ -58,12 +65,24 @@ test_htbl_int_float(void) CHK(htable_int_float_size_get(&htbl) == (size_t)(n/2)); FOR_EACH(i, 0, n/2) { float* p = htable_int_float_find(&htbl, &i); + struct htable_int_float_iterator it; + struct htable_int_float_iterator end; + htable_int_float_find_iterator(&htbl, &i, &it); + htable_int_float_end(&htbl, &end); CHK(p == NULL); + CHK(htable_int_float_iterator_eq(&it, &end)); } FOR_EACH(i, n/2, n) { float* p = htable_int_float_find(&htbl, &i); + struct htable_int_float_iterator it; + struct htable_int_float_iterator end; + htable_int_float_find_iterator(&htbl, &i, &it); + htable_int_float_end(&htbl, &end); CHK(p != NULL); CHK(*p == (float) i); + CHK(!htable_int_float_iterator_eq(&it, &end)); + CHK(*htable_int_float_iterator_key_get(&it) == i); + CHK(*htable_int_float_iterator_data_get(&it) == (float)i); } htable_int_float_release(&htbl); @@ -101,6 +120,7 @@ test_htbl_str_int(void) struct htable_str_int htbl; struct htable_str_int_iterator it0; struct htable_str_int_iterator it1; + struct htable_str_int_iterator it2; const char* str[] = { "analyse", "analysis", "analyst", "analytic", "analytical", "analytically", "analyze", "approach", "approachable", "area", "assess", "assessable", @@ -129,6 +149,7 @@ test_htbl_str_int(void) const int array_size = (int)(sizeof(array) / sizeof(int)); struct str tmp; int i = 0; + struct str* key = NULL; int* data = NULL; STATIC_ASSERT (sizeof(str)/sizeof(const char*) >= sizeof(array)/sizeof(int), @@ -157,6 +178,11 @@ test_htbl_str_int(void) str_set(&tmp, "empty"); CHK(htable_str_int_find(&htbl, &tmp) == NULL); CHK(htable_str_int_size_get(&htbl) == 0); + htable_str_int_find_iterator(&htbl, &tmp, &it0); + htable_str_int_end(&htbl, &it1); + CHK(htable_str_int_iterator_eq(&it0, &it1)); + htable_str_int_iterator_next(&it0); + CHK(htable_str_int_iterator_eq(&it0, &it1)); i = 0; str_set(&tmp, str[i]); CHK(htable_str_int_set(&htbl, &tmp, &i) == RES_OK); @@ -169,6 +195,17 @@ test_htbl_str_int(void) } CHK(htable_str_int_size_get(&htbl) == (size_t)str_size); + str_set(&tmp, str[str_size/2]); + htable_str_int_find_iterator(&htbl, &tmp, &it0); + htable_str_int_end(&htbl, &it1); + CHK(!htable_str_int_iterator_eq(&it0, &it1)); + while(!htable_str_int_iterator_eq(&it0, &it1)) { + key = htable_str_int_iterator_key_get(&it0); + data = htable_str_int_iterator_data_get(&it0); + CHK(*htable_str_int_find(&htbl, key) == *data); + htable_str_int_iterator_next(&it0); + } + str_set(&tmp, "Terra icognita"); CHK(htable_str_int_find(&htbl, &tmp) == NULL); FOR_EACH(i, 0, 64) { @@ -177,6 +214,11 @@ test_htbl_str_int(void) data = htable_str_int_find(&htbl, &tmp); CHK(data != NULL); CHK(*data == (int)j); + htable_str_int_find_iterator(&htbl, &tmp, &it0); + htable_str_int_end(&htbl, &it1); + CHK(!htable_str_int_iterator_eq(&it0, &it1)); + CHK(!str_cmp(htable_str_int_iterator_key_get(&it0), &tmp)); + CHK(*htable_str_int_iterator_data_get(&it0) == (int)j); } str_set(&tmp, "Terra icognita"); @@ -188,6 +230,9 @@ test_htbl_str_int(void) FOR_EACH(i, 0, array_size) { str_set(&tmp, str[array[i]]); CHK(htable_str_int_find(&htbl, &tmp) == 0); + htable_str_int_find_iterator(&htbl, &tmp, &it0); + htable_str_int_end(&htbl, &it1); + CHK(htable_str_int_iterator_eq(&it0, &it1)); } CHK(htable_str_int_size_get(&htbl) == (size_t)(str_size - array_size)); FOR_EACH(i, 0, str_size) { @@ -201,6 +246,11 @@ test_htbl_str_int(void) data = htable_str_int_find(&htbl, &tmp); CHK(data != NULL); CHK(*data == (int)i); + htable_str_int_find_iterator(&htbl, &tmp, &it0); + htable_str_int_end(&htbl, &it1); + CHK(!htable_str_int_iterator_eq(&it0, &it1)); + CHK(!str_cmp(htable_str_int_iterator_key_get(&it0), &tmp)); + CHK(*htable_str_int_iterator_data_get(&it0) == (int)i); } } FOR_EACH(i, 0, array_size) { @@ -216,9 +266,15 @@ test_htbl_str_int(void) CHK(htable_str_int_iterator_eq(&it0, &it1) == 0); memset(str_found, 0, sizeof(str_found)); while(!htable_str_int_iterator_eq(&it0, &it1) ) { + key = htable_str_int_iterator_key_get(&it0); data = htable_str_int_iterator_data_get(&it0); - CHK(*htable_str_int_find(&htbl, htable_str_int_iterator_key_get(&it0)) - == *data); + CHK(*htable_str_int_find(&htbl, key) == *data); + + htable_str_int_find_iterator(&htbl, key, &it2); + CHK(htable_str_int_iterator_eq(&it0, &it2)); + CHK(!str_cmp(htable_str_int_iterator_key_get(&it2), key)); + CHK(*htable_str_int_iterator_data_get(&it2) == *data); + CHK(str_found[*data] == 0); str_found[*data] = 1; htable_str_int_iterator_next(&it0); @@ -255,8 +311,13 @@ test_htbl_str_int(void) CHK(htable_str_int_size_get(&htbl) == 5); data = htable_str_int_find(&htbl, &tmp); + htable_str_int_find_iterator(&htbl, &tmp, &it0); + htable_str_int_end(&htbl, &it1); CHK(data != NULL); CHK(*data == 'a'); + CHK(!htable_str_int_iterator_eq(&it0, &it1)); + CHK(!str_cmp(htable_str_int_iterator_key_get(&it0), &tmp)); + CHK(*htable_str_int_iterator_data_get(&it0) == *data); htable_str_int_clear(&htbl); htable_str_int_begin(&htbl, &it0); @@ -409,16 +470,37 @@ ANGVBA BS QRZBAF EHA NZBX VA BHE PVGVRF.", str_set(&tmp, str[i]); data = htable_str_darray_find(&htbl, &tmp); + htable_str_darray_find_iterator(&htbl, &tmp, &it0); + htable_str_darray_end(&htbl, &it1); CHK(data != NULL); CHK(strcmp(darray_char_cdata_get(data), str[i]) == 0); + CHK(!htable_str_darray_iterator_eq(&it0, &it1)); + key = htable_str_darray_iterator_key_get(&it0); + data = htable_str_darray_iterator_data_get(&it0); + CHK(!str_cmp(key, &tmp)); + CHK(strcmp(darray_char_cdata_get(data), str[i]) == 0); data = htable_str_darray_find(&htbl2, &tmp); + htable_str_darray_find_iterator(&htbl2, &tmp, &it0); + htable_str_darray_end(&htbl2, &it1); CHK(data != NULL); CHK(strcmp(darray_char_cdata_get(data), str[i]) == 0); + CHK(!htable_str_darray_iterator_eq(&it0, &it1)); + key = htable_str_darray_iterator_key_get(&it0); + data = htable_str_darray_iterator_data_get(&it0); + CHK(!str_cmp(key, &tmp)); + CHK(strcmp(darray_char_cdata_get(data), str[i]) == 0); data = htable_str_darray_find(&htbl3, &tmp); + htable_str_darray_find_iterator(&htbl3, &tmp, &it0); + htable_str_darray_end(&htbl3, &it1); CHK(data != NULL); CHK(strcmp(darray_char_cdata_get(data), str[i]) == 0); + CHK(!htable_str_darray_iterator_eq(&it0, &it1)); + key = htable_str_darray_iterator_key_get(&it0); + data = htable_str_darray_iterator_data_get(&it0); + CHK(!str_cmp(key, &tmp)); + CHK(strcmp(darray_char_cdata_get(data), str[i]) == 0); } FOR_EACH(j, 0, nerase) { @@ -433,8 +515,14 @@ ANGVBA BS QRZBAF EHA NZBX VA BHE PVGVRF.", str_set(&tmp, str[i]); data = htable_str_darray_find(&htbl, &tmp); + htable_str_darray_find_iterator(&htbl, &tmp, &it0); + htable_str_darray_end(&htbl, &it1); CHK(data != NULL); CHK(strcmp(darray_char_cdata_get(data), str_cget(&tmp)) == 0); + key = htable_str_darray_iterator_key_get(&it0); + data = htable_str_darray_find(&htbl, &tmp); + CHK(!str_cmp(key, &tmp)); + CHK(strcmp(darray_char_cdata_get(data), str_cget(&tmp)) == 0); CHK(htable_str_darray_erase(&htbl, &tmp) == 1); CHK(htable_str_darray_erase(&htbl, &tmp) == 0); } @@ -444,15 +532,32 @@ ANGVBA BS QRZBAF EHA NZBX VA BHE PVGVRF.", str_set(&tmp, str[buf[j]]); data = htable_str_darray_find(&htbl, &tmp); + htable_str_darray_find_iterator(&htbl, &tmp, &it0); + htable_str_darray_end(&htbl, &it1); CHK(data == NULL); + CHK(htable_str_darray_iterator_eq(&it0, &it1)); data = htable_str_darray_find(&htbl2, &tmp); + htable_str_darray_find_iterator(&htbl2, &tmp, &it0); + htable_str_darray_end(&htbl2, &it1); CHK(data != NULL); CHK(strcmp(darray_char_cdata_get(data), str[buf[j]]) == 0); + CHK(!htable_str_darray_iterator_eq(&it0, &it1)); + key = htable_str_darray_iterator_key_get(&it0); + data = htable_str_darray_iterator_data_get(&it0); + CHK(!str_cmp(key, &tmp)); + CHK(strcmp(darray_char_cdata_get(data), str[buf[j]]) == 0); data = htable_str_darray_find(&htbl3, &tmp); + htable_str_darray_find_iterator(&htbl3, &tmp, &it0); + htable_str_darray_end(&htbl3, &it1); CHK(data != NULL); CHK(strcmp(darray_char_cdata_get(data), str[buf[j]]) == 0); + CHK(!htable_str_darray_iterator_eq(&it0, &it1)); + key = htable_str_darray_iterator_key_get(&it0); + data = htable_str_darray_iterator_data_get(&it0); + CHK(!str_cmp(key, &tmp)); + CHK(strcmp(darray_char_cdata_get(data), str[buf[j]]) == 0); } diff --git a/src/test_vmacros.c b/src/test_vmacros.c @@ -0,0 +1,35 @@ +/* Copyright (C) 2013-2020 Vincent Forest (vaplv@free.fr) + * + * The RSys library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The RSys library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with the RSys library. If not, see <http://www.gnu.org/licenses/>. */ + +#include "rsys.h" + +int +main(int argc, char** argv) +{ + (void)argc, (void)argv; + #define PRINTF(Fmt, Args) printf(Fmt COMMA_##Args LIST_##Args) + PRINTF("Arg0\n", ARG0()); + PRINTF("Arg1 %d\n", ARG1(1)); + PRINTF("Arg2 %d %d\n", ARG2(1, 2)); + PRINTF("Arg3 %d %d %d\n", ARG3(1, 2, 3)); + PRINTF("Arg4 %d %d %d %d\n", ARG4(1, 2, 3, 4)); + PRINTF("Arg5 %d %d %d %d %d\n", ARG5(1, 2, 3, 4, 5)); + PRINTF("Arg6 %d %d %d %d %d %d\n", ARG6(1, 2, 3, 4, 5, 6)); + PRINTF("Arg7 %d %d %d %d %d %d %d\n", ARG7(1, 2, 3, 4, 5, 6, 7)); + PRINTF("Arg8 %d %d %d %d %d %d %d %d\n", ARG8(1, 2, 3, 4, 5, 6, 7, 8)); + PRINTF("Arg9 %d %d %d %d %d %d %d %d %d\n", ARG9(1, 2, 3, 4, 5, 6, 7, 8, 9)); + #undef PRINTF + return 0; +}