KJV updated to test.
This commit is contained in:
parent
3d334cd169
commit
afec7f716d
2
Makefile
2
Makefile
@ -36,7 +36,7 @@ default: $(projects)
|
|||||||
# success
|
# success
|
||||||
|
|
||||||
bin/text: build/text.o build/test_text.o
|
bin/text: build/text.o build/test_text.o
|
||||||
bin/kjv: build/text.o build/kjv.o
|
bin/kjv: build/text.o build/kjv.o build/test_kjv.o
|
||||||
|
|
||||||
bin/%:
|
bin/%:
|
||||||
# linking test $@
|
# linking test $@
|
||||||
|
30
src/kjv.h
30
src/kjv.h
@ -1,3 +1,4 @@
|
|||||||
|
#ifndef KJV_OMIT_BASE /* <!-- base */
|
||||||
#define BOOKS \
|
#define BOOKS \
|
||||||
X(Genesis),\
|
X(Genesis),\
|
||||||
X(Exodus),\
|
X(Exodus),\
|
||||||
@ -74,11 +75,34 @@ enum kjv_book { BOOKS };
|
|||||||
static const char *kjv_book_string[] = { BOOKS };
|
static const char *kjv_book_string[] = { BOOKS };
|
||||||
#undef X
|
#undef X
|
||||||
#undef BOOKS
|
#undef BOOKS
|
||||||
|
|
||||||
#include <stdint.h> /* C99 */
|
#include <stdint.h> /* C99 */
|
||||||
|
|
||||||
/* A set of verses. */
|
|
||||||
union kjvcite {
|
union kjvcite {
|
||||||
struct { unsigned verse : 12, chapter : 13, book : 7; }; /* C11 */
|
struct { unsigned verse : 12, chapter : 13, book : 7; }; /* C11 */
|
||||||
uint32_t u32;
|
uint32_t u32;
|
||||||
};
|
};
|
||||||
|
#else /* base --><!-- !base */
|
||||||
|
#undef KJV_OMIT_BASE
|
||||||
|
#endif /* !base --> */
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef KJV_OMIT_VERSES /* <!-- verses: For external inclusion. */
|
||||||
|
struct table_verse_bucket;
|
||||||
|
struct verse_table {
|
||||||
|
struct table_verse_bucket *buckets;
|
||||||
|
uint32_t log_capacity, size, top;
|
||||||
|
};
|
||||||
|
#else /* verses --><!-- !verses */
|
||||||
|
#undef KJV_OMIT_VERSES
|
||||||
|
#endif /* !verses --> */
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef KJV_OMIT_PROTO /* <!-- proto */
|
||||||
|
#include <stddef.h>
|
||||||
|
struct kjv { struct verse_table verses; size_t words; };
|
||||||
|
struct kjv kjv(void);
|
||||||
|
void kjv_(struct kjv *);
|
||||||
|
unsigned kjv_words(/*const*/ struct kjv *const kjv, const union kjvcite cite);
|
||||||
|
const char *kjv_entire_to_string(const struct kjv *const kjv);
|
||||||
|
#else /* proto --><!-- !proto */
|
||||||
|
#undef KJV_OMIT_PROTO
|
||||||
|
#endif /* !proto --> */
|
||||||
|
158
src/kjv.re_c.c
158
src/kjv.re_c.c
@ -8,13 +8,65 @@
|
|||||||
@std C11 */
|
@std C11 */
|
||||||
|
|
||||||
#include "../src/text.h"
|
#include "../src/text.h"
|
||||||
#include "../src/kjv.h"
|
#define KJV_OMIT_VERSES
|
||||||
#include <stdlib.h>
|
#define KJV_OMIT_PROTO
|
||||||
|
#include "../src/kjv.h" /* Just the base data. */
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <assert.h>
|
#include <stdlib.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <assert.h>
|
||||||
#include <dirent.h> /* opendir readdir closedir */
|
#include <dirent.h> /* opendir readdir closedir */
|
||||||
#include <unistd.h> /* chdir (POSIX) (because I'm lazy) */
|
#include <unistd.h> /* chdir (POSIX) (because I'm lazy) */
|
||||||
|
/* #include <cmph.h> No; overkill. */
|
||||||
|
|
||||||
|
|
||||||
|
/* Reversible hash map. */
|
||||||
|
/** <https://nullprogram.com/blog/2018/07/31/>
|
||||||
|
<https://github.com/skeeto/hash-prospector> on `x`. */
|
||||||
|
static uint32_t lowbias32(uint32_t x) {
|
||||||
|
x ^= x >> 16;
|
||||||
|
x *= 0x7feb352dU;
|
||||||
|
x ^= x >> 15;
|
||||||
|
x *= 0x846ca68bU;
|
||||||
|
x ^= x >> 16;
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
/* Inverts `x`. */
|
||||||
|
static uint32_t lowbias32_r(uint32_t x) {
|
||||||
|
x ^= x >> 16;
|
||||||
|
x *= 0x43021123U;
|
||||||
|
x ^= x >> 15 ^ x >> 30;
|
||||||
|
x *= 0x1d69e2a5U;
|
||||||
|
x ^= x >> 16;
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t kjv_hash(const union kjvcite x) { return lowbias32(x.u32); }
|
||||||
|
static union kjvcite kjv_unhash(const uint32_t x)
|
||||||
|
{ union kjvcite k; k.u32 = lowbias32_r(x); return k; }
|
||||||
|
static void kjv_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); }
|
||||||
|
#define TABLE_NAME kjv
|
||||||
|
#define TABLE_KEY union kjvcite
|
||||||
|
#define TABLE_UINT uint32_t
|
||||||
|
#define TABLE_INVERSE
|
||||||
|
#define TABLE_TO_STRING
|
||||||
|
#include "../src/table.h"
|
||||||
|
|
||||||
|
/* Derived information on verse word count. */
|
||||||
|
static uint32_t verse_hash(const union kjvcite x) { return kjv_hash(x); }
|
||||||
|
static union kjvcite verse_unhash(const uint32_t x) { return kjv_unhash(x); }
|
||||||
|
static void verse_to_string(const union kjvcite x, const unsigned count,
|
||||||
|
char (*const a)[12]) { (void)count; kjv_to_string(x, a); }
|
||||||
|
#define TABLE_NAME verse
|
||||||
|
#define TABLE_KEY union kjvcite
|
||||||
|
#define TABLE_UINT uint32_t
|
||||||
|
#define TABLE_VALUE unsigned /* Count words. */
|
||||||
|
#define TABLE_INVERSE
|
||||||
|
#define TABLE_DEFAULT 0
|
||||||
|
#define TABLE_TO_STRING
|
||||||
|
#include "../src/table.h"
|
||||||
|
|
||||||
|
|
||||||
/** Helper to parse unsigned; [`s`,`e`) => `n`. */
|
/** Helper to parse unsigned; [`s`,`e`) => `n`. */
|
||||||
@ -101,69 +153,24 @@ scan:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Reversible hash map. */
|
#define KJV_OMIT_BASE
|
||||||
#include <stdint.h> /* C99 */
|
#define KJV_OMIT_VERSES
|
||||||
/** <https://nullprogram.com/blog/2018/07/31/>
|
#include "../src/kjv.h" /* Just the kjv and prototypes. */
|
||||||
<https://github.com/skeeto/hash-prospector> on `x`. */
|
|
||||||
static uint32_t lowbias32(uint32_t x) {
|
void kjv_(struct kjv *const kjv) {
|
||||||
x ^= x >> 16;
|
if(!kjv) return;
|
||||||
x *= 0x7feb352dU;
|
verse_table_(&kjv->verses);
|
||||||
x ^= x >> 15;
|
|
||||||
x *= 0x846ca68bU;
|
|
||||||
x ^= x >> 16;
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
/* Inverts `x`. */
|
|
||||||
static uint32_t lowbias32_r(uint32_t x) {
|
|
||||||
x ^= x >> 16;
|
|
||||||
x *= 0x43021123U;
|
|
||||||
x ^= x >> 15 ^ x >> 30;
|
|
||||||
x *= 0x1d69e2a5U;
|
|
||||||
x ^= x >> 16;
|
|
||||||
return x;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t kjv_hash(const union kjvcite x) { return lowbias32(x.u32); }
|
struct kjv kjv(void) {
|
||||||
static union kjvcite kjv_unhash(const uint32_t x)
|
|
||||||
{ union kjvcite k; k.u32 = lowbias32_r(x); return k; }
|
|
||||||
static void kjv_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); }
|
|
||||||
#define TABLE_NAME kjv
|
|
||||||
#define TABLE_KEY union kjvcite
|
|
||||||
#define TABLE_UINT uint32_t
|
|
||||||
#define TABLE_INVERSE
|
|
||||||
#define TABLE_TO_STRING
|
|
||||||
#include "../src/table.h"
|
|
||||||
|
|
||||||
/* Derived information on verse word count. */
|
|
||||||
static uint32_t verse_hash(const union kjvcite x) { return kjv_hash(x); }
|
|
||||||
static union kjvcite verse_unhash(const uint32_t x) { return kjv_unhash(x); }
|
|
||||||
static void verse_to_string(const union kjvcite x, const unsigned count,
|
|
||||||
char (*const a)[12]) { (void)count; kjv_to_string(x, a); }
|
|
||||||
#define TABLE_NAME verse
|
|
||||||
#define TABLE_KEY union kjvcite
|
|
||||||
#define TABLE_UINT uint32_t
|
|
||||||
#define TABLE_VALUE unsigned /* Count words. */
|
|
||||||
#define TABLE_INVERSE
|
|
||||||
#define TABLE_DEFAULT 0
|
|
||||||
#define TABLE_TO_STRING
|
|
||||||
#include "../src/table.h"
|
|
||||||
|
|
||||||
|
|
||||||
int main(void) {
|
|
||||||
const char *const dir_kjv = "kjv";
|
const char *const dir_kjv = "kjv";
|
||||||
struct {
|
struct text backing;
|
||||||
struct text backing;
|
struct kjv kjv = { 0 };
|
||||||
struct verse_table verses;
|
|
||||||
size_t words;
|
|
||||||
} kjv = { 0 };
|
|
||||||
DIR *dir = 0;
|
DIR *dir = 0;
|
||||||
struct dirent *de = 0;
|
struct dirent *de = 0;
|
||||||
struct { size_t offset; int is; } build[KJV_BOOK_SIZE] = { 0 };
|
struct { size_t offset; int is; } build[KJV_BOOK_SIZE] = { 0 };
|
||||||
enum kjv_book b = 0;
|
enum kjv_book b = 0;
|
||||||
int success = EXIT_SUCCESS, attempted_closedir = 0;
|
int attempted_closedir = 0;
|
||||||
errno = 0;
|
|
||||||
|
|
||||||
/* For all files in directory KJV with <#>*.txt, read into backing. */
|
/* For all files in directory KJV with <#>*.txt, read into backing. */
|
||||||
if(chdir(dir_kjv) == -1 || !(dir = opendir("."))) goto catch;
|
if(chdir(dir_kjv) == -1 || !(dir = opendir("."))) goto catch;
|
||||||
@ -176,10 +183,10 @@ int main(void) {
|
|||||||
{ 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(&kjv.backing, de->d_name)))
|
if(!(unstable_book = 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 - kjv.backing.a.data);
|
build[b].offset = (size_t)(unstable_book - 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;
|
||||||
|
|
||||||
@ -188,7 +195,7 @@ int main(void) {
|
|||||||
struct lex x;
|
struct lex x;
|
||||||
if(!build[b].is) { fprintf(stderr, "Missing book [%u]%s.\n",
|
if(!build[b].is) { fprintf(stderr, "Missing book [%u]%s.\n",
|
||||||
b + 1, kjv_book_string[b]); errno = EDOM; goto catch; }
|
b + 1, kjv_book_string[b]); errno = EDOM; goto catch; }
|
||||||
x = lex(kjv.backing.a.data + build[b].offset);
|
x = lex(backing.a.data + build[b].offset);
|
||||||
while(lex_next_verse(&x)) {
|
while(lex_next_verse(&x)) {
|
||||||
const union kjvcite cite
|
const union kjvcite cite
|
||||||
= { .book = b, .chapter = x.chapter, .verse = x.verse };
|
= { .book = b, .chapter = x.chapter, .verse = x.verse };
|
||||||
@ -204,27 +211,20 @@ int main(void) {
|
|||||||
if(x.error) { fprintf(stderr, "[%u]%s on line %zu\n",
|
if(x.error) { fprintf(stderr, "[%u]%s on line %zu\n",
|
||||||
b + 1, kjv_book_string[b], x.line); goto catch; }
|
b + 1, kjv_book_string[b], x.line); goto catch; }
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("words: %s\n", verse_table_to_string(&kjv.verses));
|
|
||||||
printf("kjv: %zu total words\n", kjv.words);
|
|
||||||
{
|
|
||||||
union kjvcite c;
|
|
||||||
struct verse_table_iterator it = verse_table_begin(&kjv.verses);
|
|
||||||
unsigned *w;
|
|
||||||
while(verse_table_next(&it, &c, &w))
|
|
||||||
printf("%s %u:%u -> %u\n",
|
|
||||||
kjv_book_string[c.book], c.chapter, c.verse, *w);
|
|
||||||
c = (union kjvcite){ .book = Genesis, .chapter = 1, .verse = 1 };
|
|
||||||
printf("1:1:1 -> %u\n", verse_table_get(&kjv.verses, c));
|
|
||||||
}
|
|
||||||
goto finally;
|
goto finally;
|
||||||
catch:
|
catch:
|
||||||
success = EXIT_FAILURE;
|
|
||||||
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);
|
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);
|
||||||
finally:
|
finally:
|
||||||
verse_table_(&kjv.verses);
|
text_(&backing);
|
||||||
text_(&kjv.backing);
|
return kjv;
|
||||||
return success;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned kjv_words(/*const*/ struct kjv *const kjv, const union kjvcite cite) {
|
||||||
|
return kjv && verse_table_get(&kjv->verses, cite);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *kjv_entire_to_string(const struct kjv *const kjv)
|
||||||
|
{ return kjv ? verse_table_to_string(&kjv->verses) : ""; }
|
||||||
|
29
test/test_kjv.c
Normal file
29
test/test_kjv.c
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#include "../src/kjv.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <inttypes.h> /* C99 */
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
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.words, kjv_entire_to_string(&k));
|
||||||
|
kjv_(&k);
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user