Skip to content

Commit

Permalink
ExtTokens stub correctly iterates over a inner iterator
Browse files Browse the repository at this point in the history
  • Loading branch information
halaxa committed May 14, 2023
1 parent 734f883 commit dae6da9
Show file tree
Hide file tree
Showing 5 changed files with 110 additions and 96 deletions.
36 changes: 7 additions & 29 deletions ext/jsonmachine/jsonmachine.c
Original file line number Diff line number Diff line change
Expand Up @@ -118,11 +118,7 @@ PHP_FUNCTION(jsonmachine_next_token)
ZVAL_LONG(zLastIndex, 0);
}

static zend_always_inline exttokens_object *php_exttokens_fetch_object(zend_object *obj) {
return (exttokens_object *)((char*)(obj) - XtOffsetOf(exttokens_object, std));
}
#define Z_EXTTOKENS_OBJ_P(zv) php_exttokens_fetch_object(Z_OBJ_P(zv))
#define XZ_EXTTOKENS_OBJ_P(zv) ((exttokens_object *)Z_OBJ_P((zv)))->iterator
#define Z_EXTTOKENS_OBJ_P(zv) ((exttokens_object *)Z_OBJ_P((zv)))

PHP_METHOD(ExtTokens, __construct)
{
Expand All @@ -139,7 +135,7 @@ PHP_METHOD(ExtTokens, current)
exttokens_object *objval = Z_EXTTOKENS_OBJ_P(getThis());
zval retval;
zend_call_method_with_0_params(Z_OBJ_P(&objval->iterator), Z_OBJCE_P(&objval->iterator), NULL, "current", &retval);
RETURN_ZVAL(&retval, 0, 0); // Return the value obtained from the call to 'current' and don't try to copy/free it
RETURN_ZVAL(&retval, 0, 0);
}

PHP_METHOD(ExtTokens, next)
Expand All @@ -153,15 +149,15 @@ PHP_METHOD(ExtTokens, key)
exttokens_object *objval = Z_EXTTOKENS_OBJ_P(getThis());
zval retval;
zend_call_method_with_0_params(Z_OBJ_P(&objval->iterator), Z_OBJCE_P(&objval->iterator), NULL, "key", &retval);
RETURN_ZVAL(&retval, 0, 0); // Return the value obtained from the call to 'key' and don't try to copy/free it
RETURN_ZVAL(&retval, 0, 0);
}

PHP_METHOD(ExtTokens, valid)
{
exttokens_object *objval = Z_EXTTOKENS_OBJ_P(getThis());
zval retval;
zend_call_method_with_0_params(Z_OBJ_P(&objval->iterator), Z_OBJCE_P(&objval->iterator), NULL, "valid", &retval);
RETURN_BOOL(Z_TYPE(retval) == IS_TRUE); // Returns the boolean value of the valid method's return value
RETURN_BOOL(Z_TYPE(retval) == IS_TRUE);
}

PHP_METHOD(ExtTokens, rewind)
Expand Down Expand Up @@ -230,34 +226,16 @@ void init_char_maps()
colonCommaBracket[uc(',')] = true;
}

//static const zend_function_entry exttokens_methods[] = {
// PHP_ME(ExtTokens, __construct, arginfo_exttokens_construct, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR)
// PHP_ME(ExtTokens, current, arginfo_exttokens_void, ZEND_ACC_PUBLIC)
// PHP_ME(ExtTokens, next, arginfo_exttokens_void, ZEND_ACC_PUBLIC)
// PHP_ME(ExtTokens, key, arginfo_exttokens_void, ZEND_ACC_PUBLIC)
// PHP_ME(ExtTokens, valid, arginfo_exttokens_void, ZEND_ACC_PUBLIC)
// PHP_ME(ExtTokens, rewind, arginfo_exttokens_void, ZEND_ACC_PUBLIC)
// PHP_FE_END
//};

//static zend_function_entry exttokens_methods[] = {
// PHP_ME(ExtTokens, __construct, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
// PHP_ME(ExtTokens, current, NULL, ZEND_ACC_PUBLIC)
// PHP_ME(ExtTokens, next, NULL, ZEND_ACC_PUBLIC)
// PHP_ME(ExtTokens, key, NULL, ZEND_ACC_PUBLIC)
// PHP_ME(ExtTokens, valid, NULL, ZEND_ACC_PUBLIC)
// PHP_ME(ExtTokens, rewind, NULL, ZEND_ACC_PUBLIC)
// {NULL, NULL, NULL}
//};

