1 /*******************************************************************
2 uLan Utilities Library - C library of basic reusable constructions
4 ul_dbufmore.c - more functions for dynamically allocated buffer
6 (C) Copyright 2001-2004 by Pavel Pisa - Originator
7 (C) Copyright 2003-2004 by Frantisek Vacek - Originator
9 The uLan utilities library can be used, copied and modified under
11 - GPL - GNU General Public License
12 - LGPL - GNU Lesser General Public License
13 - MPL - Mozilla Public License
14 - and other licenses added by project originators
15 Code can be modified and re-distributed under any combination
16 of the above listed licenses. If contributor does not agree with
17 some of the licenses, he/she can delete appropriate line.
18 Warning, if you delete all lines, you are not allowed to
19 distribute source code and/or binaries utilizing code.
21 See files COPYING and README for details.
23 *******************************************************************/
25 #include "ul_utmalloc.h"
28 #ifdef UL_DBUFF_LOGGING
30 extern UL_LOG_CUST(ulogd_dbuff)
31 #endif /*UL_DBUFF_LOGGING*/
33 typedef unsigned char byte;
38 * ul_dbuff_set_capacity - change capacity of buffer to at least @new_capacity
39 * @buf: buffer structure
40 * @new_capacity: new capacity
42 * Returns real capacity of reallocated buffer
44 int ul_dbuff_set_capacity(ul_dbuff_t *buf, int new_capacity)
46 if(new_capacity < 0) new_capacity = 0;
47 #ifdef UL_DBUFF_LOGGING
48 int old_capacity = buf->capacity;
50 if(buf->flags & UL_DBUFF_IS_STATIC) {
51 if(!buf->data || !buf->capacity) {
52 buf->capacity = sizeof(buf->sbuff);
53 buf->data = buf->sbuff;
57 if(new_capacity <= UL_DBUFF_SLEN) {
58 if((buf->data) && (buf->data != buf->sbuff)) {
59 // dynamic storage -> static
60 unsigned long c = buf->capacity;
61 if(c > sizeof(buf->sbuff)) c = sizeof(buf->sbuff);
62 memcpy(buf->sbuff, buf->data, c);
65 buf->capacity = sizeof(buf->sbuff);
66 buf->data = buf->sbuff;
68 else if(new_capacity != buf->capacity) {
69 if(buf->data == buf->sbuff) {
70 // static storage -> dynamic
71 buf->data = malloc((size_t)new_capacity);
72 if(buf->data != NULL) {
73 memcpy(buf->data, buf->sbuff, buf->capacity);
74 buf->capacity = new_capacity;
81 // dynamic storage -> dynamic
82 unsigned char *new_data;
83 new_data = realloc(buf->data, (size_t)new_capacity);
84 if(buf->data != NULL) {
85 buf->capacity = new_capacity;
89 /* Old data are not changed if realloc fails, capacity remains at old value */
90 #ifdef UL_DBUFF_LOGGING
91 ul_logdeb("realloc buffer to %d failed\n", new_capacity);
97 if(buf->len > buf->capacity) buf->len = buf->capacity;
98 #ifdef UL_DBUFF_LOGGING
99 ul_logdeb("capacity changed from %d to %ld, required %d\n", old_capacity, buf->capacity, new_capacity);
101 return buf->capacity;
105 * ul_dbuff_set_len - sets a new len of the buffer, change the capacity if neccessary
106 * @buf: buffer structure
107 * @new_len: new desired buffer length
109 * Returns new buffer length
111 int ul_dbuff_set_len(ul_dbuff_t *buf, int new_len)
113 if(new_len < 0) new_len = 0;
114 if(new_len > buf->capacity) {
115 unsigned long new_cap = UL_DBUFF_SLEN;
116 for(; new_cap < new_len; new_cap <<= 1);
117 ul_dbuff_set_capacity(buf, new_cap);
119 if(new_len > buf->capacity) {
120 /*buf->data = buf->sbuff;*/
121 /*strncpy(buf->data, "set_len ERROR", buf->capacity);*/
122 new_len = buf->capacity;
129 * ul_dbuff_cpy - copies bytes to buffer and change its capacity if neccessary like memset
130 * @buf: buffer structure
132 * @n: number of apended bytes
134 * Returns: length of buffer
136 int ul_dbuff_set(ul_dbuff_t *buf, byte b, int n)
138 ul_dbuff_set_len(buf, n);
139 memset(buf->data, b, buf->len);
144 * ul_dbuff_cpy - copies bytes to buffer and change its capacity if neccessary
145 * @buf: buffer structure
147 * @n: number of apended bytes
149 * Returns: length of buffer
151 int ul_dbuff_cpy(ul_dbuff_t *buf, const void *b, int n)
153 if(b == NULL) return 0;
154 ul_dbuff_set_len(buf, n);
155 memcpy(buf->data, b, buf->len);
160 * ul_dbuff_cat - appends bytes at end of buffer and change its capacity if neccessary
161 * @buf: buffer structure
163 * @n: number of apended bytes
165 * Returns: length of buffer
167 int ul_dbuff_cat(ul_dbuff_t *buf, const void *b, int n)
169 unsigned long old_len = buf->len;
170 unsigned long new_len = old_len + n;
171 if(b == NULL) return 0;
172 if(new_len == ul_dbuff_set_len(buf, new_len)) {
173 memcpy(buf->data + old_len, b, n);
175 if (old_len < buf->len)
176 memcpy(buf->data + old_len, b, buf->len - old_len);
177 #ifdef UL_DBUFF_LOGGING
178 ul_logdeb("ul_dbuff_cat: set_len(%lu) error, old_len == %lu\n, act len == %lu\n", new_len, old_len, buf->len);
185 * ul_dbuff_strcat - appends str at dhe end of buffer and change its capacity if neccessary
186 * @buf: buffer structure
187 * @str: string to append
189 * Returns number length of buffer (including terminating '\0')
191 inline int ul_dbuff_strcat(ul_dbuff_t *buf, const char *str)
194 #ifdef UL_DBUFF_LOGGING
195 if(buf->len > 0) ul_logdeb("ul_dbuff_strcat: '%s' + '%s'\n", buf->data, str);
196 else ul_logdeb("ul_dbuff_strcat: '' + %s\n", str);
199 if(str == NULL) return 0;
200 if(buf->len > 0 && buf->data[buf->len-1] == '\0') {
201 /* #ifdef UL_DBUFF_LOGGING
202 ul_logdeb("ul_dbuff_strcat: terminating zero found at %ld, after '%c'\n", buf->len-1, buf->data[buf->len - 2]);
205 ul_dbuff_set_len(buf, buf->len - 1);
207 #ifdef UL_DBUFF_LOGGING
208 if(buf->len > 0 && buf->data[buf->len-1] != '\0') {
209 ul_logerr("ul_dbuff_strcat: terminating zero not found at %ld, found '%c'\n", buf->len-1, buf->data[buf->len-1]);
212 /* #ifdef UL_DBUFF_LOGGING
213 ul_dbuff_cat(buf, str, strlen(str) + 1);
214 ul_logdeb("ul_dbuff_strcat: returning '%s'\n", buf->data);
217 return ul_dbuff_cat(buf, str, strlen(str) + 1);
219 return ul_dbuff_cat(buf, str, strlen(str) + 1);
223 * ul_dbuff_strcpy - copy str to the buffer and change its capacity if neccessary
224 * @buf: buffer structure
225 * @str: string to copy
227 * Returns number length of buffer (including terminating '\0')
229 inline int ul_dbuff_strcpy(ul_dbuff_t *buf, const char *str)
231 ul_dbuff_set_len(buf, 0);
232 return ul_dbuff_strcat(buf, str);
236 * ul_dbuff_append_byte - appends byte at dhe end of buffer and change its capacity if neccessary
237 * @buf: buffer structure
240 * Returns number length of buffer (including terminating '\0')
242 inline int ul_dbuff_append_byte(ul_dbuff_t *buf, unsigned char b)
244 return ul_dbuff_cat(buf, &b, 1);
248 * ul_dbuff_ltrim - remove all white space characters from the left
249 * @buf: buffer structure
251 * Return: new length of buffer
253 int ul_dbuff_ltrim(ul_dbuff_t *buf)
255 byte *pb = buf->data;
257 for(i=0; pb[i]<=' ' && i<buf->len; i++);
259 for(j=i, i=0; j<buf->len; j++, i++) pb[i] = pb[j];
266 * ul_dbuff_rtrim - remove all white space characters from the right
267 * @buf: buffer structure
269 * if buffer is terminated by '\0', than is also terminated after rtrim
271 * Return: new length of buffer
273 int ul_dbuff_rtrim(ul_dbuff_t *buf)
275 int i = buf->len - 1;
276 unsigned char *pb = buf->data;
278 if(i < 0) return buf->len;
279 if(pb[i] == '\0') terminated = 1;
283 if(terminated) pb[i++] = '\0';
292 * ul_dbuff_trim - remove all white space characters from the right and from the left
293 * @buf: buffer structure
295 * Returns number length of buffer (including terminating '\0')
297 int ul_dbuff_trim(ul_dbuff_t *buf)
300 return ul_dbuff_ltrim(buf);
304 * ul_dbuff_cpos - searches string for char
305 * @buf: searched dbuff
306 * @what: char to find
307 * @quote: skip str areas quoted in quote chars<br>
308 * If you want to ignore quotes assign '\0' to quote in function call
310 * Return: position of what char or negative value
312 int ul_dbuff_cpos(const ul_dbuff_t *buf, unsigned char what, unsigned char quote)
316 unsigned char *bytes = buf->data;
317 for(ret = 0; ret < buf->len; ret++) {
318 if(bytes[ret] == quote) {
319 in_quotes = !in_quotes;
322 if(bytes[ret] == what && !in_quotes) {
326 if(ret >= buf->len) ret = -1;
331 * ul_str_cpos - searches string for char
332 * @str: zero terminated string
333 * @what: char to find
334 * @quote: skip str areas quoted in quote chars
335 * If you want to ignore quotes assign '\0' to quote in function call
337 * Return: position of what char or negative value
339 int ul_str_cpos(const unsigned char *str, unsigned char what, unsigned char quote)
343 for(ret = 0; str[ret]; ret++) {
344 if(str[ret] == quote) {
345 in_quotes = !in_quotes;
348 if(str[ret] == what && !in_quotes) {
352 if(!str[ret]) ret = -1;
357 * ul_str_pos - searches string for substring
358 * @str: zero terminated string
359 * @what: string to find
360 * @quote: skip str areas quoted in quote chars
361 * If you want to ignore quotes assign '\0' to quote in function call
363 * Return: position of what string or negative value
365 int ul_str_pos(const unsigned char *str, const unsigned char *what, unsigned char quote)
369 for(ret = 0; str[ret]; ret++) {
370 if(str[ret] == quote) {
371 in_quotes = !in_quotes;
376 for(i=0; str[ret + i]==what[i] && what[i]; i++);
377 if(!what[i]) return ret;
384 * ul_str_ncpy - copies string to the buffer
385 * @to: buffer where to copy str
386 * @from: zero terminated string
387 * @buff_size: size of the @to buffer (including terminating zero)
389 * Standard strncpy function have some disadvatages
390 * (ie. do not append term. zero if copied string doesn't fit in to buffer, fills whole rest of buffer with zeros)
392 * Returns strlen(to) or negative value in case of error
394 int ul_str_ncpy(unsigned char *to, const unsigned char *from, int buff_size)
397 if(!to || !from) return -1;
398 if(buff_size <= 0) return -2;
399 for(i=0; i<buff_size-1 && from[i]; i++) to[i] = from[i];
405 * ul_dbuff_cut_pos - cut first @n bytes from @fromdb and copies it to @todb.
406 * If @n is greater than fromdb.len whole @fromdb is copied to @todb.
407 * If @n is negative position to cut is counted from the end of @fromdb.
408 * If @n is zero @fromdb stays unchanged and todb is resized to len equal zero.
409 * @fromdb: buffer to cut from
410 * @todb: buffer to copy to
411 * @n: position where to cut
413 void ul_dbuff_cut_pos(ul_dbuff_t *fromdb, ul_dbuff_t *todb, int n)
416 if(n < 0) n = fromdb->len + n;
418 if(n > fromdb->len) n = fromdb->len;
419 newlen = fromdb->len - n;
420 ul_dbuff_cpy(todb, fromdb->data, n);
421 memmove(fromdb->data, fromdb->data + n, fromdb->len - n);
422 ul_dbuff_set_len(fromdb, newlen);
426 * ul_dbuff_cut - cuts bytes before delimiter + delimiter char from @fromdb and copies tham to the @todb
427 * If @fromdb doesn't contain delimiter @todb is trimmed to zero length.
428 * @fromdb: buffer to cut from
429 * @todb: buffer to copy to
430 * @delimiter: delimiter char
431 * @quote: quoted delimiters are ignored, @quote can be '\0', than it is ignored.
433 void ul_dbuff_cut_delimited(ul_dbuff_t *fromdb, ul_dbuff_t *todb, char delimiter, char quote)
435 int pos = ul_dbuff_cpos(fromdb, delimiter, quote);
436 if(pos < 0) pos = -1;
437 ul_dbuff_cut_pos(fromdb, todb, pos+1);
441 * ul_dbuff_cut_token - cuts not whitespaces from %fromdb to %todb.
442 * Leading whitespaces are ignored. Cut string is trimmed.
443 * @fromdb: buffer to cut from
444 * @todb: buffer to copy to
446 void ul_dbuff_cut_token(ul_dbuff_t *fromdb, ul_dbuff_t *todb)
448 const unsigned char *pc = (unsigned char*)fromdb->data;
450 /* skip leading white spaces */
451 for(pos=0; pc[pos]>0 && pc[pos]<=' ' && pos<fromdb->len; pos++);
453 for(; pc[pos]>' ' && pos<fromdb->len; pos++);
454 ul_dbuff_cut_pos(fromdb, todb, pos);
459 * ul_dbuff_export - Copies data from %srcdb to the buffer %dest.
460 * @srcdb: source dbuff
461 * @dest: destination buffer
462 * @maxlen: maximum number of bytes to copy
464 * Returns: the number of bytes copied.
466 int ul_dbuff_export(ul_dbuff_t *srcdb, void *dest, int maxlen)
470 len = srcdb->len < maxlen ? srcdb->len : maxlen;
471 memcpy(dest, srcdb->data, len);