From 745e7c3167a53b090a914a73163104f94ba8de89 Mon Sep 17 00:00:00 2001 From: Neil Date: Sat, 4 Feb 2023 19:06:43 -0800 Subject: [PATCH] failing test noentry; good --- src/journal.h | 2 +- src/pair.c | 7 +++++++ src/pair.h | 1 + src/source.h | 3 ++- src/source.re.c | 33 ++++++++++++++++++++++++--------- test/test_source.c | 21 +++++++++++++++++++++ 6 files changed, 56 insertions(+), 11 deletions(-) diff --git a/src/journal.h b/src/journal.h index c29ad88..c1a89c4 100644 --- a/src/journal.h +++ b/src/journal.h @@ -10,7 +10,7 @@ union date32 { }; void date32_to_string(const union date32 d, char (*const a)[12]); union line64 { - struct { union date32 date; uint32_t line; }; /* C11, endian? */ + struct { uint32_t line; union date32 date; }; /* C11, little-endian */ uint64_t u64; /* C99 optional */ }; #endif /* base --> */ diff --git a/src/pair.c b/src/pair.c index b1df775..13df163 100644 --- a/src/pair.c +++ b/src/pair.c @@ -32,6 +32,13 @@ int pair_is_equal(struct pair x, struct pair y) { return 1; } +int pair_is_string(struct pair x, const char *y) { + assert(x.a <= x.b); + if(!x.a) return !y; + while(x.a < x.b) { if(*x.a != *y || !*y) return 0; x.a++, y++; } + return !*y; +} + /** djb2 */ uint32_t pair_djb2(struct pair p) { uint32_t hash = 5381, c; diff --git a/src/pair.h b/src/pair.h index f010a65..48d9232 100644 --- a/src/pair.h +++ b/src/pair.h @@ -4,4 +4,5 @@ struct pair { const char *a, *b; }; struct pair pair(const char *const a, const char *const b); int pair_to_natural(const char *, const char *, uint32_t *); int pair_is_equal(struct pair, struct pair); +int pair_is_string(struct pair, const char *); uint32_t pair_djb2(const struct pair p); diff --git a/src/source.h b/src/source.h index df049bb..0929880 100644 --- a/src/source.h +++ b/src/source.h @@ -40,7 +40,8 @@ struct source *sources_add(struct sources *, const union line64); struct sources sources(struct journal *); void sources_(struct sources *); const char *sources_to_string(const struct sources *); -/* And some query... */ +const struct source *source_lookup(const struct sources *s, + const union line64 range); #endif /* proto --> */ #ifdef BASE diff --git a/src/source.re.c b/src/source.re.c index 1d5dd92..5bc17d0 100644 --- a/src/source.re.c +++ b/src/source.re.c @@ -50,6 +50,7 @@ static int source_compare(const union line64 a, const union line64 b) #define TREE_VALUE size_t /* Index into source list. */ #define TREE_COMPARE #define TREE_TO_STRING +#define TREE_DEFAULT 0 #include "../src/tree.h" @@ -93,14 +94,18 @@ static int scan(union date32 date, const char *const buffer, * { why = "default source unrecognized"; goto catch; } @s0 keyword @s1 / "\n" => skip { also_add_to_tree: { - struct pair p = pair(s0, s1); - size_t i; - //const union line64 key = { ... }; - if(!(i = sourcemap_table_get(&s->map, p))) + const struct pair keyword = pair(s0, s1); + const union line64 key = { { (uint32_t)line, date } }; + size_t i, *pi; + if(line > UINT32_MAX) + { errno = ERANGE; why = "too many lines of text"; goto catch; } + if(!(i = sourcemap_table_get(&s->map, keyword))) { why = "keyword not introduced"; goto catch; } - /*switch(source_tree_assign(&s->source, )) { - ... - }*/ + switch(source_tree_try(&s->dates, key, &pi)) { + case TREE_PRESENT: why = "duplicate key"; /* _Sic_. */ + case TREE_ERROR: goto catch; + case TREE_ABSENT: *pi = i; break; + } date32_to_string(date, &datestr); printf("%s: <%.*s>\n", datestr, (int)(s1 - s0), s0); continue; @@ -113,9 +118,8 @@ static int scan(union date32 date, const char *const buffer, switch(sourcemap_table_assign(&s->map, keyword, &idx)) { case TABLE_PRESENT: errno = EDOM; why = "new keyword already used"; case TABLE_ERROR: goto catch; /* /\ _Sic_. */ - case TABLE_ABSENT: break; /* Good. */ + case TABLE_ABSENT: *idx = 0; break; /* Good. */ } - *idx = 0; /* Clean. */ if(!(source = sourcelist_array_new(&s->list))) goto catch; *idx = (size_t)(source - s->list.data); source->name.a = s0, source->name.b = s1; @@ -165,3 +169,14 @@ catch: finally: return s; } + +/** Lookup the last source in `range` in sources `s`. They are invalidated on + adding a source, (probably fine.) */ +const struct source *source_lookup(const struct sources *const s, + const union line64 range) { + struct source *looked; + assert(s); + looked = s->list.data + source_tree_left(&s->dates, range); + /* verify ... */ + return looked; +} diff --git a/test/test_source.c b/test/test_source.c index 9c40ed3..fe0528a 100644 --- a/test/test_source.c +++ b/test/test_source.c @@ -11,6 +11,27 @@ int main(void) { struct journal j = journal(); struct sources s = sources(&j); if(errno) goto catch; + + const union line64 agenda = {{4,{{20,04,1996}}}}, + before = {{1,{{1,1,1900}}}}, + noentry = {{3,{{1,6,1995}}}}; + const struct source *source; + + source = source_lookup(&s, agenda); + printf("agenda: <%.*s>\n", + (int)(source->name.b - source->name.a), source->name.a); + assert(pair_is_string(source->name, "1995agenda")); + + source = source_lookup(&s, before); + printf("before: <%.*s>\n", + (int)(source->name.b - source->name.a), source->name.a); + assert(pair_is_string(source->name, 0)); + + source = source_lookup(&s, noentry); + printf("noentry: <%.*s>\n", + (int)(source->name.b - source->name.a), source->name.a); + assert(pair_is_string(source->name, 0)); + goto finally; catch: success = EXIT_FAILURE, perror("source");