aboutsummaryrefslogtreecommitdiff
path: root/lib/libk
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libk')
-rw-r--r--lib/libk/endian.h17
-rw-r--r--lib/libk/endian/little.c43
-rw-r--r--lib/libk/stdio.h58
-rw-r--r--lib/libk/stdio/fprintf.c11
-rw-r--r--lib/libk/stdio/printf.c11
-rw-r--r--lib/libk/stdio/vfprintf.cpp54
-rw-r--r--lib/libk/stdlib.h31
-rw-r--r--lib/libk/stdlib/linked_list_allocator.c77
-rw-r--r--lib/libk/stdlib/memcpy.c13
-rw-r--r--lib/libk/stdlib/memset.c7
-rw-r--r--lib/libk/string.h28
-rw-r--r--lib/libk/string/itoa.c30
12 files changed, 380 insertions, 0 deletions
diff --git a/lib/libk/endian.h b/lib/libk/endian.h
new file mode 100644
index 0000000..70bc5f7
--- /dev/null
+++ b/lib/libk/endian.h
@@ -0,0 +1,17 @@
+//=====================================================================
+// spdx-license-identifier: ISC
+//=====================================================================
+
+#pragma once
+
+#include <stdint.h>
+
+// These functions convert the byte encoding of integer values from host byte order to and from little-endian and
+// big-endian byte order
+uint16_t htole16(uint16_t host_16b);
+uint32_t htole32(uint32_t host_32b);
+uint64_t htole64(uint64_t host_64b);
+
+uint16_t htobe16(uint16_t host_16b);
+uint32_t htobe32(uint32_t host_32b);
+uint64_t htobe64(uint64_t host_64b);
diff --git a/lib/libk/endian/little.c b/lib/libk/endian/little.c
new file mode 100644
index 0000000..042bb55
--- /dev/null
+++ b/lib/libk/endian/little.c
@@ -0,0 +1,43 @@
+//=====================================================================
+// spdx-license-identifier: ISC
+//=====================================================================
+
+#include "endian.h"
+
+#if __BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__
+#error little.c included in build on big endian target
+#endif
+
+uint16_t
+htole16(uint16_t host_16b)
+{
+ return host_16b;
+}
+
+uint32_t
+htole32(uint32_t host_32b)
+{
+ return host_32b;
+}
+
+uint64_t
+htole64(uint64_t host_64b)
+{
+ return host_64b;
+}
+
+uint16_t
+htobe16(uint16_t host_16b)
+{
+ return __builtin_bswap16(host_16b);
+}
+uint32_t
+htobe32(uint32_t host_32b)
+{
+ return __builtin_bswap32(host_32b);
+}
+uint64_t
+htobe64(uint64_t host_64b)
+{
+ return __builtin_bswap64(host_64b);
+}
diff --git a/lib/libk/stdio.h b/lib/libk/stdio.h
new file mode 100644
index 0000000..5ef68f1
--- /dev/null
+++ b/lib/libk/stdio.h
@@ -0,0 +1,58 @@
+#pragma once
+
+#include <stdarg.h>
+
+///@defgroup libk libk
+///@{
+///@defgroup stdio stdio
+///@{
+
+#ifdef __cplusplus
+/**
+ * An object type used for streams
+ */
+struct kIoDevice {
+ /** Function that prints a character to the stream */
+ virtual void putc(char) = 0;
+ /** Function that prints a string to the stream */
+ virtual int puts(const char *, int) = 0;
+ /** Flush write buffers */
+ virtual void flush() = 0;
+};
+typedef kIoDevice FILE;
+#else
+typedef void FILE;
+#endif
+
+/** A FILE value corresponding to stdin, the keyboard buffer */
+extern FILE *stdin;
+/** A FILE value corresponding to stdout, the display */
+extern FILE *stdout;
+/** A FILE value corresponding to stderr, the uart */
+extern FILE *stderr;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+/**
+ * Write the formatted string to stdout
+ * Supports ``%s`` (string), ``%d`` (decimal), ``%u`` (unsigned), ``%x`` (hexadecimal)
+ * @return number of bytes written
+ */
+int printf(const char *restrict format, ...);
+
+/**
+ * Write the formatted string to stream; see printf
+ */
+int fprintf(FILE *restrict stream, const char *restrict format, ...);
+
+/**
+ * Write the formatted string to stream; see printf
+ */
+int vfprintf(FILE *restrict stream, const char *restrict format, va_list ap);
+#ifdef __cplusplus
+}
+#endif
+
+///@}
+///@}
diff --git a/lib/libk/stdio/fprintf.c b/lib/libk/stdio/fprintf.c
new file mode 100644
index 0000000..9a96dc6
--- /dev/null
+++ b/lib/libk/stdio/fprintf.c
@@ -0,0 +1,11 @@
+#include <stdio.h>
+
+int
+fprintf(FILE *restrict stream, const char *restrict format, ...)
+{
+ va_list ap;
+ va_start(ap, format);
+ int c = vfprintf(stream, format, ap);
+ va_end(ap);
+ return c;
+}
diff --git a/lib/libk/stdio/printf.c b/lib/libk/stdio/printf.c
new file mode 100644
index 0000000..4efc1ac
--- /dev/null
+++ b/lib/libk/stdio/printf.c
@@ -0,0 +1,11 @@
+#include <stdio.h>
+
+int
+printf(const char *restrict format, ...)
+{
+ va_list ap;
+ va_start(ap, format);
+ int c = vfprintf(stdout, format, ap);
+ va_end(ap);
+ return c;
+}
diff --git a/lib/libk/stdio/vfprintf.cpp b/lib/libk/stdio/vfprintf.cpp
new file mode 100644
index 0000000..aa9256d
--- /dev/null
+++ b/lib/libk/stdio/vfprintf.cpp
@@ -0,0 +1,54 @@
+#include <stdio.h>
+#include <string.h>
+
+static char buffer[3 * sizeof(int) + 2];
+
+extern "C" int
+vfprintf(FILE *restrict stream, const char *restrict format, va_list params)
+{
+ int written = 0;
+
+ int s = 0;
+ int l = 0;
+ for (int i = 0; format[i] != '\0'; ++i) {
+ if (format[i] == '%') {
+ written += stream->puts(&format[s], l);
+ s = i + 2;
+ ++i;
+
+ switch (format[i]) {
+ case 's': {
+ const char *arg = va_arg(params, const char *);
+ written += stream->puts(arg, -1);
+ } break;
+ case 'c': {
+ const int arg = va_arg(params, int);
+ stream->putc(arg);
+ ++written;
+ } break;
+ case 'd': {
+ const char *arg = itoa(buffer, va_arg(params, int), 10);
+ written += stream->puts(arg, -1);
+ } break;
+ case 'u': {
+ const char *arg = utoa(buffer, va_arg(params, unsigned int), 10);
+ written += stream->puts(arg, -1);
+ } break;
+ case 'x': {
+ const char *arg = utoa(buffer, va_arg(params, unsigned int), 16);
+ written += stream->puts(arg, -1);
+ } break;
+ }
+
+ l = 0;
+ }
+
+ else
+ ++l;
+ }
+
+ if (l > 0) { written += stream->puts(&format[s], l); }
+
+ stream->flush();
+ return written;
+}
diff --git a/lib/libk/stdlib.h b/lib/libk/stdlib.h
new file mode 100644
index 0000000..84d9b2d
--- /dev/null
+++ b/lib/libk/stdlib.h
@@ -0,0 +1,31 @@
+#pragma once
+
+#include <stddef.h>
+
+///@defgroup libk libk
+///@{
+///@defgroup stdlib stdlib
+///@{
+
+/**
+ * Allocate size bytes and return a pointer to the allocated memory
+ */
+void *malloc(size_t size);
+
+/**
+ * Free the memory space pointed to by ptr
+ */
+void free(void *ptr);
+
+/**
+ * Fill the first n bytes of the memory area pointed to by s with the constant byte c.
+ */
+void *memset(void *s, int c, long unsigned n);
+
+/**
+ * Copy n bytes from memory area src to memory area dest. The memory areas must not overlap.
+ */
+void *memcpy(void *restrict dest, const void *restrict src, long unsigned n);
+
+///@}
+///@}
diff --git a/lib/libk/stdlib/linked_list_allocator.c b/lib/libk/stdlib/linked_list_allocator.c
new file mode 100644
index 0000000..66c63d1
--- /dev/null
+++ b/lib/libk/stdlib/linked_list_allocator.c
@@ -0,0 +1,77 @@
+#include <stdint.h>
+#include <stdlib.h>
+
+struct Chunk {
+ struct Chunk *prev;
+ struct Chunk *next;
+ int used;
+ size_t size;
+};
+
+void
+Chunk_ctor(struct Chunk *self, size_t size)
+{
+ self->prev = NULL;
+ self->next = NULL;
+ self->used = 0;
+ self->size = size - sizeof(struct Chunk);
+}
+
+static struct Chunk *begin = NULL;
+
+void
+alloc_init(void *mem, size_t size)
+{
+ if (size < sizeof(struct Chunk)) return;
+
+ begin = (struct Chunk *)mem;
+ Chunk_ctor(begin, size);
+}
+
+void *
+malloc(size_t size)
+{
+ if (begin == NULL) return NULL;
+
+ // find free chunk that is at least (size + sizeof(struct Chunk))
+ for (struct Chunk *iter = begin; iter != NULL; iter = iter->next) {
+ if (iter->used != 0 || iter->size < size) continue;
+
+ // if there's at least sizeof(struct Chunk) bytes left over, create a new Chunk
+ if (iter->size >= (size + 2 * sizeof(struct Chunk))) {
+ struct Chunk *next = (struct Chunk *)((uintptr_t)iter + sizeof(struct Chunk) + size);
+ Chunk_ctor(next, iter->size - size - sizeof(struct Chunk));
+ next->prev = iter;
+
+ iter->size = size;
+ iter->next = next;
+ }
+
+ iter->used = 1;
+ return (void *)((uintptr_t)iter + sizeof(struct Chunk));
+ }
+
+ return NULL;
+}
+
+void
+free(void *ptr)
+{
+ if (ptr == NULL) return;
+ struct Chunk *chunk = (struct Chunk *)((uintptr_t)ptr - sizeof(struct Chunk));
+ chunk->used = 0;
+
+ // merge next chunk
+ if (chunk->next != NULL && chunk->next->used == 0) {
+ chunk->size += chunk->next->size + sizeof(struct Chunk);
+ chunk->next = chunk->next->next;
+ if (chunk->next != NULL) chunk->next->prev = chunk;
+ }
+
+ // merge into prev chunk
+ if (chunk->prev != NULL && chunk->prev->used == 0) {
+ chunk->prev->size += chunk->size + sizeof(struct Chunk);
+ chunk->prev->next = chunk->next;
+ if (chunk->next != NULL) chunk->next->prev = chunk->prev;
+ }
+}
diff --git a/lib/libk/stdlib/memcpy.c b/lib/libk/stdlib/memcpy.c
new file mode 100644
index 0000000..90470d5
--- /dev/null
+++ b/lib/libk/stdlib/memcpy.c
@@ -0,0 +1,13 @@
+void *
+memcpy(void *restrict dest, const void *restrict src, long unsigned n)
+{
+ char *pDest = (char *)dest;
+ const char *pSrc = (const char *)src;
+
+ while (n) {
+ *(pDest++) = *(pSrc++);
+ --n;
+ }
+
+ return dest;
+}
diff --git a/lib/libk/stdlib/memset.c b/lib/libk/stdlib/memset.c
new file mode 100644
index 0000000..a16bd05
--- /dev/null
+++ b/lib/libk/stdlib/memset.c
@@ -0,0 +1,7 @@
+void *
+memset(void *s, int c, long unsigned n)
+{
+ char *pDest = (char *)s;
+ for (unsigned i = 0; i < n; ++i) pDest[i] = (char)c;
+ return s;
+}
diff --git a/lib/libk/string.h b/lib/libk/string.h
new file mode 100644
index 0000000..c8196c8
--- /dev/null
+++ b/lib/libk/string.h
@@ -0,0 +1,28 @@
+#pragma once
+
+///@defgroup libk libk
+///@{
+///@defgroup string string
+///@{
+
+#define OCTAL 8
+#define DECIMAL 10
+#define HEX 16
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+/**
+ * Convert int into a string
+ */
+char *itoa(char *p, int x, int base);
+/**
+ * Convert unsigned int into a string
+ */
+char *utoa(char *p, unsigned x, int base);
+#ifdef __cplusplus
+}
+#endif
+
+///@}
+///@}
diff --git a/lib/libk/string/itoa.c b/lib/libk/string/itoa.c
new file mode 100644
index 0000000..2db9768
--- /dev/null
+++ b/lib/libk/string/itoa.c
@@ -0,0 +1,30 @@
+#include <stdbool.h>
+#include <string.h>
+
+static const char *numbers = "0123456789abcdef";
+
+char *
+utoa(char *p, unsigned x, int base)
+{
+ p += 3 * sizeof(unsigned);
+ *--p = '\0';
+
+ do {
+ *--p = numbers[x % base];
+ x /= base;
+ } while (x);
+
+ return p;
+}
+
+char *
+itoa(char *p, int x, int base)
+{
+ const bool is_negative = (x < 0);
+ if (is_negative) x = -x;
+
+ p = utoa(p, x, base);
+
+ if (is_negative) *--p = '-';
+ return p;
+}