From 28ea73301e080861b9f4980a63954a7ba4ad2fcb Mon Sep 17 00:00:00 2001 From: Yves Rutschle Date: Sun, 22 Jun 2025 16:45:50 +0200 Subject: [PATCH] new gap feature: hardlimit, with test suite --- gap.c | 14 +- gap.h | 9 +- testgap/Makefile | 7 + testgap/gtest.c | 102 +++ testgap/hardlimit.tst | 11 + testgap/hardlimit.tst.ref | 514 +++++++++++ testgap/insert_extend.tst | 5 + testgap/insert_extend.tst.ref | 1538 +++++++++++++++++++++++++++++++++ testgap/inserts.tst | 6 + testgap/inserts.tst.ref | 514 +++++++++++ testgap/remove.tst | 10 + testgap/remove.tst.ref | 514 +++++++++++ testgap/run | 30 + 13 files changed, 3272 insertions(+), 2 deletions(-) create mode 100644 testgap/Makefile create mode 100644 testgap/gtest.c create mode 100644 testgap/hardlimit.tst create mode 100644 testgap/hardlimit.tst.ref create mode 100644 testgap/insert_extend.tst create mode 100644 testgap/insert_extend.tst.ref create mode 100644 testgap/inserts.tst create mode 100644 testgap/inserts.tst.ref create mode 100644 testgap/remove.tst create mode 100644 testgap/remove.tst.ref create mode 100755 testgap/run diff --git a/gap.c b/gap.c index 3b3f98c..39d2e63 100644 --- a/gap.c +++ b/gap.c @@ -59,6 +59,11 @@ gap_array* gap_init(int len) return gap; } +void gap_set_hardlimit(gap_array* gap, int index) +{ + gap->hardlimit = index; +} + int gap_extend(gap_array* gap) { int elem_size = sizeof(gap->array[0]); @@ -88,7 +93,11 @@ void gap_destroy(gap_array* gap) * is considered len elements long. * A poor man's list, if you will. Currently only used to remove probing * connections, so it only copies a few pointers at most. - * Returns -1 if ptr was not found */ + * Returns: + * -1 if ptr was not found + * -2 if `len` is inconsistent with gap->len (i.e. trying to shift beyond the + * end of the array) + * */ int gap_remove_ptr(gap_array* gap, void* ptr, int len) { int start, i; @@ -102,6 +111,9 @@ int gap_remove_ptr(gap_array* gap, void* ptr, int len) else return -1; + if (gap->len < len) + return -2; + for (i = start; i < len - 1; i++) { gap->array[i] = gap->array[i+1]; } diff --git a/gap.h b/gap.h index 26690a6..aab6005 100644 --- a/gap.h +++ b/gap.h @@ -4,6 +4,7 @@ typedef struct gap_array gap_array; gap_array* gap_init(int len); +void gap_set_hardlimit(gap_array* ga, int index); static void* gap_get(gap_array* gap, int index); static int gap_set(gap_array* gap, int index, void* ptr); void gap_destroy(gap_array* gap); @@ -13,7 +14,8 @@ int gap_remove_ptr(gap_array* gap, void* ptr, int len); /* Private declarations to allow inlining. * Don't assume my implementation. */ typedef struct gap_array { - int len; /* Number of elements in array */ + int len; /* Number of elements in array (corresponds to the number of pages allocated) */ + int hardlimit; /* Maximum index allowed after which sets will fail; 0 means no limit */ void** array; } gap_array; @@ -21,6 +23,9 @@ int gap_extend(gap_array* gap); static inline int __attribute__((unused)) gap_set(gap_array* gap, int index, void* ptr) { + if (gap->hardlimit && (index > gap->hardlimit)) + return -1; + while (index >= gap->len) { int res = gap_extend(gap); if (res == -1) return -1; @@ -37,6 +42,8 @@ static inline void* __attribute__((unused)) gap_get(gap_array* gap, int index) * gap_get()'s job. This will do for now */ if (index >= gap->len) return NULL; + if (gap->hardlimit && (index > gap->hardlimit)) return NULL; + return gap->array[index]; } diff --git a/testgap/Makefile b/testgap/Makefile new file mode 100644 index 0000000..28c24f4 --- /dev/null +++ b/testgap/Makefile @@ -0,0 +1,7 @@ + +CFLAGS=-DHASH_TESTING -O2 -Wall +OBJ=../gap.o gtest.o + +gtest: $(OBJ) + $(CC) -o gtest $(OBJ) + diff --git a/testgap/gtest.c b/testgap/gtest.c new file mode 100644 index 0000000..18c76a3 --- /dev/null +++ b/testgap/gtest.c @@ -0,0 +1,102 @@ +/* Wee testing program from the gap code, this is very similar to the hash + * testing code. + * Instead of pointers, we use integers + * + * script language: + * a 5 12 # adds value 12 at index 5 + * d 512 42 # remove value 42, 512 is the length of the array + * h 16 0 # set hard limit to 16 (value is not used) + */ + + +#include +#include +#include +#include + + + +#include "../gap.h" + +static void gtest_next_line(FILE* f, char* action, int* index, void** value) +{ + + int res = 0; + while ((res != 3) && (res != EOF)) + res = fscanf(f, "%c %d %p\n", action, index, value); + if (res == EOF) exit(0); +} + +static void gap_dump(gap_array* gap, char* filename) +{ + int i; + FILE* out = fopen(filename, "w"); + + if (!out) { + perror(filename); + exit(1); + } + + fprintf(out, "\n", gap->len, gap->hardlimit); + for (i = 0; i < gap->len; i++) { + void* value = gap_get(gap, i); + fprintf(out, "[%d] = %p\n", i, value); + } + fprintf(out, "\n"); + fclose(out); +} + + +int main(int argc, char* argv[]) +{ + gap_array* gap = gap_init(0); + char action; + int line = 0, index; + void* value; + FILE* f; + + if (argc != 3) { + fprintf(stderr, "Usage: gtest