"Fossies" - the Fresh Open Source Software Archive 
Member "netbiff-0.9.18/buffer.c" (21 Sep 2003, 4020 Bytes) of package /linux/privat/old/netbiff-0.9.18.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
1 #include "buffer.h"
2 #include "xlib.h"
3
4 #include <stdlib.h>
5 #include <string.h>
6
7 void buffer_init(Buffer *b) {
8 b->size = 0;
9 b->head = b->tail = NULL;
10 }
11
12 void buffer_finish(Buffer *b) {
13 BufferChunk *bc, *next;
14
15 for(bc = b->head; bc; bc = next) {
16 next= bc->next;
17 free(bc->buf);
18 free(bc);
19 }
20 b->head = b->tail = NULL;
21 b->size = 0;
22 }
23
24 void buffer_put(Buffer *b, const char *s, unsigned long len) {
25 BufferChunk *bc;
26
27 bc = xmalloc(sizeof(BufferChunk));
28 bc->len = len;
29 bc->buf = xmalloc(len + 1);
30 memcpy(bc->buf, s, len);
31 bc->buf[len] = '\0';
32 bc->next = NULL;
33
34 if(b->tail)
35 b->tail->next = bc;
36 else
37 b->head = bc;
38 b->tail = bc;
39
40 b->size += len;
41 }
42
43 static void compact_buffer_to_lines(Buffer *b) {
44 BufferChunk *old;
45 int in_line_flag;
46
47 old = b->head;
48 b->head = b->tail = NULL;
49
50 in_line_flag = 0;
51 while(old) {
52 BufferChunk *next = old->next;
53
54 /* If the old chunk was a line, we steal it. */
55 if(!in_line_flag &&
56 memchr(old->buf, '\n', old->len) == old->buf + old->len - 1) {
57 old->next = NULL;
58 if(b->tail)
59 b->tail->next = old;
60 else
61 b->head = old;
62 b->tail = old;
63 }
64 /* Otherwise, add all lines */
65 else {
66 char *p = old->buf;
67 while(p) {
68 char *q;
69 unsigned long len;
70
71 /* If there are no more complete lines, save what we have
72 * and quit. */
73 q = memchr(p, '\n', old->len - (p - old->buf));
74 if(!q)
75 len = old->len - (p - old->buf);
76 else
77 len = q - p + 1;
78
79 /* No point in adding 0 bytes */
80 if(len) {
81 /* Add to the last if we're continuing a line. */
82 if(in_line_flag) {
83 unsigned long prevlen = b->tail->len;
84 b->tail->len += len;
85 b->tail->buf = xrealloc(b->tail->buf, b->tail->len + 1);
86 memcpy(b->tail->buf + prevlen, p, len);
87 b->tail->buf[b->tail->len] = '\0';
88 }
89 else {
90 BufferChunk *c;
91 c = xmalloc(sizeof(BufferChunk));
92 c->len = len;
93 c->buf = xmalloc(len + 1);
94 memcpy(c->buf, p, len);
95 c->buf[len] = '\0';
96 c->next = NULL;
97 if(b->tail)
98 b->tail->next = c;
99 else
100 b->head = c;
101 b->tail = c;
102 }
103 }
104
105 p = q;
106 if(!q) {
107 if(len)
108 in_line_flag = 1;
109 }
110 else {
111 in_line_flag = 0;
112 p++;
113 }
114 }
115 free(old->buf);
116 free(old);
117 }
118 old = next;
119 }
120 }
121
122 char *buffer_get_line(Buffer *b) {
123 BufferChunk *bc;
124
125 /* If we have no data, we have no lines. */
126 bc = b->head;
127 if(!bc)
128 return NULL;
129
130 /* If our first chunk is a single, complete line,
131 * we were probably just compacted. Return the line. */
132 if(memchr(bc->buf, '\n', bc->len) == bc->buf + bc->len - 1) {
133 char *buf;
134 b->head = bc->next;
135 if(!b->head)
136 b->tail = NULL;
137 buf = bc->buf;
138 b->size -= bc->len;
139 free(bc);
140 return buf;
141 }
142
143 /* Otherwise we need to reorganize the data in lines. */
144 compact_buffer_to_lines(b);
145
146 /* Each chunk should now be either a line *or* part of a line
147 * but never multiple lines. Note that bc is no longer valid
148 * after compacting. */
149 bc = b->head;
150 if(!bc)
151 return NULL;
152 if(bc->buf[bc->len - 1] == '\n') {
153 char *buf;
154 b->head = bc->next;
155 if(!b->head)
156 b->tail = NULL;
157 buf = bc->buf;
158 b->size -= bc->len;
159 return buf;
160 }
161
162 /* If we're part of a line, we have no line. */
163 return NULL;
164 }
165
166 int buffer_get(Buffer *b, char **dest) {
167 BufferChunk *bc;
168 BufferChunk *next;
169 char *pos;
170
171 if(!b->size) {
172 *dest = NULL;
173 return 0;
174 }
175
176 pos = *dest = xmalloc(b->size);
177 for(bc = b->head; bc; bc = next) {
178 next = bc->next;
179
180 memcpy(pos, bc->buf, bc->len);
181 pos += bc->len;
182 free(bc->buf);
183 free(bc);
184 }
185 b->size = 0;
186 b->head = b->tail = NULL;
187 return pos - *dest;
188 }
189
190