exchange

Base system with REST service to issue digital coins, run by the payment service provider
Log | Files | Refs | Submodules | README | LICENSE

mustach-jansson.c (6885B)


      1 /*
      2  Author: José Bollo <jobol@nonadev.net>
      3 
      4  https://gitlab.com/jobol/mustach
      5 
      6  SPDX-License-Identifier: ISC
      7 */
      8 
      9 #ifndef _GNU_SOURCE
     10 #define _GNU_SOURCE
     11 #endif
     12 
     13 #include <stdio.h>
     14 #include <string.h>
     15 
     16 #include "mustach.h"
     17 #include "mustach-wrap.h"
     18 #include "mustach-jansson.h"
     19 
     20 struct expl
     21 {
     22   json_t *root;
     23   json_t *selection;
     24   int depth;
     25   struct
     26   {
     27     json_t *cont;
     28     json_t *obj;
     29     void *iter;
     30     int is_objiter;
     31     size_t index, count;
     32   } stack[MUSTACH_MAX_DEPTH];
     33 };
     34 
     35 static int
     36 start (void *closure)
     37 {
     38   struct expl *e = closure;
     39   e->depth = 0;
     40   e->selection = json_null ();
     41   e->stack[0].cont = NULL;
     42   e->stack[0].obj = e->root;
     43   e->stack[0].index = 0;
     44   e->stack[0].count = 1;
     45   return MUSTACH_OK;
     46 }
     47 
     48 
     49 static int
     50 compare (void *closure, const char *value)
     51 {
     52   struct expl *e = closure;
     53   json_t *o = e->selection;
     54   double d;
     55   json_int_t i;
     56 
     57   switch (json_typeof (o))
     58   {
     59   case JSON_REAL:
     60     d = json_number_value (o) - atof (value);
     61     return d < 0 ? -1 : d > 0 ? 1 : 0;
     62   case JSON_INTEGER:
     63     i = (json_int_t) json_integer_value (o) - (json_int_t) atoll (value);
     64     return i < 0 ? -1 : i > 0 ? 1 : 0;
     65   case JSON_STRING:
     66     return strcmp (json_string_value (o), value);
     67   case JSON_TRUE:
     68     return strcmp ("true", value);
     69   case JSON_FALSE:
     70     return strcmp ("false", value);
     71   case JSON_NULL:
     72     return strcmp ("null", value);
     73   default:
     74     return 1;
     75   }
     76 }
     77 
     78 
     79 static int
     80 sel (void *closure, const char *name)
     81 {
     82   struct expl *e = closure;
     83   json_t *o;
     84   int i, r;
     85 
     86   if (name == NULL)
     87   {
     88     o = e->stack[e->depth].obj;
     89     r = 1;
     90   }
     91   else
     92   {
     93     i = e->depth;
     94     while (i >= 0 && ! (o = json_object_get (e->stack[i].obj, name)))
     95       i--;
     96     if (i >= 0)
     97       r = 1;
     98     else
     99     {
    100       o = json_null ();
    101       r = 0;
    102     }
    103   }
    104   e->selection = o;
    105   return r;
    106 }
    107 
    108 
    109 static int
    110 subsel (void *closure, const char *name)
    111 {
    112   struct expl *e = closure;
    113   json_t *o = NULL;
    114   int r = 0;
    115 
    116   if (json_is_object (e->selection))
    117   {
    118     o = json_object_get (e->selection, name);
    119     r = o != NULL;
    120   }
    121   else if (json_is_array (e->selection))
    122   {
    123     char *end;
    124     size_t idx = (size_t) strtol (name, &end, 10);
    125     if (! *end && idx < json_array_size (e->selection))
    126     {
    127       o = json_array_get (e->selection, idx);
    128       r = 1;
    129     }
    130   }
    131   if (r)
    132     e->selection = o;
    133   return r;
    134 }
    135 
    136 
    137 static int
    138 enter (void *closure, int objiter)
    139 {
    140   struct expl *e = closure;
    141   json_t *o;
    142 
    143   if (++e->depth >= MUSTACH_MAX_DEPTH)
    144     return MUSTACH_ERROR_TOO_DEEP;
    145 
    146   o = e->selection;
    147   e->stack[e->depth].is_objiter = 0;
    148   /* Squash warning for comparing float to 0.0 */
    149 #pragma GCC diagnostic push
    150 #pragma GCC diagnostic ignored "-Wfloat-equal"
    151   if (objiter)
    152   {
    153     if (! json_is_object (o))
    154       goto not_entering;
    155     e->stack[e->depth].iter = json_object_iter (o);
    156     if (e->stack[e->depth].iter == NULL)
    157       goto not_entering;
    158     e->stack[e->depth].obj = json_object_iter_value (e->stack[e->depth].iter);
    159     e->stack[e->depth].cont = o;
    160     e->stack[e->depth].is_objiter = 1;
    161   }
    162   else if (json_is_array (o))
    163   {
    164     e->stack[e->depth].count = json_array_size (o);
    165     if (e->stack[e->depth].count == 0)
    166       goto not_entering;
    167     e->stack[e->depth].cont = o;
    168     e->stack[e->depth].obj = json_array_get (o, 0);
    169     e->stack[e->depth].index = 0;
    170   }
    171   else if ((json_is_object (o) && json_object_size (o))
    172            || json_is_true (o)
    173            || (json_is_string (o) && json_string_length (o) > 0)
    174            || (json_is_integer (o) && json_integer_value (o) != 0)
    175            || (json_is_real (o) && json_real_value (o) != 0))
    176   {
    177     e->stack[e->depth].count = 1;
    178     e->stack[e->depth].cont = NULL;
    179     e->stack[e->depth].obj = o;
    180     e->stack[e->depth].index = 0;
    181   }
    182   else
    183     goto not_entering;
    184 #pragma GCC diagnostic pop
    185   return 1;
    186 
    187 not_entering:
    188   e->depth--;
    189   return 0;
    190 }
    191 
    192 
    193 static int
    194 next (void *closure)
    195 {
    196   struct expl *e = closure;
    197 
    198   if (e->depth <= 0)
    199     return MUSTACH_ERROR_CLOSING;
    200 
    201   if (e->stack[e->depth].is_objiter)
    202   {
    203     e->stack[e->depth].iter = json_object_iter_next (e->stack[e->depth].cont, e->stack[e->depth].
    204                                                      iter);
    205     if (e->stack[e->depth].iter == NULL)
    206       return 0;
    207     e->stack[e->depth].obj = json_object_iter_value (e->stack[e->depth].iter);
    208     return 1;
    209   }
    210 
    211   e->stack[e->depth].index++;
    212   if (e->stack[e->depth].index >= e->stack[e->depth].count)
    213     return 0;
    214 
    215   e->stack[e->depth].obj = json_array_get (e->stack[e->depth].cont, e->stack[e->depth].index);
    216   return 1;
    217 }
    218 
    219 
    220 static int
    221 leave (void *closure)
    222 {
    223   struct expl *e = closure;
    224 
    225   if (e->depth <= 0)
    226     return MUSTACH_ERROR_CLOSING;
    227 
    228   e->depth--;
    229   return 0;
    230 }
    231 
    232 
    233 static int
    234 get (void *closure, struct mustach_sbuf *sbuf, int key)
    235 {
    236   struct expl *e = closure;
    237   const char *s;
    238   int d;
    239 
    240   if (key)
    241   {
    242     s = "";
    243     for (d = e->depth ; d >= 0 ; d--)
    244       if (e->stack[d].is_objiter)
    245       {
    246         s = json_object_iter_key (e->stack[d].iter);
    247         break;
    248       }
    249   }
    250   else if (json_is_string (e->selection))
    251     s = json_string_value (e->selection);
    252   else if (json_is_null (e->selection))
    253     s = "";
    254   else
    255   {
    256     s = json_dumps (e->selection, JSON_ENCODE_ANY | JSON_COMPACT);
    257     if (s == NULL)
    258       return MUSTACH_ERROR_SYSTEM;
    259     sbuf->freecb = free;
    260   }
    261   sbuf->value = s;
    262   return 1;
    263 }
    264 
    265 
    266 const struct mustach_wrap_itf mustach_jansson_wrap_itf = {
    267   .start = start,
    268   .stop = NULL,
    269   .compare = compare,
    270   .sel = sel,
    271   .subsel = subsel,
    272   .enter = enter,
    273   .next = next,
    274   .leave = leave,
    275   .get = get
    276 };
    277 
    278 int
    279 mustach_jansson_file (const char *template, size_t length, json_t *root, int flags, FILE *file)
    280 {
    281   struct expl e;
    282   e.root = root;
    283   return mustach_wrap_file (template, length, &mustach_jansson_wrap_itf, &e, flags, file);
    284 }
    285 
    286 
    287 int
    288 mustach_jansson_fd (const char *template, size_t length, json_t *root, int flags, int fd)
    289 {
    290   struct expl e;
    291   e.root = root;
    292   return mustach_wrap_fd (template, length, &mustach_jansson_wrap_itf, &e, flags, fd);
    293 }
    294 
    295 
    296 int
    297 mustach_jansson_mem (const char *template, size_t length, json_t *root, int flags, char **result,
    298                      size_t *size)
    299 {
    300   struct expl e;
    301   e.root = root;
    302   return mustach_wrap_mem (template, length, &mustach_jansson_wrap_itf, &e, flags, result, size);
    303 }
    304 
    305 
    306 int
    307 mustach_jansson_write (const char *template, size_t length, json_t *root, int flags,
    308                        mustach_write_cb_t *writecb, void *closure)
    309 {
    310   struct expl e;
    311   e.root = root;
    312   return mustach_wrap_write (template, length, &mustach_jansson_wrap_itf, &e, flags, writecb,
    313                              closure);
    314 }
    315 
    316 
    317 int
    318 mustach_jansson_emit (const char *template, size_t length, json_t *root, int flags,
    319                       mustach_emit_cb_t *emitcb, void *closure)
    320 {
    321   struct expl e;
    322   e.root = root;
    323   return mustach_wrap_emit (template, length, &mustach_jansson_wrap_itf, &e, flags, emitcb, closure)
    324   ;
    325 }