From 6837f00cfea37d7018b5d24df74c83e26a4a7b43 Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Tue, 11 Jan 2022 22:08:17 +0100 Subject: [PATCH] seriously simplify the buffer writer by not accepting a ref to a buffer --- ion.c | 18 ++++++---- ion.stub.php | 7 ++-- ion_arginfo.h | 12 +++++-- ion_private.h | 63 ++++++++++------------------------ tests/Symbol/Table/Local.phpt | 7 ++-- tests/Symbol/Table/Shared.phpt | 9 +++-- tests/Writer/Buffer.phpt | 17 +++++---- 7 files changed, 59 insertions(+), 74 deletions(-) diff --git a/ion.c b/ion.c index 5712668..3cd4684 100644 --- a/ion.c +++ b/ion.c @@ -1615,17 +1615,12 @@ static ZEND_METHOD(ion_Writer_Buffer_Writer, __construct) php_ion_writer *obj = php_ion_obj(writer, Z_OBJ_P(ZEND_THIS)); PTR_CHECK(obj); - zval *ref; - ZEND_PARSE_PARAMETERS_START(1, 2) - Z_PARAM_ZVAL(ref) + ZEND_PARSE_PARAMETERS_START(0, 1) Z_PARAM_OPTIONAL Z_PARAM_OBJ_OF_CLASS_OR_NULL(obj->opt, ce_Writer_Options) ZEND_PARSE_PARAMETERS_END(); obj->type = BUFFER_WRITER; - ZVAL_COPY(&obj->buffer.val, ref); - zval_dtor(Z_REFVAL_P(ref)); - php_ion_writer_ctor(obj); } static ZEND_METHOD(ion_Writer_Buffer_Writer, getBuffer) @@ -1635,7 +1630,16 @@ static ZEND_METHOD(ion_Writer_Buffer_Writer, getBuffer) ZEND_PARSE_PARAMETERS_NONE(); - RETVAL_STR(zend_string_dup(obj->buffer.str.s, 0)); + RETVAL_STR_COPY(obj->buffer.str.s); +} +static ZEND_METHOD(ion_Writer_Buffer_Writer, resetBuffer) +{ + php_ion_writer *obj = php_ion_obj(writer, Z_OBJ_P(ZEND_THIS)); + OBJ_CHECK(obj); + + ZEND_PARSE_PARAMETERS_NONE(); + + php_ion_writer_buffer_reset(obj); } static ZEND_METHOD(ion_Writer_Stream_Writer, __construct) { diff --git a/ion.stub.php b/ion.stub.php index cc9f288..7818dde 100644 --- a/ion.stub.php +++ b/ion.stub.php @@ -511,20 +511,17 @@ abstract class Writer implements \ion\Writer { namespace ion\Writer; interface Buffer extends \ion\Writer { public function getBuffer() : string; + public function resetBuffer() : void; } namespace ion\Writer\Buffer; class Writer extends \ion\Writer\Writer implements \ion\Writer\Buffer { - /** @param ref $buffer */ public function __construct( - ?string &$buffer, ?\ion\Writer\Options $options = null, ) {} - /** - * @return string a _copy_ of $buffer passed to the constructor - */ public function getBuffer() : string {} + public function resetBuffer() : void {} } namespace ion\Writer; diff --git a/ion_arginfo.h b/ion_arginfo.h index bfd758e..5015b69 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: 8cd99962a32b5321624d6cb043fb60ff13f93738 */ + * Stub hash: aafe212ff9dd7fd15753fa5b6a3c127a51073241 */ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_ion_Symbol_Table_PHP, 0, 0, ion\\Symbol\\Table, 0) ZEND_END_ARG_INFO() @@ -495,13 +495,16 @@ ZEND_END_ARG_INFO() #define arginfo_class_ion_Writer_Buffer_getBuffer arginfo_class_ion_Symbol_Enum_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) +#define arginfo_class_ion_Writer_Buffer_resetBuffer arginfo_class_ion_Reader_Reader_rewind + +ZEND_BEGIN_ARG_INFO_EX(arginfo_class_ion_Writer_Buffer_Writer___construct, 0, 0, 0) 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_Symbol_Enum_toString +#define arginfo_class_ion_Writer_Buffer_Writer_resetBuffer arginfo_class_ion_Reader_Reader_rewind + #define arginfo_class_ion_Writer_Stream_getStream arginfo_class_ion_Symbol_Table_Local___construct ZEND_BEGIN_ARG_INFO_EX(arginfo_class_ion_Writer_Stream_Writer___construct, 0, 0, 1) @@ -636,6 +639,7 @@ static ZEND_METHOD(ion_Writer_Writer, writeOne); static ZEND_METHOD(ion_Writer_Writer, writeAll); static ZEND_METHOD(ion_Writer_Buffer_Writer, __construct); static ZEND_METHOD(ion_Writer_Buffer_Writer, getBuffer); +static ZEND_METHOD(ion_Writer_Buffer_Writer, resetBuffer); static ZEND_METHOD(ion_Writer_Stream_Writer, __construct); static ZEND_METHOD(ion_Writer_Stream_Writer, getStream); static ZEND_METHOD(ion_Serializer_PHP, __construct); @@ -960,6 +964,7 @@ static const zend_function_entry class_ion_Writer_Writer_methods[] = { static const zend_function_entry class_ion_Writer_Buffer_methods[] = { ZEND_ABSTRACT_ME_WITH_FLAGS(ion_Writer_Buffer, getBuffer, arginfo_class_ion_Writer_Buffer_getBuffer, ZEND_ACC_PUBLIC|ZEND_ACC_ABSTRACT) + ZEND_ABSTRACT_ME_WITH_FLAGS(ion_Writer_Buffer, resetBuffer, arginfo_class_ion_Writer_Buffer_resetBuffer, ZEND_ACC_PUBLIC|ZEND_ACC_ABSTRACT) ZEND_FE_END }; @@ -967,6 +972,7 @@ static const zend_function_entry class_ion_Writer_Buffer_methods[] = { static const zend_function_entry class_ion_Writer_Buffer_Writer_methods[] = { ZEND_ME(ion_Writer_Buffer_Writer, __construct, arginfo_class_ion_Writer_Buffer_Writer___construct, ZEND_ACC_PUBLIC) ZEND_ME(ion_Writer_Buffer_Writer, getBuffer, arginfo_class_ion_Writer_Buffer_Writer_getBuffer, ZEND_ACC_PUBLIC) + ZEND_ME(ion_Writer_Buffer_Writer, resetBuffer, arginfo_class_ion_Writer_Buffer_Writer_resetBuffer, ZEND_ACC_PUBLIC) ZEND_FE_END }; diff --git a/ion_private.h b/ion_private.h index b168f90..928b826 100644 --- a/ion_private.h +++ b/ion_private.h @@ -11,6 +11,7 @@ */ #include "php.h" +#include "ext/standard/php_var.h" #include "ext/date/php_date.h" #if PHP_DEBUG @@ -1333,7 +1334,6 @@ typedef struct php_ion_writer { } type; union { struct { - zval val; smart_str str; } buffer; struct { @@ -1360,18 +1360,6 @@ LOCAL iERR php_ion_writer_stream_handler(struct _ion_user_stream *user) return IERR_OK; } -#define REF_STR() do { \ - ZVAL_NEW_STR(ref, obj->buffer.str.s); \ - GC_ADDREF(obj->buffer.str.s); \ -} while (0) - -#define NEW_REF_STR() do {\ - if (Z_STR_P(ref) != obj->buffer.str.s) { \ - zval_ptr_dtor(ref); \ - REF_STR(); \ - } \ -} while(0) - LOCAL void php_ion_writer_stream_init(php_ion_writer *obj, php_ion_writer_options *opt) { PTR_CHECK(obj->stream.ptr); @@ -1380,46 +1368,34 @@ LOCAL void php_ion_writer_stream_init(php_ion_writer *obj, php_ion_writer_option obj->stream.buf.length = opt ? opt->opt.allocation_page_size : 0x1000; obj->stream.buf.value = emalloc(obj->stream.buf.length); } + LOCAL void php_ion_writer_buffer_init(php_ion_writer *obj) { - zval *ref = &obj->buffer.val; - ZVAL_DEREF(ref); + smart_str_alloc(&obj->buffer.str, 0, 0); + smart_str_0(&obj->buffer.str); +} +LOCAL void php_ion_writer_buffer_reset(php_ion_writer *obj) +{ + smart_str_free(&obj->buffer.str); + memset(&obj->buffer.str, 0, sizeof(obj->buffer.str)); smart_str_alloc(&obj->buffer.str, 0, 0); smart_str_0(&obj->buffer.str); - REF_STR(); } LOCAL void php_ion_writer_buffer_grow(php_ion_writer *obj) { - zval *ref = &obj->buffer.val; - ZVAL_DEREF(ref); - - switch (GC_REFCOUNT(obj->buffer.str.s)) { - case 2: - // nothing to do - break; - case 1: - // we've been separated - GC_ADDREF(obj->buffer.str.s); - break; - default: - // we have to separate - fprintf(stderr, "SEPARATE\n"); - obj->buffer.str.s = zend_string_dup(obj->buffer.str.s, 0); - break; - } - - zend_string *old = obj->buffer.str.s; - GC_DELREF(old); - smart_str_erealloc(&obj->buffer.str, obj->buffer.str.a << 1); - if (old == obj->buffer.str.s) { - GC_ADDREF(old); - } else if(old == Z_STR_P(ref)) { - ZVAL_NULL(ref); + if (GC_REFCOUNT(obj->buffer.str.s) > 1) { + zend_string *keep = obj->buffer.str.s; + obj->buffer.str.s = NULL; + smart_str_alloc(&obj->buffer.str, obj->buffer.str.a << 1, 0); + memcpy(obj->buffer.str.s->val, keep->val, keep->len + 1); + obj->buffer.str.s->len = keep->len; + smart_str_0(&obj->buffer.str); + zend_string_release(keep); + } else { + smart_str_erealloc(&obj->buffer.str, obj->buffer.str.a << 1); } - - NEW_REF_STR(); } LOCAL iERR php_ion_writer_buffer_handler(struct _ion_user_stream *user) @@ -1512,7 +1488,6 @@ LOCAL void php_ion_writer_dtor(php_ion_writer *obj) smart_str_0(&obj->buffer.str); zend_string_release(obj->buffer.str.s); } - zval_ptr_dtor(&obj->buffer.val); } } diff --git a/tests/Symbol/Table/Local.phpt b/tests/Symbol/Table/Local.phpt index 25b0cb5..9c6b03e 100644 --- a/tests/Symbol/Table/Local.phpt +++ b/tests/Symbol/Table/Local.phpt @@ -6,8 +6,7 @@ ion TEST writeSymbol("local1"); $w->writeSymbol("local1"); @@ -16,7 +15,7 @@ $w->writeSymbol("local2"); $w->finish(); -foreach (str_split($buf, 8) as $line) { +foreach (str_split($w->getBuffer(), 8) as $line) { printf("%-26s", chunk_split(bin2hex($line), 2, " ")); foreach (str_split($line) as $byte) { echo $byte >= ' ' && $byte <= '~' ? $byte : "."; @@ -26,7 +25,7 @@ foreach (str_split($buf, 8) as $line) { echo "\n"; $u = new ion\Unserializer\PHP(multiSequence: true); -var_dump($u->unserialize($buf)); +var_dump($u->unserialize($w->getBuffer())); ?> DONE diff --git a/tests/Symbol/Table/Shared.phpt b/tests/Symbol/Table/Shared.phpt index b6a2a48..1a052db 100644 --- a/tests/Symbol/Table/Shared.phpt +++ b/tests/Symbol/Table/Shared.phpt @@ -8,8 +8,7 @@ TEST $c = new ion\Catalog; $c->add(new ion\Symbol\Table\Shared("shared", 1, ["shared1", "shared2"])); -$w = new ion\Writer\Buffer\Writer($buf, - new ion\Writer\Options(catalog: $c, outputBinary: true)); +$w = new ion\Writer\Buffer\Writer(new ion\Writer\Options(catalog: $c, outputBinary: true)); $w->writeSymbol("shared1"); $w->writeSymbol("shared1"); @@ -18,7 +17,7 @@ $w->writeSymbol("shared2"); $w->finish(); -foreach (str_split($buf, 8) as $line) { +foreach (str_split($w->getBuffer(), 8) as $line) { printf("%-26s", chunk_split(bin2hex($line), 2, " ")); foreach (str_split($line) as $byte) { echo $byte >= ' ' && $byte <= '~' ? $byte : "."; @@ -28,7 +27,7 @@ foreach (str_split($buf, 8) as $line) { echo "\n"; $u = new ion\Unserializer\PHP(multiSequence: true); -var_dump($s = $u->unserialize($buf)); +var_dump($s = $u->unserialize($w->getBuffer())); foreach ($s as $sym) { /** @var ion\Symbol $sym */ @@ -42,7 +41,7 @@ $u = new ion\Unserializer\PHP(multiSequence: true, readerOptions: new ion\Reader\Options( catalog: $c, onContextChange: fn(ion\Reader $r) => print("on_context_change\n"))); -var_dump($u->unserialize($buf)); +var_dump($u->unserialize($w->getBuffer())); ?> DONE diff --git a/tests/Writer/Buffer.phpt b/tests/Writer/Buffer.phpt index aaa5b01..d9c870f 100644 --- a/tests/Writer/Buffer.phpt +++ b/tests/Writer/Buffer.phpt @@ -6,16 +6,21 @@ ion TEST writeTypedNull(ion\Type::Int); -var_dump($buf === $w->getBuffer()); +$w = new ion\Writer\Buffer\Writer; +for ($i = 0; $i < 100; ++$i) + $w->writeTypedNull(ion\Type::Int); +$w->flush(); +echo $w->getBuffer(),"\n"; +$w->resetBuffer(); +var_dump($w->getBuffer()); +$w->writeSymbol("bar"); $w->finish(); -echo $buf; +var_dump($w->getBuffer()); ?> - DONE --EXPECTF-- TEST -bool(true) null.int%r( null.int)*%r +string(0) "" +string(3) "bar" DONE -- 2.30.2