more code
This commit is contained in:
parent
f8c5a33d36
commit
7fcb2addfe
@ -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
25
lib/include/edapi/error.h
Normal 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
|
30
lib/include/edapi/journal/entry.h
Normal file
30
lib/include/edapi/journal/entry.h
Normal 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
|
@ -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
9
lib/include/edapi/util.h
Normal 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
67
lib/src/journal/entry.c
Normal 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;
|
||||
}
|
@ -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
22
lib/tests/CMakeLists.txt
Normal 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()
|
30
lib/tests/test-journal-file-parse.c
Normal file
30
lib/tests/test-journal-file-parse.c
Normal 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);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user