allcing/tool/unpack.c

136 lines
3.4 KiB
C
Raw Normal View History

// 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;
}