Skip to content

Commit

Permalink
ext/zend_test: Move object handler test objects to their own file
Browse files Browse the repository at this point in the history
  • Loading branch information
Girgias committed Aug 1, 2023
1 parent e0bee2c commit 1ac82d7
Show file tree
Hide file tree
Showing 9 changed files with 423 additions and 367 deletions.
2 changes: 1 addition & 1 deletion ext/zend_test/config.m4
Expand Up @@ -4,5 +4,5 @@ PHP_ARG_ENABLE([zend-test],
[Enable zend_test extension])])

if test "$PHP_ZEND_TEST" != "no"; then
PHP_NEW_EXTENSION(zend_test, test.c observer.c fiber.c, $ext_shared,, -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1)
PHP_NEW_EXTENSION(zend_test, test.c observer.c fiber.c object_handlers.c, $ext_shared,, -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1)
fi
2 changes: 1 addition & 1 deletion ext/zend_test/config.w32
Expand Up @@ -3,6 +3,6 @@
ARG_ENABLE("zend-test", "enable zend_test extension", "no");

if (PHP_ZEND_TEST != "no") {
EXTENSION("zend_test", "test.c observer.c fiber.c", PHP_ZEND_TEST_SHARED, "/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1");
EXTENSION("zend_test", "test.c observer.c fiber.c object_handlers.c", PHP_ZEND_TEST_SHARED, "/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1");
ADD_FLAG("CFLAGS_ZEND_TEST", "/D PHP_ZEND_TEST_EXPORTS ");
}
258 changes: 258 additions & 0 deletions ext/zend_test/object_handlers.c
@@ -0,0 +1,258 @@
/*
+----------------------------------------------------------------------+
| Copyright (c) The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| https://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Authors: George Peter Banyard <girgias@php.net> |
+----------------------------------------------------------------------+
*/

#include "object_handlers.h"
#include "zend_API.h"
#include "object_handlers_arginfo.h"

/* donc refers to DoOperationNoCast */
static zend_class_entry *donc_ce;
static zend_object_handlers donc_object_handlers;

static zend_object* donc_object_create_ex(zend_class_entry* ce, zend_long l) {
zend_object *obj = zend_objects_new(ce);
object_properties_init(obj, ce);
obj->handlers = &donc_object_handlers;
ZVAL_LONG(OBJ_PROP_NUM(obj, 0), l);
return obj;
}
static zend_object *donc_object_create(zend_class_entry *ce) /* {{{ */
{
return donc_object_create_ex(ce, 0);
}
/* }}} */

static inline void donc_create(zval *target, zend_long l) /* {{{ */
{
ZVAL_OBJ(target, donc_object_create_ex(donc_ce, l));
}

#define IS_DONC(zval) \
(Z_TYPE_P(zval) == IS_OBJECT && instanceof_function(Z_OBJCE_P(zval), donc_ce))

static void donc_add(zval *result, zval *op1, zval *op2)
{
zend_long val_1;
zend_long val_2;
if (IS_DONC(op1)) {
val_1 = Z_LVAL_P(OBJ_PROP_NUM(Z_OBJ_P(op1), 0));
} else {
val_1 = zval_get_long(op1);
}
if (IS_DONC(op2)) {
val_2 = Z_LVAL_P(OBJ_PROP_NUM(Z_OBJ_P(op2), 0));
} else {
val_2 = zval_get_long(op2);
}

donc_create(result, val_1 + val_2);
}
static void donc_mul(zval *result, zval *op1, zval *op2)
{
zend_long val_1;
zend_long val_2;
if (IS_DONC(op1)) {
val_1 = Z_LVAL_P(OBJ_PROP_NUM(Z_OBJ_P(op1), 0));
} else {
val_1 = zval_get_long(op1);
}
if (IS_DONC(op2)) {
val_2 = Z_LVAL_P(OBJ_PROP_NUM(Z_OBJ_P(op2), 0));
} else {
val_2 = zval_get_long(op2);
}

donc_create(result, val_1 * val_2);
}