PHP_MINIT_FUNCTION(jsonmachine)
{
init_char_maps();

zend_class_entry ce;
INIT_CLASS_ENTRY(ce, "ExtTokens", exttokens_methods);
INIT_CLASS_ENTRY(ce, "ExtTokens", class_ExtTokens_methods);
exttokens_ce = zend_register_internal_class(&ce);
exttokens_ce->create_object = exttokens_create_handler;
zend_class_implements(exttokens_ce, 1, zend_ce_iterator);

memcpy(&exttokens_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
exttokens_object_handlers.clone_obj = NULL;

Expand Down
63 changes: 33 additions & 30 deletions ext/jsonmachine/jsonmachine.stub.php
Original file line number Diff line number Diff line change
@@ -1,37 +1,40 @@
<?php

/** @generate-function-entries */
namespace {
function jsonmachine_next_token(string $chunk, string &$tokenBuffer, bool &$escaping, bool &$inString, int &$lastIndex): ?string
{}
}
function jsonmachine_next_token(string $chunk, string &$tokenBuffer, bool &$escaping, bool &$inString, int &$lastIndex): ?string
{}



class ExtTokens implements \Iterator
{
public function __construct(Iterator $iterator)
{

}

public function current(): mixed
{
// TODO: Implement current() method.
}

public function next(): void
{
// TODO: Implement next() method.
}

public function key(): mixed
{
// TODO: Implement key() method.
}

public function valid(): bool
{
// TODO: Implement valid() method.
}

namespace JsonMachine {
class ExtTokens implements \Iterator
public function rewind(): void
{
public function current()
{
// TODO: Implement current() method.
}

public function next()
{
// TODO: Implement next() method.
}

public function key()
{
// TODO: Implement key() method.
}

public function valid()
{
// TODO: Implement valid() method.
}

public function rewind()
{
// TODO: Implement rewind() method.
}
// TODO: Implement rewind() method.
}
}
78 changes: 41 additions & 37 deletions ext/jsonmachine/jsonmachine_arginfo.h
Original file line number Diff line number Diff line change
@@ -1,49 +1,53 @@
/* This is a generated file, edit the .stub.php file instead.
* Stub hash: b169221255fda27e055e1a5d9e61f85449e0b0aa */

ZEND_BEGIN_ARG_INFO_EX(arginfo_jsonmachine_next_token, 0, 0, 5)
ZEND_ARG_TYPE_INFO(0, chunk, IS_STRING, 0)
ZEND_ARG_TYPE_INFO(1, tokenBuffer, IS_STRING, 0)
ZEND_ARG_TYPE_INFO(1, escaping, _IS_BOOL, 0)
ZEND_ARG_TYPE_INFO(1, inString, _IS_BOOL, 0)
ZEND_ARG_TYPE_INFO(1, lastIndex, IS_LONG, 0)
* Stub hash: 2e218bb2bc1f234cb273cb1e54b266dad5f0442d */

ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_jsonmachine_next_token, 0, 5, IS_STRING, 1)
ZEND_ARG_TYPE_INFO(0, chunk, IS_STRING, 0)
ZEND_ARG_TYPE_INFO(1, tokenBuffer, IS_STRING, 0)
ZEND_ARG_TYPE_INFO(1, escaping, _IS_BOOL, 0)
ZEND_ARG_TYPE_INFO(1, inString, _IS_BOOL, 0)
ZEND_ARG_TYPE_INFO(1, lastIndex, IS_LONG, 0)
ZEND_END_ARG_INFO()

ZEND_FUNCTION(jsonmachine_next_token);

static const zend_function_entry ext_functions[] = {
ZEND_FE(jsonmachine_next_token, arginfo_jsonmachine_next_token)
ZEND_FE_END
};
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_ExtTokens___construct, 0, 0, 1)
ZEND_ARG_OBJ_INFO(0, iterator, Iterator, 0)
ZEND_END_ARG_INFO()

PHP_METHOD(ExtTokens, __construct);
PHP_METHOD(ExtTokens, current);
PHP_METHOD(ExtTokens, next);
PHP_METHOD(ExtTokens, key);
PHP_METHOD(ExtTokens, valid);
PHP_METHOD(ExtTokens, rewind);
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_ExtTokens_current, 0, 0, IS_MIXED, 0)
ZEND_END_ARG_INFO()

