From d091272cea97af56e3a3f75bf05055d8318248bb Mon Sep 17 00:00:00 2001 From: Florian Stinglmayr Date: Tue, 29 Apr 2025 12:37:15 +0200 Subject: [PATCH] more code --- lib/include/edapi/journal/entry.h | 6 ++ lib/include/edapi/journal/file.h | 4 ++ lib/src/journal/entry.c | 67 ++++++++++++++++++++- lib/src/journal/file.c | 31 ++++++++++ lib/tests/Journal.2024-04-18T061507.01.log | 8 +-- lib/tests/test-journal-file.c | 70 ++++++++++++++++++++++ 6 files changed, 179 insertions(+), 7 deletions(-) diff --git a/lib/include/edapi/journal/entry.h b/lib/include/edapi/journal/entry.h index ba2a391..20be44a 100644 --- a/lib/include/edapi/journal/entry.h +++ b/lib/include/edapi/journal/entry.h @@ -48,6 +48,12 @@ gchar const *ed_journal_entry_get_string(EDJournalEntry *self, gchar const *ed_journal_entry_get_event(EDJournalEntry *self); +GDateTime *ed_journal_entry_get_timestamp(EDJournalEntry *self); + +gboolean ed_journal_entry_is_in_range(EDJournalEntry *self, + GDateTime *start, + GDateTime *end); + /** * Returns true if the journal entry is of the given event. */ diff --git a/lib/include/edapi/journal/file.h b/lib/include/edapi/journal/file.h index cf0fb86..1a63ad0 100644 --- a/lib/include/edapi/journal/file.h +++ b/lib/include/edapi/journal/file.h @@ -50,6 +50,10 @@ gchar const *ed_journal_file_get_gameversion(EDJournalFile *self); EDJournalEntry *ed_journal_file_get_first(EDJournalFile *self); EDJournalEntry *ed_journal_file_get_last(EDJournalFile *self); +gboolean ed_journal_file_has_entries_in_range(EDJournalFile *self, + GDateTime *start, + GDateTime *end); + gint ed_journal_file_compare(EDJournalFile *lhs, EDJournalFile *rhs); G_END_DECLS diff --git a/lib/src/journal/entry.c b/lib/src/journal/entry.c index d5ff3bc..1bac6d2 100644 --- a/lib/src/journal/entry.c +++ b/lib/src/journal/entry.c @@ -6,6 +6,7 @@ typedef struct { json_t *entry; + GDateTime *timestamp; } EDJournalEntryPrivate; G_DEFINE_QUARK("ed-json-error", ed_json_error); @@ -24,7 +25,12 @@ static void ed_journal_entry_finalize(GObject *obj) EDJournalEntryPrivate *p = ed_journal_entry_get_instance_private(self); json_decref(p->entry); - p = NULL; + p->entry = NULL; + + if (p->timestamp != NULL) { + g_date_time_unref(p->timestamp); + p->timestamp = NULL; + } G_OBJECT_CLASS(ed_journal_entry_parent_class)->finalize(obj); } @@ -69,6 +75,7 @@ EDErrorCode ed_journal_entry_parse(EDJournalEntry *self, EDJournalEntryPrivate *p = ed_journal_entry_get_instance_private(self); EDErrorCode ret = ed_error_invalid; json_error_t e; + char const *timestamp = NULL; json_decref(p->entry); p->entry = NULL; @@ -88,10 +95,43 @@ EDErrorCode ed_journal_entry_parse(EDJournalEntry *self, e.text ); ret = ed_error_invalid_json; - } else { - ret = ed_error_success; + goto done; } + timestamp = ed_journal_entry_get_string(self, "timestamp"); + if (S_EMPTY(timestamp)) { + json_decref(p->entry); + p->entry = NULL; + + g_set_error( + error, + ed_json_error_quark(), + ed_error_invalid_json, + "entry has no timestamp" + ); + ret = ed_error_invalid_json; + goto done; + } + + p->timestamp = g_date_time_new_from_iso8601(timestamp, NULL); + if (p->timestamp == NULL) { + json_decref(p->entry); + p->entry = NULL; + + g_set_error( + error, + ed_json_error_quark(), + ed_error_invalid_json, + "entry has an invalid timestamp" + ); + ret = ed_error_invalid_json; + goto done; + } + + ret = ed_error_success; + +done: + return ret; } @@ -128,3 +168,24 @@ gboolean ed_journal_entry_is(EDJournalEntry *self, gchar const *event) return (g_ascii_strcasecmp(ev, event) == 0); } + +GDateTime *ed_journal_entry_get_timestamp(EDJournalEntry *self) +{ + EDJournalEntryPrivate *p = ed_journal_entry_get_instance_private(self); + return p->timestamp; +} + +gboolean ed_journal_entry_is_in_range(EDJournalEntry *self, + GDateTime *start, + GDateTime *end) +{ + GDateTime *timestamp = ed_journal_entry_get_timestamp(self); + return_if_true(timestamp == NULL, FALSE); + + if (g_date_time_compare(start, timestamp) <= 0 && + g_date_time_compare(timestamp, end) <= 0) { + return TRUE; + } + + return FALSE; +} diff --git a/lib/src/journal/file.c b/lib/src/journal/file.c index 88f6c8b..2350df3 100644 --- a/lib/src/journal/file.c +++ b/lib/src/journal/file.c @@ -601,3 +601,34 @@ gint ed_journal_file_compare(EDJournalFile *lhs, EDJournalFile *rhs) return g_date_time_compare(ldate, rdate); } + +gboolean ed_journal_file_has_entries_in_range(EDJournalFile *self, + GDateTime *start, + GDateTime *end) +{ + return_if_true(self == NULL, FALSE); + + EDJournalFilePrivate *p = ed_journal_file_get_instance_private(self); + + return_if_true(p->first == NULL || p->last == NULL, FALSE); + + GDateTime *first = ed_journal_entry_get_timestamp(p->first); + GDateTime *last = ed_journal_entry_get_timestamp(p->last); + + if (g_date_time_compare(start, first) <= 0 && + g_date_time_compare(last, end) <= 0) { + return TRUE; + } + + if (g_date_time_compare(first, start) <= 0 && + g_date_time_compare(start, last) <= 0) { + return TRUE; + } + + if (g_date_time_compare(first, end) <= 0 && + g_date_time_compare(end, last) <= 0) { + return TRUE; + } + + return FALSE; +} diff --git a/lib/tests/Journal.2024-04-18T061507.01.log b/lib/tests/Journal.2024-04-18T061507.01.log index b6592d6..a636a6e 100644 --- a/lib/tests/Journal.2024-04-18T061507.01.log +++ b/lib/tests/Journal.2024-04-18T061507.01.log @@ -1,4 +1,4 @@ -{ "timestamp":"2023-04-18T04:14:56Z", "event":"Fileheader", "part":1, "language":"English/UK", "Odyssey":true, "gameversion":"4.0.0.1477", "build":"r291050/r0 " } -{ "timestamp":"2023-04-18T04:15:39Z", "event":"Commander", "FID":"F123456", "Name":"DeiMuata" } -{ "timestamp":"2023-04-18T05:15:39Z", "event":"Something" } -{ "timestamp":"2023-04-18T06:15:39Z", "event":"Shutdown" } +{ "timestamp":"2024-04-18T04:14:56Z", "event":"Fileheader", "part":1, "language":"English/UK", "Odyssey":true, "gameversion":"4.0.0.1477", "build":"r291050/r0 " } +{ "timestamp":"2024-04-18T04:15:39Z", "event":"Commander", "FID":"F123456", "Name":"DeiMuata" } +{ "timestamp":"2024-04-18T05:15:39Z", "event":"Something" } +{ "timestamp":"2024-04-18T06:15:39Z", "event":"Shutdown" } diff --git a/lib/tests/test-journal-file.c b/lib/tests/test-journal-file.c index a77963d..46a46e6 100644 --- a/lib/tests/test-journal-file.c +++ b/lib/tests/test-journal-file.c @@ -174,6 +174,75 @@ static void test_first_last(void **state) g_clear_object(&file); } +static void test_in_range(void **state) +{ + char const *filename = "Journal.2024-04-18T061507.01.log"; + + EDJournalFile *file = NULL; + EDErrorCode ret = 0; + GError *error = NULL; + + GDateTime *start = NULL; + GDateTime *end = NULL; + + gboolean b; + + file = ed_journal_file_new(); + assert_non_null(file); + + ret = ed_journal_file_open(file, filename, &error); + + assert_null(error); + assert_int_equal(ret, ed_error_success); + + /* start in range + */ + start = g_date_time_new_from_iso8601("2024-04-18T04:15:39Z", NULL); + end = g_date_time_new_from_iso8601("2024-04-19T04:15:39Z", NULL); + b = ed_journal_file_has_entries_in_range(file, start, end); + assert_true(b); + g_date_time_unref(start); + g_date_time_unref(end); + + /* end in range + */ + start = g_date_time_new_from_iso8601("2024-04-17T04:15:39Z", NULL); + end = g_date_time_new_from_iso8601("2024-04-18T05:15:39Z", NULL); + b = ed_journal_file_has_entries_in_range(file, start, end); + assert_true(b); + g_date_time_unref(start); + g_date_time_unref(end); + + /* both outside + */ + start = g_date_time_new_from_iso8601("2023-04-17T04:15:39Z", NULL); + end = g_date_time_new_from_iso8601("2025-04-18T05:15:39Z", NULL); + b = ed_journal_file_has_entries_in_range(file, start, end); + assert_true(b); + g_date_time_unref(start); + g_date_time_unref(end); + + /* too early + */ + start = g_date_time_new_from_iso8601("2023-04-17T04:15:39Z", NULL); + end = g_date_time_new_from_iso8601("2023-04-18T05:15:39Z", NULL); + b = ed_journal_file_has_entries_in_range(file, start, end); + assert_false(b); + g_date_time_unref(start); + g_date_time_unref(end); + + /* too late + */ + start = g_date_time_new_from_iso8601("2025-04-17T04:15:39Z", NULL); + end = g_date_time_new_from_iso8601("2025-04-18T05:15:39Z", NULL); + b = ed_journal_file_has_entries_in_range(file, start, end); + assert_false(b); + g_date_time_unref(start); + g_date_time_unref(end); + + g_clear_object(&file); +} + int main(int ac, char **av) { static const struct CMUnitTest tests[] = { @@ -184,6 +253,7 @@ int main(int ac, char **av) cmocka_unit_test(test_old_datetime), cmocka_unit_test(test_valid_peek), cmocka_unit_test(test_first_last), + cmocka_unit_test(test_in_range), }; return cmocka_run_group_tests(tests, NULL, NULL);