1 /*
2 * buf.c
3 *
4 * This file provides the implementation of a buf class
5 */
6 #include "private.h"
7 #include "lub/argv.h"
8 #include "lub/string.h"
9 #include "lub/ctype.h"
10
11 #include <assert.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <stdio.h>
15 #include <unistd.h>
16
17 #define KONF_BUF_CHUNK 1024
18
19 /*---------------------------------------------------------
20 * PRIVATE META FUNCTIONS
21 *--------------------------------------------------------- */
konf_buf_bt_compare(const void * clientnode,const void * clientkey)22 int konf_buf_bt_compare(const void *clientnode, const void *clientkey)
23 {
24 const konf_buf_t *this = clientnode;
25 int keyfd;
26
27 memcpy(&keyfd, clientkey, sizeof(keyfd));
28
29 return (this->fd - keyfd);
30 }
31
32 /*-------------------------------------------------------- */
konf_buf_key(lub_bintree_key_t * key,int fd)33 static void konf_buf_key(lub_bintree_key_t * key,
34 int fd)
35 {
36 memcpy(key, &fd, sizeof(fd));
37 }
38
39 /*-------------------------------------------------------- */
konf_buf_bt_getkey(const void * clientnode,lub_bintree_key_t * key)40 void konf_buf_bt_getkey(const void *clientnode, lub_bintree_key_t * key)
41 {
42 const konf_buf_t *this = clientnode;
43
44 konf_buf_key(key, this->fd);
45 }
46
47 /*---------------------------------------------------------
48 * PRIVATE METHODS
49 *--------------------------------------------------------- */
50 static void
konf_buf_init(konf_buf_t * this,int fd)51 konf_buf_init(konf_buf_t * this, int fd)
52 {
53 this->fd = fd;
54 this->buf = malloc(KONF_BUF_CHUNK);
55 this->size = KONF_BUF_CHUNK;
56 this->pos = 0;
57 this->rpos = 0;
58 this->data = NULL;
59
60 /* Be a good binary tree citizen */
61 lub_bintree_node_init(&this->bt_node);
62 }
63
64 /*--------------------------------------------------------- */
konf_buf_fini(konf_buf_t * this)65 static void konf_buf_fini(konf_buf_t * this)
66 {
67 free(this->buf);
68 }
69
70 /*---------------------------------------------------------
71 * PUBLIC META FUNCTIONS
72 *--------------------------------------------------------- */
konf_buf_bt_offset(void)73 size_t konf_buf_bt_offset(void)
74 {
75 return offsetof(konf_buf_t, bt_node);
76 }
77
78 /*--------------------------------------------------------- */
konf_buf_new(int fd)79 konf_buf_t *konf_buf_new(int fd)
80 {
81 konf_buf_t *this = malloc(sizeof(konf_buf_t));
82
83 if (this)
84 konf_buf_init(this, fd);
85
86 return this;
87 }
88
89 /*---------------------------------------------------------
90 * PUBLIC METHODS
91 *--------------------------------------------------------- */
konf_buf_delete(konf_buf_t * this)92 void konf_buf_delete(konf_buf_t * this)
93 {
94 konf_buf_fini(this);
95 free(this);
96 }
97
98 /*--------------------------------------------------------- */
konf_buf_realloc(konf_buf_t * this,int addsize)99 static int konf_buf_realloc(konf_buf_t *this, int addsize)
100 {
101 int chunk = KONF_BUF_CHUNK;
102 char *tmpbuf;
103
104 if (addsize > chunk)
105 chunk = addsize;
106 if ((this->size - this->pos) < chunk) {
107 tmpbuf = realloc(this->buf, this->size + chunk);
108 this->buf = tmpbuf;
109 this->size += chunk;
110 }
111
112 return this->size;
113 }
114
115 /*--------------------------------------------------------- */
konf_buf_add(konf_buf_t * this,void * str,size_t len)116 int konf_buf_add(konf_buf_t *this, void *str, size_t len)
117 {
118 char *buffer;
119
120 konf_buf_realloc(this, len);
121 buffer = this->buf + this->pos;
122 memcpy(buffer, str, len);
123 this->pos += len;
124
125 return len;
126 }
127
128 /*--------------------------------------------------------- */
konf_buf_read(konf_buf_t * this)129 int konf_buf_read(konf_buf_t *this)
130 {
131 char *buffer;
132 int buffer_size;
133 int nbytes;
134
135 konf_buf_realloc(this, 0);
136 buffer_size = this->size - this->pos;
137 buffer = this->buf + this->pos;
138
139 nbytes = read(this->fd, buffer, buffer_size);
140 if (nbytes > 0)
141 this->pos += nbytes;
142
143 return nbytes;
144 }
145
146 /*--------------------------------------------------------- */
konf_buf_string(char * buf,int len)147 char * konf_buf_string(char *buf, int len)
148 {
149 int i;
150 char *str;
151
152 for (i = 0; i < len; i++) {
153 if (('\0' == buf[i]) ||
154 ('\n' == buf[i]))
155 break;
156 }
157 if (i >= len)
158 return NULL;
159
160 str = malloc(i + 1);
161 memcpy(str, buf, i + 1);
162 str[i] = '\0';
163
164 return str;
165 }
166
167 /*--------------------------------------------------------- */
konf_buf_parse(konf_buf_t * this)168 char * konf_buf_parse(konf_buf_t *this)
169 {
170 char * str = NULL;
171
172 /* Search the buffer for the string */
173 str = konf_buf_string(this->buf, this->pos);
174
175 /* Remove parsed string from the buffer */
176 if (str) {
177 int len = strlen(str) + 1;
178 memmove(this->buf, &this->buf[len], this->pos - len);
179 this->pos -= len;
180 if (this->rpos >= len)
181 this->rpos -= len;
182 else
183 this->rpos = 0;
184 }
185
186 /* Make buffer shorter */
187 if ((this->size - this->pos) > (2 * KONF_BUF_CHUNK)) {
188 char *tmpbuf;
189 tmpbuf = realloc(this->buf, this->size - KONF_BUF_CHUNK);
190 this->buf = tmpbuf;
191 this->size -= KONF_BUF_CHUNK;
192 }
193
194 return str;
195 }
196
197 /*--------------------------------------------------------- */
konf_buf_preparse(konf_buf_t * this)198 char * konf_buf_preparse(konf_buf_t *this)
199 {
200 char * str = NULL;
201
202 str = konf_buf_string(this->buf + this->rpos, this->pos - this->rpos);
203 if (str)
204 this->rpos += (strlen(str) + 1);
205
206 return str;
207 }
208
209 /*--------------------------------------------------------- */
konf_buf_lseek(konf_buf_t * this,int newpos)210 int konf_buf_lseek(konf_buf_t *this, int newpos)
211 {
212 if (newpos > this->pos)
213 return -1;
214 this->rpos = newpos;
215
216 return newpos;
217 }
218
219 /*--------------------------------------------------------- */
konf_buf__get_fd(const konf_buf_t * this)220 int konf_buf__get_fd(const konf_buf_t * this)
221 {
222 return this->fd;
223 }
224
225 /*--------------------------------------------------------- */
konf_buf__get_len(const konf_buf_t * this)226 int konf_buf__get_len(const konf_buf_t *this)
227 {
228 return this->pos;
229 }
230
231 /*--------------------------------------------------------- */
konf_buf__dup_line(const konf_buf_t * this)232 char * konf_buf__dup_line(const konf_buf_t *this)
233 {
234 char *str;
235
236 str = malloc(this->pos + 1);
237 memcpy(str, this->buf, this->pos);
238 str[this->pos] = '\0';
239 return str;
240 }
241
242 /*--------------------------------------------------------- */
konf_buf__get_buf(const konf_buf_t * this)243 char * konf_buf__get_buf(const konf_buf_t *this)
244 {
245 return this->buf;
246 }
247
248 /*--------------------------------------------------------- */
konf_buf__get_data(const konf_buf_t * this)249 void * konf_buf__get_data(const konf_buf_t *this)
250 {
251 return this->data;
252 }
253
254 /*--------------------------------------------------------- */
konf_buf__set_data(konf_buf_t * this,void * data)255 void konf_buf__set_data(konf_buf_t *this, void *data)
256 {
257 this->data = data;
258 }
259
260 /*---------------------------------------------------------
261 * buftree functions
262 *--------------------------------------------------------- */
263
264 /*--------------------------------------------------------- */
konf_buftree_find(lub_bintree_t * this,int fd)265 konf_buf_t *konf_buftree_find(lub_bintree_t * this,
266 int fd)
267 {
268 lub_bintree_key_t key;
269
270 konf_buf_key(&key, fd);
271
272 return lub_bintree_find(this, &key);
273 }
274
275 /*--------------------------------------------------------- */
konf_buftree_remove(lub_bintree_t * this,int fd)276 void konf_buftree_remove(lub_bintree_t * this,
277 int fd)
278 {
279 konf_buf_t *tbuf;
280
281 if ((tbuf = konf_buftree_find(this, fd)) == NULL)
282 return;
283
284 lub_bintree_remove(this, tbuf);
285 konf_buf_delete(tbuf);
286 }
287
288 /*--------------------------------------------------------- */
konf_buftree_read(lub_bintree_t * this,int fd)289 int konf_buftree_read(lub_bintree_t * this, int fd)
290 {
291 konf_buf_t *buf;
292
293 buf = konf_buftree_find(this, fd);
294 if (!buf)
295 return -1;
296
297 return konf_buf_read(buf);
298 }
299
300
301 /*--------------------------------------------------------- */
konf_buftree_parse(lub_bintree_t * this,int fd)302 char * konf_buftree_parse(lub_bintree_t * this,
303 int fd)
304 {
305 konf_buf_t *buf;
306
307 buf = konf_buftree_find(this, fd);
308 if (!buf)
309 return NULL;
310
311 return konf_buf_parse(buf);
312 }
313
314