summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTazyFoundSoup <gardendistrict0x0@outlook.com>2026-05-22 09:43:59 +1000
committerTazyFoundSoup <gardendistrict0x0@outlook.com>2026-05-22 09:43:59 +1000
commit77aa9a3259ddfd6c64534d63424d5b0fa3010900 (patch)
tree3744ec77c3cbe164457d1e421fd4bf7dceff4c02
parent4d42b317f4970bd08f9b81fcc184fc015736ff58 (diff)
refactor: move benches to include directory
-rw-r--r--Makefile46
-rw-r--r--bench/README.md9
-rw-r--r--bench/src/format/image/png.c6
-rw-r--r--compile_commands.json54
-rw-r--r--include/bridges/stdio/stream_bridge.h2
-rw-r--r--include/tinyff/bench/bench.h (renamed from bench/bench.h)25
-rw-r--r--include/tinyff/common.h2
-rw-r--r--include/tinyff/dbg.h6
-rw-r--r--include/tinyff/result.h1
-rw-r--r--include/tinyff/stream.h5
-rw-r--r--src/bridges/stdio/stream_bridge.c2
-rw-r--r--src/dbg.c157
-rw-r--r--src/format/image/png.c16
-rw-r--r--tests/format/image/png/png_open.c2
14 files changed, 246 insertions, 87 deletions
diff --git a/Makefile b/Makefile
index ec46d90..f976e39 100644
--- a/Makefile
+++ b/Makefile
@@ -2,17 +2,18 @@ CC ?= gcc
AR ?= ar
OUTDIR = build
-BENCH_OUT = $(OUTDIR)/bench
LIB = libtinyff.a
-ALL_CFLAGS = -Wall -Wextra -Werror -std=c11 -Iinclude --coverage
+ALL_CFLAGS = -Wall -Wextra -Werror -std=c11 -Iinclude
DEBUG_FLAGS = -g -O0 -fno-omit-frame-pointer
RELEASE_FLAGS = -O2
SANFLAGS = -fsanitize=address,undefined -g -O1
+COVERAGE_FLAGS = -fprofile-instr-generate -fcoverage-mapping
+COVERAGE_LDFLAGS = -fprofile-instr-generate -fcoverage-mapping
+
SRC = $(shell find src -name "*.c")
-BENCH_SRC = $(shell find bench/src -name "*.c")
ifeq ($(USE_HOSTED),1)
ALL_CFLAGS += -DUSE_HOSTED -Iinclude/bridges
@@ -20,8 +21,7 @@ SRC += $(shell find src/bridges -name "*.c")
endif
ifeq ($(USE_BENCH),1)
-ALL_CFLAGS += -DUSE_BENCH -Ibench
-SRC += $(shell find bench/src -name "*.c")
+ALL_CFLAGS += -DUSE_BENCH
endif
OBJ = $(patsubst %.c,$(OUTDIR)/%.o,$(SRC))
@@ -37,7 +37,7 @@ $(OUTDIR)/%.o: %.c
$(CC) $(ALL_CFLAGS) $(CFLAGS) -c $< -o $@
clean:
- rm -rf $(OUTDIR) png_test coverage coverage.info .coverage
+ rm -rf $(OUTDIR) coverage coverage.info png_test bench_png
debug: CFLAGS = $(DEBUG_FLAGS)
debug: $(OUTDIR)/$(LIB)
@@ -51,26 +51,40 @@ asan: clean $(OUTDIR)/$(LIB)
test-png: clean
$(MAKE) USE_HOSTED=1 debug
- $(CC) $(ALL_CFLAGS) $(DEBUG_FLAGS) -DUSE_HOSTED tests/format/image/png/png_open.c -o $(OUTDIR)/png_test -L$(OUTDIR) -ltinyff && ./$(OUTDIR)/png_test
+ $(CC) $(ALL_CFLAGS) $(DEBUG_FLAGS) \
+ -DUSE_HOSTED \
+ tests/format/image/png/png_open.c \
+ -o $(OUTDIR)/png_test \
+ -L$(OUTDIR) -ltinyff
+ ./$(OUTDIR)/png_test
test: test-png
gdb: debug
gdb -x debug/.gdbinit $(OUTDIR)/$(TEST)
-bench: $(OUTDIR)/$(LIB)
- mkdir -p $(BENCH_OUT)
- $(CC) $(ALL_CFLAGS) $(RELEASE_FLAGS) $(BENCH_SRC) -o $(BENCH_OUT)/bench -L$(OUTDIR) -ltinyff
- $(BENCH_OUT)/bench
+bench: clean
+ $(MAKE) USE_HOSTED=1 USE_BENCH=1 release
+ $(CC) $(ALL_CFLAGS) $(RELEASE_FLAGS) \
+ -DUSE_HOSTED -DUSE_BENCH \
+ bench/src/format/image/png.c \
+ -o $(OUTDIR)/bench_png \
+ -L$(OUTDIR) -ltinyff
+ ./$(OUTDIR)/bench_png
coverage: clean
- $(MAKE) USE_HOSTED=1 debug
- $(CC) $(ALL_CFLAGS) $(DEBUG_FLAGS) -DUSE_HOSTED tests/format/image/png/png_open.c -o $(OUTDIR)/png_test -L$(OUTDIR) -ltinyff
+ $(MAKE) USE_HOSTED=1 CFLAGS="$(COVERAGE_FLAGS)" LDFLAGS="$(COVERAGE_LDFLAGS)" debug
+
+ $(CC) $(ALL_CFLAGS) $(DEBUG_FLAGS) $(COVERAGE_FLAGS) \
+ -DUSE_HOSTED \
+ tests/format/image/png/png_open.c \
+ -o $(OUTDIR)/png_test \
+ -L$(OUTDIR) -ltinyff $(COVERAGE_LDFLAGS)
+
./$(OUTDIR)/png_test || true
+
lcov --capture --directory . --output-file coverage.info
lcov --remove coverage.info '/usr/*' --output-file coverage.info --ignore-errors unused
genhtml coverage.info --output-directory coverage
- lcov --list coverage.info
- @echo ""
- @echo "HTML report generated at coverage/index.html"
+
.PHONY: all clean debug release asan test test-png gdb bench coverage \ No newline at end of file
diff --git a/bench/README.md b/bench/README.md
deleted file mode 100644
index 4016024..0000000
--- a/bench/README.md
+++ /dev/null
@@ -1,9 +0,0 @@
-# tinyff benching util
-
-This folder contains benchmarks for every format. It also contains an API which is used to make custom benches.
-
-## Structure
-
-`format/`: Contains benchmark tests for formats
-`test/`: Contains tests for common formats. These are example programs.
-`bench.c & bench.h`: The API for the making the `format/` directory. \ No newline at end of file
diff --git a/bench/src/format/image/png.c b/bench/src/format/image/png.c
deleted file mode 100644
index 016f686..0000000
--- a/bench/src/format/image/png.c
+++ /dev/null
@@ -1,6 +0,0 @@
-#include "bench.h"
-
-int main(void)
-{
-
-}
diff --git a/compile_commands.json b/compile_commands.json
index a9d21f0..163cafc 100644
--- a/compile_commands.json
+++ b/compile_commands.json
@@ -7,16 +7,16 @@
"-Werror",
"-std=c11",
"-Iinclude",
- "-Ibench",
+ "--coverage",
"-O2",
"-c",
"-o",
- "dist/src/bridges/stdio/stream_bridge.o",
+ "build/src/bridges/stdio/stream_bridge.o",
"src/bridges/stdio/stream_bridge.c"
],
"directory": "/home/watson/tinyff",
"file": "/home/watson/tinyff/src/bridges/stdio/stream_bridge.c",
- "output": "/home/watson/tinyff/dist/src/bridges/stdio/stream_bridge.o"
+ "output": "/home/watson/tinyff/build/src/bridges/stdio/stream_bridge.o"
},
{
"arguments": [
@@ -26,16 +26,16 @@
"-Werror",
"-std=c11",
"-Iinclude",
- "-Ibench",
+ "--coverage",
"-O2",
"-c",
"-o",
- "dist/src/common.o",
+ "build/src/common.o",
"src/common.c"
],
"directory": "/home/watson/tinyff",
"file": "/home/watson/tinyff/src/common.c",
- "output": "/home/watson/tinyff/dist/src/common.o"
+ "output": "/home/watson/tinyff/build/src/common.o"
},
{
"arguments": [
@@ -45,16 +45,16 @@
"-Werror",
"-std=c11",
"-Iinclude",
- "-Ibench",
+ "--coverage",
"-O2",
"-c",
"-o",
- "dist/src/stream.o",
+ "build/src/stream.o",
"src/stream.c"
],
"directory": "/home/watson/tinyff",
"file": "/home/watson/tinyff/src/stream.c",
- "output": "/home/watson/tinyff/dist/src/stream.o"
+ "output": "/home/watson/tinyff/build/src/stream.o"
},
{
"arguments": [
@@ -64,16 +64,16 @@
"-Werror",
"-std=c11",
"-Iinclude",
- "-Ibench",
+ "--coverage",
"-O2",
"-c",
"-o",
- "dist/src/dbg.o",
+ "build/src/dbg.o",
"src/dbg.c"
],
"directory": "/home/watson/tinyff",
"file": "/home/watson/tinyff/src/dbg.c",
- "output": "/home/watson/tinyff/dist/src/dbg.o"
+ "output": "/home/watson/tinyff/build/src/dbg.o"
},
{
"arguments": [
@@ -83,16 +83,16 @@
"-Werror",
"-std=c11",
"-Iinclude",
- "-Ibench",
+ "--coverage",
"-O2",
"-c",
"-o",
- "dist/src/format/image/bmp.o",
+ "build/src/format/image/bmp.o",
"src/format/image/bmp.c"
],
"directory": "/home/watson/tinyff",
"file": "/home/watson/tinyff/src/format/image/bmp.c",
- "output": "/home/watson/tinyff/dist/src/format/image/bmp.o"
+ "output": "/home/watson/tinyff/build/src/format/image/bmp.o"
},
{
"arguments": [
@@ -102,16 +102,16 @@
"-Werror",
"-std=c11",
"-Iinclude",
- "-Ibench",
+ "--coverage",
"-O2",
"-c",
"-o",
- "dist/src/format/image/png.o",
+ "build/src/format/image/png.o",
"src/format/image/png.c"
],
"directory": "/home/watson/tinyff",
"file": "/home/watson/tinyff/src/format/image/png.c",
- "output": "/home/watson/tinyff/dist/src/format/image/png.o"
+ "output": "/home/watson/tinyff/build/src/format/image/png.o"
},
{
"arguments": [
@@ -121,16 +121,16 @@
"-Werror",
"-std=c11",
"-Iinclude",
- "-Ibench",
+ "--coverage",
"-O2",
"-c",
"-o",
- "dist/src/tinyff.o",
+ "build/src/tinyff.o",
"src/tinyff.c"
],
"directory": "/home/watson/tinyff",
"file": "/home/watson/tinyff/src/tinyff.c",
- "output": "/home/watson/tinyff/dist/src/tinyff.o"
+ "output": "/home/watson/tinyff/build/src/tinyff.o"
},
{
"arguments": [
@@ -140,16 +140,16 @@
"-Werror",
"-std=c11",
"-Iinclude",
- "-Ibench",
+ "--coverage",
"-O2",
"-c",
"-o",
- "dist/src/ext/crc32.o",
+ "build/src/ext/crc32.o",
"src/ext/crc32.c"
],
"directory": "/home/watson/tinyff",
"file": "/home/watson/tinyff/src/ext/crc32.c",
- "output": "/home/watson/tinyff/dist/src/ext/crc32.o"
+ "output": "/home/watson/tinyff/build/src/ext/crc32.o"
},
{
"arguments": [
@@ -159,15 +159,15 @@
"-Werror",
"-std=c11",
"-Iinclude",
- "-Ibench",
+ "--coverage",
"-O2",
"-c",
"-o",
- "dist/src/ext/tinflate.o",
+ "build/src/ext/tinflate.o",
"src/ext/tinflate.c"
],
"directory": "/home/watson/tinyff",
"file": "/home/watson/tinyff/src/ext/tinflate.c",
- "output": "/home/watson/tinyff/dist/src/ext/tinflate.o"
+ "output": "/home/watson/tinyff/build/src/ext/tinflate.o"
}
]
diff --git a/include/bridges/stdio/stream_bridge.h b/include/bridges/stdio/stream_bridge.h
index 219b101..561fa8a 100644
--- a/include/bridges/stdio/stream_bridge.h
+++ b/include/bridges/stdio/stream_bridge.h
@@ -4,7 +4,7 @@
// Default reads for common types (just FILE for now, memory later)
size_t ff_file_read(void *ptr, size_t size, void *user);
-size_t ff_file_write(const void *ptr, size_t size, const void *user);
+size_t ff_file_write(const void *ptr, size_t size, void *user);
// Stream creation helpers
ff_stream ff_create_file_stream(FILE *f); \ No newline at end of file
diff --git a/bench/bench.h b/include/tinyff/bench/bench.h
index fc226d9..f623e0f 100644
--- a/bench/bench.h
+++ b/include/tinyff/bench/bench.h
@@ -1,9 +1,16 @@
+#ifdef USE_BENCH
+
#ifndef TINYFF_BENCH_H_
#define TINYFF_BENCH_H_
#include <time.h>
#include <tinyff/result.h>
+// Forward declarations
+typedef struct ff_ctx ff_ctx;
+ff_result ff_dprintf(ff_ctx* ctx, const char *msg, ...);
+
+
#define FF_BENCH_MAX_MARKERS 32
typedef struct ff_ctx ff_ctx;
@@ -54,4 +61,20 @@ static inline double ff_bench_seconds(const ff_bench *b) {
return (double)(b->_end - b->_start) / CLOCKS_PER_SEC;
}
-#endif // TINYFF_BENCH_H \ No newline at end of file
+static inline void ff_bench_print(ff_ctx* ctx, const ff_bench *b)
+{
+ double total_ms = (double)(b->_end - b->_start) * 1000.0 / CLOCKS_PER_SEC;
+
+ ff_dprintf(ctx, "== bench: %s ==\n", b->label);
+
+ for (int i = 0; i < b->_mcount; i++) {
+ double ms = (double)(b->markers[i].tick - b->_start) * 1000.0 / CLOCKS_PER_SEC;
+ ff_dprintf(ctx, " [%s] +%.3f ms\n", b->markers[i].label, ms);
+ }
+
+ ff_dprintf(ctx, "total: %.3f ms\n", total_ms);
+}
+
+
+#endif // TINYFF_BENCH_H
+#endif // USE_BENCH \ No newline at end of file
diff --git a/include/tinyff/common.h b/include/tinyff/common.h
index 1efe930..d4215ed 100644
--- a/include/tinyff/common.h
+++ b/include/tinyff/common.h
@@ -10,7 +10,7 @@
#ifdef USE_BENCH
-#include <bench.h>
+#include <tinyff/bench/bench.h>
#define FF_BENCH_MARK(ctx, label) \
do { \
diff --git a/include/tinyff/dbg.h b/include/tinyff/dbg.h
index 3fac931..379e6ce 100644
--- a/include/tinyff/dbg.h
+++ b/include/tinyff/dbg.h
@@ -14,13 +14,13 @@
#include <tinyff/common.h>
#include <tinyff/stream.h>
+#include <stdarg.h>
+
// Sets the debug stream. If stream is NULL, debug is disabled.
ff_result ff_set_debug_stream(ff_stream* stream, ff_ctx* ctx);
// Prints a string to the debug stream if debug is enabled.
-// Note: I removed stdarg. That crap nearly made me kill myself.
-// 0/10, would not recommend. Jokes on you though, I don't have a soul to kill.
-ff_result ff_dprintf(ff_ctx* ctx, const char *msg);
+ff_result ff_dprintf(ff_ctx* ctx, const char *msg, ...);
#endif \ No newline at end of file
diff --git a/include/tinyff/result.h b/include/tinyff/result.h
index f15af1b..f167277 100644
--- a/include/tinyff/result.h
+++ b/include/tinyff/result.h
@@ -24,6 +24,7 @@ typedef enum {
// Generic
FF_RESULT_ERROR_OUT_OF_BOUNDS,
+ FF_RESULT_ERROR_NULL_PTR,
// Media specific
diff --git a/include/tinyff/stream.h b/include/tinyff/stream.h
index 95c5884..88cea69 100644
--- a/include/tinyff/stream.h
+++ b/include/tinyff/stream.h
@@ -9,10 +9,7 @@
typedef size_t (*ff_read_cb)(void *ptr, size_t size, void *user);
-typedef size_t (*ff_write_cb)(const void *ptr, size_t size, const void *user);
-// ^
-// |
-// there clang, happy now?
+typedef size_t (*ff_write_cb)(const void *ptr, size_t size, void *user);
typedef struct {
ff_read_cb read;
diff --git a/src/bridges/stdio/stream_bridge.c b/src/bridges/stdio/stream_bridge.c
index 17a3191..09aad14 100644
--- a/src/bridges/stdio/stream_bridge.c
+++ b/src/bridges/stdio/stream_bridge.c
@@ -9,7 +9,7 @@ size_t ff_file_read(void *ptr, size_t size, void *user)
return fread(ptr, 1, size, f);
}
-size_t ff_file_write(const void *ptr, size_t size, const void *user)
+size_t ff_file_write(const void *ptr, size_t size, void *user)
{
FILE *f = (FILE *)user;
return fwrite(ptr, 1, size, f);
diff --git a/src/dbg.c b/src/dbg.c
index 5d94913..f61aa36 100644
--- a/src/dbg.c
+++ b/src/dbg.c
@@ -1,26 +1,157 @@
#include <tinyff/stream.h>
#include <tinyff/dbg.h>
+#include <stdarg.h>
+#include <stdint.h>
+
+static size_t ff_internal_itoa(int value, char* buf)
+{
+ char temp[12];
+ size_t i = 0, j = 0;
+
+ if (value == 0) {
+ buf[0] = '0';
+ return 1;
+ }
+
+ unsigned int uvalue;
+
+ if (value < 0) {
+ buf[j++] = '-';
+ uvalue = (unsigned int)(-(long)value);
+ } else {
+ uvalue = (unsigned int)value;
+ }
+
+ while (uvalue > 0) {
+ temp[i++] = (uvalue % 10) + '0';
+ uvalue /= 10;
+ }
+
+ while (i > 0) {
+ buf[j++] = temp[--i];
+ }
+
+ return j;
+}
ff_result ff_set_debug_stream(ff_stream* stream, ff_ctx* ctx)
{
- ctx->ff_debug_stream = *stream;
- ctx->ff_debug_enabled = (stream != NULL);
+ if (!ctx) return FF_RESULT_ERROR_NULL_PTR;
+
+ if (stream) {
+ ctx->ff_debug_stream = *stream;
+ ctx->ff_debug_enabled = true;
+ } else {
+ ctx->ff_debug_enabled = false;
+ }
- // TODO: Add banner back maybe
-
return FF_RESULT_OK;
}
-ff_result ff_dprintf(ff_ctx* ctx, const char *msg)
+static inline void ff_debug_flush(ff_ctx* ctx, char* buffer, size_t* idx)
+{
+ if (*idx == 0) return;
+
+ ctx->ff_debug_stream.write(
+ &ctx->ff_debug_stream,
+ *idx,
+ (uint8_t*)buffer
+ );
+
+ *idx = 0;
+}
+
+ff_result ff_dprintf(ff_ctx* ctx, const char *format, ...)
{
- if (!ctx->ff_debug_enabled){
+ if (!ctx || !ctx->ff_debug_enabled || !ctx->ff_debug_stream.write) {
return FF_RESULT_WARN_DEBUG_DISABLED;
}
-
- if (!ctx->ff_debug_stream.write){
- return FF_RESULT_WARN_DEBUG_DISABLED;
+
+ va_list args;
+ va_start(args, format);
+
+ char buffer[512];
+ size_t buf_idx = 0;
+ const char* p = format;
+
+ while (*p) {
+
+ if (buf_idx >= sizeof(buffer) - 64) {
+ ff_debug_flush(ctx, buffer, &buf_idx);
+ }
+
+ if (*p == '%') {
+ p++;
+
+ if (!*p) break;
+
+ if (*p == 's') {
+ const char* s = va_arg(args, const char*);
+ if (!s) s = "(null)";
+
+ while (*s) {
+ buffer[buf_idx++] = *s++;
+
+ if (buf_idx >= sizeof(buffer)) {
+ ff_debug_flush(ctx, buffer, &buf_idx);
+ }
+ }
+ }
+ else if (*p == 'd') {
+ int d = va_arg(args, int);
+ buf_idx += ff_internal_itoa(d, &buffer[buf_idx]);
+ }
+ else if (*p == 'u') {
+ unsigned int u = va_arg(args, unsigned int);
+ buf_idx += ff_internal_itoa((int)u, &buffer[buf_idx]);
+ }
+ else if (*p == 'l' && *(p + 1) == 'd') {
+ long d = va_arg(args, long);
+ buf_idx += ff_internal_itoa((int)d, &buffer[buf_idx]);
+ p++;
+ }
+ else if (*p == 'f') {
+ double f = va_arg(args, double);
+
+ if (f < 0) {
+ buffer[buf_idx++] = '-';
+ f = -f;
+ }
+
+ int whole = (int)f;
+ double frac = f - whole;
+
+ buf_idx += ff_internal_itoa(whole, &buffer[buf_idx]);
+
+ buffer[buf_idx++] = '.';
+
+ for (int i = 0; i < 3; i++) {
+ frac *= 10.0;
+ int digit = (int)frac;
+ buffer[buf_idx++] = '0' + digit;
+ frac -= digit;
+ }
+ }
+ else if (*p == 'c') {
+ buffer[buf_idx++] = (char)va_arg(args, int);
+ }
+ else if (*p == '%') {
+ buffer[buf_idx++] = '%';
+ }
+ else {
+ buffer[buf_idx++] = '%';
+ buffer[buf_idx++] = *p;
+ }
+ }
+ else {
+ buffer[buf_idx++] = *p;
+ }
+
+ p++;
}
-
- ctx->ff_debug_stream.write(msg, ff_strlen(msg), ctx->ff_debug_stream.user);
- return FF_RESULT_OK; // result_ok means the result is ok
-}
+
+ ff_debug_flush(ctx, buffer, &buf_idx);
+
+ va_end(args);
+ return FF_RESULT_OK;
+} \ No newline at end of file
diff --git a/src/format/image/png.c b/src/format/image/png.c
index 12080d6..d5959bc 100644
--- a/src/format/image/png.c
+++ b/src/format/image/png.c
@@ -483,10 +483,16 @@ ff_result ff_close_png(ff_ctx* ctx, ff_png_ctx *png_ctx)
ff_result ff_write_chunk(ff_stream *stream, const char *type, uint8_t *buf, size_t len)
{
- stream->write(stream, 4, type);
- stream->write(stream, 4, (uint32_t*)&len);
- stream->write(stream, len, buf);
- stream->write(stream, 4, (uint32_t*)0); // TODO: Implement actual CRC calculation (use ff_write_be32)
+ stream->write(type, 4, stream->user);
+
+ uint32_t be_len = (uint32_t)len;
+ stream->write(&be_len, 4, stream->user);
+
+ stream->write(buf, len, stream->user);
+
+ uint32_t zero_crc = 0;
+ stream->write(&zero_crc, 4, stream->user);
+
return FF_RESULT_OK;
}
@@ -495,7 +501,7 @@ ff_result ff_encode_png(ff_ctx *ctx, ff_png_ctx *png_ctx, ff_stream *stream)
FF_BENCH_START(ctx, "png");
FF_BENCH_MARK(ctx, "ff_encode_png");
- stream->write(stream, 8, PNG_SIGNATURE);
+ stream->write(stream, 8, (void *)PNG_SIGNATURE);
// TODO: Actually write the PNG data
// For now I'll void the parameters
diff --git a/tests/format/image/png/png_open.c b/tests/format/image/png/png_open.c
index 97392fb..3542ffa 100644
--- a/tests/format/image/png/png_open.c
+++ b/tests/format/image/png/png_open.c
@@ -2,6 +2,7 @@
#include <tinyff/tinyff.h>
#include <tinyff/image/png.h>
#include <bridges/stdio/stream_bridge.h>
+#include <tinyff/bench/bench.h>
#include <stdio.h>
ff_result fftest_rgb2x2(ff_ctx* ctx) {
@@ -35,6 +36,7 @@ ff_result fftest_lenna256(ff_ctx* ctx) {
fclose(file);
ff_close_png(ctx, png_ctx);
+ ff_bench_print(ctx, &(ctx)->bench);
return res;
}