1 /*
2  * Copyright 2010, Lloyd Hilaiel.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  *  1. Redistributions of source code must retain the above copyright
9  *     notice, this list of conditions and the following disclaimer.
10  *
11  *  2. Redistributions in binary form must reproduce the above copyright
12  *     notice, this list of conditions and the following disclaimer in
13  *     the documentation and/or other materials provided with the
14  *     distribution.
15  *
16  *  3. Neither the name of Lloyd Hilaiel nor the names of its
17  *     contributors may be used to endorse or promote products derived
18  *     from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23  * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
24  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
28  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
29  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 #include "yajl_buf.h"
34 
35 #include <assert.h>
36 #include <stdlib.h>
37 #include <string.h>
38 
39 #define YAJL_BUF_INIT_SIZE 2048
40 
41 struct yajl_buf_t {
42     unsigned int len;
43     unsigned int used;
44     unsigned char * data;
45     yajl_alloc_funcs * alloc;
46 };
47 
48 static
yajl_buf_ensure_available(yajl_buf buf, unsigned int want)49 void yajl_buf_ensure_available(yajl_buf buf, unsigned int want)
50 {
51     unsigned int need;
52 
53     assert(buf != NULL);
54 
55     /* first call */
56     if (buf->data == NULL) {
57         buf->len = YAJL_BUF_INIT_SIZE;
58         buf->data = (unsigned char *) YA_MALLOC(buf->alloc, buf->len);
59         buf->data[0] = 0;
60     }
61 
62     need = buf->len;
63 
64     while (want >= (need - buf->used)) need <<= 1;
65 
66     if (need != buf->len) {
67         buf->data = (unsigned char *) YA_REALLOC(buf->alloc, buf->data, need);
68         buf->len = need;
69     }
70 }
71 
yajl_buf_alloc(yajl_alloc_funcs * alloc)72 yajl_buf yajl_buf_alloc(yajl_alloc_funcs * alloc)
73 {
74     yajl_buf b = YA_MALLOC(alloc, sizeof(struct yajl_buf_t));
75     memset((void *) b, 0, sizeof(struct yajl_buf_t));
76     b->alloc = alloc;
77     return b;
78 }
79 
yajl_buf_free(yajl_buf buf)80 void yajl_buf_free(yajl_buf buf)
81 {
82     assert(buf != NULL);
83     if (buf->data) YA_FREE(buf->alloc, buf->data);
84     YA_FREE(buf->alloc, buf);
85 }
86 
yajl_buf_append(yajl_buf buf, const void * data, unsigned int len)87 void yajl_buf_append(yajl_buf buf, const void * data, unsigned int len)
88 {
89     yajl_buf_ensure_available(buf, len);
90     if (len > 0) {
91         assert(data != NULL);
92         memcpy(buf->data + buf->used, data, len);
93         buf->used += len;
94         buf->data[buf->used] = 0;
95     }
96 }
97 
yajl_buf_clear(yajl_buf buf)98 void yajl_buf_clear(yajl_buf buf)
99 {
100     buf->used = 0;
101     if (buf->data) buf->data[buf->used] = 0;
102 }
103 
yajl_buf_data(yajl_buf buf)104 const unsigned char * yajl_buf_data(yajl_buf buf)
105 {
106     return buf->data;
107 }
108 
yajl_buf_len(yajl_buf buf)109 unsigned int yajl_buf_len(yajl_buf buf)
110 {
111     return buf->used;
112 }
113 
114 void
yajl_buf_truncate(yajl_buf buf, unsigned int len)115 yajl_buf_truncate(yajl_buf buf, unsigned int len)
116 {
117     assert(len <= buf->used);
118     buf->used = len;
119 }
120