commit 6d6bc4e5fda551d544a72e8a157c59ab9d7f9b69
parent ac47eecae739f172adfe92b99744c1f66a680c6f
Author: Yersa Nordman <finwo@pm.me>
Date: Wed, 15 May 2024 23:22:28 +0200
Added basic testing
Diffstat:
7 files changed, 138 insertions(+), 3 deletions(-)
diff --git a/.gitignore b/.gitignore
@@ -5,3 +5,5 @@
/libdtype.*
/benchmark
/test
+/.cache/
+/compile_commands.json
diff --git a/benchmark.c b/benchmark.c
@@ -1,3 +1,5 @@
+#include "src/dtype.h"
+
int main() {
return 0;
}
diff --git a/config.mk b/config.mk
@@ -1 +0,0 @@
-SRC+=__DIRNAME/src/dtype.c
diff --git a/package.ini b/package.ini
@@ -1,5 +1,8 @@
+[dependencies]
+finwo/assert=main
+tidwall/buf=master
+
[export]
-config.mk=config.mk
include/finwo/dtype.h=src/dtype.h
[package]
diff --git a/src/dtype.c b/src/dtype.c
diff --git a/src/dtype.h b/src/dtype.h
@@ -0,0 +1,78 @@
+#ifndef __FINWO_DTYPE_H__
+#define __FINWO_DTYPE_H__
+
+#include <stdio.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "tidwall/buf.h"
+
+enum dtype_typ {
+ DTYPE_NULL,
+ DTYPE_STRING,
+ DTYPE_INTEGER,
+ DTYPE_DOUBLE,
+ DTYPE_BUFFER,
+ DTYPE_UNKNOWN,
+};
+
+struct dtype_value {
+ union {
+ void *val_null;
+ char *val_string;
+ int val_integer;
+ double val_double;
+ struct buf *val_buffer;
+ void *val_unknown;
+ };
+ enum dtype_typ type;
+};
+
+#define dtype_type(x) ((x)->type)
+
+struct dtype_value * dtype_copy(const struct dtype_value *subject) {
+ struct dtype_value *output = (struct dtype_value *)calloc(1, sizeof(struct dtype_value));
+ memcpy(output, subject, sizeof(struct dtype_value));
+ if (dtype_type(output) == DTYPE_STRING) {
+ output->val_string = strdup(output->val_string);
+ } else if (dtype_type(subject) == DTYPE_BUFFER) {
+ output->val_buffer = malloc(sizeof(struct buf));
+ memcpy(output->val_buffer, subject->val_buffer, sizeof(struct buf));
+ output->val_buffer->data = malloc(output->val_buffer->cap);
+ memcpy(output->val_buffer->data, subject->val_buffer->data, subject->val_buffer->len);
+ }
+ return output;
+}
+
+#define dtype_init_null() dtype_copy(&((const struct dtype_value){ .type = DTYPE_NULL }))
+#define dtype_init_string(x) dtype_copy(&((const struct dtype_value){ .type = DTYPE_STRING , .val_string = x }))
+#define dtype_init_integer(x) dtype_copy(&((const struct dtype_value){ .type = DTYPE_INTEGER, .val_integer = x }))
+#define dtype_init_double(x) dtype_copy(&((const struct dtype_value){ .type = DTYPE_DOUBLE , .val_double = x }))
+#define dtype_init_buffer(x) dtype_copy(&((const struct dtype_value){ .type = DTYPE_BUFFER , .val_buffer = x }))
+#define dtype_init_unknown(x) dtype_copy(&((const struct dtype_value){ .type = DTYPE_UNKNOWN, .val_unknown = x }))
+
+#define dtype_buf_append(x,data,len) buf_append(x->val_buffer, data, len)
+#define dtype_buf_append_byte(x,c) buf_append_byte(x->val_buffer, c)
+#define dtype_buf_clear(x) buf_clear(x->val_buffer)
+
+#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1900)
+#define dtype_init(x) _Generic((x), \
+ char * : dtype_init_string, \
+ int : dtype_init_integer, \
+ double : dtype_init_double, \
+ void * : dtype_init_unknown, \
+ struct buf *: dtype_init_buffer \
+ )(x)
+#endif
+
+void dtype_free(struct dtype_value *subject) {
+ if (dtype_type(subject) == DTYPE_STRING) {
+ free(subject->val_string);
+ } else if (dtype_type(subject) == DTYPE_BUFFER) {
+ buf_clear((struct buf *)subject);
+ }
+ free(subject);
+}
+
+#endif // __FINWO_DTYPE_H__
diff --git a/test.c b/test.c
@@ -1,3 +1,54 @@
+#include "finwo/assert.h"
+
+#include "src/dtype.h"
+
+void test_init() {
+ struct dtype_value *subject;
+ char *str = "Hello World";
+ void *dat = strdup(str);
+ size_t datl = strlen(str)+1;
+
+ subject = dtype_init_null();
+ ASSERT("init_null returns a valid pointer", subject != NULL );
+ ASSERT("init_null returns a null value" , dtype_type(subject) == DTYPE_NULL);
+ dtype_free(subject);
+
+ subject = dtype_init_string(str);
+ ASSERT("init_string returns a valid pointer" , subject != NULL );
+ ASSERT("init_string returns the correct type" , dtype_type(subject) == DTYPE_STRING);
+ ASSERT("init_string returns a cloned value" , subject->val_string != dat );
+ ASSERT("init_string returns the correct value", !strcmp(str, subject->val_string) );
+ dtype_free(subject);
+
+ subject = dtype_init_integer(12);
+ ASSERT("init_integer returns a valid pointer" , subject != NULL );
+ ASSERT("init_integer returns the correct type" , dtype_type(subject) == DTYPE_INTEGER);
+ ASSERT("init_integer returns the correct value", subject->val_integer == 12 );
+ dtype_free(subject);
+
+ subject = dtype_init_double(12);
+ ASSERT("init_double returns a valid pointer" , subject != NULL );
+ ASSERT("init_double returns the correct type" , dtype_type(subject) == DTYPE_DOUBLE);
+ ASSERT("init_double returns the correct value", subject->val_double == 12 );
+ dtype_free(subject);
+
+ subject = dtype_init_buffer((&((struct buf){ .cap = datl, .len = datl, .data = dat })) );
+ ASSERT("init_buffer returns a valid pointer" , subject != NULL );
+ ASSERT("init_buffer returns the correct type" , dtype_type(subject) == DTYPE_BUFFER );
+ ASSERT("init_buffer returns a cloned value" , subject->val_buffer->data != dat );
+ ASSERT("init_buffer returns the correct value", !strcmp(str, subject->val_buffer->data));
+ dtype_free(subject);
+
+ subject = dtype_init_unknown(dat);
+ ASSERT("init_unknown returns a valid pointer" , subject != NULL );
+ ASSERT("init_unknown returns the correct type" , dtype_type(subject) == DTYPE_UNKNOWN);
+ ASSERT("init_unknown returns a copied value" , subject->val_unknown == dat );
+ dtype_free(subject);
+
+ ASSERT("unknown data is untouched after free", !strcmp(dat, str));
+}
+
int main() {
- return 0;
+ RUN(test_init);
+ return TEST_REPORT();
}