]> Dogcows Code - chaz/yoink/blob - src/Moof/yajl/src/yajl_gen.c
added missing licenses
[chaz/yoink] / src / Moof / yajl / src / yajl_gen.c
1 /*
2 * Copyright 2007-2009, 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/yajl_gen.h"
34 #include "yajl_buf.h"
35 #include "yajl_encode.h"
36
37 #include <stdlib.h>
38 #include <string.h>
39 #include <stdio.h>
40
41 typedef enum {
42 yajl_gen_start,
43 yajl_gen_map_start,
44 yajl_gen_map_key,
45 yajl_gen_map_val,
46 yajl_gen_array_start,
47 yajl_gen_in_array,
48 yajl_gen_complete,
49 yajl_gen_error
50 } yajl_gen_state;
51
52 struct yajl_gen_t
53 {
54 unsigned int depth;
55 unsigned int pretty;
56 const char * indentString;
57 yajl_gen_state state[YAJL_MAX_DEPTH];
58 yajl_buf buf;
59 /* memory allocation routines */
60 yajl_alloc_funcs alloc;
61 };
62
63 yajl_gen
64 yajl_gen_alloc(const yajl_gen_config * config,
65 const yajl_alloc_funcs * afs)
66 {
67 yajl_gen g = NULL;
68 yajl_alloc_funcs afsBuffer;
69
70 /* first order of business is to set up memory allocation routines */
71 if (afs != NULL) {
72 if (afs->malloc == NULL || afs->realloc == NULL || afs->free == NULL)
73 {
74 return NULL;
75 }
76 } else {
77 yajl_set_default_alloc_funcs(&afsBuffer);
78 afs = &afsBuffer;
79 }
80
81 g = (yajl_gen) YA_MALLOC(afs, sizeof(struct yajl_gen_t));
82 memset((void *) g, 0, sizeof(struct yajl_gen_t));
83 /* copy in pointers to allocation routines */
84 memcpy((void *) &(g->alloc), (void *) afs, sizeof(yajl_alloc_funcs));
85
86 if (config) {
87 g->pretty = config->beautify;
88 g->indentString = config->indentString ? config->indentString : " ";
89 }
90 g->buf = yajl_buf_alloc(&(g->alloc));
91
92 return g;
93 }
94
95 void
96 yajl_gen_free(yajl_gen g)
97 {
98 yajl_buf_free(g->buf);
99 YA_FREE(&(g->alloc), g);
100 }
101
102 #define INSERT_SEP \
103 if (g->state[g->depth] == yajl_gen_map_key || \
104 g->state[g->depth] == yajl_gen_in_array) { \
105 yajl_buf_append(g->buf, ",", 1); \
106 if (g->pretty) yajl_buf_append(g->buf, "\n", 1); \
107 } else if (g->state[g->depth] == yajl_gen_map_val) { \
108 yajl_buf_append(g->buf, ":", 1); \
109 if (g->pretty) yajl_buf_append(g->buf, " ", 1); \
110 }
111
112 #define INSERT_WHITESPACE \
113 if (g->pretty) { \
114 if (g->state[g->depth] != yajl_gen_map_val) { \
115 unsigned int _i; \
116 for (_i=0;_i<g->depth;_i++) \
117 yajl_buf_append(g->buf, g->indentString, \
118 strlen(g->indentString)); \
119 } \
120 }
121
122 #define ENSURE_NOT_KEY \
123 if (g->state[g->depth] == yajl_gen_map_key) { \
124 return yajl_gen_keys_must_be_strings; \
125 } \
126
127 /* check that we're not complete, or in error state. in a valid state
128 * to be generating */
129 #define ENSURE_VALID_STATE \
130 if (g->state[g->depth] == yajl_gen_error) { \
131 return yajl_gen_in_error_state;\
132 } else if (g->state[g->depth] == yajl_gen_complete) { \
133 return yajl_gen_generation_complete; \
134 }
135
136 #define INCREMENT_DEPTH \
137 if (++(g->depth) >= YAJL_MAX_DEPTH) return yajl_max_depth_exceeded;
138
139 #define APPENDED_ATOM \
140 switch (g->state[g->depth]) { \
141 case yajl_gen_start: \
142 g->state[g->depth] = yajl_gen_complete; \
143 break; \
144 case yajl_gen_map_start: \
145 case yajl_gen_map_key: \
146 g->state[g->depth] = yajl_gen_map_val; \
147 break; \
148 case yajl_gen_array_start: \
149 g->state[g->depth] = yajl_gen_in_array; \
150 break; \
151 case yajl_gen_map_val: \
152 g->state[g->depth] = yajl_gen_map_key; \
153 break; \
154 default: \
155 break; \
156 } \
157
158 #define FINAL_NEWLINE \
159 if (g->pretty && g->state[g->depth] == yajl_gen_complete) \
160 yajl_buf_append(g->buf, "\n", 1);
161
162 yajl_gen_status
163 yajl_gen_integer(yajl_gen g, long int number)
164 {
165 char i[32];
166 ENSURE_VALID_STATE; ENSURE_NOT_KEY; INSERT_SEP; INSERT_WHITESPACE;
167 sprintf(i, "%ld", number);
168 yajl_buf_append(g->buf, i, strlen(i));
169 APPENDED_ATOM;
170 FINAL_NEWLINE;
171 return yajl_gen_status_ok;
172 }
173
174 yajl_gen_status
175 yajl_gen_double(yajl_gen g, double number)
176 {
177 char i[32];
178 ENSURE_VALID_STATE; ENSURE_NOT_KEY; INSERT_SEP; INSERT_WHITESPACE;
179 sprintf(i, "%g", number);
180 yajl_buf_append(g->buf, i, strlen(i));
181 APPENDED_ATOM;
182 FINAL_NEWLINE;
183 return yajl_gen_status_ok;
184 }
185
186 yajl_gen_status
187 yajl_gen_number(yajl_gen g, const char * s, unsigned int l)
188 {
189 ENSURE_VALID_STATE; ENSURE_NOT_KEY; INSERT_SEP; INSERT_WHITESPACE;
190 yajl_buf_append(g->buf, s, l);
191 APPENDED_ATOM;
192 FINAL_NEWLINE;
193 return yajl_gen_status_ok;
194 }
195
196 yajl_gen_status
197 yajl_gen_string(yajl_gen g, const unsigned char * str,
198 unsigned int len)
199 {
200 ENSURE_VALID_STATE; INSERT_SEP; INSERT_WHITESPACE;
201 yajl_buf_append(g->buf, "\"", 1);
202 yajl_string_encode(g->buf, str, len);
203 yajl_buf_append(g->buf, "\"", 1);
204 APPENDED_ATOM;
205 FINAL_NEWLINE;
206 return yajl_gen_status_ok;
207 }
208
209 yajl_gen_status
210 yajl_gen_null(yajl_gen g)
211 {
212 ENSURE_VALID_STATE; ENSURE_NOT_KEY; INSERT_SEP; INSERT_WHITESPACE;
213 yajl_buf_append(g->buf, "null", strlen("null"));
214 APPENDED_ATOM;
215 FINAL_NEWLINE;
216 return yajl_gen_status_ok;
217 }
218
219 yajl_gen_status
220 yajl_gen_bool(yajl_gen g, int boolean)
221 {
222 const char * val = boolean ? "true" : "false";
223
224 ENSURE_VALID_STATE; ENSURE_NOT_KEY; INSERT_SEP; INSERT_WHITESPACE;
225 yajl_buf_append(g->buf, val, strlen(val));
226 APPENDED_ATOM;
227 FINAL_NEWLINE;
228 return yajl_gen_status_ok;
229 }
230
231 yajl_gen_status
232 yajl_gen_map_open(yajl_gen g)
233 {
234 ENSURE_VALID_STATE; ENSURE_NOT_KEY; INSERT_SEP; INSERT_WHITESPACE;
235 INCREMENT_DEPTH;
236
237 g->state[g->depth] = yajl_gen_map_start;
238 yajl_buf_append(g->buf, "{", 1);
239 if (g->pretty) yajl_buf_append(g->buf, "\n", 1);
240 FINAL_NEWLINE;
241 return yajl_gen_status_ok;
242 }
243
244 yajl_gen_status
245 yajl_gen_map_close(yajl_gen g)
246 {
247 ENSURE_VALID_STATE;
248 (g->depth)--;
249 if (g->pretty) yajl_buf_append(g->buf, "\n", 1);
250 APPENDED_ATOM;
251 INSERT_WHITESPACE;
252 yajl_buf_append(g->buf, "}", 1);
253 FINAL_NEWLINE;
254 return yajl_gen_status_ok;
255 }
256
257 yajl_gen_status
258 yajl_gen_array_open(yajl_gen g)
259 {
260 ENSURE_VALID_STATE; ENSURE_NOT_KEY; INSERT_SEP; INSERT_WHITESPACE;
261 INCREMENT_DEPTH;
262 g->state[g->depth] = yajl_gen_array_start;
263 yajl_buf_append(g->buf, "[", 1);
264 if (g->pretty) yajl_buf_append(g->buf, "\n", 1);
265 FINAL_NEWLINE;
266 return yajl_gen_status_ok;
267 }
268
269 yajl_gen_status
270 yajl_gen_array_close(yajl_gen g)
271 {
272 ENSURE_VALID_STATE;
273 if (g->pretty) yajl_buf_append(g->buf, "\n", 1);
274 (g->depth)--;
275 APPENDED_ATOM;
276 INSERT_WHITESPACE;
277 yajl_buf_append(g->buf, "]", 1);
278 FINAL_NEWLINE;
279 return yajl_gen_status_ok;
280 }
281
282 yajl_gen_status
283 yajl_gen_get_buf(yajl_gen g, const unsigned char ** buf,
284 unsigned int * len)
285 {
286 *buf = yajl_buf_data(g->buf);
287 *len = yajl_buf_len(g->buf);
288 return yajl_gen_status_ok;
289 }
290
291 void
292 yajl_gen_clear(yajl_gen g)
293 {
294 yajl_buf_clear(g->buf);
295 }
This page took 0.046426 seconds and 4 git commands to generate.