static zend_result donc_do_operation(zend_uchar opcode, zval *result, zval *op1, zval *op2)
{
zval op1_copy;
zend_result status;

if (result == op1) {
ZVAL_COPY_VALUE(&op1_copy, op1);
op1 = &op1_copy;
}

switch (opcode) {
case ZEND_ADD:
donc_add(result, op1, op2);
if (UNEXPECTED(EG(exception))) { status = FAILURE; }
status = SUCCESS;
break;
case ZEND_MUL:
donc_mul(result, op1, op2);
if (UNEXPECTED(EG(exception))) { status = FAILURE; }
status = SUCCESS;
break;
default:
status = FAILURE;
break;
}

if (status == SUCCESS && op1 == &op1_copy) {
zval_ptr_dtor(op1);
}

return status;
}

ZEND_METHOD(DoOperationNoCast, __construct)
{
zend_long l;

ZEND_PARSE_PARAMETERS_START(1, 1)
Z_PARAM_LONG(l)
ZEND_PARSE_PARAMETERS_END();

ZVAL_LONG(OBJ_PROP_NUM(Z_OBJ_P(ZEND_THIS), 0), l);
}

static zend_class_entry *long_castable_no_operation_ce;
static zend_object_handlers long_castable_no_operation_object_handlers;

static zend_object* long_castable_no_operation_object_create_ex(zend_class_entry* ce, zend_long l) {
zend_object *obj = zend_objects_new(ce);
object_properties_init(obj, ce);
obj->handlers = &long_castable_no_operation_object_handlers;
ZVAL_LONG(OBJ_PROP_NUM(obj, 0), l);
return obj;
}

static zend_object *long_castable_no_operation_object_create(zend_class_entry *ce)
{
return long_castable_no_operation_object_create_ex(ce, 0);
}

static zend_result long_castable_no_operation_cast_object(zend_object *obj, zval *result, int type)
{
if (type == IS_LONG) {
ZVAL_COPY(result, OBJ_PROP_NUM(obj, 0));
return SUCCESS;
}
return FAILURE;
}

ZEND_METHOD(LongCastableNoOperations, __construct)
{
zend_long l;

ZEND_PARSE_PARAMETERS_START(1, 1)
Z_PARAM_LONG(l)
ZEND_PARSE_PARAMETERS_END();

ZVAL_LONG(OBJ_PROP_NUM(Z_OBJ_P(ZEND_THIS), 0), l);
}

static zend_class_entry *float_castable_no_operation_ce;
static zend_object_handlers float_castable_no_operation_object_handlers;

static zend_object* float_castable_no_operation_object_create_ex(zend_class_entry* ce, double d) {
zend_object *obj = zend_objects_new(ce);
object_properties_init(obj, ce);
obj->handlers = &float_castable_no_operation_object_handlers;
ZVAL_DOUBLE(OBJ_PROP_NUM(obj, 0), d);
return obj;
}

static zend_object *float_castable_no_operation_object_create(zend_class_entry *ce)
{
return float_castable_no_operation_object_create_ex(ce, 0.0);
}

static zend_result float_castable_no_operation_cast_object(zend_object *obj, zval *result, int type)
{
if (type == IS_DOUBLE) {
ZVAL_COPY(result, OBJ_PROP_NUM(obj, 0));
return SUCCESS;
}
return FAILURE;
}

ZEND_METHOD(FloatCastableNoOperations, __construct)
{
double d;

ZEND_PARSE_PARAMETERS_START(1, 1)
Z_PARAM_DOUBLE(d)
ZEND_PARSE_PARAMETERS_END();

ZVAL_DOUBLE(OBJ_PROP_NUM(Z_OBJ_P(ZEND_THIS), 0), d);
}

static zend_class_entry *numeric_castable_no_operation_ce;
static zend_object_handlers numeric_castable_no_operation_object_handlers;

