1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
|
#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;
};
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;
}
|