Home | History | Annotate | Download | only in zzjson
      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 
     18 static 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 
     25 ZZJSON *zzjson_create_true(ZZJSON_CONFIG *config) {
     26     return zzjson_create_templ(config, ZZJSON_TRUE);
     27 }
     28 
     29 ZZJSON *zzjson_create_false(ZZJSON_CONFIG *config) {
     30     return zzjson_create_templ(config, ZZJSON_FALSE);
     31 }
     32 
     33 ZZJSON *zzjson_create_null(ZZJSON_CONFIG *config) {
     34     return zzjson_create_templ(config, ZZJSON_NULL);
     35 }
     36 
     37 ZZJSON *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 
     44 ZZJSON *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 */
     54 static 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 
     63 ZZJSON *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 
     77 ZZJSON *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 
    108 ZZJSON *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 
    152 ZZJSON *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 
    169 ZZJSON *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 
    189 ZZJSON *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 
    213 ZZJSON *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