feat(ltm): add file data support
ci/woodpecker/push/build Pipeline was successful
Details
ci/woodpecker/push/build Pipeline was successful
Details
parent
c7a1fec6c2
commit
53c2313953
|
@ -9,14 +9,19 @@ SRCS != find '$(SRC_DIR)' -iname '*.c'
|
|||
SRCS_H != find include -iname '*.h'
|
||||
SRCS_H_INTERNAL != find $(SRC_DIR) -iname '*.h'
|
||||
SRCS_TEST != find '$(TEST_DIR)' -iname '*.c'
|
||||
SRCS_EXAMPLE != find '$(EXAMPLE_DIR)' -iname '*.c'
|
||||
|
||||
OBJS := $(SRCS:%=$(BUILD_DIR)/%.o)
|
||||
OBJS_TEST := $(SRCS_TEST:%=$(BUILD_DIR)/%.o)
|
||||
OBJS_EXAMPLE := $(SRCS_EXAMPLE:%=$(BUILD_DIR)/%.o)
|
||||
DEPS := $(SRCS:%=$(BUILD_DIR)/%.d) $(SRCS_TEST:%=$(BUILD_DIR)/%.d)
|
||||
|
||||
BINS_TEST := $(OBJS_TEST:%.c.o=%)
|
||||
BINS_EXAMPLE := $(OBJS_EXAMPLE:%.c.o=%)
|
||||
|
||||
TARGETS_TEST := $(BINS_TEST:%=test-%)
|
||||
TARGETS_MEM_TEST := $(BINS_TEST:%=test-mem-%)
|
||||
TARGETS_EXAMPLE := $(BINS_EXAMPLE:%=test-%)
|
||||
|
||||
_CFLAGS := $(addprefix -I,$(INC_DIRS)) $(CFLAGS) -Wall -Wextra
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ LIB_FILENAME = libltm.a
|
|||
BUILD_DIR = build
|
||||
SRC_DIR = src
|
||||
TEST_DIR = test
|
||||
EXAMPLE_DIR = example
|
||||
THIRDPARTY =
|
||||
|
||||
PUB_INC_DIR = include
|
||||
|
@ -13,4 +14,4 @@ INC_DIRS = $(PUB_INC_DIR) src/_include
|
|||
# object file is also recompiled if only a header is changed.
|
||||
# -MP: generate a dummy target for every header file (according to the docs it
|
||||
# prevents some errors when removing header files)
|
||||
CFLAGS ?= -MMD -MP -g
|
||||
CFLAGS ?= -MMD -MP -g -Wall -Werror
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
#include <stdio.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "ltm/template.h"
|
||||
|
||||
const char *s = "<body><pre><code>\n"
|
||||
"{{ paste }}\n"
|
||||
"</code></pre></body>";
|
||||
|
||||
int main() {
|
||||
ltm_template *template;
|
||||
ltm_template_compile(&template, s);
|
||||
ltm_instance *instance;
|
||||
ltm_template_instantiate(&instance, template);
|
||||
|
||||
struct stat sb;
|
||||
stat("Makefile", &sb);
|
||||
|
||||
FILE *f = fopen("Makefile", "rb");
|
||||
|
||||
ltm_instance_block_add_var(instance, "paste", ltm_instance_block_type_file_owned, f, sb.st_size);
|
||||
|
||||
char buf[1024];
|
||||
size_t written = 0;
|
||||
|
||||
while (ltm_instance_write(&written, buf, 1024, instance) != ltm_err_done) {
|
||||
printf("%.*s", (int)written, buf);
|
||||
}
|
||||
|
||||
printf("%.*s", (int)written, buf);
|
||||
|
||||
ltm_instance_free(instance);
|
||||
ltm_template_free(template);
|
||||
}
|
|
@ -24,6 +24,7 @@ typedef enum ltm_err {
|
|||
ltm_err_ok = 0,
|
||||
ltm_err_invalid_template,
|
||||
ltm_err_failed_alloc,
|
||||
ltm_err_failed_io,
|
||||
ltm_err_not_found,
|
||||
ltm_err_wrong_block_type,
|
||||
ltm_err_done,
|
||||
|
|
|
@ -53,6 +53,8 @@ void ltm_instance_free(ltm_instance *instance);
|
|||
typedef enum ltm_instance_block_type {
|
||||
ltm_instance_block_type_buf = 0,
|
||||
ltm_instance_block_type_buf_owned,
|
||||
ltm_instance_block_type_file,
|
||||
ltm_instance_block_type_file_owned,
|
||||
ltm_instance_block_type_nested,
|
||||
} ltm_instance_block_type;
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "ltm/common.h"
|
||||
|
@ -41,9 +42,13 @@ void ltm_instance_free(ltm_instance *instance) {
|
|||
case ltm_instance_block_type_buf_owned:
|
||||
free(block->data.ptr);
|
||||
break;
|
||||
case ltm_instance_block_type_file_owned:
|
||||
fclose(block->data.ptr);
|
||||
break;
|
||||
case ltm_instance_block_type_nested:
|
||||
ltm_instance_free(block->data.ptr);
|
||||
break;
|
||||
case ltm_instance_block_type_file:
|
||||
case ltm_instance_block_type_buf:;
|
||||
}
|
||||
|
||||
|
@ -204,6 +209,8 @@ size_t ltm_instance_size(const ltm_instance *instance) {
|
|||
switch (block->type) {
|
||||
case ltm_instance_block_type_buf:
|
||||
case ltm_instance_block_type_buf_owned:
|
||||
case ltm_instance_block_type_file:
|
||||
case ltm_instance_block_type_file_owned:
|
||||
total += block->data.len;
|
||||
break;
|
||||
case ltm_instance_block_type_nested:
|
||||
|
@ -219,6 +226,8 @@ size_t ltm_instance_size(const ltm_instance *instance) {
|
|||
|
||||
ltm_err ltm_instance_write(size_t *written, char *buf, size_t len,
|
||||
ltm_instance *instance) {
|
||||
*written = 0;
|
||||
|
||||
while ((*written < len) && (instance->blocks.current != NULL)) {
|
||||
ltm_instance_block *current = instance->blocks.current;
|
||||
|
||||
|
@ -227,7 +236,8 @@ ltm_err ltm_instance_write(size_t *written, char *buf, size_t len,
|
|||
case ltm_instance_block_type_buf_owned: {
|
||||
size_t cap =
|
||||
LTM_MIN(current->data.len - instance->written, len - *written);
|
||||
memcpy(&buf[*written], current->data.ptr, cap);
|
||||
memcpy(&buf[*written], &((char *)current->data.ptr)[instance->written],
|
||||
cap);
|
||||
*written += cap;
|
||||
instance->written += cap;
|
||||
|
||||
|
@ -236,6 +246,24 @@ ltm_err ltm_instance_write(size_t *written, char *buf, size_t len,
|
|||
instance->written = 0;
|
||||
}
|
||||
} break;
|
||||
case ltm_instance_block_type_file:
|
||||
case ltm_instance_block_type_file_owned: {
|
||||
size_t cap =
|
||||
LTM_MIN(current->data.len - instance->written, len - *written);
|
||||
size_t read = fread(&buf[*written], 1, cap, current->data.ptr);
|
||||
|
||||
if ((read == 0) && (ferror(current->data.ptr) != 0)) {
|
||||
return ltm_err_failed_io;
|
||||
}
|
||||
|
||||
*written += read;
|
||||
instance->written += read;
|
||||
|
||||
if (instance->written == current->data.len) {
|
||||
instance->blocks.current = current->next;
|
||||
instance->written = 0;
|
||||
}
|
||||
} break;
|
||||
case ltm_instance_block_type_nested: {
|
||||
size_t nested_written = 0;
|
||||
ltm_err res = ltm_instance_write(&nested_written, &buf[*written],
|
||||
|
|
|
@ -18,10 +18,21 @@ void test_single_placeholder() {
|
|||
TEST_CHECK(ltm_instance_size(instance) == 13);
|
||||
|
||||
char buf[13];
|
||||
|
||||
size_t written = 0;
|
||||
TEST_CHECK(ltm_instance_write(&written, buf, 13, instance) == ltm_err_done);
|
||||
TEST_CHECK(written == 13);
|
||||
TEST_CHECK(ltm_instance_write(&written, buf, 5, instance) == ltm_err_ok);
|
||||
TEST_CHECK(written == 5);
|
||||
|
||||
written = 0;
|
||||
TEST_CHECK(ltm_instance_write(&written, buf + 5, 5, instance) == ltm_err_ok);
|
||||
TEST_CHECK(written == 5);
|
||||
|
||||
written = 0;
|
||||
TEST_CHECK(ltm_instance_write(&written, buf + 10, 5, instance) == ltm_err_done);
|
||||
TEST_CHECK(written == 3);
|
||||
|
||||
TEST_CHECK(strncmp(buf, "Hello, World!", 13) == 0);
|
||||
TEST_DUMP("buf", buf, 13);
|
||||
|
||||
ltm_instance_free(instance);
|
||||
ltm_template_free(template);
|
||||
|
|
Loading…
Reference in New Issue