1 /*****
2 *
3 * Copyright (C) 2004-2015 CS-SI. All Rights Reserved.
4 * Author: Yoann Vandoorselaere <yoann.v@prelude-ids.com>
5 *
6 * This file is part of the Prelude library.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2, or (at your option)
11 * any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 *
22 *****/
23
24 /*
25 * This code include an heavily modified version of the prelude-strbuf
26 * API made by Krzysztof Zaraska, that is now part of prelude-string.
27 */
28
29 #include "config.h"
30 #include "libmissing.h"
31
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <sys/types.h>
36 #include <assert.h>
37
38 #include "common.h"
39 #include "prelude-log.h"
40 #include "prelude-inttypes.h"
41 #include "prelude-string.h"
42
43
44 #define PRELUDE_ERROR_SOURCE_DEFAULT PRELUDE_ERROR_SOURCE_STRING
45 #include "prelude-error.h"
46
47
48 #define CHUNK_SIZE 1024
49
50
51 /*
52 * String structure may be free'd
53 */
54 #define PRELUDE_STRING_OWN_STRUCTURE 0x1
55
56 /*
57 * String data may be free'd
58 */
59 #define PRELUDE_STRING_OWN_DATA 0x2
60
61
62 /*
63 * Whether we can reallocate this string
64 */
65 #define PRELUDE_STRING_CAN_REALLOC 0x4
66
67
68
69
70 #if ! defined (PRELUDE_VA_COPY)
71
72 # if defined (__GNUC__) && defined (__PPC__) && (defined (_CALL_SYSV) || defined (_WIN32))
73 # define PRELUDE_VA_COPY(ap1, ap2) (*(ap1) = *(ap2))
74
75 # elif defined (PRELUDE_VA_COPY_AS_ARRAY)
76 # define PRELUDE_VA_COPY(ap1, ap2) memmove ((ap1), (ap2), sizeof(va_list))
77
78 # else /* va_list is a pointer */
79 # define PRELUDE_VA_COPY(ap1, ap2) ((ap1) = (ap2))
80
81 # endif
82 #endif
83
84
85 #define STRING_RETURN_IF_INVALID(str, len) do { \
86 prelude_return_val_if_fail((len + 1) > len, \
87 prelude_error_verbose(PRELUDE_ERROR_INVAL_LENGTH, \
88 "string length warning: wrap around would occur")); \
89 \
90 prelude_return_val_if_fail(str[len] == 0, \
91 prelude_error_verbose(PRELUDE_ERROR_STRING_NOT_NULL_TERMINATED, \
92 "string warning: not nul terminated")); \
93 } while(0)
94
95
96
97 struct prelude_string {
98 PRELUDE_LINKED_OBJECT;
99
100 int flags;
101 int refcount;
102
103 union {
104 char *rwbuf;
105 const char *robuf;
106 } data;
107
108 size_t size;
109 size_t index;
110 };
111
112
string_buf_alloc(prelude_string_t * string,size_t len)113 static int string_buf_alloc(prelude_string_t *string, size_t len)
114 {
115 /*
116 * include room for terminating \0.
117 */
118 string->data.rwbuf = malloc(len + 1);
119 if ( ! string->data.rwbuf )
120 return prelude_error_from_errno(errno);
121
122 string->index = len;
123 string->size = len + 1;
124
125 return 0;
126 }
127
128
129
string_buf_copy(prelude_string_t * string,const char * buf,size_t len)130 static void string_buf_copy(prelude_string_t *string, const char *buf, size_t len)
131 {
132 assert(len < string->size);
133
134 memcpy(string->data.rwbuf, buf, len);
135 string->data.rwbuf[len] = '\0';
136 }
137
138
139
allocate_more_chunk_if_needed(prelude_string_t * s,size_t needed_len)140 static int allocate_more_chunk_if_needed(prelude_string_t *s, size_t needed_len)
141 {
142 char *ptr;
143 size_t len;
144
145 if ( needed_len )
146 len = MAX(needed_len - (s->size - s->index), CHUNK_SIZE);
147 else
148 len = CHUNK_SIZE;
149
150 if ( s->size + len < s->size )
151 return prelude_error(PRELUDE_ERROR_INVAL_LENGTH);
152
153 if ( s->flags & PRELUDE_STRING_CAN_REALLOC ) {
154
155 ptr = _prelude_realloc(s->data.rwbuf, s->size + len);
156 if ( ! ptr )
157 return prelude_error_from_errno(errno);
158 }
159
160 else {
161 ptr = malloc(s->size + len);
162 if ( ! ptr )
163 return prelude_error_from_errno(errno);
164
165 if ( s->data.robuf )
166 memcpy(ptr, s->data.robuf, s->index + 1);
167
168 s->flags |= PRELUDE_STRING_CAN_REALLOC|PRELUDE_STRING_OWN_DATA;
169 }
170
171 s->size += len;
172 s->data.rwbuf = ptr;
173
174 return 0;
175 }
176
177
178
179 /**
180 * prelude_string_new:
181 * @string: Pointer where to store the created #prelude_string_t.
182 *
183 * Create a new #prelude_string_t object, and store in in @string.
184 *
185 * Returns: 0 on success, or a negative value if an error occured.
186 */
prelude_string_new(prelude_string_t ** string)187 int prelude_string_new(prelude_string_t **string)
188 {
189 *string = calloc(1, sizeof(**string));
190 if ( ! *string )
191 return prelude_error_from_errno(errno);
192
193 (*string)->refcount = 1;
194 prelude_list_init(&(*string)->_list);
195 (*string)->flags = PRELUDE_STRING_OWN_STRUCTURE;
196
197 return 0;
198 }
199
200
201
202
203 /**
204 * prelude_string_ref:
205 * @string: Pointer to a #prelude_string_t object to reference.
206 *
207 * Increase @string reference count.
208 *
209 * Returns: @string.
210 */
prelude_string_ref(prelude_string_t * string)211 prelude_string_t *prelude_string_ref(prelude_string_t *string)
212 {
213 prelude_return_val_if_fail(string, NULL);
214
215 string->refcount++;
216 return string;
217 }
218
219
220
221 /**
222 * prelude_string_new_dup_fast:
223 * @string: Pointer where to store the created #prelude_string_t object.
224 * @str: Initial string value.
225 * @len: Lenght of @str.
226 *
227 * Create a new #prelude_string_t object with a copy of @str as it's
228 * initial value. The copy is owned by the @string and will be freed
229 * upon prelude_string_destroy().
230 *
231 * Returns: 0 on success, a negative value if an error occured.
232 */
prelude_string_new_dup_fast(prelude_string_t ** string,const char * str,size_t len)233 int prelude_string_new_dup_fast(prelude_string_t **string, const char *str, size_t len)
234 {
235 int ret;
236
237 prelude_return_val_if_fail(str, prelude_error(PRELUDE_ERROR_ASSERTION));
238 STRING_RETURN_IF_INVALID(str, len);
239
240 ret = prelude_string_new(string);
241 if ( ret < 0 )
242 return ret;
243
244 ret = string_buf_alloc(*string, len);
245 if ( ret < 0 )
246 return ret;
247
248 string_buf_copy(*string, str, len);
249 (*string)->flags |= PRELUDE_STRING_OWN_DATA|PRELUDE_STRING_CAN_REALLOC;
250
251 return 0;
252 }
253
254
255
256 /**
257 * prelude_string_new_dup:
258 * @string: Pointer where to store the created #prelude_string_t object.
259 * @str: Initial string value.
260 *
261 * Create a new #prelude_string_t object with a copy of @str as it's
262 * initial value. The copy is owned by the @string and will be freed
263 * upon prelude_string_destroy().
264 *
265 * Returns: 0 on success, a negative value if an error occured.
266 */
prelude_string_new_dup(prelude_string_t ** string,const char * str)267 int prelude_string_new_dup(prelude_string_t **string, const char *str)
268 {
269 prelude_return_val_if_fail(str, prelude_error(PRELUDE_ERROR_ASSERTION));
270 return prelude_string_new_dup_fast(string, str, strlen(str));
271 }
272
273
274
275 /**
276 * prelude_string_new_nodup_fast:
277 * @string: Pointer where to store the created #prelude_string_t object.
278 * @str: Initial string value.
279 * @len: Lenght of @str.
280 *
281 * Create a new #prelude_string_t object with a reference to @str as
282 * initial value. @str is owned by @string and will be freed upon
283 * prelude_string_destroy().
284 *
285 * Returns: 0 on success, a negative value if an error occured.
286 */
prelude_string_new_nodup_fast(prelude_string_t ** string,char * str,size_t len)287 int prelude_string_new_nodup_fast(prelude_string_t **string, char *str, size_t len)
288 {
289 int ret;
290
291 prelude_return_val_if_fail(str, prelude_error(PRELUDE_ERROR_ASSERTION));
292
293 STRING_RETURN_IF_INVALID(str, len);
294
295 ret = prelude_string_new(string);
296 if ( ret < 0 )
297 return ret;
298
299 (*string)->index = len;
300 (*string)->size = len + 1;
301 (*string)->data.rwbuf = str;
302 (*string)->flags |= PRELUDE_STRING_OWN_DATA|PRELUDE_STRING_CAN_REALLOC;
303
304 return 0;
305 }
306
307
308
309 /**
310 * prelude_string_new_nodup:
311 * @string: Pointer where to store the created #prelude_string_t object.
312 * @str: Initial string value.
313 *
314 * Create a new #prelude_string_t object with a reference to @str as
315 * initial value. @str is owned by @string and will be freed upon
316 * prelude_string_destroy().
317 *
318 * Returns: 0 on success, a negative value if an error occured.
319 */
prelude_string_new_nodup(prelude_string_t ** string,char * str)320 int prelude_string_new_nodup(prelude_string_t **string, char *str)
321 {
322 prelude_return_val_if_fail(str, prelude_error(PRELUDE_ERROR_ASSERTION));
323 return prelude_string_new_nodup_fast(string, str, strlen(str));
324 }
325
326
327
328 /**
329 * prelude_string_new_ref_fast:
330 * @string: Pointer where to store the created #prelude_string_t object.
331 * @str: Initial string value.
332 * @len: Length of @str.
333 *
334 * Create a new #prelude_string_t object with a reference to @str as
335 * initial value. @str won't be freed upon prelude_string_destroy().
336 *
337 * Returns: 0 on success, a negative value if an error occured.
338 */
prelude_string_new_ref_fast(prelude_string_t ** string,const char * buf,size_t len)339 int prelude_string_new_ref_fast(prelude_string_t **string, const char *buf, size_t len)
340 {
341 int ret;
342
343 prelude_return_val_if_fail(buf, prelude_error(PRELUDE_ERROR_ASSERTION));
344 STRING_RETURN_IF_INVALID(buf, len);
345
346 ret = prelude_string_new(string);
347 if ( ret < 0 )
348 return ret;
349
350 (*string)->index = len;
351 (*string)->size = len + 1;
352 (*string)->data.robuf = buf;
353
354 return 0;
355 }
356
357
358
359 /**
360 * prelude_string_new_ref:
361 * @string: Pointer where to store the created #prelude_string_t object.
362 * @str: Initial string value.
363 *
364 * Create a new #prelude_string_t object with a reference to @str as
365 * initial value. @str won't be freed upon prelude_string_destroy().
366 *
367 * Returns: 0 on success, a negative value if an error occured.
368 */
prelude_string_new_ref(prelude_string_t ** string,const char * str)369 int prelude_string_new_ref(prelude_string_t **string, const char *str)
370 {
371 prelude_return_val_if_fail(str, prelude_error(PRELUDE_ERROR_ASSERTION));
372 return prelude_string_new_ref_fast(string, str, strlen(str));
373 }
374
375
376
377 /**
378 * prelude_string_set_dup_fast:
379 * @string: Pointer to a #prelude_string_t object.
380 * @buf: String to store in @string.
381 * @len: Lenght of @buf.
382 *
383 * Store a copy of the string pointed by @buf in @string.
384 * The @buf copy will be freed upon prelude_string_destroy().
385 *
386 * Returns: 0 on success, or a negative value if an error occured.
387 */
prelude_string_set_dup_fast(prelude_string_t * string,const char * buf,size_t len)388 int prelude_string_set_dup_fast(prelude_string_t *string, const char *buf, size_t len)
389 {
390 int ret;
391
392 prelude_return_val_if_fail(string, prelude_error(PRELUDE_ERROR_ASSERTION));
393 prelude_return_val_if_fail(buf, prelude_error(PRELUDE_ERROR_ASSERTION));
394 STRING_RETURN_IF_INVALID(buf, len);
395
396 prelude_string_destroy_internal(string);
397
398 ret = string_buf_alloc(string, len);
399 if ( ret < 0 )
400 return ret;
401
402 string_buf_copy(string, buf, len);
403 string->flags |= PRELUDE_STRING_OWN_DATA|PRELUDE_STRING_CAN_REALLOC;
404
405 return 0;
406 }
407
408
409
410 /**
411 * prelude_string_set_dup:
412 * @string: Pointer to a #prelude_string_t object.
413 * @buf: String to store in @string.
414 *
415 * Store a copy of the string pointed by @buf in @string.
416 * The @buf copy will be freed upon prelude_string_destroy().
417 *
418 * Returns: 0 on success, or a negative value if an error occured.
419 */
prelude_string_set_dup(prelude_string_t * string,const char * buf)420 int prelude_string_set_dup(prelude_string_t *string, const char *buf)
421 {
422 prelude_return_val_if_fail(string, prelude_error(PRELUDE_ERROR_ASSERTION));
423 prelude_return_val_if_fail(buf, prelude_error(PRELUDE_ERROR_ASSERTION));
424 return prelude_string_set_dup_fast(string, buf, strlen(buf));
425 }
426
427
428
429 /**
430 * prelude_string_set_nodup_fast:
431 * @string: Pointer to a #prelude_string_t object.
432 * @buf: String to store in @string.
433 * @len: Lenght of @buf.
434 *
435 * Store a reference to the string pointed by @buf in @string.
436 * The referenced @buf will be freed upon prelude_string_destroy().
437 *
438 * Returns: 0 on success, or a negative value if an error occured.
439 */
prelude_string_set_nodup_fast(prelude_string_t * string,char * buf,size_t len)440 int prelude_string_set_nodup_fast(prelude_string_t *string, char *buf, size_t len)
441 {
442 prelude_return_val_if_fail(string, prelude_error(PRELUDE_ERROR_ASSERTION));
443 prelude_return_val_if_fail(buf, prelude_error(PRELUDE_ERROR_ASSERTION));
444 STRING_RETURN_IF_INVALID(buf, len);
445
446 prelude_string_destroy_internal(string);
447
448 string->index = len;
449 string->size = len + 1;
450 string->data.rwbuf = buf;
451
452 string->flags |= PRELUDE_STRING_OWN_DATA|PRELUDE_STRING_CAN_REALLOC;
453
454 return 0;
455 }
456
457
458
459
460 /**
461 * prelude_string_set_nodup:
462 * @string: Pointer to a #prelude_string_t object.
463 * @buf: String to store in @string.
464 *
465 * Store a reference to the string pointed by @buf in @string.
466 * The referenced @buf will be freed upon prelude_string_destroy().
467 *
468 * Returns: 0 on success, or a negative value if an error occured.
469 */
prelude_string_set_nodup(prelude_string_t * string,char * buf)470 int prelude_string_set_nodup(prelude_string_t *string, char *buf)
471 {
472 prelude_return_val_if_fail(string, prelude_error(PRELUDE_ERROR_ASSERTION));
473 prelude_return_val_if_fail(buf, prelude_error(PRELUDE_ERROR_ASSERTION));
474
475 return prelude_string_set_nodup_fast(string, buf, strlen(buf));
476 }
477
478
479
480 /**
481 * prelude_string_set_ref_fast:
482 * @string: Pointer to a #prelude_string_t object.
483 * @buf: String to store in @string.
484 * @len: Lenght of @buf.
485 *
486 * Store a reference to the string pointed by @buf in @string.
487 * The referenced @buf value won't be modified or freed.
488 *
489 * Returns: 0 on success, or a negative value if an error occured.
490 */
prelude_string_set_ref_fast(prelude_string_t * string,const char * buf,size_t len)491 int prelude_string_set_ref_fast(prelude_string_t *string, const char *buf, size_t len)
492 {
493 prelude_return_val_if_fail(string, prelude_error(PRELUDE_ERROR_ASSERTION));
494 prelude_return_val_if_fail(buf, prelude_error(PRELUDE_ERROR_ASSERTION));
495 STRING_RETURN_IF_INVALID(buf, len);
496
497 prelude_string_destroy_internal(string);
498
499 string->index = len;
500 string->size = len + 1;
501 string->data.robuf = buf;
502
503 string->flags &= ~(PRELUDE_STRING_OWN_DATA|PRELUDE_STRING_CAN_REALLOC);
504
505 return 0;
506 }
507
508
509
510 /**
511 * prelude_string_set_ref:
512 * @string: Pointer to a #prelude_string_t object.
513 * @buf: String to store in @string.
514 *
515 * Store a reference to the string pointed by @buf in @string.
516 * The referenced @buf value won't be modified or freed.
517 *
518 * Returns: 0 on success, or a negative value if an error occured.
519 */
prelude_string_set_ref(prelude_string_t * string,const char * buf)520 int prelude_string_set_ref(prelude_string_t *string, const char *buf)
521 {
522 prelude_return_val_if_fail(string, prelude_error(PRELUDE_ERROR_ASSERTION));
523 prelude_return_val_if_fail(buf, prelude_error(PRELUDE_ERROR_ASSERTION));
524
525 return prelude_string_set_ref_fast(string, buf, strlen(buf));
526 }
527
528
529
530
531 /**
532 * prelude_string_copy_ref:
533 * @src: Pointer to a #prelude_string_t object to copy data from.
534 * @dst: Pointer to a #prelude_string_t object to copy data to.
535 *
536 * Reference @src content within @dst.
537 * The referenced content won't be modified or freed.
538 *
539 * Returns: 0 on success, or a negative value if an error occured.
540 */
prelude_string_copy_ref(const prelude_string_t * src,prelude_string_t * dst)541 int prelude_string_copy_ref(const prelude_string_t *src, prelude_string_t *dst)
542 {
543 prelude_return_val_if_fail(src, prelude_error(PRELUDE_ERROR_ASSERTION));
544 prelude_return_val_if_fail(dst, prelude_error(PRELUDE_ERROR_ASSERTION));
545
546 prelude_string_destroy_internal(dst);
547
548 dst->size = src->size;
549 dst->index = src->index;
550 dst->data.robuf = src->data.robuf;
551 dst->flags &= ~(PRELUDE_STRING_OWN_DATA|PRELUDE_STRING_CAN_REALLOC);
552
553 return 0;
554 }
555
556
557
558 /**
559 * prelude_string_copy_dup:
560 * @src: Pointer to a #prelude_string_t object to copy data from.
561 * @dst: Pointer to a #prelude_string_t object to copy data to.
562 *
563 * Copy @src content within @dst.
564 * The content is owned by @src and independent of @dst.
565 *
566 * Returns: 0 on success, or a negative value if an error occured.
567 */
prelude_string_copy_dup(const prelude_string_t * src,prelude_string_t * dst)568 int prelude_string_copy_dup(const prelude_string_t *src, prelude_string_t *dst)
569 {
570 prelude_return_val_if_fail(src, prelude_error(PRELUDE_ERROR_ASSERTION));
571 prelude_return_val_if_fail(dst, prelude_error(PRELUDE_ERROR_ASSERTION));
572
573 prelude_string_destroy_internal(dst);
574
575 dst->size = src->size;
576 dst->index = src->index;
577 dst->flags |= PRELUDE_STRING_OWN_DATA|PRELUDE_STRING_CAN_REALLOC;
578
579 if ( src->size ) {
580 dst->data.rwbuf = malloc(src->size);
581 if ( ! dst->data.rwbuf )
582 return prelude_error_from_errno(errno);
583
584 string_buf_copy(dst, src->data.robuf, src->index);
585 }
586
587 return 0;
588 }
589
590
591
592 /**
593 * prelude_string_clone:
594 * @src: Pointer to an existing #prelude_string_t object.
595 * @dst: Pointer to an address where to store the created #prelude_string_t object.
596 *
597 * Clone @src within a new #prelude_string_t object stored into @dst.
598 * Data carried by @dst and @src are independant.
599 *
600 * Returns: 0 on success, or a negative value if an error occured.
601 */
prelude_string_clone(const prelude_string_t * src,prelude_string_t ** dst)602 int prelude_string_clone(const prelude_string_t *src, prelude_string_t **dst)
603 {
604 int ret;
605
606 prelude_return_val_if_fail(src, prelude_error(PRELUDE_ERROR_ASSERTION));
607
608 ret = prelude_string_new(dst);
609 if ( ret < 0 )
610 return ret;
611
612 (*dst)->size = src->size;
613 (*dst)->index = src->index;
614 (*dst)->flags |= PRELUDE_STRING_OWN_DATA|PRELUDE_STRING_CAN_REALLOC;
615
616 if ( src->size ) {
617 (*dst)->data.rwbuf = malloc(src->size);
618 if ( ! (*dst)->data.rwbuf ) {
619 prelude_string_destroy(*dst);
620 return prelude_error_from_errno(errno);
621 }
622
623 string_buf_copy(*dst, src->data.robuf, src->index);
624 }
625
626 return 0;
627 }
628
629
630
631 /**
632 * prelude_string_get_len:
633 * @string: Pointer to a #prelude_string_t object.
634 *
635 * Return the length of the string carried by @string object.
636 *
637 * Returns: The length of the string owned by @string.
638 */
prelude_string_get_len(const prelude_string_t * string)639 size_t prelude_string_get_len(const prelude_string_t *string)
640 {
641 prelude_return_val_if_fail(string, 0);
642 return string->index;
643 }
644
645
646
647 /**
648 * prelude_string_get_string_or_default:
649 * @string: Pointer to a #prelude_string_t object.
650 * @def: Default value to a return in case @string is empty.
651 *
652 * Return the string carried on by @string object, or @def if it is empty.
653 * There should be no operation done on the returned string since it is still
654 * owned by @string.
655 *
656 * Returns: The string owned by @string or @def.
657 */
prelude_string_get_string_or_default(const prelude_string_t * string,const char * def)658 const char *prelude_string_get_string_or_default(const prelude_string_t *string, const char *def)
659 {
660 prelude_return_val_if_fail(string, NULL);
661 return string->data.robuf ? string->data.robuf : def;
662 }
663
664
665
666 /**
667 * prelude_string_get_string:
668 * @string: Pointer to a #prelude_string_t object.
669 *
670 * Return the string carried on by @string object.
671 * There should be no operation done on the returned string since
672 * it is still owned by @string.
673 *
674 * Returns: The string owned by @string if any.
675 */
prelude_string_get_string(const prelude_string_t * string)676 const char *prelude_string_get_string(const prelude_string_t *string)
677 {
678 prelude_return_val_if_fail(string, NULL);
679 return string->data.robuf;
680 }
681
682
683
684
685 /**
686 * prelude_string_get_string_released:
687 * @string: Pointer to a #prelude_string_t object.
688 * @outptr: Pointer to an address where to store the released string.
689 *
690 * Get @string content, and release it so that further operation on
691 * @string won't modify the returned content.
692 *
693 * Returns: 0 on success, or a negative value if an error occured.
694 */
prelude_string_get_string_released(prelude_string_t * string,char ** outptr)695 int prelude_string_get_string_released(prelude_string_t *string, char **outptr)
696 {
697 prelude_return_val_if_fail(string, prelude_error(PRELUDE_ERROR_ASSERTION));
698 *outptr = NULL;
699
700 if ( ! string->index )
701 return 0;
702
703 if ( ! (string->flags & PRELUDE_STRING_CAN_REALLOC) ) {
704 *outptr = strdup(string->data.robuf);
705 return (*outptr) ? 0 : prelude_error_from_errno(errno);
706 }
707
708 if ( string->index + 1 <= string->index )
709 return prelude_error(PRELUDE_ERROR_INVAL_LENGTH);
710
711 *outptr = _prelude_realloc(string->data.rwbuf, string->index + 1);
712 if ( ! *outptr )
713 return prelude_error_from_errno(errno);
714
715 string->size = 0;
716 string->index = 0;
717 string->data.rwbuf = NULL;
718
719 return 0;
720 }
721
722
723
724
725 /**
726 * prelude_string_is_empty:
727 * @string: Pointer to a #prelude_string_t object.
728 *
729 * Check whether @string is empty.
730 *
731 * Returns: TRUE if @string is empty, FALSE otherwise.
732 */
prelude_string_is_empty(const prelude_string_t * string)733 prelude_bool_t prelude_string_is_empty(const prelude_string_t *string)
734 {
735 prelude_return_val_if_fail(string, TRUE);
736 return (string->index == 0) ? TRUE : FALSE;
737 }
738
739
740
741 /*
742 * This function cannot be declared static because its invoked
743 * from idmef-tree-wrap.c
744 */
prelude_string_destroy_internal(prelude_string_t * string)745 void prelude_string_destroy_internal(prelude_string_t *string)
746 {
747 prelude_return_if_fail(string);
748
749 if ( (string->flags & PRELUDE_STRING_OWN_DATA) && string->data.rwbuf )
750 free(string->data.rwbuf);
751
752 string->data.rwbuf = NULL;
753 string->index = string->size = 0;
754
755 /*
756 * free() should be done by the caller
757 */
758 }
759
760
761
762 /**
763 * prelude_string_destroy:
764 * @string: Pointer to a #prelude_string_t object.
765 *
766 * Decrease refcount and destroy @string.
767 * @string content content is destroyed if applicable (dup and nodup,
768 * or a referenced string that have been modified.
769 */
prelude_string_destroy(prelude_string_t * string)770 void prelude_string_destroy(prelude_string_t *string)
771 {
772 prelude_return_if_fail(string);
773
774 if ( --string->refcount )
775 return;
776
777 if ( ! prelude_list_is_empty(&string->_list) )
778 prelude_list_del_init(&string->_list);
779
780 prelude_string_destroy_internal(string);
781
782 if ( string->flags & PRELUDE_STRING_OWN_STRUCTURE )
783 free(string);
784 }
785
786
787
788
789 /**
790 * prelude_string_vprintf:
791 * @string: Pointer to a #prelude_string_t object.
792 * @fmt: Format string to use.
793 * @ap: Variable argument list.
794 *
795 * Produce output according to @fmt, storing argument provided in @ap
796 * variable argument list, and write the output to the given @string.
797 * See sprintf(3) for more information on @fmt format.
798 *
799 * Returns: The number of characters written, or a negative value if an error occured.
800 */
prelude_string_vprintf(prelude_string_t * string,const char * fmt,va_list ap)801 int prelude_string_vprintf(prelude_string_t *string, const char *fmt, va_list ap)
802 {
803 int ret;
804 va_list bkp;
805
806 prelude_return_val_if_fail(string, prelude_error(PRELUDE_ERROR_ASSERTION));
807 prelude_return_val_if_fail(fmt, prelude_error(PRELUDE_ERROR_ASSERTION));
808
809 if ( ! (string->flags & PRELUDE_STRING_CAN_REALLOC) ) {
810
811 ret = allocate_more_chunk_if_needed(string, 0);
812 if ( ret < 0 )
813 return ret;
814 }
815
816 PRELUDE_VA_COPY(bkp, ap);
817 ret = vsnprintf(string->data.rwbuf + string->index, string->size - string->index, fmt, ap);
818
819 /*
820 * From sprintf(3) on GNU/Linux:
821 *
822 * snprintf and vsnprintf do not write more than
823 * size bytes (including the trailing '\0'), and return -1 if
824 * the output was truncated due to this limit. (Thus until
825 * glibc 2.0.6. Since glibc 2.1 these functions follow the
826 * C99 standard and return the number of characters (exclud-
827 * ing the trailing '\0') which would have been written to
828 * the final string if enough space had been available.)
829 */
830 if ( ret >= 0 && (size_t) ret < string->size - string->index ) {
831 string->index += ret;
832 goto end;
833 }
834
835 ret = allocate_more_chunk_if_needed(string, (ret < 0) ? 0 : ret + 1);
836 if ( ret < 0 )
837 goto end;
838
839 ret = prelude_string_vprintf(string, fmt, bkp);
840
841 end:
842 va_end(bkp);
843 return ret;
844 }
845
846
847
848
849 /**
850 * prelude_string_sprintf:
851 * @string: Pointer to a #prelude_string_t object.
852 * @fmt: Format string to use.
853 * @...: Variable argument list.
854 *
855 * Produce output according to @fmt, and write output to the given
856 * @string. See snprintf(3) to learn more about @fmt format.
857 *
858 * Returns: The number of characters written, or a negative value if an error occured.
859 */
prelude_string_sprintf(prelude_string_t * string,const char * fmt,...)860 int prelude_string_sprintf(prelude_string_t *string, const char *fmt, ...)
861 {
862 int ret;
863 va_list ap;
864
865 prelude_return_val_if_fail(string, prelude_error(PRELUDE_ERROR_ASSERTION));
866 prelude_return_val_if_fail(fmt, prelude_error(PRELUDE_ERROR_ASSERTION));
867
868 va_start(ap, fmt);
869 ret = prelude_string_vprintf(string, fmt, ap);
870 va_end(ap);
871
872 return ret;
873 }
874
875
876
877 /**
878 * prelude_string_cat:
879 * @dst: Pointer to a #prelude_string_t object.
880 * @str: Pointer to a string.
881 * @len: Length of @str to copy.
882 *
883 * The prelude_string_ncat() function appends @len characters from @str to
884 * the @dst #prelude_string_t object over-writing the `\0' character at the
885 * end of @dst, and then adds a termi-nating `\0' character.
886 *
887 * Returns: @len, or a negative value if an error occured.
888 */
prelude_string_ncat(prelude_string_t * dst,const char * str,size_t len)889 int prelude_string_ncat(prelude_string_t *dst, const char *str, size_t len)
890 {
891 int ret;
892
893 prelude_return_val_if_fail(dst, prelude_error(PRELUDE_ERROR_ASSERTION));
894 prelude_return_val_if_fail(str, prelude_error(PRELUDE_ERROR_ASSERTION));
895
896 if ( dst->flags & PRELUDE_STRING_CAN_REALLOC && len < (dst->size - dst->index) ) {
897
898 memcpy(dst->data.rwbuf + dst->index, str, len);
899
900 dst->index += len;
901 dst->data.rwbuf[dst->index] = '\0';
902
903 return len;
904 }
905
906 if ( len + 1 < len )
907 return prelude_error(PRELUDE_ERROR_INVAL_LENGTH);
908
909 ret = allocate_more_chunk_if_needed(dst, len + 1);
910 if ( ret < 0 )
911 return ret;
912
913 return prelude_string_ncat(dst, str, len);
914 }
915
916
917
918 /**
919 * prelude_string_cat:
920 * @dst: Pointer to a #prelude_string_t object.
921 * @str: Pointer to a string.
922 *
923 * The prelude_string_cat() function appends the @str string to the @dst
924 * prelude_string_t object over-writing the `\0' character at the end of
925 * @dst, and then adds a termi-nating `\0' character.
926 *
927 * Returns: @len, or a negative value if an error occured.
928 */
prelude_string_cat(prelude_string_t * dst,const char * str)929 int prelude_string_cat(prelude_string_t *dst, const char *str)
930 {
931 prelude_return_val_if_fail(dst, prelude_error(PRELUDE_ERROR_ASSERTION));
932 prelude_return_val_if_fail(str, prelude_error(PRELUDE_ERROR_ASSERTION));
933
934 return prelude_string_ncat(dst, str, strlen(str));
935 }
936
937
938
939
940 /**
941 * prelude_string_clear:
942 * @string: Pointer to a #prelude_string_t object.
943 *
944 * Reset @string content to zero.
945 */
prelude_string_clear(prelude_string_t * string)946 void prelude_string_clear(prelude_string_t *string)
947 {
948 prelude_return_if_fail(string);
949
950 string->index = 0;
951
952 if ( string->data.rwbuf && string->flags & PRELUDE_STRING_OWN_DATA )
953 *(string->data.rwbuf) = '\0';
954
955 else string->data.rwbuf = NULL;
956 }
957
958
959
960 /**
961 * prelude_string_compare:
962 * @str1: Pointer to a #prelude_string_t object to compare with @str2.
963 * @str2: Pointer to a #prelude_string_t object to compare with @str1.
964 *
965 * Compare @str1 and @str2.
966 *
967 * Returns: 0 if @str1 and @str2 value are equal, a negative value otherwise.
968 */
prelude_string_compare(const prelude_string_t * str1,const prelude_string_t * str2)969 int prelude_string_compare(const prelude_string_t *str1, const prelude_string_t *str2)
970 {
971 if ( ! str1 && ! str2 )
972 return 0;
973
974 else if ( ! str1 || ! str2 )
975 return -1;
976
977 else if ( str1->index != str2->index )
978 return -1;
979
980 if ( str1->index == 0 )
981 return 0;
982
983 return strcmp(str1->data.robuf, str2->data.robuf) == 0 ? 0 : -1;
984 }
985