summaryrefslogtreecommitdiff
path: root/kernel/lib
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/lib')
-rw-r--r--kernel/lib/sb.c124
-rw-r--r--kernel/lib/sb.h30
-rw-r--r--kernel/lib/sv.c247
-rw-r--r--kernel/lib/sv.h43
4 files changed, 444 insertions, 0 deletions
diff --git a/kernel/lib/sb.c b/kernel/lib/sb.c
new file mode 100644
index 0000000..3f99d95
--- /dev/null
+++ b/kernel/lib/sb.c
@@ -0,0 +1,124 @@
+#include <kmalloc.h>
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+#include <tb/sb.h>
+
+#define DEFAULT_CAPACITY 256
+
+void sb_init(struct sb *ctx) {
+ (void)sb_init_capacity(ctx, DEFAULT_CAPACITY);
+}
+
+int sb_init_capacity(struct sb *ctx, size_t starting_capacity) {
+ ctx->length = 0;
+ ctx->prebuffer = 0;
+ ctx->string = kmalloc(starting_capacity);
+ if (NULL == ctx->string) {
+ ctx->capacity = 0;
+ return 0;
+ }
+ ctx->capacity = starting_capacity;
+ return 1;
+}
+
+void sb_init_buffer(struct sb *ctx, char *buffer, size_t size) {
+ ctx->string = buffer;
+ ctx->capacity = size;
+ ctx->length = 0;
+ ctx->prebuffer = 1;
+}
+
+void sb_free(struct sb *ctx) {
+ if (ctx->prebuffer) {
+ ctx->length = 0;
+ return;
+ }
+ ctx->length = 0;
+ ctx->capacity = 0;
+ kfree(ctx->string);
+ ctx->string = NULL;
+}
+
+void sb_reset(struct sb *ctx) {
+ ctx->length = 0;
+}
+
+int sb_isempty(const struct sb *ctx) {
+ return (0 == ctx->length);
+}
+
+int sb_increase_buffer(struct sb *ctx, size_t min) {
+ if (ctx->prebuffer) {
+ return 0;
+ }
+ size_t new_capacity = ctx->capacity + max(32, min);
+ char *new_allocation = krealloc(ctx->string, new_capacity);
+ if (!new_allocation) {
+ return 0;
+ }
+
+ ctx->string = new_allocation;
+ ctx->capacity = new_capacity;
+ return 1;
+}
+
+int sb_append_char(struct sb *ctx, char c) {
+ if (1 > ctx->capacity - ctx->length) {
+ if (!sb_increase_buffer(ctx, 1)) {
+ return 0;
+ }
+ }
+ memcpy(ctx->string + ctx->length, &c, 1);
+ ctx->length++;
+ return 1;
+}
+
+int sb_delete_right(struct sb *ctx, size_t n) {
+ n = min(n, ctx->length);
+ ctx->length -= n;
+ return n;
+}
+
+int sb_append(struct sb *ctx, const char *s) {
+ size_t l = strlen(s);
+ if (l > ctx->capacity - ctx->length) {
+ if (!sb_increase_buffer(ctx, l)) {
+ return 0;
+ }
+ }
+ memcpy(ctx->string + ctx->length, s, l);
+ ctx->length += l;
+ return 1;
+}
+
+int sb_prepend_sv(struct sb *ctx, struct sv sv) {
+ return sb_prepend_buffer(ctx, sv.s, sv.length);
+}
+
+int sb_prepend_buffer(struct sb *ctx, const char *buffer, size_t length) {
+ if (length > ctx->capacity - ctx->length) {
+ if (!sb_increase_buffer(ctx, length)) {
+ return 0;
+ }
+ }
+ memmove(ctx->string + length, ctx->string, ctx->length);
+ memcpy(ctx->string, buffer, length);
+ ctx->length += length;
+ return 1;
+}
+
+int sb_append_buffer(struct sb *ctx, const char *buffer, size_t length) {
+ if (length > ctx->capacity - ctx->length) {
+ if (!sb_increase_buffer(ctx, length)) {
+ return 0;
+ }
+ }
+ memcpy(ctx->string + ctx->length, buffer, length);
+ ctx->length += length;
+ return 1;
+}
+
+int sb_append_sv(struct sb *ctx, struct sv sv) {
+ return sb_append_buffer(ctx, sv.s, sv.length);
+}
diff --git a/kernel/lib/sb.h b/kernel/lib/sb.h
new file mode 100644
index 0000000..8493997
--- /dev/null
+++ b/kernel/lib/sb.h
@@ -0,0 +1,30 @@
+#ifndef SB_H
+#define SB_H
+#include "sv.h"
+#include <stddef.h>
+#include <stdint.h>
+
+struct sb {
+ char *string;
+ size_t length;
+ size_t capacity;
+ uint8_t prebuffer;
+};
+
+struct sv;
+
+void sb_init(struct sb *ctx);
+int sb_init_capacity(struct sb *ctx, size_t starting_capacity);
+void sb_init_buffer(struct sb *ctx, char *buffer, size_t size);
+void sb_free(struct sb *ctx);
+void sb_reset(struct sb *ctx);
+int sb_isempty(const struct sb *ctx);
+int sb_append_char(struct sb *ctx, char c);
+int sb_delete_right(struct sb *ctx, size_t n);
+int sb_append(struct sb *ctx, const char *s);
+int sb_append_buffer(struct sb *ctx, const char *buffer,
+ size_t length);
+int sb_append_sv(struct sb *ctx, struct sv sv);
+int sb_prepend_sv(struct sb *ctx, struct sv sv);
+int sb_prepend_buffer(struct sb *ctx, const char *buffer, size_t length);
+#endif
diff --git a/kernel/lib/sv.c b/kernel/lib/sv.c
new file mode 100644
index 0000000..580e63a
--- /dev/null
+++ b/kernel/lib/sv.c
@@ -0,0 +1,247 @@
+#include <ctype.h>
+#include <kmalloc.h>
+#include <lib/sv.h>
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+
+struct sv sv_init(const char *s, size_t length) {
+ return (struct sv){.s = s, .length = length};
+}
+
+char *SV_TO_C(struct sv s) {
+ char *c_string = kmalloc(s.length + 1);
+ memcpy(c_string, s.s, s.length);
+ c_string[s.length] = '\0';
+ return c_string;
+}
+
+size_t sv_to_cstring_buffer(struct sv s, char *buffer, size_t length) {
+ if (0 == length || length - 1 < s.length) {
+ return s.length;
+ }
+ memcpy(buffer, s.s, s.length);
+ buffer[s.length] = '\0';
+ return s.length;
+}
+
+struct sv sv_next(struct sv s) {
+ if (0 == s.length) {
+ return s;
+ }
+ s.length--;
+ s.s++;
+ return s;
+}
+
+struct sv sv_skip_chars(const struct sv input, const char *chars) {
+ struct sv r = input;
+ for (; r.length > 0;) {
+ int found = 0;
+ const char *p = chars;
+ for (; *p; p++) {
+ if (*p == r.s[0]) {
+ r.s++;
+ r.length--;
+ found = 1;
+ break;
+ }
+ }
+ if (!found) {
+ break;
+ }
+ }
+ return r;
+}
+
+uint64_t sv_parse_unsigned_number(struct sv input, struct sv *rest) {
+ uint64_t r = 0;
+ size_t i = 0;
+ for (; i < input.length; i++) {
+ if (!isdigit(input.s[i])) {
+ break;
+ }
+ r *= 10;
+ r += input.s[i] - '0';
+ }
+ input.length -= i;
+ input.s += i;
+ if (rest) {
+ *rest = input;
+ }
+ return r;
+}
+
+struct sv sv_split_function(const struct sv input, struct sv *rest,
+ int (*function)(int)) {
+ struct sv r = {
+ .s = input.s,
+ };
+ for (size_t i = 0; i < input.length; i++) {
+ if (function(input.s[i])) {
+ r.length = i;
+ if (rest) {
+ rest->s += i;
+ rest->length -= i;
+ }
+ return r;
+ }
+ }
+
+ if (rest) {
+ rest->s = NULL;
+ rest->length = 0;
+ }
+ return input;
+}
+
+struct sv sv_split_space(const struct sv input, struct sv *rest) {
+ return sv_split_function(input, rest, isspace);
+}
+
+struct sv sv_end_split_delim(const struct sv input, struct sv *rest,
+ char delim) {
+ for (size_t i = input.length - 1; i > 0; i--) {
+ if (delim == input.s[i]) {
+ struct sv r = {
+ .s = (input.s + i),
+ .length = input.length - i,
+ };
+ if (rest) {
+ rest->s = input.s;
+ rest->length = i;
+ }
+ return r;
+ }
+ }
+
+ if (rest) {
+ rest->s = NULL;
+ rest->length = 0;
+ }
+ return input;
+}
+
+struct sv sv_split_delim(const struct sv input, struct sv *rest, char delim) {
+ struct sv r = {
+ .s = input.s,
+ };
+ for (size_t i = 0; i < input.length; i++) {
+ if (delim == input.s[i]) {
+ r.length = i;
+ if (rest) {
+ rest->s += i + 1;
+ rest->length -= (i + 1);
+ }
+ return r;
+ }
+ }
+
+ if (rest) {
+ rest->s = NULL;
+ rest->length = 0;
+ }
+ return input;
+}
+
+int sv_isempty(struct sv s) {
+ return (0 == s.length);
+}
+
+char sv_peek(struct sv s) {
+ if (0 == s.length) {
+ return '\0';
+ }
+ return s.s[0];
+}
+
+int sv_partial_eq(struct sv a, struct sv b) {
+ if (a.length < b.length) {
+ return 0;
+ }
+ for (size_t i = 0; i < b.length; i++) {
+ if (a.s[i] != b.s[i]) {
+ return 0;
+ }
+ }
+ return 1;
+}
+
+int sv_eq(struct sv a, struct sv b) {
+ if (a.length != b.length) {
+ return 0;
+ }
+ for (size_t i = 0; i < a.length; i++) {
+ if (a.s[i] != b.s[i]) {
+ return 0;
+ }
+ }
+ return 1;
+}
+
+struct sv sv_take(struct sv s, struct sv *rest, size_t n) {
+ if (s.length < n) {
+ if (rest) {
+ rest->length = 0;
+ }
+ return s;
+ }
+ s.length = n;
+ if (rest) {
+ rest->length -= n;
+ rest->s += n;
+ }
+ return s;
+}
+
+struct sv sv_take_end(struct sv s, struct sv *rest, size_t n) {
+ if (s.length < n) {
+ if (rest) {
+ rest->length = 0;
+ }
+ return s;
+ }
+ if (rest) {
+ rest->length = s.length - n;
+ }
+ s.s += (s.length - n);
+ s.length = n;
+ return s;
+}
+
+struct sv sv_trim_left(struct sv s, size_t n) {
+ if (s.length < n) {
+ s.s += s.length;
+ s.length = 0;
+ return s;
+ }
+ s.s += n;
+ s.length -= n;
+ return s;
+}
+
+struct sv sv_clone(struct sv s) {
+ struct sv new_sv;
+ new_sv.length = s.length;
+ char *new_string = kmalloc(s.length);
+ memcpy(new_string, s.s, s.length);
+ new_sv.s = new_string;
+ return new_sv;
+}
+
+char *sv_copy_to_c(struct sv s, char *out, size_t buffer_length) {
+ int copy_len = min(s.length + 1, buffer_length);
+ if (0 == copy_len) {
+ return NULL;
+ }
+ if (!out) {
+ out = kmalloc(copy_len);
+ }
+ memcpy(out, s.s, copy_len - 1);
+ out[copy_len - 1] = '\0';
+ return out;
+}
+
+struct sv sv_clone_from_c(const char *s) {
+ return sv_clone(C_TO_SV(s));
+}
diff --git a/kernel/lib/sv.h b/kernel/lib/sv.h
new file mode 100644
index 0000000..b5cb0c9
--- /dev/null
+++ b/kernel/lib/sv.h
@@ -0,0 +1,43 @@
+#ifndef SV_H
+#define SV_H
+#include "sb.h"
+#include <stddef.h>
+
+#define SB_TO_SV(_sb) \
+ (struct sv) { \
+ .s = (_sb).string, .length = (_sb).length \
+ }
+
+#define C_TO_SV(_c_string) \
+ ((struct sv){.length = strlen(_c_string), .s = (_c_string)})
+
+#define sv_length(a) ((a).length)
+
+struct sv {
+ const char *s;
+ size_t length;
+};
+
+struct sv sv_init(const char *s, size_t length);
+char *SV_TO_C(struct sv s);
+size_t sv_to_cstring_buffer(struct sv s, char *buffer, size_t length);
+struct sv sv_split_delim(const struct sv input, struct sv *rest, char delim);
+struct sv sv_end_split_delim(const struct sv input, struct sv *rest,
+ char delim);
+struct sv sv_split_space(const struct sv input, struct sv *rest);
+struct sv sv_skip_chars(const struct sv input, const char *chars);
+struct sv sv_split_function(const struct sv input, struct sv *rest,
+ int (*function)(int));
+struct sv sv_take(struct sv s, struct sv *rest, size_t n);
+struct sv sv_take_end(struct sv s, struct sv *rest, size_t n);
+struct sv sv_next(struct sv s);
+int sv_isempty(struct sv s);
+char sv_peek(struct sv s);
+int sv_eq(struct sv a, struct sv b);
+int sv_partial_eq(struct sv a, struct sv b);
+struct sv sv_trim_left(struct sv s, size_t n);
+struct sv sv_clone(struct sv s);
+struct sv sv_clone_from_c(const char *s);
+char *sv_copy_to_c(struct sv s, char *out, size_t buffer_length);
+uint64_t sv_parse_unsigned_number(struct sv input, struct sv *rest);
+#endif