Compare commits
2 Commits
d0efc01eac
...
34075fe42d
Author | SHA1 | Date | |
---|---|---|---|
34075fe42d | |||
81e46ff140 |
23
README.md
23
README.md
@ -13,6 +13,29 @@ ALLCING is a structured logging library featuring on lightweightness.
|
||||
- compact log data with simple binary format
|
||||
- completely-free license (WTFPLv2)
|
||||
|
||||
# Log Data Format
|
||||
|
||||
```
|
||||
# [TOKEN] means TOKEN is optional
|
||||
# <TOKEN> means TOKEN is constant and refer allcing.h for actual value
|
||||
|
||||
ROOT := CHUNK_BEGIN | CHUNK_END | CHUNK_CHECK
|
||||
|
||||
CHUNK_BEGIN := <ACG_CHUNK_BEGIN> [CHUNK_DATA]
|
||||
CHUNK_END := <ACG_CHUNK_END> [CHUNK_DATA]
|
||||
CHUNK_CHECK := <ACG_CHUNK_CHECK> [CHUNK_DATA]
|
||||
|
||||
CHUNK_DATA := CHUNK_PAD | CHUNK_BLOB | CHUNK_CTX | CHUNK_LOC | CHUNK_DATA
|
||||
CHUNK_PAD := <ACG_CHUNK_PAD> PAD
|
||||
CHUNK_BLOB := <ACG_CHUNK_BLOB> BLOB
|
||||
CHUNK_CTX := <ACG_CHUNK_CTX> UINT(64) UINT(16)
|
||||
CHUNK_LOC := <ACG_CHUNK_LOC> UINT(8) BLOB
|
||||
|
||||
PAD :=
|
||||
BLOB :=
|
||||
UINT(x) :=
|
||||
```
|
||||
|
||||
# License
|
||||
|
||||
Do What The Fuck You Want to Public License v2
|
||||
|
108
allcing.h
108
allcing.h
@ -7,11 +7,15 @@
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#define ACG_CHUNK_BLOB 0x00
|
||||
#define ACG_CHUNK_PAD 0x00U
|
||||
#define ACG_CHUNK_BLOB 0x01U
|
||||
#define ACG_CHUNK_CTX 0x02U
|
||||
#define ACG_CHUNK_LOC 0x03U
|
||||
#define ACG_CHUNK_BEGIN 0x04U
|
||||
#define ACG_CHUNK_END 0x05U
|
||||
#define ACG_CHUNK_CHECK 0x06U
|
||||
|
||||
#define ACG_CHUNK_BEGIN 0x01
|
||||
#define ACG_CHUNK_END 0x02
|
||||
#define ACG_CHUNK_CHECK 0x03
|
||||
#define ACG_UNITBITS_CHUNK_ID 4U
|
||||
|
||||
|
||||
static inline uint64_t acg_util_fullbits(uint8_t bits) {
|
||||
@ -29,7 +33,15 @@ struct acg_stream {
|
||||
uint64_t cursor_bits;
|
||||
};
|
||||
|
||||
static inline bool acg_stream_write_pad(struct acg_stream* s) {
|
||||
assert(NULL != s);
|
||||
|
||||
s->cursor_bits = (s->cursor_bits+7U)/8U*8U;
|
||||
return true;
|
||||
}
|
||||
static inline bool acg_stream_write_bool(struct acg_stream* s, bool v) {
|
||||
assert(NULL != s);
|
||||
|
||||
if (s->size_bytes <= s->cursor_bits) {
|
||||
return false;
|
||||
}
|
||||
@ -39,14 +51,19 @@ static inline bool acg_stream_write_bool(struct acg_stream* s, bool v) {
|
||||
return true;
|
||||
}
|
||||
static inline bool acg_stream_write_uint(struct acg_stream* s, uint64_t v, uint8_t unit_bits) {
|
||||
assert(unit_bits >= 2U);
|
||||
assert(unit_bits <= 65U);
|
||||
assert(NULL != s);
|
||||
assert(2U <= unit_bits);
|
||||
assert(65U >= unit_bits);
|
||||
|
||||
uint8_t* const buf = s->buffer;
|
||||
uint64_t* const c = &s->cursor_bits;
|
||||
|
||||
const uint8_t unit_data_bits = unit_bits - 1U;
|
||||
while (v) {
|
||||
if (s->size_bytes*8U - *c < unit_bits) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const uint64_t next_v = v >> unit_data_bits;
|
||||
acg_stream_write_bool(s, !!next_v);
|
||||
|
||||
@ -66,7 +83,80 @@ static inline bool acg_stream_write_uint(struct acg_stream* s, uint64_t v, uint8
|
||||
return true;
|
||||
}
|
||||
static inline bool acg_stream_write_int(struct acg_stream* s, int64_t v, uint8_t unit_bits) {
|
||||
assert(unit_bits > 0);
|
||||
const uint64_t uv = v >= 0? ((uint64_t) v): (~((uint64_t) -v) + 1);
|
||||
return acg_stream_write_uint(s, uv, 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_chunk_pad(struct acg_stream* s) {
|
||||
assert(NULL != s);
|
||||
|
||||
if (s->cursor_bits%8U == 0U) {
|
||||
return true;
|
||||
}
|
||||
if (s->size_bytes <= s->cursor_bits/8U) {
|
||||
return false;
|
||||
}
|
||||
return
|
||||
acg_stream_write_uint(s, ACG_CHUNK_PAD, ACG_UNITBITS_CHUNK_ID) &&
|
||||
acg_stream_write_pad(s);
|
||||
}
|
||||
static inline bool acg_stream_write_chunk_blob(struct acg_stream* s, uint64_t size_bytes, const uint8_t* buf) {
|
||||
assert(NULL != s);
|
||||
|
||||
if (!acg_stream_write_uint(s, ACG_CHUNK_BLOB, ACG_UNITBITS_CHUNK_ID)) {
|
||||
return false;
|
||||
}
|
||||
if (!acg_stream_write_uint(s, size_bytes, 8U)) {
|
||||
return false;
|
||||
}
|
||||
if (!acg_stream_write_pad(s)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint64_t* const c = &s->cursor_bits;
|
||||
|
||||
const uint64_t avail_bytes = s->size_bytes - *c/8U;
|
||||
if (avail_bytes < size_bytes) {
|
||||
return false;
|
||||
}
|
||||
memcpy(&s->buffer[*c/8], buf, size_bytes);
|
||||
|
||||
const uint64_t size_bits = size_bytes * 8U;
|
||||
*c += size_bits;
|
||||
return true;
|
||||
}
|
||||
static inline bool acg_stream_write_chunk_begin(struct acg_stream* s) {
|
||||
assert(NULL != s);
|
||||
|
||||
if (!acg_stream_write_uint(s, ACG_CHUNK_BEGIN, ACG_UNITBITS_CHUNK_ID)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
static inline bool acg_stream_write_chunk_end(struct acg_stream* s) {
|
||||
assert(NULL != s);
|
||||
|
||||
if (!acg_stream_write_uint(s, ACG_CHUNK_END, ACG_UNITBITS_CHUNK_ID)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
static inline bool acg_stream_write_chunk_check(struct acg_stream* s) {
|
||||
assert(NULL != s);
|
||||
|
||||
if (!acg_stream_write_uint(s, ACG_CHUNK_CHECK, ACG_UNITBITS_CHUNK_ID)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
72
test.c
72
test.c
@ -11,12 +11,6 @@
|
||||
|
||||
|
||||
int main(int, char**) {
|
||||
# define DEFINE_STREAM(name, offset) \
|
||||
struct acg_stream s = { \
|
||||
.buffer = (uint8_t[1024U]) {0U}, \
|
||||
.size_bytes = 1024U, \
|
||||
.cursor_bits = (offset), \
|
||||
}
|
||||
# define STREAM(size, offset) \
|
||||
(struct acg_stream) { \
|
||||
.buffer = (uint8_t[size]) {0U}, \
|
||||
@ -24,6 +18,17 @@ int main(int, char**) {
|
||||
.cursor_bits = (offset), \
|
||||
}
|
||||
|
||||
/* acg_stream_write_pad / without offset */ {
|
||||
struct acg_stream s = STREAM(1024U, 0U);
|
||||
assert(acg_stream_write_pad(&s));
|
||||
assert(s.cursor_bits == 0U);
|
||||
}
|
||||
/* acg_stream_write_pad / with offset */ {
|
||||
struct acg_stream s = STREAM(1024U, 1U);
|
||||
assert(acg_stream_write_pad(&s));
|
||||
assert(s.cursor_bits == 8U);
|
||||
}
|
||||
|
||||
/* acg_stream_write_bool / value=true */ {
|
||||
struct acg_stream s = STREAM(1024U, 0U);
|
||||
assert(acg_stream_write_bool(&s, true));
|
||||
@ -64,5 +69,60 @@ int main(int, char**) {
|
||||
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 */ {
|
||||
struct acg_stream s = STREAM(1024U, 0U);
|
||||
assert(acg_stream_write_chunk_pad(&s));
|
||||
assert(s.cursor_bits == 0U);
|
||||
}
|
||||
/* acg_stream_write_chunk_pad / with offset */ {
|
||||
struct acg_stream s = STREAM(1024U, 1U);
|
||||
assert(acg_stream_write_chunk_pad(&s));
|
||||
assert(s.buffer[0U] == 0U);
|
||||
assert(s.cursor_bits == 8U);
|
||||
}
|
||||
|
||||
/* acg_stream_write_chunk_pad / without offset */ {
|
||||
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] == 0x82);
|
||||
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_pad / with offset=1 */ {
|
||||
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);
|
||||
assert(acg_stream_write_chunk_blob(
|
||||
&s, 4U, (uint8_t[]) {0x00, 0x01, 0x02, 0x03}));
|
||||
assert(s.buffer[0U] == 0x20);
|
||||
assert(s.buffer[1U] == 0x08);
|
||||
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);
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user