aboutsummaryrefslogtreecommitdiff
path: root/sb.c
diff options
context:
space:
mode:
Diffstat (limited to 'sb.c')
-rw-r--r--sb.c88
1 files changed, 88 insertions, 0 deletions
diff --git a/sb.c b/sb.c
new file mode 100644
index 0000000..06ee8d9
--- /dev/null
+++ b/sb.c
@@ -0,0 +1,88 @@
+#include <stdlib.h>
+#include <string.h>
+
+#include "sb.h"
+
+struct sb {
+ sbnode* head;
+ sbnode* tail;
+ size_t loc;
+ size_t sz;
+};
+
+struct sbnode {
+ char* str;
+ sbnode* next;
+};
+
+sbnode* newsbnode(sbnode* prev, size_t sz){
+ sbnode* node = malloc(sizeof(sbnode)); // Allocate
+ node->str = malloc(sizeof(char)*(sz+1)); node->str[sz] = 0;
+ node->next = NULL; // Init
+ if (prev) prev->next = node; // Link
+ return node;
+}
+
+sb* newsb(size_t sz){
+ sb* out = malloc(sizeof(sb));
+ out->head = out->tail = newsbnode(NULL, sz);
+ out->sz = sz;
+ out->loc = 0;
+ return out;
+}
+
+void extendsb(sb* buf){
+ buf->sz *= 2;
+ buf->loc = 0;
+ buf->tail = newsbnode(buf->tail, buf->sz);
+}
+
+void insstr(sb* buf, char* str){
+ size_t rem = strlen(str); // remaining chars to push
+ while (rem > (buf->sz - buf->loc)){ // while buffer has less room
+ // than needed, fill the buffer with str
+ memcpy(buf->tail->str+buf->loc, str, buf->sz - buf->loc);
+ // move the string pointer by that amount
+ str += buf->sz - buf->loc;
+ // reduce the number of remaining characters by that amount
+ rem -= buf->sz - buf->loc;
+ // and add a new node, resetting buf->loc
+ extendsb(buf);
+ }
+ // copy the rest into the buffer
+ memcpy(buf->tail->str+buf->loc, str, rem);
+ // and advance buf->loc
+ buf->loc += rem;
+}
+
+sbnode* freenodenext(sbnode* node){
+ sbnode* out = node->next;
+ free(node->str);
+ free(node);
+ return out;
+}
+
+char* decompose(sb* buf){
+ // Make the last node a proper string
+ buf->tail->str[buf->loc] = 0;
+ // Start with the length of the last node
+ size_t len = 0;
+ // For every non-tail node (cur->next == NULL for it),
+ for (sbnode* cur = buf->head; cur != NULL; cur = cur->next){
+ // add the length of its string
+ len += strlen(cur->str);
+ }
+ // make a string to fit it all
+ char* str = malloc(sizeof(char)*(len+1)); str[len] = 0;
+ // and its iterator
+ char* pos = str;
+ // for every node,
+ for (sbnode* cur = buf->head; cur != NULL; cur = freenodenext(cur)){
+ size_t slen = strlen(cur->str);
+ memcpy(pos, cur->str, slen); // copy
+ pos += slen;
+ }
+ free(buf);
+ return str;
+}
+