diff --git a/libc3/buf_parse.c b/libc3/buf_parse.c
index bbc258d..a08c119 100644
--- a/libc3/buf_parse.c
+++ b/libc3/buf_parse.c
@@ -405,6 +405,7 @@ sw buf_parse_fact (s_buf *buf, s_fact *dest)
result += r;
if ((r = buf_read_1(buf, "}")) < 0)
goto restore;
+ result += r;
dest->subject = subject;
dest->predicate = predicate;
dest->object = object;
diff --git a/libc3/facts.c b/libc3/facts.c
index bef6d35..1c8293d 100644
--- a/libc3/facts.c
+++ b/libc3/facts.c
@@ -30,6 +30,9 @@
#include "skiplist__fact.h"
#include "tag.h"
+sw facts_open_file_create (s_facts *facts, const s8 *path);
+sw facts_open_log (s_facts *facts, s_buf *buf);
+
s_fact * facts_add_fact (s_facts *facts, const s_fact *fact)
{
s_fact tmp;
@@ -196,6 +199,9 @@ sw facts_load (s_facts *facts, s_buf *buf)
{
u64 count;
s_fact fact;
+ t_hash hash;
+ u64 hash_u64;
+ u64 hash_u64_buf;
u64 i;
sw r;
sw result = 0;
@@ -209,21 +215,49 @@ sw facts_load (s_facts *facts, s_buf *buf)
result += r;
if ((r = buf_parse_u64_hex(buf, &count)) < 0)
return r;
- if ((r = buf_write_1(buf, "}\n")) < 0)
+ result += r;
+ if ((r = buf_read_1(buf, "}\n")) < 0)
return r;
result += r;
+ hash_init(&hash);
for (i = 0; i < count; i++) {
if ((r = buf_parse_fact(buf, &fact)) <= 0)
- break;
+ goto ko_fact;
result += r;
+ hash_update_fact(&hash, &fact);
facts_add_fact(facts, &fact);
- buf_read_1(buf, "\n");
+ if ((r = buf_read_1(buf, "\n")) <= 0) {
+ r = -1;
+ goto ko_fact;
+ }
+ result += r;
}
- /*
- buf_write_1(buf, "%{hash: 0x");
- buf_inspect_u64_hex(buf, hash_u64);
- */
+ hash_u64 = hash_to_u64(&hash);
+ if ((r = buf_read_1(buf, "%{hash: 0x")) <= 0)
+ goto ko_hash;
+ result += r;
+ if ((r = buf_parse_u64_hex(buf, &hash_u64_buf)) <= 0)
+ goto ko_hash;
+ result += r;
+ if ((r = buf_read_1(buf, "}\n")) <= 0)
+ goto ko_hash;
+ result += r;
+ i++;
+ if (hash_u64_buf != hash_u64)
+ goto ko_hash;
return result;
+ ko_fact:
+ if (r)
+ warnx("facts_load: invalid fact line %llu", i + 3);
+ else
+ warnx("facts_load: missing fact line %llu", i + 3);
+ return -1;
+ ko_hash:
+ if (r)
+ warnx("facts_load: invalid hash line %llu", i + 3);
+ else
+ warnx("facts_load: missing hash line %llu", i + 3);
+ return -1;
}
sw facts_load_file (s_facts *facts, const s8 *path)
@@ -302,37 +336,17 @@ sw facts_open_file (s_facts *facts, const s8 *path)
s_buf in;
s_buf *out;
sw r;
+ sw result = 0;
BUF_INIT_ALLOCA(&in, BUF_SIZE);
if (! (fp = fopen(path, "rb"))) {
- if (errno == ENOENT) {
- if (! (fp = fopen(path, "wb"))) {
- warn("fopen: %s", path);
- return -1;
- }
- if (facts_count(facts)) {
- /* TODO: clear facts
- facts_close(facts);
- facts_remove_all(facts);
- */
- warnx("facts_open_file: not supported");
- return -1;
- }
- out = buf_new_alloc(BUF_SIZE);
- buf_file_open_w(out, fp);
- if ((r = facts_save_header(out)) < 0)
- return r;
- if ((r = facts_dump(facts, out)) < 0)
- return r;
- buf_flush(out);
- facts->log = out;
- return r;
- }
- fp = fopen(path, "wb");
+ if (errno == ENOENT)
+ return facts_open_file_create(facts, path);
return -1;
}
buf_file_open_r(&in, fp);
if ((r = facts_open_buf(facts, &in)) < 0)
return r;
+ result += r;
fclose(fp);
if (! (fp = fopen(path, "wb"))) {
warn("fopen: %s", path);
@@ -341,7 +355,38 @@ sw facts_open_file (s_facts *facts, const s8 *path)
out = buf_new_alloc(BUF_SIZE);
buf_file_open_w(out, fp);
facts->log = out;
- return r;
+ return result;
+}
+
+sw facts_open_file_create (s_facts *facts, const s8 *path)
+{
+ FILE *fp;
+ s_buf *out;
+ sw r;
+ sw result = 0;
+ if (! (fp = fopen(path, "wb"))) {
+ warn("fopen: %s", path);
+ return -1;
+ }
+ if (facts_count(facts)) {
+ /* TODO: clear facts
+ facts_close(facts);
+ facts_remove_all(facts);
+ */
+ warnx("facts_open_file: not supported");
+ return -1;
+ }
+ out = buf_new_alloc(BUF_SIZE);
+ buf_file_open_w(out, fp);
+ if ((r = facts_save_header(out)) < 0)
+ return r;
+ result += r;
+ if ((r = facts_dump(facts, out)) < 0)
+ return r;
+ result += r;
+ buf_flush(out);
+ facts->log = out;
+ return result;
}
sw facts_open_log (s_facts *facts, s_buf *buf)
diff --git a/libc3/facts.h b/libc3/facts.h
index 2a238f3..636bd1e 100644
--- a/libc3/facts.h
+++ b/libc3/facts.h
@@ -37,7 +37,6 @@ void facts_close (s_facts *facts);
sw facts_load (s_facts *facts, s_buf *buf);
sw facts_load_file (s_facts *facts, const s8 *path);
sw facts_open_file (s_facts *facts, const s8 *path);
-sw facts_open_log (s_facts *facts, s_buf *buf);
s_tag * facts_ref_tag (s_facts *facts, const s_tag *tag);
e_bool facts_remove_fact (s_facts *facts, const s_fact *fact);
sw facts_save_file (s_facts *facts, const s8 *path);
diff --git a/test/facts_test.c b/test/facts_test.c
index 051016b..74793f3 100644
--- a/test/facts_test.c
+++ b/test/facts_test.c
@@ -41,6 +41,7 @@ void facts_test ()
facts_test_log_add();
facts_test_log_remove();
facts_test_dump_file();
+ facts_test_load();
facts_test_save();
}
@@ -219,12 +220,47 @@ void facts_test_init_clean ()
void facts_test_load ()
{
+ uw i = 0;
+ s8 *p[24] = {
+ "\"a\"",
+ ":a",
+ "A",
+ "a",
+ "[]",
+ "[[], []]",
+ "{:a, :b}",
+ "{{:a, :b}, {:c, :d}}",
+ "{a, b}",
+ "{{a, b}, {c, d}}",
+ "0",
+ "1",
+ "10",
+ "0x100",
+ "0x10000",
+ "0x100000000",
+ "0x10000000000000000",
+ "-1",
+ "-10",
+ "-0x100",
+ "-0x10000",
+ "-0x100000000",
+ "-0x10000000000000000",
+ NULL
+ };
+ s_fact fact;
s_facts facts;
facts_init(&facts);
TEST_EQ(facts_load_file(&facts,
"facts_test_dump_file.facts.expected"),
- 0);
+ 742);
TEST_EQ(facts_count(&facts), 23);
+ while (p[i]) {
+ fact_test_init_1(&fact, p[i]);
+ TEST_ASSERT(facts_find_fact(&facts, &fact));
+ fact_test_clean_1(&fact);
+ i++;
+ }
+ facts_clean(&facts);
}
void facts_test_log_add ()