more code

This commit is contained in:
Florian Stinglmayr 2025-04-24 12:59:55 +02:00
parent f8c5a33d36
commit 7fcb2addfe
9 changed files with 273 additions and 8 deletions

View File

@ -4,20 +4,25 @@ FIND_PACKAGE(PkgConfig)
PKG_CHECK_MODULES(JANSSON REQUIRED jansson)
PKG_CHECK_MODULES(GLIB2 REQUIRED glib-2.0)
PKG_CHECK_MODULES(GOBJECT2 REQUIRED gobject-2.0)
SET(SOURCES
"src/journal/file.c"
"include/edapi/journal/entry.h"
"include/edapi/journal/file.h"
"src/journal/entry.c"
"src/journal/file.c"
)
INCLUDE_DIRECTORIES(
"include"
${GLIB2_INCLUDE_DIRS}
${GOBJECT2_INCLUDE_DIRS}
${JANSSON_INCLUDE_DIRS}
)
LINK_DIRECTORIES(
${GLIB2_LIBRARY_DIRS}
${GOBJECT2_LIBRARY_DIRS}
${JANSSON_LIBRARY_DIRS}
)
@ -25,5 +30,9 @@ ADD_LIBRARY("edapi" SHARED ${SOURCES})
TARGET_LINK_LIBRARIES(
"edapi"
${GLIB2_LIBRARIES}
${GOBJECT2_LIBRARIES}
${JANSSON_LIBRARIES}
)
ENABLE_TESTING()
ADD_SUBDIRECTORY("tests")

25
lib/include/edapi/error.h Normal file
View File

@ -0,0 +1,25 @@
#ifndef EDAPI_ERROR_H
#define EDAPI_ERROR_H
typedef enum {
ed_error_success = 0,
ed_error_args,
ed_error_invalid,
ed_error_internal,
ed_error_invalid_json,
} EDErrorCode;
#define ED_SUCCESS(r) ((r) == ed_error_success)
#define ED_ERROR(r) ((r) != ed_error_success)
/**
* Goes to label l if b is true.
*/
#define goto_if_true(b, l) do { if (b) goto l; } while(0)
/**
* Goes to label `l` if r is an error code.
*/
#define goto_if_error(r, l) do { if (ED_ERROR(r)) goto l; } while(0)
#endif

View File

@ -0,0 +1,30 @@
#ifndef EDAPI_JOURNAL_ENTRY_H
#define EDAPI_JOURNAL_ENTRY_H
#include <edapi/error.h>
#include <glib.h>
#include <glib-object.h>
G_BEGIN_DECLS
struct _EDJournalEntryClass {
GObjectClass parent_class;
gpointer padding[42];
};
G_DECLARE_DERIVABLE_TYPE(
EDJournalEntry, ed_journal_entry, ED, JOURNALENTRY, GObject);
#define ED_TYPE_JOURNALENTRY ed_journal_entry_get_type()
EDJournalEntry *ed_journal_entry_new(void);
EDErrorCode ed_journal_entry_parse(EDJournalEntry *self,
gchar const *line,
GError **error);
G_END_DECLS
#endif

View File

@ -1,6 +1,8 @@
#ifndef EDAPI_JOURNAL_FILE_H
#define EDAPI_JOURNAL_FILE_H
#include <edapi/error.h>
#include <glib.h>
#include <glib-object.h>
@ -12,6 +14,10 @@ G_DECLARE_FINAL_TYPE(EDJournalFile, ed_journal_file, ED, JOURNALFILE, GObject);
EDJournalFile *ed_journal_file_new(void);
EDErrorCode ed_journal_file_parse(EDJournalFile *file, char const *filename);
EDErrorCode ed_journal_file_open(EDJournalFile *file, char const *filename);
G_END_DECLS
#endif

9
lib/include/edapi/util.h Normal file
View File

@ -0,0 +1,9 @@
#ifndef EDAPI_UTIL_H
#define EDAPI_UTIL_H
/**
* Checks if a string pointer is NULL or empty
*/
#define S_EMPTY(s) ((s == NULL) || strlen(s) <= 0)
#endif

67
lib/src/journal/entry.c Normal file
View File

