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.c
Test: PHP Code Coverage
Date: 2009-11-23 Instrumented lines: 268
Code covered: 93.7 % Executed lines: 251
Legend: not executed executed

       1                 : /*
       2                 :   +----------------------------------------------------------------------+
       3                 :   | PHP Version 6                                                        |
       4                 :   +----------------------------------------------------------------------+
       5                 :   | Copyright (c) 1997-2009 The PHP Group                                |
       6                 :   +----------------------------------------------------------------------+
       7                 :   | This source file is subject to version 3.01 of the PHP license,      |
       8                 :   | that is bundled with this package in the file LICENSE, and is        |
       9                 :   | available through the world-wide-web at the following url:           |
      10                 :   | http://www.php.net/license/3_01.txt                                  |
      11                 :   | If you did not receive a copy of the PHP license and are unable to   |
      12                 :   | obtain it through the world-wide-web, please send a note to          |
      13                 :   | license@php.net so we can mail you a copy immediately.               |
      14                 :   +----------------------------------------------------------------------+
      15                 :   | Author: Omar Kilani <omar@php.net>                                   |
      16                 :   +----------------------------------------------------------------------+
      17                 : */
      18                 : 
      19                 : /* $Id: json.c 284625 2009-07-22 21:32:58Z rasmus $ */
      20                 : 
      21                 : /*
      22                 :  * UTODO
      23                 :  * - take a look at json_decode, some weird IS_STRING checks there
      24                 :  * - expose encode/decode API once that's done
      25                 :  */
      26                 : 
      27                 : #ifdef HAVE_CONFIG_H
      28                 : #include "config.h"
      29                 : #endif
      30                 : 
      31                 : #include "php.h"
      32                 : #include "php_ini.h"
      33                 : #include "ext/standard/info.h"
      34                 : #include "ext/standard/php_smart_str.h"
      35                 : #include "utf8_to_utf16.h"
      36                 : #include "JSON_parser.h"
      37                 : #include "php_json.h"
      38                 : 
      39                 : static PHP_MINFO_FUNCTION(json);
      40                 : static PHP_FUNCTION(json_encode);
      41                 : static PHP_FUNCTION(json_decode);
      42                 : static PHP_FUNCTION(json_last_error);
      43                 : 
      44                 : static const char digits[] = "0123456789abcdef";
      45                 : 
      46                 : #define PHP_JSON_HEX_TAG        (1<<0)
      47                 : #define PHP_JSON_HEX_AMP        (1<<1)
      48                 : #define PHP_JSON_HEX_APOS       (1<<2)
      49                 : #define PHP_JSON_HEX_QUOT       (1<<3)
      50                 : #define PHP_JSON_FORCE_OBJECT   (1<<4)
      51                 : 
      52                 : #define PHP_JSON_OUTPUT_ARRAY 0
      53                 : #define PHP_JSON_OUTPUT_OBJECT 1
      54                 : 
      55                 : ZEND_DECLARE_MODULE_GLOBALS(json)
      56                 : 
      57                 : /* {{{ arginfo */
      58                 : ZEND_BEGIN_ARG_INFO_EX(arginfo_json_encode, 0, 0, 1)
      59                 :         ZEND_ARG_INFO(0, value)
      60                 :         ZEND_ARG_INFO(0, options)
      61                 : ZEND_END_ARG_INFO()
      62                 : 
      63                 : ZEND_BEGIN_ARG_INFO_EX(arginfo_json_decode, 0, 0, 1)
      64                 :         ZEND_ARG_INFO(0, json)
      65                 :         ZEND_ARG_INFO(0, assoc)
      66                 :         ZEND_ARG_INFO(0, depth)
      67                 : ZEND_END_ARG_INFO()
      68                 : 
      69                 : ZEND_BEGIN_ARG_INFO(arginfo_json_last_error, 0)
      70                 : ZEND_END_ARG_INFO()
      71                 : /* }}} */
      72                 : 
      73                 : /* {{{ json_functions[] */
      74                 : static const function_entry json_functions[] = {
      75                 :         PHP_FE(json_encode, arginfo_json_encode)
      76                 :         PHP_FE(json_decode, arginfo_json_decode)
      77                 :         PHP_FE(json_last_error, arginfo_json_last_error)
      78                 :         {NULL, NULL, NULL}
      79                 : };
      80                 : /* }}} */
      81                 : 
      82                 : /* {{{ MINIT */
      83                 : static PHP_MINIT_FUNCTION(json)
      84           17007 : {
      85           17007 :         REGISTER_LONG_CONSTANT("JSON_HEX_TAG",  PHP_JSON_HEX_TAG,  CONST_CS | CONST_PERSISTENT);
      86           17007 :         REGISTER_LONG_CONSTANT("JSON_HEX_AMP",  PHP_JSON_HEX_AMP,  CONST_CS | CONST_PERSISTENT);
      87           17007 :         REGISTER_LONG_CONSTANT("JSON_HEX_APOS", PHP_JSON_HEX_APOS, CONST_CS | CONST_PERSISTENT);
      88           17007 :         REGISTER_LONG_CONSTANT("JSON_HEX_QUOT", PHP_JSON_HEX_QUOT, CONST_CS | CONST_PERSISTENT);
      89           17007 :         REGISTER_LONG_CONSTANT("JSON_FORCE_OBJECT", PHP_JSON_FORCE_OBJECT, CONST_CS | CONST_PERSISTENT);
      90                 : 
      91           17007 :         REGISTER_LONG_CONSTANT("JSON_ERROR_NONE", PHP_JSON_ERROR_NONE, CONST_CS | CONST_PERSISTENT);
      92           17007 :         REGISTER_LONG_CONSTANT("JSON_ERROR_DEPTH", PHP_JSON_ERROR_DEPTH, CONST_CS | CONST_PERSISTENT);
      93           17007 :         REGISTER_LONG_CONSTANT("JSON_ERROR_STATE_MISMATCH", PHP_JSON_ERROR_STATE_MISMATCH, CONST_CS | CONST_PERSISTENT);
      94           17007 :         REGISTER_LONG_CONSTANT("JSON_ERROR_CTRL_CHAR", PHP_JSON_ERROR_CTRL_CHAR, CONST_CS | CONST_PERSISTENT);
      95           17007 :         REGISTER_LONG_CONSTANT("JSON_ERROR_SYNTAX", PHP_JSON_ERROR_SYNTAX, CONST_CS | CONST_PERSISTENT);
      96           17007 :         REGISTER_LONG_CONSTANT("JSON_ERROR_UTF8", PHP_JSON_ERROR_UTF8, CONST_CS | CONST_PERSISTENT);
      97                 : 
      98           17007 :         return SUCCESS;
      99                 : }
     100                 : /* }}} */
     101                 : 
     102                 : /* {{{ PHP_GINIT_FUNCTION
     103                 : */
     104                 : static PHP_GINIT_FUNCTION(json)
     105           17007 : {
     106           17007 :         json_globals->error_code = 0;
     107           17007 : }
     108                 : /* }}} */
     109                 : 
     110                 : 
     111                 : /* {{{ json_module_entry
     112                 :  */
     113                 : zend_module_entry json_module_entry = {
     114                 :         STANDARD_MODULE_HEADER,
     115                 :         "json",
     116                 :         json_functions,
     117                 :         PHP_MINIT(json),
     118                 :         NULL,
     119                 :         NULL,
     120                 :         NULL,
     121                 :         PHP_MINFO(json),
     122                 :         PHP_JSON_VERSION,
     123                 :         PHP_MODULE_GLOBALS(json),
     124                 :         PHP_GINIT(json),
     125                 :         NULL,
     126                 :         NULL,
     127                 :         STANDARD_MODULE_PROPERTIES_EX
     128                 : };
     129                 : /* }}} */
     130                 : 
     131                 : #ifdef COMPILE_DL_JSON
     132                 : ZEND_GET_MODULE(json)
     133                 : #endif
     134                 : 
     135                 : /* {{{ PHP_MINFO_FUNCTION
     136                 :  */
     137                 : static PHP_MINFO_FUNCTION(json)
     138              43 : {
     139              43 :         php_info_print_table_start();
     140              43 :         php_info_print_table_row(2, "json support", "enabled");
     141              43 :         php_info_print_table_row(2, "json version", PHP_JSON_VERSION);
     142              43 :         php_info_print_table_end();
     143              43 : }
     144                 : /* }}} */
     145                 : 
     146                 : static void json_encode_r(smart_str *buf, zval *val, int options TSRMLS_DC);
     147                 : static void json_escape_string(smart_str *buf, zstr s, int len, zend_uchar type, int options TSRMLS_DC);
     148                 : 
     149                 : static int json_determine_array_type(zval **val TSRMLS_DC) /* {{{ */
     150             102 : {
     151                 :         int i;
     152             102 :         HashTable *myht = HASH_OF(*val);
     153                 : 
     154             102 :         i = myht ? zend_hash_num_elements(myht) : 0;
     155             102 :         if (i > 0) {
     156                 :                 zstr key;
     157                 :                 ulong index, idx;
     158                 :                 uint key_len;
     159                 :                 HashPosition pos;
     160                 : 
     161              87 :                 zend_hash_internal_pointer_reset_ex(myht, &pos);
     162              87 :                 idx = 0;
     163             214 :                 for (;; zend_hash_move_forward_ex(myht, &pos)) {
     164             301 :                         i = zend_hash_get_current_key_ex(myht, &key, &key_len, &index, 0, &pos);
     165             301 :                         if (i == HASH_KEY_NON_EXISTANT)
     166              74 :                                 break;
     167                 : 
     168             227 :                         if (i == HASH_KEY_IS_STRING || i == HASH_KEY_IS_UNICODE) {
     169              10 :                                 return 1;
     170                 :                         } else {
     171             217 :                                 if (index != idx) {
     172               3 :                                         return 1;
     173                 :                                 }
     174                 :                         }
     175             214 :                         idx++;
     176             214 :                 }
     177                 :         }
     178                 : 
     179              89 :         return PHP_JSON_OUTPUT_ARRAY;
     180                 : }
     181                 : /* }}} */
     182                 : 
     183                 : static void json_encode_array(smart_str *buf, zval **val, int options TSRMLS_DC) /* {{{ */
     184             125 : {
     185                 :         int i, r;
     186                 :         HashTable *myht;
     187                 : 
     188             125 :         if (Z_TYPE_PP(val) == IS_ARRAY) {
     189             106 :                 myht = HASH_OF(*val);
     190             106 :                 r = (options & PHP_JSON_FORCE_OBJECT) ? PHP_JSON_OUTPUT_OBJECT : json_determine_array_type(val TSRMLS_CC);
     191                 :         } else {
     192              19 :                 myht = Z_OBJPROP_PP(val);
     193              19 :                 r = PHP_JSON_OUTPUT_OBJECT;
     194                 :         }
     195                 : 
     196             125 :         if (myht && myht->nApplyCount > 1) {
     197               2 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "recursion detected");
     198               2 :                 smart_str_appendl(buf, "null", 4);
     199               2 :                 return;
     200                 :         }
     201                 : 
     202             123 :         if (r == PHP_JSON_OUTPUT_ARRAY) {
     203              88 :                 smart_str_appendc(buf, '[');
     204                 :         } else {
     205              35 :                 smart_str_appendc(buf, '{');
     206                 :         }
     207                 : 
     208             123 :         i = myht ? zend_hash_num_elements(myht) : 0;
     209                 : 
     210             123 :         if (i > 0)
     211                 :         {
     212                 :                 zstr key;
     213                 :                 zval **data;
     214                 :                 ulong index;
     215                 :                 uint key_len;
     216                 :                 HashPosition pos;
     217                 :                 HashTable *tmp_ht;
     218             103 :                 int need_comma = 0;
     219                 : 
     220             103 :                 zend_hash_internal_pointer_reset_ex(myht, &pos);
     221             396 :                 for (;; zend_hash_move_forward_ex(myht, &pos)) {
     222             499 :                         i = zend_hash_get_current_key_ex(myht, &key, &key_len, &index, 0, &pos);
     223             499 :                         if (i == HASH_KEY_NON_EXISTANT)
     224             103 :                                 break;
     225                 : 
     226             396 :                         if (zend_hash_get_current_data_ex(myht, (void **) &data, &pos) == SUCCESS) {
     227             396 :                                 tmp_ht = HASH_OF(*data);
     228             396 :                                 if (tmp_ht) {
     229              92 :                                         tmp_ht->nApplyCount++;
     230                 :                                 }
     231                 : 
     232             396 :                                 if (r == PHP_JSON_OUTPUT_ARRAY) {
     233             212 :                                         if (need_comma) {
     234             139 :                                                 smart_str_appendc(buf, ',');
     235                 :                                         } else {
     236              73 :                                                 need_comma = 1;
     237                 :                                         }
     238                 :  
     239             212 :                                         json_encode_r(buf, *data, options TSRMLS_CC);
     240             184 :                                 } else if (r == PHP_JSON_OUTPUT_OBJECT) {
     241             353 :                                         if (i == HASH_KEY_IS_STRING || i == HASH_KEY_IS_UNICODE) {
     242             170 :                                                 if (key.s[0] == '\0' && Z_TYPE_PP(val) == IS_OBJECT) {
     243                 :                                                         /* Skip protected and private members. */
     244               1 :                                                         if (tmp_ht) {
     245               1 :                                                                 tmp_ht->nApplyCount--;
     246                 :                                                         }
     247               1 :                                                         continue;
     248                 :                                                 }
     249                 : 
     250             169 :                                                 if (need_comma) {
     251             146 :                                                         smart_str_appendc(buf, ',');
     252                 :                                                 } else {
     253              23 :                                                         need_comma = 1;
     254                 :                                                 }
     255                 : 
     256             169 :                                                 json_escape_string(buf, key, key_len - 1, (i == HASH_KEY_IS_UNICODE) ? IS_UNICODE : IS_STRING, options TSRMLS_CC);
     257             169 :                                                 smart_str_appendc(buf, ':');
     258                 : 
     259             169 :                                                 json_encode_r(buf, *data, options TSRMLS_CC);
     260                 :                                         } else {
     261              14 :                                                 if (need_comma) {
     262               8 :                                                         smart_str_appendc(buf, ',');
     263                 :                                                 } else {
     264               6 :                                                         need_comma = 1;
     265                 :                                                 }
     266                 : 
     267              14 :                                                 smart_str_appendc(buf, '"');
     268              14 :                                                 smart_str_append_long(buf, (long) index);
     269              14 :                                                 smart_str_appendc(buf, '"');
     270              14 :                                                 smart_str_appendc(buf, ':');
     271                 : 
     272              14 :                                                 json_encode_r(buf, *data, options TSRMLS_CC);
     273                 :                                         }
     274                 :                                 }
     275                 : 
     276             395 :                                 if (tmp_ht) {
     277              91 :                                         tmp_ht->nApplyCount--;
     278                 :                                 }
     279                 :                         }
     280             396 :                 }
     281                 :         }
     282                 : 
     283             123 :         if (r == PHP_JSON_OUTPUT_ARRAY) {
     284              88 :                 smart_str_appendc(buf, ']');
     285                 :         } else {
     286              35 :                 smart_str_appendc(buf, '}');
     287                 :         }
     288                 : }
     289                 : /* }}} */
     290                 : 
     291                 : #define REVERSE16(us) (((us & 0xf) << 12) | (((us >> 4) & 0xf) << 8) | (((us >> 8) & 0xf) << 4) | ((us >> 12) & 0xf))
     292                 : 
     293                 : static void json_escape_string(smart_str *buf, zstr s, int len, zend_uchar type, int options TSRMLS_DC) /* {{{ */
     294             324 : {
     295             324 :         int pos = 0;
     296                 :         unsigned short us;
     297                 :         unsigned short *utf16;
     298                 : 
     299             324 :         if (len == 0) {
     300              11 :                 smart_str_appendl(buf, "\"\"", 2);
     301              11 :                 return;
     302                 :         }
     303                 : 
     304             313 :         if (type == IS_UNICODE) {
     305             306 :                 utf16 = (unsigned short *) s.u;
     306                 :         } else {
     307               7 :                 utf16 = (unsigned short *) safe_emalloc(len, sizeof(unsigned short), 0);
     308                 : 
     309               7 :                 len = utf8_to_utf16(utf16, s.s, len);
     310               7 :                 if (len <= 0) {
     311               4 :                         if (utf16) {
     312               4 :                                 efree(utf16);
     313                 :                         }
     314               4 :                         if (len < 0) {
     315               4 :                                 JSON_G(error_code) = PHP_JSON_ERROR_UTF8;
     316               4 :                                 if (!PG(display_errors)) {
     317               0 :                                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid UTF-8 sequence in argument");
     318                 :                                 }
     319               4 :                                 smart_str_appendl(buf, "null", 4);
     320                 :                         } else {
     321               0 :                                 smart_str_appendl(buf, "\"\"", 2);
     322                 :                         }
     323               4 :                         return;
     324                 :                 }
     325                 :         }
     326                 : 
     327             309 :         smart_str_appendc(buf, '"');
     328                 : 
     329            3466 :         while (pos < len)
     330                 :         {
     331            2848 :                 us = utf16[pos++];
     332                 : 
     333            2848 :                 switch (us)
     334                 :                 {
     335                 :                         case '"':
     336              44 :                                 if (options & PHP_JSON_HEX_QUOT) {
     337               4 :                                         smart_str_appendl(buf, "\\u0022", 6);
     338                 :                                 } else {
     339              40 :                                         smart_str_appendl(buf, "\\\"", 2);
     340                 :                                 }
     341              44 :                                 break;
     342                 : 
     343                 :                         case '\\':
     344               8 :                                 smart_str_appendl(buf, "\\\\", 2);
     345               8 :                                 break;
     346                 : 
     347                 :                         case '/':
     348              48 :                                 smart_str_appendl(buf, "\\/", 2);
     349              48 :                                 break;
     350                 : 
     351                 :                         case '\b':
     352               8 :                                 smart_str_appendl(buf, "\\b", 2);
     353               8 :                                 break;
     354                 : 
     355                 :                         case '\f':
     356               8 :                                 smart_str_appendl(buf, "\\f", 2);
     357               8 :                                 break;
     358                 : 
     359                 :                         case '\n':
     360               9 :                                 smart_str_appendl(buf, "\\n", 2);
     361               9 :                                 break;
     362                 : 
     363                 :                         case '\r':
     364               8 :                                 smart_str_appendl(buf, "\\r", 2);
     365               8 :                                 break;
     366                 : 
     367                 :                         case '\t':
     368              10 :                                 smart_str_appendl(buf, "\\t", 2);
     369              10 :                                 break;
     370                 : 
     371                 :                         case '<':
     372              18 :                                 if (options & PHP_JSON_HEX_TAG) {
     373               2 :                                         smart_str_appendl(buf, "\\u003C", 6);
     374                 :                                 } else {
     375              16 :                                         smart_str_appendc(buf, '<');
     376                 :                                 }
     377              18 :                                 break;
     378                 : 
     379                 :                         case '>':
     380              18 :                                 if (options & PHP_JSON_HEX_TAG) {
     381               2 :                                         smart_str_appendl(buf, "\\u003E", 6);
     382                 :                                 } else {
     383              16 :                                         smart_str_appendc(buf, '>');
     384                 :                                 }
     385              18 :                                 break;
     386                 : 
     387                 :                         case '&':
     388              32 :                                 if (options & PHP_JSON_HEX_AMP) {
     389               4 :                                         smart_str_appendl(buf, "\\u0026", 6);
     390                 :                                 } else {
     391              28 :                                         smart_str_appendc(buf, '&');
     392                 :                                 }
     393              32 :                                 break;
     394                 : 
     395                 :                         case '\'':
     396              20 :                                 if (options & PHP_JSON_HEX_APOS) {
     397               4 :                                         smart_str_appendl(buf, "\\u0027", 6);
     398                 :                                 } else {
     399              16 :                                         smart_str_appendc(buf, '\'');
     400                 :                                 }
     401              20 :                                 break;
     402                 : 
     403                 :                         default:
     404            5122 :                                 if (us >= ' ' && (us & 127) == us) {
     405            2505 :                                         smart_str_appendc(buf, (unsigned char) us);
     406                 :                                 } else {
     407             112 :                                         smart_str_appendl(buf, "\\u", 2);
     408             112 :                                         us = REVERSE16(us);
     409                 : 
     410             112 :                                         smart_str_appendc(buf, digits[us & ((1 << 4) - 1)]);
     411             112 :                                         us >>= 4;
     412             112 :                                         smart_str_appendc(buf, digits[us & ((1 << 4) - 1)]);
     413             112 :                                         us >>= 4;
     414             112 :                                         smart_str_appendc(buf, digits[us & ((1 << 4) - 1)]);
     415             112 :                                         us >>= 4;
     416             112 :                                         smart_str_appendc(buf, digits[us & ((1 << 4) - 1)]);
     417                 :                                 }
     418                 :                                 break;
     419                 :                 }
     420                 :         }
     421                 : 
     422             309 :         smart_str_appendc(buf, '"');
     423                 : 
     424             309 :         if (type == IS_STRING) {
     425               3 :                 efree(utf16);
     426                 :         }
     427                 : }
     428                 : /* }}} */
     429                 : 
     430                 : static void json_encode_r(smart_str *buf, zval *val, int options TSRMLS_DC) /* {{{ */
     431             466 : {
     432             466 :         switch (Z_TYPE_P(val))
     433                 :         {
     434                 :                 case IS_NULL:
     435              14 :                         smart_str_appendl(buf, "null", 4);
     436              14 :                         break;
     437                 : 
     438                 :                 case IS_BOOL:
     439              22 :                         if (Z_BVAL_P(val)) {
     440              12 :                                 smart_str_appendl(buf, "true", 4);
     441                 :                         } else {
     442              10 :                                 smart_str_appendl(buf, "false", 5);
     443                 :                         }
     444              22 :                         break;
     445                 : 
     446                 :                 case IS_LONG:
     447             110 :                         smart_str_append_long(buf, Z_LVAL_P(val));
     448             110 :                         break;
     449                 : 
     450                 :                 case IS_DOUBLE:
     451                 :                         {
     452              39 :                                 char *d = NULL;
     453                 :                                 int len;
     454              39 :                                 double dbl = Z_DVAL_P(val);
     455                 : 
     456              74 :                                 if (!zend_isinf(dbl) && !zend_isnan(dbl)) {
     457              35 :                                         len = spprintf(&d, 0, "%.*k", (int) EG(precision), dbl);
     458              35 :                                         smart_str_appendl(buf, d, len);
     459              35 :                                         efree(d);
     460                 :                                 } else {
     461               4 :                                         zend_error(E_WARNING, "[json] (json_encode_r) double %.9g does not conform to the JSON spec, encoded as 0", dbl);
     462               4 :                                         smart_str_appendc(buf, '0');
     463                 :                                 }
     464                 :                         }
     465              39 :                         break;
     466                 : 
     467                 :                 case IS_STRING:
     468                 :                 case IS_UNICODE:
     469             155 :                         json_escape_string(buf, Z_UNIVAL_P(val), Z_UNILEN_P(val), Z_TYPE_P(val), options TSRMLS_CC);
     470             155 :                         break;
     471                 : 
     472                 :                 case IS_ARRAY:
     473                 :                 case IS_OBJECT:
     474             125 :                         json_encode_array(buf, &val, options TSRMLS_CC);
     475             125 :                         break;
     476                 : 
     477                 :                 default:
     478               1 :                         zend_error(E_WARNING, "[json] (json_encode_r) type is unsupported, encoded as null");
     479               1 :                         smart_str_appendl(buf, "null", 4);
     480                 :                         break;
     481                 :         }
     482                 : 
     483                 :         return;
     484                 : }
     485                 : /* }}} */
     486                 : 
     487                 : /* {{{ proto string json_encode(mixed data [, long options]) U
     488                 :    Returns the JSON representation of a value */
     489                 : static PHP_FUNCTION(json_encode)
     490              73 : {
     491                 :         zval *parameter;
     492              73 :         smart_str buf = {0};
     493              73 :         long options = 0;
     494                 : 
     495              73 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|l", &parameter, &options) == FAILURE) {
     496               2 :                 return;
     497                 :         }
     498                 : 
     499              71 :         json_encode_r(&buf, parameter, options TSRMLS_CC);
     500                 : 
     501                 :         /*
     502                 :          * Return as binary string, since the result is 99% likely to be just
     503                 :          * echo'ed out and we want to avoid overhead of double conversion.
     504                 :          */
     505              71 :         ZVAL_STRINGL(return_value, buf.c, buf.len, 1);
     506                 : 
     507              71 :         smart_str_free(&buf);
     508                 : }
     509                 : /* }}} */
     510                 : 
     511                 : /* {{{ proto mixed json_decode(string json [, bool assoc [, long depth]]) U
     512                 :    Decodes the JSON representation into a PHP value */
     513                 : static PHP_FUNCTION(json_decode)
     514             142 : {
     515                 :         zstr str;
     516                 :         int str_len, utf16_len;
     517                 :         zend_uchar str_type;
     518             142 :         zend_bool assoc = 0; /* return JS objects as PHP objects by default */
     519             142 :         long depth = JSON_PARSER_DEFAULT_DEPTH;
     520                 :         zval *z;
     521                 :         unsigned short *utf16;
     522                 :         JSON_parser jp;
     523                 : 
     524             142 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "t|bl", &str, &str_len, &str_type, &assoc, &depth) == FAILURE) {
     525               3 :                 return;
     526                 :         }
     527                 : 
     528             139 :         if (!str_len) {
     529               4 :                 RETURN_NULL();
     530                 :         }
     531                 : 
     532             135 :         if (str_type == IS_UNICODE) {
     533             123 :                 utf16 = str.u;
     534             123 :                 utf16_len = str_len;
     535                 :         } else {
     536              12 :                 utf16 = (unsigned short *) safe_emalloc((str_len+1), sizeof(unsigned short), 0);
     537                 : 
     538              12 :                 utf16_len = utf8_to_utf16(utf16, str.s, str_len);
     539              12 :                 if (utf16_len <= 0) {
     540               0 :                         if (utf16) {
     541               0 :                                 efree(utf16);
     542                 :                         }
     543               0 :                         JSON_G(error_code) = PHP_JSON_ERROR_UTF8;
     544               0 :                         RETURN_NULL();
     545                 :                 }
     546                 :         }
     547                 : 
     548             135 :         if (depth <= 0) {
     549               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Depth must greater than zero");
     550               0 :                 efree(utf16);
     551               0 :                 RETURN_NULL();
     552                 :         }
     553                 : 
     554             135 :         ALLOC_INIT_ZVAL(z);
     555             135 :         jp = new_JSON_parser(depth);
     556             135 :         if (parse_JSON(jp, z, utf16, utf16_len, assoc TSRMLS_CC)) {
     557              51 :                 *return_value = *z;
     558                 :         }
     559              84 :         else if (str_type == IS_STRING)
     560                 :         {
     561                 :                 double d;
     562                 :                 int type;
     563                 :                 long p;
     564                 : 
     565               1 :                 zval_dtor(z);
     566               1 :                 RETVAL_NULL();
     567                 : 
     568               1 :                 if (str_len == 4) {
     569               0 :                         if (!strcasecmp(str.s, "null")) {
     570                 :                                 /* We need to explicitly clear the error because its an actual NULL and not an error */
     571               0 :                                 jp->error_code = PHP_JSON_ERROR_NONE;
     572               0 :                                 RETVAL_NULL();
     573               0 :                         } else if (!strcasecmp(str.s, "true")) {
     574               0 :                                 RETVAL_BOOL(1);
     575                 :                         }
     576               1 :                 } else if (str_len == 5 && !strcasecmp(str.s, "false")) {
     577               0 :                         RETVAL_BOOL(0);
     578                 :                 }
     579                 : 
     580               1 :                 if ((type = is_numeric_string(str.s, str_len, &p, &d, 0)) != 0) {
     581               1 :                         if (type == IS_LONG) {
     582               0 :                                 RETVAL_LONG(p);
     583               1 :                         } else if (type == IS_DOUBLE) {
     584               1 :                                 RETVAL_DOUBLE(d);
     585                 :                         }
     586                 :                 }
     587                 : 
     588               1 :                 if (Z_TYPE_P(return_value) != IS_NULL) {
     589               1 :                         jp->error_code = PHP_JSON_ERROR_NONE;
     590                 :                 }
     591                 :         }
     592                 :         else
     593                 :         {
     594                 :                 double d;
     595                 :                 int type;
     596                 :                 long p;
     597                 : 
     598              83 :                 zval_dtor(z);
     599              83 :                 RETVAL_NULL();
     600                 : 
     601              83 :                 if (str_len == 4) {
     602              10 :                         if (ZEND_U_CASE_EQUAL(IS_UNICODE, str, str_len, "null", sizeof("null")-1)) {
     603                 :                                 /* We need to explicitly clear the error because its an actual NULL and not an error */
     604               2 :                                 jp->error_code = PHP_JSON_ERROR_NONE;
     605               2 :                                 RETVAL_NULL();
     606               8 :                         } else if (ZEND_U_CASE_EQUAL(IS_UNICODE, str, str_len, "true", sizeof("true")-1)) {
     607               2 :                                 RETVAL_BOOL(1);
     608                 :                         }
     609              73 :                 } else if (str_len == 5 && ZEND_U_CASE_EQUAL(IS_UNICODE, str, str_len, "false", sizeof("false")-1)) {
     610               2 :                         RETVAL_BOOL(0);
     611                 :                 }
     612                 : 
     613              83 :                 if ((type = is_numeric_unicode(str.u, str_len, &p, &d, 0)) != 0) {
     614              16 :                         if (type == IS_LONG) {
     615              14 :                                 RETVAL_LONG(p);
     616               2 :                         } else if (type == IS_DOUBLE) {
     617               2 :                                 RETVAL_DOUBLE(d);
     618                 :                         }
     619                 :                 }
     620                 :                 
     621              83 :                 if (Z_TYPE_P(return_value) != IS_NULL) {
     622              20 :                         jp->error_code = PHP_JSON_ERROR_NONE;
     623                 :                 }
     624                 :         }
     625                 : 
     626             135 :         FREE_ZVAL(z);
     627             135 :         if (str_type == IS_STRING) {
     628              12 :                 efree(utf16);
     629                 :         }
     630             135 :         JSON_G(error_code) = jp->error_code;
     631             135 :         free_JSON_parser(jp);
     632                 : }
     633                 : /* }}} */
     634                 : 
     635                 : /* {{{ proto int json_last_error() U
     636                 :    Returns the error code of the last json_decode(). */
     637                 : static PHP_FUNCTION(json_last_error)
     638               5 : {
     639               5 :         if (zend_parse_parameters_none() == FAILURE) {
     640               0 :                 return;
     641                 :         }
     642                 : 
     643               5 :         RETURN_LONG(JSON_G(error_code));
     644                 : }
     645                 : /* }}} */
     646                 : 
     647                 : /*
     648                 :  * Local variables:
     649                 :  * tab-width: 4
     650                 :  * c-basic-offset: 4
     651                 :  * End:
     652                 :  * vim600: noet sw=4 ts=4
     653                 :  * vim<600: noet sw=4 ts=4
     654                 :  */

Generated by: LTP GCOV extension version 1.5

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

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