yajl - JSON library working with the compiler. URL: http://lloyd.github.com/yajl/

Dependencies:   mbed

Committer:
rolf
Date:
Wed Nov 18 17:56:51 2009 +0000
Revision:
0:34f4a53d4ca3

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
rolf 0:34f4a53d4ca3 1 /*
rolf 0:34f4a53d4ca3 2 * Copyright 2007-2009, Lloyd Hilaiel.
rolf 0:34f4a53d4ca3 3 *
rolf 0:34f4a53d4ca3 4 * Redistribution and use in source and binary forms, with or without
rolf 0:34f4a53d4ca3 5 * modification, are permitted provided that the following conditions are
rolf 0:34f4a53d4ca3 6 * met:
rolf 0:34f4a53d4ca3 7 *
rolf 0:34f4a53d4ca3 8 * 1. Redistributions of source code must retain the above copyright
rolf 0:34f4a53d4ca3 9 * notice, this list of conditions and the following disclaimer.
rolf 0:34f4a53d4ca3 10 *
rolf 0:34f4a53d4ca3 11 * 2. Redistributions in binary form must reproduce the above copyright
rolf 0:34f4a53d4ca3 12 * notice, this list of conditions and the following disclaimer in
rolf 0:34f4a53d4ca3 13 * the documentation and/or other materials provided with the
rolf 0:34f4a53d4ca3 14 * distribution.
rolf 0:34f4a53d4ca3 15 *
rolf 0:34f4a53d4ca3 16 * 3. Neither the name of Lloyd Hilaiel nor the names of its
rolf 0:34f4a53d4ca3 17 * contributors may be used to endorse or promote products derived
rolf 0:34f4a53d4ca3 18 * from this software without specific prior written permission.
rolf 0:34f4a53d4ca3 19 *
rolf 0:34f4a53d4ca3 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
rolf 0:34f4a53d4ca3 21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
rolf 0:34f4a53d4ca3 22 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
rolf 0:34f4a53d4ca3 23 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
rolf 0:34f4a53d4ca3 24 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
rolf 0:34f4a53d4ca3 25 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
rolf 0:34f4a53d4ca3 26 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
rolf 0:34f4a53d4ca3 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
rolf 0:34f4a53d4ca3 28 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
rolf 0:34f4a53d4ca3 29 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
rolf 0:34f4a53d4ca3 30 * POSSIBILITY OF SUCH DAMAGE.
rolf 0:34f4a53d4ca3 31 */
rolf 0:34f4a53d4ca3 32 #ifdef __cplusplus
rolf 0:34f4a53d4ca3 33 extern "C" {
rolf 0:34f4a53d4ca3 34 #endif
rolf 0:34f4a53d4ca3 35
rolf 0:34f4a53d4ca3 36 #include "yajl/yajl_gen.h"
rolf 0:34f4a53d4ca3 37 #include "yajl_buf.h"
rolf 0:34f4a53d4ca3 38 #include "yajl_encode.h"
rolf 0:34f4a53d4ca3 39
rolf 0:34f4a53d4ca3 40 #include <stdlib.h>
rolf 0:34f4a53d4ca3 41 #include <string.h>
rolf 0:34f4a53d4ca3 42 #include <stdio.h>
rolf 0:34f4a53d4ca3 43
rolf 0:34f4a53d4ca3 44 typedef enum {
rolf 0:34f4a53d4ca3 45 yajl_gen_start,
rolf 0:34f4a53d4ca3 46 yajl_gen_map_start,
rolf 0:34f4a53d4ca3 47 yajl_gen_map_key,
rolf 0:34f4a53d4ca3 48 yajl_gen_map_val,
rolf 0:34f4a53d4ca3 49 yajl_gen_array_start,
rolf 0:34f4a53d4ca3 50 yajl_gen_in_array,
rolf 0:34f4a53d4ca3 51 yajl_gen_complete,
rolf 0:34f4a53d4ca3 52 yajl_gen_error
rolf 0:34f4a53d4ca3 53 } yajl_gen_state;
rolf 0:34f4a53d4ca3 54
rolf 0:34f4a53d4ca3 55 struct yajl_gen_t
rolf 0:34f4a53d4ca3 56 {
rolf 0:34f4a53d4ca3 57 unsigned int depth;
rolf 0:34f4a53d4ca3 58 unsigned int pretty;
rolf 0:34f4a53d4ca3 59 const char * indentString;
rolf 0:34f4a53d4ca3 60 yajl_gen_state state[YAJL_MAX_DEPTH];
rolf 0:34f4a53d4ca3 61 yajl_buf buf;
rolf 0:34f4a53d4ca3 62 /* memory allocation routines */
rolf 0:34f4a53d4ca3 63 yajl_alloc_funcs alloc;
rolf 0:34f4a53d4ca3 64 };
rolf 0:34f4a53d4ca3 65
rolf 0:34f4a53d4ca3 66 yajl_gen
rolf 0:34f4a53d4ca3 67 yajl_gen_alloc(const yajl_gen_config * config,
rolf 0:34f4a53d4ca3 68 const yajl_alloc_funcs * afs)
rolf 0:34f4a53d4ca3 69 {
rolf 0:34f4a53d4ca3 70 yajl_gen g = NULL;
rolf 0:34f4a53d4ca3 71 yajl_alloc_funcs afsBuffer;
rolf 0:34f4a53d4ca3 72
rolf 0:34f4a53d4ca3 73 /* first order of business is to set up memory allocation routines */
rolf 0:34f4a53d4ca3 74 if (afs != NULL) {
rolf 0:34f4a53d4ca3 75 if (afs->malloc == NULL || afs->realloc == NULL || afs->free == NULL)
rolf 0:34f4a53d4ca3 76 {
rolf 0:34f4a53d4ca3 77 return NULL;
rolf 0:34f4a53d4ca3 78 }
rolf 0:34f4a53d4ca3 79 } else {
rolf 0:34f4a53d4ca3 80 yajl_set_default_alloc_funcs(&afsBuffer);
rolf 0:34f4a53d4ca3 81 afs = &afsBuffer;
rolf 0:34f4a53d4ca3 82 }
rolf 0:34f4a53d4ca3 83
rolf 0:34f4a53d4ca3 84 g = (yajl_gen) YA_MALLOC(afs, sizeof(struct yajl_gen_t));
rolf 0:34f4a53d4ca3 85 memset((void *) g, 0, sizeof(struct yajl_gen_t));
rolf 0:34f4a53d4ca3 86 /* copy in pointers to allocation routines */
rolf 0:34f4a53d4ca3 87 memcpy((void *) &(g->alloc), (void *) afs, sizeof(yajl_alloc_funcs));
rolf 0:34f4a53d4ca3 88
rolf 0:34f4a53d4ca3 89 if (config) {
rolf 0:34f4a53d4ca3 90 g->pretty = config->beautify;
rolf 0:34f4a53d4ca3 91 g->indentString = config->indentString ? config->indentString : " ";
rolf 0:34f4a53d4ca3 92 }
rolf 0:34f4a53d4ca3 93 g->buf = yajl_buf_alloc(&(g->alloc));
rolf 0:34f4a53d4ca3 94
rolf 0:34f4a53d4ca3 95 return g;
rolf 0:34f4a53d4ca3 96 }
rolf 0:34f4a53d4ca3 97
rolf 0:34f4a53d4ca3 98 void
rolf 0:34f4a53d4ca3 99 yajl_gen_free(yajl_gen g)
rolf 0:34f4a53d4ca3 100 {
rolf 0:34f4a53d4ca3 101 yajl_buf_free(g->buf);
rolf 0:34f4a53d4ca3 102 YA_FREE(&(g->alloc), g);
rolf 0:34f4a53d4ca3 103 }
rolf 0:34f4a53d4ca3 104
rolf 0:34f4a53d4ca3 105 #define INSERT_SEP \
rolf 0:34f4a53d4ca3 106 if (g->state[g->depth] == yajl_gen_map_key || \
rolf 0:34f4a53d4ca3 107 g->state[g->depth] == yajl_gen_in_array) { \
rolf 0:34f4a53d4ca3 108 yajl_buf_append(g->buf, ",", 1); \
rolf 0:34f4a53d4ca3 109 if (g->pretty) yajl_buf_append(g->buf, "\n", 1); \
rolf 0:34f4a53d4ca3 110 } else if (g->state[g->depth] == yajl_gen_map_val) { \
rolf 0:34f4a53d4ca3 111 yajl_buf_append(g->buf, ":", 1); \
rolf 0:34f4a53d4ca3 112 if (g->pretty) yajl_buf_append(g->buf, " ", 1); \
rolf 0:34f4a53d4ca3 113 }
rolf 0:34f4a53d4ca3 114
rolf 0:34f4a53d4ca3 115 #define INSERT_WHITESPACE \
rolf 0:34f4a53d4ca3 116 if (g->pretty) { \
rolf 0:34f4a53d4ca3 117 if (g->state[g->depth] != yajl_gen_map_val) { \
rolf 0:34f4a53d4ca3 118 unsigned int _i; \
rolf 0:34f4a53d4ca3 119 for (_i=0;_i<g->depth;_i++) \
rolf 0:34f4a53d4ca3 120 yajl_buf_append(g->buf, g->indentString, \
rolf 0:34f4a53d4ca3 121 strlen(g->indentString)); \
rolf 0:34f4a53d4ca3 122 } \
rolf 0:34f4a53d4ca3 123 }
rolf 0:34f4a53d4ca3 124
rolf 0:34f4a53d4ca3 125 #define ENSURE_NOT_KEY \
rolf 0:34f4a53d4ca3 126 if (g->state[g->depth] == yajl_gen_map_key) { \
rolf 0:34f4a53d4ca3 127 return yajl_gen_keys_must_be_strings; \
rolf 0:34f4a53d4ca3 128 } \
rolf 0:34f4a53d4ca3 129
rolf 0:34f4a53d4ca3 130 /* check that we're not complete, or in error state. in a valid state
rolf 0:34f4a53d4ca3 131 * to be generating */
rolf 0:34f4a53d4ca3 132 #define ENSURE_VALID_STATE \
rolf 0:34f4a53d4ca3 133 if (g->state[g->depth] == yajl_gen_error) { \
rolf 0:34f4a53d4ca3 134 return yajl_gen_in_error_state;\
rolf 0:34f4a53d4ca3 135 } else if (g->state[g->depth] == yajl_gen_complete) { \
rolf 0:34f4a53d4ca3 136 return yajl_gen_generation_complete; \
rolf 0:34f4a53d4ca3 137 }
rolf 0:34f4a53d4ca3 138
rolf 0:34f4a53d4ca3 139 #define INCREMENT_DEPTH \
rolf 0:34f4a53d4ca3 140 if (++(g->depth) >= YAJL_MAX_DEPTH) return yajl_max_depth_exceeded;
rolf 0:34f4a53d4ca3 141
rolf 0:34f4a53d4ca3 142 #define APPENDED_ATOM \
rolf 0:34f4a53d4ca3 143 switch (g->state[g->depth]) { \
rolf 0:34f4a53d4ca3 144 case yajl_gen_start: \
rolf 0:34f4a53d4ca3 145 g->state[g->depth] = yajl_gen_complete; \
rolf 0:34f4a53d4ca3 146 break; \
rolf 0:34f4a53d4ca3 147 case yajl_gen_map_start: \
rolf 0:34f4a53d4ca3 148 case yajl_gen_map_key: \
rolf 0:34f4a53d4ca3 149 g->state[g->depth] = yajl_gen_map_val; \
rolf 0:34f4a53d4ca3 150 break; \
rolf 0:34f4a53d4ca3 151 case yajl_gen_array_start: \
rolf 0:34f4a53d4ca3 152 g->state[g->depth] = yajl_gen_in_array; \
rolf 0:34f4a53d4ca3 153 break; \
rolf 0:34f4a53d4ca3 154 case yajl_gen_map_val: \
rolf 0:34f4a53d4ca3 155 g->state[g->depth] = yajl_gen_map_key; \
rolf 0:34f4a53d4ca3 156 break; \
rolf 0:34f4a53d4ca3 157 default: \
rolf 0:34f4a53d4ca3 158 break; \
rolf 0:34f4a53d4ca3 159 } \
rolf 0:34f4a53d4ca3 160
rolf 0:34f4a53d4ca3 161 #define FINAL_NEWLINE \
rolf 0:34f4a53d4ca3 162 if (g->pretty && g->state[g->depth] == yajl_gen_complete) \
rolf 0:34f4a53d4ca3 163 yajl_buf_append(g->buf, "\n", 1);
rolf 0:34f4a53d4ca3 164
rolf 0:34f4a53d4ca3 165 yajl_gen_status
rolf 0:34f4a53d4ca3 166 yajl_gen_integer(yajl_gen g, long int number)
rolf 0:34f4a53d4ca3 167 {
rolf 0:34f4a53d4ca3 168 char i[32];
rolf 0:34f4a53d4ca3 169 ENSURE_VALID_STATE; ENSURE_NOT_KEY; INSERT_SEP; INSERT_WHITESPACE;
rolf 0:34f4a53d4ca3 170 sprintf(i, "%ld", number);
rolf 0:34f4a53d4ca3 171 yajl_buf_append(g->buf, i, strlen(i));
rolf 0:34f4a53d4ca3 172 APPENDED_ATOM;
rolf 0:34f4a53d4ca3 173 FINAL_NEWLINE;
rolf 0:34f4a53d4ca3 174 return yajl_gen_status_ok;
rolf 0:34f4a53d4ca3 175 }
rolf 0:34f4a53d4ca3 176
rolf 0:34f4a53d4ca3 177 yajl_gen_status
rolf 0:34f4a53d4ca3 178 yajl_gen_double(yajl_gen g, double number)
rolf 0:34f4a53d4ca3 179 {
rolf 0:34f4a53d4ca3 180 char i[32];
rolf 0:34f4a53d4ca3 181 ENSURE_VALID_STATE; ENSURE_NOT_KEY; INSERT_SEP; INSERT_WHITESPACE;
rolf 0:34f4a53d4ca3 182 sprintf(i, "%g", number);
rolf 0:34f4a53d4ca3 183 yajl_buf_append(g->buf, i, strlen(i));
rolf 0:34f4a53d4ca3 184 APPENDED_ATOM;
rolf 0:34f4a53d4ca3 185 FINAL_NEWLINE;
rolf 0:34f4a53d4ca3 186 return yajl_gen_status_ok;
rolf 0:34f4a53d4ca3 187 }
rolf 0:34f4a53d4ca3 188
rolf 0:34f4a53d4ca3 189 yajl_gen_status
rolf 0:34f4a53d4ca3 190 yajl_gen_number(yajl_gen g, const char * s, unsigned int l)
rolf 0:34f4a53d4ca3 191 {
rolf 0:34f4a53d4ca3 192 ENSURE_VALID_STATE; ENSURE_NOT_KEY; INSERT_SEP; INSERT_WHITESPACE;
rolf 0:34f4a53d4ca3 193 yajl_buf_append(g->buf, s, l);
rolf 0:34f4a53d4ca3 194 APPENDED_ATOM;
rolf 0:34f4a53d4ca3 195 FINAL_NEWLINE;
rolf 0:34f4a53d4ca3 196 return yajl_gen_status_ok;
rolf 0:34f4a53d4ca3 197 }
rolf 0:34f4a53d4ca3 198
rolf 0:34f4a53d4ca3 199 yajl_gen_status
rolf 0:34f4a53d4ca3 200 yajl_gen_string(yajl_gen g, const unsigned char * str,
rolf 0:34f4a53d4ca3 201 unsigned int len)
rolf 0:34f4a53d4ca3 202 {
rolf 0:34f4a53d4ca3 203 ENSURE_VALID_STATE; INSERT_SEP; INSERT_WHITESPACE;
rolf 0:34f4a53d4ca3 204 yajl_buf_append(g->buf, "\"", 1);
rolf 0:34f4a53d4ca3 205 yajl_string_encode(g->buf, str, len);
rolf 0:34f4a53d4ca3 206 yajl_buf_append(g->buf, "\"", 1);
rolf 0:34f4a53d4ca3 207 APPENDED_ATOM;
rolf 0:34f4a53d4ca3 208 FINAL_NEWLINE;
rolf 0:34f4a53d4ca3 209 return yajl_gen_status_ok;
rolf 0:34f4a53d4ca3 210 }
rolf 0:34f4a53d4ca3 211
rolf 0:34f4a53d4ca3 212 yajl_gen_status
rolf 0:34f4a53d4ca3 213 yajl_gen_null(yajl_gen g)
rolf 0:34f4a53d4ca3 214 {
rolf 0:34f4a53d4ca3 215 ENSURE_VALID_STATE; ENSURE_NOT_KEY; INSERT_SEP; INSERT_WHITESPACE;
rolf 0:34f4a53d4ca3 216 yajl_buf_append(g->buf, "null", strlen("null"));
rolf 0:34f4a53d4ca3 217 APPENDED_ATOM;
rolf 0:34f4a53d4ca3 218 FINAL_NEWLINE;
rolf 0:34f4a53d4ca3 219 return yajl_gen_status_ok;
rolf 0:34f4a53d4ca3 220 }
rolf 0:34f4a53d4ca3 221
rolf 0:34f4a53d4ca3 222 yajl_gen_status
rolf 0:34f4a53d4ca3 223 yajl_gen_bool(yajl_gen g, int boolean)
rolf 0:34f4a53d4ca3 224 {
rolf 0:34f4a53d4ca3 225 const char * val = boolean ? "true" : "false";
rolf 0:34f4a53d4ca3 226
rolf 0:34f4a53d4ca3 227 ENSURE_VALID_STATE; ENSURE_NOT_KEY; INSERT_SEP; INSERT_WHITESPACE;
rolf 0:34f4a53d4ca3 228 yajl_buf_append(g->buf, val, strlen(val));
rolf 0:34f4a53d4ca3 229 APPENDED_ATOM;
rolf 0:34f4a53d4ca3 230 FINAL_NEWLINE;
rolf 0:34f4a53d4ca3 231 return yajl_gen_status_ok;
rolf 0:34f4a53d4ca3 232 }
rolf 0:34f4a53d4ca3 233
rolf 0:34f4a53d4ca3 234 yajl_gen_status
rolf 0:34f4a53d4ca3 235 yajl_gen_map_open(yajl_gen g)
rolf 0:34f4a53d4ca3 236 {
rolf 0:34f4a53d4ca3 237 ENSURE_VALID_STATE; ENSURE_NOT_KEY; INSERT_SEP; INSERT_WHITESPACE;
rolf 0:34f4a53d4ca3 238 INCREMENT_DEPTH;
rolf 0:34f4a53d4ca3 239
rolf 0:34f4a53d4ca3 240 g->state[g->depth] = yajl_gen_map_start;
rolf 0:34f4a53d4ca3 241 yajl_buf_append(g->buf, "{", 1);
rolf 0:34f4a53d4ca3 242 if (g->pretty) yajl_buf_append(g->buf, "\n", 1);
rolf 0:34f4a53d4ca3 243 FINAL_NEWLINE;
rolf 0:34f4a53d4ca3 244 return yajl_gen_status_ok;
rolf 0:34f4a53d4ca3 245 }
rolf 0:34f4a53d4ca3 246
rolf 0:34f4a53d4ca3 247 yajl_gen_status
rolf 0:34f4a53d4ca3 248 yajl_gen_map_close(yajl_gen g)
rolf 0:34f4a53d4ca3 249 {
rolf 0:34f4a53d4ca3 250 ENSURE_VALID_STATE;
rolf 0:34f4a53d4ca3 251 (g->depth)--;
rolf 0:34f4a53d4ca3 252 if (g->pretty) yajl_buf_append(g->buf, "\n", 1);
rolf 0:34f4a53d4ca3 253 APPENDED_ATOM;
rolf 0:34f4a53d4ca3 254 INSERT_WHITESPACE;
rolf 0:34f4a53d4ca3 255 yajl_buf_append(g->buf, "}", 1);
rolf 0:34f4a53d4ca3 256 FINAL_NEWLINE;
rolf 0:34f4a53d4ca3 257 return yajl_gen_status_ok;
rolf 0:34f4a53d4ca3 258 }
rolf 0:34f4a53d4ca3 259
rolf 0:34f4a53d4ca3 260 yajl_gen_status
rolf 0:34f4a53d4ca3 261 yajl_gen_array_open(yajl_gen g)
rolf 0:34f4a53d4ca3 262 {
rolf 0:34f4a53d4ca3 263 ENSURE_VALID_STATE; ENSURE_NOT_KEY; INSERT_SEP; INSERT_WHITESPACE;
rolf 0:34f4a53d4ca3 264 INCREMENT_DEPTH;
rolf 0:34f4a53d4ca3 265 g->state[g->depth] = yajl_gen_array_start;
rolf 0:34f4a53d4ca3 266 yajl_buf_append(g->buf, "[", 1);
rolf 0:34f4a53d4ca3 267 if (g->pretty) yajl_buf_append(g->buf, "\n", 1);
rolf 0:34f4a53d4ca3 268 FINAL_NEWLINE;
rolf 0:34f4a53d4ca3 269 return yajl_gen_status_ok;
rolf 0:34f4a53d4ca3 270 }
rolf 0:34f4a53d4ca3 271
rolf 0:34f4a53d4ca3 272 yajl_gen_status
rolf 0:34f4a53d4ca3 273 yajl_gen_array_close(yajl_gen g)
rolf 0:34f4a53d4ca3 274 {
rolf 0:34f4a53d4ca3 275 ENSURE_VALID_STATE;
rolf 0:34f4a53d4ca3 276 if (g->pretty) yajl_buf_append(g->buf, "\n", 1);
rolf 0:34f4a53d4ca3 277 (g->depth)--;
rolf 0:34f4a53d4ca3 278 APPENDED_ATOM;
rolf 0:34f4a53d4ca3 279 INSERT_WHITESPACE;
rolf 0:34f4a53d4ca3 280 yajl_buf_append(g->buf, "]", 1);
rolf 0:34f4a53d4ca3 281 FINAL_NEWLINE;
rolf 0:34f4a53d4ca3 282 return yajl_gen_status_ok;
rolf 0:34f4a53d4ca3 283 }
rolf 0:34f4a53d4ca3 284
rolf 0:34f4a53d4ca3 285 yajl_gen_status
rolf 0:34f4a53d4ca3 286 yajl_gen_get_buf(yajl_gen g, const unsigned char ** buf,
rolf 0:34f4a53d4ca3 287 unsigned int * len)
rolf 0:34f4a53d4ca3 288 {
rolf 0:34f4a53d4ca3 289 *buf = yajl_buf_data(g->buf);
rolf 0:34f4a53d4ca3 290 *len = yajl_buf_len(g->buf);
rolf 0:34f4a53d4ca3 291 return yajl_gen_status_ok;
rolf 0:34f4a53d4ca3 292 }
rolf 0:34f4a53d4ca3 293
rolf 0:34f4a53d4ca3 294 void
rolf 0:34f4a53d4ca3 295 yajl_gen_clear(yajl_gen g)
rolf 0:34f4a53d4ca3 296 {
rolf 0:34f4a53d4ca3 297 yajl_buf_clear(g->buf);
rolf 0:34f4a53d4ca3 298 }
rolf 0:34f4a53d4ca3 299
rolf 0:34f4a53d4ca3 300 #ifdef __cplusplus
rolf 0:34f4a53d4ca3 301 }
rolf 0:34f4a53d4ca3 302 #endif