Skip to content

Commit 1a673da

Browse files
authored
Merge pull request #88 from crazyxman/fix-bugs
4.0.0: Fix bugs noticed while writing documentation
2 parents 7e41838 + 4ac4c44 commit 1a673da

5 files changed

Lines changed: 154 additions & 16 deletions

File tree

package.xml

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,25 +18,25 @@
1818
<active>yes</active>
1919
</lead>
2020
-->
21-
<date>2022-10-17</date>
21+
<date>2022-10-19</date>
2222
<version>
23-
<release>3.0.0</release>
24-
<api>3.0.0</api>
23+
<release>4.0.0</release>
24+
<api>4.0.0</api>
2525
</version>
2626
<stability>
2727
<release>stable</release>
2828
<api>stable</api>
2929
</stability>
3030
<license uri="https://www.apache.org/licenses/LICENSE-2.0.html">Apache 2.0</license>
3131
<notes>
32-
* Add SimdJsonValueError. In php 8.0+, it extends ValueError, and it extends Error in older php versions.
33-
This provides an API similar to the JSON module, which started throwing ValueError for invalid depths in php 8.0.
34-
* Throw SimdJsonValueError instead of emitting notices if $depth is too small or too large in all simdjson PHP functions.
35-
simdjson_is_valid(), simdjson_key_count() and simdjson_key_exists() now have non-null return types.
36-
* Throw a SimdJsonException in simdjson_key_exists on error conditions such as invalid json, to be consistent with other simdjson PHP functions.
37-
* Add an optional boolean `$throw_if_uncountable = false` to simdjson_key_count.
38-
When this is overridden to be true, simdjson_key_count will throw a SimdJsonException if the JSON pointer refers to a value that exists but is neither an array nor an object instead of returning 0.
39-
* Rename the parameter $assoc to $associative in simdjson_decode and simdjson_key_value, to match naming practices used in json_decode()
32+
* Make the `SIMDJSON_ERR_*` constants case-sensitive in all PHP versions.
33+
(The code it was based on was missing the flag needed to mark constants as case sensitive before PHP 8)
34+
* Fix a bug that prevented using JSON pointer in `simdjson_key_count`, `simdjson_key_exists`, and `simdjson_key_value` with a leading slash https://www.rfc-editor.org/rfc/rfc6901.html.
35+
36+
This bug was introduced when working around test failures following a change in json pointer validation in the underlying C simdjson library.
37+
* "" in a JSON pointer continues to refer to the entire document.
38+
* "/" in a JSON pointer now properly refers to the key that is the empty string.
39+
* Continue to allow the non-standard omission of the leading "/" for compatibility with earlier PECL releases. This may be deprecated in a subsequent release.
4040
</notes>
4141
<contents>
4242
<dir name="/">
@@ -83,6 +83,7 @@
8383
<file name="key_value_exception.phpt" role="test"/>
8484
<file name="key_value_int.phpt" role="test"/>
8585
<file name="key_value_result.phpt" role="test"/>
86+
<file name="key_value_slash.phpt" role="test"/>
8687
<file name="uint64_overflow.phpt" role="test"/>
8788
<file name="_files/result.json" role="test"/>
8889
<dir name="compat">
@@ -124,6 +125,27 @@
124125
<providesextension>simdjson</providesextension>
125126
<extsrcrelease/>
126127
<changelog>
128+
<release>
129+
<version>
130+
<release>3.0.0</release>
131+
<api>3.0.0</api>
132+
</version>
133+
<stability>
134+
<release>stable</release>
135+
<api>stable</api>
136+
</stability>
137+
<license uri="https://www.apache.org/licenses/LICENSE-2.0.html">Apache 2.0</license>
138+
<notes>
139+
* Add SimdJsonValueError. In php 8.0+, it extends ValueError, and it extends Error in older php versions.
140+
This provides an API similar to the JSON module, which started throwing ValueError for invalid depths in php 8.0.
141+
* Throw SimdJsonValueError instead of emitting notices if $depth is too small or too large in all simdjson PHP functions.
142+
simdjson_is_valid(), simdjson_key_count() and simdjson_key_exists() now have non-null return types.
143+
* Throw a SimdJsonException in simdjson_key_exists on error conditions such as invalid json, to be consistent with other simdjson PHP functions.
144+
* Add an optional boolean `$throw_if_uncountable = false` to simdjson_key_count.
145+
When this is overridden to be true, simdjson_key_count will throw a SimdJsonException if the JSON pointer refers to a value that exists but is neither an array nor an object instead of returning 0.
146+
* Rename the parameter $assoc to $associative in simdjson_decode and simdjson_key_value, to match naming practices used in json_decode()
147+
</notes>
148+
</release>
127149
<release>
128150
<date>2022-10-14</date>
129151
<version>

php_simdjson.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -244,8 +244,8 @@ ZEND_TSRMLS_CACHE_UPDATE();
244244

