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)