Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

qcschema_json.c

Go to the documentation of this file.
00001 /* vim: set et ts=3 sw=3 sts=3 ft=c:
00002  *
00003  * Copyright (C) 2012, 2013, 2014 James McLaughlin et al.  All rights reserved.
00004  * https://github.com/udp/json-parser
00005  *
00006  * Redistribution and use in source and binary forms, with or without
00007  * modification, are permitted provided that the following conditions
00008  * are met:
00009  *
00010  * 1. Redistributions of source code must retain the above copyright
00011  *   notice, this list of conditions and the following disclaimer.
00012  *
00013  * 2. Redistributions in binary form must reproduce the above copyright
00014  *   notice, this list of conditions and the following disclaimer in the
00015  *   documentation and/or other materials provided with the distribution.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
00018  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
00021  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00022  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00023  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00024  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00025  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00026  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00027  * SUCH DAMAGE.
00028  */
00029 
00030 #include "qcschema_json.h"
00031 
00032 #ifdef _MSC_VER
00033    #ifndef _CRT_SECURE_NO_WARNINGS
00034       #define _CRT_SECURE_NO_WARNINGS
00035    #endif
00036    #include <stdint.h>
00037 #endif
00038 
00039 const struct _json_value json_value_none;
00040 
00041 #include <stdio.h>
00042 #include <string.h>
00043 #include <ctype.h>
00044 #include <math.h>
00045 
00046 typedef unsigned int json_uchar;
00047 
00048 /* There has to be a better way to do this */
00049 static const json_int_t JSON_INT_MAX = sizeof(json_int_t) == 1
00050                                        ? INT8_MAX
00051                                        : (sizeof(json_int_t) == 2
00052                                          ? INT16_MAX
00053                                          : (sizeof(json_int_t) == 4
00054                                            ? INT32_MAX
00055                                            : INT64_MAX));
00056 
00057 static unsigned char hex_value (json_char c)
00058 {
00059    if (isdigit(c))
00060       return c - '0';
00061 
00062    switch (c) {
00063       case 'a': case 'A': return 0x0A;
00064       case 'b': case 'B': return 0x0B;
00065       case 'c': case 'C': return 0x0C;
00066       case 'd': case 'D': return 0x0D;
00067       case 'e': case 'E': return 0x0E;
00068       case 'f': case 'F': return 0x0F;
00069       default: return 0xFF;
00070    }
00071 }
00072 
00073 static int would_overflow (json_int_t value, json_char b)
00074 {
00075    return ((JSON_INT_MAX - (b - '0')) / 10 ) < value;
00076 }
00077 
00078 typedef struct
00079 {
00080    unsigned long used_memory;
00081 
00082    unsigned int uint_max;
00083    unsigned long ulong_max;
00084 
00085    json_settings settings;
00086    int first_pass;
00087 
00088    const json_char * ptr;
00089    unsigned int cur_line, cur_col;
00090 
00091 } json_state;
00092 
00093 static void * default_alloc (size_t size, int zero, void * user_data)
00094 {
00095    return zero ? calloc (1, size) : malloc (size);
00096 }
00097 
00098 static void default_free (void * ptr, void * user_data)
00099 {
00100    free (ptr);
00101 }
00102 
00103 static void * json_alloc (json_state * state, unsigned long size, int zero)
00104 {
00105    if ((state->ulong_max - state->used_memory) < size)
00106       return 0;
00107 
00108    if (state->settings.max_memory
00109          && (state->used_memory += size) > state->settings.max_memory)
00110    {
00111       return 0;
00112    }
00113 
00114    return state->settings.mem_alloc (size, zero, state->settings.user_data);
00115 }
00116 
00117 static int new_value (json_state * state,
00118                       json_value ** top, json_value ** root, json_value ** alloc,
00119                       json_type type)
00120 {
00121    json_value * value;
00122    int values_size;
00123 
00124    if (!state->first_pass)
00125    {
00126       value = *top = *alloc;
00127       *alloc = (*alloc)->_reserved.next_alloc;
00128 
00129       if (!*root)
00130          *root = value;
00131 
00132       switch (value->type)
00133       {
00134          case json_array:
00135 
00136             if (value->u.array.length == 0)
00137                break;
00138 
00139             if (! (value->u.array.values = (json_value **) json_alloc
00140                (state, value->u.array.length * sizeof (json_value *), 0)) )
00141             {
00142                return 0;
00143             }
00144 
00145             value->u.array.length = 0;
00146             break;
00147 
00148          case json_object:
00149 
00150             if (value->u.object.length == 0)
00151                break;
00152 
00153             values_size = sizeof (*value->u.object.values) * value->u.object.length;
00154 
00155             if (! (value->u.object.values = (json_object_entry *) json_alloc
00156                   (state, values_size + ((unsigned long) value->u.object.values), 0)) )
00157             {
00158                return 0;
00159             }
00160 
00161             value->_reserved.object_mem = (*(char **) &value->u.object.values) + values_size;
00162 
00163             value->u.object.length = 0;
00164             break;
00165 
00166          case json_string:
00167 
00168             if (! (value->u.string.ptr = (json_char *) json_alloc
00169                (state, (value->u.string.length + 1) * sizeof (json_char), 0)) )
00170             {
00171                return 0;
00172             }
00173 
00174             value->u.string.length = 0;
00175             break;
00176 
00177          default:
00178             break;
00179       };
00180 
00181       return 1;
00182    }
00183 
00184    if (! (value = (json_value *) json_alloc
00185          (state, sizeof (json_value) + state->settings.value_extra, 1)))
00186    {
00187       return 0;
00188    }
00189 
00190    if (!*root)
00191       *root = value;
00192 
00193    value->type = type;
00194    value->parent = *top;
00195 
00196    #ifdef JSON_TRACK_SOURCE
00197       value->line = state->cur_line;
00198       value->col = state->cur_col;
00199    #endif
00200 
00201    if (*alloc)
00202       (*alloc)->_reserved.next_alloc = value;
00203 
00204    *alloc = *top = value;
00205 
00206    return 1;
00207 }
00208 
00209 #define whitespace \
00210    case '\n': ++ state.cur_line;  state.cur_col = 0; \
00211    case ' ': case '\t': case '\r'
00212 
00213 #define string_add(b)  \
00214    do { if (!state.first_pass) string [string_length] = b;  ++ string_length; } while (0);
00215 
00216 #define line_and_col \
00217    state.cur_line, state.cur_col
00218 
00219 static const long
00220    flag_next             = 1 << 0,
00221    flag_reproc           = 1 << 1,
00222    flag_need_comma       = 1 << 2,
00223    flag_seek_value       = 1 << 3, 
00224    flag_escaped          = 1 << 4,
00225    flag_string           = 1 << 5,
00226    flag_need_colon       = 1 << 6,
00227    flag_done             = 1 << 7,
00228    flag_num_negative     = 1 << 8,
00229    flag_num_zero         = 1 << 9,
00230    flag_num_e            = 1 << 10,
00231    flag_num_e_got_sign   = 1 << 11,
00232    flag_num_e_negative   = 1 << 12,
00233    flag_line_comment     = 1 << 13,
00234    flag_block_comment    = 1 << 14,
00235    flag_num_got_decimal  = 1 << 15;
00236 
00237 json_value * json_parse_ex (json_settings * settings,
00238                             const json_char * json,
00239                             size_t length,
00240                             char * error_buf)
00241 {
00242    json_char error [json_error_max];
00243    const json_char * end;
00244    json_value * top, * root, * alloc = 0;
00245    json_state state = { 0 };
00246    long flags = 0;
00247    double num_digits = 0, num_e = 0;
00248    double num_fraction = 0;
00249 
00250    /* Skip UTF-8 BOM
00251     */
00252    if (length >= 3 && ((unsigned char) json [0]) == 0xEF
00253                    && ((unsigned char) json [1]) == 0xBB
00254                    && ((unsigned char) json [2]) == 0xBF)
00255    {
00256       json += 3;
00257       length -= 3;
00258    }
00259 
00260    error[0] = '\0';
00261    end = (json + length);
00262 
00263    memcpy (&state.settings, settings, sizeof (json_settings));
00264 
00265    if (!state.settings.mem_alloc)
00266       state.settings.mem_alloc = default_alloc;
00267 
00268    if (!state.settings.mem_free)
00269       state.settings.mem_free = default_free;
00270 
00271    memset (&state.uint_max, 0xFF, sizeof (state.uint_max));
00272    memset (&state.ulong_max, 0xFF, sizeof (state.ulong_max));
00273 
00274    state.uint_max -= 8; /* limit of how much can be added before next check */
00275    state.ulong_max -= 8;
00276 
00277    for (state.first_pass = 1; state.first_pass >= 0; -- state.first_pass)
00278    {
00279       json_uchar uchar;
00280       unsigned char uc_b1, uc_b2, uc_b3, uc_b4;
00281       json_char * string = 0;
00282       unsigned int string_length = 0;
00283 
00284       top = root = 0;
00285       flags = flag_seek_value;
00286 
00287       state.cur_line = 1;
00288 
00289       for (state.ptr = json ;; ++ state.ptr)
00290       {
00291          json_char b = (state.ptr == end ? 0 : *state.ptr);
00292          
00293          if (flags & flag_string)
00294          {
00295             if (!b)
00296             {  sprintf (error, "Unexpected EOF in string (at %d:%d)", line_and_col);
00297                goto e_failed;
00298             }
00299 
00300             if (string_length > state.uint_max)
00301                goto e_overflow;
00302 
00303             if (flags & flag_escaped)
00304             {
00305                flags &= ~ flag_escaped;
00306 
00307                switch (b)
00308                {
00309                   case 'b':  string_add ('\b');  break;
00310                   case 'f':  string_add ('\f');  break;
00311                   case 'n':  string_add ('\n');  break;
00312                   case 'r':  string_add ('\r');  break;
00313                   case 't':  string_add ('\t');  break;
00314                   case 'u':
00315 
00316                     if (end - state.ptr <= 4 || 
00317                         (uc_b1 = hex_value (*++ state.ptr)) == 0xFF ||
00318                         (uc_b2 = hex_value (*++ state.ptr)) == 0xFF ||
00319                         (uc_b3 = hex_value (*++ state.ptr)) == 0xFF ||
00320                         (uc_b4 = hex_value (*++ state.ptr)) == 0xFF)
00321                     {
00322                         sprintf (error, "Invalid character value `%c` (at %d:%d)", b, line_and_col);
00323                         goto e_failed;
00324                     }
00325 
00326                     uc_b1 = (uc_b1 << 4) | uc_b2;
00327                     uc_b2 = (uc_b3 << 4) | uc_b4;
00328                     uchar = (uc_b1 << 8) | uc_b2;
00329 
00330                     if ((uchar & 0xF800) == 0xD800) {
00331                         json_uchar uchar2;
00332                         
00333                         if (end - state.ptr <= 6 || (*++ state.ptr) != '\\' || (*++ state.ptr) != 'u' ||
00334                             (uc_b1 = hex_value (*++ state.ptr)) == 0xFF ||
00335                             (uc_b2 = hex_value (*++ state.ptr)) == 0xFF ||
00336                             (uc_b3 = hex_value (*++ state.ptr)) == 0xFF ||
00337                             (uc_b4 = hex_value (*++ state.ptr)) == 0xFF)
00338                         {
00339                             sprintf (error, "Invalid character value `%c` (at %d:%d)", b, line_and_col);
00340                             goto e_failed;
00341                         }
00342 
00343                         uc_b1 = (uc_b1 << 4) | uc_b2;
00344                         uc_b2 = (uc_b3 << 4) | uc_b4;
00345                         uchar2 = (uc_b1 << 8) | uc_b2;
00346                         
00347                         uchar = 0x010000 | ((uchar & 0x3FF) << 10) | (uchar2 & 0x3FF);
00348                     }
00349 
00350                     if (sizeof (json_char) >= sizeof (json_uchar) || (uchar <= 0x7F))
00351                     {
00352                        string_add ((json_char) uchar);
00353                        break;
00354                     }
00355 
00356                     if (uchar <= 0x7FF)
00357                     {
00358                         if (state.first_pass)
00359                            string_length += 2;
00360                         else
00361                         {  string [string_length ++] = 0xC0 | (uchar >> 6);
00362                            string [string_length ++] = 0x80 | (uchar & 0x3F);
00363                         }
00364 
00365                         break;
00366                     }
00367 
00368                     if (uchar <= 0xFFFF) {
00369                         if (state.first_pass)
00370                            string_length += 3;
00371                         else
00372                         {  string [string_length ++] = 0xE0 | (uchar >> 12);
00373                            string [string_length ++] = 0x80 | ((uchar >> 6) & 0x3F);
00374                            string [string_length ++] = 0x80 | (uchar & 0x3F);
00375                         }
00376                         
00377                         break;
00378                     }
00379 
00380                     if (state.first_pass)
00381                        string_length += 4;
00382                     else
00383                     {  string [string_length ++] = 0xF0 | (uchar >> 18);
00384                        string [string_length ++] = 0x80 | ((uchar >> 12) & 0x3F);
00385                        string [string_length ++] = 0x80 | ((uchar >> 6) & 0x3F);
00386                        string [string_length ++] = 0x80 | (uchar & 0x3F);
00387                     }
00388 
00389                     break;
00390 
00391                   default:
00392                      string_add (b);
00393                };
00394 
00395                continue;
00396             }
00397 
00398             if (b == '\\')
00399             {
00400                flags |= flag_escaped;
00401                continue;
00402             }
00403 
00404             if (b == '"')
00405             {
00406                if (!state.first_pass)
00407                   string [string_length] = 0;
00408 
00409                flags &= ~ flag_string;
00410                string = 0;
00411 
00412                switch (top->type)
00413                {
00414                   case json_string:
00415 
00416                      top->u.string.length = string_length;
00417                      flags |= flag_next;
00418 
00419                      break;
00420 
00421                   case json_object:
00422 
00423                      if (state.first_pass)
00424                         (*(json_char **) &top->u.object.values) += string_length + 1;
00425                      else
00426                      {  
00427                         top->u.object.values [top->u.object.length].name
00428                            = (json_char *) top->_reserved.object_mem;
00429 
00430                         top->u.object.values [top->u.object.length].name_length
00431                            = string_length;
00432 
00433                         (*(json_char **) &top->_reserved.object_mem) += string_length + 1;
00434                      }
00435 
00436                      flags |= flag_seek_value | flag_need_colon;
00437                      continue;
00438 
00439                   default:
00440                      break;
00441                };
00442             }
00443             else
00444             {
00445                string_add (b);
00446                continue;
00447             }
00448          }
00449 
00450          if (state.settings.settings & json_enable_comments)
00451          {
00452             if (flags & (flag_line_comment | flag_block_comment))
00453             {
00454                if (flags & flag_line_comment)
00455                {
00456                   if (b == '\r' || b == '\n' || !b)
00457                   {
00458                      flags &= ~ flag_line_comment;
00459                      -- state.ptr;  /* so null can be reproc'd */
00460                   }
00461 
00462                   continue;
00463                }
00464 
00465                if (flags & flag_block_comment)
00466                {
00467                   if (!b)
00468                   {  sprintf (error, "%d:%d: Unexpected EOF in block comment", line_and_col);
00469                      goto e_failed;
00470                   }
00471 
00472                   if (b == '*' && state.ptr < (end - 1) && state.ptr [1] == '/')
00473                   {
00474                      flags &= ~ flag_block_comment;
00475                      ++ state.ptr;  /* skip closing sequence */
00476                   }
00477 
00478                   continue;
00479                }
00480             }
00481             else if (b == '/')
00482             {
00483                if (! (flags & (flag_seek_value | flag_done)) && top->type != json_object)
00484                {  sprintf (error, "%d:%d: Comment not allowed here", line_and_col);
00485                   goto e_failed;
00486                }
00487 
00488                if (++ state.ptr == end)
00489                {  sprintf (error, "%d:%d: EOF unexpected", line_and_col);
00490                   goto e_failed;
00491                }
00492 
00493                switch (b = *state.ptr)
00494                {
00495                   case '/':
00496                      flags |= flag_line_comment;
00497                      continue;
00498 
00499                   case '*':
00500                      flags |= flag_block_comment;
00501                      continue;
00502 
00503                   default:
00504                      sprintf (error, "%d:%d: Unexpected `%c` in comment opening sequence", line_and_col, b);
00505                      goto e_failed;
00506                };
00507             }
00508          }
00509 
00510          if (flags & flag_done)
00511          {
00512             if (!b)
00513                break;
00514 
00515             switch (b)
00516             {
00517                whitespace:
00518                   continue;
00519 
00520                default:
00521 
00522                   sprintf (error, "%d:%d: Trailing garbage: `%c`",
00523                            state.cur_line, state.cur_col, b);
00524 
00525                   goto e_failed;
00526             };
00527          }
00528 
00529          if (flags & flag_seek_value)
00530          {
00531             switch (b)
00532             {
00533                whitespace:
00534                   continue;
00535 
00536                case ']':
00537 
00538                   if (top && top->type == json_array)
00539                      flags = (flags & ~ (flag_need_comma | flag_seek_value)) | flag_next;
00540                   else
00541                   {  sprintf (error, "%d:%d: Unexpected ]", line_and_col);
00542                      goto e_failed;
00543                   }
00544 
00545                   break;
00546 
00547                default:
00548 
00549                   if (flags & flag_need_comma)
00550                   {
00551                      if (b == ',')
00552                      {  flags &= ~ flag_need_comma;
00553                         continue;
00554                      }
00555                      else
00556                      {
00557                         sprintf (error, "%d:%d: Expected , before %c",
00558                                  state.cur_line, state.cur_col, b);
00559 
00560                         goto e_failed;
00561                      }
00562                   }
00563 
00564                   if (flags & flag_need_colon)
00565                   {
00566                      if (b == ':')
00567                      {  flags &= ~ flag_need_colon;
00568                         continue;
00569                      }
00570                      else
00571                      { 
00572                         sprintf (error, "%d:%d: Expected : before %c",
00573                                  state.cur_line, state.cur_col, b);
00574 
00575                         goto e_failed;
00576                      }
00577                   }
00578 
00579                   flags &= ~ flag_seek_value;
00580 
00581                   switch (b)
00582                   {
00583                      case '{':
00584 
00585                         if (!new_value (&state, &top, &root, &alloc, json_object))
00586                            goto e_alloc_failure;
00587 
00588                         continue;
00589 
00590                      case '[':
00591 
00592                         if (!new_value (&state, &top, &root, &alloc, json_array))
00593                            goto e_alloc_failure;
00594 
00595                         flags |= flag_seek_value;
00596                         continue;
00597 
00598                      case '"':
00599 
00600                         if (!new_value (&state, &top, &root, &alloc, json_string))
00601                            goto e_alloc_failure;
00602 
00603                         flags |= flag_string;
00604 
00605                         string = top->u.string.ptr;
00606                         string_length = 0;
00607 
00608                         continue;
00609 
00610                      case 't':
00611 
00612                         if ((end - state.ptr) < 3 || *(++ state.ptr) != 'r' ||
00613                             *(++ state.ptr) != 'u' || *(++ state.ptr) != 'e')
00614                         {
00615                            goto e_unknown_value;
00616                         }
00617 
00618                         if (!new_value (&state, &top, &root, &alloc, json_boolean))
00619                            goto e_alloc_failure;
00620 
00621                         top->u.boolean = 1;
00622 
00623                         flags |= flag_next;
00624                         break;
00625 
00626                      case 'f':
00627 
00628                         if ((end - state.ptr) < 4 || *(++ state.ptr) != 'a' ||
00629                             *(++ state.ptr) != 'l' || *(++ state.ptr) != 's' ||
00630                             *(++ state.ptr) != 'e')
00631                         {
00632                            goto e_unknown_value;
00633                         }
00634 
00635                         if (!new_value (&state, &top, &root, &alloc, json_boolean))
00636                            goto e_alloc_failure;
00637 
00638                         flags |= flag_next;
00639                         break;
00640 
00641                      case 'n':
00642 
00643                         if ((end - state.ptr) < 3 || *(++ state.ptr) != 'u' ||
00644                             *(++ state.ptr) != 'l' || *(++ state.ptr) != 'l')
00645                         {
00646                            goto e_unknown_value;
00647                         }
00648 
00649                         if (!new_value (&state, &top, &root, &alloc, json_null))
00650                            goto e_alloc_failure;
00651 
00652                         flags |= flag_next;
00653                         break;
00654 
00655                      default:
00656 
00657                         if (isdigit (b) || b == '-')
00658                         {
00659                            if (!new_value (&state, &top, &root, &alloc, json_integer))
00660                               goto e_alloc_failure;
00661 
00662                            if (!state.first_pass)
00663                            {
00664                               while (isdigit (b) || b == '+' || b == '-'
00665                                         || b == 'e' || b == 'E' || b == '.')
00666                               {
00667                                  if ( (++ state.ptr) == end)
00668                                  {
00669                                     b = 0;
00670                                     break;
00671                                  }
00672 
00673                                  b = *state.ptr;
00674                               }
00675 
00676                               flags |= flag_next | flag_reproc;
00677                               break;
00678                            }
00679 
00680                            flags &= ~ (flag_num_negative | flag_num_e |
00681                                         flag_num_e_got_sign | flag_num_e_negative |
00682                                            flag_num_zero);
00683 
00684                            num_digits = 0;
00685                            num_fraction = 0;
00686                            num_e = 0;
00687 
00688                            if (b != '-')
00689                            {
00690                               flags |= flag_reproc;
00691                               break;
00692                            }
00693 
00694                            flags |= flag_num_negative;
00695                            continue;
00696                         }
00697                         else
00698                         {  sprintf (error, "%d:%d: Unexpected %c when seeking value", line_and_col, b);
00699                            goto e_failed;
00700                         }
00701                   };
00702             };
00703          }
00704          else
00705          {
00706             switch (top->type)
00707             {
00708             case json_object:
00709                
00710                switch (b)
00711                {
00712                   whitespace:
00713                      continue;
00714 
00715                   case '"':
00716 
00717                      if (flags & flag_need_comma)
00718                      {  sprintf (error, "%d:%d: Expected , before \"", line_and_col);
00719                         goto e_failed;
00720                      }
00721 
00722                      flags |= flag_string;
00723 
00724                      string = (json_char *) top->_reserved.object_mem;
00725                      string_length = 0;
00726 
00727                      break;
00728                   
00729                   case '}':
00730 
00731                      flags = (flags & ~ flag_need_comma) | flag_next;
00732                      break;
00733 
00734                   case ',':
00735 
00736                      if (flags & flag_need_comma)
00737                      {
00738                         flags &= ~ flag_need_comma;
00739                         break;
00740                      }
00741 
00742                   default:
00743                      sprintf (error, "%d:%d: Unexpected `%c` in object", line_and_col, b);
00744                      goto e_failed;
00745                };
00746 
00747                break;
00748 
00749             case json_integer:
00750             case json_double:
00751 
00752                if (isdigit (b))
00753                {
00754                   ++ num_digits;
00755 
00756                   if (top->type == json_integer || flags & flag_num_e)
00757                   {
00758                      if (! (flags & flag_num_e))
00759                      {
00760                         if (flags & flag_num_zero)
00761                         {  sprintf (error, "%d:%d: Unexpected `0` before `%c`", line_and_col, b);
00762                            goto e_failed;
00763                         }
00764 
00765                         if (num_digits == 1 && b == '0')
00766                            flags |= flag_num_zero;
00767                      }
00768                      else
00769                      {
00770                         flags |= flag_num_e_got_sign;
00771                         num_e = (num_e * 10) + (b - '0');
00772                         continue;
00773                      }
00774 
00775                      if (would_overflow(top->u.integer, b))
00776                      {  -- num_digits;
00777                         -- state.ptr;
00778                         top->type = json_double;
00779                         top->u.dbl = (double)top->u.integer;
00780                         continue;
00781                      }
00782 
00783                      top->u.integer = (top->u.integer * 10) + (b - '0');
00784                      continue;
00785                   }
00786 
00787                   if (flags & flag_num_got_decimal)
00788                      num_fraction = (num_fraction * 10) + (b - '0');
00789                   else
00790                      top->u.dbl = (top->u.dbl * 10) + (b - '0');
00791 
00792                   continue;
00793                }
00794 
00795                if (b == '+' || b == '-')
00796                {
00797                   if ( (flags & flag_num_e) && !(flags & flag_num_e_got_sign))
00798                   {
00799                      flags |= flag_num_e_got_sign;
00800 
00801                      if (b == '-')
00802                         flags |= flag_num_e_negative;
00803 
00804                      continue;
00805                   }
00806                }
00807                else if (b == '.' && top->type == json_integer)
00808                {
00809                   if (!num_digits)
00810                   {  sprintf (error, "%d:%d: Expected digit before `.`", line_and_col);
00811                      goto e_failed;
00812                   }
00813 
00814                   top->type = json_double;
00815                   top->u.dbl = (double) top->u.integer;
00816 
00817                   flags |= flag_num_got_decimal;
00818                   num_digits = 0;
00819                   continue;
00820                }
00821 
00822                if (! (flags & flag_num_e))
00823                {
00824                   if (top->type == json_double)
00825                   {
00826                      if (!num_digits)
00827                      {  sprintf (error, "%d:%d: Expected digit after `.`", line_and_col);
00828                         goto e_failed;
00829                      }
00830 
00831                      top->u.dbl += num_fraction / pow (10.0, num_digits);
00832                   }
00833 
00834                   if (b == 'e' || b == 'E')
00835                   {
00836                      flags |= flag_num_e;
00837 
00838                      if (top->type == json_integer)
00839                      {
00840                         top->type = json_double;
00841                         top->u.dbl = (double) top->u.integer;
00842                      }
00843 
00844                      num_digits = 0;
00845                      flags &= ~ flag_num_zero;
00846 
00847                      continue;
00848                   }
00849                }
00850                else
00851                {
00852                   if (!num_digits)
00853                   {  sprintf (error, "%d:%d: Expected digit after `e`", line_and_col);
00854                      goto e_failed;
00855                   }
00856 
00857                   top->u.dbl *= pow (10.0, (flags & flag_num_e_negative ? - num_e : num_e));
00858                }
00859 
00860                if (flags & flag_num_negative)
00861                {
00862                   if (top->type == json_integer)
00863                      top->u.integer = - top->u.integer;
00864                   else
00865                      top->u.dbl = - top->u.dbl;
00866                }
00867 
00868                flags |= flag_next | flag_reproc;
00869                break;
00870 
00871             default:
00872                break;
00873             };
00874          }
00875 
00876          if (flags & flag_reproc)
00877          {
00878             flags &= ~ flag_reproc;
00879             -- state.ptr;
00880          }
00881 
00882          if (flags & flag_next)
00883          {
00884             flags = (flags & ~ flag_next) | flag_need_comma;
00885 
00886             if (!top->parent)
00887             {
00888                /* root value done */
00889 
00890                flags |= flag_done;
00891                continue;
00892             }
00893 
00894             if (top->parent->type == json_array)
00895                flags |= flag_seek_value;
00896                
00897             if (!state.first_pass)
00898             {
00899                json_value * parent = top->parent;
00900 
00901                switch (parent->type)
00902                {
00903                   case json_object:
00904 
00905                      parent->u.object.values
00906                         [parent->u.object.length].value = top;
00907 
00908                      break;
00909 
00910                   case json_array:
00911 
00912                      parent->u.array.values
00913                            [parent->u.array.length] = top;
00914 
00915                      break;
00916 
00917                   default:
00918                      break;
00919                };
00920             }
00921 
00922             if ( (++ top->parent->u.array.length) > state.uint_max)
00923                goto e_overflow;
00924 
00925             top = top->parent;
00926 
00927             continue;
00928          }
00929       }
00930 
00931       alloc = root;
00932    }
00933 
00934    return root;
00935 
00936 e_unknown_value:
00937 
00938    sprintf (error, "%d:%d: Unknown value", line_and_col);
00939    goto e_failed;
00940 
00941 e_alloc_failure:
00942 
00943    strcpy (error, "Memory allocation failure");
00944    goto e_failed;
00945 
00946 e_overflow:
00947 
00948    sprintf (error, "%d:%d: Too long (caught overflow)", line_and_col);
00949    goto e_failed;
00950 
00951 e_failed:
00952 
00953    if (error_buf)
00954    {
00955       if (*error)
00956          strcpy (error_buf, error);
00957       else
00958          strcpy (error_buf, "Unknown error");
00959    }
00960 
00961    if (state.first_pass)
00962       alloc = root;
00963 
00964    while (alloc)
00965    {
00966       top = alloc->_reserved.next_alloc;
00967       state.settings.mem_free (alloc, state.settings.user_data);
00968       alloc = top;
00969    }
00970 
00971    if (!state.first_pass)
00972       json_value_free_ex (&state.settings, root);
00973 
00974    return 0;
00975 }
00976 
00977 json_value * json_parse (const json_char * json, size_t length)
00978 {
00979    json_settings settings = { 0 };
00980    return json_parse_ex (&settings, json, length, 0);
00981 }
00982 
00983 void json_value_free_ex (json_settings * settings, json_value * value)
00984 {
00985    json_value * cur_value;
00986 
00987    if (!value)
00988       return;
00989 
00990    value->parent = 0;
00991 
00992    while (value)
00993    {
00994       switch (value->type)
00995       {
00996          case json_array:
00997 
00998             if (!value->u.array.length)
00999             {
01000                settings->mem_free (value->u.array.values, settings->user_data);
01001                break;
01002             }
01003 
01004             value = value->u.array.values [-- value->u.array.length];
01005             continue;
01006 
01007          case json_object:
01008 
01009             if (!value->u.object.length)
01010             {
01011                settings->mem_free (value->u.object.values, settings->user_data);
01012                break;
01013             }
01014 
01015             value = value->u.object.values [-- value->u.object.length].value;
01016             continue;
01017 
01018          case json_string:
01019 
01020             settings->mem_free (value->u.string.ptr, settings->user_data);
01021             break;
01022 
01023          default:
01024             break;
01025       };
01026 
01027       cur_value = value;
01028       value = value->parent;
01029       settings->mem_free (cur_value, settings->user_data);
01030    }
01031 }
01032 
01033 void json_value_free (json_value * value)
01034 {
01035    json_settings settings = { 0 };
01036    settings.mem_free = default_free;
01037    json_value_free_ex (&settings, value);
01038 }
01039 

Generated on Thu Dec 5 03:07:36 2024 for VMD Plugins (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002