Index: lib/json.c
===================================================================
--- lib/json.c	(revision 7a80925eabe969ffc1e8e24c2ad31c80c33ab3cd)
+++ lib/json.c	(revision eab8e52503885305ea652bf99a48f7a584ddc1cd)
@@ -1,5 +1,6 @@
-/* vim: set et ts=3 sw=3 sts=3 ft=c:
+
+/* vim: set et ts=3 sw=3 ft=c:
  *
- * Copyright (C) 2012, 2013, 2014 James McLaughlin et al.  All rights reserved.
+ * Copyright (C) 2012 James McLaughlin et al.  All rights reserved.
  * https://github.com/udp/json-parser
  *
@@ -28,6 +29,4 @@
  */
 
-#include <glib.h>
-
 #include "json.h"
 
@@ -44,8 +43,9 @@
 #endif
 
+#include <glib.h>
+#include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
 #include <ctype.h>
-#include <math.h>
 
 typedef unsigned short json_uchar;
@@ -53,20 +53,21 @@
 static unsigned char hex_value (json_char c)
 {
-   if (isdigit(c))
+   if (c >= 'A' && c <= 'F')
+      return (c - 'A') + 10;
+
+   if (c >= 'a' && c <= 'f')
+      return (c - 'a') + 10;
+
+   if (c >= '0' && c <= '9')
       return c - '0';
 
-   switch (c) {
-      case 'a': case 'A': return 0x0A;
-      case 'b': case 'B': return 0x0B;
-      case 'c': case 'C': return 0x0C;
-      case 'd': case 'D': return 0x0D;
-      case 'e': case 'E': return 0x0E;
-      case 'f': case 'F': return 0x0F;
-      default: return 0xFF;
-   }
+   return 0xFF;
 }
 
 typedef struct
 {
+   json_settings settings;
+   int first_pass;
+
    unsigned long used_memory;
 
@@ -74,21 +75,10 @@
    unsigned long ulong_max;
 
-   json_settings settings;
-   int first_pass;
-
 } json_state;
-
-static void * default_alloc (size_t size, int zero, void * user_data)
-{
-   return zero ? calloc (1, size) : malloc (size);
-}
-
-static void default_free (void * ptr, void * user_data)
-{
-   free (ptr);
-}
 
 static void * json_alloc (json_state * state, unsigned long size, int zero)
 {
+   void * mem;
+
    if ((state->ulong_max - state->used_memory) < size)
       return 0;
@@ -100,5 +90,8 @@
    }
 
-   return state->settings.mem_alloc (size, zero, state->settings.user_data);
+   if (! (mem = zero ? calloc (size, 1) : malloc (size)))
+      return 0;
+
+   return mem;
 }
 
@@ -127,5 +120,4 @@
             }
 
-            value->u.array.length = 0;
             break;
 
@@ -142,5 +134,4 @@
             value->_reserved.object_mem = (*(char **) &value->u.object.values) + values_size;
 
-            value->u.object.length = 0;
             break;
 
@@ -153,5 +144,4 @@
             }
 
-            value->u.string.length = 0;
             break;
 
@@ -160,4 +150,6 @@
       };
 
+      value->u.array.length = 0;
+
       return 1;
    }
@@ -192,55 +184,22 @@
    do { if (!state.first_pass) string [string_length] = b;  ++ string_length; } while (0);
 
