diff options
Diffstat (limited to 'sb.c')
-rw-r--r-- | sb.c | 88 |
1 files changed, 88 insertions, 0 deletions
@@ -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; +} + |