summaryrefslogtreecommitdiff
path: root/kernel/lib/sv.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/lib/sv.c')
-rw-r--r--kernel/lib/sv.c247
1 files changed, 247 insertions, 0 deletions
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));
+}