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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
|
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "buf.h"
#define min(a,b) (a<b) ? a : b
struct buf_node{
char* text;
struct buf_node* next;
};
struct buf{
buf_node* head;
buf_node* tail;
size_t cap;
size_t ins;
size_t pop;
}; // a "thick" linked list (buffered for mem efficiency)
buf_node* newbufnode(size_t cap){
buf_node* bufnode = malloc(sizeof(buf_node));
bufnode->text = malloc(sizeof(char)*cap);
return bufnode;
}
buf* newbuf(size_t cap){
buf* buffer = malloc(sizeof(buf));
buffer->tail = buffer->head = newbufnode(cap);
buffer->cap = cap;
buffer->ins = buffer->pop = 0;
return buffer;
}
size_t buflen(buf* buffer){
buf_node* cur = buffer->tail;
size_t size = buffer->ins-buffer->pop+buffer->cap;
while (cur != buffer->head) {
cur = cur->next; // skips one iter ^^^
size += buffer->cap;
};
return size;
}
void extendbuf(buf* buffer){
buffer->head->next = newbufnode(buffer->cap);
buffer->head = buffer->head->next;
// buffer->ins = 0 is taken care of in the function that uses this.
}
void shortenbuf(buf* buffer){
buf_node* tmp = buffer->tail;
buffer->tail = buffer->tail->next;
free(tmp);
buffer->pop = 0;
}
char popchrbuf(buf* buffer){
if (buffer->pop == buffer->cap) shortenbuf(buffer);
buffer->pop++;
return buffer->tail->text[buffer->pop-1];
}
char* popstrbuf(buf* buffer, size_t ct){
char* str = malloc((ct+1)*sizeof(char)); str[ct] = 0;
size_t rem;
for (size_t loc = 0; ct>loc; loc += rem){
if (buffer->pop == buffer->cap) shortenbuf(buffer);
rem = min(buffer->cap, ct-loc);
memcpy(str+loc, buffer->tail->text+buffer->pop, rem);
buffer->pop += rem;
} /* probably some inefficiencies here*/
return str;
}
void inschrbuf(buf* buffer, char chr){
if (buffer->ins == buffer->cap) extendbuf(buffer);
buffer->cap++;
buffer->head->text[buffer->cap-1] = chr;
}
void insstrbuf(buf* buffer, char* str){
size_t len = strlen(str);
size_t tgt = min(len, buffer->cap - buffer->ins);
memcpy(buffer->head->text+buffer->ins, str, tgt);
buffer->ins += len;
buffer->ins %= buffer->cap;
for (;tgt<len; tgt += buffer->cap){
extendbuf(buffer);
memcpy(buffer->head->text, str+tgt, min(len-tgt, buffer->cap));
}
}
char* peekstrbuf(buf* buffer, size_t loc, size_t len){
char* str = malloc(sizeof(char)*(len+1)); str[len] = 0;
buf_node* start;
loc += buffer->ins;
for (start = buffer->tail; loc>0;
loc -= buffer->cap)
start = start->next; // start,loc is where one starts streaming
if (len > buffer->cap){
memcpy(str, start->text+loc, buffer->cap-loc);
len -= buffer->cap - loc;
}
for (; len > buffer->cap; len -= buffer->cap ){
memcpy(str, start->text, buffer->cap);
}
memcpy(str, start->text, len);
return str;
}
|