more code
This commit is contained in:
parent
32d2484637
commit
cf38de5355
@ -14,12 +14,20 @@ G_DECLARE_FINAL_TYPE(EDJournalFile, ed_journal_file, ED, JOURNALFILE, GObject);
|
|||||||
|
|
||||||
EDJournalFile *ed_journal_file_new(void);
|
EDJournalFile *ed_journal_file_new(void);
|
||||||
|
|
||||||
|
EDErrorCode ed_journal_file_parse_filename(
|
||||||
|
char const *basename,
|
||||||
|
gchar **date,
|
||||||
|
gint *part
|
||||||
|
);
|
||||||
|
|
||||||
EDErrorCode ed_journal_file_parse(EDJournalFile *file, char const *filename);
|
EDErrorCode ed_journal_file_parse(EDJournalFile *file, char const *filename);
|
||||||
|
|
||||||
EDErrorCode ed_journal_file_open(EDJournalFile *file,
|
EDErrorCode ed_journal_file_open(EDJournalFile *file,
|
||||||
char const *filename,
|
char const *filename,
|
||||||
GError **error);
|
GError **error);
|
||||||
|
|
||||||
|
GDateTime *ed_journal_file_get_datetime(EDJournalFile *self);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -3,11 +3,13 @@
|
|||||||
#include <edapi/util.h>
|
#include <edapi/util.h>
|
||||||
|
|
||||||
#include <gio/gio.h>
|
#include <gio/gio.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
gchar *filename;
|
gchar *filename;
|
||||||
gchar *timestamp;
|
gchar *datetime;
|
||||||
int index;
|
GDateTime *timestamp;
|
||||||
|
gint part;
|
||||||
GList *entries;
|
GList *entries;
|
||||||
} EDJournalFilePrivate;
|
} EDJournalFilePrivate;
|
||||||
|
|
||||||
@ -35,8 +37,16 @@ static void ed_journal_file_finalize(GObject *obj)
|
|||||||
free(p->filename);
|
free(p->filename);
|
||||||
p->filename = NULL;
|
p->filename = NULL;
|
||||||
|
|
||||||
free(p->timestamp);
|
free(p->datetime);
|
||||||
p->timestamp = NULL;
|
p->datetime = NULL;
|
||||||
|
|
||||||
|
if (p->timestamp != NULL) {
|
||||||
|
/* my only pet peeve of glib: you never know if their functions
|
||||||
|
* fail on a NULL pointer or not
|
||||||
|
*/
|
||||||
|
g_date_time_unref(p->timestamp);
|
||||||
|
p->timestamp = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
g_list_free_full(p->entries, g_object_unref);
|
g_list_free_full(p->entries, g_object_unref);
|
||||||
p->entries = NULL;
|
p->entries = NULL;
|
||||||
@ -58,20 +68,15 @@ EDJournalFile *ed_journal_file_new(void)
|
|||||||
return g_object_new(ED_TYPE_JOURNALFILE, NULL);
|
return g_object_new(ED_TYPE_JOURNALFILE, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
EDErrorCode ed_journal_file_parse(EDJournalFile *file, char const *filename)
|
EDErrorCode ed_journal_file_parse_filename(char const *basename,
|
||||||
|
gchar **date,
|
||||||
|
gint *part)
|
||||||
{
|
{
|
||||||
EDJournalFilePrivate *p = ed_journal_file_get_instance_private(file);
|
|
||||||
gchar *basename = NULL;
|
|
||||||
EDErrorCode ret = ed_error_internal;
|
|
||||||
|
|
||||||
GRegex *new_style = NULL;
|
GRegex *new_style = NULL;
|
||||||
GMatchInfo *matches = NULL;
|
GMatchInfo *matches = NULL;
|
||||||
|
|
||||||
gchar *timestamp = NULL;
|
gchar *timestamp = NULL;
|
||||||
gchar *index = NULL;
|
gchar *index = NULL;
|
||||||
|
EDErrorCode ret = ed_error_invalid;
|
||||||
return_if_true(file == NULL, ed_error_args);
|
|
||||||
return_if_true(S_EMPTY(filename), ed_error_args);
|
|
||||||
|
|
||||||
new_style = g_regex_new(
|
new_style = g_regex_new(
|
||||||
"Journal\\.([\\dT\\-]+)\\.(\\d+)\\.log",
|
"Journal\\.([\\dT\\-]+)\\.(\\d+)\\.log",
|
||||||
@ -79,24 +84,111 @@ EDErrorCode ed_journal_file_parse(EDJournalFile *file, char const *filename)
|
|||||||
);
|
);
|
||||||
goto_if_true(new_style == NULL, done);
|
goto_if_true(new_style == NULL, done);
|
||||||
|
|
||||||
basename = g_path_get_basename(filename);
|
|
||||||
goto_if_true(S_EMPTY(basename), done);
|
|
||||||
|
|
||||||
if (g_regex_match(new_style, basename, 0, &matches)) {
|
if (g_regex_match(new_style, basename, 0, &matches)) {
|
||||||
timestamp = g_match_info_fetch(matches, 1);
|
timestamp = g_match_info_fetch(matches, 1);
|
||||||
index = g_match_info_fetch(matches, 2);
|
index = g_match_info_fetch(matches, 2);
|
||||||
|
|
||||||
|
ret = ed_error_success;
|
||||||
|
} else {
|
||||||
|
ret = ed_error_invalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_match_info_unref(matches);
|
g_match_info_unref(matches);
|
||||||
matches = NULL;
|
matches = NULL;
|
||||||
|
|
||||||
goto_if_true(S_EMPTY(timestamp), done);
|
if (ED_SUCCESS(ret)) {
|
||||||
goto_if_true(S_EMPTY(index), done);
|
if (date != NULL) {
|
||||||
|
*date = timestamp;
|
||||||
|
/* we gave timestamp to the caller */
|
||||||
|
timestamp = NULL;
|
||||||
|
}
|
||||||
|
if (part != NULL) {
|
||||||
|
*part = strtol(index, NULL, 10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
g_free(p->timestamp);
|
done:
|
||||||
p->timestamp = g_strdup(timestamp);
|
|
||||||
|
|
||||||
p->index = strtol(index, NULL, 0);
|
g_free(timestamp);
|
||||||
|
g_free(index);
|
||||||
|
g_regex_unref(new_style);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static EDErrorCode ed_journal_file_parse_timestamp(EDJournalFile *file)
|
||||||
|
{
|
||||||
|
EDJournalFilePrivate *p = ed_journal_file_get_instance_private(file);
|
||||||
|
|
||||||
|
return_if_true(p->datetime == NULL, ed_error_invalid);
|
||||||
|
|
||||||
|
if (strchr(p->datetime, 'T') != NULL) {
|
||||||
|
/**
|
||||||
|
* new style ISO timestamps
|
||||||
|
*/
|
||||||
|
GTimeZone *utc = g_time_zone_new_utc();
|
||||||
|
GDateTime *dt = g_date_time_new_from_iso8601(p->datetime, utc);
|
||||||
|
g_time_zone_unref(utc);
|
||||||
|
return_if_true(dt == NULL, ed_error_invalid);
|
||||||
|
p->timestamp = dt;
|
||||||
|
|
||||||
|
return ed_error_success;
|
||||||
|
} else {
|
||||||
|
/**
|
||||||
|
* old school non-ISO timestamps, used around 2021
|
||||||
|
*/
|
||||||
|
int year = 0, month = 0, day = 0, hour = 0, minute = 0, second = 0;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
ret = sscanf(p->datetime,
|
||||||
|
"%2d%2d%2d%2d%2d%2d",
|
||||||
|
&year, &month, &day,
|
||||||
|
&hour, &minute, &second
|
||||||
|
);
|
||||||
|
|
||||||
|
if (ret != 6) {
|
||||||
|
return ed_error_invalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* add base year to years
|
||||||
|
*/
|
||||||
|
year += 2000;
|
||||||
|
|
||||||
|
GDateTime *dt = g_date_time_new_utc(
|
||||||
|
year, month, day, hour, minute, second);
|
||||||
|
return_if_true(dt == NULL, ed_error_invalid);
|
||||||
|
p->timestamp = dt;
|
||||||
|
|
||||||
|
return ed_error_success;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ed_error_invalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
EDErrorCode ed_journal_file_parse(EDJournalFile *self, char const *filename)
|
||||||
|
{
|
||||||
|
EDJournalFilePrivate *p = ed_journal_file_get_instance_private(self);
|
||||||
|
gchar *basename = NULL;
|
||||||
|
EDErrorCode ret = ed_error_internal;
|
||||||
|
|
||||||
|
return_if_true(self == NULL, ed_error_args);
|
||||||
|
return_if_true(S_EMPTY(filename), ed_error_args);
|
||||||
|
|
||||||
|
basename = g_path_get_basename(filename);
|
||||||
|
goto_if_true(S_EMPTY(basename), done);
|
||||||
|
|
||||||
|
ret = ed_journal_file_parse_filename(basename, &p->datetime, &p->part);
|
||||||
|
if (ED_ERROR(ret)) {
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = ed_journal_file_parse_timestamp(self);
|
||||||
|
if (ED_ERROR(ret)) {
|
||||||
|
g_free(p->datetime);
|
||||||
|
p->datetime = NULL;
|
||||||
|
p->part = 0;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
g_free(p->filename);
|
g_free(p->filename);
|
||||||
p->filename = g_strdup(filename);
|
p->filename = g_strdup(filename);
|
||||||
@ -105,10 +197,7 @@ EDErrorCode ed_journal_file_parse(EDJournalFile *file, char const *filename)
|
|||||||
|
|
||||||
done:
|
done:
|
||||||
|
|
||||||
g_free(timestamp);
|
|
||||||
g_free(index);
|
|
||||||
g_free(basename);
|
g_free(basename);
|
||||||
g_regex_unref(new_style);
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -156,6 +245,15 @@ static EDErrorCode ed_journal_file_load(EDJournalFile *self,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ignore empty lines
|
||||||
|
*/
|
||||||
|
g_strchomp(line);
|
||||||
|
if (strlen(line) <= 0) {
|
||||||
|
g_free(line);
|
||||||
|
line = NULL;
|
||||||
|
linelen = 0;
|
||||||
|
}
|
||||||
|
|
||||||
entry = ed_journal_entry_new();
|
entry = ed_journal_entry_new();
|
||||||
goto_if_true(entry == NULL, done);
|
goto_if_true(entry == NULL, done);
|
||||||
|
|
||||||
@ -200,3 +298,10 @@ EDErrorCode ed_journal_file_open(EDJournalFile *file,
|
|||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GDateTime *ed_journal_file_get_datetime(EDJournalFile *self)
|
||||||
|
{
|
||||||
|
return_if_true(self == NULL, NULL);
|
||||||
|
EDJournalFilePrivate *p = ed_journal_file_get_instance_private(self);
|
||||||
|
return p->timestamp;
|
||||||
|
}
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
#include <edapi/journal/journal.h>
|
#include <edapi/journal/journal.h>
|
||||||
|
#include <edapi/journal/file.h>
|
||||||
#include <edapi/util.h>
|
#include <edapi/util.h>
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
gchar *location;
|
gchar *location;
|
||||||
|
GList *files;
|
||||||
} EDJournalPrivate;
|
} EDJournalPrivate;
|
||||||
|
|
||||||
struct _EDJournal {
|
struct _EDJournal {
|
||||||
@ -39,23 +41,30 @@ static void ed_journal_class_init(EDJournalClass *klass)
|
|||||||
|
|
||||||
static EDErrorCode ed_journal_determine_location(EDJournal *self)
|
static EDErrorCode ed_journal_determine_location(EDJournal *self)
|
||||||
{
|
{
|
||||||
EDJournalPrivate *p = ed_journal_get_instance_private(self);
|
|
||||||
gchar *location = NULL;
|
gchar *location = NULL;
|
||||||
|
gchar *tmp = NULL;
|
||||||
|
|
||||||
#ifdef G_OS_WIN32
|
/**
|
||||||
char const *env = getenv("%USERPROFILE%");
|
* on Windows we have %USERPROFILE% which points to the current
|
||||||
|
* users home directory. See if they have a Saved Games folder.
|
||||||
if (!S_EMPTY(env)) {
|
*/
|
||||||
location = g_build_path(
|
char const *env1 = getenv("%USERPROFILE%");
|
||||||
|
char const *env2 = getenv("USERPROFILE");
|
||||||
|
if (!S_EMPTY(env1) || !S_EMPTY(env2)) {
|
||||||
|
tmp = g_build_path(
|
||||||
G_DIR_SEPARATOR_S,
|
G_DIR_SEPARATOR_S,
|
||||||
env,
|
S_EMPTY(env1) ? env2 : env1,
|
||||||
"Saved Games",
|
"Saved Games",
|
||||||
"Frontier Developments",
|
"Frontier Developments",
|
||||||
"Elite Dangerous",
|
"Elite Dangerous",
|
||||||
NULL
|
NULL
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (g_file_test(tmp, G_FILE_TEST_IS_DIR)) {
|
||||||
|
location = tmp;
|
||||||
|
tmp = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
if (S_EMPTY(location)) {
|
if (S_EMPTY(location)) {
|
||||||
return ed_error_invalid;
|
return ed_error_invalid;
|
||||||
@ -66,8 +75,7 @@ static EDErrorCode ed_journal_determine_location(EDJournal *self)
|
|||||||
return ed_error_invalid;
|
return ed_error_invalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_free(p->location);
|
ed_journal_set_location(self, location);
|
||||||
p->location = location;
|
|
||||||
|
|
||||||
return ed_error_success;
|
return ed_error_success;
|
||||||
}
|
}
|
||||||
@ -82,6 +90,60 @@ EDJournal *ed_journal_new(void)
|
|||||||
return g_object_new(ED_TYPE_JOURNAL, NULL);
|
return g_object_new(ED_TYPE_JOURNAL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ed_journal_load_files(EDJournal *self)
|
||||||
|
{
|
||||||
|
EDJournalPrivate *p = ed_journal_get_instance_private(self);
|
||||||
|
GDir *loc = NULL;
|
||||||
|
gchar const *name = NULL;
|
||||||
|
EDErrorCode ret = ed_error_success;
|
||||||
|
EDJournalFile *journalfile = NULL;
|
||||||
|
|
||||||
|
g_list_free_full(p->files, g_object_unref);
|
||||||
|
p->files = NULL;
|
||||||
|
|
||||||
|
loc = g_dir_open(p->location, 0, NULL);
|
||||||
|
goto_if_true(loc == NULL, done);
|
||||||
|
|
||||||
|
while ((name = g_dir_read_name(loc)) != NULL) {
|
||||||
|
if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
gchar *full = g_build_path(
|
||||||
|
G_DIR_SEPARATOR_S,
|
||||||
|
p->location,
|
||||||
|
name,
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
if (g_file_test(full, G_FILE_TEST_IS_DIR)) {
|
||||||
|
goto next;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = ed_journal_file_parse_filename(name, NULL, NULL);
|
||||||
|
goto_if_error(ret, next);
|
||||||
|
|
||||||
|
journalfile = ed_journal_file_new();
|
||||||
|
goto_if_true(journalfile == NULL, next);
|
||||||
|
|
||||||
|
ret = ed_journal_file_open(journalfile, full, NULL);
|
||||||
|
if (ED_SUCCESS(ret)) {
|
||||||
|
p->files = g_list_append(p->files, journalfile);
|
||||||
|
}
|
||||||
|
|
||||||
|
next:
|
||||||
|
|
||||||
|
g_free(full);
|
||||||
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
|
||||||
|
if (loc != NULL) {
|
||||||
|
g_dir_close(loc);
|
||||||
|
loc = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
gchar const *ed_journal_get_location(EDJournal *self)
|
gchar const *ed_journal_get_location(EDJournal *self)
|
||||||
{
|
{
|
||||||
return_if_true(self == NULL, NULL);
|
return_if_true(self == NULL, NULL);
|
||||||
@ -102,5 +164,7 @@ EDErrorCode ed_journal_set_location(EDJournal *self, gchar const *dir)
|
|||||||
g_free(p->location);
|
g_free(p->location);
|
||||||
p->location = g_strdup(dir);
|
p->location = g_strdup(dir);
|
||||||
|
|
||||||
|
ed_journal_load_files(self);
|
||||||
|
|
||||||
return ed_error_success;
|
return ed_error_success;
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ SET(TESTS
|
|||||||
|
|
||||||
INCLUDE_DIRECTORIES(
|
INCLUDE_DIRECTORIES(
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/../include"
|
"${CMAKE_CURRENT_SOURCE_DIR}/../include"
|
||||||
"${CMOCKA_INCLUDE_DIRS}"
|
#"${CMOCKA_INCLUDE_DIRS}"
|
||||||
)
|
)
|
||||||
|
|
||||||
FOREACH(TEST ${TESTS})
|
FOREACH(TEST ${TESTS})
|
||||||
@ -22,6 +22,6 @@ FOREACH(TEST ${TESTS})
|
|||||||
ADD_TEST(
|
ADD_TEST(
|
||||||
NAME ${TEST}
|
NAME ${TEST}
|
||||||
COMMAND ${TEST}
|
COMMAND ${TEST}
|
||||||
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/.."
|
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||||
)
|
)
|
||||||
ENDFOREACH()
|
ENDFOREACH()
|
||||||
|
1
lib/tests/Journal.2023-04-18T061507.01.log
Normal file
1
lib/tests/Journal.2023-04-18T061507.01.log
Normal file
@ -0,0 +1 @@
|
|||||||
|
{ "timestamp":"2023-04-18T04:14:56Z", "event":"Fileheader", "part":1, "language":"English/UK", "Odyssey":true, "gameversion":"4.0.0.1477", "build":"r291050/r0 " }
|
@ -12,11 +12,13 @@ static void test_new_filename(void **state)
|
|||||||
|
|
||||||
EDJournalFile *file = ed_journal_file_new();
|
EDJournalFile *file = ed_journal_file_new();
|
||||||
EDErrorCode ret = 0;
|
EDErrorCode ret = 0;
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
assert_non_null(file);
|
assert_non_null(file);
|
||||||
|
|
||||||
ret = ed_journal_file_parse(file, filename);
|
ret = ed_journal_file_open(file, filename, &error);
|
||||||
assert_int_equal(ret, ed_error_success);
|
assert_int_equal(ret, ed_error_success);
|
||||||
|
assert_null(error);
|
||||||
|
|
||||||
g_clear_object(&file);
|
g_clear_object(&file);
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,18 @@
|
|||||||
|
#define _DEFAULT_SOURCE
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <setjmp.h>
|
#include <setjmp.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <cmocka.h>
|
#include <cmocka.h>
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include <edapi/journal/journal.h>
|
#include <edapi/journal/journal.h>
|
||||||
|
|
||||||
static void test_new_location(void **state)
|
static void test_userprofile_location(void **state)
|
||||||
{
|
{
|
||||||
|
setenv("USERPROFILE", "./", 1);
|
||||||
|
|
||||||
EDJournal *journal = ed_journal_new();
|
EDJournal *journal = ed_journal_new();
|
||||||
assert_non_null(journal);
|
assert_non_null(journal);
|
||||||
|
|
||||||
@ -20,7 +25,7 @@ static void test_new_location(void **state)
|
|||||||
int main(int ac, char **av)
|
int main(int ac, char **av)
|
||||||
{
|
{
|
||||||
static const struct CMUnitTest tests[] = {
|
static const struct CMUnitTest tests[] = {
|
||||||
cmocka_unit_test(test_new_location),
|
cmocka_unit_test(test_userprofile_location),
|
||||||
};
|
};
|
||||||
|
|
||||||
return cmocka_run_group_tests(tests, NULL, NULL);
|
return cmocka_run_group_tests(tests, NULL, NULL);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user