This is Unofficial EPICS BASE Doxygen Site
yajl_gen.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2007-2011, Lloyd Hilaiel <lloyd@hilaiel.com>
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 <stdlib.h>
18 #include <string.h>
19 #include <stdio.h>
20 #include <stdarg.h>
21 
22 #include "epicsMath.h"
23 #include "yajl_gen.h"
24 #include "yajl_buf.h"
25 #include "yajl_encode.h"
26 
27 typedef enum {
37 
38 struct yajl_gen_t
39 {
40  unsigned int flags;
41  unsigned int depth;
42  const char * indentString;
45  void * ctx; /* yajl_buf */
46  /* memory allocation routines */
48 };
49 
50 int
52 {
53  int rv = 1;
54  va_list ap;
55  va_start(ap, opt);
56 
57  switch(opt) {
58  case yajl_gen_beautify:
60  if (va_arg(ap, int)) g->flags |= opt;
61  else g->flags &= ~opt;
62  break;
64  const char *indent = va_arg(ap, const char *);
65  g->indentString = indent;
66  for (; *indent; indent++) {
67  if (*indent != '\n'
68  && *indent != '\v'
69  && *indent != '\f'
70  && *indent != '\t'
71  && *indent != '\r'
72  && *indent != ' ')
73  {
74  g->indentString = NULL;
75  rv = 0;
76  }
77  }
78  break;
79  }
81  yajl_buf_free(g->ctx);
82  g->print = va_arg(ap, const yajl_print_t);
83  g->ctx = va_arg(ap, void *);
84  break;
85  default:
86  rv = 0;
87  }
88 
89  va_end(ap);
90 
91  return rv;
92 }
93 
94 
95 
98 {
99  yajl_gen g = NULL;
100  yajl_alloc_funcs afsBuffer;
101 
102  /* first order of business is to set up memory allocation routines */
103  if (afs != NULL) {
104  if (afs->malloc == NULL || afs->realloc == NULL || afs->free == NULL)
105  {
106  return NULL;
107  }
108  } else {
109  yajl_set_default_alloc_funcs(&afsBuffer);
110  afs = &afsBuffer;
111  }
112 
113  g = (yajl_gen) YA_MALLOC(afs, sizeof(struct yajl_gen_t));
114  if (!g) return NULL;
115 
116  memset((void *) g, 0, sizeof(struct yajl_gen_t));
117  /* copy in pointers to allocation routines */
118  memcpy((void *) &(g->alloc), (void *) afs, sizeof(yajl_alloc_funcs));
119 
121  g->ctx = yajl_buf_alloc(&(g->alloc));
122  g->indentString = " ";
123 
124  return g;
125 }
126 
127 void
129 {
131  YA_FREE(&(g->alloc), g);
132 }
133 
134 #define INSERT_SEP \
135  if (g->state[g->depth] == yajl_gen_map_key || \
136  g->state[g->depth] == yajl_gen_in_array) { \
137  g->print(g->ctx, ",", 1); \
138  if ((g->flags & yajl_gen_beautify)) g->print(g->ctx, "\n", 1); \
139  } else if (g->state[g->depth] == yajl_gen_map_val) { \
140  g->print(g->ctx, ":", 1); \
141  if ((g->flags & yajl_gen_beautify)) g->print(g->ctx, " ", 1); \
142  }
143 
144 #define INSERT_WHITESPACE \
145  if ((g->flags & yajl_gen_beautify)) { \
146  if (g->state[g->depth] != yajl_gen_map_val) { \
147  unsigned int _i; \
148  for (_i=0;_i<g->depth;_i++) \
149  g->print(g->ctx, \
150  g->indentString, \
151  (unsigned int)strlen(g->indentString)); \
152  } \
153  }
154 
155 #define ENSURE_NOT_KEY \
156  if (g->state[g->depth] == yajl_gen_map_key || \
157  g->state[g->depth] == yajl_gen_map_start) { \
158  return yajl_gen_keys_must_be_strings; \
159  } \
160 
161 /* check that we're not complete, or in error state. in a valid state
162  * to be generating */
163 #define ENSURE_VALID_STATE \
164  if (g->state[g->depth] == yajl_gen_error) { \
165  return yajl_gen_in_error_state;\
166  } else if (g->state[g->depth] == yajl_gen_complete) { \
167  return yajl_gen_generation_complete; \
168  }
169 
170 #define INCREMENT_DEPTH \
171  if (++(g->depth) >= YAJL_MAX_DEPTH) return yajl_max_depth_exceeded;
172 
173 #define DECREMENT_DEPTH \
174  if (--(g->depth) >= YAJL_MAX_DEPTH) return yajl_max_depth_exceeded;
175 
176 #define APPENDED_ATOM \
177  switch (g->state[g->depth]) { \
178  case yajl_gen_start: \
179  g->state[g->depth] = yajl_gen_complete; \
180  break; \
181  case yajl_gen_map_start: \
182  case yajl_gen_map_key: \
183  g->state[g->depth] = yajl_gen_map_val; \
184  break; \
185  case yajl_gen_array_start: \
186  g->state[g->depth] = yajl_gen_in_array; \
187  break; \
188  case yajl_gen_map_val: \
189  g->state[g->depth] = yajl_gen_map_key; \
190  break; \
191  default: \
192  break; \
193  } \
194 
195 #define FINAL_NEWLINE \
196  if ((g->flags & yajl_gen_beautify) && g->state[g->depth] == yajl_gen_complete) \
197  g->print(g->ctx, "\n", 1);
198 
200 yajl_gen_integer(yajl_gen g, long long int number)
201 {
202  char i[32];
204  sprintf(i, "%lld", number);
205  g->print(g->ctx, i, (unsigned int)strlen(i));
208  return yajl_gen_status_ok;
209 }
210 
212 yajl_gen_double(yajl_gen g, double number)
213 {
214  char i[32];
216  if (isnan(number) || isinf(number)) return yajl_gen_invalid_number;
218  sprintf(i, "%.20g", number);
219  g->print(g->ctx, i, (unsigned int)strlen(i));
222  return yajl_gen_status_ok;
223 }
224 
226 yajl_gen_number(yajl_gen g, const char * s, size_t l)
227 {
229  g->print(g->ctx, s, l);
232  return yajl_gen_status_ok;
233 }
234 
236 yajl_gen_string(yajl_gen g, const unsigned char * str,
237  size_t len)
238 {
239  // if validation is enabled, check that the string is valid utf8
240  // XXX: This checking could be done a little faster, in the same pass as
241  // the string encoding
242  if (g->flags & yajl_gen_validate_utf8) {
243  if (!yajl_string_validate_utf8(str, len)) {
245  }
246  }
248  g->print(g->ctx, "\"", 1);
249  yajl_string_encode(g->print, g->ctx, str, len, g->flags & yajl_gen_escape_solidus);
250  g->print(g->ctx, "\"", 1);
253  return yajl_gen_status_ok;
254 }
255 
258 {
260  g->print(g->ctx, "null", strlen("null"));
263  return yajl_gen_status_ok;
264 }
265 
267 yajl_gen_bool(yajl_gen g, int boolean)
268 {
269  const char * val = boolean ? "true" : "false";
270 
272  g->print(g->ctx, val, (unsigned int)strlen(val));
275  return yajl_gen_status_ok;
276 }
277 
280 {
283 
284  g->state[g->depth] = yajl_gen_map_start;
285  g->print(g->ctx, "{", 1);
286  if ((g->flags & yajl_gen_beautify)) g->print(g->ctx, "\n", 1);
288  return yajl_gen_status_ok;
289 }
290 
293 {
296 
297  if ((g->flags & yajl_gen_beautify)) g->print(g->ctx, "\n", 1);
300  g->print(g->ctx, "}", 1);
302  return yajl_gen_status_ok;
303 }
304 
307 {
311  g->print(g->ctx, "[", 1);
312  if ((g->flags & yajl_gen_beautify)) g->print(g->ctx, "\n", 1);
314  return yajl_gen_status_ok;
315 }
316 
319 {
322  if ((g->flags & yajl_gen_beautify)) g->print(g->ctx, "\n", 1);
325  g->print(g->ctx, "]", 1);
327  return yajl_gen_status_ok;
328 }
329 
331 yajl_gen_get_buf(yajl_gen g, const unsigned char ** buf,
332  size_t * len)
333 {
335  *buf = yajl_buf_data((yajl_buf)g->ctx);
336  *len = yajl_buf_len((yajl_buf)g->ctx);
337  return yajl_gen_status_ok;
338 }
339 
340 void
342 {
344 }
struct yajl_gen_t * yajl_gen
Definition: yajl_gen.h:59
yajl_gen_status yajl_gen_array_open(yajl_gen g)
Definition: yajl_gen.c:306
int yajl_string_validate_utf8(const unsigned char *s, size_t len)
Definition: yajl_encode.c:182
yajl_free_func free
Definition: yajl_common.h:75
#define YA_MALLOC(afs, sz)
Definition: yajl_alloc.h:32
yajl_gen_status yajl_gen_number(yajl_gen g, const char *s, size_t l)
Definition: yajl_gen.c:226
int yajl_gen_config(yajl_gen g, yajl_gen_option opt,...)
Definition: yajl_gen.c:51
#define YA_FREE(afs, ptr)
Definition: yajl_alloc.h:33
int i
Definition: scan.c:967
#define APPENDED_ATOM
Definition: yajl_gen.c:176
Interface to YAJL&#39;s JSON generation facilities.
#define FINAL_NEWLINE
Definition: yajl_gen.c:195
yajl_buf yajl_buf_alloc(yajl_alloc_funcs *alloc)
Definition: yajl_buf.c:56
yajl_gen_status yajl_gen_get_buf(yajl_gen g, const unsigned char **buf, size_t *len)
Definition: yajl_gen.c:331
#define isinf(x)
Definition: epicsMath.h:16
#define INSERT_WHITESPACE
Definition: yajl_gen.c:144
yajl_gen_state state[YAJL_MAX_DEPTH]
Definition: yajl_gen.c:43
#define NULL
Definition: catime.c:38
#define str(v)
#define ENSURE_NOT_KEY
Definition: yajl_gen.c:155
#define INCREMENT_DEPTH
Definition: yajl_gen.c:170
void yajl_set_default_alloc_funcs(yajl_alloc_funcs *yaf)
Definition: yajl_alloc.c:43
void yajl_gen_clear(yajl_gen g)
Definition: yajl_gen.c:341
size_t yajl_buf_len(yajl_buf buf)
Definition: yajl_buf.c:97
yajl_realloc_func realloc
Definition: yajl_common.h:72
yajl_gen_status yajl_gen_bool(yajl_gen g, int boolean)
Definition: yajl_gen.c:267
void yajl_buf_append(yajl_buf buf, const void *data, size_t len)
Definition: yajl_buf.c:75
#define ENSURE_VALID_STATE
Definition: yajl_gen.c:163
#define DECREMENT_DEPTH
Definition: yajl_gen.c:173
#define isnan(x)
Definition: epicsMath.h:21
yajl_gen_state
Definition: yajl_gen.c:27
void yajl_gen_free(yajl_gen g)
Definition: yajl_gen.c:128
yajl_gen_status yajl_gen_map_close(yajl_gen g)
Definition: yajl_gen.c:292
yajl_gen_status yajl_gen_null(yajl_gen g)
Definition: yajl_gen.c:257
yajl_alloc_funcs alloc
Definition: yajl_gen.c:47
yajl_gen yajl_gen_alloc(const yajl_alloc_funcs *afs)
Definition: yajl_gen.c:97
yajl_gen_status yajl_gen_double(yajl_gen g, double number)
Definition: yajl_gen.c:212
void yajl_buf_clear(yajl_buf buf)
Definition: yajl_buf.c:86
yajl_gen_status yajl_gen_integer(yajl_gen g, long long int number)
Definition: yajl_gen.c:200
yajl_gen_status yajl_gen_map_open(yajl_gen g)
Definition: yajl_gen.c:279
unsigned int flags
Definition: yajl_gen.c:40
yajl_print_t print
Definition: yajl_gen.c:44
void yajl_buf_free(yajl_buf buf)
Definition: yajl_buf.c:68
#define INSERT_SEP
Definition: yajl_gen.c:134
#define YAJL_MAX_DEPTH
Definition: yajl_common.h:49
const char * indentString
Definition: yajl_gen.c:42
yajl_gen_option
Definition: yajl_gen.h:69
void(* yajl_print_t)(void *ctx, const char *str, size_t len)
Definition: yajl_gen.h:62
void yajl_string_encode(const yajl_print_t print, void *ctx, const unsigned char *str, size_t len, int escape_solidus)
Definition: yajl_encode.c:32
unsigned int depth
Definition: yajl_gen.c:41
yajl_malloc_func malloc
Definition: yajl_common.h:70
const unsigned char * yajl_buf_data(yajl_buf buf)
Definition: yajl_buf.c:92
yajl_gen_status
Definition: yajl_gen.h:32
yajl_gen_status yajl_gen_array_close(yajl_gen g)
Definition: yajl_gen.c:318
void * ctx
Definition: yajl_gen.c:45
yajl_gen_status yajl_gen_string(yajl_gen g, const unsigned char *str, size_t len)
Definition: yajl_gen.c:236