-static const long
-   flag_next             = 1 << 0,
-   flag_reproc           = 1 << 1,
-   flag_need_comma       = 1 << 2,
-   flag_seek_value       = 1 << 3, 
-   flag_escaped          = 1 << 4,
-   flag_string           = 1 << 5,
-   flag_need_colon       = 1 << 6,
-   flag_done             = 1 << 7,
-   flag_num_negative     = 1 << 8,
-   flag_num_zero         = 1 << 9,
-   flag_num_e            = 1 << 10,
-   flag_num_e_got_sign   = 1 << 11,
-   flag_num_e_negative   = 1 << 12,
-   flag_line_comment     = 1 << 13,
-   flag_block_comment    = 1 << 14;
-
-json_value * json_parse_ex (json_settings * settings,
-                            const json_char * json,
-                            size_t length,
-                            char * error_buf)
+const static int
+   flag_next = 1, flag_reproc = 2, flag_need_comma = 4, flag_seek_value = 8, flag_exponent = 16,
+   flag_got_exponent_sign = 32, flag_escaped = 64, flag_string = 128, flag_need_colon = 256,
+   flag_done = 512;
+
+json_value * json_parse_ex (json_settings * settings, const json_char * json, char * error_buf)
 {
-   json_char error [json_error_max];
+   json_char error [128];
    unsigned int cur_line;
-   const json_char * cur_line_begin, * i, * end;
+   const json_char * cur_line_begin, * i;
    json_value * top, * root, * alloc = 0;
-   json_state state = { 0 };
-   long flags;
-   long num_digits = 0, num_e = 0;
-   json_int_t num_fraction = 0;
-
-   /* Skip UTF-8 BOM
-    */
-   if (length >= 3 && ((unsigned char) json [0]) == 0xEF
-                   && ((unsigned char) json [1]) == 0xBB
-                   && ((unsigned char) json [2]) == 0xBF)
-   {
-      json += 3;
-      length -= 3;
-   }
+   json_state state;
+   int flags;
 
    error[0] = '\0';
-   end = (json + length);
-
+
+   memset (&state, 0, sizeof (json_state));
    memcpy (&state.settings, settings, sizeof (json_settings));
-
-   if (!state.settings.mem_alloc)
-      state.settings.mem_alloc = default_alloc;
-
-   if (!state.settings.mem_free)
-      state.settings.mem_free = default_free;
 
    memset (&state.uint_max, 0xFF, sizeof (state.uint_max));
@@ -265,6 +224,22 @@
       for (i = json ;; ++ i)
       {
-         json_char b = (i == end ? 0 : *i);
-         
+         json_char b = *i;
+
+         if (flags & flag_done)
+         {
+            if (!b)
+               break;
+
+            switch (b)
+            {
+               whitespace:
+                  continue;
+
+               default:
+                  sprintf (error, "%d:%d: Trailing garbage: `%c`", cur_line, e_off, b);
+                  goto e_failed;
+            };
+         }
+
          if (flags & flag_string)
          {
@@ -290,6 +265,5 @@
                   case 'u':
 
-                    if (end - i < 4 || 
-                        (uc_b1 = hex_value (*++ i)) == 0xFF || (uc_b2 = hex_value (*++ i)) == 0xFF
+                    if ((uc_b1 = hex_value (*++ i)) == 0xFF || (uc_b2 = hex_value (*++ i)) == 0xFF
                           || (uc_b3 = hex_value (*++ i)) == 0xFF || (uc_b4 = hex_value (*++ i)) == 0xFF)
                     {
@@ -370,7 +344,4 @@
                            = (json_char *) top->_reserved.object_mem;
 
-                        top->u.object.values [top->u.object.length].name_length
-                           = string_length;
-
                         (*(json_char **) &top->_reserved.object_mem) += string_length + 1;
                      }
@@ -390,81 +361,4 @@
          }
 
-         if (state.settings.settings & json_enable_comments)
-         {
-            if (flags & (flag_line_comment | flag_block_comment))
-            {
-               if (flags & flag_line_comment)
-               {
-                  if (b == '\r' || b == '\n' || !b)
-                  {
-                     flags &= ~ flag_line_comment;
-                     -- i;  /* so null can be reproc'd */
-                  }
-
-                  continue;
-               }
-
-               if (flags & flag_block_comment)
-               {
-                  if (!b)
-                  {  sprintf (error, "%d:%d: Unexpected EOF in block comment", cur_line, e_off);
-                     goto e_failed;
-                  }
-
-                  if (b == '*' && i < (end - 1) && i [1] == '/')
-                  {
-                     flags &= ~ flag_block_comment;
-                     ++ i;  /* skip closing sequence */
-                  }
-
-                  continue;
-               }
-            }
-            else if (b == '/')
-            {
-               if (! (flags & (flag_seek_value | flag_done)) && top->type != json_object)
-               {
-                  sprintf (error, "%d:%d: Comment not allowed here", cur_line, e_off);
-                  goto e_failed;
-               }
-
-               if (++ i == end)
-               {  sprintf (error, "%d:%d: EOF unexpected", cur_line, e_off);
-                  goto e_failed;
-               }
-
-               switch (b = *i)
-               {
-                  case '/':
-                     flags |= flag_line_comment;
-                     continue;
-
-                  case '*':
-                     flags |= flag_block_comment;
-                     continue;
-
-                  default:
-                     sprintf (error, "%d:%d: Unexpected `%c` in comment opening sequence", cur_line, e_off, b);
-                     goto e_failed;
-               };
-            }
-         }
-
-         if (flags & flag_done)
-         {
-            if (!b)
-               break;
-
-            switch (b)
-            {
-               whitespace:
-                  continue;
-
-               default:
-                  sprintf (error, "%d:%d: Trailing garbage: `%c`", cur_line, e_off, b);
-                  goto e_failed;
-            };
-         }
-
          if (flags & flag_seek_value)
          {
@@ -478,5 +372,5 @@
                   if (top->type == json_array)
                      flags = (flags & ~ (flag_need_comma | flag_seek_value)) | flag_next;
-                  else
+                  else if (!state.settings.settings & json_relaxed_commas)
                   {  sprintf (error, "%d:%d: Unexpected ]", cur_line, e_off);
                      goto e_failed;
@@ -544,5 +438,5 @@
                      case 't':
 
-                        if ((end - i) < 3 || *(++ i) != 'r' || *(++ i) != 'u' || *(++ i) != 'e')
+                        if (*(++ i) != 'r' || *(++ i) != 'u' || *(++ i) != 'e')
                            goto e_unknown_value;
 
@@ -557,5 +451,5 @@
                      case 'f':
 
-                        if ((end - i) < 4 || *(++ i) != 'a' || *(++ i) != 'l' || *(++ i) != 's' || *(++ i) != 'e')
+                        if (*(++ i) != 'a' || *(++ i) != 'l' || *(++ i) != 's' || *(++ i) != 'e')
                            goto e_unknown_value;
 
@@ -568,5 +462,5 @@
                      case 'n':
 
-                        if ((end - i) < 3 || *(++ i) != 'u' || *(++ i) != 'l' || *(++ i) != 'l')
+                        if (*(++ i) != 'u' || *(++ i) != 'l' || *(++ i) != 'l')
                            goto e_unknown_value;
 
@@ -584,38 +478,15 @@
                               goto e_alloc_failure;
 
-                           if (!state.first_pass)
-                           {
-                              while (isdigit (b) || b == '+' || b == '-'
-                                        || b == 'e' || b == 'E' || b == '.')
-                              {
-                                 if ( (++ i) == end)
-                                 {
-                                    b = 0;
-                                    break;
-                                 }
-
-                                 b = *i;
-                              }
-
-                              flags |= flag_next | flag_reproc;
-                              break;
-                           }
-
-                           flags &= ~ (flag_num_negative | flag_num_e |
-                                        flag_num_e_got_sign | flag_num_e_negative |
-                                           flag_num_zero);
-
-                           num_digits = 0;
-                           num_fraction = 0;
-                           num_e = 0;
-
-                           if (b != '-')
-                           {
-                              flags |= flag_reproc;
-                              break;
-                           }
-
-                           flags |= flag_num_negative;
-                           continue;
+                           flags &= ~ (flag_exponent | flag_got_exponent_sign);
+
+                           if (state.first_pass)
+                              continue;
+
+                           if (top->type == json_double)
+                              top->u.dbl = g_ascii_strtod (i, (json_char **) &i);
+                           else
+                              top->u.integer = g_ascii_strtoll (i, (json_char **) &i, 10);
+
+                           flags |= flag_next | flag_reproc;
                         }
                         else
@@ -639,5 +510,5 @@
                   case '"':
 
-                     if (flags & flag_need_comma)
+                     if (flags & flag_need_comma && (!state.settings.settings & json_relaxed_commas))
                      {
                         sprintf (error, "%d:%d: Expected , before \"", cur_line, e_off);
@@ -677,43 +548,21 @@
 
                if (isdigit (b))
+                  continue;
+
+               if (b == 'e' || b == 'E')
                {
-                  ++ num_digits;
-
-                  if (top->type == json_integer || flags & flag_num_e)
+                  if (!(flags & flag_exponent))
                   {
-                     if (! (flags & flag_num_e))
-                     {
-                        if (flags & flag_num_zero)
-                        {  sprintf (error, "%d:%d: Unexpected `0` before `%c`", cur_line, e_off, b);
-                           goto e_failed;
-                        }
-
-                        if (num_digits == 1 && b == '0')
-                           flags |= flag_num_zero;
-                     }
-                     else
-                     {
-                        flags |= flag_num_e_got_sign;
-                        num_e = (num_e * 10) + (b - '0');
-                        continue;
-                     }
-
-                     top->u.integer = (top->u.integer * 10) + (b - '0');
+                     flags |= flag_exponent;
+                     top->type = json_double;
+
                      continue;
                   }
-
-                  num_fraction = (num_fraction * 10) + (b - '0');
-                  continue;
                }
-
-               if (b == '+' || b == '-')
+               else if (b == '+' || b == '-')
                {
-                  if ( (flags & flag_num_e) && !(flags & flag_num_e_got_sign))
+                  if (flags & flag_exponent && !(flags & flag_got_exponent_sign))
                   {
-                     flags |= flag_num_e_got_sign;
-
-                     if (b == '-')
-                        flags |= flag_num_e_negative;
-
+                     flags |= flag_got_exponent_sign;
                      continue;
                   }
@@ -721,60 +570,6 @@
                else if (b == '.' && top->type == json_integer)
                {
-                  if (!num_digits)
-                  {  sprintf (error, "%d:%d: Expected digit before `.`", cur_line, e_off);
-                     goto e_failed;
-                  }
-
                   top->type = json_double;
-                  top->u.dbl = (double) top->u.integer;
-
-                  num_digits = 0;
                   continue;
-               }
-
-               if (! (flags & flag_num_e))
-               {
-                  if (top->type == json_double)
-                  {
-                     if (!num_digits)
-                     {  sprintf (error, "%d:%d: Expected digit after `.`", cur_line, e_off);
-                        goto e_failed;
-                     }
-
-                     top->u.dbl += ((double) num_fraction) / (pow (10, (double) num_digits));
-                  }
-
-                  if (b == 'e' || b == 'E')
-                  {
-                     flags |= flag_num_e;
-
-                     if (top->type == json_integer)
-                     {
-                        top->type = json_double;
-                        top->u.dbl = (double) top->u.integer;
-                     }
-
-                     num_digits = 0;
-                     flags &= ~ flag_num_zero;
-
-                     continue;
-                  }
-               }
-               else
-               {
-                  if (!num_digits)
-                  {  sprintf (error, "%d:%d: Expected digit after `e`", cur_line, e_off);
-                     goto e_failed;
-                  }
-
-                  top->u.dbl *= pow (10, (double) (flags & flag_num_e_negative ? - num_e : num_e));
-               }
-
-               if (flags & flag_num_negative)
-               {
-                  if (top->type == json_integer)
-                     top->u.integer = - top->u.integer;
-                  else
-                     top->u.dbl = - top->u.dbl;
                }
 
@@ -878,21 +673,23 @@
    {
       top = alloc->_reserved.next_alloc;
-      state.settings.mem_free (alloc, state.settings.user_data);
+      free (alloc);
       alloc = top;
    }
 
    if (!state.first_pass)
-      json_value_free_ex (&state.settings, root);
+      json_value_free (root);
 
    return 0;
 }
 
-json_value * json_parse (const json_char * json, size_t length)
+json_value * json_parse (const json_char * json)
 {
-   json_settings settings = { 0 };
-   return json_parse_ex (&settings, json, length, 0);
+   json_settings settings;
+   memset (&settings, 0, sizeof (json_settings));
+
+   return json_parse_ex (&settings, json, 0);
 }
 
-void json_value_free_ex (json_settings * settings, json_value * value)
+void json_value_free (json_value * value)
 {
    json_value * cur_value;
@@ -911,5 +708,5 @@
             if (!value->u.array.length)
             {
-               settings->mem_free (value->u.array.values, settings->user_data);
+               free (value->u.array.values);
                break;
             }
@@ -922,5 +719,5 @@
             if (!value->u.object.length)
             {
-               settings->mem_free (value->u.object.values, settings->user_data);
+               free (value->u.object.values);
                break;
             }
@@ -931,5 +728,5 @@
          case json_string:
 
-            settings->mem_free (value->u.string.ptr, settings->user_data);
+            free (value->u.string.ptr);
             break;
 
@@ -940,13 +737,7 @@
       cur_value = value;
       value = value->parent;
-      settings->mem_free (cur_value, settings->user_data);
+      free (cur_value);
    }
 }
 
-void json_value_free (json_value * value)
-{
-   json_settings settings = { 0 };
-   settings.mem_free = default_free;
-   json_value_free_ex (&settings, value);
-}
-
+
