aboutsummaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authornodist <kevin.comas.git@gmail.com>2026-10-06 17:13:01 -0400
committernodist <kevin.comas.git@gmail.com>2026-10-06 17:13:01 -0400
commit7bd050ccf74222e1b659f2fd6826a86e6afbcc94 (patch)
tree30bae9ca5dd110f32cd4abb10d42ea4d872b4d82 /include
parentde65adbc1b2d1b3efdbe6a023bb7435f84b2f3a7 (diff)
basic tests
Diffstat (limited to 'include')
-rw-r--r--include/README12
-rw-r--r--include/kpl.h9
-rw-r--r--include/kpl/base.h33
-rw-r--r--include/kpl/class.h34
-rw-r--r--include/kpl/color.h120
-rw-r--r--include/kpl/object.h33
-rw-r--r--include/kpl/runtime.h52
-rw-r--r--include/kpl/tree.h61
-rw-r--r--include/kpl_test.h69
9 files changed, 423 insertions, 0 deletions
diff --git a/include/README b/include/README
new file mode 100644
index 0000000..6800f87
--- /dev/null
+++ b/include/README
@@ -0,0 +1,12 @@
+Header Files
+
+---
+
+Includes:
+
+Only include one of these files in the source
+
+kpl.h # For the main kpl application
+kpl_test.h # For Testing
+
+---
diff --git a/include/kpl.h b/include/kpl.h
new file mode 100644
index 0000000..913edb7
--- /dev/null
+++ b/include/kpl.h
@@ -0,0 +1,9 @@
+/*
+ * This is the only header included in any c source file
+ */
+
+#pragma once
+
+#include "kpl/runtime.h"
+
+#define KPL_VERSION "0.0.0"
diff --git a/include/kpl/base.h b/include/kpl/base.h
new file mode 100644
index 0000000..144fd51
--- /dev/null
+++ b/include/kpl/base.h
@@ -0,0 +1,33 @@
+/*
+ * The header for headers included in kpl.h
+ */
+
+#pragma once
+
+// System includes
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+#include <ctype.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/uio.h>
+#include <linux/fs.h>
+#include <linux/io_uring.h>
+// KPL includes
+#include "color.h"
+#include "class.h"
+#include "object.h"
+#include "tree.h"
+
+typedef enum : int32_t {
+ KPL_EXIT_CODE_SUCCESS = 0,
+ KPL_EXIT_CODE_ERROR = 1
+} kpl_exit_code;
diff --git a/include/kpl/class.h b/include/kpl/class.h
new file mode 100644
index 0000000..b1b7054
--- /dev/null
+++ b/include/kpl/class.h
@@ -0,0 +1,34 @@
+/*
+ * The kpl class a 64bit value with an table of functions
+ */
+
+typedef uint8_t kpl_utf8[4];
+
+typedef union {
+ uint8_t u8;
+ int8_t i8;
+ uint16_t u16;
+ int16_t i16;
+ uint32_t u32;
+ int32_t i32;
+ uint64_t u64;
+ int64_t i64;
+ kpl_utf8 utf8;
+ float f32;
+ double f64;
+ void *ptr;
+} kpl_value;
+
+typedef struct {
+ kpl_value value;
+ int64_t tag;
+} kpl_result;
+
+typedef struct {
+// TODO KPL INTERFACE
+} kpl_interface;
+
+typedef struct {
+ kpl_value value;
+ kpl_interface *interface;
+} kpl_class;
diff --git a/include/kpl/color.h b/include/kpl/color.h
new file mode 100644
index 0000000..dc7fe20
--- /dev/null
+++ b/include/kpl/color.h
@@ -0,0 +1,120 @@
+/*
+ * Colors for pretty printing
+ */
+
+#pragma once
+
+#define KPL_COLOR_CONCAT(COLOR) KPL_COLOR_ ## COLOR
+
+#ifndef KPL_COLOR_OFF
+
+#define KPL_COLOR(A) "\e[" KPL_COLOR_CONCAT(A) "m"
+#define KPL_COLOR2(A, B) "\e[" KPL_COLOR_CONCAT(A) ";" KPL_COLOR_CONCAT(B) "m"
+#define KPL_COLOR3(A, B, C) "\e[" KPL_COLOR_CONCAT(A) ";" KPL_COLOR_CONCAT(B) ";" KPL_COLOR_CONCAT(C) "m"
+
+#define KPL_COLOR_RESET "0"
+#define KPL_COLOR_BOLD "1"
+#define KPL_COLOR_FAINT "2"
+#define KPL_COLOR_ITALIC "3"
+#define KPL_COLOR_UNDERLINE "4"
+#define KPL_COLOR_BLINK "5"
+#define KPL_COLOR_REVERSE "7"
+#define KPL_COLOR_HIDDEN "8"
+#define KPL_COLOR_RESET_BOLD "21"
+#define KPL_COLOR_RESET_FAINT "22"
+#define KPL_COLOR_RESET_ITALIC "23"
+#define KPL_COLOR_RESET_UNDERLINE "24"
+#define KPL_COLOR_RESET_BLINK "25"
+#define KPL_COLOR_RESET_REVERSE "27"
+#define KPL_COLOR_RESET_HIDDEN "28"
+#define KPL_COLOR_BLACK "30"
+#define KPL_COLOR_RED "31"
+#define KPL_COLOR_GREEN "32"
+#define KPL_COLOR_YELLOW "33"
+#define KPL_COLOR_BLUE "34"
+#define KPL_COLOR_MAGENTA "35"
+#define KPL_COLOR_CYAN "36"
+#define KPL_COLOR_GREY "37"
+#define KPL_COLOR_DEFAULT "39"
+#define KPL_COLOR_BG_BLACK "30"
+#define KPL_COLOR_BG_RED "41"
+#define KPL_COLOR_BG_GREEN "42"
+#define KPL_COLOR_BG_YELLOW "43"
+#define KPL_COLOR_BG_BLUE "44"
+#define KPL_COLOR_BG_MAGENTA "45"
+#define KPL_COLOR_BG_CYAN "46"
+#define KPL_COLOR_BG_GREY "47"
+#define KPL_COLOR_DARK_GREY "90"
+#define KPL_COLOR_LIGHT_RED "91"
+#define KPL_COLOR_LIGHT_GREEN "92"
+#define KPL_COLOR_LIGHT_YELLOW "93"
+#define KPL_COLOR_LIGHT_BLUE "94"
+#define KPL_COLOR_LIGHT_MAGENTA "95"
+#define KPL_COLOR_LIGHT_CYAN "96"
+#define KPL_COLOR_WHITE "97"
+#define KPL_COLOR_BG_DARK_GREY "100"
+#define KPL_COLOR_BG_LIGHT_RED "101"
+#define KPL_COLOR_BG_LIGHT_GREEN "102"
+#define KPL_COLOR_BG_LIGHT_YELLOW "103"
+#define KPL_COLOR_BG_LIGHT_BLUE "104"
+#define KPL_COLOR_BG_LIGHT_MAGENTA "105"
+#define KPL_COLOR_BG_LIGHT_CYAN "106"
+#define KPL_COLOR_BG_WHITE "107"
+
+#else
+
+#define KPL_COLOR(A) KPL_COLOR_CONCAT(A)
+#define KPL_COLOR2(A, B) KPL_COLOR_CONCAT(A) KPL_COLOR_CONCAT(B)
+#define KPL_COLOR3(A, B, C) KPL_COLOR_CONCAT(A) KPL_COLOR_CONCAT(B) KPL_COLOR_CONCAT(C)
+
+
+#define KPL_COLOR_RESET ""
+#define KPL_COLOR_BOLD ""
+#define KPL_COLOR_FAINT ""
+#define KPL_COLOR_ITALIC ""
+#define KPL_COLOR_UNDERLINE ""
+#define KPL_COLOR_BLINK ""
+#define KPL_COLOR_REVERSE ""
+#define KPL_COLOR_HIDDEN ""
+#define KPL_COLOR_RESET_BOLD ""
+#define KPL_COLOR_RESET_FAINT ""
+#define KPL_COLOR_RESET_ITALIC ""
+#define KPL_COLOR_RESET_UNDERLINE ""
+#define KPL_COLOR_RESET_BLINK ""
+#define KPL_COLOR_RESET_REVERSE ""
+#define KPL_COLOR_RESET_HIDDEN ""
+#define KPL_COLOR_BLACK ""
+#define KPL_COLOR_RED ""
+#define KPL_COLOR_GREEN ""
+#define KPL_COLOR_YELLOW ""
+#define KPL_COLOR_BLUE ""
+#define KPL_COLOR_MAGENTA ""
+#define KPL_COLOR_CYAN ""
+#define KPL_COLOR_GREY ""
+#define KPL_COLOR_DEFAULT ""
+#define KPL_COLOR_BG_BLACK ""
+#define KPL_COLOR_BG_RED ""
+#define KPL_COLOR_BG_GREEN ""
+#define KPL_COLOR_BG_YELLOW ""
+#define KPL_COLOR_BG_BLUE ""
+#define KPL_COLOR_BG_MAGENTA ""
+#define KPL_COLOR_BG_CYAN ""
+#define KPL_COLOR_BG_GREY ""
+#define KPL_COLOR_DARK_GREY ""
+#define KPL_COLOR_LIGHT_RED ""
+#define KPL_COLOR_LIGHT_GREEN ""
+#define KPL_COLOR_LIGHT_YELLOW ""
+#define KPL_COLOR_LIGHT_BLUE ""
+#define KPL_COLOR_LIGHT_MAGENTA ""
+#define KPL_COLOR_LIGHT_CYAN ""
+#define KPL_COLOR_WHITE ""
+#define KPL_COLOR_BG_DARK_GREY ""
+#define KPL_COLOR_BG_LIGHT_RED ""
+#define KPL_COLOR_BG_LIGHT_GREEN ""
+#define KPL_COLOR_BG_LIGHT_YELLOW ""
+#define KPL_COLOR_BG_LIGHT_BLUE ""
+#define KPL_COLOR_BG_LIGHT_MAGENTA ""
+#define KPL_COLOR_BG_LIGHT_CYAN ""
+#define KPL_COLOR_BG_WHITE ""
+
+#endif
diff --git a/include/kpl/object.h b/include/kpl/object.h
new file mode 100644
index 0000000..0f54a5e
--- /dev/null
+++ b/include/kpl/object.h
@@ -0,0 +1,33 @@
+/*
+ * KPL specific objects
+ */
+
+#pragma once
+
+// for atomic linked list queue
+// size in bytes, index on the kpl_threads array
+#define KPL_OBJECT_HEADER(STRUCT_NAME) \
+ struct STRUCT_NAME *_Atomic queue_next; \
+ int32_t obj_size, thread_id
+
+typedef struct _kpl_object {
+ KPL_OBJECT_HEADER(_kpl_object);
+} kpl_object; // all kpl objects allocated by the kpl allocator extend this header
+
+typedef struct {
+ kpl_object *_Atomic head, *tail; // head is modified with atomic exchange
+ struct {
+ kpl_object *_Atomic queue_next;
+ } dummy; // head and tail are never null will always point to this
+} kpl_object_queue; // atomic linked list queue any thread can add, only owner thread can remove
+
+typedef struct _kpl_task kpl_task;
+
+typedef struct _kpl_env kpl_env;
+
+typedef void kpl_task_fn(kpl_task *task, kpl_env *env);
+
+typedef struct _kpl_task {
+ KPL_OBJECT_HEADER(_kpl_task);
+ // TODO
+} kpl_task;
diff --git a/include/kpl/runtime.h b/include/kpl/runtime.h
new file mode 100644
index 0000000..2adf402
--- /dev/null
+++ b/include/kpl/runtime.h
@@ -0,0 +1,52 @@
+/*
+ * KPL allocators, io and threading
+ */
+
+#pragma once
+
+#include "base.h"
+
+typedef enum : uint8_t {
+ KPL_MEMORY_ALLOCATOR_MIN_POW2 = 7,
+ KPL_MEMORY_ALLOCATOR_MAX_POW2 = 30
+} kpl_memory_allocator_enum;
+
+/*
+ * All allocations are rounded to the next power of two at lest to a min or error if over max
+ * Each power of two has a bucket in the memory pool for reuse
+ */
+typedef struct {
+// TODO MEMORY ALLOCATOR
+} kpl_memory_allocator;
+
+typedef enum : uint8_t {
+ KPL_MEMORY_POOL_COUNT = 31
+} kpl_memory_pool_enum;
+
+// TODO IO URING
+
+// TODO JIT ALLOCATOR
+
+typedef struct {
+ kpl_memory_allocator allocator;
+ kpl_object_queue memory_pools[KPL_MEMORY_POOL_COUNT]; // each index represents 2 ** INDEX size in bytes
+ // TODO io_uring
+ // TODO jit allocator
+ _Atomic ssize_t priority; // running + the total number of tasks in threads queue, lower is higher priority
+ kpl_object_queue task_queue;
+ pthread_t pthread; // not used for main thread
+ sem_t sem; // wait when no task queue and io queue is empty
+} kpl_thread;
+
+typedef enum : int32_t {
+ KPL_THREAD_DETERIMINE_COUNT = -1,
+ KPL_THREAD_MAIN_ID = 0
+} kpl_thread_enum;
+
+typedef struct _kpl_env {
+ int32_t thread_count; // -1 updates this value to max possible, 0 invalid, >= 1 for specific number
+ _Atomic ssize_t total_priority; // the sum of the threads priority fields, application stops on zero
+ kpl_thread *thread_array; // 0 is main thread, >= 1 are spawned pthreads
+ kpl_tree *namespace_tree, *module_tree; // *namespace_tree lookups are thread safe, *module_tree needs mutex
+ pthread_mutex_t module_tree_mutex;
+} kpl_env; // kpl state, no globals
diff --git a/include/kpl/tree.h b/include/kpl/tree.h
new file mode 100644
index 0000000..8e52524
--- /dev/null
+++ b/include/kpl/tree.h
@@ -0,0 +1,61 @@
+/*
+ * KPL tree
+ */
+
+#pragma once
+
+// tree_duplicate is a linked stack
+#define KPL_TREE_HEADER(STRUCT_NAME) \
+ struct STRUCT_NAME *tree_left, *tree_right, *tree_duplicate; \
+ int32_t tree_height
+
+/*
+ * Recursive AVL saves 8 bytes per object (no need for parent pointer) and keeps the insertion and finding simple
+ */
+typedef struct _kpl_tree_node {
+ KPL_TREE_HEADER(_kpl_tree_node);
+} kpl_tree_node;
+
+typedef enum : int32_t {
+ KPL_TREE_TREE_HEIGHT_INIT = 1
+} kpl_tree_enum;
+
+/*
+ * -1 search left, 1 search right, 0 found
+ */
+typedef int32_t kpl_tree_node_compare_fn(const void *node_a, const void *node_b);
+
+typedef void kpl_tree_node_free_fn(void *node);
+
+/*
+ * KPL needs tree with insertion and find operations, deletion is not needed, all nodes are freed on tree free
+ */
+typedef struct {
+ kpl_tree_node *root_node;
+ kpl_tree_node_compare_fn *node_compare_fn;
+ kpl_tree_node_free_fn *node_free_fn;
+} kpl_tree;
+
+#define KPL_TREE_INIT_STATIC(COMPARE_FN, FREE_FN) \
+ (kpl_tree) { .root_node = NULL, .node_compare_fn = COMPARE_FN, .node_free_fn = FREE_FN }
+
+inline void kpl_tree_init(kpl_tree *tree, kpl_tree_node_compare_fn node_compare_fn,
+ kpl_tree_node_free_fn node_free_fn) {
+ tree->root_node = NULL;
+ tree->node_compare_fn = node_compare_fn;
+ tree->node_free_fn = node_free_fn;
+}
+
+void kpl_tree_free(kpl_tree *tree);
+
+/*
+ * *find is stack allocated
+ * NULL for not found
+ */
+void *kpl_tree_find(kpl_tree *tree, const void *find_node);
+
+/*
+ * *insert is heap allocated
+ * All inserts succeed, duplicates are added to *tree_duplicate
+ */
+void kpl_tree_insert(kpl_tree *tree, void *insert_node);
diff --git a/include/kpl_test.h b/include/kpl_test.h
new file mode 100644
index 0000000..a656761
--- /dev/null
+++ b/include/kpl_test.h
@@ -0,0 +1,69 @@
+/*
+ * This is the only header included in any c test file
+ */
+
+#pragma once
+
+#include "kpl.h"
+
+typedef enum : int32_t {
+ KPL_TEST_ERROR_LINE_NUMBER_INIT = -1,
+} kpl_test_enum;
+
+typedef struct _kpl_test kpl_test;
+
+typedef void kpl_test_fn(__attribute__((unused)) kpl_test *_test);
+
+/*
+ * The kpl_test object is used to build a static singly linked list and a static tree
+ * The list is for running all tests and moving failed tests to an error linked list
+ * The tree is used for running tests by name
+ */
+typedef struct _kpl_test {
+ KPL_TREE_HEADER(_kpl_test);
+ int32_t error_line_number; // -1 line number for no error
+ struct _kpl_test *list_next;
+ const char *source_file, *name, *error_message; // static c strings only
+ kpl_test_fn *test_fn;
+} kpl_test; // Per test object, lists and trees are globals
+
+void _kpl_test_add(kpl_test *_test); // do not call outside KPL_TEST macro
+
+#define _KPL_TEST_FN_DEFINITION(NAME) static void NAME(__attribute__((unused)) kpl_test *_test)
+
+/*
+ * Each test is a static function added to the test list and tree by a static gnu constructor function
+ * The NAME becomes the function name _NAME becomes the constructor name, only one name can be used per file
+ */
+#define KPL_TEST(NAME) _KPL_TEST_FN_DEFINITION(NAME); \
+static void __attribute__((constructor)) _ ## NAME(void) { \
+ static kpl_test _test = { \
+ .tree_left = NULL, .tree_right = NULL, .tree_duplicate = NULL, \
+ .tree_height = KPL_TREE_TREE_HEIGHT_INIT, \
+ .error_line_number = KPL_TEST_ERROR_LINE_NUMBER_INIT, \
+ .list_next = NULL, \
+ .source_file = __FILE__, .name = #NAME, .error_message = NULL, \
+ .test_fn = NAME \
+ }; \
+ _kpl_test_add(&_test); \
+} \
+_KPL_TEST_FN_DEFINITION(NAME)
+
+/*
+ * MESSAGE is a static c string, sets the error fields in a test once, aborting the rest of test
+ * Can only be called within a KPL_TEST
+ */
+#define KPL_FAIL(MESSAGE) do { \
+ _test->error_line_number = __LINE__; \
+ _test->error_message = MESSAGE; \
+ return; \
+} while (0)
+
+/*
+ * CONDITION is statement evaluating to true or false, MESSAGE is a static c string, false invokes KPL_FAIL
+ * Can only be called within KPL_TEST
+ */
+#define KPL_ASSERT(CONDITION, MESSAGE) do { \
+ if (!(CONDITION)) \
+ KPL_FAIL(#CONDITION "; " MESSAGE); \
+} while (0)