create new project

This commit is contained in:
falsycat 2024-02-11 12:03:19 +09:00
parent 0cdf1b89e6
commit c0b4b34dd6
4 changed files with 186 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/build/

45
CMakeLists.txt Normal file
View 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
View 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
View 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;
}