#include #include #include "sb.h" struct sb { sbnode* head; sbnode* tail; size_t loc; size_t sz; }; struct sbnode { char* str; sbnode* next; }; static 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; } static 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; } static sbnode* freenext(sbnode* node){ sbnode* out = node->next; free(node->str); free(node); if (node != out) return out; else return node; } 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 = freenext(cur)){ size_t slen = strlen(cur->str); memcpy(pos, cur->str, slen); // copy pos += slen; } free(buf); return str; }