ZEND_BEGIN_ARG_INFO(arginfo_exttokens_construct, 0)
ZEND_ARG_OBJ_INFO(0, iterator, Iterator, 0)
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_ExtTokens_next, 0, 0, IS_VOID, 0)
ZEND_END_ARG_INFO()

ZEND_BEGIN_ARG_INFO(arginfo_exttokens_void, 0)
#define arginfo_class_ExtTokens_key arginfo_class_ExtTokens_current

ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_ExtTokens_valid, 0, 0, _IS_BOOL, 0)
ZEND_END_ARG_INFO()

static const zend_function_entry exttokens_methods[] = {
PHP_ME(ExtTokens, __construct, arginfo_exttokens_construct, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR)
PHP_ME(ExtTokens, current, arginfo_exttokens_void, ZEND_ACC_PUBLIC)
PHP_ME(ExtTokens, next, arginfo_exttokens_void, ZEND_ACC_PUBLIC)
PHP_ME(ExtTokens, key, arginfo_exttokens_void, ZEND_ACC_PUBLIC)
PHP_ME(ExtTokens, valid, arginfo_exttokens_void, ZEND_ACC_PUBLIC)
PHP_ME(ExtTokens, rewind, arginfo_exttokens_void, ZEND_ACC_PUBLIC)
PHP_FE_END
#define arginfo_class_ExtTokens_rewind arginfo_class_ExtTokens_next


ZEND_FUNCTION(jsonmachine_next_token);
ZEND_METHOD(ExtTokens, __construct);
ZEND_METHOD(ExtTokens, current);
ZEND_METHOD(ExtTokens, next);
ZEND_METHOD(ExtTokens, key);
ZEND_METHOD(ExtTokens, valid);
ZEND_METHOD(ExtTokens, rewind);


static const zend_function_entry ext_functions[] = {
ZEND_FE(jsonmachine_next_token, arginfo_jsonmachine_next_token)
ZEND_FE_END
};

typedef struct _exttokens_object {
zend_object std;
zval iterator;
} exttokens_object;

zend_class_entry *exttokens_ce;
zend_object_handlers exttokens_object_handlers;
static const zend_function_entry class_ExtTokens_methods[] = {
ZEND_ME(ExtTokens, __construct, arginfo_class_ExtTokens___construct, ZEND_ACC_PUBLIC)
ZEND_ME(ExtTokens, current, arginfo_class_ExtTokens_current, ZEND_ACC_PUBLIC)
ZEND_ME(ExtTokens, next, arginfo_class_ExtTokens_next, ZEND_ACC_PUBLIC)
ZEND_ME(ExtTokens, key, arginfo_class_ExtTokens_key, ZEND_ACC_PUBLIC)
ZEND_ME(ExtTokens, valid, arginfo_class_ExtTokens_valid, ZEND_ACC_PUBLIC)
ZEND_ME(ExtTokens, rewind, arginfo_class_ExtTokens_rewind, ZEND_ACC_PUBLIC)
ZEND_FE_END
};
8 changes: 8 additions & 0 deletions ext/jsonmachine/php_jsonmachine.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,12 @@ extern zend_module_entry jsonmachine_module_entry;
ZEND_TSRMLS_CACHE_EXTERN()
# endif

typedef struct _exttokens_object {
zend_object std;
zval iterator;
} exttokens_object;

zend_class_entry *exttokens_ce;
zend_object_handlers exttokens_object_handlers;

#endif /* PHP_JSONMACHINE_H */
21 changes: 21 additions & 0 deletions test/ExtTokensTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

declare(strict_types=1);

use PHPUnit\Framework\TestCase;

/**
* @covers \ExtTokens
*/
class ExtTokensTest extends TestCase
{
public function testExtTokensIterates()
{
if ( ! class_exists(ExtTokens::class)) {
$this->markTestSkipped();
}
$extTokens = new ExtTokens(new ArrayIterator([1.0, 1, 2, 3, '5', []]));
$this->assertInstanceOf(Iterator::class, $extTokens);
$this->assertSame([1.0, 1, 2, 3, '5', []], iterator_to_array($extTokens));
}
}

0 comments on commit dae6da9

Please sign in to comment.