Fixed the off-by-one.

This commit is contained in:
Neil 2022-12-27 13:48:45 -08:00
parent a89873d4b0
commit a795b70859
3 changed files with 21 additions and 24 deletions

View File

@ -110,6 +110,7 @@ struct kjv {
}; };
struct kjv kjv(void); struct kjv kjv(void);
void kjv_(struct kjv *); void kjv_(struct kjv *);
int kjv_is_valid(const struct kjv *const kjv);
int kjv_add(struct kjv *const kjv, const union kjvcite cite); int kjv_add(struct kjv *const kjv, const union kjvcite cite);
const char *kjv_to_string(const struct kjv *const kjv); const char *kjv_to_string(const struct kjv *const kjv);
const char *kjv_set_to_string(const struct kjv *const kjv); const char *kjv_set_to_string(const struct kjv *const kjv);

View File

@ -46,7 +46,7 @@ static union kjvcite kjvset_unhash(const uint32_t x)
{ union kjvcite k; k.u32 = lowbias32_r(x); return k; } { union kjvcite k; k.u32 = lowbias32_r(x); return k; }
static void kjvset_to_string(const union kjvcite x, char (*const a)[12]) static void kjvset_to_string(const union kjvcite x, char (*const a)[12])
{ sprintf(*a, "%.4s%u:%u", kjv_book_string[x.book], { 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_NAME kjvset
#define TABLE_KEY union kjvcite #define TABLE_KEY union kjvcite
#define TABLE_UINT uint32_t #define TABLE_UINT uint32_t
@ -157,12 +157,14 @@ scan:
#define KJV_OMIT_VERSES #define KJV_OMIT_VERSES
#include "../src/kjv.h" /* Just the kjv and prototypes. */ #include "../src/kjv.h" /* Just the kjv and prototypes. */
/** Frees `kjv`. */
void kjv_(struct kjv *const kjv) { void kjv_(struct kjv *const kjv) {
if(!kjv) return; if(!kjv) return;
kjvset_table_(&kjv->set); kjvset_table_(&kjv->set);
verse_table_(&kjv->verses); verse_table_(&kjv->verses);
} }
/** Loads 66 files from the "kjv/" directory. */
struct kjv kjv(void) { struct kjv kjv(void) {
const char *const dir_kjv = "kjv"; const char *const dir_kjv = "kjv";
struct text backing; struct text backing;
@ -177,17 +179,17 @@ struct kjv kjv(void) {
if(chdir(dir_kjv) == -1 || !(dir = opendir("."))) goto catch; if(chdir(dir_kjv) == -1 || !(dir = opendir("."))) goto catch;
while((de = readdir(dir))) { while((de = readdir(dir))) {
unsigned ordinal; unsigned ordinal;
char *unstable_book; char *unstable_backing;
if(!looks_like_book_fn(de->d_name, &ordinal)) continue; if(!looks_like_book_fn(de->d_name, &ordinal)) continue;
/*fprintf(stderr, "<%s> ordinal: %u\n", de->d_name, ordinal);*/ /*fprintf(stderr, "<%s> ordinal: %u\n", de->d_name, ordinal);*/
if(ordinal < 1 || ordinal > KJV_BOOK_SIZE) if(ordinal < 1 || ordinal > KJV_BOOK_SIZE)
{ errno = ERANGE; goto catch; } /* Not in range. */ { errno = ERANGE; goto catch; } /* Not in range. */
if(build[b = ordinal - 1].is) /* Convert to zero-based. */ if(build[b = ordinal - 1].is) /* Convert to zero-based. */
{ errno = EDOM; goto catch; } /* Is duplicate. */ { 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; goto catch;
build[b].is = 1; 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; if(attempted_closedir = 1, closedir(dir) == -1) goto catch; dir = 0;
@ -215,7 +217,6 @@ struct kjv kjv(void) {
goto finally; goto finally;
catch: catch:
if(de) fprintf(stderr, "While reading %s.\n", de->d_name); 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); if(dir && !attempted_closedir && closedir(dir) == -1) perror(dir_kjv);
kjv_(&kjv); kjv_(&kjv);
finally: finally:
@ -223,6 +224,11 @@ finally:
return kjv; 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) { int kjv_add(struct kjv *const kjv, const union kjvcite cite) {
if(!kjv) return 0; if(!kjv) return 0;
switch(kjvset_table_try(&kjv->set, cite)) { switch(kjvset_table_try(&kjv->set, cite)) {

View File

@ -4,28 +4,18 @@
#include <stdlib.h> #include <stdlib.h>
int main(void) { int main(void) {
int success = EXIT_SUCCESS;
struct kjv k = kjv(); 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)); 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 }); 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)); 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); kjv_(&k);
return EXIT_SUCCESS; return success;
} }