create new project
This commit is contained in:
parent
0cdf1b89e6
commit
c0b4b34dd6
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
/build/
|
45
CMakeLists.txt
Normal file
45
CMakeLists.txt
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.27)
|
||||||
|
|
||||||
|
project(allcing C)
|
||||||
|
|
||||||
|
set(CMAKE_C_STANDARD 23)
|
||||||
|
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||||
|
|
||||||
|
|
||||||
|
# ---- thirdparty modules
|
||||||
|
include(CTest)
|
||||||
|
|
||||||
|
|
||||||
|
# ---- common config
|
||||||
|
add_library(allcing_config INTERFACE)
|
||||||
|
target_include_directories(allcing_config
|
||||||
|
INTERFACE
|
||||||
|
${PROJECT_SOURCE_DIR}
|
||||||
|
${NF7_GENERATED_DIR}
|
||||||
|
)
|
||||||
|
target_compile_options(allcing_config INTERFACE
|
||||||
|
$<$<CXX_COMPILER_ID:MSVC>:
|
||||||
|
/W4
|
||||||
|
$<$<CONFIG:Debug>:/WX>
|
||||||
|
>
|
||||||
|
$<$<NOT:$<CXX_COMPILER_ID:MSVC>>:
|
||||||
|
-Wall -Wextra -Wpedantic
|
||||||
|
-Wno-gnu-zero-variadic-macro-arguments
|
||||||
|
$<$<CONFIG:Debug>:-Werror>
|
||||||
|
>
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# ---- library header
|
||||||
|
add_library(allcing INTERFACE)
|
||||||
|
target_sources(allcing INTERFACE allcing.h)
|
||||||
|
target_link_libraries(allcing INTERFACE allcing_config)
|
||||||
|
|
||||||
|
|
||||||
|
# ---- test binary
|
||||||
|
if (BUILD_TESTING)
|
||||||
|
add_executable(allcing_test)
|
||||||
|
target_sources(allcing_test PRIVATE test.c)
|
||||||
|
target_link_libraries(allcing_test PRIVATE allcing)
|
||||||
|
add_test(NAME allcing_test COMMAND $<TARGET_FILE:allcing_test>)
|
||||||
|
endif()
|
72
allcing.h
Normal file
72
allcing.h
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
// No copyright
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define ACG_CHUNK_BLOB 0x00
|
||||||
|
|
||||||
|
#define ACG_CHUNK_BEGIN 0x01
|
||||||
|
#define ACG_CHUNK_END 0x02
|
||||||
|
#define ACG_CHUNK_CHECK 0x03
|
||||||
|
|
||||||
|
|
||||||
|
static inline uint64_t acg_util_fullbits(uint8_t bits) {
|
||||||
|
return (((uint64_t) 1U) << bits) - 1U;
|
||||||
|
}
|
||||||
|
static inline uint64_t acg_util_umin(uint64_t a, uint64_t b) {
|
||||||
|
return a > b? b: a;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct acg_stream {
|
||||||
|
uint8_t* buffer;
|
||||||
|
uint64_t size_bytes;
|
||||||
|
|
||||||
|
uint64_t cursor_bits;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline bool acg_stream_write_bool(struct acg_stream* s, bool v) {
|
||||||
|
if (s->size_bytes <= s->cursor_bits) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
uint64_t* const c = &s->cursor_bits;
|
||||||
|
s->buffer[*c/8U] |= (!!v) << (*c%8U);
|
||||||
|
++*c;
|
||||||
|
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);
|
||||||
|
|
||||||
|
uint8_t* const buf = s->buffer;
|
||||||
|
uint64_t* const c = &s->cursor_bits;
|
||||||
|
|
||||||
|
const uint8_t unit_data_bits = unit_bits - 1U;
|
||||||
|
while (v) {
|
||||||
|
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);
|
||||||
|
if (frag_bits > 0U) {
|
||||||
|
buf[*c/8U] |= (v & acg_util_fullbits(frag_bits)) << (*c%8U);
|
||||||
|
*c += 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);
|
||||||
|
memcpy(&buf[*c/8U], &v_part, (remain_bits + 7U) / 8U);
|
||||||
|
*c += remain_bits;
|
||||||
|
|
||||||
|
v = next_v;
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
}
|
68
test.c
Normal file
68
test.c
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
#include "allcing.h"
|
||||||
|
|
||||||
|
#ifdef NDEBUG
|
||||||
|
# undef NDEBUG // this test uses assert() macro
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
|
||||||
|
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}, \
|
||||||
|
.size_bytes = (size), \
|
||||||
|
.cursor_bits = (offset), \
|
||||||
|
}
|
||||||
|
|
||||||
|
/* acg_stream_write_bool / value=true */ {
|
||||||
|
struct acg_stream s = STREAM(1024U, 0U);
|
||||||
|
assert(acg_stream_write_bool(&s, true));
|
||||||
|
assert(s.buffer[0U] == 0x1U);
|
||||||
|
assert(s.cursor_bits == 1U);
|
||||||
|
}
|
||||||
|
/* acg_stream_write_bool / value=false */ {
|
||||||
|
struct acg_stream s = STREAM(1024U, 0U);
|
||||||
|
assert(acg_stream_write_bool(&s, false));
|
||||||
|
assert(s.buffer[0U] == 0x0U);
|
||||||
|
assert(s.cursor_bits == 1U);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* acg_stream_write_uint / ends in a single byte */ {
|
||||||
|
struct acg_stream s = STREAM(1024U, 0U);
|
||||||
|
assert(acg_stream_write_uint(&s, 7U, 4U));
|
||||||
|
assert(s.buffer[0U] == 0x0EU);
|
||||||
|
assert(s.cursor_bits == 4U);
|
||||||
|
}
|
||||||
|
/* acg_stream_write_uint / ends in a single byte with offset */ {
|
||||||
|
struct acg_stream s = STREAM(1024U, 1U);
|
||||||
|
assert(acg_stream_write_uint(&s, 7U, 4U));
|
||||||
|
assert(s.buffer[0U] == 0x1CU);
|
||||||
|
assert(s.cursor_bits == 5U);
|
||||||
|
}
|
||||||
|
/* acg_stream_write_uint / separated data bits */ {
|
||||||
|
struct acg_stream s = STREAM(1024U, 6U);
|
||||||
|
assert(acg_stream_write_uint(&s, 7U, 4U));
|
||||||
|
assert(s.buffer[0U] == 0x80U);
|
||||||
|
assert(s.buffer[1U] == 0x03U);
|
||||||
|
assert(s.cursor_bits == 10U);
|
||||||
|
}
|
||||||
|
/* acg_stream_write_uint / separated cont flag */ {
|
||||||
|
struct acg_stream s = STREAM(1024U, 7U);
|
||||||
|
assert(acg_stream_write_uint(&s, 7U, 4U));
|
||||||
|
assert(s.buffer[0U] == 0x00U);
|
||||||
|
assert(s.buffer[1U] == 0x07U);
|
||||||
|
assert(s.cursor_bits == 11U);
|
||||||
|
}
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user