@ -0,0 +1,67 @@
#include <edapi/journal/entry.h>
#include <edapi/util.h>
#include <jansson.h>
typedef struct {
json_t *entry;
} EDJournalEntryPrivate;
G_DEFINE_QUARK("ed-json-error", ed_json_error);
G_DEFINE_TYPE_EXTENDED(
EDJournalEntry,
ed_journal_entry,
G_TYPE_OBJECT,
0,
G_ADD_PRIVATE(EDJournalEntry)
);
static void ed_journal_entry_class_init(EDJournalEntryClass *klass)
{
}
static void ed_journal_entry_init(EDJournalEntry *self)
{
}
EDJournalEntry *ed_journal_entry_new(void)
{
return g_object_new(
ED_TYPE_JOURNALENTRY,
NULL
);
}
EDErrorCode ed_journal_entry_parse(EDJournalEntry *self,
gchar const *line,
GError **error)
{
EDJournalEntryPrivate *p = ed_journal_entry_get_instance_private(self);
EDErrorCode ret = ed_error_invalid;
json_error_t e;
json_decref(p->entry);
p->entry = NULL;
memset(&e, 0, sizeof(e));
p->entry = json_loads(line, 0, &e);
if (p->entry == NULL) {
g_set_error(
error,
ed_json_error_quark(),
ed_error_invalid_json,
"%d: %d: %d: %s",
e.line,
e.column,
e.position,
e.text
);
ret = ed_error_invalid_json;
} else {
ret = ed_error_success;
}
return ret;
}

View File

@ -1,8 +1,10 @@
#include <edapi/journal/file.h>
#include <edapi/util.h>
typedef struct {
char *filename;
char *timestamp;
gchar *filename;
gchar *timestamp;
int index;
} EDJournalFilePrivate;
struct _EDJournalFile {
@ -13,7 +15,8 @@ struct _EDJournalFileClass {
GObjectClass parent_class;
};
G_DEFINE_TYPE_EXTENDED(EDJournalFile,
G_DEFINE_TYPE_EXTENDED(
EDJournalFile,
ed_journal_file,
G_TYPE_OBJECT,
0,
@ -47,3 +50,67 @@ EDJournalFile *ed_journal_file_new(void)
{
return g_object_new(ED_TYPE_JOURNALFILE, NULL);
}
EDErrorCode ed_journal_file_parse(EDJournalFile *file, char const *filename)
{
EDJournalFilePrivate *p = ed_journal_file_get_instance_private(file);
gchar *basename = NULL;
EDErrorCode ret = ed_error_internal;
GRegex *new_style = NULL;
GMatchInfo *matches = NULL;
gchar *timestamp = NULL;
gchar *index = NULL;
new_style = g_regex_new(
"Journal\\.([\\dT\\-]+)\\.(\\d+)\\.log",
0, 0, NULL
);
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)) {
timestamp = g_match_info_fetch(matches, 1);
index = g_match_info_fetch(matches, 2);
}
g_match_info_unref(matches);
matches = NULL;
goto_if_true(S_EMPTY(timestamp), done);
goto_if_true(S_EMPTY(index), done);
g_free(p->timestamp);
p->timestamp = g_strdup(timestamp);
p->index = strtol(index, NULL, 0);
g_free(p->filename);
p->filename = g_strdup(filename);
ret = ed_error_success;
done:
g_free(timestamp);
g_free(index);
g_free(basename);
g_regex_unref(new_style);
return ret;
}
EDErrorCode ed_journal_file_open(EDJournalFile *file, char const *filename)
{
EDErrorCode r = ed_error_success;
r = ed_journal_file_parse(file, filename);
if (ED_ERROR(r)) {
return r;
}
return r;
}

22
lib/tests/CMakeLists.txt Normal file
View File

@ -0,0 +1,22 @@
CMAKE_MINIMUM_REQUIRED(VERSION 3.24)
PKG_CHECK_MODULES(CMOCKA REQUIRED cmocka)
SET(TESTS
"test-journal-file-parse"
)
INCLUDE_DIRECTORIES(
"${CMAKE_CURRENT_SOURCE_DIR}/../include"
"${CMOCKA_INCLUDE_DIRS}"
)
FOREACH(TEST ${TESTS})
ADD_EXECUTABLE(${TEST} "${TEST}.c")
TARGET_LINK_LIBRARIES(
"${TEST}"
"edapi"
${CMOCKA_LIBRARIES}
)
ADD_TEST(NAME ${TEST} COMMAND ${TEST})
ENDFOREACH()

View File

@ -0,0 +1,30 @@
#include <stdarg.h>
#include <setjmp.h>
#include <stddef.h>
#include <cmocka.h>
#include <edapi/journal/file.h>
static void test_new_filename(void **state)
{
char const *filename = "Journal.2023-04-18T061507.01.log";
EDJournalFile *file = ed_journal_file_new();
EDErrorCode ret = 0;
assert_non_null(file);
ret = ed_journal_file_parse(file, filename);
assert_int_equal(ret, ed_error_success);
g_clear_object(&file);
}
int main(int ac, char **av)
{
static const struct CMUnitTest tests[] = {
cmocka_unit_test(test_new_filename),
};
return cmocka_run_group_tests(tests, NULL, NULL);
}