diff --git a/package.xml b/package.xml
index f9d2353..7e08b0d 100644
--- a/package.xml
+++ b/package.xml
@@ -18,10 +18,10 @@
yes
-->
- 2022-10-17
+ 2022-10-19
- 3.0.0
- 3.0.0
+ 4.0.0
+ 4.0.0
stable
@@ -29,14 +29,14 @@
Apache 2.0
-* Add SimdJsonValueError. In php 8.0+, it extends ValueError, and it extends Error in older php versions.
- This provides an API similar to the JSON module, which started throwing ValueError for invalid depths in php 8.0.
-* Throw SimdJsonValueError instead of emitting notices if $depth is too small or too large in all simdjson PHP functions.
- simdjson_is_valid(), simdjson_key_count() and simdjson_key_exists() now have non-null return types.
-* Throw a SimdJsonException in simdjson_key_exists on error conditions such as invalid json, to be consistent with other simdjson PHP functions.
-* Add an optional boolean `$throw_if_uncountable = false` to simdjson_key_count.
- 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.
-* Rename the parameter $assoc to $associative in simdjson_decode and simdjson_key_value, to match naming practices used in json_decode()
+* Make the `SIMDJSON_ERR_*` constants case-sensitive in all PHP versions.
+ (The code it was based on was missing the flag needed to mark constants as case sensitive before PHP 8)
+* 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.
+
+ This bug was introduced when working around test failures following a change in json pointer validation in the underlying C simdjson library.
+* "" in a JSON pointer continues to refer to the entire document.
+* "/" in a JSON pointer now properly refers to the key that is the empty string.
+* Continue to allow the non-standard omission of the leading "/" for compatibility with earlier PECL releases. This may be deprecated in a subsequent release.
@@ -83,6 +83,7 @@
+
@@ -124,6 +125,27 @@
simdjson
+
+
+ 3.0.0
+ 3.0.0
+
+
+ stable
+ stable
+
+ Apache 2.0
+
+* Add SimdJsonValueError. In php 8.0+, it extends ValueError, and it extends Error in older php versions.
+ This provides an API similar to the JSON module, which started throwing ValueError for invalid depths in php 8.0.
+* Throw SimdJsonValueError instead of emitting notices if $depth is too small or too large in all simdjson PHP functions.
+ simdjson_is_valid(), simdjson_key_count() and simdjson_key_exists() now have non-null return types.
+* Throw a SimdJsonException in simdjson_key_exists on error conditions such as invalid json, to be consistent with other simdjson PHP functions.
+* Add an optional boolean `$throw_if_uncountable = false` to simdjson_key_count.
+ 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.
+* Rename the parameter $assoc to $associative in simdjson_decode and simdjson_key_value, to match naming practices used in json_decode()
+
+
2022-10-14
diff --git a/php_simdjson.cpp b/php_simdjson.cpp
index dc9482b..021a4cc 100644
--- a/php_simdjson.cpp
+++ b/php_simdjson.cpp
@@ -244,8 +244,8 @@ ZEND_TSRMLS_CACHE_UPDATE();
/** {{{ PHP_MINIT_FUNCTION
*/
-#define SIMDJSON_REGISTER_ERROR_CODE_CONSTANT(errcode) REGISTER_LONG_CONSTANT("SIMDJSON_ERR_" #errcode, simdjson::errcode, CONST_PERSISTENT)
-#define SIMDJSON_REGISTER_CUSTOM_ERROR_CODE_CONSTANT(errcode, val) REGISTER_LONG_CONSTANT("SIMDJSON_ERR_" #errcode, (val), CONST_PERSISTENT)
+#define SIMDJSON_REGISTER_ERROR_CODE_CONSTANT(errcode) REGISTER_LONG_CONSTANT("SIMDJSON_ERR_" #errcode, simdjson::errcode, CONST_PERSISTENT | CONST_CS)
+#define SIMDJSON_REGISTER_CUSTOM_ERROR_CODE_CONSTANT(errcode, val) REGISTER_LONG_CONSTANT("SIMDJSON_ERR_" #errcode, (val), CONST_PERSISTENT | CONST_CS)
PHP_MINIT_FUNCTION (simdjson) {
simdjson_exception_ce = register_class_SimdJsonException(spl_ce_RuntimeException);
#if PHP_VERSION_ID >= 80000
diff --git a/php_simdjson.h b/php_simdjson.h
index 84d7b02..9d6ce7d 100644
--- a/php_simdjson.h
+++ b/php_simdjson.h
@@ -51,12 +51,12 @@ BEGIN_EXTERN_C()
extern zend_module_entry simdjson_module_entry;
#define phpext_simdjson_ptr &simdjson_module_entry
-#define PHP_SIMDJSON_VERSION "3.0.0"
+#define PHP_SIMDJSON_VERSION "4.0.0"
/**
* PHP_SIMDJSON_VERSION_ID has the same format as PHP_VERSION_ID: Major version * 10000 + Minor version * 100 + Patch version.
* This is meant for use by PECL extensions that depend on simdjson.
*/
-#define PHP_SIMDJSON_VERSION_ID 30000
+#define PHP_SIMDJSON_VERSION_ID 40000
#define SIMDJSON_SUPPORT_URL "https://github.com/crazyxman/simdjson_php"
diff --git a/src/simdjson_bindings.cpp b/src/simdjson_bindings.cpp
index 36af5bc..45fdf5c 100644
--- a/src/simdjson_bindings.cpp
+++ b/src/simdjson_bindings.cpp
@@ -48,7 +48,9 @@ PHP_SIMDJSON_API void php_simdjson_throw_jsonexception(simdjson_php_error_code e
static inline simdjson::simdjson_result
get_key_with_optional_prefix(simdjson::dom::element &doc, std::string_view json_pointer)
{
- auto std_pointer = (json_pointer.empty() ? "" : "/") + std::string(json_pointer.begin(), json_pointer.end());
+ /* https://www.rfc-editor.org/rfc/rfc6901.html */
+ /* TODO: Deprecate in a subsequent minor release and remove in a major release to comply with the standard. */
+ auto std_pointer = ((!json_pointer.empty() && json_pointer[0] != '/') ? "/" : "") + std::string(json_pointer.begin(), json_pointer.end());
return doc.at_pointer(std_pointer);
}
diff --git a/tests/key_value_slash.phpt b/tests/key_value_slash.phpt
new file mode 100644
index 0000000..254a2a9
--- /dev/null
+++ b/tests/key_value_slash.phpt
@@ -0,0 +1,114 @@
+--TEST--
+simdjson_key_value with int test
+--SKIPIF--
+
+--EXPECT--
+Test '/code'
+int(123)
+int(123)
+Test '/'
+bool(true)
+bool(true)
+Test ''
+object(stdClass)#2 (4) {
+ [""]=>
+ bool(true)
+ ["code"]=>
+ int(123)
+ ["values"]=>
+ array(1) {
+ [0]=>
+ object(stdClass)#3 (0) {
+ }
+ }
+ ["obj"]=>
+ object(stdClass)#4 (1) {
+ ["z"]=>
+ bool(false)
+ }
+}
+array(4) {
+ [""]=>
+ bool(true)
+ ["code"]=>
+ int(123)
+ ["values"]=>
+ array(1) {
+ [0]=>
+ array(0) {
+ }
+ }
+ ["obj"]=>
+ array(1) {
+ ["z"]=>
+ bool(false)
+ }
+}
+Test '/code'
+int(123)
+int(123)
+Test '/code/0'
+Caught SimdJsonException: Invalid JSON pointer syntax.
+Caught SimdJsonException: Invalid JSON pointer syntax.
+Test '/code/x'
+Caught SimdJsonException: Invalid JSON pointer syntax.
+Caught SimdJsonException: Invalid JSON pointer syntax.
+Test '/values'
+array(1) {
+ [0]=>
+ object(stdClass)#2 (0) {
+ }
+}
+array(1) {
+ [0]=>
+ array(0) {
+ }
+}
+Test '/values/0'
+object(stdClass)#2 (0) {
+}
+array(0) {
+}
+Test '/values/1'
+Caught SimdJsonException: Attempted to access an element of a JSON array that is beyond its length.
+Caught SimdJsonException: Attempted to access an element of a JSON array that is beyond its length.
+Test '/values/-1'
+Caught SimdJsonException: The JSON element does not have the requested type.
+Caught SimdJsonException: The JSON element does not have the requested type.
+Test '/obj'
+object(stdClass)#2 (1) {
+ ["z"]=>
+ bool(false)
+}
+array(1) {
+ ["z"]=>
+ bool(false)
+}
+Test '/obj/z'
+bool(false)
+bool(false)