aboutsummaryrefslogtreecommitdiff
path: root/sys/base/string.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/base/string.c')
-rw-r--r--sys/base/string.c386
1 files changed, 0 insertions, 386 deletions
diff --git a/sys/base/string.c b/sys/base/string.c
deleted file mode 100644
index 1ef9068..0000000
--- a/sys/base/string.c
+++ /dev/null
@@ -1,386 +0,0 @@
-#include <u.h>
-#include <base.h>
-
-#define MAX_STRING_ALLOC 1024 * 1024
-
-typedef struct Hdr
-{
- vlong len;
- vlong cap;
- byte buf[];
-} Hdr;
-
-// -------------------------------------------------------------------------
-// Dynamic string functions
-
-// New returns a new dynamic string object, initialized from the given C string.
-// len defines the length of the C substring that we will copy into our buffer.
-// The backing buffer will have capacity cap.
-string
-str·makecap(const byte *s, vlong len, vlong cap)
-{
- struct Hdr* h;
-
- h = malloc(sizeof(*h) + cap + 1);
- if (s == nil) memset(h, 0, sizeof(*h));
-
- if (h == nil) return nil; // Allocation failed.
-
- h->len = (s == nil) ? 0 : len;
- h->cap = cap;
-
- if (cap < h->len) goto cleanup;
-
- if (s != nil && cap > 0) {
- memcpy(h->buf, s, h->len);
- memset(h->buf + h->len, '\0', h->cap - h->len + 1);
- }
-
- return h->buf;
-
-cleanup:
- free(h);
- panicf("Attempted to create a string with less capacity than length");
- return nil;
-}
-
-// New returns a new dynamic string object, initialized from the given C string.
-// The backing buffer capacity is equivalent to the string length.
-string
-str·makelen(const byte *s, vlong len)
-{
- vlong sl = (!s) ? 0 : strlen(s);
- if (sl < len) panicf("attempted to take a bigger substring than string length");
-
- vlong cap = (len == 0) ? 1 : len;
- return str·makecap(s, len, cap);
-}
-
-// New returns a new dynamic string object, initialized from the given C string.
-// The backing buffer capacity is equivalent to the string length.
-string
-str·make(const byte *s)
-{
- vlong len = (!s) ? 0 : strlen(s);
- return str·makelen(s, len);
-}
-
-// Newf returns a new dynamic string object
-string
-str·makef(const byte *fmt, ...)
-{
- vlong n;
- string s;
- va_list args;
-
- va_start(args, fmt);
- n = vsnprintf(nil, 0, fmt, args);
- va_end(args);
-
- s = str·makecap(nil, 0, n);
-
- va_start(args, fmt);
- vsnprintf(s, n + 1, fmt, args);
- va_end(args);
-
- Hdr* h = (Hdr*)(s - sizeof(Hdr));
- h->len = n;
-
- return s;
-}
-
-// Free returns memory associated to the buffer.
-void
-str·free(string s)
-{
- free(s - sizeof(Hdr));
-}
-
-// Len returns the length of the string.
-int
-str·len(const string s)
-{
- Hdr* h = (Hdr*)(s - sizeof(Hdr));
- return h->len;
-}
-
-// Cap returns the capacity of the string buffer.
-int
-str·cap(const string s)
-{
- Hdr* h = (Hdr*)(s - sizeof(Hdr));
- return h->cap;
-}
-
-void
-str·clear(string *s)
-{
- Hdr* h = (Hdr*)(*s - sizeof(Hdr));
- h->len = 0;
- *s[0] = '\0';
-}
-
-// Grow ensures that the string can encompass AT LEAST delta bytes.
-// If it already can, this is a NO OP.
-// If it can't, the string will be reallocated.
-void
-str·grow(string *s, vlong delta)
-{
- Hdr *h, *newh;
- vlong cap = str·cap(*s);
- vlong len = str·len(*s);
- assert(cap >= len); // To prevent unsigned behavior
-
- if (cap - len >= delta) return;
-
- h = (Hdr*)(*s - sizeof(Hdr));
-
- vlong newCap = cap + delta;
- assert(newCap >= cap); // To prevent unsigned behavior
- if (newCap < MAX_STRING_ALLOC) {
- newCap *= 2;
- } else
- newCap += MAX_STRING_ALLOC;
-
- newh = (Hdr*)realloc(h, sizeof(*h) + newCap + 1);
- if (newh == nil) return;
-
- memset(newh->buf + len, '\0', newCap - len);
- newh->cap = newCap;
- newh->len = len;
-
- *s = newh->buf;
-}
-
-// Fit reallocates the string such that the buffer is exactly sized for the
-// buffer. If the capacity equals the length, then the function is a NOOP. The
-// byte array is unchanged.
-void
-str·fit(string *s)
-{
- Hdr* h;
- vlong cap = str·cap(*s);
- vlong len = str·len(*s);
-
- if (cap == len) return;
-
- h = (Hdr*)(s - sizeof(Hdr));
- h = realloc(h, sizeof(*h) + len + 1);
- h->cap = len;
-
- *s = h->buf;
-}
-
-// Append will append the given null terminated C string to the string data
-// structure. This variant can append a substring of length len of the given
-// string to our buffer. The result is reallocated if not enough room is present
-// in the buffer.
-int
-str·appendlen(string *s, vlong n, const byte* b)
-{
- /*
- bl = strlen(b);
- if (n > bl) panicf("attempted to make a substring longer than string");
- */
-
- str·grow(s, n);
- if (*s == nil) return 0;
-
- Hdr* h = (Hdr*)(*s - sizeof(Hdr));
-
- memcpy(*s + str·len(*s), b, n);
- h->len += n;
- (*s)[h->len] = '\0';
-
- return n;
-}
-
-// Append will append the given null terminated C string to the string data
-// structure. This variant will append the entire string.
-int
-str·append(string *s, const byte* b)
-{
- return str·appendlen(s, strlen(b), b);
-}
-
-// AppendByte will append the given byte to our string.
-// NOTE: As the byte is on the stack, it is not null-terminated.
-// Can not pass to the above functions.
-int
-str·appendbyte(string *s, const byte b)
-{
- str·grow(s, 1);
- if (*s == nil) return 0;
-
- Hdr* h = (Hdr*)(*s - sizeof(Hdr));
-
- *(*s + str·len(*s)) = b;
- h->len++;
- (*s)[h->len] = '\0'; // NOTE: I don't think an explicit zero is required..?
-
- return 1;
-}
-
-/*
- * Appendf will append the given formatted string to our buffer.
- * Returns the newly minted string
- */
-
-int
-str·appendf(string *s, const byte* fmt, ...)
-{
- va_list args;
- va_start(args, fmt);
- int remain = str·cap(*s) - str·len(*s);
- int n = vsnprintf(*s + str·len(*s), remain + 1, fmt, args);
- va_end(args);
-
- if (n > remain) {
- // If the first write was incomplete, we overwite the data again.
- str·grow(s, n);
- va_list args;
- va_start(args, fmt);
- n = vsnprintf(*s + str·len(*s), n + 1, fmt, args);
- assert(n - remain <= str·cap(*s));
- va_end(args);
- }
-
- Hdr* h = (Hdr*)(*s - sizeof(Hdr));
- h->len += n;
-
- return n;
-}
-
-// Equals returns true if string s and t are equivalent.
-bool
-str·equals(const string s, const string t)
-{
- vlong sL = str·len(s);
- vlong tL = str·len(t);
- if (sL != tL) return false;
-
- return memcmp(s, t, sL) == 0;
-}
-
-//------------------------------------------------------------------------
-// Utility Methods
-
-int
-str·read(string s, int size, int n, void *buf)
-{
- int len;
-
- len = MIN(n * size, str·len(s));
- memcpy(buf, s, len);
-
- return len;
-}
-
-// Find will find the first occurence of
-// substr in the string Returns -1 if nothing was found.
-int
-str·find(string s, const byte* substr)
-{
- byte* loc = strstr(s, substr);
- if (loc == nil) return -1;
- return (int)(loc - s);
-}
-
-//
-// Lower will force all runes in the string to be lowercase.
-void
-str·lower(string s)
-{
- byte *b, *e;
- b = s;
- e = b + str·len(s);
- while (b++ != e)
- *b = tolower(*b);
-}
-
-// Upper will force all runes in the string to be uppercase.
-void
-str·upper(string s)
-{
- byte *b, *e;
- b = s;
- e = b + str·len(s);
- while (b++ != e)
- *b = toupper(*b);
-}
-
-// Replace will replace all occurences of the given bytes 'from' to bytes 'to'
-// Edits are done in place and modify the string.
-// NOTE: As of now strings from and to must be the same size.
-void
-str·replace(string s, const byte* from, const byte* to)
-{
- vlong fromL = strlen(from);
- vlong toL = strlen(to);
- if (toL != fromL) { panicf("different sized replacement string not supported"); }
-
- vlong l = str·len(s);
- vlong i = l;
- vlong j = l;
-
- for (i = 0; i < l; i++) {
- for (j = 0; j < toL; j++) {
- if (s[i] == from[j]) {
- s[i] = to[j];
- break;
- }
- }
- }
-}
-
-// Split will split the string by the given token.
-// Returns a stretchy buffer of strings that result from the partition.
-// It is the caller's responsibility to clean the memory.
-string*
-str·split(string s, const byte* tok)
-{
- string* fields = nil;
- vlong start = 0;
-
- vlong sL = str·len(s);
- vlong tokL = strlen(tok);
- if (sL == 0 || tokL == 0) return nil;
-
- buffit(fields, 5);
-
- for (vlong i = 0; i < sL - tokL; i++) {
- if ((tokL == 1 && s[i] == tokL) || !memcmp(s + i, tok, tokL)) {
- bufpush(fields, str·makelen(s + start, i - start));
- if (fields[buflen(fields) - 1] == nil) goto cleanup;
-
- start = i + tokL;
- i += tokL - 1;
- }
- }
-
- bufpush(fields, str·makelen(s + start, sL - start));
-
- return fields;
-
-cleanup:
- for (vlong i = 0; i < buflen(fields); i++) {
- str·free(fields[i]);
- }
- buffree(fields);
- return nil;
-}
-
-string
-str·join(vlong len, byte** fields, const byte* sep)
-{
- string s = str·makecap("", 0, 10);
- int j = 0;
-
- for (j = 0; j < len; j++) {
- str·append(&s, fields[j]);
- if (j < len - 1)
- str·appendlen(&s, 1, sep);
- }
-
- return s;
-}