1 | /*
2 | * Copyright (c) 2007-2014, Lloyd Hilaiel <me@lloyd.io>
3 | *
4 | * Permission to use, copy, modify, and/or distribute this software for any
5 | * purpose with or without fee is hereby granted, provided that the above
6 | * copyright notice and this permission notice appear in all copies.
7 | *
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 | */
16 |
17 | #include "yajl_buf.h"
18 |
19 | #include <assert.h>
20 | #include <stdlib.h>
21 | #include <string.h>
22 |
23 | #define YAJL_BUF_INIT_SIZE 2048
24 |
25 | struct yajl_buf_t {
26 | size_t len;
27 | size_t used;
28 | unsigned char * data;
29 | yajl_alloc_funcs * alloc;
30 | };
31 |
32 | static
33 | void yajl_buf_ensure_available(yajl_buf buf, size_t want)
34 | {
35 | size_t need;
36 |
37 | assert(buf != NULL);
38 |
39 | /* first call */
40 | if (buf->data == NULL) {
41 | assert(buf->used == 0);
42 | buf->len = YAJL_BUF_INIT_SIZE;
43 | buf->data = (unsigned char *) YA_MALLOC(buf->alloc, buf->len);
44 | #if 0
45 | memset((void *) buf->data, 0, buf->len);
46 | #else /* it's really just a string, albiet UTF-8.... */
47 | buf->data[0] = 0;
48 | #endif
49 | }
50 |
51 | need = buf->len;
52 |
53 | while (want >= (need - buf->used)) {
54 | need <<= 1; /* XXX maybe this is a bit too aggressive? */
55 | }
56 | if (need != buf->len) {
57 | buf->data = (unsigned char *) YA_REALLOC(buf->alloc, buf->data, need);
58 | buf->len = need;
59 | }
60 | }
61 |
62 | /*+ allocate a new buffer +*/
63 | yajl_buf yajl_buf_alloc(yajl_alloc_funcs * alloc)
64 | {
65 | yajl_buf b = YA_MALLOC(alloc, sizeof(struct yajl_buf_t));
66 | memset((void *) b, 0, sizeof(struct yajl_buf_t));
67 | b->alloc = alloc;
68 | return b;
69 | }
70 |
71 | /*+ free the buffer +*/
72 | void yajl_buf_free(yajl_buf buf)
73 | {
74 | assert(buf != NULL);
75 | if (buf->data) {
76 | YA_FREE(buf->alloc, buf->data);
77 | }
78 | YA_FREE(buf->alloc, buf);
79 | }
80 |
81 | /*+ append a number of bytes to the buffer +*/
82 | void yajl_buf_append(yajl_buf buf, const void * data, size_t len)
83 | {
84 | yajl_buf_ensure_available(buf, len);
85 | if (len > 0) {
86 | assert(data != NULL);
87 | memcpy(buf->data + buf->used, data, len);
88 | buf->used += len;
89 | buf->data[buf->used] = 0;
90 | }
91 | }
92 |
93 | /*+ empty the buffer +*/
94 | void yajl_buf_clear(yajl_buf buf)
95 | {
96 | buf->used = 0;
97 | if (buf->data) {
98 | buf->data[buf->used] = 0;
99 | }
100 | }
101 |
102 | /*+ get a pointer to the beginning of the buffer +*/
103 | const unsigned char * yajl_buf_data(yajl_buf buf)
104 | {
105 | return buf->data;
106 | }
107 |
108 | /*+ get the length of the buffer +*/
109 | size_t yajl_buf_len(yajl_buf buf)
110 | {
111 | return buf->used;
112 | }
113 |
114 | /*+ truncate the buffer +*/
115 | void
116 | yajl_buf_truncate(yajl_buf buf, size_t len)
117 | {
118 | assert(len <= buf->used);
119 | buf->used = len;
120 | }