1/* JSON Create ZZJSON structures 2 * ZZJSON - Copyright (C) 2008 by Ivo van Poorten 3 * License: GNU Lesser General Public License version 2.1 4 */ 5 6#include "zzjson.h" 7#include <stdlib.h> 8#include <string.h> 9#include <stdarg.h> 10 11#ifdef CONFIG_NO_ERROR_MESSAGES 12#define ERROR(x...) 13#else 14#define ERROR(x...) config->error(config->ehandle, ##x) 15#endif 16#define MEMERROR() ERROR("out of memory") 17 18static ZZJSON *zzjson_create_templ(ZZJSON_CONFIG *config, ZZJSON_TYPE type) { 19 ZZJSON *zzjson = config->calloc(1, sizeof(ZZJSON)); 20 if (!zzjson) MEMERROR(); 21 else zzjson->type = type; 22 return zzjson; 23} 24 25ZZJSON *zzjson_create_true(ZZJSON_CONFIG *config) { 26 return zzjson_create_templ(config, ZZJSON_TRUE); 27} 28 29ZZJSON *zzjson_create_false(ZZJSON_CONFIG *config) { 30 return zzjson_create_templ(config, ZZJSON_FALSE); 31} 32 33ZZJSON *zzjson_create_null(ZZJSON_CONFIG *config) { 34 return zzjson_create_templ(config, ZZJSON_NULL); 35} 36 37ZZJSON *zzjson_create_number_d(ZZJSON_CONFIG *config, double d) { 38 ZZJSON *zzjson = zzjson_create_templ(config, ZZJSON_NUMBER_DOUBLE); 39 if (zzjson) 40 zzjson->value.number.val.dval = d; 41 return zzjson; 42} 43 44ZZJSON *zzjson_create_number_i(ZZJSON_CONFIG *config, long long i) { 45 ZZJSON *zzjson = zzjson_create_templ(config, ZZJSON_NUMBER_NEGINT); 46 if (zzjson) { 47 zzjson->type = i<0LL ? ZZJSON_NUMBER_NEGINT : ZZJSON_NUMBER_POSINT; 48 zzjson->value.number.val.ival = llabs(i); 49 } 50 return zzjson; 51} 52 53/* sdup mimics strdup, but avoids having another function pointer in config */ 54static char *sdup(ZZJSON_CONFIG *config, char *s) { 55 size_t slen = strlen(s)+1; 56 char *scopy = config->malloc(slen); 57 58 if (!scopy) MEMERROR(); 59 else memcpy(scopy, s, slen); 60 return scopy; 61} 62 63ZZJSON *zzjson_create_string(ZZJSON_CONFIG *config, char *s) { 64 ZZJSON *zzjson = NULL; 65 char *scopy; 66 67 if (!(scopy = sdup(config,s))) return zzjson; 68 69 if ((zzjson = zzjson_create_templ(config, ZZJSON_STRING))) 70 zzjson->value.string.string = scopy; 71 else 72 config->free(scopy); 73 74 return zzjson; 75} 76 77ZZJSON *zzjson_create_array(ZZJSON_CONFIG *config, ...) { 78 ZZJSON *zzjson, *retval, *val; 79 va_list ap; 80 81 if (!(zzjson = zzjson_create_templ(config, ZZJSON_ARRAY))) return zzjson; 82 retval = zzjson; 83 84 va_start(ap, config); 85 val = va_arg(ap, ZZJSON *); 86 while (val) { 87 zzjson->value.array.val = val; 88 val = va_arg(ap, ZZJSON *); 89 90 if (val) { 91 ZZJSON *next = zzjson_create_templ(config, ZZJSON_ARRAY); 92 if (!next) { 93 while (retval) { 94 next = retval->next; 95 config->free(retval); 96 retval = next; 97 } 98 break; 99 } 100 zzjson->next = next; 101 zzjson = next; 102 } 103 } 104 va_end(ap); 105 return retval; 106} 107 108ZZJSON *zzjson_create_object(ZZJSON_CONFIG *config, ...) { 109 ZZJSON *zzjson, *retval, *val; 110 char *label, *labelcopy; 111 va_list ap; 112 113 if (!(zzjson = zzjson_create_templ(config, ZZJSON_OBJECT))) return zzjson; 114 retval = zzjson; 115 116 va_start(ap, config); 117 label = va_arg(ap, char *); 118 while (label) { 119 val = va_arg(ap, ZZJSON *); 120 labelcopy = sdup(config, label); 121 122 if (!labelcopy) { 123 zzjson_free(config, retval); 124 retval = NULL; 125 break; 126 } 127 128 zzjson->value.object.label = labelcopy; 129 zzjson->value.object.val = val; 130 131 label = va_arg(ap, char *); 132 133 if (label) { 134 ZZJSON *next = zzjson_create_templ(config, ZZJSON_OBJECT); 135 if (!next) { 136 while (retval) { 137 next = retval->next; 138 config->free(retval->value.object.label); 139 config->free(retval); 140 retval = next; 141 } 142 break; 143 } 144 zzjson->next = next; 145 zzjson = next; 146 } 147 } 148 va_end(ap); 149 return retval; 150} 151 152ZZJSON *zzjson_array_prepend(ZZJSON_CONFIG *config, ZZJSON *array, 153 ZZJSON *val) { 154 ZZJSON *zzjson; 155 156 if (!array->value.array.val) { /* empty array */ 157 array->value.array.val = val; 158 return array; 159 } 160 161 zzjson = zzjson_create_templ(config, ZZJSON_ARRAY); 162 if (zzjson) { 163 zzjson->value.array.val = val; 164 zzjson->next = array; 165 } 166 return zzjson; 167} 168 169ZZJSON *zzjson_array_append(ZZJSON_CONFIG *config, ZZJSON *array, 170 ZZJSON *val) { 171 ZZJSON *retval = array, *zzjson; 172 173 if (!array->value.array.val) { /* empty array */ 174 array->value.array.val = val; 175 return array; 176 } 177 178 zzjson = zzjson_create_templ(config, ZZJSON_ARRAY); 179 if (!zzjson) return NULL; 180 181 while (array->next) array = array->next; 182 183 zzjson->value.array.val = val; 184 array->next = zzjson; 185 186 return retval; 187} 188 189ZZJSON *zzjson_object_prepend(ZZJSON_CONFIG *config, ZZJSON *object, 190 char *label, ZZJSON *val) { 191 ZZJSON *zzjson = NULL; 192 char *labelcopy = sdup(config, label); 193 194 if (!labelcopy) return zzjson; 195 196 if (!object->value.object.label) { /* empty object */ 197 object->value.object.label = labelcopy; 198 object->value.object.val = val; 199 return object; 200 } 201 202 zzjson = zzjson_create_templ(config, ZZJSON_OBJECT); 203 if (zzjson) { 204 zzjson->value.object.label = labelcopy; 205 zzjson->value.object.val = val; 206 zzjson->next = object; 207 } else { 208 config->free(labelcopy); 209 } 210 return zzjson; 211} 212 213ZZJSON *zzjson_object_append(ZZJSON_CONFIG *config, ZZJSON *object, 214 char *label, ZZJSON *val) { 215 ZZJSON *retval = object, *zzjson = NULL; 216 char *labelcopy = sdup(config, label); 217 218 if (!labelcopy) return zzjson; 219 220 if (!object->value.object.label) { /* empty object */ 221 object->value.object.label = labelcopy; 222 object->value.object.val = val; 223 return object; 224 } 225 226 zzjson = zzjson_create_templ(config, ZZJSON_OBJECT); 227 if (!zzjson) { 228 config->free(labelcopy); 229 return NULL; 230 } 231 232 while (object->next) object = object->next; 233 234 zzjson->value.object.label = labelcopy; 235 zzjson->value.object.val = val; 236 object->next = zzjson; 237 238 return retval; 239} 240 241