Update copyright notices for 2012
[jansson.git] / src / strbuffer.c
1 /*
2  * Copyright (c) 2009-2012 Petri Lehtinen <petri@digip.org>
3  *
4  * Jansson is free software; you can redistribute it and/or modify
5  * it under the terms of the MIT license. See LICENSE for details.
6  */
7
8 #define _GNU_SOURCE
9 #include <stdlib.h>
10 #include <string.h>
11 #include "jansson_private.h"
12 #include "strbuffer.h"
13
14 #define STRBUFFER_MIN_SIZE  16
15 #define STRBUFFER_FACTOR    2
16 #define STRBUFFER_SIZE_MAX  ((size_t)-1)
17
18 int strbuffer_init(strbuffer_t *strbuff)
19 {
20     strbuff->size = STRBUFFER_MIN_SIZE;
21     strbuff->length = 0;
22
23     strbuff->value = jsonp_malloc(strbuff->size);
24     if(!strbuff->value)
25         return -1;
26
27     /* initialize to empty */
28     strbuff->value[0] = '\0';
29     return 0;
30 }
31
32 void strbuffer_close(strbuffer_t *strbuff)
33 {
34     jsonp_free(strbuff->value);
35     strbuff->size = 0;
36     strbuff->length = 0;
37     strbuff->value = NULL;
38 }
39
40 void strbuffer_clear(strbuffer_t *strbuff)
41 {
42     strbuff->length = 0;
43     strbuff->value[0] = '\0';
44 }
45
46 const char *strbuffer_value(const strbuffer_t *strbuff)
47 {
48     return strbuff->value;
49 }
50
51 char *strbuffer_steal_value(strbuffer_t *strbuff)
52 {
53     char *result = strbuff->value;
54     strbuffer_init(strbuff);
55     return result;
56 }
57
58 int strbuffer_append(strbuffer_t *strbuff, const char *string)
59 {
60     return strbuffer_append_bytes(strbuff, string, strlen(string));
61 }
62
63 int strbuffer_append_byte(strbuffer_t *strbuff, char byte)
64 {
65     return strbuffer_append_bytes(strbuff, &byte, 1);
66 }
67
68 int strbuffer_append_bytes(strbuffer_t *strbuff, const char *data, size_t size)
69 {
70     if(size >= strbuff->size - strbuff->length)
71     {
72         size_t new_size;
73         char *new_value;
74
75         /* avoid integer overflow */
76         if (strbuff->size > STRBUFFER_SIZE_MAX / STRBUFFER_FACTOR
77             || size > STRBUFFER_SIZE_MAX - 1
78             || strbuff->length > STRBUFFER_SIZE_MAX - 1 - size)
79             return -1;
80
81         new_size = max(strbuff->size * STRBUFFER_FACTOR,
82                        strbuff->length + size + 1);
83
84         new_value = jsonp_malloc(new_size);
85         if(!new_value)
86             return -1;
87
88         memcpy(new_value, strbuff->value, strbuff->length);
89
90         jsonp_free(strbuff->value);
91         strbuff->value = new_value;
92         strbuff->size = new_size;
93     }
94
95     memcpy(strbuff->value + strbuff->length, data, size);
96     strbuff->length += size;
97     strbuff->value[strbuff->length] = '\0';
98
99     return 0;
100 }
101
102 char strbuffer_pop(strbuffer_t *strbuff)
103 {
104     if(strbuff->length > 0) {
105         char c = strbuff->value[--strbuff->length];
106         strbuff->value[strbuff->length] = '\0';
107         return c;
108     }
109     else
110         return '\0';
111 }