Compare commits
2 Commits
a1cefa690d
...
e07604dc4b
Author | SHA1 | Date | |
---|---|---|---|
e07604dc4b | |||
2d71b4cec2 |
@ -33,14 +33,14 @@ target_compile_options(allcing_config INTERFACE
|
|||||||
# ---- library header
|
# ---- library header
|
||||||
add_library(allcing INTERFACE)
|
add_library(allcing INTERFACE)
|
||||||
target_sources(allcing INTERFACE allcing.h)
|
target_sources(allcing INTERFACE allcing.h)
|
||||||
target_link_libraries(allcing INTERFACE allcing_config)
|
target_include_directories(allcing SYSTEM INTERFACE .)
|
||||||
|
|
||||||
|
|
||||||
# ---- test binary
|
# ---- test binary
|
||||||
if (BUILD_TESTING)
|
if (BUILD_TESTING)
|
||||||
add_executable(allcing_test)
|
add_executable(allcing_test)
|
||||||
target_sources(allcing_test PRIVATE test.c)
|
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>)
|
add_test(NAME allcing_test COMMAND $<TARGET_FILE:allcing_test>)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@ -48,4 +48,8 @@ endif()
|
|||||||
# ---- example binary
|
# ---- example binary
|
||||||
add_executable(allcing_example EXCLUDE_FROM_ALL)
|
add_executable(allcing_example EXCLUDE_FROM_ALL)
|
||||||
target_sources(allcing_example PRIVATE example.c)
|
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)
|
||||||
|
143
allcing.h
143
allcing.h
@ -15,10 +15,10 @@
|
|||||||
|
|
||||||
// ---- variable points
|
// ---- variable points
|
||||||
#if !defined(ACG_NOW)
|
#if !defined(ACG_NOW)
|
||||||
# define ACG_NOW ((uint64_t) (clock()/CLOCKS_PER_SEC*10000000U))
|
# define ACG_NOW ((uint64_t) ((double) clock()/CLOCKS_PER_SEC*1000000U))
|
||||||
#endif
|
#endif
|
||||||
#if !defined(ACG_TID)
|
#if !defined(ACG_TID)
|
||||||
# define ACG_TID (0U) // you should replace ACG_TID to log an actual TID
|
# define ACG_TID (0x700FU) // you should replace ACG_TID to log an actual TID
|
||||||
#endif
|
#endif
|
||||||
#if !defined(ACG_LOC_FULL)
|
#if !defined(ACG_LOC_FULL)
|
||||||
# define ACG_LOC_FULL (__FILE__ ":" ACG_UTIL_STR2(__func__) ":" ACG_UTIL_STR2(__LINE__))
|
# define ACG_LOC_FULL (__FILE__ ":" ACG_UTIL_STR2(__func__) ":" ACG_UTIL_STR2(__LINE__))
|
||||||
@ -33,11 +33,11 @@
|
|||||||
|
|
||||||
// ---- sugar syntax for logging
|
// ---- sugar syntax for logging
|
||||||
#define ACG_BLOB_LITERAL(s, data) ( \
|
#define ACG_BLOB_LITERAL(s, data) ( \
|
||||||
acg_stream_write_blob((s), sizeof((data)), (const uint8_t*) (data)) && \
|
acg_stream_write_chunk_blob((s), sizeof((data)), (const uint8_t*) (data)) && \
|
||||||
ACG_FLUSH((s)) \
|
ACG_FLUSH((s)) \
|
||||||
)
|
)
|
||||||
#define ACG_BLOB(s, size, data) ( \
|
#define ACG_BLOB(s, size, data) ( \
|
||||||
acg_stream_write_blob((s), (size), (const uint8_t*) (data)) && \
|
acg_stream_write_chunk_blob((s), (size), (const uint8_t*) (data)) && \
|
||||||
ACG_FLUSH((s)) \
|
ACG_FLUSH((s)) \
|
||||||
)
|
)
|
||||||
#define ACG_BEGIN(s) ( \
|
#define ACG_BEGIN(s) ( \
|
||||||
@ -89,6 +89,8 @@ struct acg_stream {
|
|||||||
void* udata;
|
void* udata;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#if !defined(ACG_NO_WRITE_FUNCTIONS)
|
||||||
static inline bool acg_stream_write_pad(struct acg_stream* s) {
|
static inline bool acg_stream_write_pad(struct acg_stream* s) {
|
||||||
assert(NULL != s);
|
assert(NULL != s);
|
||||||
|
|
||||||
@ -115,44 +117,31 @@ static inline bool acg_stream_write_uint(struct acg_stream* s, uint64_t v, uint8
|
|||||||
uint64_t* const c = &s->cursor_bits;
|
uint64_t* const c = &s->cursor_bits;
|
||||||
|
|
||||||
const uint8_t unit_data_bits = unit_bits - 1U;
|
const uint8_t unit_data_bits = unit_bits - 1U;
|
||||||
while (v) {
|
do {
|
||||||
if (s->size_bytes*8U - *c < unit_bits) {
|
if (s->size_bytes*8U - *c < unit_bits) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint64_t next_v = v >> unit_data_bits;
|
|
||||||
acg_stream_write_bool(s, !!next_v);
|
|
||||||
|
|
||||||
const uint8_t frag_bits = acg_util_umin(unit_data_bits, (8U - *c%8U)%8U);
|
const uint8_t frag_bits = acg_util_umin(unit_data_bits, (8U - *c%8U)%8U);
|
||||||
if (frag_bits > 0U) {
|
if (frag_bits > 0U) {
|
||||||
buf[*c/8U] |= (v & acg_util_fullbits(frag_bits)) << (*c%8U);
|
buf[*c/8U] |= (v & acg_util_fullbits(frag_bits)) << (*c%8U);
|
||||||
*c += frag_bits;
|
*c += frag_bits;
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint8_t remain_bits = unit_data_bits - frag_bits;
|
const uint8_t remain_bits = unit_data_bits - frag_bits;
|
||||||
const uint64_t v_part = (v >> frag_bits) & acg_util_fullbits(remain_bits);
|
if (remain_bits > 0U) {
|
||||||
memcpy(&buf[*c/8U], &v_part, (remain_bits + 7U) / 8U);
|
assert(*c%8U == 0U);
|
||||||
*c += remain_bits;
|
|
||||||
|
|
||||||
v = next_v;
|
const uint64_t v_part = (v >> frag_bits) & acg_util_fullbits(remain_bits);
|
||||||
}
|
memcpy(&buf[*c/8U], &v_part, (remain_bits + 7U) / 8U);
|
||||||
|
*c += remain_bits;
|
||||||
|
}
|
||||||
|
|
||||||
|
v >>= unit_data_bits;;
|
||||||
|
acg_stream_write_bool(s, !!v);
|
||||||
|
} while (v);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
static inline bool acg_stream_write_int(struct acg_stream* s, int64_t v, uint8_t unit_bits) {
|
|
||||||
assert(NULL != s);
|
|
||||||
assert(2U <= unit_bits);
|
|
||||||
assert(65U >= unit_bits);
|
|
||||||
|
|
||||||
if (v >= 0U) {
|
|
||||||
return
|
|
||||||
acg_stream_write_bool(s, false) &&
|
|
||||||
acg_stream_write_uint(s, (uint64_t) v, unit_bits);
|
|
||||||
} else {
|
|
||||||
return
|
|
||||||
acg_stream_write_bool(s, true) &&
|
|
||||||
acg_stream_write_uint(s, (uint64_t) -v, unit_bits);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
static inline bool acg_stream_write_blob(struct acg_stream* s, uint64_t size_bytes, const uint8_t* buf) {
|
static inline bool acg_stream_write_blob(struct acg_stream* s, uint64_t size_bytes, const uint8_t* buf) {
|
||||||
assert(NULL != s);
|
assert(NULL != s);
|
||||||
|
|
||||||
@ -198,7 +187,7 @@ static inline bool acg_stream_write_chunk_blob(struct acg_stream* s, uint64_t si
|
|||||||
static inline bool acg_stream_write_chunk_ctx(struct acg_stream* s, uint64_t time, uint64_t tid) {
|
static inline bool acg_stream_write_chunk_ctx(struct acg_stream* s, uint64_t time, uint64_t tid) {
|
||||||
assert(NULL != s);
|
assert(NULL != s);
|
||||||
return
|
return
|
||||||
acg_stream_write_uint(s, ACG_CHUNK_LOC, ACG_UNITBITS_CHUNK_ID) &&
|
acg_stream_write_uint(s, ACG_CHUNK_CTX, ACG_UNITBITS_CHUNK_ID) &&
|
||||||
acg_stream_write_uint(s, time, 64U) &&
|
acg_stream_write_uint(s, time, 64U) &&
|
||||||
acg_stream_write_uint(s, tid, 16U);
|
acg_stream_write_uint(s, tid, 16U);
|
||||||
}
|
}
|
||||||
@ -220,3 +209,97 @@ static inline bool acg_stream_write_chunk_check(struct acg_stream* s) {
|
|||||||
assert(NULL != s);
|
assert(NULL != s);
|
||||||
return acg_stream_write_uint(s, ACG_CHUNK_CHECK, ACG_UNITBITS_CHUNK_ID);
|
return acg_stream_write_uint(s, ACG_CHUNK_CHECK, ACG_UNITBITS_CHUNK_ID);
|
||||||
}
|
}
|
||||||
|
#endif // !defined(ACG_NO_WRITE_FUNCTIONS)
|
||||||
|
|
||||||
|
|
||||||
|
#if !defined(ACG_NO_READ_FUNCTIONS)
|
||||||
|
static inline bool acg_stream_read_pad(struct acg_stream* s) {
|
||||||
|
assert(NULL != s);
|
||||||
|
|
||||||
|
s->cursor_bits = (s->cursor_bits + 7U)/8U*8U;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
static inline bool acg_stream_read_bool(struct acg_stream* s, bool* v) {
|
||||||
|
assert(NULL != s);
|
||||||
|
assert(NULL != v);
|
||||||
|
|
||||||
|
if (s->size_bytes*8U <= s->cursor_bits) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
uint64_t* const c = &s->cursor_bits;
|
||||||
|
*v = (s->buffer[*c/8U] >> (*c%8U)) & 1U;
|
||||||
|
++*c;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
static inline bool acg_stream_read_uint(struct acg_stream* s, uint64_t* v, uint8_t unit_bits) {
|
||||||
|
assert(NULL != s);
|
||||||
|
assert(NULL != v);
|
||||||
|
assert(2U <= unit_bits);
|
||||||
|
assert(65U >= unit_bits);
|
||||||
|
|
||||||
|
*v = 0U;
|
||||||
|
|
||||||
|
const uint8_t unit_data_bits = unit_bits - 1U;
|
||||||
|
|
||||||
|
const uint8_t* const buf = s->buffer;
|
||||||
|
uint64_t* const c = &s->cursor_bits;
|
||||||
|
|
||||||
|
uint8_t v_offset_bits = 0U;
|
||||||
|
bool cont_flag = true;
|
||||||
|
|
||||||
|
while (cont_flag) {
|
||||||
|
if (s->size_bytes*8U < *c+unit_data_bits) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint8_t frag_bits = acg_util_umin((8U - *c%8U)%8U, unit_data_bits);
|
||||||
|
if (frag_bits > 0U) {
|
||||||
|
const uint64_t v_part =
|
||||||
|
(buf[*c/8U] >> (*c%8U)) & acg_util_fullbits(frag_bits);
|
||||||
|
*v |= v_part << v_offset_bits;
|
||||||
|
*c += frag_bits;
|
||||||
|
v_offset_bits += frag_bits;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint8_t remain_bits = unit_data_bits - frag_bits;
|
||||||
|
if (remain_bits > 0U) {
|
||||||
|
assert(*c%8U == 0U);
|
||||||
|
|
||||||
|
uint64_t v_part = 0U;
|
||||||
|
memcpy(&v_part, &buf[*c/8U], (remain_bits+7U)/8U);
|
||||||
|
v_part &= acg_util_fullbits(remain_bits);
|
||||||
|
|
||||||
|
*v |= v_part << v_offset_bits;
|
||||||
|
*c += remain_bits;
|
||||||
|
v_offset_bits += remain_bits;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!acg_stream_read_bool(s, &cont_flag)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
static inline bool acg_stream_read_blob(struct acg_stream* s, uint64_t* size, uint8_t** buf) {
|
||||||
|
assert(NULL != s);
|
||||||
|
assert(NULL != size);
|
||||||
|
assert(NULL != buf);
|
||||||
|
|
||||||
|
if (!acg_stream_read_uint(s, size, 8U)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!acg_stream_read_pad(s)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t* const c = &s->cursor_bits;
|
||||||
|
|
||||||
|
const uint64_t offset = *c/8U;
|
||||||
|
if (s->size_bytes < offset + *size) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*buf = &s->buffer[offset];
|
||||||
|
*c += *size *8U;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif // !defined(ACG_NO_READ_FUNCTIONS)
|
||||||
|
18
example.c
18
example.c
@ -6,10 +6,12 @@
|
|||||||
|
|
||||||
// ----
|
// ----
|
||||||
|
|
||||||
|
#define ACG_NO_READ_FUNCTIONS
|
||||||
#include "allcing.h"
|
#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);
|
assert(NULL != s);
|
||||||
|
acg_stream_write_chunk_pad(s);
|
||||||
if (s->cursor_bits < 8U) {
|
if (s->cursor_bits < 8U) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -21,11 +23,19 @@ static inline bool acg_flush(struct acg_stream* s) {
|
|||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (1U != fwrite(s->buffer, s->cursor_bits/8U, 1U, *fp)) {
|
if (1U != fwrite(s->buffer, s->cursor_bits/8U, 1U, *fp)) {
|
||||||
return false;
|
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)) {
|
if (0U != fflush(*fp)) {
|
||||||
return false;
|
return false;
|
||||||
@ -35,7 +45,7 @@ static inline bool acg_flush(struct acg_stream* s) {
|
|||||||
#undef ACG_LOC_FULL
|
#undef ACG_LOC_FULL
|
||||||
#define ACG_LOC_FULL ACG_LOC_SHORT
|
#define ACG_LOC_FULL ACG_LOC_SHORT
|
||||||
#undef ACG_FLUSH
|
#undef ACG_FLUSH
|
||||||
#define ACG_FLUSH(s) acg_flush((s))
|
#define ACG_FLUSH(s) acg_stream_flush((s))
|
||||||
|
|
||||||
struct acg_stream logstream = {
|
struct acg_stream logstream = {
|
||||||
.buffer = (uint8_t[1024U]) {0U},
|
.buffer = (uint8_t[1024U]) {0U},
|
||||||
|
103
test.c
103
test.c
@ -11,9 +11,9 @@
|
|||||||
|
|
||||||
|
|
||||||
int main(int, char**) {
|
int main(int, char**) {
|
||||||
# define STREAM(size, offset) \
|
# define STREAM(size, offset, ...) \
|
||||||
(struct acg_stream) { \
|
(struct acg_stream) { \
|
||||||
.buffer = (uint8_t[size]) {0U}, \
|
.buffer = (uint8_t[size]) {__VA_ARGS__ __VA_OPT__(,) 0U,}, \
|
||||||
.size_bytes = (size), \
|
.size_bytes = (size), \
|
||||||
.cursor_bits = (offset), \
|
.cursor_bits = (offset), \
|
||||||
}
|
}
|
||||||
@ -45,37 +45,30 @@ int main(int, char**) {
|
|||||||
/* acg_stream_write_uint / ends in a single byte */ {
|
/* acg_stream_write_uint / ends in a single byte */ {
|
||||||
struct acg_stream s = STREAM(1024U, 0U);
|
struct acg_stream s = STREAM(1024U, 0U);
|
||||||
assert(acg_stream_write_uint(&s, 7U, 4U));
|
assert(acg_stream_write_uint(&s, 7U, 4U));
|
||||||
assert(s.buffer[0U] == 0x0EU);
|
assert(s.buffer[0U] == 0x07U);
|
||||||
assert(s.cursor_bits == 4U);
|
assert(s.cursor_bits == 4U);
|
||||||
}
|
}
|
||||||
/* acg_stream_write_uint / ends in a single byte with offset */ {
|
/* acg_stream_write_uint / ends in a single byte with offset */ {
|
||||||
struct acg_stream s = STREAM(1024U, 1U);
|
struct acg_stream s = STREAM(1024U, 1U);
|
||||||
assert(acg_stream_write_uint(&s, 7U, 4U));
|
assert(acg_stream_write_uint(&s, 7U, 4U));
|
||||||
assert(s.buffer[0U] == 0x1CU);
|
assert(s.buffer[0U] == 0x0EU);
|
||||||
assert(s.cursor_bits == 5U);
|
assert(s.cursor_bits == 5U);
|
||||||
}
|
}
|
||||||
/* acg_stream_write_uint / separated data bits */ {
|
/* acg_stream_write_uint / separated data bits */ {
|
||||||
struct acg_stream s = STREAM(1024U, 6U);
|
struct acg_stream s = STREAM(1024U, 6U);
|
||||||
assert(acg_stream_write_uint(&s, 7U, 4U));
|
assert(acg_stream_write_uint(&s, 7U, 4U));
|
||||||
assert(s.buffer[0U] == 0x80U);
|
assert(s.buffer[0U] == 0xC0U);
|
||||||
assert(s.buffer[1U] == 0x03U);
|
assert(s.buffer[1U] == 0x01U);
|
||||||
assert(s.cursor_bits == 10U);
|
assert(s.cursor_bits == 10U);
|
||||||
}
|
}
|
||||||
/* acg_stream_write_uint / separated cont flag */ {
|
/* acg_stream_write_uint / separated cont flag */ {
|
||||||
struct acg_stream s = STREAM(1024U, 7U);
|
struct acg_stream s = STREAM(1024U, 7U);
|
||||||
assert(acg_stream_write_uint(&s, 7U, 4U));
|
assert(acg_stream_write_uint(&s, 7U, 4U));
|
||||||
assert(s.buffer[0U] == 0x00U);
|
assert(s.buffer[0U] == 0x80U);
|
||||||
assert(s.buffer[1U] == 0x07U);
|
assert(s.buffer[1U] == 0x03U);
|
||||||
assert(s.cursor_bits == 11U);
|
assert(s.cursor_bits == 11U);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* acg_stream_write_int */ {
|
|
||||||
struct acg_stream s = STREAM(1024U, 0U);
|
|
||||||
assert(acg_stream_write_int(&s, -1, 4U));
|
|
||||||
assert(s.buffer[0U] == 0x05U);
|
|
||||||
assert(s.cursor_bits == 5U);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* acg_stream_write_chunk_pad / without offset */ {
|
/* acg_stream_write_chunk_pad / without offset */ {
|
||||||
struct acg_stream s = STREAM(1024U, 0U);
|
struct acg_stream s = STREAM(1024U, 0U);
|
||||||
assert(acg_stream_write_chunk_pad(&s));
|
assert(acg_stream_write_chunk_pad(&s));
|
||||||
@ -88,8 +81,20 @@ int main(int, char**) {
|
|||||||
assert(s.cursor_bits == 8U);
|
assert(s.cursor_bits == 8U);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* acg_stream_write_chunk_pad / without offset */ {
|
/* acg_stream_write_chunk_blob / without offset */ {
|
||||||
struct acg_stream s = STREAM(1024U, 0U);
|
struct acg_stream s = STREAM(1024U, 0U);
|
||||||
|
assert(acg_stream_write_chunk_blob(
|
||||||
|
&s, 4U, (uint8_t[]) {0x00, 0x01, 0x02, 0x03}));
|
||||||
|
assert(s.buffer[0U] == 0x41);
|
||||||
|
assert(s.buffer[1U] == 0x00);
|
||||||
|
assert(s.buffer[2U] == 0x00);
|
||||||
|
assert(s.buffer[3U] == 0x01);
|
||||||
|
assert(s.buffer[4U] == 0x02);
|
||||||
|
assert(s.buffer[5U] == 0x03);
|
||||||
|
assert(s.cursor_bits == 48U);
|
||||||
|
}
|
||||||
|
/* acg_stream_write_chunk_blob / with offset=1 */ {
|
||||||
|
struct acg_stream s = STREAM(1024U, 1U);
|
||||||
assert(acg_stream_write_chunk_blob(
|
assert(acg_stream_write_chunk_blob(
|
||||||
&s, 4U, (uint8_t[]) {0x00, 0x01, 0x02, 0x03}));
|
&s, 4U, (uint8_t[]) {0x00, 0x01, 0x02, 0x03}));
|
||||||
assert(s.buffer[0U] == 0x82);
|
assert(s.buffer[0U] == 0x82);
|
||||||
@ -100,29 +105,65 @@ int main(int, char**) {
|
|||||||
assert(s.buffer[5U] == 0x03);
|
assert(s.buffer[5U] == 0x03);
|
||||||
assert(s.cursor_bits == 48U);
|
assert(s.cursor_bits == 48U);
|
||||||
}
|
}
|
||||||
/* acg_stream_write_chunk_pad / with offset=1 */ {
|
/* acg_stream_write_chunk_blob / with offset=4 */ {
|
||||||
struct acg_stream s = STREAM(1024U, 1U);
|
|
||||||
assert(acg_stream_write_chunk_blob(
|
|
||||||
&s, 4U, (uint8_t[]) {0x00, 0x01, 0x02, 0x03}));
|
|
||||||
assert(s.buffer[0U] == 0x04);
|
|
||||||
assert(s.buffer[1U] == 0x01);
|
|
||||||
assert(s.buffer[2U] == 0x00);
|
|
||||||
assert(s.buffer[3U] == 0x01);
|
|
||||||
assert(s.buffer[4U] == 0x02);
|
|
||||||
assert(s.buffer[5U] == 0x03);
|
|
||||||
assert(s.cursor_bits == 48U);
|
|
||||||
}
|
|
||||||
/* acg_stream_write_chunk_pad / with offset=4 */ {
|
|
||||||
struct acg_stream s = STREAM(1024U, 4U);
|
struct acg_stream s = STREAM(1024U, 4U);
|
||||||
assert(acg_stream_write_chunk_blob(
|
assert(acg_stream_write_chunk_blob(
|
||||||
&s, 4U, (uint8_t[]) {0x00, 0x01, 0x02, 0x03}));
|
&s, 4U, (uint8_t[]) {0x00, 0x01, 0x02, 0x03}));
|
||||||
assert(s.buffer[0U] == 0x20);
|
assert(s.buffer[0U] == 0x10);
|
||||||
assert(s.buffer[1U] == 0x08);
|
assert(s.buffer[1U] == 0x04);
|
||||||
assert(s.buffer[2U] == 0x00);
|
assert(s.buffer[2U] == 0x00);
|
||||||
assert(s.buffer[3U] == 0x01);
|
assert(s.buffer[3U] == 0x01);
|
||||||
assert(s.buffer[4U] == 0x02);
|
assert(s.buffer[4U] == 0x02);
|
||||||
assert(s.buffer[5U] == 0x03);
|
assert(s.buffer[5U] == 0x03);
|
||||||
assert(s.cursor_bits == 48U);
|
assert(s.cursor_bits == 48U);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* acg_stream_read_pad / without offset */ {
|
||||||
|
struct acg_stream s = STREAM(1024U, 0U);
|
||||||
|
assert(acg_stream_read_pad(&s));
|
||||||
|
assert(s.cursor_bits == 0U);
|
||||||
|
}
|
||||||
|
/* acg_stream_read_pad / with offset=1 */ {
|
||||||
|
struct acg_stream s = STREAM(1024U, 1U);
|
||||||
|
assert(acg_stream_read_pad(&s));
|
||||||
|
assert(s.cursor_bits == 8U);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* acg_stream_read_bool / with value=false */ {
|
||||||
|
struct acg_stream s = STREAM(1024U, 0U);
|
||||||
|
bool v;
|
||||||
|
assert(acg_stream_read_bool(&s, &v));
|
||||||
|
assert(v == false);
|
||||||
|
assert(s.cursor_bits == 1U);
|
||||||
|
}
|
||||||
|
/* acg_stream_read_bool / with value=true */ {
|
||||||
|
struct acg_stream s = STREAM(1024U, 0U, 0x01U);
|
||||||
|
bool v;
|
||||||
|
assert(acg_stream_read_bool(&s, &v));
|
||||||
|
assert(v == true);
|
||||||
|
assert(s.cursor_bits == 1U);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* acg_stream_read_uint / with a single unit */ {
|
||||||
|
struct acg_stream s = STREAM(1024U, 0U, 0x04U);
|
||||||
|
uint64_t v;
|
||||||
|
assert(acg_stream_read_uint(&s, &v, 4U));
|
||||||
|
assert(v == 4U);
|
||||||
|
assert(s.cursor_bits == 4U);
|
||||||
|
}
|
||||||
|
/* acg_stream_read_uint / with multi units */ {
|
||||||
|
struct acg_stream s = STREAM(1024U, 0U, 0x48U);
|
||||||
|
uint64_t v;
|
||||||
|
assert(acg_stream_read_uint(&s, &v, 4U));
|
||||||
|
assert(v == 32U);
|
||||||
|
assert(s.cursor_bits == 8U);
|
||||||
|
}
|
||||||
|
/* acg_stream_read_uint / with multi bytes */ {
|
||||||
|
struct acg_stream s = STREAM(1024U, 0U, 0x88U, 0x04U);
|
||||||
|
uint64_t v;
|
||||||
|
assert(acg_stream_read_uint(&s, &v, 4U));
|
||||||
|
assert(v == 256U);
|
||||||
|
assert(s.cursor_bits == 12U);
|
||||||
|
}
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
4
tool/CMakeLists.txt
Normal file
4
tool/CMakeLists.txt
Normal 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
135
tool/unpack.c
Normal 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;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user