commit 701dcd26c847e003cccb6ce8410a5dfd9fb532ad
parent 93ad86974a4ffa9907a66a7ca441bfb54d95250e
Author: vaplv <vaplv@free.fr>
Date: Wed, 18 Nov 2020 11:06:31 +0100
Merge branch 'release_0.11'
Diffstat:
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;
+}