From a795b70859afc40187610b692bb5b01009136edf Mon Sep 17 00:00:00 2001 From: Neil Date: Tue, 27 Dec 2022 13:48:45 -0800 Subject: [PATCH] Fixed the off-by-one. --- src/kjv.h | 1 + src/kjv.re_c.c | 16 +++++++++++----- test/test_kjv.c | 28 +++++++++------------------- 3 files changed, 21 insertions(+), 24 deletions(-) diff --git a/src/kjv.h b/src/kjv.h index a6cc4e7..399629c 100644 --- a/src/kjv.h +++ b/src/kjv.h @@ -110,6 +110,7 @@ struct kjv { }; struct kjv kjv(void); void kjv_(struct kjv *); +int kjv_is_valid(const struct kjv *const kjv); int kjv_add(struct kjv *const kjv, const union kjvcite cite); const char *kjv_to_string(const struct kjv *const kjv); const char *kjv_set_to_string(const struct kjv *const kjv); diff --git a/src/kjv.re_c.c b/src/kjv.re_c.c index ee53e3e..ac77711 100644 --- a/src/kjv.re_c.c +++ b/src/kjv.re_c.c @@ -46,7 +46,7 @@ static union kjvcite kjvset_unhash(const uint32_t x) { union kjvcite k; k.u32 = lowbias32_r(x); return k; } static void kjvset_to_string(const union kjvcite x, char (*const a)[12]) { sprintf(*a, "%.4s%u:%u", kjv_book_string[x.book], - (x.chapter + 1) % 1000, (x.verse + 1) % 1000); } + x.chapter % 1000, x.verse % 1000); } #define TABLE_NAME kjvset #define TABLE_KEY union kjvcite #define TABLE_UINT uint32_t @@ -157,12 +157,14 @@ scan: #define KJV_OMIT_VERSES #include "../src/kjv.h" /* Just the kjv and prototypes. */ +/** Frees `kjv`. */ void kjv_(struct kjv *const kjv) { if(!kjv) return; kjvset_table_(&kjv->set); verse_table_(&kjv->verses); } +/** Loads 66 files from the "kjv/" directory. */ struct kjv kjv(void) { const char *const dir_kjv = "kjv"; struct text backing; @@ -177,17 +179,17 @@ struct kjv kjv(void) { if(chdir(dir_kjv) == -1 || !(dir = opendir("."))) goto catch; while((de = readdir(dir))) { unsigned ordinal; - char *unstable_book; + char *unstable_backing; if(!looks_like_book_fn(de->d_name, &ordinal)) continue; /*fprintf(stderr, "<%s> ordinal: %u\n", de->d_name, ordinal);*/ if(ordinal < 1 || ordinal > KJV_BOOK_SIZE) { errno = ERANGE; goto catch; } /* Not in range. */ if(build[b = ordinal - 1].is) /* Convert to zero-based. */ { errno = EDOM; goto catch; } /* Is duplicate. */ - if(!(unstable_book = text_append_file(&backing, de->d_name))) + if(!(unstable_backing = text_append_file(&backing, de->d_name))) goto catch; build[b].is = 1; - build[b].offset = (size_t)(unstable_book - backing.a.data); + build[b].offset = (size_t)(unstable_backing - backing.a.data); } if(attempted_closedir = 1, closedir(dir) == -1) goto catch; dir = 0; @@ -215,7 +217,6 @@ struct kjv kjv(void) { goto finally; catch: if(de) fprintf(stderr, "While reading %s.\n", de->d_name); - perror(de ? de->d_name : dir_kjv); if(dir && !attempted_closedir && closedir(dir) == -1) perror(dir_kjv); kjv_(&kjv); finally: @@ -223,6 +224,11 @@ finally: return kjv; } +/** Has loaded properly? Otherwise, probably `errno` is set. */ +int kjv_is_valid(const struct kjv *const kjv) + { return kjv && kjv->verses.buckets; } + +/** Adds `cite` to `kjv` if not present. @return Is the kjv still valid. */ int kjv_add(struct kjv *const kjv, const union kjvcite cite) { if(!kjv) return 0; switch(kjvset_table_try(&kjv->set, cite)) { diff --git a/test/test_kjv.c b/test/test_kjv.c index 9ff28ea..0ff16a0 100644 --- a/test/test_kjv.c +++ b/test/test_kjv.c @@ -4,28 +4,18 @@ #include int main(void) { + int success = EXIT_SUCCESS; struct kjv k = kjv(); - union kjvcite c; - /*struct verse_table_iterator it = verse_table_begin(&kjv.verses);*/ - unsigned *verses; - /* printf("%%{\n" - "#include \"../src/kjv.h\"\n" - "%%}\n" - "struct kjvverse { uint32_t name; unsigned words; };\n" - "%%%%\n"); I don't even think this is possible 1.44 bits/key. */ - - /*while(verse_table_next(&it, &c, &verses)) - printf("%" PRIu32 ", %u\n", c.u32, *verses);*/ - /*printf("%s %u:%u -> %u\n", - kjv_book_string[c.book], c.chapter, c.verse, *verses);*/ - /*c = (union kjvcite){ .book = Genesis, .chapter = 1, .verse = 1 }; - printf("1:1:1 -> %u\n", verse_table_get(&kjv.verses, c));*/ - /*c = (union kjvcite){ .book = Genesis, .chapter = 1, .verse = 1 }; - printf("1:1:1 -> %u\n", verse_table_get(&kjv.verses, c));*/ - fprintf(stderr, "%zu total words, %s.\n", k.total_words, kjv_to_string(&k)); + if(!kjv_is_valid(&k)) goto catch; + kjv_add(&k, (union kjvcite){ .book = Genesis, .chapter = 1, .verse = 1 }); + kjv_add(&k, (union kjvcite){ .book = Genesis, .chapter = 1, .verse = 2 }); kjv_add(&k, (union kjvcite){ .book = Genesis, .chapter = 1, .verse = 1 }); fprintf(stderr, "%zu of which: %s.\n", k.set_words, kjv_set_to_string(&k)); + goto finally; +catch: + success = EXIT_FAILURE, perror("kjv"); +finally: kjv_(&k); - return EXIT_SUCCESS; + return success; }