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