├── CREDITS ├── json-c ├── ChangeLog ├── AUTHORS ├── json_c_version.c ├── random_seed.h ├── json_inttypes.h ├── json_c_version.h ├── bits.h ├── json.h ├── json_object_private.h ├── json_util.h ├── json_config.h ├── arraylist.h ├── config.h ├── debug.h ├── debug.c ├── COPYING ├── printbuf.h ├── arraylist.c ├── printbuf.c ├── json_object_iterator.c ├── random_seed.c ├── linkhash.h ├── json_tokener.h ├── json_util.c └── json_object_iterator.h ├── .gitmodules ├── TODO ├── tests ├── issue12.phpt ├── bug45791.phpt ├── json_encode_unescaped_slashes.phpt ├── bug55543.phpt ├── 012-null-byte.phpt ├── bug41034.phpt ├── bug41567.phpt ├── 005.phpt ├── bug66021.phpt ├── issue23.phpt ├── 008.phpt ├── issue28.phpt ├── bug46215.phpt ├── bug54484.phpt ├── bug40503.phpt ├── bug43941.phpt ├── bug41067.phpt ├── bug41504.phpt ├── bug42090.phpt ├── unsupported_type_error.phpt ├── json_encode_numeric.phpt ├── 003.phpt ├── 004.phpt ├── bug62369.phpt ├── depth.phpt ├── bug42785.phpt ├── json_encode_pretty_print.phpt ├── jsonp.phpt ├── bug46944.phpt ├── bug47644.phpt ├── bug53946.phpt ├── bug41403.phpt ├── json_encode_basic_utf8.phpt ├── 002.phpt ├── 006.phpt ├── issue9.phpt ├── 007-jsonc.phpt ├── inf_nan_error.phpt ├── bug61978.phpt ├── 010-incrementalparserfile.phpt ├── bug54058.phpt ├── json_encode_error.phpt ├── 007.phpt ├── bug61537.phpt ├── json_decode_error.phpt ├── 011-comments.phpt ├── 009-incrementalparser.phpt ├── json_decode_float.phpt ├── 001.phpt ├── bug50224.phpt ├── serialize.phpt ├── pass003.phpt ├── json_decode_basic.phpt ├── json_encode_basic.phpt ├── fail001.phpt ├── pass002.phpt ├── bug70499.phpt └── pass001.phpt ├── run-tests.sh ├── bench.sh ├── minitest.sh ├── BENCH ├── gen_travis_yml.php ├── config.w32 ├── .travis.yml ├── INSTALL ├── bench.php ├── README.md ├── LICENSE ├── minitest.php ├── config.m4 ├── php_json.h ├── STATUS └── package.xml /CREDITS: -------------------------------------------------------------------------------- 1 | JSON 2 | Omar Kilani, Scott MacVicar, Remi Collet 3 | -------------------------------------------------------------------------------- /json-c/ChangeLog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/remicollet/pecl-json-c/HEAD/json-c/ChangeLog -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "travis-pecl"] 2 | path = travis/pecl 3 | url = https://github.com/m6w6/travis-pecl.git 4 | branch = master 5 | -------------------------------------------------------------------------------- /json-c/AUTHORS: -------------------------------------------------------------------------------- 1 | Michael Clark 2 | Jehiah Czebotar 3 | Eric Haszlakiewicz 4 | C. Watford (christopher.watford@gmail.com) 5 | 6 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | DONE 2 | ==== 3 | - json_encode 4 | https://bugs.php.net/bug.php?id=63588 5 | - json_decode 6 | 7 | TODO 8 | ==== 9 | - improve decode speed 10 | 11 | 12 | JSON-C upstream waiting pull request 13 | ====== 14 | - https://github.com/json-c/json-c/pull/94 15 | 16 | -------------------------------------------------------------------------------- /tests/issue12.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Issue #12 json_decode: fails with number int frac 3 | --INI-- 4 | precision=14 5 | --SKIPIF-- 6 | 7 | --FILE-- 8 | 12 | Done 13 | --EXPECT-- 14 | float(0.1) 15 | Done 16 | -------------------------------------------------------------------------------- /run-tests.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/bash 2 | 3 | cd $(dirname $0) 4 | 5 | TEST_PHP_EXECUTABLE=$(which php) \ 6 | TEST_PHP_ARGS="-n -d extension_dir=$PWD/modules -d extension=json.so" \ 7 | NO_INTERACTION=1 \ 8 | REPORT_EXIT_STATUS=1 \ 9 | php -n run-tests.php $* | tee STATUS 10 | 11 | sed -e 's/^TEST.*\x0d//' -i STATUS 12 | 13 | -------------------------------------------------------------------------------- /bench.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/bash 2 | 3 | cd $(dirname $0) 4 | 5 | ext=$(php -r 'echo ini_get("extension_dir");') 6 | echo -e "Benchmark of a huge array encode/decode\n"; 7 | php -n -d extension=$PWD/refmod/json bench.php 8 | php -n -d extension=$PWD/modules/json.so bench.php 9 | php -n -d extension=$PWD/refmod/jsond bench.php 10 | -------------------------------------------------------------------------------- /tests/bug45791.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Bug #45791 (json_decode() does not handle number 0e0) 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 11 | --EXPECT-- 12 | object(stdClass)#1 (1) { 13 | ["zero"]=> 14 | float(0) 15 | } 16 | -------------------------------------------------------------------------------- /tests/json_encode_unescaped_slashes.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | json_decode() tests 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 10 | --EXPECT-- 11 | string(6) ""a\/b"" 12 | string(5) ""a/b"" 13 | -------------------------------------------------------------------------------- /tests/bug55543.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Bug #55543 (json_encode() with JSON_NUMERIC_CHECK & numeric string properties) 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | {"1"} = "5"; 9 | 10 | var_dump(json_encode($a, JSON_NUMERIC_CHECK)); 11 | ?> 12 | --EXPECT-- 13 | string(7) "{"1":5}" 14 | -------------------------------------------------------------------------------- /tests/012-null-byte.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Decode value with null-byte (key not yet properly decode) 3 | --SKIPIF-- 4 | 8 | --FILE-- 9 | 13 | --EXPECT-- 14 | 666f6f00626172 15 | Done 16 | -------------------------------------------------------------------------------- /tests/bug41034.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Bug #41034 (json_encode() ignores null byte started keys in arrays) 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 1,"\0null-prefixed value")); 8 | echo "\nDone\n"; 9 | ?> 10 | --EXPECT-- 11 | {"0":0,"\u0000ab":1,"1":"\u0000null-prefixed value"} 12 | Done 13 | -------------------------------------------------------------------------------- /tests/bug41567.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Bug #41567 (json_encode() double conversion is inconsistent with PHP) 3 | --INI-- 4 | precision=14 5 | --SKIPIF-- 6 | 7 | --FILE-- 8 | 15 | --EXPECT-- 16 | float(123456789.12345) 17 | Done 18 | -------------------------------------------------------------------------------- /tests/005.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | json_encode() & endless loop - 3 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 16 | --EXPECTF-- 17 | array(1) { 18 | [0]=> 19 | array(0) { 20 | } 21 | } 22 | string(4) "[[]]" 23 | Done 24 | -------------------------------------------------------------------------------- /tests/bug66021.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Bug #66021 (Blank line inside empty array/object when JSON_PRETTY_PRINT is set) 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 15 | --EXPECT-- 16 | [ 17 | [], 18 | {}, 19 | {} 20 | ] 21 | -------------------------------------------------------------------------------- /minitest.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/bash 2 | 3 | #php -n -d extension_dir=modules -d extension=json.so --re json 4 | 5 | old=$(mktemp) 6 | new=$(mktemp) 7 | ext=$(php -r 'echo ini_get("extension_dir");') 8 | 9 | php -n -d extension_dir=$ext -d extension=json.so minitest.php >$old 10 | php -n -d extension_dir=modules -d extension=json.so minitest.php >$new 11 | 12 | if ! diff -u $old $new; then 13 | echo 'Perfect !' 14 | fi 15 | rm -f $old $new 16 | 17 | -------------------------------------------------------------------------------- /tests/issue23.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Issue #23 json_decode: single quote in property name 3 | --INI-- 4 | precision=14 5 | --SKIPIF-- 6 | 7 | --FILE-- 8 | 13 | Done 14 | --EXPECT-- 15 | NULL 16 | array(1) { 17 | ["foo"]=> 18 | string(3) "bar" 19 | } 20 | Done 21 | -------------------------------------------------------------------------------- /json-c/json_c_version.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012 Eric Haszlakiewicz 3 | * 4 | * This library is free software; you can redistribute it and/or modify 5 | * it under the terms of the MIT license. See COPYING for details. 6 | */ 7 | #include "config.h" 8 | 9 | #include "json_c_version.h" 10 | 11 | const char *json_c_version(void) 12 | { 13 | return JSON_C_VERSION; 14 | } 15 | 16 | int json_c_version_num(void) 17 | { 18 | return JSON_C_VERSION_NUM; 19 | } 20 | 21 | -------------------------------------------------------------------------------- /tests/008.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | json_decode() with large integers 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | largenum); 10 | $x = json_decode($json, false, 512, JSON_BIGINT_AS_STRING); 11 | var_dump($x->largenum); 12 | echo "Done\n"; 13 | ?> 14 | --EXPECT-- 15 | float(1.2345678901235E+29) 16 | string(30) "123456789012345678901234567890" 17 | Done 18 | -------------------------------------------------------------------------------- /tests/issue28.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Issue #28 json_decode: result when we decode number with "-" in bad position 3 | --INI-- 4 | precision=14 5 | --SKIPIF-- 6 | 7 | --FILE-- 8 | 21 | Done 22 | --EXPECT-- 23 | int(-1) 24 | float(0.1) 25 | NULL 26 | NULL 27 | NULL 28 | NULL 29 | Done 30 | -------------------------------------------------------------------------------- /BENCH: -------------------------------------------------------------------------------- 1 | Benchmark of a huge array encode/decode 2 | 3 | 4 | PHP Version: 5.6.0-dev 5 | Json Version: ext/json 1.2.1 6 | 7 | Count: 262929 8 | Encode in 0.01415 sec, 1038857 bytes 9 | Decode in 0.04043 sec 10 | 11 | PHP Version: 5.6.0-dev 12 | Json Version: pecl/jsonc 1.3.4 13 | 14 | Count: 262929 15 | Encode in 0.01375 sec, 1038857 bytes 16 | Decode in 0.08779 sec 17 | 18 | PHP Version: 5.6.0-dev 19 | Json Version: pecl/jsond 1.3.0 20 | 21 | Count: 262929 22 | Encode in 0.01428 sec, 1038858 bytes 23 | Decode in 0.04500 sec 24 | -------------------------------------------------------------------------------- /json-c/random_seed.h: -------------------------------------------------------------------------------- 1 | /* 2 | * random_seed.h 3 | * 4 | * Copyright (c) 2013 Metaparadigm Pte. Ltd. 5 | * Michael Clark 6 | * 7 | * This library is free software; you can redistribute it and/or modify 8 | * it under the terms of the MIT license. See COPYING for details. 9 | * 10 | */ 11 | 12 | #ifndef seed_h 13 | #define seed_h 14 | 15 | #ifdef __cplusplus 16 | extern "C" { 17 | #endif 18 | 19 | extern int json_c_get_random_seed(); 20 | 21 | #ifdef __cplusplus 22 | } 23 | #endif 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /tests/bug46215.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Bug #46215 (json_encode mutates its parameter and has some class-specific state) 3 | --SKIPIF-- 4 | 9 | --FILE-- 10 | 22 | --EXPECT-- 23 | foo Object 24 | ( 25 | [a:protected] => Array 26 | ( 27 | ) 28 | 29 | ) 30 | -------------------------------------------------------------------------------- /tests/bug54484.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Bug #54484 (Empty string in json_decode doesn't reset json_last_error) 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 21 | --EXPECT-- 22 | int(0) 23 | int(0) 24 | int(4) 25 | int(0) 26 | -------------------------------------------------------------------------------- /tests/bug40503.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Bug #40503 (json_encode() value corruption on 32bit systems with overflown values) 3 | --INI-- 4 | precision=14 5 | --SKIPIF-- 6 | 7 | --FILE-- 8 | 19 | --EXPECT-- 20 | 2147483647 == 2147483647 21 | 2147483648 == 2147483648 22 | -------------------------------------------------------------------------------- /tests/bug43941.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Bug #43941 (json_encode() invalid UTF-8) 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 15 | --EXPECTF-- 16 | string(5) ""abc"" 17 | bool(false) 18 | string(4) "null" 19 | string(17) "[null,null,"abc"]" 20 | Done 21 | -------------------------------------------------------------------------------- /tests/bug41067.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Bug #41067 (json_encode() problem with UTF-16 input) 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 18 | --EXPECT-- 19 | f09d8480 20 | ["\ud834\udd00"] 21 | 22 | f09d8480 23 | END 24 | -------------------------------------------------------------------------------- /gen_travis_yml.php: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env php 2 | # file was generated by ; do not edit! 3 | 4 | sudo: false 5 | language: c 6 | 7 | addons: 8 | apt: 9 | packages: 10 | - php5-cli 11 | - php-pear 12 | 13 | env: 14 | ["5.4", "5.5", "5.6"], 18 | "enable_debug", 19 | "enable_maintainer_zts", 20 | ]); 21 | foreach ($env as $e) { 22 | printf(" - %s\n", $e); 23 | } 24 | ?> 25 | 26 | before_script: 27 | - make -f travis/pecl/Makefile php 28 | - make -f travis/pecl/Makefile ext PECL=json-c:json 29 | 30 | script: 31 | - make -f travis/pecl/Makefile test 32 | -------------------------------------------------------------------------------- /tests/bug41504.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Bug #41504 (json_decode() converts empty array keys to "_empty_") 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 14 | --EXPECT-- 15 | array(1) { 16 | [""]=> 17 | string(5) "value" 18 | } 19 | array(2) { 20 | [""]=> 21 | string(5) "value" 22 | ["key"]=> 23 | string(5) "value" 24 | } 25 | array(2) { 26 | ["key"]=> 27 | string(5) "value" 28 | [""]=> 29 | string(5) "value" 30 | } 31 | Done 32 | -------------------------------------------------------------------------------- /tests/bug42090.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Bug #42090 (json_decode causes segmentation fault) 3 | --SKIPIF-- 4 | 0.11') 9 | ?> 10 | --FILE-- 11 | 22 | --EXPECT-- 23 | string(0) "" 24 | NULL 25 | NULL 26 | NULL 27 | string(4) ""\""" 28 | string(1) """ 29 | string(2) """" 30 | -------------------------------------------------------------------------------- /tests/unsupported_type_error.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | An error is thrown when an unsupported type is encoded 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 19 | --EXPECTF-- 20 | resource(5) of type (stream) 21 | bool(false) 22 | int(8) 23 | string(21) "Type is not supported" 24 | string(4) "null" 25 | int(8) 26 | string(21) "Type is not supported" 27 | -------------------------------------------------------------------------------- /json-c/json_inttypes.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef _json_inttypes_h_ 3 | #define _json_inttypes_h_ 4 | 5 | #include "json_config.h" 6 | 7 | #if defined(_MSC_VER) && _MSC_VER < 1700 8 | 9 | /* Anything less than Visual Studio C++ 10 is missing stdint.h and inttypes.h */ 10 | typedef __int32 int32_t; 11 | #define INT32_MIN ((int32_t)_I32_MIN) 12 | #define INT32_MAX ((int32_t)_I32_MAX) 13 | typedef __int64 int64_t; 14 | #define INT64_MIN ((int64_t)_I64_MIN) 15 | #define INT64_MAX ((int64_t)_I64_MAX) 16 | #define PRId64 "I64d" 17 | #define SCNd64 "I64d" 18 | 19 | #else 20 | 21 | #ifdef JSON_C_HAVE_INTTYPES_H 22 | #include 23 | #endif 24 | /* inttypes.h includes stdint.h */ 25 | 26 | #endif 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /tests/json_encode_numeric.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test json_encode() function with numeric flag 3 | --SKIPIF-- 4 | 9 | --FILE-- 10 | 20 | --EXPECT-- 21 | string(1) "1" 22 | string(6) "9.4324" 23 | string(22) "[122321,3232595.33423]" 24 | string(3) ""1"" 25 | string(8) ""9.4324"" 26 | string(26) "["122321","3232595.33423"]" 27 | -------------------------------------------------------------------------------- /config.w32: -------------------------------------------------------------------------------- 1 | 2 | ARG_WITH("jsonc", "enable jsonc support", "no"); 3 | 4 | if (PHP_JSONC != "no") { 5 | if (CHECK_HEADER_ADD_INCLUDE('json.h', 'CFLAGS_JSONC', PHP_JSONC + "\\json-c;" + PHP_EXTRA_INCLUDES + "\\json-c") && 6 | CHECK_LIB("json.lib;json_a.lib", "jsonc", PHP_JSONC)) { 7 | EXTENSION("jsonc", "json.c"); 8 | 9 | AC_DEFINE("HAVE_JSONC", 1, "Have jsonc support"); 10 | PHP_INSTALL_HEADERS("ext/json", "php_json.h"); 11 | 12 | ADD_FLAG("CFLAGS_JSONC", "/D HAVE_LIBJSON"); 13 | /* Cheat so the ext is 'json' internally, despite the filename is jsonc */ 14 | ADD_FLAG("CFLAGS_JSONC", "/D JSON_EXPORTS=1 /D COMPILE_DL_JSON"); 15 | } else { 16 | WARNING('jsonc not enabled, headers or libraries not found'); 17 | } 18 | } 19 | 20 | -------------------------------------------------------------------------------- /tests/003.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | json_encode() & endless loop - 1 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 25 | --EXPECTF-- 26 | array(1) { 27 | [0]=> 28 | &array(1) { 29 | [0]=> 30 | *RECURSION* 31 | } 32 | } 33 | 34 | bool(false) 35 | int(6) 36 | string(%d) "Recursion detected" 37 | 38 | string(8) "[[null]]" 39 | int(6) 40 | string(%d) "Recursion detected" 41 | Done 42 | -------------------------------------------------------------------------------- /tests/004.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | json_encode() & endless loop - 2 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | prop = $a; 10 | 11 | var_dump($a); 12 | 13 | echo "\n"; 14 | 15 | var_dump(json_encode($a)); 16 | var_dump(json_last_error(), json_last_error_msg()); 17 | 18 | echo "\n"; 19 | 20 | var_dump(json_encode($a, JSON_PARTIAL_OUTPUT_ON_ERROR)); 21 | var_dump(json_last_error(), json_last_error_msg()); 22 | 23 | echo "Done\n"; 24 | ?> 25 | --EXPECTF-- 26 | object(stdClass)#%d (1) { 27 | ["prop"]=> 28 | *RECURSION* 29 | } 30 | 31 | bool(false) 32 | int(6) 33 | string(%d) "Recursion detected" 34 | 35 | string(22) "{"prop":{"prop":null}}" 36 | int(6) 37 | string(%d) "Recursion detected" 38 | Done 39 | -------------------------------------------------------------------------------- /json-c/json_c_version.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012 Eric Haszlakiewicz 3 | * 4 | * This library is free software; you can redistribute it and/or modify 5 | * it under the terms of the MIT license. See COPYING for details. 6 | */ 7 | 8 | #ifndef _json_c_version_h_ 9 | #define _json_c_version_h_ 10 | 11 | #define JSON_C_MAJOR_VERSION 0 12 | #define JSON_C_MINOR_VERSION 11 13 | #define JSON_C_MICRO_VERSION 0 14 | #define JSON_C_VERSION_NUM ((JSON_C_MAJOR_VERSION << 16) | \ 15 | (JSON_C_MINOR_VERSION << 8) | \ 16 | JSON_C_MICRO_VERSION) 17 | #define JSON_C_VERSION "0.11" 18 | 19 | const char *json_c_version(void); /* Returns JSON_C_VERSION */ 20 | int json_c_version_num(void); /* Returns JSON_C_VERSION_NUM */ 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /tests/bug62369.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | FR #62369 (Segfault on json_encode(deeply_nested_array) 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 5 | --FILE-- 6 | 15 | --EXPECT-- 16 | array(1) { 17 | [0]=> 18 | array(1) { 19 | [0]=> 20 | int(1) 21 | } 22 | } 23 | int(0) 24 | string(8) "No error" 25 | NULL 26 | int(1) 27 | string(28) "Maximum stack depth exceeded" 28 | NULL 29 | int(1) 30 | string(28) "Maximum stack depth exceeded" 31 | Done 32 | -------------------------------------------------------------------------------- /tests/bug42785.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Bug #42785 (Incorrect formatting of double values with non-english locales) 3 | --SKIPIF-- 4 | 11 | --FILE-- 12 | a = 100.10; 21 | $bar1->b = "foo"; 22 | var_dump(json_encode($bar1)); 23 | ?> 24 | --EXPECT-- 25 | string(13) "[100.1,"bar"]" 26 | string(21) "{"a":100.1,"b":"foo"}" 27 | -------------------------------------------------------------------------------- /json-c/bits.h: -------------------------------------------------------------------------------- 1 | /* 2 | * $Id: bits.h,v 1.10 2006/01/30 23:07:57 mclark Exp $ 3 | * 4 | * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. 5 | * Michael Clark 6 | * 7 | * This library is free software; you can redistribute it and/or modify 8 | * it under the terms of the MIT license. See COPYING for details. 9 | * 10 | */ 11 | 12 | #ifndef _bits_h_ 13 | #define _bits_h_ 14 | 15 | #ifndef json_min 16 | #define json_min(a,b) ((a) < (b) ? (a) : (b)) 17 | #endif 18 | 19 | #ifndef json_max 20 | #define json_max(a,b) ((a) > (b) ? (a) : (b)) 21 | #endif 22 | 23 | #define hexdigit(x) (((x) <= '9') ? (x) - '0' : ((x) & 7) + 9) 24 | #define error_ptr(error) ((void*)error) 25 | #define error_description(error) (json_tokener_errors[error]) 26 | #define is_error(ptr) (ptr == NULL) 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /tests/json_encode_pretty_print.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | json_encode() with JSON_PRETTY_PRINT 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 18 | --EXPECT-- 19 | [ 20 | 1, 21 | 2, 22 | 3, 23 | [ 24 | 1, 25 | 2, 26 | 3 27 | ] 28 | ] 29 | Match: 1 30 | { 31 | "a": 1, 32 | "b": [ 33 | 1, 34 | 2 35 | ], 36 | "c": { 37 | "d": 42 38 | } 39 | } 40 | Match: 1 41 | -------------------------------------------------------------------------------- /tests/jsonp.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | json_decode() with comments 3 | --SKIPIF-- 4 | 0.11') 9 | ?> 10 | --FILE-- 11 | 27 | --EXPECTF-- 28 | /* hello */"foo": NULL 29 | // hello 30 | "foo": NULL 31 | ["\n"]: array(1) { 32 | [0]=> 33 | string(1) " 34 | " 35 | } 36 | {"one":1} : object(stdClass)#1 (1) { 37 | ["one"]=> 38 | int(1) 39 | } 40 | Done 41 | -------------------------------------------------------------------------------- /tests/bug46944.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Bug #46944 (json_encode() doesn't handle 3 byte utf8 correctly) 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | > 2); 10 | $second = 0x8f|($i & 3) << 4; 11 | $string = sprintf("aa%c%c\xbf\xbdzz", $first, $second); 12 | echo json_encode($string) . "\n"; 13 | } 14 | 15 | 16 | echo "Done\n"; 17 | ?> 18 | --EXPECT-- 19 | "aa\ud83f\udffdzz" 20 | "aa\ud87f\udffdzz" 21 | "aa\ud8bf\udffdzz" 22 | "aa\ud8ff\udffdzz" 23 | "aa\ud93f\udffdzz" 24 | "aa\ud97f\udffdzz" 25 | "aa\ud9bf\udffdzz" 26 | "aa\ud9ff\udffdzz" 27 | "aa\uda3f\udffdzz" 28 | "aa\uda7f\udffdzz" 29 | "aa\udabf\udffdzz" 30 | "aa\udaff\udffdzz" 31 | "aa\udb3f\udffdzz" 32 | "aa\udb7f\udffdzz" 33 | "aa\udbbf\udffdzz" 34 | "aa\udbff\udffdzz" 35 | Done 36 | -------------------------------------------------------------------------------- /json-c/json.h: -------------------------------------------------------------------------------- 1 | /* 2 | * $Id: json.h,v 1.6 2006/01/26 02:16:28 mclark Exp $ 3 | * 4 | * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. 5 | * Michael Clark 6 | * Copyright (c) 2009 Hewlett-Packard Development Company, L.P. 7 | * 8 | * This library is free software; you can redistribute it and/or modify 9 | * it under the terms of the MIT license. See COPYING for details. 10 | * 11 | */ 12 | 13 | #ifndef _json_h_ 14 | #define _json_h_ 15 | 16 | #ifdef __cplusplus 17 | extern "C" { 18 | #endif 19 | 20 | #include "bits.h" 21 | #include "debug.h" 22 | #include "linkhash.h" 23 | #include "arraylist.h" 24 | #include "json_util.h" 25 | #include "json_object.h" 26 | #include "json_tokener.h" 27 | #include "json_object_iterator.h" 28 | #include "json_c_version.h" 29 | 30 | #ifdef __cplusplus 31 | } 32 | #endif 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /tests/bug47644.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Bug #47644 (valid large integers are truncated) 3 | --SKIPIF-- 4 | 8 | --FILE-- 9 | 18 | --EXPECT-- 19 | array(1) { 20 | [0]=> 21 | int(10000000000000000) 22 | } 23 | array(1) { 24 | [0]=> 25 | int(10000000000000001) 26 | } 27 | array(1) { 28 | [0]=> 29 | int(10000000000000002) 30 | } 31 | array(1) { 32 | [0]=> 33 | int(10000000000000003) 34 | } 35 | array(1) { 36 | [0]=> 37 | int(10000000000000004) 38 | } 39 | array(1) { 40 | [0]=> 41 | int(10000000000000005) 42 | } 43 | Done 44 | -------------------------------------------------------------------------------- /tests/bug53946.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | bug #53946 (json_encode() with JSON_UNESCAPED_UNICODE) 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 𝄞<")); 8 | var_dump(json_encode("latin 1234 -/ russian мама мыла раму specialchars \x02 \x08 \n U+1D11E >𝄞<", JSON_UNESCAPED_UNICODE)); 9 | var_dump(json_encode("ab\xE0")); 10 | var_dump(json_encode("ab\xE0", JSON_UNESCAPED_UNICODE)); 11 | ?> 12 | --EXPECTF-- 13 | string(156) ""latin 1234 -\/ russian \u043c\u0430\u043c\u0430 \u043c\u044b\u043b\u0430 \u0440\u0430\u043c\u0443 specialchars \u0002 \b \n U+1D11E >\ud834\udd1e<"" 14 | string(100) ""latin 1234 -\/ russian мама мыла раму specialchars \u0002 \b \n U+1D11E >𝄞<"" 15 | bool(false) 16 | bool(false) 17 | -------------------------------------------------------------------------------- /tests/bug41403.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Bug #41403 (json_decode cannot decode floats if localeconv decimal_point is not '.') 3 | --SKIPIF-- 4 | 12 | --INI-- 13 | precision=14 14 | --FILE-- 15 | 25 | --EXPECTF-- 26 | array(1) { 27 | [0]=> 28 | float(2,1) 29 | } 30 | array(1) { 31 | [0]=> 32 | float(0,15) 33 | } 34 | array(1) { 35 | [0]=> 36 | float(123,13452345) 37 | } 38 | array(2) { 39 | [0]=> 40 | int(123) 41 | [1]=> 42 | int(13452345) 43 | } 44 | Done 45 | -------------------------------------------------------------------------------- /tests/json_encode_basic_utf8.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test json_encode() function : basic functionality with UTF8 string input 3 | --SKIPIF-- 4 | 9 | --FILE-- 10 | 22 | ===Done=== 23 | --EXPECTF-- 24 | *** Testing json_encode() : basic functionality with UTF-8 input*** 25 | string(103) ""\u65e5\u672c\u8a9e\u30c6\u30ad\u30b9\u30c8\u3067\u3059\u300201234\uff15\uff16\uff17\uff18\uff19\u3002"" 26 | ===Done=== 27 | -------------------------------------------------------------------------------- /tests/002.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | json_encode() tests 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | ""))); 13 | var_dump(json_encode(array(array(1)))); 14 | var_dump(json_encode(array())); 15 | 16 | var_dump(json_encode(array(""=>""), JSON_FORCE_OBJECT)); 17 | var_dump(json_encode(array(array(1)), JSON_FORCE_OBJECT)); 18 | var_dump(json_encode(array(), JSON_FORCE_OBJECT)); 19 | 20 | var_dump(json_encode(1)); 21 | var_dump(json_encode("руссиш")); 22 | 23 | 24 | echo "Done\n"; 25 | ?> 26 | --EXPECTF-- 27 | string(2) """" 28 | string(4) "null" 29 | string(4) "true" 30 | string(7) "{"":""}" 31 | string(5) "[[1]]" 32 | string(2) "[]" 33 | string(7) "{"":""}" 34 | string(13) "{"0":{"0":1}}" 35 | string(2) "{}" 36 | string(1) "1" 37 | string(38) ""\u0440\u0443\u0441\u0441\u0438\u0448"" 38 | Done 39 | -------------------------------------------------------------------------------- /tests/006.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | json_encode() & extended encoding 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | ',"'bar'",'"baz"','&blong&'); 9 | 10 | echo "Normal: ", json_encode($a), "\n"; 11 | echo "Tags: ", json_encode($a,JSON_HEX_TAG), "\n"; 12 | echo "Apos: ", json_encode($a,JSON_HEX_APOS), "\n"; 13 | echo "Quot: ", json_encode($a,JSON_HEX_QUOT), "\n"; 14 | echo "Amp: ", json_encode($a,JSON_HEX_AMP), "\n"; 15 | echo "All: ", json_encode($a,JSON_HEX_TAG|JSON_HEX_APOS|JSON_HEX_QUOT|JSON_HEX_AMP), "\n"; 16 | ?> 17 | --EXPECT-- 18 | Normal: ["","'bar'","\"baz\"","&blong&"] 19 | Tags: ["\u003Cfoo\u003E","'bar'","\"baz\"","&blong&"] 20 | Apos: ["","\u0027bar\u0027","\"baz\"","&blong&"] 21 | Quot: ["","'bar'","\u0022baz\u0022","&blong&"] 22 | Amp: ["","'bar'","\"baz\"","\u0026blong\u0026"] 23 | All: ["\u003Cfoo\u003E","\u0027bar\u0027","\u0022baz\u0022","\u0026blong\u0026"] 24 | -------------------------------------------------------------------------------- /tests/issue9.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Issue #9 json_decode: invalid UTF-8 characters 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 27 | Done 28 | --EXPECT-- 29 | NULL 30 | int(5) 31 | string(56) "Malformed UTF-8 characters, possibly incorrectly encoded" 32 | string(4) "c1bf" 33 | NULL 34 | bool(true) 35 | NULL 36 | bool(true) 37 | Done 38 | -------------------------------------------------------------------------------- /tests/007-jsonc.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | json_last_error() tests 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 21 | --EXPECT-- 22 | array(1) { 23 | [0]=> 24 | int(1) 25 | } 26 | int(0) 27 | string(8) "No error" 28 | NULL 29 | int(1) 30 | string(28) "Maximum stack depth exceeded" 31 | NULL 32 | int(4) 33 | string(34) "array value separator ',' expected" 34 | NULL 35 | int(4) 36 | string(22) "unexpected end of data" 37 | NULL 38 | int(4) 39 | string(22) "unexpected end of data" 40 | Done 41 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # file was generated by gen_travis_yml.php; do not edit! 2 | 3 | sudo: false 4 | language: c 5 | 6 | addons: 7 | apt: 8 | packages: 9 | - php5-cli 10 | - php-pear 11 | 12 | env: 13 | - PHP=5.4 enable_debug=no enable_maintainer_zts=no 14 | - PHP=5.5 enable_debug=no enable_maintainer_zts=no 15 | - PHP=5.6 enable_debug=no enable_maintainer_zts=no 16 | - PHP=5.4 enable_debug=yes enable_maintainer_zts=no 17 | - PHP=5.5 enable_debug=yes enable_maintainer_zts=no 18 | - PHP=5.6 enable_debug=yes enable_maintainer_zts=no 19 | - PHP=5.4 enable_debug=no enable_maintainer_zts=yes 20 | - PHP=5.5 enable_debug=no enable_maintainer_zts=yes 21 | - PHP=5.6 enable_debug=no enable_maintainer_zts=yes 22 | - PHP=5.4 enable_debug=yes enable_maintainer_zts=yes 23 | - PHP=5.5 enable_debug=yes enable_maintainer_zts=yes 24 | - PHP=5.6 enable_debug=yes enable_maintainer_zts=yes 25 | 26 | before_script: 27 | - make -f travis/pecl/Makefile php 28 | - make -f travis/pecl/Makefile ext PECL=json-c:json 29 | 30 | script: 31 | - make -f travis/pecl/Makefile test 32 | -------------------------------------------------------------------------------- /INSTALL: -------------------------------------------------------------------------------- 1 | 1/ Quick installation 2 | 3 | Replace the ext/json tree in the php sources: 4 | 5 | tar xf php-5.#.#.tar.bz2 6 | tar xf jsonc-1.3.#.tgz 7 | rm -rf php-5.#.#/ext/json 8 | mv jsonc-1.3.# php-5.#.#/ext/json 9 | 10 | build PHP as usual. 11 | 12 | 13 | 2/ PECL installation 14 | 15 | You need to build PHP without json extension 16 | using the --disable-json option, then build 17 | jsonc as every pecl extension: 18 | 19 | tar xf jsonc-1.3.#.tgz 20 | cd jsonc-1.3.# 21 | $PHP_DIR/bin/phpize 22 | ./configure \ 23 | --with-php-config=$PHP_DIR/bin/php-config 24 | make 25 | 26 | You can also use the --with-libjson option to use the system 27 | jsonc-c library instead of the bundled copy. 28 | 29 | 30 | 3/ TEST installation 31 | 32 | If you need to build both extensions to easily switch from one 33 | to the others, build PHP with json extension as shared 34 | using --enable-json=shared. 35 | 36 | Build the pecl jsonc extension with --with-jsonc option (the 37 | module will be renamed to jsonc.so) 38 | 39 | Both can be installed, but, only one can be enabled. 40 | 41 | -------------------------------------------------------------------------------- /tests/inf_nan_error.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | An error is thrown when INF or NaN are encoded 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 30 | --EXPECTF-- 31 | float(INF) 32 | bool(false) 33 | int(7) 34 | string(34) "Inf and NaN cannot be JSON encoded" 35 | string(1) "0" 36 | int(7) 37 | string(34) "Inf and NaN cannot be JSON encoded" 38 | 39 | float(NAN) 40 | bool(false) 41 | int(7) 42 | string(34) "Inf and NaN cannot be JSON encoded" 43 | string(1) "0" 44 | int(7) 45 | string(34) "Inf and NaN cannot be JSON encoded" 46 | -------------------------------------------------------------------------------- /tests/bug61978.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Bug #61978 (Object recursion not detected for classes that implement JsonSerializable) 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | test = '123'; 13 | $this->me = $this; 14 | } 15 | } 16 | 17 | class JsonTest2 implements JsonSerializable { 18 | public $test; 19 | public function __construct() { 20 | $this->test = '123'; 21 | } 22 | public function jsonSerialize() { 23 | return array( 24 | 'test' => $this->test, 25 | 'me' => $this 26 | ); 27 | } 28 | } 29 | 30 | 31 | $obj1 = new JsonTest1(); 32 | var_dump(json_encode($obj1, JSON_PARTIAL_OUTPUT_ON_ERROR)); 33 | 34 | echo "==\n"; 35 | 36 | $obj2 = new JsonTest2(); 37 | var_dump(json_encode($obj2, JSON_PARTIAL_OUTPUT_ON_ERROR)); 38 | 39 | ?> 40 | --EXPECTF-- 41 | string(44) "{"test":"123","me":{"test":"123","me":null}}" 42 | == 43 | string(44) "{"test":"123","me":{"test":"123","me":null}}" 44 | -------------------------------------------------------------------------------- /tests/010-incrementalparserfile.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | JsonIncremantalParser::parseFile() test 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 1, "Two" => 2, "Three" =>3); 11 | public $pi = 3.14159; 12 | } 13 | $parser = new JsonIncrementalParser(10, JSON_PARSER_NOTSTRICT); 14 | 15 | $fic = __DIR__.'/minitest.json'; 16 | $txt = "/*\nTest file\n*/\n"; 17 | $txt .= json_encode(new Foo(), JSON_PRETTY_PRINT); 18 | 19 | file_put_contents($fic, $txt); 20 | var_dump($parser->parseFile($fic)); 21 | var_dump($parser->get()); 22 | unlink($fic); 23 | 24 | echo "Done\n"; 25 | ?> 26 | --EXPECT-- 27 | int(0) 28 | object(stdClass)#2 (4) { 29 | ["one"]=> 30 | int(1) 31 | ["arr"]=> 32 | array(2) { 33 | [0]=> 34 | string(3) "foo" 35 | [1]=> 36 | string(3) "bar" 37 | } 38 | ["hash"]=> 39 | object(stdClass)#3 (3) { 40 | ["One"]=> 41 | int(1) 42 | ["Two"]=> 43 | int(2) 44 | ["Three"]=> 45 | int(3) 46 | } 47 | ["pi"]=> 48 | float(3.14159) 49 | } 50 | Done 51 | -------------------------------------------------------------------------------- /tests/bug54058.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Bug #54058 (json_last_error() invalid UTF-8 produces wrong error) 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | foo = quoted_printable_decode('=B0'); 15 | json_encode($a); 16 | var_dump(json_last_error(), json_last_error_msg()); 17 | 18 | $b = new stdclass; 19 | $b->foo = $bad_utf8; 20 | $b->bar = 1; 21 | json_encode($b); 22 | var_dump(json_last_error(), json_last_error_msg()); 23 | 24 | $c = array( 25 | 'foo' => $bad_utf8, 26 | 'bar' => 1 27 | ); 28 | json_encode($c); 29 | var_dump(json_last_error(), json_last_error_msg()); 30 | 31 | ?> 32 | --EXPECTF-- 33 | int(5) 34 | string(56) "Malformed UTF-8 characters, possibly incorrectly encoded" 35 | int(5) 36 | string(56) "Malformed UTF-8 characters, possibly incorrectly encoded" 37 | int(5) 38 | string(56) "Malformed UTF-8 characters, possibly incorrectly encoded" 39 | int(5) 40 | string(56) "Malformed UTF-8 characters, possibly incorrectly encoded" 41 | -------------------------------------------------------------------------------- /tests/json_encode_error.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test json_encode() function : error conditions 3 | --SKIPIF-- 4 | 9 | --FILE-- 10 | 27 | ===Done=== 28 | --EXPECTF-- 29 | *** Testing json_encode() : error conditions *** 30 | 31 | -- Testing json_encode() function with no arguments -- 32 | 33 | Warning: json_encode() expects at least 1 parameter, 0 given in %s on line %d 34 | NULL 35 | 36 | -- Testing json_encode() function with more than expected no. of arguments -- 37 | string(5) ""abc"" 38 | ===Done=== 39 | -------------------------------------------------------------------------------- /tests/007.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | json_last_error() tests 3 | --SKIPIF-- 4 | ')) die("skip with PHP 5.4"); 7 | ?> 8 | --XFAIL-- 9 | Different parser, so different error codes. 10 | --FILE-- 11 | 26 | --EXPECT-- 27 | array(1) { 28 | [0]=> 29 | int(1) 30 | } 31 | int(0) 32 | string(8) "No error" 33 | NULL 34 | int(1) 35 | string(28) "Maximum stack depth exceeded" 36 | NULL 37 | int(2) 38 | string(42) "State mismatch (invalid or malformed JSON)" 39 | NULL 40 | int(3) 41 | string(53) "Control character error, possibly incorrectly encoded" 42 | NULL 43 | int(4) 44 | string(12) "Syntax error" 45 | Done 46 | -------------------------------------------------------------------------------- /json-c/json_object_private.h: -------------------------------------------------------------------------------- 1 | /* 2 | * $Id: json_object_private.h,v 1.4 2006/01/26 02:16:28 mclark Exp $ 3 | * 4 | * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. 5 | * Michael Clark 6 | * 7 | * This library is free software; you can redistribute it and/or modify 8 | * it under the terms of the MIT license. See COPYING for details. 9 | * 10 | */ 11 | 12 | #ifndef _json_object_private_h_ 13 | #define _json_object_private_h_ 14 | 15 | #ifdef __cplusplus 16 | extern "C" { 17 | #endif 18 | 19 | typedef void (json_object_private_delete_fn)(struct json_object *o); 20 | 21 | struct json_object 22 | { 23 | enum json_type o_type; 24 | json_object_private_delete_fn *_delete; 25 | json_object_to_json_string_fn *_to_json_string; 26 | int _ref_count; 27 | struct printbuf *_pb; 28 | union data { 29 | json_bool c_boolean; 30 | double c_double; 31 | int64_t c_int64; 32 | struct lh_table *c_object; 33 | struct array_list *c_array; 34 | struct { 35 | char *str; 36 | int len; 37 | } c_string; 38 | } o; 39 | json_object_delete_fn *_user_delete; 40 | void *_userdata; 41 | }; 42 | 43 | #ifdef __cplusplus 44 | } 45 | #endif 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /json-c/json_util.h: -------------------------------------------------------------------------------- 1 | /* 2 | * $Id: json_util.h,v 1.4 2006/01/30 23:07:57 mclark Exp $ 3 | * 4 | * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. 5 | * Michael Clark 6 | * 7 | * This library is free software; you can redistribute it and/or modify 8 | * it under the terms of the MIT license. See COPYING for details. 9 | * 10 | */ 11 | 12 | #ifndef _json_util_h_ 13 | #define _json_util_h_ 14 | 15 | #include "json_object.h" 16 | 17 | #ifdef __cplusplus 18 | extern "C" { 19 | #endif 20 | 21 | #define JSON_FILE_BUF_SIZE 4096 22 | 23 | /* utility functions */ 24 | extern struct json_object* json_object_from_file(const char *filename); 25 | extern int json_object_to_file(char *filename, struct json_object *obj); 26 | extern int json_object_to_file_ext(char *filename, struct json_object *obj, int flags); 27 | extern int json_parse_int64(const char *buf, int64_t *retval); 28 | extern int json_parse_double(const char *buf, double *retval); 29 | 30 | 31 | /** 32 | * Return a string describing the type of the object. 33 | * e.g. "int", or "object", etc... 34 | */ 35 | extern const char *json_type_to_name(enum json_type o_type); 36 | 37 | #ifdef __cplusplus 38 | } 39 | #endif 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /tests/bug61537.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Bug #61537 (json_encode() incorrectly truncates/discards information) 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 26 | --EXPECTF-- 27 | bool(false) 28 | int(5) 29 | string(56) "Malformed UTF-8 characters, possibly incorrectly encoded" 30 | string(4) "null" 31 | int(5) 32 | string(56) "Malformed UTF-8 characters, possibly incorrectly encoded" 33 | 34 | bool(false) 35 | int(5) 36 | string(56) "Malformed UTF-8 characters, possibly incorrectly encoded" 37 | string(4) "null" 38 | int(5) 39 | string(56) "Malformed UTF-8 characters, possibly incorrectly encoded" 40 | -------------------------------------------------------------------------------- /tests/json_decode_error.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test json_decode() function : error conditions 3 | --SKIPIF-- 4 | 9 | --FILE-- 10 | 26 | ===Done=== 27 | --EXPECTF-- 28 | *** Testing json_decode() : error conditions *** 29 | 30 | -- Testing json_decode() function with no arguments -- 31 | 32 | Warning: json_decode() expects at least 1 parameter, 0 given in %s on line %d 33 | NULL 34 | 35 | -- Testing json_decode() function with more than expected no. of arguments -- 36 | 37 | Warning: json_decode() expects at most 4 parameters, 5 given in %s on line %d 38 | NULL 39 | ===Done=== 40 | -------------------------------------------------------------------------------- /json-c/json_config.h: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------+ 3 | | PHP Version 5 | 4 | +----------------------------------------------------------------------+ 5 | | Copyright (c) 1997-2012 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 | | Authors: Remi Collet | 16 | +----------------------------------------------------------------------+ 17 | */ 18 | #include "config.h" 19 | 20 | #ifdef HAVE_INTTYPES_H 21 | #define JSON_C_HAVE_INTTYPES_H 1 22 | #endif 23 | 24 | -------------------------------------------------------------------------------- /tests/011-comments.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | JsonIncremantalParser::parseFile() test 3 | --SKIPIF-- 4 | 0.11') 9 | ?> 10 | --FILE-- 11 | 26 | --EXPECT-- 27 | Testing: / bad comment 28 | ["foo"] 29 | NULL 30 | NULL 31 | Testing: // comment 32 | ["foo"] 33 | NULL 34 | array(1) { 35 | [0]=> 36 | string(3) "foo" 37 | } 38 | Testing: /* comment */ ["foo"] 39 | NULL 40 | array(1) { 41 | [0]=> 42 | string(3) "foo" 43 | } 44 | Testing: [/* comment */ "foo"] 45 | NULL 46 | array(1) { 47 | [0]=> 48 | string(3) "foo" 49 | } 50 | Testing: ["/* not a comment */ foo"] 51 | array(1) { 52 | [0]=> 53 | string(23) "/* not a comment */ foo" 54 | } 55 | array(1) { 56 | [0]=> 57 | string(23) "/* not a comment */ foo" 58 | } 59 | Done 60 | -------------------------------------------------------------------------------- /json-c/arraylist.h: -------------------------------------------------------------------------------- 1 | /* 2 | * $Id: arraylist.h,v 1.4 2006/01/26 02:16:28 mclark Exp $ 3 | * 4 | * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. 5 | * Michael Clark 6 | * 7 | * This library is free software; you can redistribute it and/or modify 8 | * it under the terms of the MIT license. See COPYING for details. 9 | * 10 | */ 11 | 12 | #ifndef _arraylist_h_ 13 | #define _arraylist_h_ 14 | 15 | #ifdef __cplusplus 16 | extern "C" { 17 | #endif 18 | 19 | #define ARRAY_LIST_DEFAULT_SIZE 32 20 | 21 | typedef void (array_list_free_fn) (void *data); 22 | 23 | struct array_list 24 | { 25 | void **array; 26 | int length; 27 | int size; 28 | array_list_free_fn *free_fn; 29 | }; 30 | 31 | extern struct array_list* 32 | array_list_new(array_list_free_fn *free_fn); 33 | 34 | extern void 35 | array_list_free(struct array_list *al); 36 | 37 | extern void* 38 | array_list_get_idx(struct array_list *al, int i); 39 | 40 | extern int 41 | array_list_put_idx(struct array_list *al, int i, void *data); 42 | 43 | extern int 44 | array_list_add(struct array_list *al, void *data); 45 | 46 | extern int 47 | array_list_length(struct array_list *al); 48 | 49 | extern void 50 | array_list_sort(struct array_list *arr, int(*compar)(const void *, const void *)); 51 | 52 | #ifdef __cplusplus 53 | } 54 | #endif 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /json-c/config.h: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------+ 3 | | PHP Version 5 | 4 | +----------------------------------------------------------------------+ 5 | | Copyright (c) 1997-2012 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 | | Authors: Remi Collet | 16 | +----------------------------------------------------------------------+ 17 | */ 18 | #ifdef HAVE_CONFIG_H 19 | /* Building in PECL */ 20 | #include "../config.h" 21 | 22 | #else 23 | /* Building in PHP tree */ 24 | #include "php_config.h" 25 | #endif 26 | -------------------------------------------------------------------------------- /tests/009-incrementalparser.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | JsonIncremantalParser::parse() simple test 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | getError()); 10 | // Simple parse 11 | var_dump($parser->parse('"foo"')); 12 | var_dump($parser->get()); 13 | // Simple parse 14 | var_dump($parser->parse('thisisnotjson')); 15 | var_dump($parser->get()); 16 | // Reset test 17 | var_dump($parser->reset()); 18 | var_dump($parser->get()); 19 | // Partial parse 20 | var_dump($parser->parse('["foo",')); 21 | var_dump($parser->get()); 22 | // Complete parse 23 | var_dump($parser->parse('"bar"]')); 24 | var_dump($parser->get()); 25 | // Object get twice 26 | var_dump($parser->parse('{"One":"foo",')); 27 | var_dump($parser->parse('"Two":"bar"}')); 28 | var_dump($parser->get()); 29 | var_dump($parser->get(JSON_OBJECT_AS_ARRAY)); 30 | echo "Done\n"; 31 | ?> 32 | --EXPECT-- 33 | int(0) 34 | int(0) 35 | string(3) "foo" 36 | int(6) 37 | NULL 38 | int(0) 39 | NULL 40 | int(1) 41 | NULL 42 | int(0) 43 | array(2) { 44 | [0]=> 45 | string(3) "foo" 46 | [1]=> 47 | string(3) "bar" 48 | } 49 | int(1) 50 | int(0) 51 | object(stdClass)#2 (2) { 52 | ["One"]=> 53 | string(3) "foo" 54 | ["Two"]=> 55 | string(3) "bar" 56 | } 57 | array(2) { 58 | ["One"]=> 59 | string(3) "foo" 60 | ["Two"]=> 61 | string(3) "bar" 62 | } 63 | Done 64 | -------------------------------------------------------------------------------- /tests/json_decode_float.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test json_decode() function with float 3 | --SKIPIF-- 4 | 9 | --FILE-- 10 | 67 | Done 68 | --EXPECT-- 69 | bool(true) 70 | int(41) 71 | NULL 72 | NULL 73 | NULL 74 | NULL 75 | Done 76 | -------------------------------------------------------------------------------- /tests/001.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | json_decode() tests 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | ")); 15 | var_dump(json_decode(";")); 16 | var_dump(json_decode("руссиш")); 17 | var_dump(json_decode("blah")); 18 | var_dump(json_decode(NULL)); 19 | var_dump(json_decode('{ "test": { "foo": "bar" } }')); 20 | var_dump(json_decode('{ "test": { "foo": "" } }')); 21 | var_dump(json_decode('{ "": { "foo": "" } }')); 22 | var_dump(json_decode('{ "": { "": "" } }')); 23 | var_dump(json_decode('{ "": { "": "" }')); 24 | var_dump(json_decode('{ "": "": "" } }')); 25 | 26 | ?> 27 | ===DONE=== 28 | --EXPECTF-- 29 | Warning: json_decode() expects at least 1 parameter, 0 given in %s on line %d 30 | NULL 31 | NULL 32 | NULL 33 | NULL 34 | NULL 35 | NULL 36 | NULL 37 | NULL 38 | NULL 39 | NULL 40 | NULL 41 | object(stdClass)#%d (1) { 42 | ["test"]=> 43 | object(stdClass)#%d (1) { 44 | ["foo"]=> 45 | string(3) "bar" 46 | } 47 | } 48 | object(stdClass)#%d (1) { 49 | ["test"]=> 50 | object(stdClass)#%d (1) { 51 | ["foo"]=> 52 | string(0) "" 53 | } 54 | } 55 | object(stdClass)#%d (1) { 56 | ["_empty_"]=> 57 | object(stdClass)#%d (1) { 58 | ["foo"]=> 59 | string(0) "" 60 | } 61 | } 62 | object(stdClass)#%d (1) { 63 | ["_empty_"]=> 64 | object(stdClass)#%d (1) { 65 | ["_empty_"]=> 66 | string(0) "" 67 | } 68 | } 69 | NULL 70 | NULL 71 | ===DONE=== 72 | -------------------------------------------------------------------------------- /bench.php: -------------------------------------------------------------------------------- 1 | parseFile("bench.json"); 63 | $json = $p->get(); 64 | $b = microtime(true); 65 | if ($json) { 66 | printf("Decode from file in %.5f sec\n", $b-$a); 67 | } 68 | } 69 | */ 70 | -------------------------------------------------------------------------------- /tests/bug50224.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | bug #50224 (json_encode() does not always encode a float as a float) 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 12.0, 'integer' => 12), JSON_PRESERVE_ZERO_FRACTION)); 14 | 15 | echo "\n* Testing encode/decode symmetry\n\n"; 16 | 17 | var_dump(json_decode(json_encode(12.3, JSON_PRESERVE_ZERO_FRACTION))); 18 | var_dump(json_decode(json_encode(12, JSON_PRESERVE_ZERO_FRACTION))); 19 | var_dump(json_decode(json_encode(12.0, JSON_PRESERVE_ZERO_FRACTION))); 20 | var_dump(json_decode(json_encode(0.0, JSON_PRESERVE_ZERO_FRACTION))); 21 | var_dump(json_decode(json_encode(array(12, 12.0, 12.3), JSON_PRESERVE_ZERO_FRACTION))); 22 | var_dump(json_decode(json_encode((object)array('float' => 12.0, 'integer' => 12), JSON_PRESERVE_ZERO_FRACTION))); 23 | var_dump(json_decode(json_encode((object)array('float' => 12.0, 'integer' => 12), JSON_PRESERVE_ZERO_FRACTION), true)); 24 | ?> 25 | --EXPECTF-- 26 | * Testing JSON output 27 | 28 | string(4) "12.3" 29 | string(2) "12" 30 | string(4) "12.0" 31 | string(3) "0.0" 32 | string(14) "[12,12.0,12.3]" 33 | string(27) "{"float":12.0,"integer":12}" 34 | 35 | * Testing encode/decode symmetry 36 | 37 | float(12.3) 38 | int(12) 39 | float(12) 40 | float(0) 41 | array(3) { 42 | [0]=> 43 | int(12) 44 | [1]=> 45 | float(12) 46 | [2]=> 47 | float(12.3) 48 | } 49 | object(stdClass)#%d (2) { 50 | ["float"]=> 51 | float(12) 52 | ["integer"]=> 53 | int(12) 54 | } 55 | array(2) { 56 | ["float"]=> 57 | float(12) 58 | ["integer"]=> 59 | int(12) 60 | } -------------------------------------------------------------------------------- /json-c/debug.h: -------------------------------------------------------------------------------- 1 | /* 2 | * $Id: debug.h,v 1.5 2006/01/30 23:07:57 mclark Exp $ 3 | * 4 | * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. 5 | * Michael Clark 6 | * Copyright (c) 2009 Hewlett-Packard Development Company, L.P. 7 | * 8 | * This library is free software; you can redistribute it and/or modify 9 | * it under the terms of the MIT license. See COPYING for details. 10 | * 11 | */ 12 | 13 | #ifndef _DEBUG_H_ 14 | #define _DEBUG_H_ 15 | 16 | #include 17 | 18 | #ifdef __cplusplus 19 | extern "C" { 20 | #endif 21 | 22 | extern void mc_set_debug(int debug); 23 | extern int mc_get_debug(void); 24 | 25 | extern void mc_set_syslog(int syslog); 26 | extern void mc_abort(const char *msg, ...); 27 | extern void mc_debug(const char *msg, ...); 28 | extern void mc_error(const char *msg, ...); 29 | extern void mc_info(const char *msg, ...); 30 | 31 | #ifndef __STRING 32 | #define __STRING(x) #x 33 | #endif 34 | 35 | #ifndef PARSER_BROKEN_FIXED 36 | 37 | #define JASSERT(cond) do {} while(0) 38 | 39 | #else 40 | 41 | #define JASSERT(cond) do { \ 42 | if (!(cond)) { \ 43 | mc_error("cjson assert failure %s:%d : cond \"" __STRING(cond) "failed\n", __FILE__, __LINE__); \ 44 | *(int *)0 = 1;\ 45 | abort(); \ 46 | }\ 47 | } while(0) 48 | 49 | #endif 50 | 51 | #define MC_ABORT(x, ...) mc_abort(x, ##__VA_ARGS__) 52 | #define MC_ERROR(x, ...) mc_error(x, ##__VA_ARGS__) 53 | 54 | #ifdef MC_MAINTAINER_MODE 55 | #define MC_SET_DEBUG(x) mc_set_debug(x) 56 | #define MC_GET_DEBUG() mc_get_debug() 57 | #define MC_SET_SYSLOG(x) mc_set_syslog(x) 58 | #define MC_DEBUG(x, ...) mc_debug(x, ##__VA_ARGS__) 59 | #define MC_INFO(x, ...) mc_info(x, ##__VA_ARGS__) 60 | #else 61 | #define MC_SET_DEBUG(x) if (0) mc_set_debug(x) 62 | #define MC_GET_DEBUG() (0) 63 | #define MC_SET_SYSLOG(x) if (0) mc_set_syslog(x) 64 | #define MC_DEBUG(x, ...) if (0) mc_debug(x, ##__VA_ARGS__) 65 | #define MC_INFO(x, ...) if (0) mc_info(x, ##__VA_ARGS__) 66 | #endif 67 | 68 | #ifdef __cplusplus 69 | } 70 | #endif 71 | 72 | #endif 73 | -------------------------------------------------------------------------------- /json-c/debug.c: -------------------------------------------------------------------------------- 1 | /* 2 | * $Id: debug.c,v 1.5 2006/01/26 02:16:28 mclark Exp $ 3 | * 4 | * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. 5 | * Michael Clark 6 | * 7 | * This library is free software; you can redistribute it and/or modify 8 | * it under the terms of the MIT license. See COPYING for details. 9 | * 10 | */ 11 | 12 | #include "config.h" 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #if HAVE_SYSLOG_H 20 | # include 21 | #endif /* HAVE_SYSLOG_H */ 22 | 23 | #if HAVE_UNISTD_H 24 | # include 25 | #endif /* HAVE_UNISTD_H */ 26 | 27 | #if HAVE_SYS_PARAM_H 28 | #include 29 | #endif /* HAVE_SYS_PARAM_H */ 30 | 31 | #include "debug.h" 32 | 33 | static int _syslog = 0; 34 | static int _debug = 0; 35 | 36 | void mc_set_debug(int debug) { _debug = debug; } 37 | int mc_get_debug(void) { return _debug; } 38 | 39 | extern void mc_set_syslog(int syslog) 40 | { 41 | _syslog = syslog; 42 | } 43 | 44 | void mc_abort(const char *msg, ...) 45 | { 46 | va_list ap; 47 | va_start(ap, msg); 48 | #if HAVE_VSYSLOG 49 | if(_syslog) { 50 | vsyslog(LOG_ERR, msg, ap); 51 | } else 52 | #endif 53 | vprintf(msg, ap); 54 | va_end(ap); 55 | exit(1); 56 | } 57 | 58 | 59 | void mc_debug(const char *msg, ...) 60 | { 61 | va_list ap; 62 | if(_debug) { 63 | va_start(ap, msg); 64 | #if HAVE_VSYSLOG 65 | if(_syslog) { 66 | vsyslog(LOG_DEBUG, msg, ap); 67 | } else 68 | #endif 69 | vprintf(msg, ap); 70 | va_end(ap); 71 | } 72 | } 73 | 74 | void mc_error(const char *msg, ...) 75 | { 76 | va_list ap; 77 | va_start(ap, msg); 78 | #if HAVE_VSYSLOG 79 | if(_syslog) { 80 | vsyslog(LOG_ERR, msg, ap); 81 | } else 82 | #endif 83 | vfprintf(stderr, msg, ap); 84 | va_end(ap); 85 | } 86 | 87 | void mc_info(const char *msg, ...) 88 | { 89 | va_list ap; 90 | va_start(ap, msg); 91 | #if HAVE_VSYSLOG 92 | if(_syslog) { 93 | vsyslog(LOG_INFO, msg, ap); 94 | } else 95 | #endif 96 | vfprintf(stderr, msg, ap); 97 | va_end(ap); 98 | } 99 | -------------------------------------------------------------------------------- /json-c/COPYING: -------------------------------------------------------------------------------- 1 | 2 | Copyright (c) 2009-2012 Eric Haszlakiewicz 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a 5 | copy of this software and associated documentation files (the "Software"), 6 | to deal in the Software without restriction, including without limitation 7 | the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | and/or sell copies of the Software, and to permit persons to whom the 9 | Software is furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included 12 | in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | 22 | ---------------------------------------------------------------- 23 | 24 | Copyright (c) 2004, 2005 Metaparadigm Pte Ltd 25 | 26 | Permission is hereby granted, free of charge, to any person obtaining a 27 | copy of this software and associated documentation files (the "Software"), 28 | to deal in the Software without restriction, including without limitation 29 | the rights to use, copy, modify, merge, publish, distribute, sublicense, 30 | and/or sell copies of the Software, and to permit persons to whom the 31 | Software is furnished to do so, subject to the following conditions: 32 | 33 | The above copyright notice and this permission notice shall be included 34 | in all copies or substantial portions of the Software. 35 | 36 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 37 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 38 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 39 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 40 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 41 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 42 | SOFTWARE. 43 | -------------------------------------------------------------------------------- /tests/serialize.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | json_encode() Serialization tests 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | data = $data; 15 | } 16 | } 17 | 18 | class SerializingTest extends NonSerializingTest implements JsonSerializable 19 | { 20 | public function jsonSerialize() 21 | { 22 | return $this->data; 23 | } 24 | } 25 | 26 | class ValueSerializingTest extends SerializingTest 27 | { 28 | public function jsonSerialize() 29 | { 30 | return array_values(is_array($this->data) ? $this->data : get_object_vars($this->data)); 31 | } 32 | } 33 | 34 | class SelfSerializingTest extends SerializingTest 35 | { 36 | public function jsonSerialize() 37 | { 38 | return $this; 39 | } 40 | } 41 | 42 | $adata = array( 43 | 'str' => 'foo', 44 | 'int' => 1, 45 | 'float' => 2.3, 46 | 'bool' => false, 47 | 'nil' => null, 48 | 'arr' => array(1,2,3), 49 | 'obj' => new StdClass, 50 | ); 51 | 52 | $ndata = array_values($adata); 53 | 54 | $odata = (object)$adata; 55 | 56 | foreach(array('NonSerializingTest','SerializingTest','ValueSerializingTest','SelfSerializingTest') as $class) { 57 | echo "==$class==\n"; 58 | echo json_encode(new $class($adata)), "\n"; 59 | echo json_encode(new $class($ndata)), "\n"; 60 | echo json_encode(new $class($odata)), "\n"; 61 | } 62 | --EXPECT-- 63 | ==NonSerializingTest== 64 | {"data":{"str":"foo","int":1,"float":2.3,"bool":false,"nil":null,"arr":[1,2,3],"obj":{}}} 65 | {"data":["foo",1,2.3,false,null,[1,2,3],{}]} 66 | {"data":{"str":"foo","int":1,"float":2.3,"bool":false,"nil":null,"arr":[1,2,3],"obj":{}}} 67 | ==SerializingTest== 68 | {"str":"foo","int":1,"float":2.3,"bool":false,"nil":null,"arr":[1,2,3],"obj":{}} 69 | ["foo",1,2.3,false,null,[1,2,3],{}] 70 | {"str":"foo","int":1,"float":2.3,"bool":false,"nil":null,"arr":[1,2,3],"obj":{}} 71 | ==ValueSerializingTest== 72 | ["foo",1,2.3,false,null,[1,2,3],{}] 73 | ["foo",1,2.3,false,null,[1,2,3],{}] 74 | ["foo",1,2.3,false,null,[1,2,3],{}] 75 | ==SelfSerializingTest== 76 | {"data":{"str":"foo","int":1,"float":2.3,"bool":false,"nil":null,"arr":[1,2,3],"obj":{}}} 77 | {"data":["foo",1,2.3,false,null,[1,2,3],{}]} 78 | {"data":{"str":"foo","int":1,"float":2.3,"bool":false,"nil":null,"arr":[1,2,3],"obj":{}}} 79 | 80 | 81 | -------------------------------------------------------------------------------- /json-c/printbuf.h: -------------------------------------------------------------------------------- 1 | /* 2 | * $Id: printbuf.h,v 1.4 2006/01/26 02:16:28 mclark Exp $ 3 | * 4 | * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. 5 | * Michael Clark 6 | * 7 | * This library is free software; you can redistribute it and/or modify 8 | * it under the terms of the MIT license. See COPYING for details. 9 | * 10 | * 11 | * Copyright (c) 2008-2009 Yahoo! Inc. All rights reserved. 12 | * The copyrights to the contents of this file are licensed under the MIT License 13 | * (http://www.opensource.org/licenses/mit-license.php) 14 | */ 15 | 16 | #ifndef _printbuf_h_ 17 | #define _printbuf_h_ 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | struct printbuf { 24 | char *buf; 25 | int bpos; 26 | int size; 27 | }; 28 | 29 | extern struct printbuf* 30 | printbuf_new(void); 31 | 32 | /* As an optimization, printbuf_memappend_fast is defined as a macro 33 | * that handles copying data if the buffer is large enough; otherwise 34 | * it invokes printbuf_memappend_real() which performs the heavy 35 | * lifting of realloc()ing the buffer and copying data. 36 | * Your code should not use printbuf_memappend directly--use 37 | * printbuf_memappend_fast instead. 38 | */ 39 | extern int 40 | printbuf_memappend(struct printbuf *p, const char *buf, int size); 41 | 42 | #define printbuf_memappend_fast(p, bufptr, bufsize) \ 43 | do { \ 44 | if ((p->size - p->bpos) > bufsize) { \ 45 | memcpy(p->buf + p->bpos, (bufptr), bufsize); \ 46 | p->bpos += bufsize; \ 47 | p->buf[p->bpos]= '\0'; \ 48 | } else { printbuf_memappend(p, (bufptr), bufsize); } \ 49 | } while (0) 50 | 51 | #define printbuf_length(p) ((p)->bpos) 52 | 53 | /** 54 | * Set len bytes of the buffer to charvalue, starting at offset offset. 55 | * Similar to calling memset(x, charvalue, len); 56 | * 57 | * The memory allocated for the buffer is extended as necessary. 58 | * 59 | * If offset is -1, this starts at the end of the current data in the buffer. 60 | */ 61 | extern int 62 | printbuf_memset(struct printbuf *pb, int offset, int charvalue, int len); 63 | 64 | extern int 65 | sprintbuf(struct printbuf *p, const char *msg, ...); 66 | 67 | extern void 68 | printbuf_reset(struct printbuf *p); 69 | 70 | extern void 71 | printbuf_free(struct printbuf *p); 72 | 73 | #ifdef __cplusplus 74 | } 75 | #endif 76 | 77 | #endif 78 | -------------------------------------------------------------------------------- /tests/pass003.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | JSON (http://www.crockford.com/JSON/JSON_checker/test/pass3.json) 3 | --SKIPIF-- 4 | 7 | --FILE-- 8 | 42 | --EXPECT-- 43 | Testing: 44 | { 45 | "JSON Test Pattern pass3": { 46 | "The outermost value": "must be an object or array.", 47 | "In this test": "It is an object." 48 | } 49 | } 50 | 51 | DECODE: AS OBJECT 52 | object(stdClass)#1 (1) { 53 | ["JSON Test Pattern pass3"]=> 54 | object(stdClass)#2 (2) { 55 | ["The outermost value"]=> 56 | string(27) "must be an object or array." 57 | ["In this test"]=> 58 | string(16) "It is an object." 59 | } 60 | } 61 | DECODE: AS ARRAY 62 | array(1) { 63 | ["JSON Test Pattern pass3"]=> 64 | array(2) { 65 | ["The outermost value"]=> 66 | string(27) "must be an object or array." 67 | ["In this test"]=> 68 | string(16) "It is an object." 69 | } 70 | } 71 | ENCODE: FROM OBJECT 72 | {"JSON Test Pattern pass3":{"The outermost value":"must be an object or array.","In this test":"It is an object."}} 73 | ENCODE: FROM ARRAY 74 | {"JSON Test Pattern pass3":{"The outermost value":"must be an object or array.","In this test":"It is an object."}} 75 | DECODE AGAIN: AS OBJECT 76 | object(stdClass)#3 (1) { 77 | ["JSON Test Pattern pass3"]=> 78 | object(stdClass)#4 (2) { 79 | ["The outermost value"]=> 80 | string(27) "must be an object or array." 81 | ["In this test"]=> 82 | string(16) "It is an object." 83 | } 84 | } 85 | DECODE AGAIN: AS ARRAY 86 | array(1) { 87 | ["JSON Test Pattern pass3"]=> 88 | array(2) { 89 | ["The outermost value"]=> 90 | string(27) "must be an object or array." 91 | ["In this test"]=> 92 | string(16) "It is an object." 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | pecl-json-c 2 | =========== 3 | 4 | [![Build Status](https://travis-ci.org/remicollet/pecl-json-c.svg?branch=master)](https://travis-ci.org/remicollet/pecl-json-c) 5 | 6 | 7 | JSON-C wrapper 8 | 9 | This is the sources repository for http://pecl.php.net/package/jsonc 10 | 11 | This extension was created to be a drop-in alternative to the standard 12 | **PHP 5** json extension, because of the licensing concerns over the JSON parser 13 | code used as part of the standard PHP json extension. 14 | See [PHP bug #63520](https://bugs.php.net/63520) 15 | 16 | As **PHP 7** have a new ext/json extension, which is free, 17 | this extension will not be made comptible, and won't be 18 | available for PHP 7. 19 | 20 | json_encode is the same than current PHP one. 21 | 22 | json_decode use the json-c library and is mostly compatible. 23 | 24 | A new option JSON_PARSER_NOTSTRICT allow to reduce parser strictness 25 | - integer could start with zero 26 | - string can be single or double-quoted 27 | - comments are allowed in json string/files (Using /* */ or // until end of line) 28 | - ignore trailing char after data 29 | - no check for invalid UTF-8 characters 30 | 31 | Also provide a new incremental parser object: 32 | 33 | $parser = new JsonIncrementalParser(); 34 | $fic = fopen("somefile.json", "r"); 35 | do { 36 | $buf = fgets($fic); 37 | $ret = $parser->parse($buf); 38 | } while ($buf && ($ret==JsonIncrementalParser::JSON_PARSER_CONTINUE)); 39 | $result = $parser->get(); 40 | 41 | or, even simpler: 42 | 43 | $ret = $parser->parseFile("somefile.json"); 44 | $result = $parser->get(); 45 | 46 | Debian DEB available, since Jessie for PHP 5.5 47 | - http://packages.debian.org/jessie/php5-json 48 | 49 | Fedora RPM are available in official repo, since Fedora 19 50 | - https://apps.fedoraproject.org/packages/php-pecl-jsonc 51 | 52 | Ubuntu DEB available, since Saucy for PHP 5.5 53 | - http://packages.ubuntu.com/saucy/php5-json 54 | 55 | Fedora RPM are available in remi repo 56 | - http://blog.famillecollet.com/post/2013/06/04/php-pecl-json-1.3.0-en 57 | 58 | Windows build are available 59 | - http://windows.php.net/downloads/pecl/releases/jsonc/ 60 | - http://windows.php.net/downloads/pecl/deps/ 61 | 62 | Merged PR in upstream json-c library (release pending) 63 | - number must not have leading zeroes 64 | https://github.com/json-c/json-c/pull/90 65 | - string must be double-quoted 66 | - no comment in strict mode 67 | - no trailing char after data 68 | https://github.com/json-c/json-c/pull/94 69 | 70 | Pending PR in upstream json-c library 71 | - none 72 | 73 | > The world will not be destroyed by those who do evil, 74 | > but by those who watch them without doing anything. 75 | > -- Albert Einstein 76 | -------------------------------------------------------------------------------- /json-c/arraylist.c: -------------------------------------------------------------------------------- 1 | /* 2 | * $Id: arraylist.c,v 1.4 2006/01/26 02:16:28 mclark Exp $ 3 | * 4 | * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. 5 | * Michael Clark 6 | * 7 | * This library is free software; you can redistribute it and/or modify 8 | * it under the terms of the MIT license. See COPYING for details. 9 | * 10 | */ 11 | 12 | #include "config.h" 13 | 14 | #ifdef STDC_HEADERS 15 | # include 16 | # include 17 | #endif /* STDC_HEADERS */ 18 | 19 | #if defined(HAVE_STRINGS_H) && !defined(_STRING_H) && !defined(__USE_BSD) 20 | # include 21 | #endif /* HAVE_STRINGS_H */ 22 | 23 | #include "bits.h" 24 | #include "arraylist.h" 25 | 26 | struct array_list* 27 | array_list_new(array_list_free_fn *free_fn) 28 | { 29 | struct array_list *arr; 30 | 31 | arr = (struct array_list*)calloc(1, sizeof(struct array_list)); 32 | if(!arr) return NULL; 33 | arr->size = ARRAY_LIST_DEFAULT_SIZE; 34 | arr->length = 0; 35 | arr->free_fn = free_fn; 36 | if(!(arr->array = (void**)calloc(sizeof(void*), arr->size))) { 37 | free(arr); 38 | return NULL; 39 | } 40 | return arr; 41 | } 42 | 43 | extern void 44 | array_list_free(struct array_list *arr) 45 | { 46 | int i; 47 | for(i = 0; i < arr->length; i++) 48 | if(arr->array[i]) arr->free_fn(arr->array[i]); 49 | free(arr->array); 50 | free(arr); 51 | } 52 | 53 | void* 54 | array_list_get_idx(struct array_list *arr, int i) 55 | { 56 | if(i >= arr->length) return NULL; 57 | return arr->array[i]; 58 | } 59 | 60 | static int array_list_expand_internal(struct array_list *arr, int max) 61 | { 62 | void *t; 63 | int new_size; 64 | 65 | if(max < arr->size) return 0; 66 | new_size = json_max(arr->size << 1, max); 67 | if(!(t = realloc(arr->array, new_size*sizeof(void*)))) return -1; 68 | arr->array = (void**)t; 69 | (void)memset(arr->array + arr->size, 0, (new_size-arr->size)*sizeof(void*)); 70 | arr->size = new_size; 71 | return 0; 72 | } 73 | 74 | int 75 | array_list_put_idx(struct array_list *arr, int idx, void *data) 76 | { 77 | if(array_list_expand_internal(arr, idx+1)) return -1; 78 | if(arr->array[idx]) arr->free_fn(arr->array[idx]); 79 | arr->array[idx] = data; 80 | if(arr->length <= idx) arr->length = idx + 1; 81 | return 0; 82 | } 83 | 84 | int 85 | array_list_add(struct array_list *arr, void *data) 86 | { 87 | return array_list_put_idx(arr, arr->length, data); 88 | } 89 | 90 | void 91 | array_list_sort(struct array_list *arr, int(*sort_fn)(const void *, const void *)) 92 | { 93 | qsort(arr->array, arr->length, sizeof(arr->array[0]), 94 | (int (*)(const void *, const void *))sort_fn); 95 | } 96 | 97 | int 98 | array_list_length(struct array_list *arr) 99 | { 100 | return arr->length; 101 | } 102 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------- 2 | The PHP License, version 3.01 3 | Copyright (c) 1999 - 2012 The PHP Group. All rights reserved. 4 | -------------------------------------------------------------------- 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, is permitted provided that the following conditions 8 | are met: 9 | 10 | 1. Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | 13 | 2. Redistributions in binary form must reproduce the above copyright 14 | notice, this list of conditions and the following disclaimer in 15 | the documentation and/or other materials provided with the 16 | distribution. 17 | 18 | 3. The name "PHP" must not be used to endorse or promote products 19 | derived from this software without prior written permission. For 20 | written permission, please contact group@php.net. 21 | 22 | 4. Products derived from this software may not be called "PHP", nor 23 | may "PHP" appear in their name, without prior written permission 24 | from group@php.net. You may indicate that your software works in 25 | conjunction with PHP by saying "Foo for PHP" instead of calling 26 | it "PHP Foo" or "phpfoo" 27 | 28 | 5. The PHP Group may publish revised and/or new versions of the 29 | license from time to time. Each version will be given a 30 | distinguishing version number. 31 | Once covered code has been published under a particular version 32 | of the license, you may always continue to use it under the terms 33 | of that version. You may also choose to use such covered code 34 | under the terms of any subsequent version of the license 35 | published by the PHP Group. No one other than the PHP Group has 36 | the right to modify the terms applicable to covered code created 37 | under this License. 38 | 39 | 6. Redistributions of any form whatsoever must retain the following 40 | acknowledgment: 41 | "This product includes PHP software, freely available from 42 | ". 43 | 44 | THIS SOFTWARE IS PROVIDED BY THE PHP DEVELOPMENT TEAM ``AS IS'' AND 45 | ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 46 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 47 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PHP 48 | DEVELOPMENT TEAM OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 49 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 50 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 51 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 52 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 53 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 54 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 55 | OF THE POSSIBILITY OF SUCH DAMAGE. 56 | 57 | -------------------------------------------------------------------- 58 | 59 | This software consists of voluntary contributions made by many 60 | individuals on behalf of the PHP Group. 61 | 62 | The PHP Group can be contacted via Email at group@php.net. 63 | 64 | For more information on the PHP Group and the PHP project, 65 | please see . 66 | 67 | PHP includes the Zend Engine, freely available at 68 | . 69 | -------------------------------------------------------------------------------- /minitest.php: -------------------------------------------------------------------------------- 1 | prop1 = $val1; 8 | $this->prop2 = $val2; 9 | } 10 | } 11 | class MiniSer1 extends Mini implements JsonSerializable { 12 | public function jsonSerialize(){ 13 | return array("One" => $this->prop1, "Two" => $this->prop2); 14 | } 15 | } 16 | class MiniSer2 extends Mini implements JsonSerializable { 17 | public function jsonSerialize(){ 18 | return $this; 19 | } 20 | } 21 | 22 | echo "\nPHP Version: ".phpversion()."\n"; 23 | echo "Json Version: ".phpversion('json')."\n"; 24 | 25 | echo "\nEncode\n"; 26 | echo "\nNULL: ".json_encode(NULL); 27 | echo "\nTrue: ".json_encode(true); 28 | echo "\nFalse: ".json_encode(false); 29 | echo "\nInteger: ".json_encode(123); 30 | echo "\nAscii String: ".json_encode("foo"); 31 | echo "\nString 1: ".json_encode("x'x"); 32 | echo "\nString 2: ".json_encode('y"y'); 33 | echo "\nAscii String: ".json_encode("foo"); 34 | echo "\nUTF-8 String: ".json_encode("réunion"); 35 | echo "\nArray1: ".json_encode(array(2,4,6)); 36 | echo "\nArray2: ".json_encode(array(2,NULL,6)); 37 | echo "\nArray3: ".json_encode(array()); 38 | echo "\nArray as Obj: ".json_encode(array(2,4,6), JSON_FORCE_OBJECT); 39 | echo "\nObject1: ".json_encode(new Mini("foo", "bar")); 40 | echo "\nObject2: ".json_encode(new Mini("foo", NULL)); 41 | echo "\nObject Ser 1: ".json_encode(new MiniSer1("foo", "bar")); 42 | echo "\nObject Ser 2: ".json_encode(new MiniSer2("foo", "bar")); 43 | 44 | echo "\nDecode\n"; 45 | echo "null: "; var_dump(json_decode("null")); 46 | echo "123: "; var_dump(json_decode("123")); 47 | echo "3.14: "; var_dump(json_decode("3.14")); 48 | echo "true: "; var_dump(json_decode("true")); 49 | echo "false: "; var_dump(json_decode("false")); 50 | echo "string 1: "; var_dump(json_decode('"foo"')); 51 | echo "string 2: "; var_dump(json_decode('"r\u00e9union"')); 52 | echo "string 3: "; var_dump(json_decode('"x\'x"')); 53 | echo "string 4: "; var_dump(json_decode('"y\"y"')); 54 | echo "array 1: "; var_dump(json_decode('[2,4,6]')); 55 | echo "array 2: "; var_dump(json_decode('[2,null,6]')); 56 | echo "array 3: "; var_dump(json_decode('[]')); 57 | echo "Obj as array1:"; var_dump(json_decode('{"One":"foo","Two":"bar"}', true)); 58 | echo "Obj as array2:"; var_dump(json_decode('{"One":"foo","":"bar"}', true)); 59 | echo "Object 1: "; var_dump(json_decode('{"One":"foo","Two":"bar"}', false)); 60 | echo "Object 2: "; var_dump(json_decode('{"One":"foo","":"bar"}', false)); 61 | echo "BigInt 1: "; var_dump(json_decode("12345678901234567890")); 62 | echo "BigInt 2: "; var_dump(json_decode("12345678901234567890", true, 5, JSON_BIGINT_AS_STRING)); 63 | 64 | if (class_exists('JsonIncrementalParser')) { 65 | echo "\nJsonIncrementalParser\n"; 66 | $parser = new JsonIncrementalParser(); 67 | var_dump($parser->getError()); 68 | var_dump($parser->parse('"foo"')); 69 | var_dump($parser->get()); 70 | var_dump($parser->reset()); 71 | var_dump($parser->get()); 72 | var_dump($parser->parse('["foo",')); 73 | var_dump($parser->get()); 74 | var_dump($parser->parse('"bar"]')); 75 | var_dump($parser->get()); 76 | var_dump($parser->parse('{"One":"foo",')); 77 | var_dump($parser->parse('"Two":"bar"}')); 78 | var_dump($parser->get()); 79 | var_dump($parser->get(JSON_OBJECT_AS_ARRAY)); 80 | 81 | $txt = "/*\nTest file\n*/\n".json_encode(new Mini("foo", array("bar1", "bar2")), JSON_PRETTY_PRINT); 82 | file_put_contents(__DIR__.'/minitest.json', $txt); 83 | var_dump($parser->parseFile(__DIR__.'/minitest.json')); 84 | var_dump($parser->get()); 85 | } 86 | echo "\nDone\n"; 87 | -------------------------------------------------------------------------------- /config.m4: -------------------------------------------------------------------------------- 1 | dnl 2 | dnl $Id$ 3 | dnl 4 | 5 | PHP_ARG_ENABLE(json, whether to enable JavaScript Object Serialization support, 6 | [ --disable-json Disable JavaScript Object Serialization support (json.so)], yes) 7 | 8 | PHP_ARG_WITH(jsonc, whether to rename module file to jsonc, 9 | [ --with-jsonc JSON: rename module file to jsonc.so], no, no) 10 | 11 | PHP_ARG_WITH(libjson, libjson, 12 | [ --with-libjson JSON: use system json-c], no, no) 13 | 14 | PHP_ARG_ENABLE(rdrand, whether to enable RDRAND Hardware RNG Hash Seed generation on supported x86/x64 platforms, 15 | [ --disable-rdrand Disable RDRAND Hardware RNG Hash Seed generation on supported x86/x64 platforms], yes, no) 16 | 17 | if test "$PHP_JSON" != "no"; then 18 | AC_GNU_SOURCE 19 | AC_DEFINE([HAVE_JSON], 1 ,[whether to enable JavaScript Object Serialization support]) 20 | AC_HEADER_STDC 21 | 22 | if test "$PHP_LIBJSON" != "no"; then 23 | AC_MSG_ERROR(Build with system libjson-c is no more supported) 24 | 25 | AC_PATH_PROG(PKG_CONFIG, pkg-config, no) 26 | AC_MSG_CHECKING(JSON-C version) 27 | if test -x "$PKG_CONFIG" && $PKG_CONFIG --exists json-c; then 28 | LIBJSON_INCLUDE=`$PKG_CONFIG json-c --cflags` 29 | LIBJSON_LIBRARY=`$PKG_CONFIG json-c --libs` 30 | LIBJSON_VERSION=`$PKG_CONFIG json-c --modversion` 31 | fi 32 | 33 | if test -z "$LIBJSON_VERSION"; then 34 | AC_MSG_RESULT(version not found) 35 | AC_MSG_ERROR(Please reinstall json-c version >= 0.11) 36 | else 37 | AC_MSG_RESULT(version=$LIBJSON_VERSION include=$LIBJSON_INCLUDE library=$LIBJSON_LIBRARY) 38 | fi 39 | 40 | PHP_CHECK_LIBRARY(json-c, json_tokener_new_ex, 41 | [ 42 | AC_DEFINE_UNQUOTED(HAVE_LIBJSON, 1, [use system libjson-c]) 43 | ],[ 44 | AC_MSG_ERROR([Sorry, Incompatible json-c library, requires version >= 0.11]) 45 | ],[ 46 | $LIBJSON_LIBRARY 47 | ]) 48 | 49 | PHP_EVAL_INCLINE($LIBJSON_INCLUDE) 50 | PHP_EVAL_LIBLINE($LIBJSON_LIBRARY, JSONC_SHARED_LIBADD) 51 | PHP_EVAL_LIBLINE($LIBJSON_LIBRARY, JSON_SHARED_LIBADD) 52 | else 53 | AC_MSG_CHECKING([for working sscanf]) 54 | AC_TRY_RUN([ 55 | #include 56 | #include 57 | #include 58 | int main(int argc, char *argv[]){ 59 | long i; 60 | errno=0; 61 | return (sscanf("1234567890123456789012345","%ld",&i)==1 && errno==ERANGE && i==INT64_MAX ? 0 : 1); 62 | }],[ 63 | AC_MSG_RESULT([yes]) 64 | AC_DEFINE(HAS_SSCANF_ERANGE, 1, [Whether correctly return ERANGE]) 65 | ],[ 66 | AC_MSG_RESULT([no, not working]) 67 | ],[ 68 | AC_MSG_RESULT([no, not found]) 69 | ]) 70 | AC_CHECK_HEADERS(fcntl.h limits.h strings.h syslog.h unistd.h [sys/param.h] stdarg.h inttypes.h locale.h endian.h) 71 | AC_CHECK_FUNCS(strcasecmp strdup strndup strerror snprintf vsnprintf vasprintf open vsyslog strncasecmp setlocale) 72 | 73 | PHP_LIBJSON_SOURCES="json-c/arraylist.c \ 74 | json-c/debug.c \ 75 | json-c/json_c_version.c \ 76 | json-c/json_object.c \ 77 | json-c/json_object_iterator.c \ 78 | json-c/json_tokener.c \ 79 | json-c/json_util.c \ 80 | json-c/linkhash.c \ 81 | json-c/random_seed.c \ 82 | json-c/printbuf.c" 83 | fi 84 | 85 | if test "$PHP_RDRAND" != "no"; then 86 | AC_DEFINE(ENABLE_RDRAND, 1, [Enable RDRANR Hardware RNG Hash Seed]) 87 | fi 88 | 89 | AC_MSG_CHECKING(JSON extension name:) 90 | if test "$PHP_JSONC" != "no"; then 91 | AC_MSG_RESULT(jsonc) 92 | PHP_NEW_EXTENSION(jsonc, json.c $PHP_LIBJSON_SOURCES, $ext_shared) 93 | PHP_SUBST(JSONC_SHARED_LIBADD) 94 | else 95 | AC_MSG_RESULT(json) 96 | PHP_NEW_EXTENSION(json, json.c $PHP_LIBJSON_SOURCES, $ext_shared) 97 | PHP_SUBST(JSON_SHARED_LIBADD) 98 | fi 99 | 100 | PHP_INSTALL_HEADERS([ext/json], [php_json.h]) 101 | fi 102 | -------------------------------------------------------------------------------- /tests/json_decode_basic.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test json_decode() function : basic functionality 3 | --SKIPIF-- 4 | 9 | --FILE-- 10 | 51 | ===Done=== 52 | --EXPECTF-- 53 | *** Testing json_decode() : basic functionality *** 54 | -- Iteration 1 -- 55 | int(0) 56 | int(0) 57 | -- Iteration 2 -- 58 | int(123) 59 | int(123) 60 | -- Iteration 3 -- 61 | int(-123) 62 | int(-123) 63 | -- Iteration 4 -- 64 | int(2147483647) 65 | int(2147483647) 66 | -- Iteration 5 -- 67 | int(-2147483648) 68 | int(-2147483648) 69 | -- Iteration 6 -- 70 | float(123.456) 71 | float(123.456) 72 | -- Iteration 7 -- 73 | int(1230) 74 | int(1230) 75 | -- Iteration 8 -- 76 | int(-1230) 77 | int(-1230) 78 | -- Iteration 9 -- 79 | bool(true) 80 | bool(true) 81 | -- Iteration 10 -- 82 | bool(false) 83 | bool(false) 84 | -- Iteration 11 -- 85 | NULL 86 | NULL 87 | -- Iteration 12 -- 88 | string(3) "abc" 89 | string(3) "abc" 90 | -- Iteration 13 -- 91 | string(13) "Hello World 92 | " 93 | string(13) "Hello World 94 | " 95 | -- Iteration 14 -- 96 | array(0) { 97 | } 98 | array(0) { 99 | } 100 | -- Iteration 15 -- 101 | array(5) { 102 | [0]=> 103 | int(1) 104 | [1]=> 105 | int(2) 106 | [2]=> 107 | int(3) 108 | [3]=> 109 | int(4) 110 | [4]=> 111 | int(5) 112 | } 113 | array(5) { 114 | [0]=> 115 | int(1) 116 | [1]=> 117 | int(2) 118 | [2]=> 119 | int(3) 120 | [3]=> 121 | int(4) 122 | [4]=> 123 | int(5) 124 | } 125 | -- Iteration 16 -- 126 | object(stdClass)#%d (5) { 127 | ["myInt"]=> 128 | int(99) 129 | ["myFloat"]=> 130 | float(123.45) 131 | ["myNull"]=> 132 | NULL 133 | ["myBool"]=> 134 | bool(true) 135 | ["myString"]=> 136 | string(11) "Hello World" 137 | } 138 | array(5) { 139 | ["myInt"]=> 140 | int(99) 141 | ["myFloat"]=> 142 | float(123.45) 143 | ["myNull"]=> 144 | NULL 145 | ["myBool"]=> 146 | bool(true) 147 | ["myString"]=> 148 | string(11) "Hello World" 149 | } 150 | -- Iteration 17 -- 151 | object(stdClass)#%d (6) { 152 | ["Jan"]=> 153 | int(31) 154 | ["Feb"]=> 155 | int(29) 156 | ["Mar"]=> 157 | int(31) 158 | ["April"]=> 159 | int(30) 160 | ["May"]=> 161 | int(31) 162 | ["June"]=> 163 | int(30) 164 | } 165 | array(6) { 166 | ["Jan"]=> 167 | int(31) 168 | ["Feb"]=> 169 | int(29) 170 | ["Mar"]=> 171 | int(31) 172 | ["April"]=> 173 | int(30) 174 | ["May"]=> 175 | int(31) 176 | ["June"]=> 177 | int(30) 178 | } 179 | -- Iteration 18 -- 180 | string(0) "" 181 | string(0) "" 182 | -- Iteration 19 -- 183 | object(stdClass)#%d (0) { 184 | } 185 | array(0) { 186 | } 187 | ===Done=== 188 | -------------------------------------------------------------------------------- /tests/json_encode_basic.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test json_encode() function : basic functionality 3 | --SKIPIF-- 4 | 9 | --FILE-- 10 | MyInt = 99; 31 | $obj->MyFloat = 123.45; 32 | $obj->MyBool = true; 33 | $obj->MyNull = null; 34 | $obj->MyString = "Hello World"; 35 | 36 | // array with different values for $string 37 | $inputs = array ( 38 | 39 | // integers 40 | /*1*/ 0, 41 | 123, 42 | -123, 43 | 2147483647, 44 | -2147483648, 45 | 46 | // floats 47 | /*6*/ 123.456, 48 | 1.23E3, 49 | -1.23E3, 50 | 51 | // boolean 52 | /*9*/ TRUE, 53 | true, 54 | FALSE, 55 | false, 56 | 57 | // NULL 58 | /*13*/ NULL, 59 | null, 60 | 61 | // strings 62 | /*15*/ "abc", 63 | 'abc', 64 | "Hello\t\tWorld\n", 65 | 66 | // arrays 67 | /*18*/ array(), 68 | array(1,2,3,4,5), 69 | array(1 => "Sun", 2=>"Mon", 3 => "Tue", 4 => "Wed", 5 => "Thur", 6 => "Fri", 7 => "Sat"), 70 | array("Jan" => 31, "Feb" => 29, "Mar" => 31, "April" => 30, "May" => 31, "June" => 30), 71 | 72 | // empty data 73 | /*22*/ "", 74 | '', 75 | 76 | // undefined data 77 | /*24*/ @$undefined_var, 78 | 79 | // unset data 80 | /*25*/ @$unset_var, 81 | 82 | // resource variable 83 | /*26*/ $fp, 84 | 85 | // object variable 86 | /*27*/ $obj 87 | 88 | ); 89 | 90 | // loop through with each element of the $inputs array to test json_encode() function 91 | $count = 1; 92 | foreach($inputs as $input) { 93 | echo "-- Iteration $count --\n"; 94 | var_dump(json_encode($input)); 95 | $count ++; 96 | } 97 | 98 | ?> 99 | ===Done=== 100 | --EXPECTF-- 101 | *** Testing json_encode() : basic functionality *** 102 | -- Iteration 1 -- 103 | string(1) "0" 104 | -- Iteration 2 -- 105 | string(3) "123" 106 | -- Iteration 3 -- 107 | string(4) "-123" 108 | -- Iteration 4 -- 109 | string(10) "2147483647" 110 | -- Iteration 5 -- 111 | string(11) "-2147483648" 112 | -- Iteration 6 -- 113 | string(7) "123.456" 114 | -- Iteration 7 -- 115 | string(4) "1230" 116 | -- Iteration 8 -- 117 | string(5) "-1230" 118 | -- Iteration 9 -- 119 | string(4) "true" 120 | -- Iteration 10 -- 121 | string(4) "true" 122 | -- Iteration 11 -- 123 | string(5) "false" 124 | -- Iteration 12 -- 125 | string(5) "false" 126 | -- Iteration 13 -- 127 | string(4) "null" 128 | -- Iteration 14 -- 129 | string(4) "null" 130 | -- Iteration 15 -- 131 | string(5) ""abc"" 132 | -- Iteration 16 -- 133 | string(5) ""abc"" 134 | -- Iteration 17 -- 135 | string(18) ""Hello\t\tWorld\n"" 136 | -- Iteration 18 -- 137 | string(2) "[]" 138 | -- Iteration 19 -- 139 | string(11) "[1,2,3,4,5]" 140 | -- Iteration 20 -- 141 | string(72) "{"1":"Sun","2":"Mon","3":"Tue","4":"Wed","5":"Thur","6":"Fri","7":"Sat"}" 142 | -- Iteration 21 -- 143 | string(58) "{"Jan":31,"Feb":29,"Mar":31,"April":30,"May":31,"June":30}" 144 | -- Iteration 22 -- 145 | string(2) """" 146 | -- Iteration 23 -- 147 | string(2) """" 148 | -- Iteration 24 -- 149 | string(4) "null" 150 | -- Iteration 25 -- 151 | string(4) "null" 152 | -- Iteration 26 -- 153 | bool(false) 154 | -- Iteration 27 -- 155 | string(82) "{"MyInt":99,"MyFloat":123.45,"MyBool":true,"MyNull":null,"MyString":"Hello World"}" 156 | ===Done=== 157 | -------------------------------------------------------------------------------- /php_json.h: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------+ 3 | | PHP Version 5 | 4 | +----------------------------------------------------------------------+ 5 | | Copyright (c) 1997-2015 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 | | Authors: Omar Kilani | 16 | | Remi Collet | 17 | +----------------------------------------------------------------------+ 18 | */ 19 | 20 | /* $Id$ */ 21 | 22 | #ifndef PHP_JSON_H 23 | #define PHP_JSON_H 24 | 25 | #define PHP_JSON_VERSION "1.3.10" 26 | #include "ext/standard/php_smart_str.h" 27 | 28 | extern zend_module_entry json_module_entry; 29 | #define phpext_json_ptr &json_module_entry 30 | 31 | #if defined(PHP_WIN32) && defined(JSON_EXPORTS) 32 | #define PHP_JSON_API __declspec(dllexport) 33 | #else 34 | #define PHP_JSON_API PHPAPI 35 | #endif 36 | 37 | #ifdef ZTS 38 | #include "TSRM.h" 39 | #endif 40 | 41 | enum error_codes { 42 | PHP_JSON_ERROR_NONE = 0, 43 | PHP_JSON_ERROR_DEPTH, 44 | PHP_JSON_ERROR_STATE_MISMATCH, 45 | PHP_JSON_ERROR_CTRL_CHAR, 46 | PHP_JSON_ERROR_SYNTAX, 47 | PHP_JSON_ERROR_UTF8, 48 | PHP_JSON_ERROR_RECURSION, 49 | PHP_JSON_ERROR_INF_OR_NAN, 50 | PHP_JSON_ERROR_UNSUPPORTED_TYPE 51 | }; 52 | #define JSON_PARSER_DEFAULT_DEPTH 512 53 | 54 | ZEND_BEGIN_MODULE_GLOBALS(json) 55 | int encoder_depth; 56 | int error_code; 57 | int parser_code; 58 | int encode_max_depth; 59 | ZEND_END_MODULE_GLOBALS(json) 60 | 61 | #ifdef ZTS 62 | # define JSON_G(v) TSRMG(json_globals_id, zend_json_globals *, v) 63 | #else 64 | # define JSON_G(v) (json_globals.v) 65 | #endif 66 | 67 | PHP_JSON_API void php_json_encode(smart_str *buf, zval *val, int options TSRMLS_DC); 68 | PHP_JSON_API void php_json_decode_ex(zval *return_value, char *str, int str_len, int options, long depth TSRMLS_DC); 69 | extern PHP_JSON_API zend_class_entry *php_json_serializable_ce; 70 | 71 | 72 | /* json_encode() options */ 73 | #define PHP_JSON_HEX_TAG (1<<0) 74 | #define PHP_JSON_HEX_AMP (1<<1) 75 | #define PHP_JSON_HEX_APOS (1<<2) 76 | #define PHP_JSON_HEX_QUOT (1<<3) 77 | #define PHP_JSON_FORCE_OBJECT (1<<4) 78 | #define PHP_JSON_NUMERIC_CHECK (1<<5) 79 | #define PHP_JSON_UNESCAPED_SLASHES (1<<6) 80 | #define PHP_JSON_PRETTY_PRINT (1<<7) 81 | #define PHP_JSON_UNESCAPED_UNICODE (1<<8) 82 | #define PHP_JSON_PARTIAL_OUTPUT_ON_ERROR (1<<9) 83 | #define PHP_JSON_PRESERVE_ZERO_FRACTION (1<<10) 84 | 85 | /* Internal flags */ 86 | #define PHP_JSON_OUTPUT_ARRAY 0 87 | #define PHP_JSON_OUTPUT_OBJECT 1 88 | 89 | /* json_decode() options */ 90 | #define PHP_JSON_OBJECT_AS_ARRAY (1<<0) 91 | #define PHP_JSON_BIGINT_AS_STRING (1<<1) 92 | #define PHP_JSON_PARSER_NOTSTRICT (1<<2) 93 | 94 | static inline void php_json_decode(zval *return_value, char *str, int str_len, zend_bool assoc, long depth TSRMLS_DC) 95 | { 96 | php_json_decode_ex(return_value, str, str_len, assoc ? PHP_JSON_OBJECT_AS_ARRAY : 0, depth TSRMLS_CC); 97 | } 98 | 99 | 100 | #endif /* PHP_JSON_H */ 101 | 102 | /* 103 | * Local variables: 104 | * tab-width: 4 105 | * c-basic-offset: 4 106 | * End: 107 | * vim600: noet sw=4 ts=4 fdm=marker 108 | * vim<600: noet sw=4 ts=4 109 | */ 110 | -------------------------------------------------------------------------------- /json-c/printbuf.c: -------------------------------------------------------------------------------- 1 | /* 2 | * $Id: printbuf.c,v 1.5 2006/01/26 02:16:28 mclark Exp $ 3 | * 4 | * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. 5 | * Michael Clark 6 | * 7 | * This library is free software; you can redistribute it and/or modify 8 | * it under the terms of the MIT license. See COPYING for details. 9 | * 10 | * 11 | * Copyright (c) 2008-2009 Yahoo! Inc. All rights reserved. 12 | * The copyrights to the contents of this file are licensed under the MIT License 13 | * (http://www.opensource.org/licenses/mit-license.php) 14 | */ 15 | 16 | #include "config.h" 17 | 18 | #include 19 | #include 20 | #include 21 | 22 | #ifdef HAVE_STDARG_H 23 | # include 24 | #else /* !HAVE_STDARG_H */ 25 | # error Not enough var arg support! 26 | #endif /* HAVE_STDARG_H */ 27 | 28 | #include "bits.h" 29 | #include "debug.h" 30 | #include "printbuf.h" 31 | 32 | static int printbuf_extend(struct printbuf *p, int min_size); 33 | 34 | struct printbuf* printbuf_new(void) 35 | { 36 | struct printbuf *p; 37 | 38 | p = (struct printbuf*)calloc(1, sizeof(struct printbuf)); 39 | if(!p) return NULL; 40 | p->size = 32; 41 | p->bpos = 0; 42 | if(!(p->buf = (char*)malloc(p->size))) { 43 | free(p); 44 | return NULL; 45 | } 46 | return p; 47 | } 48 | 49 | 50 | /** 51 | * Extend the buffer p so it has a size of at least min_size. 52 | * 53 | * If the current size is large enough, nothing is changed. 54 | * 55 | * Note: this does not check the available space! The caller 56 | * is responsible for performing those calculations. 57 | */ 58 | static int printbuf_extend(struct printbuf *p, int min_size) 59 | { 60 | char *t; 61 | int new_size; 62 | 63 | if (p->size >= min_size) 64 | return 0; 65 | 66 | new_size = json_max(p->size * 2, min_size + 8); 67 | #ifdef PRINTBUF_DEBUG 68 | MC_DEBUG("printbuf_memappend: realloc " 69 | "bpos=%d min_size=%d old_size=%d new_size=%d\n", 70 | p->bpos, min_size, p->size, new_size); 71 | #endif /* PRINTBUF_DEBUG */ 72 | if(!(t = (char*)realloc(p->buf, new_size))) 73 | return -1; 74 | p->size = new_size; 75 | p->buf = t; 76 | return 0; 77 | } 78 | 79 | int printbuf_memappend(struct printbuf *p, const char *buf, int size) 80 | { 81 | if (p->size <= p->bpos + size + 1) { 82 | if (printbuf_extend(p, p->bpos + size + 1) < 0) 83 | return -1; 84 | } 85 | memcpy(p->buf + p->bpos, buf, size); 86 | p->bpos += size; 87 | p->buf[p->bpos]= '\0'; 88 | return size; 89 | } 90 | 91 | int printbuf_memset(struct printbuf *pb, int offset, int charvalue, int len) 92 | { 93 | int size_needed; 94 | 95 | if (offset == -1) 96 | offset = pb->bpos; 97 | size_needed = offset + len; 98 | if (pb->size < size_needed) 99 | { 100 | if (printbuf_extend(pb, size_needed) < 0) 101 | return -1; 102 | } 103 | 104 | memset(pb->buf + offset, charvalue, len); 105 | if (pb->bpos < size_needed) 106 | pb->bpos = size_needed; 107 | 108 | return 0; 109 | } 110 | 111 | #if !defined(HAVE_VSNPRINTF) && defined(_MSC_VER) 112 | # define vsnprintf _vsnprintf 113 | #elif !defined(HAVE_VSNPRINTF) /* !HAVE_VSNPRINTF */ 114 | # error Need vsnprintf! 115 | #endif /* !HAVE_VSNPRINTF && defined(WIN32) */ 116 | 117 | #if !defined(HAVE_VASPRINTF) 118 | /* CAW: compliant version of vasprintf */ 119 | static int vasprintf(char **buf, const char *fmt, va_list ap) 120 | { 121 | #ifndef WIN32 122 | static char _T_emptybuffer = '\0'; 123 | #endif /* !defined(WIN32) */ 124 | int chars; 125 | char *b; 126 | 127 | if(!buf) { return -1; } 128 | 129 | #ifdef WIN32 130 | chars = _vscprintf(fmt, ap)+1; 131 | #else /* !defined(WIN32) */ 132 | /* CAW: RAWR! We have to hope to god here that vsnprintf doesn't overwrite 133 | our buffer like on some 64bit sun systems.... but hey, its time to move on */ 134 | chars = vsnprintf(&_T_emptybuffer, 0, fmt, ap)+1; 135 | if(chars < 0) { chars *= -1; } /* CAW: old glibc versions have this problem */ 136 | #endif /* defined(WIN32) */ 137 | 138 | b = (char*)malloc(sizeof(char)*chars); 139 | if(!b) { return -1; } 140 | 141 | if((chars = vsprintf(b, fmt, ap)) < 0) 142 | { 143 | free(b); 144 | } else { 145 | *buf = b; 146 | } 147 | 148 | return chars; 149 | } 150 | #endif /* !HAVE_VASPRINTF */ 151 | 152 | int sprintbuf(struct printbuf *p, const char *msg, ...) 153 | { 154 | va_list ap; 155 | char *t; 156 | int size; 157 | char buf[128]; 158 | 159 | /* user stack buffer first */ 160 | va_start(ap, msg); 161 | size = vsnprintf(buf, 128, msg, ap); 162 | va_end(ap); 163 | /* if string is greater than stack buffer, then use dynamic string 164 | with vasprintf. Note: some implementation of vsnprintf return -1 165 | if output is truncated whereas some return the number of bytes that 166 | would have been written - this code handles both cases. */ 167 | if(size == -1 || size > 127) { 168 | va_start(ap, msg); 169 | if((size = vasprintf(&t, msg, ap)) < 0) { va_end(ap); return -1; } 170 | va_end(ap); 171 | printbuf_memappend(p, t, size); 172 | free(t); 173 | return size; 174 | } else { 175 | printbuf_memappend(p, buf, size); 176 | return size; 177 | } 178 | } 179 | 180 | void printbuf_reset(struct printbuf *p) 181 | { 182 | p->buf[0] = '\0'; 183 | p->bpos = 0; 184 | } 185 | 186 | void printbuf_free(struct printbuf *p) 187 | { 188 | if(p) { 189 | free(p->buf); 190 | free(p); 191 | } 192 | } 193 | -------------------------------------------------------------------------------- /json-c/json_object_iterator.c: -------------------------------------------------------------------------------- 1 | /** 2 | ******************************************************************************* 3 | * @file json_object_iterator.c 4 | * 5 | * Copyright (c) 2009-2012 Hewlett-Packard Development Company, L.P. 6 | * 7 | * This library is free software; you can redistribute it and/or modify 8 | * it under the terms of the MIT license. See COPYING for details. 9 | * 10 | * @brief json-c forces clients to use its private data 11 | * structures for JSON Object iteration. This API 12 | * implementation corrects that by abstracting the 13 | * private json-c details. 14 | * 15 | ******************************************************************************* 16 | */ 17 | 18 | #include 19 | 20 | #include "json.h" 21 | #include "json_object_private.h" 22 | 23 | #include "json_object_iterator.h" 24 | 25 | /** 26 | * How It Works 27 | * 28 | * For each JSON Object, json-c maintains a linked list of zero 29 | * or more lh_entry (link-hash entry) structures inside the 30 | * Object's link-hash table (lh_table). 31 | * 32 | * Each lh_entry structure on the JSON Object's linked list 33 | * represents a single name/value pair. The "next" field of the 34 | * last lh_entry in the list is set to NULL, which terminates 35 | * the list. 36 | * 37 | * We represent a valid iterator that refers to an actual 38 | * name/value pair via a pointer to the pair's lh_entry 39 | * structure set as the iterator's opaque_ field. 40 | * 41 | * We follow json-c's current pair list representation by 42 | * representing a valid "end" iterator (one that refers past the 43 | * last pair) with a NULL value in the iterator's opaque_ field. 44 | * 45 | * A JSON Object without any pairs in it will have the "head" 46 | * field of its lh_table structure set to NULL. For such an 47 | * object, json_object_iter_begin will return an iterator with 48 | * the opaque_ field set to NULL, which is equivalent to the 49 | * "end" iterator. 50 | * 51 | * When iterating, we simply update the iterator's opaque_ field 52 | * to point to the next lh_entry structure in the linked list. 53 | * opaque_ will become NULL once we iterate past the last pair 54 | * in the list, which makes the iterator equivalent to the "end" 55 | * iterator. 56 | */ 57 | 58 | /// Our current representation of the "end" iterator; 59 | /// 60 | /// @note May not always be NULL 61 | static const void* kObjectEndIterValue = NULL; 62 | 63 | /** 64 | * **************************************************************************** 65 | */ 66 | struct json_object_iterator 67 | json_object_iter_begin(struct json_object* obj) 68 | { 69 | struct json_object_iterator iter; 70 | struct lh_table* pTable; 71 | 72 | /// @note json_object_get_object will return NULL if passed NULL 73 | /// or a non-json_type_object instance 74 | pTable = json_object_get_object(obj); 75 | JASSERT(NULL != pTable); 76 | 77 | /// @note For a pair-less Object, head is NULL, which matches our 78 | /// definition of the "end" iterator 79 | iter.opaque_ = pTable->head; 80 | return iter; 81 | } 82 | 83 | /** 84 | * **************************************************************************** 85 | */ 86 | struct json_object_iterator 87 | json_object_iter_end(const struct json_object* obj) 88 | { 89 | struct json_object_iterator iter; 90 | 91 | JASSERT(NULL != obj); 92 | JASSERT(json_object_is_type(obj, json_type_object)); 93 | 94 | iter.opaque_ = kObjectEndIterValue; 95 | 96 | return iter; 97 | } 98 | 99 | /** 100 | * **************************************************************************** 101 | */ 102 | void 103 | json_object_iter_next(struct json_object_iterator* iter) 104 | { 105 | JASSERT(NULL != iter); 106 | JASSERT(kObjectEndIterValue != iter->opaque_); 107 | 108 | iter->opaque_ = ((struct lh_entry *)iter->opaque_)->next; 109 | } 110 | 111 | 112 | /** 113 | * **************************************************************************** 114 | */ 115 | const char* 116 | json_object_iter_peek_name(const struct json_object_iterator* iter) 117 | { 118 | JASSERT(NULL != iter); 119 | JASSERT(kObjectEndIterValue != iter->opaque_); 120 | 121 | return (const char*)(((struct lh_entry *)iter->opaque_)->k); 122 | } 123 | 124 | 125 | /** 126 | * **************************************************************************** 127 | */ 128 | struct json_object* 129 | json_object_iter_peek_value(const struct json_object_iterator* iter) 130 | { 131 | JASSERT(NULL != iter); 132 | JASSERT(kObjectEndIterValue != iter->opaque_); 133 | 134 | return (struct json_object*)(((struct lh_entry *)iter->opaque_)->v); 135 | } 136 | 137 | 138 | /** 139 | * **************************************************************************** 140 | */ 141 | json_bool 142 | json_object_iter_equal(const struct json_object_iterator* iter1, 143 | const struct json_object_iterator* iter2) 144 | { 145 | JASSERT(NULL != iter1); 146 | JASSERT(NULL != iter2); 147 | 148 | return (iter1->opaque_ == iter2->opaque_); 149 | } 150 | 151 | 152 | /** 153 | * **************************************************************************** 154 | */ 155 | struct json_object_iterator 156 | json_object_iter_init_default(void) 157 | { 158 | struct json_object_iterator iter; 159 | 160 | /** 161 | * @note Make this a negative, invalid value, such that 162 | * accidental access to it would likely be trapped by the 163 | * hardware as an invalid address. 164 | */ 165 | iter.opaque_ = NULL; 166 | 167 | return iter; 168 | } 169 | -------------------------------------------------------------------------------- /json-c/random_seed.c: -------------------------------------------------------------------------------- 1 | /* 2 | * random_seed.c 3 | * 4 | * Copyright (c) 2013 Metaparadigm Pte. Ltd. 5 | * Michael Clark 6 | * 7 | * This library is free software; you can redistribute it and/or modify 8 | * it under the terms of the MIT license. See COPYING for details. 9 | * 10 | */ 11 | 12 | #include 13 | #include "config.h" 14 | 15 | #define DEBUG_SEED(s) 16 | 17 | 18 | #if defined ENABLE_RDRAND 19 | 20 | /* cpuid */ 21 | 22 | #if defined __GNUC__ && (defined __i386__ || defined __x86_64__) 23 | #define HAS_X86_CPUID 1 24 | 25 | static void do_cpuid(int regs[], int h) 26 | { 27 | __asm__ __volatile__( 28 | #if defined __x86_64__ 29 | "pushq %%rbx;\n" 30 | #else 31 | "pushl %%ebx;\n" 32 | #endif 33 | "cpuid;\n" 34 | #if defined __x86_64__ 35 | "popq %%rbx;\n" 36 | #else 37 | "popl %%ebx;\n" 38 | #endif 39 | : "=a"(regs[0]), [ebx] "=r"(regs[1]), "=c"(regs[2]), "=d"(regs[3]) 40 | : "a"(h)); 41 | } 42 | 43 | #elif defined _MSC_VER 44 | 45 | #define HAS_X86_CPUID 1 46 | #define do_cpuid __cpuid 47 | 48 | #endif 49 | 50 | /* has_rdrand */ 51 | 52 | #if HAS_X86_CPUID 53 | 54 | static int has_rdrand() 55 | { 56 | // CPUID.01H:ECX.RDRAND[bit 30] == 1 57 | int regs[4]; 58 | do_cpuid(regs, 1); 59 | return (regs[2] & (1 << 30)) != 0; 60 | } 61 | 62 | #endif 63 | 64 | /* get_rdrand_seed - GCC x86 and X64 */ 65 | 66 | #if defined __GNUC__ && (defined __i386__ || defined __x86_64__) 67 | 68 | #define HAVE_RDRAND 1 69 | 70 | static int get_rdrand_seed() 71 | { 72 | DEBUG_SEED("get_rdrand_seed"); 73 | int _eax; 74 | // rdrand eax 75 | __asm__ __volatile__("1: .byte 0x0F\n" 76 | " .byte 0xC7\n" 77 | " .byte 0xF0\n" 78 | " jnc 1b;\n" 79 | : "=a" (_eax)); 80 | return _eax; 81 | } 82 | 83 | #endif 84 | 85 | #if defined _MSC_VER 86 | 87 | #if _MSC_VER >= 1700 88 | #define HAVE_RDRAND 1 89 | 90 | /* get_rdrand_seed - Visual Studio 2012 and above */ 91 | 92 | static int get_rdrand_seed() 93 | { 94 | DEBUG_SEED("get_rdrand_seed"); 95 | int r; 96 | while (_rdrand32_step(&r) == 0); 97 | return r; 98 | } 99 | 100 | #elif defined _M_IX86 101 | #define HAVE_RDRAND 1 102 | 103 | /* get_rdrand_seed - Visual Studio 2010 and below - x86 only */ 104 | 105 | static int get_rdrand_seed() 106 | { 107 | DEBUG_SEED("get_rdrand_seed"); 108 | int _eax; 109 | retry: 110 | // rdrand eax 111 | __asm _emit 0x0F __asm _emit 0xC7 __asm _emit 0xF0 112 | __asm jnc retry 113 | __asm mov _eax, eax 114 | return _eax; 115 | } 116 | 117 | #endif 118 | #endif 119 | 120 | #endif /* defined ENABLE_RDRAND */ 121 | 122 | 123 | /* has_dev_urandom */ 124 | 125 | #if defined (__APPLE__) || defined(__unix__) || defined(__linux__) 126 | 127 | #include 128 | #include 129 | #include 130 | #include 131 | #include 132 | #include 133 | 134 | #define HAVE_DEV_RANDOM 1 135 | 136 | static const char *dev_random_file = "/dev/urandom"; 137 | 138 | static int has_dev_urandom() 139 | { 140 | struct stat buf; 141 | if (stat(dev_random_file, &buf)) { 142 | return 0; 143 | } 144 | return ((buf.st_mode & S_IFCHR) != 0); 145 | } 146 | 147 | 148 | /* get_dev_random_seed */ 149 | 150 | static int get_dev_random_seed() 151 | { 152 | DEBUG_SEED("get_dev_random_seed"); 153 | 154 | int fd = open(dev_random_file, O_RDONLY); 155 | if (fd < 0) { 156 | fprintf(stderr, "error opening %s: %s", dev_random_file, strerror(errno)); 157 | exit(1); 158 | } 159 | 160 | int r; 161 | ssize_t nread = read(fd, &r, sizeof(r)); 162 | if (nread != sizeof(r)) { 163 | fprintf(stderr, "error read %s: %s", dev_random_file, strerror(errno)); 164 | exit(1); 165 | } 166 | else if (nread != sizeof(r)) { 167 | fprintf(stderr, "error short read %s", dev_random_file); 168 | exit(1); 169 | } 170 | close(fd); 171 | return r; 172 | } 173 | 174 | #endif 175 | 176 | 177 | /* get_cryptgenrandom_seed */ 178 | 179 | #ifdef WIN32 180 | 181 | #define HAVE_CRYPTGENRANDOM 1 182 | 183 | #include 184 | #pragma comment(lib, "advapi32.lib") 185 | 186 | static int get_cryptgenrandom_seed() 187 | { 188 | DEBUG_SEED("get_cryptgenrandom_seed"); 189 | 190 | HCRYPTPROV hProvider = 0; 191 | int r; 192 | 193 | if (!CryptAcquireContextW(&hProvider, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) { 194 | fprintf(stderr, "error CryptAcquireContextW"); 195 | exit(1); 196 | } 197 | 198 | if (!CryptGenRandom(hProvider, sizeof(r), (BYTE*)&r)) { 199 | fprintf(stderr, "error CryptGenRandom"); 200 | exit(1); 201 | } 202 | 203 | CryptReleaseContext(hProvider, 0); 204 | 205 | return r; 206 | } 207 | 208 | #endif 209 | 210 | 211 | /* get_time_seed */ 212 | 213 | #include 214 | 215 | static int get_time_seed() 216 | { 217 | DEBUG_SEED("get_time_seed"); 218 | 219 | return (int)time(NULL) * 433494437; 220 | } 221 | 222 | 223 | /* json_c_get_random_seed */ 224 | 225 | int json_c_get_random_seed() 226 | { 227 | #if HAVE_RDRAND 228 | if (has_rdrand()) return get_rdrand_seed(); 229 | #endif 230 | #if HAVE_DEV_RANDOM 231 | if (has_dev_urandom()) return get_dev_random_seed(); 232 | #endif 233 | #if HAVE_CRYPTGENRANDOM 234 | return get_cryptgenrandom_seed(); 235 | #endif 236 | return get_time_seed(); 237 | } 238 | -------------------------------------------------------------------------------- /tests/fail001.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | JSON (http://www.crockford.com/JSON/JSON_checker/test/fail*.json) 3 | --SKIPIF-- 4 | 0.11') 9 | ?> 10 | --FILE-- 11 | 48 | --EXPECT-- 49 | Testing: "A JSON payload should be an object or array, not a string." 50 | AS OBJECT 51 | string(58) "A JSON payload should be an object or array, not a string." 52 | AS ARRAY 53 | string(58) "A JSON payload should be an object or array, not a string." 54 | Testing: ["Unclosed array" 55 | AS OBJECT 56 | NULL 57 | AS ARRAY 58 | NULL 59 | Testing: {unquoted_key: "keys must be quoted} 60 | AS OBJECT 61 | NULL 62 | AS ARRAY 63 | NULL 64 | Testing: ["extra comma",] 65 | AS OBJECT 66 | NULL 67 | AS ARRAY 68 | NULL 69 | Testing: ["double extra comma",,] 70 | AS OBJECT 71 | NULL 72 | AS ARRAY 73 | NULL 74 | Testing: [ , "<-- missing value"] 75 | AS OBJECT 76 | NULL 77 | AS ARRAY 78 | NULL 79 | Testing: ["Comma after the close"], 80 | AS OBJECT 81 | NULL 82 | AS ARRAY 83 | NULL 84 | Testing: ["Extra close"]] 85 | AS OBJECT 86 | NULL 87 | AS ARRAY 88 | NULL 89 | Testing: {"Extra comma": true,} 90 | AS OBJECT 91 | NULL 92 | AS ARRAY 93 | NULL 94 | Testing: {"Extra value after close": true} "misplaced quoted value" 95 | AS OBJECT 96 | NULL 97 | AS ARRAY 98 | NULL 99 | Testing: {"Illegal expression": 1 + 2} 100 | AS OBJECT 101 | NULL 102 | AS ARRAY 103 | NULL 104 | Testing: {"Illegal invocation": alert()} 105 | AS OBJECT 106 | NULL 107 | AS ARRAY 108 | NULL 109 | Testing: {"Numbers cannot have leading zeroes": 013} 110 | AS OBJECT 111 | NULL 112 | AS ARRAY 113 | NULL 114 | Testing: {"Numbers cannot be hex": 0x14} 115 | AS OBJECT 116 | NULL 117 | AS ARRAY 118 | NULL 119 | Testing: ["Illegal backslash escape: \x15"] 120 | AS OBJECT 121 | NULL 122 | AS ARRAY 123 | NULL 124 | Testing: ["Illegal backslash escape: \'"] 125 | AS OBJECT 126 | NULL 127 | AS ARRAY 128 | NULL 129 | Testing: ["Illegal backslash escape: \017"] 130 | AS OBJECT 131 | NULL 132 | AS ARRAY 133 | NULL 134 | Testing: [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[["Too deep"]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]] 135 | AS OBJECT 136 | NULL 137 | AS ARRAY 138 | NULL 139 | Testing: {"Missing colon" null} 140 | AS OBJECT 141 | NULL 142 | AS ARRAY 143 | NULL 144 | Testing: {"Double colon":: null} 145 | AS OBJECT 146 | NULL 147 | AS ARRAY 148 | NULL 149 | Testing: {"Comma instead of colon", null} 150 | AS OBJECT 151 | NULL 152 | AS ARRAY 153 | NULL 154 | Testing: ["Colon instead of comma": false] 155 | AS OBJECT 156 | NULL 157 | AS ARRAY 158 | NULL 159 | Testing: ["Bad value", truth] 160 | AS OBJECT 161 | NULL 162 | AS ARRAY 163 | NULL 164 | Testing: ['single quote'] 165 | AS OBJECT 166 | NULL 167 | AS ARRAY 168 | NULL 169 | 170 | -------------------------------------------------------------------------------- /STATUS: -------------------------------------------------------------------------------- 1 | 2 | ===================================================================== 3 | PHP : /usr/bin/php 4 | PHP_SAPI : cli 5 | PHP_VERSION : 5.5.3 6 | ZEND_VERSION: 2.5.0 7 | PHP_OS : Linux - Linux schrodingerscat.famillecollet.com 3.10.7-200.fc19.x86_64 #1 SMP Thu Aug 15 23:19:45 UTC 2013 x86_64 8 | INI actual : /work/GIT/pecl-json-c 9 | More .INIs : 10 | CWD : /work/GIT/pecl-json-c 11 | Extra dirs : 12 | VALGRIND : Not used 13 | ===================================================================== 14 | TIME START 2013-08-23 12:08:47 15 | ===================================================================== 16 | PASS json_decode() tests [tests/001.phpt] 17 | PASS json_encode() tests [tests/002.phpt] 18 | PASS json_encode() & endless loop - 1 [tests/003.phpt] 19 | PASS json_encode() & endless loop - 2 [tests/004.phpt] 20 | PASS json_encode() & endless loop - 3 [tests/005.phpt] 21 | PASS json_encode() & extended encoding [tests/006.phpt] 22 | PASS json_last_error() tests [tests/007-jsonc.phpt] 23 | XFAIL json_last_error() tests [tests/007.phpt] XFAIL REASON: Different parser, so different error codes. 24 | PASS json_decode() with large integers [tests/008-jsonc.phpt] 25 | XFAIL json_decode() with large integers [tests/008.phpt] XFAIL REASON: Large number always treat as integer. 26 | PASS JsonIncremantalParser::parse() simple test [tests/009-incrementalparser.phpt] 27 | PASS JsonIncremantalParser::parseFile() test [tests/010-incrementalparserfile.phpt] 28 | PASS JsonIncremantalParser::parseFile() test [tests/011-comments.phpt] 29 | PASS Bug #40503 (json_encode() value corruption on 32bit systems with overflown values) [tests/bug40503.phpt] 30 | PASS Bug #41034 (json_encode() ignores null byte started keys in arrays) [tests/bug41034.phpt] 31 | PASS Bug #41067 (json_encode() problem with UTF-16 input) [tests/bug41067.phpt] 32 | PASS Bug #41403 (json_decode cannot decode floats if localeconv decimal_point is not '.') [tests/bug41403.phpt] 33 | PASS Bug #41504 (json_decode() converts empty array keys to "_empty_") [tests/bug41504.phpt] 34 | PASS Bug #41567 (json_encode() double conversion is inconsistent with PHP) [tests/bug41567.phpt] 35 | PASS Bug #42090 (json_decode causes segmentation fault) [tests/bug42090.phpt] 36 | PASS Bug #42785 (Incorrect formatting of double values with non-english locales) [tests/bug42785.phpt] 37 | PASS Bug #43941 (json_encode() invalid UTF-8) [tests/bug43941.phpt] 38 | PASS Bug #45791 (json_decode() does not handle number 0e0) [tests/bug45791.phpt] 39 | PASS Bug #46215 (json_encode mutates its parameter and has some class-specific state) [tests/bug46215.phpt] 40 | PASS Bug #46944 (json_encode() doesn't handle 3 byte utf8 correctly) [tests/bug46944.phpt] 41 | PASS Bug #47644 (valid large integers are truncated) [tests/bug47644.phpt] 42 | PASS bug #53946 (json_encode() with JSON_UNESCAPED_UNICODE) [tests/bug53946.phpt] 43 | PASS Bug #54058 (json_last_error() invalid UTF-8 produces wrong error) [tests/bug54058.phpt] 44 | PASS Bug #54484 (Empty string in json_decode doesn't reset json_last_error) [tests/bug54484.phpt] 45 | PASS Bug #55543 (json_encode() with JSON_NUMERIC_CHECK & numeric string properties) [tests/bug55543.phpt] 46 | PASS Bug #61537 (json_encode() incorrectly truncates/discards information) [tests/bug61537.phpt] 47 | PASS Bug #61978 (Object recursion not detected for classes that implement JsonSerializable) [tests/bug61978.phpt] 48 | PASS FR #62369 (Segfault on json_encode(deeply_nested_array) [tests/bug62369.phpt] 49 | PASS json_decode() with max recursion depth [tests/depth.phpt] 50 | PASS JSON (http://www.crockford.com/JSON/JSON_checker/test/fail*.json) [tests/fail001.phpt] 51 | PASS An error is thrown when INF or NaN are encoded [tests/inf_nan_error.phpt] 52 | PASS Test json_decode() function : basic functionality [tests/json_decode_basic.phpt] 53 | PASS Test json_decode() function : error conditions [tests/json_decode_error.phpt] 54 | PASS Test json_encode() function : basic functionality [tests/json_encode_basic.phpt] 55 | PASS Test json_encode() function : basic functionality with UTF8 string input [tests/json_encode_basic_utf8.phpt] 56 | PASS Test json_encode() function : error conditions [tests/json_encode_error.phpt] 57 | PASS Test json_encode() function with numeric flag [tests/json_encode_numeric.phpt] 58 | PASS json_encode() with JSON_PRETTY_PRINT [tests/json_encode_pretty_print.phpt] 59 | PASS json_decode() tests [tests/json_encode_unescaped_slashes.phpt] 60 | PASS json_decode() with comments [tests/jsonp.phpt] 61 | SKIP JSON (http://www.crockford.com/JSON/JSON_checker/test/pass1.json) [tests/pass001.1.phpt] reason: this test is for 32bit platform only 62 | PASS JSON (http://www.crockford.com/JSON/JSON_checker/test/pass1.json) [tests/pass001.1_64bit.phpt] 63 | PASS JSON (http://www.crockford.com/JSON/JSON_checker/test/pass1.json) [tests/pass001.phpt] 64 | PASS JSON (http://www.crockford.com/JSON/JSON_checker/test/pass2.json) [tests/pass002.phpt] 65 | PASS JSON (http://www.crockford.com/JSON/JSON_checker/test/pass3.json) [tests/pass003.phpt] 66 | PASS json_encode() Serialization tests [tests/serialize.phpt] 67 | PASS An error is thrown when an unsupported type is encoded [tests/unsupported_type_error.phpt] 68 | ===================================================================== 69 | TIME END 2013-08-23 12:08:49 70 | 71 | ===================================================================== 72 | TEST RESULT SUMMARY 73 | --------------------------------------------------------------------- 74 | Exts skipped : 0 75 | Exts tested : 17 76 | --------------------------------------------------------------------- 77 | 78 | Number of tests : 52 51 79 | Tests skipped : 1 ( 1.9%) -------- 80 | Tests warned : 0 ( 0.0%) ( 0.0%) 81 | Tests failed : 0 ( 0.0%) ( 0.0%) 82 | Expected fail : 2 ( 3.8%) ( 3.9%) 83 | Tests passed : 49 ( 94.2%) ( 96.1%) 84 | --------------------------------------------------------------------- 85 | Time taken : 2 seconds 86 | ===================================================================== 87 | 88 | ===================================================================== 89 | EXPECTED FAILED TEST SUMMARY 90 | --------------------------------------------------------------------- 91 | json_last_error() tests [tests/007.phpt] XFAIL REASON: Different parser, so different error codes. 92 | json_decode() with large integers [tests/008.phpt] XFAIL REASON: Large number always treat as integer. 93 | ===================================================================== 94 | -------------------------------------------------------------------------------- /json-c/linkhash.h: -------------------------------------------------------------------------------- 1 | /* 2 | * $Id: linkhash.h,v 1.6 2006/01/30 23:07:57 mclark Exp $ 3 | * 4 | * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. 5 | * Michael Clark 6 | * Copyright (c) 2009 Hewlett-Packard Development Company, L.P. 7 | * 8 | * This library is free software; you can redistribute it and/or modify 9 | * it under the terms of the MIT license. See COPYING for details. 10 | * 11 | */ 12 | 13 | #ifndef _linkhash_h_ 14 | #define _linkhash_h_ 15 | 16 | #include "json_object.h" 17 | 18 | #ifdef __cplusplus 19 | extern "C" { 20 | #endif 21 | 22 | /** 23 | * golden prime used in hash functions 24 | */ 25 | #define LH_PRIME 0x9e370001UL 26 | 27 | /** 28 | * The fraction of filled hash buckets until an insert will cause the table 29 | * to be resized. 30 | * This can range from just above 0 up to 1.0. 31 | */ 32 | #define LH_LOAD_FACTOR 0.66 33 | 34 | /** 35 | * sentinel pointer value for empty slots 36 | */ 37 | #define LH_EMPTY (void*)-1 38 | 39 | /** 40 | * sentinel pointer value for freed slots 41 | */ 42 | #define LH_FREED (void*)-2 43 | 44 | struct lh_entry; 45 | 46 | /** 47 | * callback function prototypes 48 | */ 49 | typedef void (lh_entry_free_fn) (struct lh_entry *e); 50 | /** 51 | * callback function prototypes 52 | */ 53 | typedef unsigned long (lh_hash_fn) (const void *k); 54 | /** 55 | * callback function prototypes 56 | */ 57 | typedef int (lh_equal_fn) (const void *k1, const void *k2); 58 | 59 | /** 60 | * An entry in the hash table 61 | */ 62 | struct lh_entry { 63 | /** 64 | * The key. 65 | */ 66 | void *k; 67 | /** 68 | * The value. 69 | */ 70 | const void *v; 71 | /** 72 | * The next entry 73 | */ 74 | struct lh_entry *next; 75 | /** 76 | * The previous entry. 77 | */ 78 | struct lh_entry *prev; 79 | }; 80 | 81 | 82 | /** 83 | * The hash table structure. 84 | */ 85 | struct lh_table { 86 | /** 87 | * Size of our hash. 88 | */ 89 | int size; 90 | /** 91 | * Numbers of entries. 92 | */ 93 | int count; 94 | 95 | /** 96 | * Number of collisions. 97 | */ 98 | int collisions; 99 | 100 | /** 101 | * Number of resizes. 102 | */ 103 | int resizes; 104 | 105 | /** 106 | * Number of lookups. 107 | */ 108 | int lookups; 109 | 110 | /** 111 | * Number of inserts. 112 | */ 113 | int inserts; 114 | 115 | /** 116 | * Number of deletes. 117 | */ 118 | int deletes; 119 | 120 | /** 121 | * Name of the hash table. 122 | */ 123 | const char *name; 124 | 125 | /** 126 | * The first entry. 127 | */ 128 | struct lh_entry *head; 129 | 130 | /** 131 | * The last entry. 132 | */ 133 | struct lh_entry *tail; 134 | 135 | struct lh_entry *table; 136 | 137 | /** 138 | * A pointer onto the function responsible for freeing an entry. 139 | */ 140 | lh_entry_free_fn *free_fn; 141 | lh_hash_fn *hash_fn; 142 | lh_equal_fn *equal_fn; 143 | }; 144 | 145 | 146 | /** 147 | * Pre-defined hash and equality functions 148 | */ 149 | extern unsigned long lh_ptr_hash(const void *k); 150 | extern int lh_ptr_equal(const void *k1, const void *k2); 151 | 152 | extern unsigned long lh_char_hash(const void *k); 153 | extern int lh_char_equal(const void *k1, const void *k2); 154 | 155 | 156 | /** 157 | * Convenience list iterator. 158 | */ 159 | #define lh_foreach(table, entry) \ 160 | for(entry = table->head; entry; entry = entry->next) 161 | 162 | /** 163 | * lh_foreach_safe allows calling of deletion routine while iterating. 164 | */ 165 | #define lh_foreach_safe(table, entry, tmp) \ 166 | for(entry = table->head; entry && ((tmp = entry->next) || 1); entry = tmp) 167 | 168 | 169 | 170 | /** 171 | * Create a new linkhash table. 172 | * @param size initial table size. The table is automatically resized 173 | * although this incurs a performance penalty. 174 | * @param name the table name. 175 | * @param free_fn callback function used to free memory for entries 176 | * when lh_table_free or lh_table_delete is called. 177 | * If NULL is provided, then memory for keys and values 178 | * must be freed by the caller. 179 | * @param hash_fn function used to hash keys. 2 standard ones are defined: 180 | * lh_ptr_hash and lh_char_hash for hashing pointer values 181 | * and C strings respectively. 182 | * @param equal_fn comparison function to compare keys. 2 standard ones defined: 183 | * lh_ptr_hash and lh_char_hash for comparing pointer values 184 | * and C strings respectively. 185 | * @return a pointer onto the linkhash table. 186 | */ 187 | extern struct lh_table* lh_table_new(int size, const char *name, 188 | lh_entry_free_fn *free_fn, 189 | lh_hash_fn *hash_fn, 190 | lh_equal_fn *equal_fn); 191 | 192 | /** 193 | * Convenience function to create a new linkhash 194 | * table with char keys. 195 | * @param size initial table size. 196 | * @param name table name. 197 | * @param free_fn callback function used to free memory for entries. 198 | * @return a pointer onto the linkhash table. 199 | */ 200 | extern struct lh_table* lh_kchar_table_new(int size, const char *name, 201 | lh_entry_free_fn *free_fn); 202 | 203 | 204 | /** 205 | * Convenience function to create a new linkhash 206 | * table with ptr keys. 207 | * @param size initial table size. 208 | * @param name table name. 209 | * @param free_fn callback function used to free memory for entries. 210 | * @return a pointer onto the linkhash table. 211 | */ 212 | extern struct lh_table* lh_kptr_table_new(int size, const char *name, 213 | lh_entry_free_fn *free_fn); 214 | 215 | 216 | /** 217 | * Free a linkhash table. 218 | * If a callback free function is provided then it is called for all 219 | * entries in the table. 220 | * @param t table to free. 221 | */ 222 | extern void lh_table_free(struct lh_table *t); 223 | 224 | 225 | /** 226 | * Insert a record into the table. 227 | * @param t the table to insert into. 228 | * @param k a pointer to the key to insert. 229 | * @param v a pointer to the value to insert. 230 | */ 231 | extern int lh_table_insert(struct lh_table *t, void *k, const void *v); 232 | 233 | 234 | /** 235 | * Lookup a record into the table. 236 | * @param t the table to lookup 237 | * @param k a pointer to the key to lookup 238 | * @return a pointer to the record structure of the value or NULL if it does not exist. 239 | */ 240 | extern struct lh_entry* lh_table_lookup_entry(struct lh_table *t, const void *k); 241 | 242 | /** 243 | * Lookup a record into the table 244 | * @param t the table to lookup 245 | * @param k a pointer to the key to lookup 246 | * @return a pointer to the found value or NULL if it does not exist. 247 | * @deprecated Use lh_table_lookup_ex instead. 248 | */ 249 | extern const void* lh_table_lookup(struct lh_table *t, const void *k); 250 | 251 | /** 252 | * Lookup a record in the table 253 | * @param t the table to lookup 254 | * @param k a pointer to the key to lookup 255 | * @param v a pointer to a where to store the found value (set to NULL if it doesn't exist). 256 | * @return whether or not the key was found 257 | */ 258 | extern json_bool lh_table_lookup_ex(struct lh_table *t, const void *k, void **v); 259 | 260 | /** 261 | * Delete a record from the table. 262 | * If a callback free function is provided then it is called for the 263 | * for the item being deleted. 264 | * @param t the table to delete from. 265 | * @param e a pointer to the entry to delete. 266 | * @return 0 if the item was deleted. 267 | * @return -1 if it was not found. 268 | */ 269 | extern int lh_table_delete_entry(struct lh_table *t, struct lh_entry *e); 270 | 271 | 272 | /** 273 | * Delete a record from the table. 274 | * If a callback free function is provided then it is called for the 275 | * for the item being deleted. 276 | * @param t the table to delete from. 277 | * @param k a pointer to the key to delete. 278 | * @return 0 if the item was deleted. 279 | * @return -1 if it was not found. 280 | */ 281 | extern int lh_table_delete(struct lh_table *t, const void *k); 282 | 283 | extern int lh_table_length(struct lh_table *t); 284 | 285 | void lh_abort(const char *msg, ...); 286 | void lh_table_resize(struct lh_table *t, int new_size); 287 | 288 | #ifdef __cplusplus 289 | } 290 | #endif 291 | 292 | #endif 293 | -------------------------------------------------------------------------------- /json-c/json_tokener.h: -------------------------------------------------------------------------------- 1 | /* 2 | * $Id: json_tokener.h,v 1.10 2006/07/25 03:24:50 mclark Exp $ 3 | * 4 | * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. 5 | * Michael Clark 6 | * 7 | * This library is free software; you can redistribute it and/or modify 8 | * it under the terms of the MIT license. See COPYING for details. 9 | * 10 | */ 11 | 12 | #ifndef _json_tokener_h_ 13 | #define _json_tokener_h_ 14 | 15 | #include 16 | #include "json_object.h" 17 | 18 | #ifdef __cplusplus 19 | extern "C" { 20 | #endif 21 | 22 | enum json_tokener_error { 23 | json_tokener_success, 24 | json_tokener_continue, 25 | json_tokener_error_depth, 26 | json_tokener_error_parse_eof, 27 | json_tokener_error_parse_unexpected, 28 | json_tokener_error_parse_null, 29 | json_tokener_error_parse_boolean, 30 | json_tokener_error_parse_number, 31 | json_tokener_error_parse_array, 32 | json_tokener_error_parse_object_key_name, 33 | json_tokener_error_parse_object_key_sep, 34 | json_tokener_error_parse_object_value_sep, 35 | json_tokener_error_parse_string, 36 | json_tokener_error_parse_comment, 37 | json_tokener_error_size 38 | }; 39 | 40 | enum json_tokener_state { 41 | json_tokener_state_eatws, 42 | json_tokener_state_start, 43 | json_tokener_state_finish, 44 | json_tokener_state_null, 45 | json_tokener_state_comment_start, 46 | json_tokener_state_comment, 47 | json_tokener_state_comment_eol, 48 | json_tokener_state_comment_end, 49 | json_tokener_state_string, 50 | json_tokener_state_string_escape, 51 | json_tokener_state_escape_unicode, 52 | json_tokener_state_boolean, 53 | json_tokener_state_number, 54 | json_tokener_state_array, 55 | json_tokener_state_array_add, 56 | json_tokener_state_array_sep, 57 | json_tokener_state_object_field_start, 58 | json_tokener_state_object_field, 59 | json_tokener_state_object_field_end, 60 | json_tokener_state_object_value, 61 | json_tokener_state_object_value_add, 62 | json_tokener_state_object_sep, 63 | json_tokener_state_array_after_sep, 64 | json_tokener_state_object_field_start_after_sep 65 | }; 66 | 67 | struct json_tokener_srec 68 | { 69 | enum json_tokener_state state, saved_state; 70 | struct json_object *obj; 71 | struct json_object *current; 72 | char *obj_field_name; 73 | }; 74 | 75 | #define JSON_TOKENER_DEFAULT_DEPTH 32 76 | 77 | struct json_tokener 78 | { 79 | char *str; 80 | struct printbuf *pb; 81 | int max_depth, depth, is_double, st_pos, char_offset; 82 | enum json_tokener_error err; 83 | unsigned int ucs_char; 84 | char quote_char; 85 | struct json_tokener_srec *stack; 86 | int flags; 87 | /* for bigint detection */ 88 | int intmaxlen; 89 | const char *digits; 90 | }; 91 | 92 | /** 93 | * Be strict when parsing JSON input. Use caution with 94 | * this flag as what is considered valid may become more 95 | * restrictive from one release to the next, causing your 96 | * code to fail on previously working input. 97 | * 98 | * This flag is not set by default. 99 | * 100 | * @see json_tokener_set_flags() 101 | */ 102 | #define JSON_TOKENER_STRICT 0x01 103 | 104 | /* BIGINT as string instead of float */ 105 | #define JSON_TOKENER_BIGINT_AS_STRING 0x02 106 | 107 | /** 108 | * Given an error previously returned by json_tokener_get_error(), 109 | * return a human readable description of the error. 110 | * 111 | * @return a generic error message is returned if an invalid error value is provided. 112 | */ 113 | const char *json_tokener_error_desc(enum json_tokener_error jerr); 114 | 115 | /** 116 | * @b XXX do not use json_tokener_errors directly. 117 | * After v0.10 this will be removed. 118 | * 119 | * See json_tokener_error_desc() instead. 120 | */ 121 | extern const char* json_tokener_errors[]; 122 | 123 | /** 124 | * Retrieve the error caused by the last call to json_tokener_parse_ex(), 125 | * or json_tokener_success if there is no error. 126 | * 127 | * When parsing a JSON string in pieces, if the tokener is in the middle 128 | * of parsing this will return json_tokener_continue. 129 | * 130 | * See also json_tokener_error_desc(). 131 | */ 132 | enum json_tokener_error json_tokener_get_error(struct json_tokener *tok); 133 | 134 | extern struct json_tokener* json_tokener_new(void); 135 | extern struct json_tokener* json_tokener_new_ex(int depth); 136 | extern void json_tokener_free(struct json_tokener *tok); 137 | extern void json_tokener_reset(struct json_tokener *tok); 138 | extern struct json_object* json_tokener_parse(const char *str); 139 | extern struct json_object* json_tokener_parse_verbose(const char *str, enum json_tokener_error *error); 140 | 141 | /** 142 | * Set flags that control how parsing will be done. 143 | */ 144 | extern void json_tokener_set_flags(struct json_tokener *tok, int flags); 145 | extern void json_tokener_set_bigint(struct json_tokener *tok, const char *digits); 146 | 147 | /** 148 | * Parse a string and return a non-NULL json_object if a valid JSON value 149 | * is found. The string does not need to be a JSON object or array; 150 | * it can also be a string, number or boolean value. 151 | * 152 | * A partial JSON string can be parsed. If the parsing is incomplete, 153 | * NULL will be returned and json_tokener_get_error() will be return 154 | * json_tokener_continue. 155 | * json_tokener_parse_ex() can then be called with additional bytes in str 156 | * to continue the parsing. 157 | * 158 | * If json_tokener_parse_ex() returns NULL and the error anything other than 159 | * json_tokener_continue, a fatal error has occurred and parsing must be 160 | * halted. Then tok object must not be re-used until json_tokener_reset() is 161 | * called. 162 | * 163 | * When a valid JSON value is parsed, a non-NULL json_object will be 164 | * returned. Also, json_tokener_get_error() will return json_tokener_success. 165 | * Be sure to check the type with json_object_is_type() or 166 | * json_object_get_type() before using the object. 167 | * 168 | * @b XXX this shouldn't use internal fields: 169 | * Trailing characters after the parsed value do not automatically cause an 170 | * error. It is up to the caller to decide whether to treat this as an 171 | * error or to handle the additional characters, perhaps by parsing another 172 | * json value starting from that point. 173 | * 174 | * Extra characters can be detected by comparing the tok->char_offset against 175 | * the length of the last len parameter passed in. 176 | * 177 | * The tokener does \b not maintain an internal buffer so the caller is 178 | * responsible for calling json_tokener_parse_ex with an appropriate str 179 | * parameter starting with the extra characters. 180 | * 181 | * This interface is presently not 64-bit clean due to the int len argument 182 | * so the function limits the maximum string size to INT32_MAX (2GB). 183 | * If the function is called with len == -1 then strlen is called to check 184 | * the string length is less than INT32_MAX (2GB) 185 | * 186 | * Example: 187 | * @code 188 | json_object *jobj = NULL; 189 | const char *mystring = NULL; 190 | int stringlen = 0; 191 | enum json_tokener_error jerr; 192 | do { 193 | mystring = ... // get JSON string, e.g. read from file, etc... 194 | stringlen = strlen(mystring); 195 | jobj = json_tokener_parse_ex(tok, mystring, stringlen); 196 | } while ((jerr = json_tokener_get_error(tok)) == json_tokener_continue); 197 | if (jerr != json_tokener_success) 198 | { 199 | fprintf(stderr, "Error: %s\n", json_tokener_error_desc(jerr)); 200 | // Handle errors, as appropriate for your application. 201 | } 202 | if (tok->char_offset < stringlen) // XXX shouldn't access internal fields 203 | { 204 | // Handle extra characters after parsed object as desired. 205 | // e.g. issue an error, parse another object from that point, etc... 206 | } 207 | // Success, use jobj here. 208 | 209 | @endcode 210 | * 211 | * @param tok a json_tokener previously allocated with json_tokener_new() 212 | * @param str an string with any valid JSON expression, or portion of. This does not need to be null terminated. 213 | * @param len the length of str 214 | */ 215 | extern struct json_object* json_tokener_parse_ex(struct json_tokener *tok, 216 | const char *str, int len); 217 | 218 | #ifdef __cplusplus 219 | } 220 | #endif 221 | 222 | #endif 223 | -------------------------------------------------------------------------------- /tests/pass002.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | JSON (http://www.crockford.com/JSON/JSON_checker/test/pass2.json) 3 | --SKIPIF-- 4 | 7 | --FILE-- 8 | 34 | --EXPECT-- 35 | Testing: [[[[[[[[[[[[[[[[[[["Not too deep"]]]]]]]]]]]]]]]]]]] 36 | DECODE: AS OBJECT 37 | array(1) { 38 | [0]=> 39 | array(1) { 40 | [0]=> 41 | array(1) { 42 | [0]=> 43 | array(1) { 44 | [0]=> 45 | array(1) { 46 | [0]=> 47 | array(1) { 48 | [0]=> 49 | array(1) { 50 | [0]=> 51 | array(1) { 52 | [0]=> 53 | array(1) { 54 | [0]=> 55 | array(1) { 56 | [0]=> 57 | array(1) { 58 | [0]=> 59 | array(1) { 60 | [0]=> 61 | array(1) { 62 | [0]=> 63 | array(1) { 64 | [0]=> 65 | array(1) { 66 | [0]=> 67 | array(1) { 68 | [0]=> 69 | array(1) { 70 | [0]=> 71 | array(1) { 72 | [0]=> 73 | array(1) { 74 | [0]=> 75 | string(12) "Not too deep" 76 | } 77 | } 78 | } 79 | } 80 | } 81 | } 82 | } 83 | } 84 | } 85 | } 86 | } 87 | } 88 | } 89 | } 90 | } 91 | } 92 | } 93 | } 94 | } 95 | DECODE: AS ARRAY 96 | array(1) { 97 | [0]=> 98 | array(1) { 99 | [0]=> 100 | array(1) { 101 | [0]=> 102 | array(1) { 103 | [0]=> 104 | array(1) { 105 | [0]=> 106 | array(1) { 107 | [0]=> 108 | array(1) { 109 | [0]=> 110 | array(1) { 111 | [0]=> 112 | array(1) { 113 | [0]=> 114 | array(1) { 115 | [0]=> 116 | array(1) { 117 | [0]=> 118 | array(1) { 119 | [0]=> 120 | array(1) { 121 | [0]=> 122 | array(1) { 123 | [0]=> 124 | array(1) { 125 | [0]=> 126 | array(1) { 127 | [0]=> 128 | array(1) { 129 | [0]=> 130 | array(1) { 131 | [0]=> 132 | array(1) { 133 | [0]=> 134 | string(12) "Not too deep" 135 | } 136 | } 137 | } 138 | } 139 | } 140 | } 141 | } 142 | } 143 | } 144 | } 145 | } 146 | } 147 | } 148 | } 149 | } 150 | } 151 | } 152 | } 153 | } 154 | ENCODE: FROM OBJECT 155 | [[[[[[[[[[[[[[[[[[["Not too deep"]]]]]]]]]]]]]]]]]]] 156 | ENCODE: FROM ARRAY 157 | [[[[[[[[[[[[[[[[[[["Not too deep"]]]]]]]]]]]]]]]]]]] 158 | DECODE AGAIN: AS OBJECT 159 | array(1) { 160 | [0]=> 161 | array(1) { 162 | [0]=> 163 | array(1) { 164 | [0]=> 165 | array(1) { 166 | [0]=> 167 | array(1) { 168 | [0]=> 169 | array(1) { 170 | [0]=> 171 | array(1) { 172 | [0]=> 173 | array(1) { 174 | [0]=> 175 | array(1) { 176 | [0]=> 177 | array(1) { 178 | [0]=> 179 | array(1) { 180 | [0]=> 181 | array(1) { 182 | [0]=> 183 | array(1) { 184 | [0]=> 185 | array(1) { 186 | [0]=> 187 | array(1) { 188 | [0]=> 189 | array(1) { 190 | [0]=> 191 | array(1) { 192 | [0]=> 193 | array(1) { 194 | [0]=> 195 | array(1) { 196 | [0]=> 197 | string(12) "Not too deep" 198 | } 199 | } 200 | } 201 | } 202 | } 203 | } 204 | } 205 | } 206 | } 207 | } 208 | } 209 | } 210 | } 211 | } 212 | } 213 | } 214 | } 215 | } 216 | } 217 | DECODE AGAIN: AS ARRAY 218 | array(1) { 219 | [0]=> 220 | array(1) { 221 | [0]=> 222 | array(1) { 223 | [0]=> 224 | array(1) { 225 | [0]=> 226 | array(1) { 227 | [0]=> 228 | array(1) { 229 | [0]=> 230 | array(1) { 231 | [0]=> 232 | array(1) { 233 | [0]=> 234 | array(1) { 235 | [0]=> 236 | array(1) { 237 | [0]=> 238 | array(1) { 239 | [0]=> 240 | array(1) { 241 | [0]=> 242 | array(1) { 243 | [0]=> 244 | array(1) { 245 | [0]=> 246 | array(1) { 247 | [0]=> 248 | array(1) { 249 | [0]=> 250 | array(1) { 251 | [0]=> 252 | array(1) { 253 | [0]=> 254 | array(1) { 255 | [0]=> 256 | string(12) "Not too deep" 257 | } 258 | } 259 | } 260 | } 261 | } 262 | } 263 | } 264 | } 265 | } 266 | } 267 | } 268 | } 269 | } 270 | } 271 | } 272 | } 273 | } 274 | } 275 | } 276 | -------------------------------------------------------------------------------- /json-c/json_util.c: -------------------------------------------------------------------------------- 1 | /* 2 | * $Id: json_util.c,v 1.4 2006/01/30 23:07:57 mclark Exp $ 3 | * 4 | * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. 5 | * Michael Clark 6 | * 7 | * This library is free software; you can redistribute it and/or modify 8 | * it under the terms of the MIT license. See COPYING for details. 9 | * 10 | */ 11 | 12 | #include "config.h" 13 | #undef realloc 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #ifdef HAVE_SYS_TYPES_H 24 | #include 25 | #endif /* HAVE_SYS_TYPES_H */ 26 | 27 | #ifdef HAVE_SYS_STAT_H 28 | #include 29 | #endif /* HAVE_SYS_STAT_H */ 30 | 31 | #ifdef HAVE_FCNTL_H 32 | #include 33 | #endif /* HAVE_FCNTL_H */ 34 | 35 | #ifdef HAVE_UNISTD_H 36 | # include 37 | #endif /* HAVE_UNISTD_H */ 38 | 39 | #ifdef WIN32 40 | # define WIN32_LEAN_AND_MEAN 41 | # include 42 | # include 43 | #endif /* defined(WIN32) */ 44 | 45 | #if !defined(HAVE_OPEN) && defined(WIN32) 46 | # define open _open 47 | #endif 48 | 49 | #if !defined(HAVE_SNPRINTF) && defined(_MSC_VER) 50 | /* MSC has the version as _snprintf */ 51 | # define snprintf _snprintf 52 | #elif !defined(HAVE_SNPRINTF) 53 | # error You do not have snprintf on your system. 54 | #endif /* HAVE_SNPRINTF */ 55 | 56 | #include "bits.h" 57 | #include "debug.h" 58 | #include "printbuf.h" 59 | #include "json_inttypes.h" 60 | #include "json_object.h" 61 | #include "json_tokener.h" 62 | #include "json_util.h" 63 | 64 | static int sscanf_is_broken = 0; 65 | static int sscanf_is_broken_testdone = 0; 66 | static void sscanf_is_broken_test(void); 67 | 68 | struct json_object* json_object_from_file(const char *filename) 69 | { 70 | struct printbuf *pb; 71 | struct json_object *obj; 72 | char buf[JSON_FILE_BUF_SIZE]; 73 | int fd, ret; 74 | 75 | if((fd = open(filename, O_RDONLY)) < 0) { 76 | MC_ERROR("json_object_from_file: error reading file %s: %s\n", 77 | filename, strerror(errno)); 78 | return NULL; 79 | } 80 | if(!(pb = printbuf_new())) { 81 | close(fd); 82 | MC_ERROR("json_object_from_file: printbuf_new failed\n"); 83 | return NULL; 84 | } 85 | while((ret = read(fd, buf, JSON_FILE_BUF_SIZE)) > 0) { 86 | printbuf_memappend(pb, buf, ret); 87 | } 88 | close(fd); 89 | if(ret < 0) { 90 | MC_ABORT("json_object_from_file: error reading file %s: %s\n", 91 | filename, strerror(errno)); 92 | printbuf_free(pb); 93 | return NULL; 94 | } 95 | obj = json_tokener_parse(pb->buf); 96 | printbuf_free(pb); 97 | return obj; 98 | } 99 | 100 | /* extended "format and write to file" function */ 101 | 102 | int json_object_to_file_ext(char *filename, struct json_object *obj, int flags) 103 | { 104 | const char *json_str; 105 | int fd, ret; 106 | unsigned int wpos, wsize; 107 | 108 | if(!obj) { 109 | MC_ERROR("json_object_to_file: object is null\n"); 110 | return -1; 111 | } 112 | 113 | if((fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT, 0644)) < 0) { 114 | MC_ERROR("json_object_to_file: error opening file %s: %s\n", 115 | filename, strerror(errno)); 116 | return -1; 117 | } 118 | 119 | if(!(json_str = json_object_to_json_string_ext(obj,flags))) { 120 | close(fd); 121 | return -1; 122 | } 123 | 124 | wsize = (unsigned int)(strlen(json_str) & UINT_MAX); /* CAW: probably unnecessary, but the most 64bit safe */ 125 | wpos = 0; 126 | while(wpos < wsize) { 127 | if((ret = write(fd, json_str + wpos, wsize-wpos)) < 0) { 128 | close(fd); 129 | MC_ERROR("json_object_to_file: error writing file %s: %s\n", 130 | filename, strerror(errno)); 131 | return -1; 132 | } 133 | 134 | /* because of the above check for ret < 0, we can safely cast and add */ 135 | wpos += (unsigned int)ret; 136 | } 137 | 138 | close(fd); 139 | return 0; 140 | } 141 | 142 | // backwards compatible "format and write to file" function 143 | 144 | int json_object_to_file(char *filename, struct json_object *obj) 145 | { 146 | return json_object_to_file_ext(filename, obj, JSON_C_TO_STRING_PLAIN); 147 | } 148 | 149 | int json_parse_double(const char *buf, double *retval) 150 | { 151 | return (sscanf(buf, "%lf", retval)==1 ? 0 : 1); 152 | } 153 | 154 | /* 155 | * Not all implementations of sscanf actually work properly. 156 | * Check whether the one we're currently using does, and if 157 | * it's broken, enable the workaround code. 158 | */ 159 | static void sscanf_is_broken_test() 160 | { 161 | int64_t num64; 162 | 163 | (void)sscanf(" -01234567890123456789012345", "%" SCNd64, &num64); 164 | int ret_errno = errno; 165 | int is_int64_min = (num64 == INT64_MIN); 166 | 167 | (void)sscanf(" 01234567890123456789012345", "%" SCNd64, &num64); 168 | int ret_errno2 = errno; 169 | int is_int64_max = (num64 == INT64_MAX); 170 | 171 | if (ret_errno != ERANGE || !is_int64_min || 172 | ret_errno2 != ERANGE || !is_int64_max) 173 | { 174 | MC_DEBUG("sscanf_is_broken_test failed, enabling workaround code\n"); 175 | sscanf_is_broken = 1; 176 | } 177 | } 178 | 179 | int json_parse_int64(const char *buf, int64_t *retval) 180 | { 181 | int64_t num64; 182 | const char *buf_sig_digits; 183 | int orig_has_neg; 184 | int saved_errno; 185 | 186 | if (!sscanf_is_broken_testdone) 187 | { 188 | sscanf_is_broken_test(); 189 | sscanf_is_broken_testdone = 1; 190 | } 191 | 192 | // Skip leading spaces 193 | while (isspace((int)*buf) && *buf) 194 | buf++; 195 | 196 | errno = 0; // sscanf won't always set errno, so initialize 197 | if (sscanf(buf, "%" SCNd64, &num64) != 1) 198 | { 199 | MC_DEBUG("Failed to parse, sscanf != 1\n"); 200 | return 1; 201 | } 202 | 203 | saved_errno = errno; 204 | buf_sig_digits = buf; 205 | orig_has_neg = 0; 206 | if (*buf_sig_digits == '-') 207 | { 208 | buf_sig_digits++; 209 | orig_has_neg = 1; 210 | } 211 | 212 | // Not all sscanf implementations actually work 213 | if (sscanf_is_broken && saved_errno != ERANGE) 214 | { 215 | char buf_cmp[100]; 216 | char *buf_cmp_start = buf_cmp; 217 | int recheck_has_neg = 0; 218 | int buf_cmp_len; 219 | 220 | // Skip leading zeros, but keep at least one digit 221 | while (buf_sig_digits[0] == '0' && buf_sig_digits[1] != '\0') 222 | buf_sig_digits++; 223 | if (num64 == 0) // assume all sscanf impl's will parse -0 to 0 224 | orig_has_neg = 0; // "-0" is the same as just plain "0" 225 | 226 | snprintf(buf_cmp_start, sizeof(buf_cmp), "%" PRId64, num64); 227 | if (*buf_cmp_start == '-') 228 | { 229 | recheck_has_neg = 1; 230 | buf_cmp_start++; 231 | } 232 | // No need to skip leading spaces or zeros here. 233 | 234 | buf_cmp_len = strlen(buf_cmp_start); 235 | /** 236 | * If the sign is different, or 237 | * some of the digits are different, or 238 | * there is another digit present in the original string 239 | * then we have NOT successfully parsed the value. 240 | */ 241 | if (orig_has_neg != recheck_has_neg || 242 | strncmp(buf_sig_digits, buf_cmp_start, strlen(buf_cmp_start)) != 0 || 243 | ((int)strlen(buf_sig_digits) != buf_cmp_len && 244 | isdigit((int)buf_sig_digits[buf_cmp_len]) 245 | ) 246 | ) 247 | { 248 | saved_errno = ERANGE; 249 | } 250 | } 251 | 252 | // Not all sscanf impl's set the value properly when out of range. 253 | // Always do this, even for properly functioning implementations, 254 | // since it shouldn't slow things down much. 255 | if (saved_errno == ERANGE) 256 | { 257 | if (orig_has_neg) 258 | num64 = INT64_MIN; 259 | else 260 | num64 = INT64_MAX; 261 | } 262 | *retval = num64; 263 | return 0; 264 | } 265 | 266 | #ifndef HAVE_REALLOC 267 | void* rpl_realloc(void* p, size_t n) 268 | { 269 | if (n == 0) 270 | n = 1; 271 | if (p == 0) 272 | return malloc(n); 273 | return realloc(p, n); 274 | } 275 | #endif 276 | 277 | #define NELEM(a) (sizeof(a) / sizeof(a[0])) 278 | static const char* json_type_name[] = { 279 | /* If you change this, be sure to update the enum json_type definition too */ 280 | "null", 281 | "boolean", 282 | "double", 283 | "int", 284 | "object", 285 | "array", 286 | "string", 287 | }; 288 | 289 | const char *json_type_to_name(enum json_type o_type) 290 | { 291 | int o_type_int = (int)o_type; 292 | if (o_type_int < 0 || o_type_int >= (int)NELEM(json_type_name)) 293 | { 294 | MC_ERROR("json_type_to_name: type %d is out of range [0,%d]\n", o_type, NELEM(json_type_name)); 295 | return NULL; 296 | } 297 | return json_type_name[o_type]; 298 | } 299 | 300 | -------------------------------------------------------------------------------- /tests/bug70499.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | bug #70499 (segfaults after json_decode) 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 123 | done 124 | --EXPECTF-- 125 | NULL 126 | NULL 127 | done -------------------------------------------------------------------------------- /json-c/json_object_iterator.h: -------------------------------------------------------------------------------- 1 | /** 2 | ******************************************************************************* 3 | * @file json_object_iterator.h 4 | * 5 | * Copyright (c) 2009-2012 Hewlett-Packard Development Company, L.P. 6 | * 7 | * This library is free software; you can redistribute it and/or modify 8 | * it under the terms of the MIT license. See COPYING for details. 9 | * 10 | * @brief json-c forces clients to use its private data 11 | * structures for JSON Object iteration. This API 12 | * corrects that by abstracting the private json-c 13 | * details. 14 | * 15 | * API attributes:
16 | * * Thread-safe: NO
17 | * * Reentrant: NO 18 | * 19 | ******************************************************************************* 20 | */ 21 | 22 | 23 | #ifndef JSON_OBJECT_ITERATOR_H 24 | #define JSON_OBJECT_ITERATOR_H 25 | 26 | #include 27 | 28 | #ifdef __cplusplus 29 | extern "C" { 30 | #endif 31 | 32 | /** 33 | * Forward declaration for the opaque iterator information. 34 | */ 35 | struct json_object_iter_info_; 36 | 37 | /** 38 | * The opaque iterator that references a name/value pair within 39 | * a JSON Object instance or the "end" iterator value. 40 | */ 41 | struct json_object_iterator { 42 | const void* opaque_; 43 | }; 44 | 45 | 46 | /** 47 | * forward declaration of json-c's JSON value instance structure 48 | */ 49 | struct json_object; 50 | 51 | 52 | /** 53 | * Initializes an iterator structure to a "default" value that 54 | * is convenient for initializing an iterator variable to a 55 | * default state (e.g., initialization list in a class' 56 | * constructor). 57 | * 58 | * @code 59 | * struct json_object_iterator iter = json_object_iter_init_default(); 60 | * MyClass() : iter_(json_object_iter_init_default()) 61 | * @endcode 62 | * 63 | * @note The initialized value doesn't reference any specific 64 | * pair, is considered an invalid iterator, and MUST NOT 65 | * be passed to any json-c API that expects a valid 66 | * iterator. 67 | * 68 | * @note User and internal code MUST NOT make any assumptions 69 | * about and dependencies on the value of the "default" 70 | * iterator value. 71 | * 72 | * @return json_object_iterator 73 | */ 74 | struct json_object_iterator 75 | json_object_iter_init_default(void); 76 | 77 | /** Retrieves an iterator to the first pair of the JSON Object. 78 | * 79 | * @warning Any modification of the underlying pair invalidates all 80 | * iterators to that pair. 81 | * 82 | * @param obj JSON Object instance (MUST be of type json_object) 83 | * 84 | * @return json_object_iterator If the JSON Object has at 85 | * least one pair, on return, the iterator refers 86 | * to the first pair. If the JSON Object doesn't 87 | * have any pairs, the returned iterator is 88 | * equivalent to the "end" iterator for the same 89 | * JSON Object instance. 90 | * 91 | * @code 92 | * struct json_object_iterator it; 93 | * struct json_object_iterator itEnd; 94 | * struct json_object* obj; 95 | * 96 | * obj = json_tokener_parse("{'first':'george', 'age':100}"); 97 | * it = json_object_iter_begin(obj); 98 | * itEnd = json_object_iter_end(obj); 99 | * 100 | * while (!json_object_iter_equal(&it, &itEnd)) { 101 | * printf("%s\n", 102 | * json_object_iter_peek_name(&it)); 103 | * json_object_iter_next(&it); 104 | * } 105 | * 106 | * @endcode 107 | */ 108 | struct json_object_iterator 109 | json_object_iter_begin(struct json_object* obj); 110 | 111 | /** Retrieves the iterator that represents the position beyond the 112 | * last pair of the given JSON Object instance. 113 | * 114 | * @warning Do NOT write code that assumes that the "end" 115 | * iterator value is NULL, even if it is so in a 116 | * particular instance of the implementation. 117 | * 118 | * @note The reason we do not (and MUST NOT) provide 119 | * "json_object_iter_is_end(json_object_iterator* iter)" 120 | * type of API is because it would limit the underlying 121 | * representation of name/value containment (or force us 122 | * to add additional, otherwise unnecessary, fields to 123 | * the iterator structure). The "end" iterator and the 124 | * equality test method, on the other hand, permit us to 125 | * cleanly abstract pretty much any reasonable underlying 126 | * representation without burdening the iterator 127 | * structure with unnecessary data. 128 | * 129 | * @note For performance reasons, memorize the "end" iterator prior 130 | * to any loop. 131 | * 132 | * @param obj JSON Object instance (MUST be of type json_object) 133 | * 134 | * @return json_object_iterator On return, the iterator refers 135 | * to the "end" of the Object instance's pairs 136 | * (i.e., NOT the last pair, but "beyond the last 137 | * pair" value) 138 | */ 139 | struct json_object_iterator 140 | json_object_iter_end(const struct json_object* obj); 141 | 142 | /** Returns an iterator to the next pair, if any 143 | * 144 | * @warning Any modification of the underlying pair 145 | * invalidates all iterators to that pair. 146 | * 147 | * @param iter [IN/OUT] Pointer to iterator that references a 148 | * name/value pair; MUST be a valid, non-end iterator. 149 | * WARNING: bad things will happen if invalid or "end" 150 | * iterator is passed. Upon return will contain the 151 | * reference to the next pair if there is one; if there 152 | * are no more pairs, will contain the "end" iterator 153 | * value, which may be compared against the return value 154 | * of json_object_iter_end() for the same JSON Object 155 | * instance. 156 | */ 157 | void 158 | json_object_iter_next(struct json_object_iterator* iter); 159 | 160 | 161 | /** Returns a const pointer to the name of the pair referenced 162 | * by the given iterator. 163 | * 164 | * @param iter pointer to iterator that references a name/value 165 | * pair; MUST be a valid, non-end iterator. 166 | * 167 | * @warning bad things will happen if an invalid or 168 | * "end" iterator is passed. 169 | * 170 | * @return const char* Pointer to the name of the referenced 171 | * name/value pair. The name memory belongs to the 172 | * name/value pair, will be freed when the pair is 173 | * deleted or modified, and MUST NOT be modified or 174 | * freed by the user. 175 | */ 176 | const char* 177 | json_object_iter_peek_name(const struct json_object_iterator* iter); 178 | 179 | 180 | /** Returns a pointer to the json-c instance representing the 181 | * value of the referenced name/value pair, without altering 182 | * the instance's reference count. 183 | * 184 | * @param iter pointer to iterator that references a name/value 185 | * pair; MUST be a valid, non-end iterator. 186 | * 187 | * @warning bad things will happen if invalid or 188 | * "end" iterator is passed. 189 | * 190 | * @return struct json_object* Pointer to the json-c value 191 | * instance of the referenced name/value pair; the 192 | * value's reference count is not changed by this 193 | * function: if you plan to hold on to this json-c node, 194 | * take a look at json_object_get() and 195 | * json_object_put(). IMPORTANT: json-c API represents 196 | * the JSON Null value as a NULL json_object instance 197 | * pointer. 198 | */ 199 | struct json_object* 200 | json_object_iter_peek_value(const struct json_object_iterator* iter); 201 | 202 | 203 | /** Tests two iterators for equality. Typically used to test 204 | * for end of iteration by comparing an iterator to the 205 | * corresponding "end" iterator (that was derived from the same 206 | * JSON Object instance). 207 | * 208 | * @note The reason we do not (and MUST NOT) provide 209 | * "json_object_iter_is_end(json_object_iterator* iter)" 210 | * type of API is because it would limit the underlying 211 | * representation of name/value containment (or force us 212 | * to add additional, otherwise unnecessary, fields to 213 | * the iterator structure). The equality test method, on 214 | * the other hand, permits us to cleanly abstract pretty 215 | * much any reasonable underlying representation. 216 | * 217 | * @param iter1 Pointer to first valid, non-NULL iterator 218 | * @param iter2 POinter to second valid, non-NULL iterator 219 | * 220 | * @warning if a NULL iterator pointer or an uninitialized 221 | * or invalid iterator, or iterators derived from 222 | * different JSON Object instances are passed, bad things 223 | * will happen! 224 | * 225 | * @return json_bool non-zero if iterators are equal (i.e., both 226 | * reference the same name/value pair or are both at 227 | * "end"); zero if they are not equal. 228 | */ 229 | json_bool 230 | json_object_iter_equal(const struct json_object_iterator* iter1, 231 | const struct json_object_iterator* iter2); 232 | 233 | 234 | #ifdef __cplusplus 235 | } 236 | #endif 237 | 238 | 239 | #endif // JSON_OBJECT_ITERATOR_H 240 | -------------------------------------------------------------------------------- /package.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | jsonc 7 | pecl.php.net 8 | JavaScript Object Notation 9 | 10 | Support for JSON (JavaScript Object Notation) serialization. 11 | This is a drop-in alternative to PHP standard json extension. 12 | 13 | 14 | Remi Collet 15 | remi 16 | remi@php.net 17 | yes 18 | 19 | 2016-06-15 20 | 21 | 22 | 1.3.10 23 | 1.3.0 24 | 25 | 26 | stable 27 | stable 28 | 29 | PHP 3.01 30 | 31 | - fix gh#27 invalid string to float convertion 32 | - fix gh#28 fix result when we decode number with "-" in bad position 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 5.4.0 142 | 6.0.0 143 | 144 | 145 | 1.9.0 146 | 147 | 148 | 149 | json 150 | 151 | 152 | 153 | 154 | 1.0.0 155 | 1.0.0 156 | 157 | 158 | stable 159 | stable 160 | 161 | 2005-04-01 162 | PHP 3.01 163 | 164 | Initial release. 165 | 166 | 167 | 168 | 169 | 1.0.1 170 | 1.0.1 171 | 172 | 173 | stable 174 | stable 175 | 176 | 2005-06-10 177 | PHP 3.01 178 | 179 | Fixed non-linear and mixed type array index issues, fixed issues with escaping \\, forked json-c and added Unicode support. 180 | 181 | 182 | 183 | 184 | 1.0.2 185 | 1.0.2 186 | 187 | 188 | stable 189 | stable 190 | 191 | 2005-06-11 192 | PHP 3.01 193 | 194 | Fixed issues with object reference counts under PHP4. 195 | 196 | 197 | 198 | 199 | 1.0.3 200 | 1.0.3 201 | 202 | 203 | stable 204 | stable 205 | 206 | 2005-06-15 207 | PHP 3.01 208 | 209 | Fixed json-c string corruption issues under Mac OS X and FreeBSD. 210 | 211 | 212 | 213 | 214 | 1.0.4 215 | 1.0.4 216 | 217 | 218 | stable 219 | stable 220 | 221 | 2005-06-15 222 | PHP 3.01 223 | 224 | Changes in 1.0.4 released with 1.0.5. 225 | 226 | 227 | 228 | 229 | 1.0.5 230 | 1.0.5 231 | 232 | 233 | stable 234 | stable 235 | 236 | 2005-06-16 237 | PHP 3.01 238 | 239 | Changed spacing in json-c encoding, added optional assoc (boolean) parameter to json_decode to decode as associative array instead of object, fixed issues with escaping /. 240 | 241 | 242 | 243 | 244 | 1.0.6 245 | 1.0.6 246 | 247 | 248 | stable 249 | stable 250 | 251 | 2005-08-05 252 | PHP 3.01 253 | 254 | Fixed issues with exporting private and protected class members. 255 | 256 | 257 | 258 | 259 | 1.0.7 260 | 1.0.7 261 | 262 | 263 | stable 264 | stable 265 | 266 | 2005-09-07 267 | PHP 3.01 268 | 269 | Fixed issues with negative array keys, modified json-c to return an error on unquoted object key names instead of going into an infinite loop. 270 | 271 | 272 | 273 | 274 | 1.0.8 275 | 1.0.8 276 | 277 | 278 | stable 279 | stable 280 | 281 | 2005-12-01 282 | PHP 3.01 283 | 284 | Changed license to LGPL, modified build system to allow static compilation into PHP, added strndup check for json-c. 285 | 286 | 287 | 288 | 289 | 1.1.0 290 | 1.1.0 291 | 292 | 293 | stable 294 | stable 295 | 296 | 2005-12-04 297 | PHP 3.01 298 | 299 | Port to Win32. 300 | 301 | 302 | 303 | 304 | 1.1.1 305 | 1.1.1 306 | 307 | 308 | stable 309 | stable 310 | 311 | 2006-01-12 312 | PHP 3.01 313 | 314 | Cleanup and TSRM performance fixes by rasmus. 315 | 316 | 317 | 318 | 319 | 1.2.0 320 | 1.2.0 321 | 322 | 323 | stable 324 | stable 325 | 326 | 2006-03-15 327 | PHP 3.01 328 | 329 | Complete rewrite using JSON_checker as the base for the parser. Implements the JSON specification. 3-8x faster on encodes and 1.2x-4x faster on decodes. 330 | 331 | 332 | 333 | 334 | 1.2.1 335 | 1.2.1 336 | 337 | 338 | stable 339 | stable 340 | 341 | 2006-03-18 342 | PHP 3.01 343 | 344 | Fix PECL bug #7147 - rework handling of comma insertion while encoding. 345 | Add tests to package.xml 346 | 347 | 348 | 349 | 350 | 1.3.0 351 | 1.3.0 352 | 353 | 354 | beta 355 | stable 356 | 357 | 2013-06-04 358 | PHP 3.01 359 | 360 | Version 1.3.0 is Major rewrite which use the use json-c library 0.11: 361 | - json_decode use json-c parser 362 | - add JsonIncrementalParser class 363 | - temporarily rename as jsonc 364 | 365 | 366 | 367 | 368 | 1.3.1 369 | 1.3.0 370 | 371 | 372 | beta 373 | stable 374 | 375 | 2013-06-12 376 | PHP 3.01 377 | 378 | - windows build support (thanks to weltling) 379 | - build as json.so or jsonc.so (--with-jsonc option) 380 | - rename LIBJSON_VERSION to HAVE_LIBJSON (internal only) 381 | - parse 64 bits integer as float, or string, on 32 bits build 382 | 383 | 384 | 385 | 386 | 1.3.2 387 | 1.3.0 388 | 389 | 390 | stable 391 | stable 392 | 393 | 2013-09-09 394 | PHP 3.01 395 | 396 | - number must not have leading zeroes (json-c library pr #90, merged) 397 | - string must be double-quoted (json-c library PR #94, merged) 398 | - comment are not allowed (json-c library PR #94, merged) 399 | - trailing char after data not allowed (json-c library PR #94, merged) 400 | - add JSON_C_BUNDLED and JSON_C_VERSION constants 401 | 402 | 403 | 404 | 405 | 1.3.3 406 | 1.3.0 407 | 408 | 409 | stable 410 | stable 411 | 412 | 2013-12-12 413 | PHP 3.01 414 | 415 | - properly decode string value with null-byte 416 | - allow to build in php tree 417 | - drop confusing warning about JSON_BIGINT_AS_STRING 418 | - add E_NOTICE "integer overflow detected" 419 | 420 | 421 | 422 | 423 | 1.3.4 424 | 1.3.0 425 | 426 | 427 | stable 428 | stable 429 | 430 | 2014-02-22 431 | PHP 3.01 432 | 433 | - Fixed bug #65753 JsonSerializeable couldn't implement on module extension 434 | 435 | 436 | 437 | 2014-04-10 438 | 439 | 1.3.5 440 | 1.3.0 441 | 442 | 443 | stable 444 | stable 445 | 446 | PHP 3.01 447 | 448 | - libjson-c CVE-2013-6371: hash collision denial of service 449 | - libjson-c CVE-2013-6370: buffer overflow if size_t is larger than int 450 | 451 | 452 | 453 | 2014-08-01 454 | 455 | 1.3.6 456 | 1.3.0 457 | 458 | 459 | stable 460 | stable 461 | 462 | PHP 3.01 463 | 464 | - apply fix for #66021 (Blank line inside empty array/object) 465 | - fix #20 json_decode segfault when depth=0 466 | 467 | 468 | 469 | 2015-02-18 470 | 471 | 1.3.7 472 | 1.3.0 473 | 474 | 475 | stable 476 | stable 477 | 478 | PHP 3.01 479 | 480 | - apply fix for #50224 where float without decimals were converted to 481 | integer by adding JSON_PRESERVE_ZERO_FRACTION. (Juan Basso) 482 | 483 | 484 | 485 | 2015-09-07 486 | 487 | 1.3.8 488 | 1.3.0 489 | 490 | 491 | stable 492 | stable 493 | 494 | PHP 3.01 495 | 496 | - using system libjson-c is no more supported 497 | - fix BIGINT behavior 498 | - fix #12 allow float starting with a dot 499 | - fix #23 single quote in property name 500 | - fix #9 invalid UTF-8 characters 501 | 502 | 503 | 504 | 2015-09-15 505 | 506 | 1.3.9 507 | 1.3.0 508 | 509 | 510 | stable 511 | stable 512 | 513 | PHP 3.01 514 | 515 | - fix #70499 segfault after json_decode 516 | 517 | 518 | 519 | 520 | -------------------------------------------------------------------------------- /tests/pass001.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | JSON (http://www.crockford.com/JSON/JSON_checker/test/pass1.json) 3 | --INI-- 4 | precision=14 5 | --SKIPIF-- 6 | 9 | --FILE-- 10 | ?\", 41 | \"hex\": \"\\u0123\\u4567\\u89AB\\uCDEF\\uabcd\\uef4A\", 42 | \"true\": true, 43 | \"false\": false, 44 | \"null\": null, 45 | \"array\":[ ], 46 | \"object\":{ }, 47 | \"address\": \"50 St. James Street\", 48 | \"url\": \"http://www.JSON.org/\", 49 | \"comment\": \"// /* */\": \" \", 51 | \" s p a c e d \" :[1,2 , 3 52 | 53 | , 54 | 55 | 4 , 5 , 6 ,7 ], 56 | \"compact\": [1,2,3,4,5,6,7], 57 | \"jsontext\": \"{\\\"object with 1 member\\\":[\\\"array with 1 element\\\"]}\", 58 | \"quotes\": \"" \\u0022 %22 0x22 034 "\", 59 | \"\\/\\\\\\\"\\uCAFE\\uBABE\\uAB98\\uFCDE\\ubcda\\uef4A\\b\\f\\n\\r\\t`1~!@#$%^&*()_+-=[]{}|;:',./<>?\" 60 | : \"A key can be any string\" 61 | }, 62 | 0.5 ,98.6 63 | , 64 | 99.44 65 | , 66 | 67 | 1066 68 | 69 | 70 | ,\"rosebud\"] 71 | "; 72 | 73 | echo 'Testing: ' . $test . "\n"; 74 | echo "DECODE: AS OBJECT\n"; 75 | $obj = json_decode($test); 76 | var_dump($obj); 77 | echo "DECODE: AS ARRAY\n"; 78 | $arr = json_decode($test, true); 79 | var_dump($arr); 80 | 81 | echo "ENCODE: FROM OBJECT\n"; 82 | $obj_enc = json_encode($obj, JSON_PARTIAL_OUTPUT_ON_ERROR); 83 | echo $obj_enc . "\n"; 84 | echo "ENCODE: FROM ARRAY\n"; 85 | $arr_enc = json_encode($arr, JSON_PARTIAL_OUTPUT_ON_ERROR); 86 | echo $arr_enc . "\n"; 87 | 88 | echo "DECODE AGAIN: AS OBJECT\n"; 89 | $obj = json_decode($obj_enc); 90 | var_dump($obj); 91 | echo "DECODE AGAIN: AS ARRAY\n"; 92 | $arr = json_decode($arr_enc, true); 93 | var_dump($arr); 94 | 95 | ?> 96 | --EXPECT-- 97 | Testing: 98 | [ 99 | "JSON Test Pattern pass1", 100 | {"object with 1 member":["array with 1 element"]}, 101 | {}, 102 | [], 103 | -42, 104 | true, 105 | false, 106 | null, 107 | { 108 | "integer": 1234567890, 109 | "real": -9876.543210, 110 | "e": 0.123456789e-12, 111 | "E": 1.234567890E+34, 112 | "": 23456789012E666, 113 | "zero": 0, 114 | "one": 1, 115 | "space": " ", 116 | "quote": "\"", 117 | "backslash": "\\", 118 | "controls": "\b\f\n\r\t", 119 | "slash": "/ & \/", 120 | "alpha": "abcdefghijklmnopqrstuvwyz", 121 | "ALPHA": "ABCDEFGHIJKLMNOPQRSTUVWYZ", 122 | "digit": "0123456789", 123 | "special": "`1~!@#$%^&*()_+-={':[,]}|;.?", 124 | "hex": "\u0123\u4567\u89AB\uCDEF\uabcd\uef4A", 125 | "true": true, 126 | "false": false, 127 | "null": null, 128 | "array":[ ], 129 | "object":{ }, 130 | "address": "50 St. James Street", 131 | "url": "http://www.JSON.org/", 132 | "comment": "// /* */": " ", 134 | " s p a c e d " :[1,2 , 3 135 | 136 | , 137 | 138 | 4 , 5 , 6 ,7 ], 139 | "compact": [1,2,3,4,5,6,7], 140 | "jsontext": "{\"object with 1 member\":[\"array with 1 element\"]}", 141 | "quotes": "" \u0022 %22 0x22 034 "", 142 | "\/\\\"\uCAFE\uBABE\uAB98\uFCDE\ubcda\uef4A\b\f\n\r\t`1~!@#$%^&*()_+-=[]{}|;:',./<>?" 143 | : "A key can be any string" 144 | }, 145 | 0.5 ,98.6 146 | , 147 | 99.44 148 | , 149 | 150 | 1066 151 | 152 | 153 | ,"rosebud"] 154 | 155 | DECODE: AS OBJECT 156 | array(14) { 157 | [0]=> 158 | string(23) "JSON Test Pattern pass1" 159 | [1]=> 160 | object(stdClass)#1 (1) { 161 | ["object with 1 member"]=> 162 | array(1) { 163 | [0]=> 164 | string(20) "array with 1 element" 165 | } 166 | } 167 | [2]=> 168 | object(stdClass)#2 (0) { 169 | } 170 | [3]=> 171 | array(0) { 172 | } 173 | [4]=> 174 | int(-42) 175 | [5]=> 176 | bool(true) 177 | [6]=> 178 | bool(false) 179 | [7]=> 180 | NULL 181 | [8]=> 182 | object(stdClass)#3 (31) { 183 | ["integer"]=> 184 | int(1234567890) 185 | ["real"]=> 186 | float(-9876.54321) 187 | ["e"]=> 188 | float(1.23456789E-13) 189 | ["E"]=> 190 | float(1.23456789E+34) 191 | ["_empty_"]=> 192 | float(INF) 193 | ["zero"]=> 194 | int(0) 195 | ["one"]=> 196 | int(1) 197 | ["space"]=> 198 | string(1) " " 199 | ["quote"]=> 200 | string(1) """ 201 | ["backslash"]=> 202 | string(1) "\" 203 | ["controls"]=> 204 | string(5) " 205 | " 206 | ["slash"]=> 207 | string(5) "/ & /" 208 | ["alpha"]=> 209 | string(25) "abcdefghijklmnopqrstuvwyz" 210 | ["ALPHA"]=> 211 | string(25) "ABCDEFGHIJKLMNOPQRSTUVWYZ" 212 | ["digit"]=> 213 | string(10) "0123456789" 214 | ["special"]=> 215 | string(31) "`1~!@#$%^&*()_+-={':[,]}|;.?" 216 | ["hex"]=> 217 | string(17) "ģ䕧覫췯ꯍ" 218 | ["true"]=> 219 | bool(true) 220 | ["false"]=> 221 | bool(false) 222 | ["null"]=> 223 | NULL 224 | ["array"]=> 225 | array(0) { 226 | } 227 | ["object"]=> 228 | object(stdClass)#4 (0) { 229 | } 230 | ["address"]=> 231 | string(19) "50 St. James Street" 232 | ["url"]=> 233 | string(20) "http://www.JSON.org/" 234 | ["comment"]=> 235 | string(13) "// /* */"]=> 237 | string(1) " " 238 | [" s p a c e d "]=> 239 | array(7) { 240 | [0]=> 241 | int(1) 242 | [1]=> 243 | int(2) 244 | [2]=> 245 | int(3) 246 | [3]=> 247 | int(4) 248 | [4]=> 249 | int(5) 250 | [5]=> 251 | int(6) 252 | [6]=> 253 | int(7) 254 | } 255 | ["compact"]=> 256 | array(7) { 257 | [0]=> 258 | int(1) 259 | [1]=> 260 | int(2) 261 | [2]=> 262 | int(3) 263 | [3]=> 264 | int(4) 265 | [4]=> 266 | int(5) 267 | [5]=> 268 | int(6) 269 | [6]=> 270 | int(7) 271 | } 272 | ["jsontext"]=> 273 | string(49) "{"object with 1 member":["array with 1 element"]}" 274 | ["quotes"]=> 275 | string(27) "" " %22 0x22 034 "" 276 | ["/\"쫾몾ꮘﳞ볚 277 | `1~!@#$%^&*()_+-=[]{}|;:',./<>?"]=> 278 | string(23) "A key can be any string" 279 | } 280 | [9]=> 281 | float(0.5) 282 | [10]=> 283 | float(98.6) 284 | [11]=> 285 | float(99.44) 286 | [12]=> 287 | int(1066) 288 | [13]=> 289 | string(7) "rosebud" 290 | } 291 | DECODE: AS ARRAY 292 | array(14) { 293 | [0]=> 294 | string(23) "JSON Test Pattern pass1" 295 | [1]=> 296 | array(1) { 297 | ["object with 1 member"]=> 298 | array(1) { 299 | [0]=> 300 | string(20) "array with 1 element" 301 | } 302 | } 303 | [2]=> 304 | array(0) { 305 | } 306 | [3]=> 307 | array(0) { 308 | } 309 | [4]=> 310 | int(-42) 311 | [5]=> 312 | bool(true) 313 | [6]=> 314 | bool(false) 315 | [7]=> 316 | NULL 317 | [8]=> 318 | array(31) { 319 | ["integer"]=> 320 | int(1234567890) 321 | ["real"]=> 322 | float(-9876.54321) 323 | ["e"]=> 324 | float(1.23456789E-13) 325 | ["E"]=> 326 | float(1.23456789E+34) 327 | [""]=> 328 | float(INF) 329 | ["zero"]=> 330 | int(0) 331 | ["one"]=> 332 | int(1) 333 | ["space"]=> 334 | string(1) " " 335 | ["quote"]=> 336 | string(1) """ 337 | ["backslash"]=> 338 | string(1) "\" 339 | ["controls"]=> 340 | string(5) " 341 | " 342 | ["slash"]=> 343 | string(5) "/ & /" 344 | ["alpha"]=> 345 | string(25) "abcdefghijklmnopqrstuvwyz" 346 | ["ALPHA"]=> 347 | string(25) "ABCDEFGHIJKLMNOPQRSTUVWYZ" 348 | ["digit"]=> 349 | string(10) "0123456789" 350 | ["special"]=> 351 | string(31) "`1~!@#$%^&*()_+-={':[,]}|;.?" 352 | ["hex"]=> 353 | string(17) "ģ䕧覫췯ꯍ" 354 | ["true"]=> 355 | bool(true) 356 | ["false"]=> 357 | bool(false) 358 | ["null"]=> 359 | NULL 360 | ["array"]=> 361 | array(0) { 362 | } 363 | ["object"]=> 364 | array(0) { 365 | } 366 | ["address"]=> 367 | string(19) "50 St. James Street" 368 | ["url"]=> 369 | string(20) "http://www.JSON.org/" 370 | ["comment"]=> 371 | string(13) "// /* */"]=> 373 | string(1) " " 374 | [" s p a c e d "]=> 375 | array(7) { 376 | [0]=> 377 | int(1) 378 | [1]=> 379 | int(2) 380 | [2]=> 381 | int(3) 382 | [3]=> 383 | int(4) 384 | [4]=> 385 | int(5) 386 | [5]=> 387 | int(6) 388 | [6]=> 389 | int(7) 390 | } 391 | ["compact"]=> 392 | array(7) { 393 | [0]=> 394 | int(1) 395 | [1]=> 396 | int(2) 397 | [2]=> 398 | int(3) 399 | [3]=> 400 | int(4) 401 | [4]=> 402 | int(5) 403 | [5]=> 404 | int(6) 405 | [6]=> 406 | int(7) 407 | } 408 | ["jsontext"]=> 409 | string(49) "{"object with 1 member":["array with 1 element"]}" 410 | ["quotes"]=> 411 | string(27) "" " %22 0x22 034 "" 412 | ["/\"쫾몾ꮘﳞ볚 413 | `1~!@#$%^&*()_+-=[]{}|;:',./<>?"]=> 414 | string(23) "A key can be any string" 415 | } 416 | [9]=> 417 | float(0.5) 418 | [10]=> 419 | float(98.6) 420 | [11]=> 421 | float(99.44) 422 | [12]=> 423 | int(1066) 424 | [13]=> 425 | string(7) "rosebud" 426 | } 427 | ENCODE: FROM OBJECT 428 | ["JSON Test Pattern pass1",{"object with 1 member":["array with 1 element"]},{},[],-42,true,false,null,{"integer":1234567890,"real":-9876.54321,"e":1.23456789e-13,"E":1.23456789e+34,"_empty_":0,"zero":0,"one":1,"space":" ","quote":"\"","backslash":"\\","controls":"\b\f\n\r\t","slash":"\/ & \/","alpha":"abcdefghijklmnopqrstuvwyz","ALPHA":"ABCDEFGHIJKLMNOPQRSTUVWYZ","digit":"0123456789","special":"`1~!@#$%^&*()_+-={':[,]}|;.<\/>?","hex":"\u0123\u4567\u89ab\ucdef\uabcd\uef4a","true":true,"false":false,"null":null,"array":[],"object":{},"address":"50 St. James Street","url":"http:\/\/www.JSON.org\/","comment":"\/\/ \/* *\/":" "," s p a c e d ":[1,2,3,4,5,6,7],"compact":[1,2,3,4,5,6,7],"jsontext":"{\"object with 1 member\":[\"array with 1 element\"]}","quotes":"" \" %22 0x22 034 "","\/\\\"\ucafe\ubabe\uab98\ufcde\ubcda\uef4a\b\f\n\r\t`1~!@#$%^&*()_+-=[]{}|;:',.\/<>?":"A key can be any string"},0.5,98.6,99.44,1066,"rosebud"] 429 | ENCODE: FROM ARRAY 430 | ["JSON Test Pattern pass1",{"object with 1 member":["array with 1 element"]},[],[],-42,true,false,null,{"integer":1234567890,"real":-9876.54321,"e":1.23456789e-13,"E":1.23456789e+34,"":0,"zero":0,"one":1,"space":" ","quote":"\"","backslash":"\\","controls":"\b\f\n\r\t","slash":"\/ & \/","alpha":"abcdefghijklmnopqrstuvwyz","ALPHA":"ABCDEFGHIJKLMNOPQRSTUVWYZ","digit":"0123456789","special":"`1~!@#$%^&*()_+-={':[,]}|;.<\/>?","hex":"\u0123\u4567\u89ab\ucdef\uabcd\uef4a","true":true,"false":false,"null":null,"array":[],"object":[],"address":"50 St. James Street","url":"http:\/\/www.JSON.org\/","comment":"\/\/ \/* *\/":" "," s p a c e d ":[1,2,3,4,5,6,7],"compact":[1,2,3,4,5,6,7],"jsontext":"{\"object with 1 member\":[\"array with 1 element\"]}","quotes":"" \" %22 0x22 034 "","\/\\\"\ucafe\ubabe\uab98\ufcde\ubcda\uef4a\b\f\n\r\t`1~!@#$%^&*()_+-=[]{}|;:',.\/<>?":"A key can be any string"},0.5,98.6,99.44,1066,"rosebud"] 431 | DECODE AGAIN: AS OBJECT 432 | array(14) { 433 | [0]=> 434 | string(23) "JSON Test Pattern pass1" 435 | [1]=> 436 | object(stdClass)#5 (1) { 437 | ["object with 1 member"]=> 438 | array(1) { 439 | [0]=> 440 | string(20) "array with 1 element" 441 | } 442 | } 443 | [2]=> 444 | object(stdClass)#6 (0) { 445 | } 446 | [3]=> 447 | array(0) { 448 | } 449 | [4]=> 450 | int(-42) 451 | [5]=> 452 | bool(true) 453 | [6]=> 454 | bool(false) 455 | [7]=> 456 | NULL 457 | [8]=> 458 | object(stdClass)#7 (31) { 459 | ["integer"]=> 460 | int(1234567890) 461 | ["real"]=> 462 | float(-9876.54321) 463 | ["e"]=> 464 | float(1.23456789E-13) 465 | ["E"]=> 466 | float(1.23456789E+34) 467 | ["_empty_"]=> 468 | int(0) 469 | ["zero"]=> 470 | int(0) 471 | ["one"]=> 472 | int(1) 473 | ["space"]=> 474 | string(1) " " 475 | ["quote"]=> 476 | string(1) """ 477 | ["backslash"]=> 478 | string(1) "\" 479 | ["controls"]=> 480 | string(5) " 481 | " 482 | ["slash"]=> 483 | string(5) "/ & /" 484 | ["alpha"]=> 485 | string(25) "abcdefghijklmnopqrstuvwyz" 486 | ["ALPHA"]=> 487 | string(25) "ABCDEFGHIJKLMNOPQRSTUVWYZ" 488 | ["digit"]=> 489 | string(10) "0123456789" 490 | ["special"]=> 491 | string(31) "`1~!@#$%^&*()_+-={':[,]}|;.?" 492 | ["hex"]=> 493 | string(17) "ģ䕧覫췯ꯍ" 494 | ["true"]=> 495 | bool(true) 496 | ["false"]=> 497 | bool(false) 498 | ["null"]=> 499 | NULL 500 | ["array"]=> 501 | array(0) { 502 | } 503 | ["object"]=> 504 | object(stdClass)#8 (0) { 505 | } 506 | ["address"]=> 507 | string(19) "50 St. James Street" 508 | ["url"]=> 509 | string(20) "http://www.JSON.org/" 510 | ["comment"]=> 511 | string(13) "// /* */"]=> 513 | string(1) " " 514 | [" s p a c e d "]=> 515 | array(7) { 516 | [0]=> 517 | int(1) 518 | [1]=> 519 | int(2) 520 | [2]=> 521 | int(3) 522 | [3]=> 523 | int(4) 524 | [4]=> 525 | int(5) 526 | [5]=> 527 | int(6) 528 | [6]=> 529 | int(7) 530 | } 531 | ["compact"]=> 532 | array(7) { 533 | [0]=> 534 | int(1) 535 | [1]=> 536 | int(2) 537 | [2]=> 538 | int(3) 539 | [3]=> 540 | int(4) 541 | [4]=> 542 | int(5) 543 | [5]=> 544 | int(6) 545 | [6]=> 546 | int(7) 547 | } 548 | ["jsontext"]=> 549 | string(49) "{"object with 1 member":["array with 1 element"]}" 550 | ["quotes"]=> 551 | string(27) "" " %22 0x22 034 "" 552 | ["/\"쫾몾ꮘﳞ볚 553 | `1~!@#$%^&*()_+-=[]{}|;:',./<>?"]=> 554 | string(23) "A key can be any string" 555 | } 556 | [9]=> 557 | float(0.5) 558 | [10]=> 559 | float(98.6) 560 | [11]=> 561 | float(99.44) 562 | [12]=> 563 | int(1066) 564 | [13]=> 565 | string(7) "rosebud" 566 | } 567 | DECODE AGAIN: AS ARRAY 568 | array(14) { 569 | [0]=> 570 | string(23) "JSON Test Pattern pass1" 571 | [1]=> 572 | array(1) { 573 | ["object with 1 member"]=> 574 | array(1) { 575 | [0]=> 576 | string(20) "array with 1 element" 577 | } 578 | } 579 | [2]=> 580 | array(0) { 581 | } 582 | [3]=> 583 | array(0) { 584 | } 585 | [4]=> 586 | int(-42) 587 | [5]=> 588 | bool(true) 589 | [6]=> 590 | bool(false) 591 | [7]=> 592 | NULL 593 | [8]=> 594 | array(31) { 595 | ["integer"]=> 596 | int(1234567890) 597 | ["real"]=> 598 | float(-9876.54321) 599 | ["e"]=> 600 | float(1.23456789E-13) 601 | ["E"]=> 602 | float(1.23456789E+34) 603 | [""]=> 604 | int(0) 605 | ["zero"]=> 606 | int(0) 607 | ["one"]=> 608 | int(1) 609 | ["space"]=> 610 | string(1) " " 611 | ["quote"]=> 612 | string(1) """ 613 | ["backslash"]=> 614 | string(1) "\" 615 | ["controls"]=> 616 | string(5) " 617 | " 618 | ["slash"]=> 619 | string(5) "/ & /" 620 | ["alpha"]=> 621 | string(25) "abcdefghijklmnopqrstuvwyz" 622 | ["ALPHA"]=> 623 | string(25) "ABCDEFGHIJKLMNOPQRSTUVWYZ" 624 | ["digit"]=> 625 | string(10) "0123456789" 626 | ["special"]=> 627 | string(31) "`1~!@#$%^&*()_+-={':[,]}|;.?" 628 | ["hex"]=> 629 | string(17) "ģ䕧覫췯ꯍ" 630 | ["true"]=> 631 | bool(true) 632 | ["false"]=> 633 | bool(false) 634 | ["null"]=> 635 | NULL 636 | ["array"]=> 637 | array(0) { 638 | } 639 | ["object"]=> 640 | array(0) { 641 | } 642 | ["address"]=> 643 | string(19) "50 St. James Street" 644 | ["url"]=> 645 | string(20) "http://www.JSON.org/" 646 | ["comment"]=> 647 | string(13) "// /* */"]=> 649 | string(1) " " 650 | [" s p a c e d "]=> 651 | array(7) { 652 | [0]=> 653 | int(1) 654 | [1]=> 655 | int(2) 656 | [2]=> 657 | int(3) 658 | [3]=> 659 | int(4) 660 | [4]=> 661 | int(5) 662 | [5]=> 663 | int(6) 664 | [6]=> 665 | int(7) 666 | } 667 | ["compact"]=> 668 | array(7) { 669 | [0]=> 670 | int(1) 671 | [1]=> 672 | int(2) 673 | [2]=> 674 | int(3) 675 | [3]=> 676 | int(4) 677 | [4]=> 678 | int(5) 679 | [5]=> 680 | int(6) 681 | [6]=> 682 | int(7) 683 | } 684 | ["jsontext"]=> 685 | string(49) "{"object with 1 member":["array with 1 element"]}" 686 | ["quotes"]=> 687 | string(27) "" " %22 0x22 034 "" 688 | ["/\"쫾몾ꮘﳞ볚 689 | `1~!@#$%^&*()_+-=[]{}|;:',./<>?"]=> 690 | string(23) "A key can be any string" 691 | } 692 | [9]=> 693 | float(0.5) 694 | [10]=> 695 | float(98.6) 696 | [11]=> 697 | float(99.44) 698 | [12]=> 699 | int(1066) 700 | [13]=> 701 | string(7) "rosebud" 702 | } 703 | --------------------------------------------------------------------------------