add new target of an executable to unpack binary log data

This commit is contained in:
falsycat 2024-02-15 09:30:46 +09:00
parent 2d71b4cec2
commit e07604dc4b
4 changed files with 160 additions and 7 deletions

View File

@ -33,14 +33,14 @@ target_compile_options(allcing_config INTERFACE
# ---- library header
add_library(allcing INTERFACE)
target_sources(allcing INTERFACE allcing.h)
target_link_libraries(allcing INTERFACE allcing_config)
target_include_directories(allcing SYSTEM INTERFACE .)
# ---- test binary
if (BUILD_TESTING)
add_executable(allcing_test)
target_sources(allcing_test PRIVATE test.c)
target_link_libraries(allcing_test PRIVATE allcing)
target_link_libraries(allcing_test PRIVATE allcing allcing_config)
add_test(NAME allcing_test COMMAND $<TARGET_FILE:allcing_test>)
endif()
@ -48,4 +48,8 @@ endif()
# ---- example binary
add_executable(allcing_example EXCLUDE_FROM_ALL)
target_sources(allcing_example PRIVATE example.c)
target_link_libraries(allcing_example PRIVATE allcing)
target_link_libraries(allcing_example PRIVATE allcing allcing_config)
# ---- tool subdirs
add_subdirectory(tool EXCLUDE_FROM_ALL)

View File

@ -6,10 +6,12 @@
// ----
#define ACG_NO_READ_FUNCTIONS
#include "allcing.h"
static inline bool acg_flush(struct acg_stream* s) {
static inline bool acg_stream_flush(struct acg_stream* s) {
assert(NULL != s);
acg_stream_write_chunk_pad(s);
if (s->cursor_bits < 8U) {
return false;
}
@ -21,11 +23,19 @@ static inline bool acg_flush(struct acg_stream* s) {
abort();
}
}
if (1U != fwrite(s->buffer, s->cursor_bits/8U, 1U, *fp)) {
return false;
}
memset(s->buffer, 0U, (s->cursor_bits+7U)/8U);
s->cursor_bits = 0;
uint8_t frag = 0U;
if (s->cursor_bits%8U > 0U) {
frag = s->buffer[s->cursor_bits/8U];
}
memset(s->buffer, 0U, s->size_bytes);
s->buffer[0] = frag;
s->cursor_bits %= 8U;
if (0U != fflush(*fp)) {
return false;
@ -35,7 +45,7 @@ static inline bool acg_flush(struct acg_stream* s) {
#undef ACG_LOC_FULL
#define ACG_LOC_FULL ACG_LOC_SHORT
#undef ACG_FLUSH
#define ACG_FLUSH(s) acg_flush((s))
#define ACG_FLUSH(s) acg_stream_flush((s))
struct acg_stream logstream = {
.buffer = (uint8_t[1024U]) {0U},

4
tool/CMakeLists.txt Normal file
View File

@ -0,0 +1,4 @@
# ---- allcing_unpack: converts binary format to human readable text
add_executable(allcing_unpack)
target_sources(allcing_unpack PRIVATE unpack.c)
target_link_libraries(allcing_unpack PRIVATE allcing allcing_config)

135
tool/unpack.c Normal file
View File

@ -0,0 +1,135 @@
// No copyright
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <allcing.h>
#define READ_CHUNK_SIZE 1024U
static inline bool acg_stream_refill(struct acg_stream* s) {
assert(NULL != s);
FILE* fp = s->udata;
assert(NULL != fp);
uint8_t* const buf = s->buffer;
uint64_t* const c = &s->cursor_bits;
uint64_t* const size = &s->size_bytes;
const uint64_t remain = *size - *c/8U;
memmove(buf, &buf[*c/8U], remain);
*c %= 8U;
const uint64_t expect_size = READ_CHUNK_SIZE - remain;
const uint64_t actual_size = fread(&buf[remain], 1U, expect_size, fp);
*size = remain + actual_size;
return true;
}
int main(int argc, char** argv) {
if (argc != 2U) {
fprintf(stderr, "invalid args\n");
return EXIT_FAILURE;
}
FILE* fp = fopen(argv[1], "rb");
if (NULL == fp) {
fprintf(stderr, "failed to open: %s\n", argv[1]);
return EXIT_FAILURE;
}
struct acg_stream s = {
.buffer = (uint8_t[READ_CHUNK_SIZE]) {0U},
.udata = fp,
};
uint64_t last_event_chunk_id = 0U;
uint32_t indent = 0U;
# define INDENT_PRINT(FMT, ...) \
printf("%*s" FMT "\n", indent, "" __VA_OPT__(,) __VA_ARGS__)
while (true) {
if (!acg_stream_refill(&s)) {
fprintf(stderr, "failed to read: %s\n", argv[1]);
return EXIT_FAILURE;
}
if (0U == s.size_bytes) {
break;
}
uint64_t chunk_id;
if (!acg_stream_read_uint(&s, &chunk_id, ACG_UNITBITS_CHUNK_ID)) {
fprintf(stderr, "failed to read chunk id\n");
return EXIT_FAILURE;
}
const bool is_event_chunk = chunk_id >= ACG_CHUNK_BEGIN;
if (is_event_chunk) {
if (ACG_CHUNK_BEGIN == last_event_chunk_id) {
++indent;
} else if (ACG_CHUNK_END == last_event_chunk_id) {
--indent;
}
last_event_chunk_id = chunk_id;
}
switch (chunk_id) {
case ACG_CHUNK_PAD:
acg_stream_read_pad(&s);
break;
case ACG_CHUNK_BLOB: {
uint64_t size;
uint8_t* buf;
if (!acg_stream_read_blob(&s, &size, &buf)) {
fprintf(stderr, "failed to read BLOB in BLOB chunk\n");
return EXIT_FAILURE;
}
INDENT_PRINT("-BLOB: %.*s", (int) size, (const char*) buf);
} break;
case ACG_CHUNK_CTX: {
uint64_t time;
if (!acg_stream_read_uint(&s, &time, 64U)) {
fprintf(stderr, "failed to read TIME in CTX chunk\n");
return EXIT_FAILURE;
}
uint64_t tid;
if (!acg_stream_read_uint(&s, &tid, 16U)) {
fprintf(stderr, "failed to read TID in CTX chunk\n");
return EXIT_FAILURE;
}
INDENT_PRINT("-CTX: TIME=%" PRIu64 " / TID=%" PRIx64, time, tid);
} break;
case ACG_CHUNK_LOC: {
uint64_t size;
uint8_t* buf;
if (!acg_stream_read_blob(&s, &size, &buf)) {
fprintf(stderr, "failed to read BLOB in BLOB chunk\n");
return EXIT_FAILURE;
}
INDENT_PRINT("-LOC: %.*s", (int) size, (const char*) buf);
} break;
case ACG_CHUNK_BEGIN:
INDENT_PRINT("BEGIN:");
break;
case ACG_CHUNK_END:
if (0U == indent) {
fprintf(stderr, "too many END chunk\n");
return EXIT_FAILURE;
}
INDENT_PRINT("END:");
break;
case ACG_CHUNK_CHECK:
INDENT_PRINT("CHECK:");
break;
default:
fprintf(stderr, "unknown chunk id: %" PRIu64 "\n", chunk_id);
return EXIT_FAILURE;
}
}
fclose(fp);
return EXIT_SUCCESS;
}