From 276e3951449b3c4a77ad843372de4e3b1f80b6e2 Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Tue, 7 Dec 2021 16:07:08 +0100 Subject: [PATCH] improve symbol support --- ion.c | 25 +++++++++----- ion.stub.php | 7 ++-- ion_arginfo.h | 43 +++++++++++++---------- ion_private.h | 16 ++++++--- tests/Symbol.phpt | 73 ++++++++++++++++++++++++++++++++++++++++ tests/Symbol/equals.phpt | 31 +++++++++++++++++ 6 files changed, 162 insertions(+), 33 deletions(-) create mode 100644 tests/Symbol.phpt create mode 100644 tests/Symbol/equals.phpt diff --git a/ion.c b/ion.c index 1b8340d..017e88f 100644 --- a/ion.c +++ b/ion.c @@ -38,11 +38,10 @@ ZEND_METHOD(ion_Symbol_ImportLocation, __construct) { - zend_long location; php_ion_symbol_iloc *obj = php_ion_obj(symbol_iloc, Z_OBJ_P(ZEND_THIS)); - PTR_CHECK(obj); + zend_long location; ZEND_PARSE_PARAMETERS_START(2, 2) Z_PARAM_STR(obj->name) Z_PARAM_LONG(location) @@ -53,14 +52,13 @@ ZEND_METHOD(ion_Symbol_ImportLocation, __construct) } ZEND_METHOD(ion_Symbol, __construct) { - zend_long sid = -1; php_ion_symbol *obj = php_ion_obj(symbol, Z_OBJ_P(ZEND_THIS)); - PTR_CHECK(obj); - ZEND_PARSE_PARAMETERS_START(1, 3) - Z_PARAM_STR(obj->value) + zend_long sid = -1; + ZEND_PARSE_PARAMETERS_START(0, 3) Z_PARAM_OPTIONAL + Z_PARAM_STR_OR_NULL(obj->value) Z_PARAM_LONG(sid) Z_PARAM_OBJ_OF_CLASS_OR_NULL(obj->iloc, ce_Symbol_ImportLocation) ZEND_PARSE_PARAMETERS_END(); @@ -70,11 +68,10 @@ ZEND_METHOD(ion_Symbol, __construct) } ZEND_METHOD(ion_Symbol, equals) { - zend_object *other_obj; php_ion_symbol *sym = php_ion_obj(symbol, Z_OBJ_P(ZEND_THIS)); - OBJ_CHECK(sym); + zend_object *other_obj; ZEND_PARSE_PARAMETERS_START(1, 1) Z_PARAM_OBJ_OF_CLASS(other_obj, ce_Symbol) ZEND_PARSE_PARAMETERS_END(); @@ -86,6 +83,18 @@ ZEND_METHOD(ion_Symbol, equals) ION_CHECK(err); RETVAL_BOOL(eq); } +ZEND_METHOD(ion_Symbol, __toString) +{ + php_ion_symbol *sym = php_ion_obj(symbol, Z_OBJ_P(ZEND_THIS)); + OBJ_CHECK(sym); + + ZEND_PARSE_PARAMETERS_NONE(); + + if (!sym->value) { + RETURN_EMPTY_STRING(); + } + RETURN_STR(sym->value); +} ZEND_METHOD(ion_Timestamp, __construct) { php_ion_timestamp *obj = php_ion_obj(timestamp, Z_OBJ_P(ZEND_THIS)); diff --git a/ion.stub.php b/ion.stub.php index cbddd8d..99eeabd 100644 --- a/ion.stub.php +++ b/ion.stub.php @@ -76,12 +76,15 @@ enum SID : int { namespace ion; class Symbol { public function __construct( - public readonly string $value, + public readonly ?string $value = null, public readonly int $sid = -1, public readonly ?Symbol\ImportLocation $importLocation = null, ) {} - public function equals(Symbol $symbol): bool { } + public function equals(Symbol $symbol): bool {} + public function __toString() : string {} + /** @alias ion\Symbol::__toString */ + public function toString() : string {} } namespace ion\Symbol; diff --git a/ion_arginfo.h b/ion_arginfo.h index 1b600b5..5697c99 100644 --- a/ion_arginfo.h +++ b/ion_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 20996b59177d52516ad45582152909be017ba39d */ + * Stub hash: b634f10fc96ce251beeade7a41bd8531343395d5 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_ion_serialize, 0, 1, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, data, IS_MIXED, 0) @@ -16,8 +16,8 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_ion_Symbol_ImportLocation___construct, 0, 0 ZEND_ARG_TYPE_INFO(0, location, IS_LONG, 0) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_INFO_EX(arginfo_class_ion_Symbol___construct, 0, 0, 1) - ZEND_ARG_TYPE_INFO(0, value, IS_STRING, 0) +ZEND_BEGIN_ARG_INFO_EX(arginfo_class_ion_Symbol___construct, 0, 0, 0) + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, value, IS_STRING, 1, "null") ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, sid, IS_LONG, 0, "-1") ZEND_ARG_OBJ_INFO_WITH_DEFAULT_VALUE(0, importLocation, ion\\Symbol\\ImportLocation, 1, "null") ZEND_END_ARG_INFO() @@ -26,6 +26,11 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_ion_Symbol_equals, 0, 1, _ ZEND_ARG_OBJ_INFO(0, symbol, ion\\Symbol, 0) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_ion_Symbol___toString, 0, 0, IS_STRING, 0) +ZEND_END_ARG_INFO() + +#define arginfo_class_ion_Symbol_toString arginfo_class_ion_Symbol___toString + ZEND_BEGIN_ARG_INFO_EX(arginfo_class_ion_Decimal_Context___construct, 0, 0, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, bits, IS_LONG, 0, "128") ZEND_END_ARG_INFO() @@ -42,10 +47,9 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_ion_Decimal_isInt, 0, 0, _IS_BOOL, 0) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_ion_Decimal___toString, 0, 0, IS_STRING, 0) -ZEND_END_ARG_INFO() +#define arginfo_class_ion_Decimal___toString arginfo_class_ion_Symbol___toString -#define arginfo_class_ion_Decimal_toString arginfo_class_ion_Decimal___toString +#define arginfo_class_ion_Decimal_toString arginfo_class_ion_Symbol___toString ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_ion_Decimal_toInt, 0, 0, IS_LONG, 0) ZEND_END_ARG_INFO() @@ -57,7 +61,7 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_ion_Timestamp___construct, 0, 0, 1) ZEND_ARG_OBJ_INFO_WITH_DEFAULT_VALUE(0, timezone, DateTimeZone, 1, "null") ZEND_END_ARG_INFO() -#define arginfo_class_ion_Timestamp___toString arginfo_class_ion_Decimal___toString +#define arginfo_class_ion_Timestamp___toString arginfo_class_ion_Symbol___toString ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_class_ion_Reader_getType, 0, 0, ion\\Type, 0) ZEND_END_ARG_INFO() @@ -72,7 +76,7 @@ ZEND_END_ARG_INFO() #define arginfo_class_ion_Reader_isInStruct arginfo_class_ion_Decimal_isInt -#define arginfo_class_ion_Reader_getFieldName arginfo_class_ion_Decimal___toString +#define arginfo_class_ion_Reader_getFieldName arginfo_class_ion_Symbol___toString ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_class_ion_Reader_getFieldNameSymbol, 0, 0, ion\\Symbol, 0) ZEND_END_ARG_INFO() @@ -110,14 +114,14 @@ ZEND_END_ARG_INFO() #define arginfo_class_ion_Reader_readSymbol arginfo_class_ion_Reader_getFieldNameSymbol -#define arginfo_class_ion_Reader_readString arginfo_class_ion_Decimal___toString +#define arginfo_class_ion_Reader_readString arginfo_class_ion_Symbol___toString ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_ion_Reader_readStringPart, 0, 1, _IS_BOOL, 0) ZEND_ARG_INFO(1, string) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, length, IS_LONG, 0, "0x1000") ZEND_END_ARG_INFO() -#define arginfo_class_ion_Reader_readLob arginfo_class_ion_Decimal___toString +#define arginfo_class_ion_Reader_readLob arginfo_class_ion_Symbol___toString #define arginfo_class_ion_Reader_readLobPart arginfo_class_ion_Reader_readStringPart @@ -177,7 +181,7 @@ ZEND_END_ARG_INFO() #define arginfo_class_ion_Reader_Reader_isInStruct arginfo_class_ion_Decimal_isInt -#define arginfo_class_ion_Reader_Reader_getFieldName arginfo_class_ion_Decimal___toString +#define arginfo_class_ion_Reader_Reader_getFieldName arginfo_class_ion_Symbol___toString #define arginfo_class_ion_Reader_Reader_getFieldNameSymbol arginfo_class_ion_Reader_getFieldNameSymbol @@ -205,11 +209,11 @@ ZEND_END_ARG_INFO() #define arginfo_class_ion_Reader_Reader_readSymbol arginfo_class_ion_Reader_getFieldNameSymbol -#define arginfo_class_ion_Reader_Reader_readString arginfo_class_ion_Decimal___toString +#define arginfo_class_ion_Reader_Reader_readString arginfo_class_ion_Symbol___toString #define arginfo_class_ion_Reader_Reader_readStringPart arginfo_class_ion_Reader_readStringPart -#define arginfo_class_ion_Reader_Reader_readLob arginfo_class_ion_Decimal___toString +#define arginfo_class_ion_Reader_Reader_readLob arginfo_class_ion_Symbol___toString #define arginfo_class_ion_Reader_Reader_readLobPart arginfo_class_ion_Reader_readStringPart @@ -223,14 +227,14 @@ ZEND_END_ARG_INFO() #define arginfo_class_ion_Reader_Reader_getValueLength arginfo_class_ion_Decimal_toInt -#define arginfo_class_ion_Reader_Buffer_getBuffer arginfo_class_ion_Decimal___toString +#define arginfo_class_ion_Reader_Buffer_getBuffer arginfo_class_ion_Symbol___toString ZEND_BEGIN_ARG_INFO_EX(arginfo_class_ion_Reader_Buffer_Reader___construct, 0, 0, 1) ZEND_ARG_TYPE_INFO(0, buffer, IS_STRING, 0) ZEND_ARG_OBJ_INFO_WITH_DEFAULT_VALUE(0, options, ion\\Reader\\Options, 1, "null") ZEND_END_ARG_INFO() -#define arginfo_class_ion_Reader_Buffer_Reader_getBuffer arginfo_class_ion_Decimal___toString +#define arginfo_class_ion_Reader_Buffer_Reader_getBuffer arginfo_class_ion_Symbol___toString ZEND_BEGIN_ARG_INFO_EX(arginfo_class_ion_Reader_Stream_getStream, 0, 0, 0) ZEND_END_ARG_INFO() @@ -391,14 +395,14 @@ ZEND_END_ARG_INFO() #define arginfo_class_ion_Writer_Writer_writeAll arginfo_class_ion_Writer_writeOne -#define arginfo_class_ion_Writer_Buffer_getBuffer arginfo_class_ion_Decimal___toString +#define arginfo_class_ion_Writer_Buffer_getBuffer arginfo_class_ion_Symbol___toString ZEND_BEGIN_ARG_INFO_EX(arginfo_class_ion_Writer_Buffer_Writer___construct, 0, 0, 1) ZEND_ARG_TYPE_INFO(1, buffer, IS_STRING, 1) ZEND_ARG_OBJ_INFO_WITH_DEFAULT_VALUE(0, options, ion\\Writer\\Options, 1, "null") ZEND_END_ARG_INFO() -#define arginfo_class_ion_Writer_Buffer_Writer_getBuffer arginfo_class_ion_Decimal___toString +#define arginfo_class_ion_Writer_Buffer_Writer_getBuffer arginfo_class_ion_Symbol___toString #define arginfo_class_ion_Writer_Stream_getStream arginfo_class_ion_Reader_Stream_getStream @@ -437,6 +441,7 @@ ZEND_FUNCTION(ion_unserialize); ZEND_METHOD(ion_Symbol_ImportLocation, __construct); ZEND_METHOD(ion_Symbol, __construct); ZEND_METHOD(ion_Symbol, equals); +ZEND_METHOD(ion_Symbol, __toString); ZEND_METHOD(ion_Decimal_Context, __construct); ZEND_METHOD(ion_Decimal, __construct); ZEND_METHOD(ion_Decimal, equals); @@ -559,6 +564,8 @@ static const zend_function_entry class_ion_Symbol_System_SID_methods[] = { static const zend_function_entry class_ion_Symbol_methods[] = { ZEND_ME(ion_Symbol, __construct, arginfo_class_ion_Symbol___construct, ZEND_ACC_PUBLIC) ZEND_ME(ion_Symbol, equals, arginfo_class_ion_Symbol_equals, ZEND_ACC_PUBLIC) + ZEND_ME(ion_Symbol, __toString, arginfo_class_ion_Symbol___toString, ZEND_ACC_PUBLIC) + ZEND_MALIAS(ion_Symbol, toString, __toString, arginfo_class_ion_Symbol_toString, ZEND_ACC_PUBLIC) ZEND_FE_END }; @@ -1074,7 +1081,7 @@ static zend_class_entry *register_class_ion_Symbol(void) zval property_value_default_value; ZVAL_UNDEF(&property_value_default_value); zend_string *property_value_name = zend_string_init("value", sizeof("value") - 1, 1); - zend_declare_typed_property(class_entry, property_value_name, &property_value_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_READONLY, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); + zend_declare_typed_property(class_entry, property_value_name, &property_value_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_READONLY, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING|MAY_BE_NULL)); zend_string_release(property_value_name); zval property_sid_default_value; diff --git a/ion_private.h b/ion_private.h index 5b6a461..98a3291 100644 --- a/ion_private.h +++ b/ion_private.h @@ -242,8 +242,8 @@ static inline ION_STRING *ion_string_from_cstr(ION_STRING *is, const char *s, si static inline ION_STRING *ion_string_from_zend(ION_STRING *is, const zend_string *zs) { - is->length = ZSTR_LEN(zs); - is->value = (BYTE *) ZSTR_VAL(zs); + is->length = zs ? zs->len : 0; + is->value = (BYTE *) (zs ? zs->val : NULL); return is; } @@ -312,7 +312,11 @@ static inline void php_ion_symbol_ctor(php_ion_symbol *obj) { zend_update_property_long(obj->std.ce, &obj->std, ZEND_STRL("sid"), obj->sym.sid); - zend_update_property_str(obj->std.ce, &obj->std, ZEND_STRL("value"), obj->value); + if (obj->value) { + zend_update_property_str(obj->std.ce, &obj->std, ZEND_STRL("value"), obj->value); + } else{ + zend_update_property_null(obj->std.ce, &obj->std, ZEND_STRL("value")); + } ion_string_from_zend(&obj->sym.value, obj->value); if (obj->iloc) { update_property_obj(&obj->std, ZEND_STRL("importLocation"), obj->iloc); @@ -324,7 +328,9 @@ static inline void php_ion_symbol_ctor(php_ion_symbol *obj) static inline void php_ion_symbol_dtor(php_ion_symbol *obj) { - zend_string_release(obj->value); + if (obj->value) { + zend_string_release(obj->value); + } } static inline void php_ion_symbol_zval(ION_SYMBOL *sym_ptr, zval *return_value) @@ -493,7 +499,7 @@ static inline timelib_time* php_time_from_ion(const ION_TIMESTAMP *ts, decContex } if (fmt) { - fmt = php_dt_format_from_precision(ts->precision); + *fmt = php_dt_format_from_precision(ts->precision); } return time; } diff --git a/tests/Symbol.phpt b/tests/Symbol.phpt new file mode 100644 index 0000000..7c0adaa --- /dev/null +++ b/tests/Symbol.phpt @@ -0,0 +1,73 @@ +--TEST-- +ion\Symbol +--EXTENSIONS-- +ion +--FILE-- +TEST +sid); +var_dump($s=new Symbol("s"), (string)$s, $s->sid); +var_dump($s=new Symbol("s", 1), (string)$s, $s->sid); +var_dump($s=new Symbol(1, 2), (string)$s, $s->sid); + +?> +DONE +--EXPECTF-- +TEST +object(ion\Symbol)#%d (3) { + ["value"]=> + NULL + ["sid"]=> + int(-1) + ["importLocation"]=> + NULL +} +object(ion\Symbol)#%d (3) { + ["value"]=> + NULL + ["sid"]=> + int(-1) + ["importLocation"]=> + NULL +} +string(0) "" +int(-1) +object(ion\Symbol)#%d (3) { + ["value"]=> + string(1) "s" + ["sid"]=> + int(-1) + ["importLocation"]=> + NULL +} +string(1) "s" +int(-1) +object(ion\Symbol)#%d (3) { + ["value"]=> + string(1) "s" + ["sid"]=> + int(1) + ["importLocation"]=> + NULL +} +string(1) "s" +int(1) +object(ion\Symbol)#%d (3) { + ["value"]=> + string(1) "1" + ["sid"]=> + int(2) + ["importLocation"]=> + NULL +} +string(1) "1" +int(2) +DONE diff --git a/tests/Symbol/equals.phpt b/tests/Symbol/equals.phpt new file mode 100644 index 0000000..45571ab --- /dev/null +++ b/tests/Symbol/equals.phpt @@ -0,0 +1,31 @@ +--TEST-- +ion\Symbol::equals +--EXTENSIONS-- +ion +--FILE-- +TEST +equals(new Symbol("1"))); + +var_dump((new Symbol(1, 123))->equals(new Symbol("1", 321))); + +var_dump(new Symbol(1) == new Symbol(2)); +var_dump((new Symbol(1))->equals(new Symbol(2))); + +// All local symbols with unknown text are equivalent to each other (and to symbol zero). +var_dump((new Symbol(sid:123))->equals(new Symbol(sid:321))); + +?> +DONE +--EXPECT-- +TEST +bool(true) +bool(true) +bool(true) +bool(false) +bool(false) +bool(true) +DONE -- 2.30.2