static zend_object* numeric_castable_no_operation_object_create_ex(zend_class_entry* ce, const zval *n) {
zend_object *obj = zend_objects_new(ce);
object_properties_init(obj, ce);
obj->handlers = &numeric_castable_no_operation_object_handlers;
ZVAL_COPY(OBJ_PROP_NUM(obj, 0), n);
return obj;
}

static zend_object *numeric_castable_no_operation_object_create(zend_class_entry *ce)
{
zval tmp;
ZVAL_LONG(&tmp, 0);
return numeric_castable_no_operation_object_create_ex(ce, &tmp);
}

static zend_result numeric_castable_no_operation_cast_object(zend_object *obj, zval *result, int type)
{
if (type == _IS_NUMBER) {
ZVAL_COPY(result, OBJ_PROP_NUM(obj, 0));
return SUCCESS;
}
return FAILURE;
}

ZEND_METHOD(NumericCastableNoOperations, __construct)
{
zval *n;

ZEND_PARSE_PARAMETERS_START(1, 1)
Z_PARAM_NUMBER(n)
ZEND_PARSE_PARAMETERS_END();

ZVAL_COPY(OBJ_PROP_NUM(Z_OBJ_P(ZEND_THIS), 0), n);
}

void zend_test_object_handlers_init(void)
{
/* DoOperationNoCast class */
donc_ce = register_class_DoOperationNoCast();
donc_ce->create_object = donc_object_create;
memcpy(&donc_object_handlers, &std_object_handlers, sizeof(zend_object_handlers));
donc_object_handlers.do_operation = donc_do_operation;

/* CastableNoOperation classes */
long_castable_no_operation_ce = register_class_LongCastableNoOperations();
long_castable_no_operation_ce->create_object = long_castable_no_operation_object_create;
memcpy(&long_castable_no_operation_object_handlers, &std_object_handlers, sizeof(zend_object_handlers));
long_castable_no_operation_object_handlers.cast_object = long_castable_no_operation_cast_object;

float_castable_no_operation_ce = register_class_FloatCastableNoOperations();
float_castable_no_operation_ce->create_object = float_castable_no_operation_object_create;
memcpy(&float_castable_no_operation_object_handlers, &std_object_handlers, sizeof(zend_object_handlers));
float_castable_no_operation_object_handlers.cast_object = float_castable_no_operation_cast_object;

numeric_castable_no_operation_ce = register_class_NumericCastableNoOperations();
numeric_castable_no_operation_ce->create_object = numeric_castable_no_operation_object_create;
memcpy(&numeric_castable_no_operation_object_handlers, &std_object_handlers, sizeof(zend_object_handlers));
numeric_castable_no_operation_object_handlers.cast_object = numeric_castable_no_operation_cast_object;
}
22 changes: 22 additions & 0 deletions ext/zend_test/object_handlers.h
@@ -0,0 +1,22 @@
/*
+----------------------------------------------------------------------+
| Copyright (c) The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| https://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Authors: George Peter Banyard <girgias@php.net> |
+----------------------------------------------------------------------+
*/

#ifndef ZEND_TEST_OBJECT_HANDLERS_H
#define ZEND_TEST_OBJECT_HANDLERS_H

void zend_test_object_handlers_init(void);

#endif
24 changes: 24 additions & 0 deletions ext/zend_test/object_handlers.stub.php
@@ -0,0 +1,24 @@
<?php

/**
* @generate-class-entries static
* @undocumentable
*/

final class DoOperationNoCast {
private int $val;
public function __construct(int $val) {}
}

final class LongCastableNoOperations {
private int $val;
public function __construct(int $val) {}
}
final class FloatCastableNoOperations {
private float $val;
public function __construct(float $val) {}
}
final class NumericCastableNoOperations {
private int|float $val;
public function __construct(int|float $val) {}
}

0 comments on commit 1ac82d7

Please sign in to comment.