PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LTP GCOV extension - code coverage report
Current view: directory - json - JSON_parser.c
Test: PHP Code Coverage
Date: 2009-11-23 Instrumented lines: 259
Code covered: 94.2 % Executed lines: 244
Legend: not executed executed

       1                 : /* JSON_parser.c */
       2                 : 
       3                 : /* 2005-12-30 */
       4                 : 
       5                 : /*
       6                 : Copyright (c) 2005 JSON.org
       7                 : 
       8                 : Permission is hereby granted, free of charge, to any person obtaining a copy
       9                 : of this software and associated documentation files (the "Software"), to deal
      10                 : in the Software without restriction, including without limitation the rights
      11                 : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      12                 : copies of the Software, and to permit persons to whom the Software is
      13                 : furnished to do so, subject to the following conditions:
      14                 : 
      15                 : The above copyright notice and this permission notice shall be included in all
      16                 : copies or substantial portions of the Software.
      17                 : 
      18                 : The Software shall be used for Good, not Evil.
      19                 : 
      20                 : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      21                 : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      22                 : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      23                 : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      24                 : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      25                 : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
      26                 : SOFTWARE.
      27                 : */
      28                 : 
      29                 : #include <stdio.h>
      30                 : #include "JSON_parser.h"
      31                 : 
      32                 : /* Windows defines IN for documentation */
      33                 : #undef IN
      34                 : 
      35                 : #define true  1
      36                 : #define false 0
      37                 : #define __   -1     /* the universal error code */
      38                 : 
      39                 : /*
      40                 :     Characters are mapped into these 31 character classes. This allows for
      41                 :     a significant reduction in the size of the state transition table.
      42                 : */
      43                 : 
      44                 : enum classes {
      45                 :     C_SPACE,  /* space */
      46                 :     C_WHITE,  /* other whitespace */
      47                 :     C_LCURB,  /* {  */
      48                 :     C_RCURB,  /* } */
      49                 :     C_LSQRB,  /* [ */
      50                 :     C_RSQRB,  /* ] */
      51                 :     C_COLON,  /* : */
      52                 :     C_COMMA,  /* , */
      53                 :     C_QUOTE,  /* " */
      54                 :     C_BACKS,  /* \ */
      55                 :     C_SLASH,  /* / */
      56                 :     C_PLUS,   /* + */
      57                 :     C_MINUS,  /* - */
      58                 :     C_POINT,  /* . */
      59                 :     C_ZERO ,  /* 0 */
      60                 :     C_DIGIT,  /* 123456789 */
      61                 :     C_LOW_A,  /* a */
      62                 :     C_LOW_B,  /* b */
      63                 :     C_LOW_C,  /* c */
      64                 :     C_LOW_D,  /* d */
      65                 :     C_LOW_E,  /* e */
      66                 :     C_LOW_F,  /* f */
      67                 :     C_LOW_L,  /* l */
      68                 :     C_LOW_N,  /* n */
      69                 :     C_LOW_R,  /* r */
      70                 :     C_LOW_S,  /* s */
      71                 :     C_LOW_T,  /* t */
      72                 :     C_LOW_U,  /* u */
      73                 :     C_ABCDF,  /* ABCDF */
      74                 :     C_E,      /* E */
      75                 :     C_ETC,    /* everything else */
      76                 :     NR_CLASSES
      77                 : };
      78                 : 
      79                 : static const int ascii_class[128] = {
      80                 : /*
      81                 :     This array maps the 128 ASCII characters into character classes.
      82                 :     The remaining Unicode characters should be mapped to C_ETC.
      83                 :     Non-whitespace control characters are errors.
      84                 : */
      85                 :     __,      __,      __,      __,      __,      __,      __,      __,
      86                 :     __,      C_WHITE, C_WHITE, __,      __,      C_WHITE, __,      __,
      87                 :     __,      __,      __,      __,      __,      __,      __,      __,
      88                 :     __,      __,      __,      __,      __,      __,      __,      __,
      89                 : 
      90                 :     C_SPACE, C_ETC,   C_QUOTE, C_ETC,   C_ETC,   C_ETC,   C_ETC,   C_ETC,
      91                 :     C_ETC,   C_ETC,   C_ETC,   C_PLUS,  C_COMMA, C_MINUS, C_POINT, C_SLASH,
      92                 :     C_ZERO,  C_DIGIT, C_DIGIT, C_DIGIT, C_DIGIT, C_DIGIT, C_DIGIT, C_DIGIT,
      93                 :     C_DIGIT, C_DIGIT, C_COLON, C_ETC,   C_ETC,   C_ETC,   C_ETC,   C_ETC,
      94                 : 
      95                 :     C_ETC,   C_ABCDF, C_ABCDF, C_ABCDF, C_ABCDF, C_E,     C_ABCDF, C_ETC,
      96                 :     C_ETC,   C_ETC,   C_ETC,   C_ETC,   C_ETC,   C_ETC,   C_ETC,   C_ETC,
      97                 :     C_ETC,   C_ETC,   C_ETC,   C_ETC,   C_ETC,   C_ETC,   C_ETC,   C_ETC,
      98                 :     C_ETC,   C_ETC,   C_ETC,   C_LSQRB, C_BACKS, C_RSQRB, C_ETC,   C_ETC,
      99                 : 
     100                 :     C_ETC,   C_LOW_A, C_LOW_B, C_LOW_C, C_LOW_D, C_LOW_E, C_LOW_F, C_ETC,
     101                 :     C_ETC,   C_ETC,   C_ETC,   C_ETC,   C_LOW_L, C_ETC,   C_LOW_N, C_ETC,
     102                 :     C_ETC,   C_ETC,   C_LOW_R, C_LOW_S, C_LOW_T, C_LOW_U, C_ETC,   C_ETC,
     103                 :     C_ETC,   C_ETC,   C_ETC,   C_LCURB, C_ETC,   C_RCURB, C_ETC,   C_ETC
     104                 : };
     105                 : 
     106                 : 
     107                 : /*
     108                 :     The state codes.
     109                 : */
     110                 : enum states {
     111                 :     GO,  /* start    */
     112                 :     OK,  /* ok       */
     113                 :     OB,  /* object   */
     114                 :     KE,  /* key      */
     115                 :     CO,  /* colon    */
     116                 :     VA,  /* value    */
     117                 :     AR,  /* array    */
     118                 :     ST,  /* string   */
     119                 :     ES,  /* escape   */
     120                 :     U1,  /* u1       */
     121                 :     U2,  /* u2       */
     122                 :     U3,  /* u3       */
     123                 :     U4,  /* u4       */
     124                 :     MI,  /* minus    */
     125                 :     ZE,  /* zero     */
     126                 :     IN,  /* integer  */
     127                 :     FR,  /* fraction */
     128                 :     E1,  /* e        */
     129                 :     E2,  /* ex       */
     130                 :     E3,  /* exp      */
     131                 :     T1,  /* tr       */
     132                 :     T2,  /* tru      */
     133                 :     T3,  /* true     */
     134                 :     F1,  /* fa       */
     135                 :     F2,  /* fal      */
     136                 :     F3,  /* fals     */
     137                 :     F4,  /* false    */
     138                 :     N1,  /* nu       */
     139                 :     N2,  /* nul      */
     140                 :     N3,  /* null     */
     141                 :     NR_STATES
     142                 : };
     143                 : 
     144                 : 
     145                 : static const int state_transition_table[NR_STATES][NR_CLASSES] = {
     146                 : /*
     147                 :     The state transition table takes the current state and the current symbol,
     148                 :     and returns either a new state or an action. An action is represented as a
     149                 :     negative number. A JSON text is accepted if at the end of the text the
     150                 :     state is OK and if the mode is MODE_DONE.
     151                 : 
     152                 :                  white                                      1-9                                   ABCDF  etc
     153                 :              space |  {  }  [  ]  :  ,  "  \  /  +  -  .  0  |  a  b  c  d  e  f  l  n  r  s  t  u  |  E  |*/
     154                 : /*start  GO*/ {GO,GO,-6,__,-5,__,__,__,ST,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__},
     155                 : /*ok     OK*/ {OK,OK,__,-8,__,-7,__,-3,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__},
     156                 : /*object OB*/ {OB,OB,__,-9,__,__,__,__,ST,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__},
     157                 : /*key    KE*/ {KE,KE,__,__,__,__,__,__,ST,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__},
     158                 : /*colon  CO*/ {CO,CO,__,__,__,__,-2,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__},
     159                 : /*value  VA*/ {VA,VA,-6,__,-5,__,__,__,ST,__,__,__,MI,__,ZE,IN,__,__,__,__,__,F1,__,N1,__,__,T1,__,__,__,__},
     160                 : /*array  AR*/ {AR,AR,-6,__,-5,-7,__,__,ST,__,__,__,MI,__,ZE,IN,__,__,__,__,__,F1,__,N1,__,__,T1,__,__,__,__},
     161                 : /*string ST*/ {ST,__,ST,ST,ST,ST,ST,ST,-4,ES,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST},
     162                 : /*escape ES*/ {__,__,__,__,__,__,__,__,ST,ST,ST,__,__,__,__,__,__,ST,__,__,__,ST,__,ST,ST,__,ST,U1,__,__,__},
     163                 : /*u1     U1*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,U2,U2,U2,U2,U2,U2,U2,U2,__,__,__,__,__,__,U2,U2,__},
     164                 : /*u2     U2*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,U3,U3,U3,U3,U3,U3,U3,U3,__,__,__,__,__,__,U3,U3,__},
     165                 : /*u3     U3*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,U4,U4,U4,U4,U4,U4,U4,U4,__,__,__,__,__,__,U4,U4,__},
     166                 : /*u4     U4*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,ST,ST,ST,ST,ST,ST,ST,ST,__,__,__,__,__,__,ST,ST,__},
     167                 : /*minus  MI*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,ZE,IN,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__},
     168                 : /*zero   ZE*/ {OK,OK,__,-8,__,-7,__,-3,__,__,__,__,__,FR,__,__,__,__,__,__,E1,__,__,__,__,__,__,__,__,E1,__},
     169                 : /*int    IN*/ {OK,OK,__,-8,__,-7,__,-3,__,__,__,__,__,FR,IN,IN,__,__,__,__,E1,__,__,__,__,__,__,__,__,E1,__},
     170                 : /*frac   FR*/ {OK,OK,__,-8,__,-7,__,-3,__,__,__,__,__,__,FR,FR,__,__,__,__,E1,__,__,__,__,__,__,__,__,E1,__},
     171                 : /*e      E1*/ {__,__,__,__,__,__,__,__,__,__,__,E2,E2,__,E3,E3,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__},
     172                 : /*ex     E2*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,E3,E3,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__},
     173                 : /*exp    E3*/ {OK,OK,__,-8,__,-7,__,-3,__,__,__,__,__,__,E3,E3,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__},
     174                 : /*tr     T1*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,T2,__,__,__,__,__,__},
     175                 : /*tru    T2*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,T3,__,__,__},
     176                 : /*true   T3*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,OK,__,__,__,__,__,__,__,__,__,__},
     177                 : /*fa     F1*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,F2,__,__,__,__,__,__,__,__,__,__,__,__,__,__},
     178                 : /*fal    F2*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,F3,__,__,__,__,__,__,__,__},
     179                 : /*fals   F3*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,F4,__,__,__,__,__},
     180                 : /*false  F4*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,OK,__,__,__,__,__,__,__,__,__,__},
     181                 : /*nu     N1*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,N2,__,__,__},
     182                 : /*nul    N2*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,N3,__,__,__,__,__,__,__,__},
     183                 : /*null   N3*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,OK,__,__,__,__,__,__,__,__},
     184                 : };
     185                 : 
     186                 : 
     187                 : /*
     188                 :     These modes can be pushed on the stack.
     189                 : */
     190                 : enum modes {
     191                 :     MODE_ARRAY, 
     192                 :     MODE_DONE,  
     193                 :     MODE_KEY,   
     194                 :     MODE_OBJECT,
     195                 : };
     196                 : 
     197                 : 
     198                 : /*
     199                 :     Push a mode onto the stack. Return false if there is overflow.
     200                 : */
     201                 : static int
     202                 : push(JSON_parser jp, int mode)
     203            2078 : {
     204            2078 :     jp->top += 1;
     205            2078 :     if (jp->top >= jp->depth) {
     206               3 :                 jp->error_code = PHP_JSON_ERROR_DEPTH;
     207               3 :         return false;
     208                 :     }
     209            2075 :     jp->stack[jp->top] = mode;
     210            2075 :     return true;
     211                 : }
     212                 : 
     213                 : 
     214                 : /*
     215                 :     Pop the stack, assuring that the current mode matches the expectation.
     216                 :     Return false if there is underflow or if the modes mismatch.
     217                 : */
     218                 : static int
     219                 : pop(JSON_parser jp, int mode)
     220             931 : {
     221             931 :     if (jp->top < 0 || jp->stack[jp->top] != mode) {
     222               6 :                 jp->error_code = PHP_JSON_ERROR_STATE_MISMATCH;
     223               6 :         return false;
     224                 :     }
     225             925 :     jp->top -= 1;
     226             925 :     return true;
     227                 : }
     228                 : 
     229                 : /*
     230                 :     new_JSON_checker starts the checking process by constructing a JSON_checker
     231                 :     object. It takes a depth parameter that restricts the level of maximum
     232                 :     nesting.
     233                 : 
     234                 :     To continue the process, call JSON_checker_char for each character in the
     235                 :     JSON text, and then call JSON_checker_done to obtain the final result.
     236                 :     These functions are fully reentrant.
     237                 : 
     238                 :     The JSON_checker object will be deleted by JSON_checker_done.
     239                 :     JSON_checker_char will delete the JSON_checker object if it sees an error.
     240                 : */
     241                 : JSON_parser
     242                 : new_JSON_parser(int depth)
     243             135 : {
     244             135 :     JSON_parser jp = (JSON_parser)emalloc(sizeof(struct JSON_parser_struct));
     245             135 :     jp->state = GO;
     246             135 :     jp->depth = depth;
     247             135 :     jp->top = -1;
     248             135 :         jp->error_code = PHP_JSON_ERROR_NONE;
     249             135 :     jp->stack = (int*)ecalloc(depth, sizeof(int));
     250             135 :     if (depth > JSON_PARSER_DEFAULT_DEPTH) {
     251               0 :         jp->the_zstack = (zval **)safe_emalloc(depth, sizeof(zval), 0);
     252                 :     } else {
     253             135 :         jp->the_zstack = &jp->the_static_zstack[0];
     254                 :     }
     255             135 :     push(jp, MODE_DONE);
     256             135 :     return jp;
     257                 : }
     258                 : 
     259                 : /*
     260                 :     Delete the JSON_parser object.
     261                 : */
     262                 : int
     263                 : free_JSON_parser(JSON_parser jp)
     264             135 : {
     265             135 :     efree((void*)jp->stack);
     266             135 :     if (jp->the_zstack != &jp->the_static_zstack[0]) {
     267               0 :         efree(jp->the_zstack);
     268                 :     }
     269             135 :     efree((void*)jp);
     270             135 :     return false;
     271                 : }
     272                 : 
     273                 : static int dehexchar(char c)
     274             608 : {
     275             608 :     if (c >= '0' && c <= '9')
     276                 :     {
     277             270 :         return c - '0';
     278                 :     }
     279             338 :     else if (c >= 'A' && c <= 'F')
     280                 :     {
     281              88 :         return c - ('A' - 10);
     282                 :     }
     283             250 :     else if (c >= 'a' && c <= 'f')
     284                 :     {
     285             250 :         return c - ('a' - 10);
     286                 :     }
     287                 :     else
     288                 :     {
     289               0 :         return -1;
     290                 :     }
     291                 : }
     292                 : 
     293                 : 
     294                 : static void json_create_zval(zval **z, smart_str *buf, int type TSRMLS_DC)
     295             548 : {
     296             548 :     ALLOC_INIT_ZVAL(*z);
     297                 : 
     298             548 :     if (type == IS_LONG)
     299                 :     {
     300             209 :                 if (buf->c[0] == '-') {
     301               8 :                         buf->len--;
     302                 :                 }
     303                 : 
     304             209 :                 if (buf->len >= MAX_LENGTH_OF_LONG - 1) {
     305              10 :                         if (buf->len == MAX_LENGTH_OF_LONG - 1) {
     306               8 :                                 int cmp = strcmp(buf->c + (buf->c[0] == '-'), long_min_digits);
     307                 : 
     308               8 :                                 if (!(cmp < 0 || (cmp == 0 && buf->c[0] == '-'))) {
     309                 :                                         goto use_double;
     310                 :                                 }
     311                 :                         } else {
     312               2 :                                 goto use_double;
     313                 :                         }
     314                 :                 }
     315                 : 
     316             207 :                 ZVAL_LONG(*z, strtol(buf->c, NULL, 10));
     317                 :     }
     318             339 :     else if (type == IS_DOUBLE)
     319                 :     {
     320              62 : use_double:
     321              62 :         ZVAL_DOUBLE(*z, zend_strtod(buf->c, NULL));
     322                 :     }
     323             279 :     else if (type == IS_STRING)
     324                 :     {
     325             223 :         ZVAL_UTF8_STRINGL(*z, buf->c, buf->len, ZSTR_DUPLICATE);
     326                 :     }
     327              56 :     else if (type == IS_BOOL)
     328                 :     {
     329              38 :         ZVAL_BOOL(*z, (*(buf->c) == 't'));
     330                 :     }
     331                 :     else /* type == IS_NULL) || type unknown */
     332                 :     {
     333              18 :         ZVAL_NULL(*z);
     334                 :     }
     335             548 : }
     336                 : 
     337                 : 
     338                 : static void utf16_to_utf8(smart_str *buf, unsigned short utf16)
     339            6797 : {
     340            6797 :     if (utf16 < 0x80)
     341                 :     {
     342            6625 :         smart_str_appendc(buf, (unsigned char) utf16);
     343                 :     }
     344             172 :     else if (utf16 < 0x800)
     345                 :     {
     346              12 :         smart_str_appendc(buf, 0xc0 | (utf16 >> 6));
     347              12 :         smart_str_appendc(buf, 0x80 | (utf16 & 0x3f));
     348                 :     }
     349             160 :     else if ((utf16 & 0xfc00) == 0xdc00
     350                 :                 && buf->len >= 3
     351                 :                 && ((unsigned char) buf->c[buf->len - 3]) == 0xed
     352                 :                 && ((unsigned char) buf->c[buf->len - 2] & 0xf0) == 0xa0
     353                 :                 && ((unsigned char) buf->c[buf->len - 1] & 0xc0) == 0x80)
     354                 :     {
     355                 :         /* found surrogate pair */
     356                 :         unsigned long utf32;
     357                 : 
     358               0 :         utf32 = (((buf->c[buf->len - 2] & 0xf) << 16)
     359                 :                     | ((buf->c[buf->len - 1] & 0x3f) << 10)
     360                 :                     | (utf16 & 0x3ff)) + 0x10000;
     361               0 :         buf->len -= 3;
     362                 : 
     363               0 :         smart_str_appendc(buf, (unsigned char) (0xf0 | (utf32 >> 18)));
     364               0 :         smart_str_appendc(buf, 0x80 | ((utf32 >> 12) & 0x3f));
     365               0 :         smart_str_appendc(buf, 0x80 | ((utf32 >> 6) & 0x3f));
     366               0 :         smart_str_appendc(buf, 0x80 | (utf32 & 0x3f));
     367                 :     }
     368                 :     else
     369                 :     {
     370             160 :         smart_str_appendc(buf, 0xe0 | (utf16 >> 12));
     371             160 :         smart_str_appendc(buf, 0x80 | ((utf16 >> 6) & 0x3f));
     372             160 :         smart_str_appendc(buf, 0x80 | (utf16 & 0x3f));
     373                 :     }
     374            6797 : }
     375                 : 
     376                 : static void attach_zval(JSON_parser jp, int up, int cur, smart_str *key, int assoc TSRMLS_DC)
     377            1193 : {
     378            1193 :     zval *root = jp->the_zstack[up];
     379            1193 :     zval *child =  jp->the_zstack[cur];
     380            1193 :     int up_mode = jp->stack[up];
     381                 : 
     382            1193 :     if (up_mode == MODE_ARRAY)
     383                 :     {
     384            1124 :         add_next_index_zval(root, child);
     385                 :     }
     386              69 :     else if (up_mode == MODE_OBJECT)
     387                 :     {
     388              69 :         if (!assoc)
     389                 :         {
     390              37 :             add_utf8_property_zval_ex(root, (key->len ? key->c : "_empty_"), (key->len ? (key->len + 1) : sizeof("_empty_")), child TSRMLS_CC);
     391              37 :             Z_DELREF_P(child);
     392                 :         }
     393                 :         else
     394                 :         {
     395              32 :             add_utf8_assoc_zval_ex(root, (key->len ? key->c : ""), (key->len ? (key->len + 1) : sizeof("")), child);
     396                 :         }
     397              69 :         key->len = 0;
     398                 :     }
     399            1193 : }
     400                 : 
     401                 : 
     402                 : #define FREE_BUFFERS() smart_str_free(&buf); smart_str_free(&key);
     403                 : #define SWAP_BUFFERS(from, to) do { \
     404                 :         char *t1 = from.c; \
     405                 :         int t2 = from.a; \
     406                 :         from.c = to.c; \
     407                 :         from.a = to.a; \
     408                 :         to.c = t1; \
     409                 :         to.a = t2; \
     410                 :         to.len = from.len; \
     411                 :         from.len = 0; \
     412                 :         } while(0);
     413                 : #define JSON_RESET_TYPE() type = -1;
     414                 : 
     415                 : /*
     416                 :     The JSON_parser takes a UTF-16 encoded string and determines if it is a
     417                 :     syntactically correct JSON text. Along the way, it creates a PHP variable.
     418                 : 
     419                 :     It is implemented as a Pushdown Automaton; that means it is a finite state
     420                 :     machine with a stack.
     421                 : */
     422                 : int
     423                 : parse_JSON(JSON_parser jp, zval *z, unsigned short utf16_json[], int length, int assoc TSRMLS_DC)
     424             135 : {
     425                 :     int next_char;  /* the next character */
     426                 :     int next_class;  /* the next character class */
     427                 :     int next_state;  /* the next state */
     428                 :     int the_index;
     429                 : 
     430             135 :     smart_str buf = {0};
     431             135 :     smart_str key = {0};
     432                 : 
     433             135 :     unsigned short utf16 = 0;
     434                 :     int type;
     435                 : 
     436             135 :         JSON_RESET_TYPE();
     437                 : 
     438           13936 :     for (the_index = 0; the_index < length; the_index += 1) {
     439           13880 :         next_char = utf16_json[the_index];
     440           13880 :                 if (next_char >= 128) {
     441              25 :                         next_class = C_ETC;
     442                 :                 } else {
     443           13855 :                         next_class = ascii_class[next_char];
     444           13855 :                         if (next_class <= __) {
     445               1 :                                 jp->error_code = PHP_JSON_ERROR_CTRL_CHAR;
     446               1 :                                 FREE_BUFFERS();
     447               1 :                                 return false;
     448                 :                         }
     449                 :                 }
     450                 : /*
     451                 :     Get the next state from the transition table.
     452                 : */
     453           13879 :         next_state = state_transition_table[jp->state][next_class];
     454           13879 :         if (next_state >= 0) {
     455                 : /*
     456                 :     Change the state and iterate
     457                 : */
     458           10793 :                         if (type == IS_STRING) {
     459           13096 :                     if (next_state == ST && jp->state != U4) {
     460            5966 :                         if (jp->state != ES) {
     461            5755 :                             utf16_to_utf8(&buf, next_char);
     462                 :                         } else {
     463             211 :                             switch (next_char) {
     464                 :                                 case 'b':
     465              16 :                                     smart_str_appendc(&buf, '\b');
     466              16 :                                     break;
     467                 :                                 case 't':
     468              16 :                                     smart_str_appendc(&buf, '\t');
     469              16 :                                     break;
     470                 :                                 case 'n':
     471              18 :                                     smart_str_appendc(&buf, '\n');
     472              18 :                                     break;
     473                 :                                 case 'f':
     474              16 :                                     smart_str_appendc(&buf, '\f');
     475              16 :                                     break;
     476                 :                                 case 'r':
     477              18 :                                     smart_str_appendc(&buf, '\r');
     478              18 :                                     break;
     479                 :                                 default:
     480             127 :                                     utf16_to_utf8(&buf, next_char);
     481                 :                                     break;
     482                 :                             }
     483                 :                         }
     484            1164 :                     } else if (next_state == U2) {
     485             152 :                         utf16 = dehexchar(next_char) << 12;
     486            1012 :                     } else if (next_state == U3) {
     487             152 :                         utf16 += dehexchar(next_char) << 8;
     488             860 :                     } else if (next_state == U4) {
     489             152 :                         utf16 += dehexchar(next_char) << 4;
     490             708 :                     } else if (next_state == ST && jp->state == U4) {
     491             152 :                         utf16 += dehexchar(next_char);
     492             152 :                         utf16_to_utf8(&buf, utf16);
     493                 :                     }
     494            3940 :                 } else if (type < IS_LONG && (next_class == C_DIGIT || next_class == C_ZERO)) {
     495             277 :                     type = IS_LONG;
     496             277 :                     smart_str_appendc(&buf, next_char);
     497            3393 :                 } else if (type == IS_LONG && next_state == E1) {
     498               7 :                     type = IS_DOUBLE;
     499               7 :                     smart_str_appendc(&buf, next_char);
     500            3432 :                 } else if (type < IS_DOUBLE && next_class == C_POINT) {
     501              53 :                     type = IS_DOUBLE;
     502              53 :                     smart_str_appendc(&buf, next_char);
     503            3940 :                 } else if (type < IS_STRING && next_class == C_QUOTE) {
     504             614 :                     type = IS_STRING;
     505            2750 :                 } else if (type < IS_BOOL && ((jp->state == T3 && next_state == OK) || (jp->state == F4 && next_state == OK))) {
     506              38 :                     type = IS_BOOL;
     507            2692 :                 } else if (type < IS_NULL && jp->state == N3 && next_state == OK) {
     508              18 :                     type = IS_NULL;
     509            2656 :                 } else if (type != IS_STRING && next_class > C_WHITE) {
     510             763 :                     utf16_to_utf8(&buf, next_char);
     511                 :                 }
     512           10793 :                 jp->state = next_state;
     513                 :                 } else {
     514                 : /*
     515                 :     Perform one of the predefined actions.
     516                 : */
     517            3086 :             switch (next_state) {
     518                 : /* empty } */
     519                 :             case -9:
     520              14 :                 if (!pop(jp, MODE_KEY)) {
     521               0 :                     FREE_BUFFERS();
     522               0 :                     return false;
     523                 :                 }
     524              14 :                 jp->state = OK;
     525              14 :                 break;
     526                 : /* } */
     527                 :             case -8:
     528              56 :                 if (type != -1 && jp->stack[jp->top] == MODE_OBJECT)
     529                 :                 {
     530                 :                     zval *mval;
     531              27 :                     smart_str_0(&buf);
     532                 : 
     533              27 :                     json_create_zval(&mval, &buf, type TSRMLS_CC);
     534                 : 
     535              27 :                     if (!assoc) {
     536              15 :                         add_utf8_property_zval_ex(jp->the_zstack[jp->top], (key.len ? key.c : "_empty_"), (key.len ? (key.len + 1) : sizeof("_empty_")), mval TSRMLS_CC);
     537              15 :                         Z_DELREF_P(mval);
     538                 :                     } else {
     539              12 :                         add_utf8_assoc_zval_ex(jp->the_zstack[jp->top], (key.len ? key.c : ""), (key.len ? (key.len + 1) : sizeof("")), mval);
     540                 :                     }
     541              27 :                     key.len = 0;
     542              27 :                     buf.len = 0;
     543              27 :                     JSON_RESET_TYPE();
     544                 :                 }
     545                 : 
     546                 : 
     547              56 :                 if (!pop(jp, MODE_OBJECT)) {
     548               1 :                     FREE_BUFFERS();
     549               1 :                     return false;
     550                 :                 }
     551              55 :                 jp->state = OK;
     552              55 :                 break;
     553                 : /* ] */
     554                 :             case -7:
     555                 :             {
     556             152 :                 if (type != -1 && jp->stack[jp->top] == MODE_ARRAY)
     557                 :                 {
     558                 :                     zval *mval;
     559              56 :                     smart_str_0(&buf);
     560                 : 
     561              56 :                     json_create_zval(&mval, &buf, type TSRMLS_CC);
     562              56 :                     add_next_index_zval(jp->the_zstack[jp->top], mval);
     563              56 :                     buf.len = 0;
     564              56 :                     JSON_RESET_TYPE();
     565                 :                 }
     566                 : 
     567             152 :                 if (!pop(jp, MODE_ARRAY)) {
     568               2 :                     FREE_BUFFERS();
     569               2 :                     return false;
     570                 :                 }
     571             150 :                 jp->state = OK;
     572                 :             }
     573             150 :                         break;
     574                 : /* { */
     575                 :             case -6:
     576              89 :                 if (!push(jp, MODE_KEY)) {
     577               0 :                     FREE_BUFFERS();
     578               0 :                     return false;
     579                 :                 }
     580                 : 
     581              89 :                 jp->state = OB;
     582              89 :                 if (jp->top > 0) {
     583                 :                     zval *obj;
     584                 : 
     585              89 :                     if (jp->top == 1) {
     586              40 :                         obj = z;
     587                 :                         } else {
     588              49 :                         ALLOC_INIT_ZVAL(obj);
     589                 :                     }
     590                 : 
     591              89 :                     if (!assoc) {
     592              51 :                         object_init(obj);
     593                 :                     } else {
     594              38 :                         array_init(obj);
     595                 :                     }
     596                 : 
     597              89 :                     jp->the_zstack[jp->top] = obj;
     598                 : 
     599              89 :                     if (jp->top > 1) {
     600              49 :                         attach_zval(jp, jp->top - 1, jp->top, &key, assoc TSRMLS_CC);
     601                 :                     }
     602                 : 
     603              89 :                     JSON_RESET_TYPE();
     604                 :                 }
     605                 : 
     606              89 :                 break;
     607                 : /* [ */
     608                 :             case -5:
     609            1199 :                 if (!push(jp, MODE_ARRAY)) {
     610               3 :                     FREE_BUFFERS();
     611               3 :                     return false;
     612                 :                 }
     613            1196 :                 jp->state = AR;
     614                 : 
     615            1196 :                 if (jp->top > 0) {
     616                 :                     zval *arr;
     617                 : 
     618            1196 :                     if (jp->top == 1) {
     619              52 :                         arr = z;
     620                 :                     } else {
     621            1144 :                         ALLOC_INIT_ZVAL(arr);
     622                 :                     }
     623                 : 
     624            1196 :                     array_init(arr);
     625            1196 :                     jp->the_zstack[jp->top] = arr;
     626                 : 
     627            1196 :                     if (jp->top > 1) {
     628            1144 :                         attach_zval(jp, jp->top - 1, jp->top, &key, assoc TSRMLS_CC);
     629                 :                     }
     630                 : 
     631            1196 :                     JSON_RESET_TYPE();
     632                 :                 }
     633                 : 
     634            1196 :                 break;
     635                 : 
     636                 : /* " */
     637                 :             case -4:
     638             606 :                 switch (jp->stack[jp->top]) {
     639                 :                 case MODE_KEY:
     640             365 :                     jp->state = CO;
     641             365 :                     smart_str_0(&buf);
     642             365 :                     SWAP_BUFFERS(buf, key);
     643             365 :                     JSON_RESET_TYPE();
     644             365 :                     break;
     645                 :                 case MODE_ARRAY:
     646                 :                 case MODE_OBJECT:
     647             228 :                     jp->state = OK;
     648             228 :                     break;
     649                 :                                 case MODE_DONE:
     650              13 :                                         if (type == IS_STRING) {
     651              13 :                                                 smart_str_0(&buf);
     652              13 :                                                 ZVAL_UTF8_STRINGL(z, buf.c, buf.len, ZSTR_DUPLICATE);
     653              13 :                                                 jp->state = OK;
     654              13 :                                                 break;
     655                 :                                         }
     656                 :                                         /* fall through if not IS_STRING */
     657                 :                 default:
     658               0 :                     FREE_BUFFERS();
     659               0 :                     return false;
     660                 :                 }
     661             606 :                 break;
     662                 : /* , */
     663                 :             case -3:
     664                 :             {
     665                 :                 zval *mval;
     666                 : 
     667             539 :                 if (type != -1 &&
     668                 :                     (jp->stack[jp->top] == MODE_OBJECT ||
     669                 :                      jp->stack[jp->top] == MODE_ARRAY))
     670                 :                 {
     671             465 :                     smart_str_0(&buf);
     672             465 :                     json_create_zval(&mval, &buf, type TSRMLS_CC);
     673                 :                 }
     674                 : 
     675             539 :                 switch (jp->stack[jp->top]) {
     676                 :                     case MODE_OBJECT:
     677             294 :                         if (pop(jp, MODE_OBJECT) && push(jp, MODE_KEY)) {
     678             294 :                             if (type != -1) {
     679             254 :                                 if (!assoc) {
     680             126 :                                     add_utf8_property_zval_ex(jp->the_zstack[jp->top], (key.len ? key.c : "_empty_"), (key.len ? (key.len + 1) : sizeof("_empty_")), mval TSRMLS_CC);
     681             126 :                                     Z_DELREF_P(mval);
     682                 :                                 } else {
     683             128 :                                     add_utf8_assoc_zval_ex(jp->the_zstack[jp->top], (key.len ? key.c : ""), (key.len ? (key.len + 1) : sizeof("")), mval);
     684                 :                                 }
     685             254 :                                 key.len = 0;
     686                 :                             }
     687             294 :                             jp->state = KE;
     688                 :                         }
     689             294 :                         break;
     690                 :                     case MODE_ARRAY:
     691             243 :                         if (type != -1) {
     692             211 :                             add_next_index_zval(jp->the_zstack[jp->top], mval);
     693                 :                         }
     694             243 :                         jp->state = VA;
     695             243 :                         break;
     696                 :                     default:
     697               2 :                         FREE_BUFFERS();
     698               2 :                         return false;
     699                 :                 }
     700             537 :                 buf.len = 0;
     701             537 :                 JSON_RESET_TYPE();
     702                 :             }
     703             537 :             break;
     704                 : /* : */
     705                 :             case -2:
     706             361 :                 if (pop(jp, MODE_KEY) && push(jp, MODE_OBJECT)) {
     707             361 :                     jp->state = VA;
     708             361 :                     break;
     709                 :                 }
     710                 : /*
     711                 :     syntax error
     712                 : */
     713                 :             default:
     714                 :                 {
     715              70 :                                         jp->error_code = PHP_JSON_ERROR_SYNTAX;
     716              70 :                     FREE_BUFFERS();
     717              70 :                     return false;
     718                 :                 }
     719                 :             }
     720                 :         }
     721                 :     }
     722                 : 
     723              56 :     FREE_BUFFERS();
     724              56 :         if (jp->state == OK && pop(jp, MODE_DONE)) {
     725              51 :                 return true;
     726                 :         }
     727                 : 
     728               5 :         jp->error_code = PHP_JSON_ERROR_SYNTAX;
     729               5 :         return false;
     730                 : }
     731                 : 
     732                 : /*
     733                 :  * Local variables:
     734                 :  * tab-width: 4
     735                 :  * c-basic-offset: 4
     736                 :  * End:
     737                 :  * vim600: noet sw=4 ts=4
     738                 :  * vim<600: noet sw=4 ts=4
     739                 :  */

Generated by: LTP GCOV extension version 1.5

Generated at Mon, 23 Nov 2009 17:39:31 +0000 (34 hours ago)

Copyright © 2005-2009 The PHP Group
All rights reserved.