245245
/** {{{ PHP_MINIT_FUNCTION
246246
*/
247-
#define SIMDJSON_REGISTER_ERROR_CODE_CONSTANT(errcode) REGISTER_LONG_CONSTANT("SIMDJSON_ERR_" #errcode, simdjson::errcode, CONST_PERSISTENT)
248-
#define SIMDJSON_REGISTER_CUSTOM_ERROR_CODE_CONSTANT(errcode, val) REGISTER_LONG_CONSTANT("SIMDJSON_ERR_" #errcode, (val), CONST_PERSISTENT)
247+
#define SIMDJSON_REGISTER_ERROR_CODE_CONSTANT(errcode) REGISTER_LONG_CONSTANT("SIMDJSON_ERR_" #errcode, simdjson::errcode, CONST_PERSISTENT | CONST_CS)
248+
#define SIMDJSON_REGISTER_CUSTOM_ERROR_CODE_CONSTANT(errcode, val) REGISTER_LONG_CONSTANT("SIMDJSON_ERR_" #errcode, (val), CONST_PERSISTENT | CONST_CS)
249249
PHP_MINIT_FUNCTION (simdjson) {
250250
simdjson_exception_ce = register_class_SimdJsonException(spl_ce_RuntimeException);
251251
#if PHP_VERSION_ID >= 80000

php_simdjson.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,12 +51,12 @@ BEGIN_EXTERN_C()
5151
extern zend_module_entry simdjson_module_entry;
5252
#define phpext_simdjson_ptr &simdjson_module_entry
5353

54-
#define PHP_SIMDJSON_VERSION "3.0.0"
54+
#define PHP_SIMDJSON_VERSION "4.0.0"
5555
/**
5656
* PHP_SIMDJSON_VERSION_ID has the same format as PHP_VERSION_ID: Major version * 10000 + Minor version * 100 + Patch version.
5757
* This is meant for use by PECL extensions that depend on simdjson.
5858
*/
59-
#define PHP_SIMDJSON_VERSION_ID 30000
59+
#define PHP_SIMDJSON_VERSION_ID 40000
6060

6161
#define SIMDJSON_SUPPORT_URL "https://github.com/crazyxman/simdjson_php"
6262

src/simdjson_bindings.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,9 @@ PHP_SIMDJSON_API void php_simdjson_throw_jsonexception(simdjson_php_error_code e
4848
static inline simdjson::simdjson_result<simdjson::dom::element>
4949
get_key_with_optional_prefix(simdjson::dom::element &doc, std::string_view json_pointer)
5050
{
51-
auto std_pointer = (json_pointer.empty() ? "" : "/") + std::string(json_pointer.begin(), json_pointer.end());
51+
/* https://www.rfc-editor.org/rfc/rfc6901.html */
52+
/* TODO: Deprecate in a subsequent minor release and remove in a major release to comply with the standard. */
53+
auto std_pointer = ((!json_pointer.empty() && json_pointer[0] != '/') ? "/" : "") + std::string(json_pointer.begin(), json_pointer.end());
5254
return doc.at_pointer(std_pointer);
5355
}
5456

tests/key_value_slash.phpt

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
--TEST--
2+
simdjson_key_value with int test
3+
--SKIPIF--
4+
<?php if (PHP_VERSION_ID < 70100) echo "skip requires php 7.1+ for empty string as object key\n";
5+
--FILE--
6+
<?php
7+
require_once __DIR__ . '/dump.inc';
8+
$json = '{"":true,"code":123,"values":[{}],"obj":{"z": false}}';
9+
$pointers = [
10+
'/code',
11+
'/',
12+
'',
13+
'/code',
14+
'/code/0',
15+
'/code/x',
16+
'/values',
17+
'/values/0',
18+
'/values/1',
19+
'/values/-1',
20+
'/obj',
21+
'/obj/z',
22+
];
23+
foreach ($pointers as $pointer) {
24+
echo "Test ", var_export($pointer, true), "\n";
25+
dump(function () use ($json, $pointer) { return simdjson_key_value($json, $pointer, false); });
26+
dump(function () use ($json, $pointer) { return simdjson_key_value($json, $pointer, true); });
27+
}
28+
29+
?>
30+
--EXPECT--
31+
Test '/code'
32+
int(123)
33+
int(123)
34+
Test '/'
35+
bool(true)
36+
bool(true)
37+
Test ''
38+
object(stdClass)#2 (4) {
39+
[""]=>
40+
bool(true)
41+
["code"]=>
42+
int(123)
43+
["values"]=>
44+
array(1) {
45+
[0]=>
46+
object(stdClass)#3 (0) {
47+
}
48+
}
49+
["obj"]=>
50+
object(stdClass)#4 (1) {
51+
["z"]=>
52+
bool(false)
53+
}
54+
}
55+
array(4) {
56+
[""]=>
57+
bool(true)
58+
["code"]=>
59+
int(123)
60+
["values"]=>
61+
array(1) {
62+
[0]=>
63+
array(0) {
64+
}
65+
}
66+
["obj"]=>
67+
array(1) {
68+
["z"]=>
69+
bool(false)
70+
}
71+
}
72+
Test '/code'
73+
int(123)
74+
int(123)
75+
Test '/code/0'
76+
Caught SimdJsonException: Invalid JSON pointer syntax.
77+
Caught SimdJsonException: Invalid JSON pointer syntax.
78+
Test '/code/x'
79+
Caught SimdJsonException: Invalid JSON pointer syntax.
80+
Caught SimdJsonException: Invalid JSON pointer syntax.
81+
Test '/values'
82+
array(1) {
83+
[0]=>
84+
object(stdClass)#2 (0) {
85+
}
86+
}
87+
array(1) {
88+
[0]=>
89+
array(0) {
90+
}
91+
}
92+
Test '/values/0'
93+
object(stdClass)#2 (0) {
94+
}
95+
array(0) {
96+
}
97+
Test '/values/1'
98+
Caught SimdJsonException: Attempted to access an element of a JSON array that is beyond its length.
99+
Caught SimdJsonException: Attempted to access an element of a JSON array that is beyond its length.
100+
Test '/values/-1'
101+
Caught SimdJsonException: The JSON element does not have the requested type.
102+
Caught SimdJsonException: The JSON element does not have the requested type.
103+
Test '/obj'
104+
object(stdClass)#2 (1) {
105+
["z"]=>
106+
bool(false)
107+
}
108+
array(1) {
109+
["z"]=>
110+
bool(false)
111+
}
112+
Test '/obj/z'
113+
bool(false)
114+
bool(false)

0 commit comments

Comments
 (0)