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