Changeset 7a80925 for lib


Ignore:
Timestamp:
2014-02-13T08:48:37Z (6 years ago)
Author:
Wilmer van der Gaast <wilmer@…>
Branches:
master
Children:
6ae1056
Parents:
e76cf26
Message:

Update json-parser code to git rev 11a80f389769d1f66ca7fbe64ad89c82d3ba4ba9.
Few BitlBee-specific diffs now. Annoyingly need to link to libm now for the
use of the function pow() since the lib now does its own number parsing...

Location:
lib
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • lib/json.c

    re76cf26 r7a80925  
    1 
    2 /* vim: set et ts=3 sw=3 ft=c:
     1/* vim: set et ts=3 sw=3 sts=3 ft=c:
    32 *
    4  * Copyright (C) 2012 James McLaughlin et al.  All rights reserved.
     3 * Copyright (C) 2012, 2013, 2014 James McLaughlin et al.  All rights reserved.
    54 * https://github.com/udp/json-parser
    65 *
     
    2928 */
    3029
     30#include <glib.h>
     31
    3132#include "json.h"
    3233
     
    4344#endif
    4445
    45 #include <glib.h>
    46 #include <stdlib.h>
    4746#include <stdio.h>
    4847#include <string.h>
    4948#include <ctype.h>
     49#include <math.h>
    5050
    5151typedef unsigned short json_uchar;
     
    5353static unsigned char hex_value (json_char c)
    5454{
    55    if (c >= 'A' && c <= 'F')
    56       return (c - 'A') + 10;
    57 
    58    if (c >= 'a' && c <= 'f')
    59       return (c - 'a') + 10;
    60 
    61    if (c >= '0' && c <= '9')
     55   if (isdigit(c))
    6256      return c - '0';
    6357
    64    return 0xFF;
     58   switch (c) {
     59      case 'a': case 'A': return 0x0A;
     60      case 'b': case 'B': return 0x0B;
     61      case 'c': case 'C': return 0x0C;
     62      case 'd': case 'D': return 0x0D;
     63      case 'e': case 'E': return 0x0E;
     64      case 'f': case 'F': return 0x0F;
     65      default: return 0xFF;
     66   }
    6567}
    6668
    6769typedef struct
    6870{
     71   unsigned long used_memory;
     72
     73   unsigned int uint_max;
     74   unsigned long ulong_max;
     75
    6976   json_settings settings;
    7077   int first_pass;
    7178
    72    unsigned long used_memory;
    73 
    74    unsigned int uint_max;
    75    unsigned long ulong_max;
    76 
    7779} json_state;
     80
     81static void * default_alloc (size_t size, int zero, void * user_data)
     82{
     83   return zero ? calloc (1, size) : malloc (size);
     84}
     85
     86static void default_free (void * ptr, void * user_data)
     87{
     88   free (ptr);
     89}
    7890
    7991static void * json_alloc (json_state * state, unsigned long size, int zero)
    8092{
    81    void * mem;
    82 
    8393   if ((state->ulong_max - state->used_memory) < size)
    8494      return 0;
     
    90100   }
    91101
    92    if (! (mem = zero ? calloc (size, 1) : malloc (size)))
    93       return 0;
    94 
    95    return mem;
     102   return state->settings.mem_alloc (size, zero, state->settings.user_data);
    96103}
    97104
     
    120127            }
    121128
     129            value->u.array.length = 0;
    122130            break;
    123131
     
    134142            value->_reserved.object_mem = (*(char **) &value->u.object.values) + values_size;
    135143
     144            value->u.object.length = 0;
    136145            break;
    137146
     
    144153            }
    145154
     155            value->u.string.length = 0;
    146156            break;
    147157
     
    150160      };
    151161
    152       value->u.array.length = 0;
    153 
    154162      return 1;
    155163   }
     
    184192   do { if (!state.first_pass) string [string_length] = b;  ++ string_length; } while (0);
    185193
    186 const static int
    187    flag_next = 1, flag_reproc = 2, flag_need_comma = 4, flag_seek_value = 8, flag_exponent = 16,
    188    flag_got_exponent_sign = 32, flag_escaped = 64, flag_string = 128, flag_need_colon = 256,
    189    flag_done = 512;
    190 
    191 json_value * json_parse_ex (json_settings * settings, const json_char * json, char * error_buf)
     194static const long
     195   flag_next             = 1 << 0,
     196   flag_reproc           = 1 << 1,
     197   flag_need_comma       = 1 << 2,
     198   flag_seek_value       = 1 << 3,
     199   flag_escaped          = 1 << 4,
     200   flag_string           = 1 << 5,
     201   flag_need_colon       = 1 << 6,
     202   flag_done             = 1 << 7,
     203   flag_num_negative     = 1 << 8,
     204   flag_num_zero         = 1 << 9,
     205   flag_num_e            = 1 << 10,
     206   flag_num_e_got_sign   = 1 << 11,
     207   flag_num_e_negative   = 1 << 12,
     208   flag_line_comment     = 1 << 13,
     209   flag_block_comment    = 1 << 14;
     210
     211json_value * json_parse_ex (json_settings * settings,
     212                            const json_char * json,
     213                            size_t length,
     214                            char * error_buf)
    192215{
    193    json_char error [128];
     216   json_char error [json_error_max];
    194217   unsigned int cur_line;
    195    const json_char * cur_line_begin, * i;
     218   const json_char * cur_line_begin, * i, * end;
    196219   json_value * top, * root, * alloc = 0;
    197    json_state state;
    198    int flags;
     220   json_state state = { 0 };
     221   long flags;
     222   long num_digits = 0, num_e = 0;
     223   json_int_t num_fraction = 0;
     224
     225   /* Skip UTF-8 BOM
     226    */
     227   if (length >= 3 && ((unsigned char) json [0]) == 0xEF
     228                   && ((unsigned char) json [1]) == 0xBB
     229                   && ((unsigned char) json [2]) == 0xBF)
     230   {
     231      json += 3;
     232      length -= 3;
     233   }
    199234
    200235   error[0] = '\0';
    201 
    202    memset (&state, 0, sizeof (json_state));
     236   end = (json + length);
     237
    203238   memcpy (&state.settings, settings, sizeof (json_settings));
     239
     240   if (!state.settings.mem_alloc)
     241      state.settings.mem_alloc = default_alloc;
     242
     243   if (!state.settings.mem_free)
     244      state.settings.mem_free = default_free;
    204245
    205246   memset (&state.uint_max, 0xFF, sizeof (state.uint_max));
     
    224265      for (i = json ;; ++ i)
    225266      {
    226          json_char b = *i;
    227 
    228          if (flags & flag_done)
    229          {
    230             if (!b)
    231                break;
    232 
    233             switch (b)
    234             {
    235                whitespace:
    236                   continue;
    237 
    238                default:
    239                   sprintf (error, "%d:%d: Trailing garbage: `%c`", cur_line, e_off, b);
    240                   goto e_failed;
    241             };
    242          }
    243 
     267         json_char b = (i == end ? 0 : *i);
     268         
    244269         if (flags & flag_string)
    245270         {
     
    265290                  case 'u':
    266291
    267                     if ((uc_b1 = hex_value (*++ i)) == 0xFF || (uc_b2 = hex_value (*++ i)) == 0xFF
     292                    if (end - i < 4 ||
     293                        (uc_b1 = hex_value (*++ i)) == 0xFF || (uc_b2 = hex_value (*++ i)) == 0xFF
    268294                          || (uc_b3 = hex_value (*++ i)) == 0xFF || (uc_b4 = hex_value (*++ i)) == 0xFF)
    269295                    {
     
    344370                           = (json_char *) top->_reserved.object_mem;
    345371
     372                        top->u.object.values [top->u.object.length].name_length
     373                           = string_length;
     374
    346375                        (*(json_char **) &top->_reserved.object_mem) += string_length + 1;
    347376                     }
     
    361390         }
    362391
     392         if (state.settings.settings & json_enable_comments)
     393         {
     394            if (flags & (flag_line_comment | flag_block_comment))
     395            {
     396               if (flags & flag_line_comment)
     397               {
     398                  if (b == '\r' || b == '\n' || !b)
     399                  {
     400                     flags &= ~ flag_line_comment;
     401                     -- i;  /* so null can be reproc'd */
     402                  }
     403
     404                  continue;
     405               }
     406
     407               if (flags & flag_block_comment)
     408               {
     409                  if (!b)
     410                  {  sprintf (error, "%d:%d: Unexpected EOF in block comment", cur_line, e_off);
     411                     goto e_failed;
     412                  }
     413
     414                  if (b == '*' && i < (end - 1) && i [1] == '/')
     415                  {
     416                     flags &= ~ flag_block_comment;
     417                     ++ i;  /* skip closing sequence */
     418                  }
     419
     420                  continue;
     421               }
     422            }
     423            else if (b == '/')
     424            {
     425               if (! (flags & (flag_seek_value | flag_done)) && top->type != json_object)
     426               {
     427                  sprintf (error, "%d:%d: Comment not allowed here", cur_line, e_off);
     428                  goto e_failed;
     429               }
     430
     431               if (++ i == end)
     432               {  sprintf (error, "%d:%d: EOF unexpected", cur_line, e_off);
     433                  goto e_failed;
     434               }
     435
     436               switch (b = *i)
     437               {
     438                  case '/':
     439                     flags |= flag_line_comment;
     440                     continue;
     441
     442                  case '*':
     443                     flags |= flag_block_comment;
     444                     continue;
     445
     446                  default:
     447                     sprintf (error, "%d:%d: Unexpected `%c` in comment opening sequence", cur_line, e_off, b);
     448                     goto e_failed;
     449               };
     450            }
     451         }
     452
     453         if (flags & flag_done)
     454         {
     455            if (!b)
     456               break;
     457
     458            switch (b)
     459            {
     460               whitespace:
     461                  continue;
     462
     463               default:
     464                  sprintf (error, "%d:%d: Trailing garbage: `%c`", cur_line, e_off, b);
     465                  goto e_failed;
     466            };
     467         }
     468
    363469         if (flags & flag_seek_value)
    364470         {
     
    372478                  if (top->type == json_array)
    373479                     flags = (flags & ~ (flag_need_comma | flag_seek_value)) | flag_next;
    374                   else if (!state.settings.settings & json_relaxed_commas)
     480                  else
    375481                  {  sprintf (error, "%d:%d: Unexpected ]", cur_line, e_off);
    376482                     goto e_failed;
     
    438544                     case 't':
    439545
    440                         if (*(++ i) != 'r' || *(++ i) != 'u' || *(++ i) != 'e')
     546                        if ((end - i) < 3 || *(++ i) != 'r' || *(++ i) != 'u' || *(++ i) != 'e')
    441547                           goto e_unknown_value;
    442548
     
    451557                     case 'f':
    452558
    453                         if (*(++ i) != 'a' || *(++ i) != 'l' || *(++ i) != 's' || *(++ i) != 'e')
     559                        if ((end - i) < 4 || *(++ i) != 'a' || *(++ i) != 'l' || *(++ i) != 's' || *(++ i) != 'e')
    454560                           goto e_unknown_value;
    455561
     
    462568                     case 'n':
    463569
    464                         if (*(++ i) != 'u' || *(++ i) != 'l' || *(++ i) != 'l')
     570                        if ((end - i) < 3 || *(++ i) != 'u' || *(++ i) != 'l' || *(++ i) != 'l')
    465571                           goto e_unknown_value;
    466572
     
    478584                              goto e_alloc_failure;
    479585
    480                            flags &= ~ (flag_exponent | flag_got_exponent_sign);
    481 
    482                            if (state.first_pass)
    483                               continue;
    484 
    485                            if (top->type == json_double)
    486                               top->u.dbl = g_ascii_strtod (i, (json_char **) &i);
    487                            else
    488                               top->u.integer = g_ascii_strtoll (i, (json_char **) &i, 10);
    489 
    490                            flags |= flag_next | flag_reproc;
     586                           if (!state.first_pass)
     587                           {
     588                              while (isdigit (b) || b == '+' || b == '-'
     589                                        || b == 'e' || b == 'E' || b == '.')
     590                              {
     591                                 if ( (++ i) == end)
     592                                 {
     593                                    b = 0;
     594                                    break;
     595                                 }
     596
     597                                 b = *i;
     598                              }
     599
     600                              flags |= flag_next | flag_reproc;
     601                              break;
     602                           }
     603
     604                           flags &= ~ (flag_num_negative | flag_num_e |
     605                                        flag_num_e_got_sign | flag_num_e_negative |
     606                                           flag_num_zero);
     607
     608                           num_digits = 0;
     609                           num_fraction = 0;
     610                           num_e = 0;
     611
     612                           if (b != '-')
     613                           {
     614                              flags |= flag_reproc;
     615                              break;
     616                           }
     617
     618                           flags |= flag_num_negative;
     619                           continue;
    491620                        }
    492621                        else
     
    510639                  case '"':
    511640
    512                      if (flags & flag_need_comma && (!state.settings.settings & json_relaxed_commas))
     641                     if (flags & flag_need_comma)
    513642                     {
    514643                        sprintf (error, "%d:%d: Expected , before \"", cur_line, e_off);
     
    548677
    549678               if (isdigit (b))
     679               {
     680                  ++ num_digits;
     681
     682                  if (top->type == json_integer || flags & flag_num_e)
     683                  {
     684                     if (! (flags & flag_num_e))
     685                     {
     686                        if (flags & flag_num_zero)
     687                        {  sprintf (error, "%d:%d: Unexpected `0` before `%c`", cur_line, e_off, b);
     688                           goto e_failed;
     689                        }
     690
     691                        if (num_digits == 1 && b == '0')
     692                           flags |= flag_num_zero;
     693                     }
     694                     else
     695                     {
     696                        flags |= flag_num_e_got_sign;
     697                        num_e = (num_e * 10) + (b - '0');
     698                        continue;
     699                     }
     700
     701                     top->u.integer = (top->u.integer * 10) + (b - '0');
     702                     continue;
     703                  }
     704
     705                  num_fraction = (num_fraction * 10) + (b - '0');
    550706                  continue;
    551 
    552                if (b == 'e' || b == 'E')
    553                {
    554                   if (!(flags & flag_exponent))
     707               }
     708
     709               if (b == '+' || b == '-')
     710               {
     711                  if ( (flags & flag_num_e) && !(flags & flag_num_e_got_sign))
    555712                  {
    556                      flags |= flag_exponent;
    557                      top->type = json_double;
    558 
    559                      continue;
    560                   }
    561                }
    562                else if (b == '+' || b == '-')
    563                {
    564                   if (flags & flag_exponent && !(flags & flag_got_exponent_sign))
    565                   {
    566                      flags |= flag_got_exponent_sign;
     713                     flags |= flag_num_e_got_sign;
     714
     715                     if (b == '-')
     716                        flags |= flag_num_e_negative;
     717
    567718                     continue;
    568719                  }
     
    570721               else if (b == '.' && top->type == json_integer)
    571722               {
     723                  if (!num_digits)
     724                  {  sprintf (error, "%d:%d: Expected digit before `.`", cur_line, e_off);
     725                     goto e_failed;
     726                  }
     727
    572728                  top->type = json_double;
     729                  top->u.dbl = (double) top->u.integer;
     730
     731                  num_digits = 0;
    573732                  continue;
     733               }
     734
     735               if (! (flags & flag_num_e))
     736               {
     737                  if (top->type == json_double)
     738                  {
     739                     if (!num_digits)
     740                     {  sprintf (error, "%d:%d: Expected digit after `.`", cur_line, e_off);
     741                        goto e_failed;
     742                     }
     743
     744                     top->u.dbl += ((double) num_fraction) / (pow (10, (double) num_digits));
     745                  }
     746
     747                  if (b == 'e' || b == 'E')
     748                  {
     749                     flags |= flag_num_e;
     750
     751                     if (top->type == json_integer)
     752                     {
     753                        top->type = json_double;
     754                        top->u.dbl = (double) top->u.integer;
     755                     }
     756
     757                     num_digits = 0;
     758                     flags &= ~ flag_num_zero;
     759
     760                     continue;
     761                  }
     762               }
     763               else
     764               {
     765                  if (!num_digits)
     766                  {  sprintf (error, "%d:%d: Expected digit after `e`", cur_line, e_off);
     767                     goto e_failed;
     768                  }
     769
     770                  top->u.dbl *= pow (10, (double) (flags & flag_num_e_negative ? - num_e : num_e));
     771               }
     772
     773               if (flags & flag_num_negative)
     774               {
     775                  if (top->type == json_integer)
     776                     top->u.integer = - top->u.integer;
     777                  else
     778                     top->u.dbl = - top->u.dbl;
    574779               }
    575780
     
    673878   {
    674879      top = alloc->_reserved.next_alloc;
    675       free (alloc);
     880      state.settings.mem_free (alloc, state.settings.user_data);
    676881      alloc = top;
    677882   }
    678883
    679884   if (!state.first_pass)
    680       json_value_free (root);
     885      json_value_free_ex (&state.settings, root);
    681886
    682887   return 0;
    683888}
    684889
    685 json_value * json_parse (const json_char * json)
     890json_value * json_parse (const json_char * json, size_t length)
    686891{
    687    json_settings settings;
    688    memset (&settings, 0, sizeof (json_settings));
    689 
    690    return json_parse_ex (&settings, json, 0);
     892   json_settings settings = { 0 };
     893   return json_parse_ex (&settings, json, length, 0);
    691894}
    692895
    693 void json_value_free (json_value * value)
     896void json_value_free_ex (json_settings * settings, json_value * value)
    694897{
    695898   json_value * cur_value;
     
    708911            if (!value->u.array.length)
    709912            {
    710                free (value->u.array.values);
     913               settings->mem_free (value->u.array.values, settings->user_data);
    711914               break;
    712915            }
     
    719922            if (!value->u.object.length)
    720923            {
    721                free (value->u.object.values);
     924               settings->mem_free (value->u.object.values, settings->user_data);
    722925               break;
    723926            }
     
    728931         case json_string:
    729932
    730             free (value->u.string.ptr);
     933            settings->mem_free (value->u.string.ptr, settings->user_data);
    731934            break;
    732935
     
    737940      cur_value = value;
    738941      value = value->parent;
    739       free (cur_value);
     942      settings->mem_free (cur_value, settings->user_data);
    740943   }
    741944}
    742945
    743 
     946void json_value_free (json_value * value)
     947{
     948   json_settings settings = { 0 };
     949   settings.mem_free = default_free;
     950   json_value_free_ex (&settings, value);
     951}
     952
  • lib/json.h

    re76cf26 r7a80925  
    11
    2 /* vim: set et ts=3 sw=3 ft=c:
    3  *
    4  * Copyright (C) 2012 James McLaughlin et al.  All rights reserved.
     2/* vim: set et ts=3 sw=3 sts=3 ft=c:
     3 *
     4 * Copyright (C) 2012, 2013, 2014 James McLaughlin et al.  All rights reserved.
    55 * https://github.com/udp/json-parser
    66 *
     
    3636#endif
    3737
     38#ifndef json_int_t
     39   #ifndef _MSC_VER
     40      #include <inttypes.h>
     41      #define json_int_t int64_t
     42   #else
     43      #define json_int_t __int64
     44   #endif
     45#endif
     46
     47#include <stdlib.h>
     48
    3849#ifdef __cplusplus
    3950
     
    5061   int settings;
    5162
     63   /* Custom allocator support (leave null to use malloc/free)
     64    */
     65
     66   void * (* mem_alloc) (size_t, int zero, void * user_data);
     67   void (* mem_free) (void *, void * user_data);
     68
     69   void * user_data;  /* will be passed to mem_alloc and mem_free */
     70
    5271} json_settings;
    5372
    54 #define json_relaxed_commas 1
     73#define json_enable_comments  0x01
    5574
    5675typedef enum
     
    7897   {
    7998      int boolean;
    80       long long integer;
     99      json_int_t integer;
    81100      double dbl;
    82101
     
    95114         {
    96115            json_char * name;
     116            unsigned int name_length;
     117
    97118            struct _json_value * value;
    98119
    99120         } * values;
     121
     122         #if defined(__cplusplus) && __cplusplus >= 201103L
     123         decltype(values) begin () const
     124         {  return values;
     125         }
     126         decltype(values) end () const
     127         {  return values + length;
     128         }
     129         #endif
    100130
    101131      } object;
     
    106136         struct _json_value ** values;
    107137
     138         #if defined(__cplusplus) && __cplusplus >= 201103L
     139         decltype(values) begin () const
     140         {  return values;
     141         }
     142         decltype(values) end () const
     143         {  return values + length;
     144         }
     145         #endif
     146
    108147      } array;
    109148
     
    163202         }
    164203
    165          inline operator long () const
    166          {  return u.integer;
     204         inline operator json_int_t () const
     205         { 
     206            switch (type)
     207            {
     208               case json_integer:
     209                  return u.integer;
     210
     211               case json_double:
     212                  return (json_int_t) u.dbl;
     213
     214               default:
     215                  return 0;
     216            };
    167217         }
    168218
    169219         inline operator bool () const
    170          {  return u.boolean != 0;
     220         { 
     221            if (type != json_boolean)
     222               return false;
     223
     224            return u.boolean != 0;
     225         }
     226
     227         inline operator double () const
     228         { 
     229            switch (type)
     230            {
     231               case json_integer:
     232                  return (double) u.integer;
     233
     234               case json_double:
     235                  return u.dbl;
     236
     237               default:
     238                  return 0;
     239            };
    171240         }
    172241
     
    175244} json_value;
    176245
    177 json_value * json_parse
    178    (const json_char * json);
    179 
    180 json_value * json_parse_ex
    181    (json_settings * settings, const json_char * json, char * error);
     246json_value * json_parse (const json_char * json,
     247                         size_t length);
     248
     249#define json_error_max 128
     250json_value * json_parse_ex (json_settings * settings,
     251                            const json_char * json,
     252                            size_t length,
     253                            char * error);
    182254
    183255void json_value_free (json_value *);
     256
     257
     258/* Not usually necessary, unless you used a custom mem_alloc and now want to
     259 * use a custom mem_free.
     260 */
     261void json_value_free_ex (json_settings * settings,
     262                         json_value *);
    184263
    185264
  • lib/oauth2.c

    re76cf26 r7a80925  
    154154                              strstr( content_type, "text/javascript" ) ) )
    155155        {
    156                 json_value *js = json_parse( req->reply_body );
     156                json_value *js = json_parse( req->reply_body, req->body_size );
    157157                if( js && js->type == json_object )
    158158                {
Note: See TracChangeset for help on using the changeset viewer.