Clean up receiver pre-processor binding

This commit is contained in:
Alex Palaistras 2016-05-05 22:21:57 +01:00
parent deb519497d
commit 3d31c927e3
6 changed files with 240 additions and 166 deletions

View File

@ -191,7 +191,7 @@ func engineSetHeader(ctx *C.struct__engine_context, operation C.uint, buffer uns
//export engineReceiverNew
func engineReceiverNew(rcvr *C.struct__engine_receiver, args unsafe.Pointer) C.int {
n := C.GoString(C.receiver_get_name(rcvr))
n := C.GoString(C._receiver_get_name(rcvr))
if engine == nil || engine.receivers[n] == nil {
return 1
}
@ -215,7 +215,7 @@ func engineReceiverNew(rcvr *C.struct__engine_receiver, args unsafe.Pointer) C.i
//export engineReceiverGet
func engineReceiverGet(rcvr *C.struct__engine_receiver, name *C.char) unsafe.Pointer {
n := C.GoString(C.receiver_get_name(rcvr))
n := C.GoString(C._receiver_get_name(rcvr))
if engine == nil || engine.receivers[n].objects[rcvr] == nil {
return nil
}
@ -230,7 +230,7 @@ func engineReceiverGet(rcvr *C.struct__engine_receiver, name *C.char) unsafe.Poi
//export engineReceiverSet
func engineReceiverSet(rcvr *C.struct__engine_receiver, name *C.char, val unsafe.Pointer) {
n := C.GoString(C.receiver_get_name(rcvr))
n := C.GoString(C._receiver_get_name(rcvr))
if engine == nil || engine.receivers[n].objects[rcvr] == nil {
return
}
@ -245,7 +245,7 @@ func engineReceiverSet(rcvr *C.struct__engine_receiver, name *C.char, val unsafe
//export engineReceiverExists
func engineReceiverExists(rcvr *C.struct__engine_receiver, name *C.char) C.int {
n := C.GoString(C.receiver_get_name(rcvr))
n := C.GoString(C._receiver_get_name(rcvr))
if engine == nil || engine.receivers[n].objects[rcvr] == nil {
return 0
}
@ -259,7 +259,7 @@ func engineReceiverExists(rcvr *C.struct__engine_receiver, name *C.char) C.int {
//export engineReceiverCall
func engineReceiverCall(rcvr *C.struct__engine_receiver, name *C.char, args unsafe.Pointer) unsafe.Pointer {
n := C.GoString(C.receiver_get_name(rcvr))
n := C.GoString(C._receiver_get_name(rcvr))
if engine == nil || engine.receivers[n].objects[rcvr] == nil {
return nil
}

View File

@ -5,63 +5,20 @@
#ifndef ___RECEIVER_H___
#define ___RECEIVER_H___
#define RECEIVER_GET(o, m) receiver_get(o, m, int t, const zend_literal *k)
#define RECEIVER_SET(o, m, v) receiver_set(o, m, v, const zend_literal *k)
#define RECEIVER_EXISTS(o, m, c) receiver_exists(o, m, c, const zend_literal *k)
#define RECEIVER_METHOD_GET(o, n, l) receiver_method_get(zval **o, char *n, int l, const zend_literal *k)
#define RECEIVER_METHOD_CALL(m) receiver_method_call(const char *m, INTERNAL_FUNCTION_PARAMETERS)
#define RECEIVER_CONSTRUCTOR_GET(o) receiver_constructor_get(zval *o)
#define RECEIVER_FREE(o) receiver_free(void *o)
#define RECEIVER_INIT(c) zend_object_value receiver_init(c)
static zval *_receiver_get(zval *object, zval *member, int type, const zend_literal *key);
static void _receiver_set(zval *object, zval *member, zval *value, const zend_literal *key);
static int _receiver_exists(zval *object, zval *member, int check, const zend_literal *key);
#define RECEIVER_DESTROY(n) do { \
zend_class_entry **c; \
if (zend_hash_find(CG(class_table), n, strlen(n), (void **) &c) == SUCCESS) { \
destroy_zend_class(c); \
zend_hash_del_key_or_index(CG(class_table), n, strlen(n), 0, HASH_DEL_KEY); \
} \
} while (0)
static int _receiver_method_call(const char *method, INTERNAL_FUNCTION_PARAMETERS);
static zend_function *_receiver_method_get(zval **object, char *name, int len, const zend_literal *key);
static zend_function *_receiver_constructor_get(zval *object);
static inline zval *RECEIVER_RETVAL() {
zval *val = NULL;
MAKE_STD_ZVAL(val);
return val;
}
static void _receiver_free(void *object);
static zend_object_value _receiver_init(zend_class_entry *class_type);
static void _receiver_destroy(char *name);
#define RECEIVER_THIS(o) ((engine_receiver *) zend_object_store_get_object(o))
#define RECEIVER_STRING_COPY(n) estrndup(n, len)
static engine_receiver *_receiver_this(zval *object);
static void _receiver_handlers_set(zend_object_handlers *handlers);
char *_receiver_get_name(engine_receiver *rcvr);
#define RECEIVER_FUNC() (zend_internal_function *) EG(current_execute_data)->function_state.function
#define RECEIVER_FUNC_NAME(m) (char *) (m)
#define RECEIVER_FUNC_SET_ARGFLAGS(f)
#define RECEIVER_OBJECT(o) ((zend_object *) (&(RECEIVER_THIS(o)->obj)))
#define RECEIVER_OBJECT_CREATE(r, t) do { \
r = emalloc(sizeof(engine_receiver)); \
memset(r, 0, sizeof(engine_receiver)); \
zend_object_std_init(&this->obj, t); \
zend_object_value object; \
object.handle = zend_objects_store_put(r, \
(zend_objects_store_dtor_t) zend_objects_destroy_object, \
(zend_objects_free_object_storage_t) receiver_free, NULL); \
object.handlers = &receiver_handlers; \
return object; \
} while (0)
#define RECEIVER_OBJECT_DESTROY(r) do { \
zend_object_std_dtor(&r->obj); \
efree(r); \
} while (0)
#define RECEIVER_HANDLERS_SET(h) do { \
zend_object_handlers *std = zend_get_std_object_handlers(); \
h.get_class_name = std->get_class_name; \
h.get_class_entry = std->get_class_entry; \
} while (0)
// Return class name for method receiver.
static inline char *receiver_get_name(engine_receiver *rcvr) {
return (char *) rcvr->obj.ce->name;
}
#endif
#endif

View File

@ -5,54 +5,20 @@
#ifndef ___RECEIVER_H___
#define ___RECEIVER_H___
#define RECEIVER_GET(o, m) receiver_get(o, m, int t, void **c, zval *r)
#define RECEIVER_SET(o, m, v) receiver_set(o, m, v, void **c)
#define RECEIVER_EXISTS(o, m, h) receiver_exists(o, m, h, void **c)
#define RECEIVER_METHOD_GET(o, n, l) receiver_method_get(zend_object **o, zend_string *n, const zval *k)
#define RECEIVER_METHOD_CALL(m) receiver_method_call(zend_string *m, zend_object *o, INTERNAL_FUNCTION_PARAMETERS)
#define RECEIVER_CONSTRUCTOR_GET(o) receiver_constructor_get(zend_object *o)
#define RECEIVER_FREE(o) receiver_free(zend_object *o)
#define RECEIVER_INIT(c) zend_object *receiver_init(c)
static zval *_receiver_get(zval *object, zval *member, int type, void **cache_slot, zval *retval);
static void _receiver_set(zval *object, zval *member, zval *value, void **cache_slot);
static int _receiver_exists(zval *object, zval *member, int check, void **cache_slot);
#define RECEIVER_DESTROY(n) do { \
zval *c = zend_hash_str_find(CG(class_table), n, strlen(n)); \
if (c != NULL) { \
destroy_zend_class(c); \
zend_hash_str_del(CG(class_table), n, strlen(n)); \
} \
} while (0)
static int _receiver_method_call(zend_string *method, zend_object *object, INTERNAL_FUNCTION_PARAMETERS);
static zend_function *_receiver_method_get(zend_object **object, zend_string *name, const zval *key);
static zend_function *_receiver_constructor_get(zend_object *object);
#define RECEIVER_RETVAL() (r)
#define RECEIVER_THIS(o) ((engine_receiver *) Z_OBJ_P(o))
#define RECEIVER_STRING_COPY(n) zend_string_copy(name)
static void _receiver_free(zend_object *object);
static zend_object *_receiver_init(zend_class_entry *class_type);
static void _receiver_destroy(char *name);
#define RECEIVER_FUNC() (zend_internal_function *) EX(func)
#define RECEIVER_FUNC_NAME(m) (m)->val
#define RECEIVER_FUNC_SET_ARGFLAGS(f) zend_set_function_arg_flags((zend_function *) f);
static engine_receiver *_receiver_this(zval *object);
static void _receiver_handlers_set(zend_object_handlers *handlers);
char *_receiver_get_name(engine_receiver *rcvr);
#define RECEIVER_OBJECT(o) (o)
#define RECEIVER_OBJECT_CREATE(r, t) do { \
r = emalloc(sizeof(engine_receiver)); \
memset(r, 0, sizeof(engine_receiver)); \
zend_object_std_init(&r->obj, t); \
object_properties_init(&r->obj, t); \
r->obj.handlers = &receiver_handlers; \
return &r->obj; \
} while (0)
#define RECEIVER_OBJECT_DESTROY(r) do { \
zend_object_std_dtor(&r->obj); \
} while (0)
#define RECEIVER_HANDLERS_SET(h) do { \
zend_object_handlers *std = zend_get_std_object_handlers(); \
h.get_class_name = std->get_class_name; \
h.free_obj = receiver_free; \
} while (0)
// Return class name for method receiver.
static inline char *receiver_get_name(engine_receiver *rcvr) {
return rcvr->obj.ce->name->val;
}
#endif
#endif

View File

@ -14,31 +14,20 @@
#include "_cgo_export.h"
// Fetch and return field for method receiver.
static zval *RECEIVER_GET(zval *object, zval *member) {
engine_receiver *this = RECEIVER_THIS(object);
zval *val = RECEIVER_RETVAL();
engine_value *result = engineReceiverGet(this, Z_STRVAL_P(member));
if (result == NULL) {
ZVAL_NULL(val);
return val;
}
value_copy(val, result->internal);
value_destroy(result);
return val;
static engine_value *receiver_get(zval *object, zval *member) {
engine_receiver *this = _receiver_this(object);
return engineReceiverGet(this, Z_STRVAL_P(member));
}
// Set field for method receiver.
static void RECEIVER_SET(zval *object, zval *member, zval *value) {
engine_receiver *this = RECEIVER_THIS(object);
static void receiver_set(zval *object, zval *member, zval *value) {
engine_receiver *this = _receiver_this(object);
engineReceiverSet(this, Z_STRVAL_P(member), (void *) value);
}
// Check if field exists for method receiver.
static int RECEIVER_EXISTS(zval *object, zval *member, int check) {
engine_receiver *this = RECEIVER_THIS(object);
static int receiver_exists(zval *object, zval *member, int check) {
engine_receiver *this = _receiver_this(object);
if (!engineReceiverExists(this, Z_STRVAL_P(member))) {
// Value does not exist.
@ -68,10 +57,9 @@ static int RECEIVER_EXISTS(zval *object, zval *member, int check) {
}
// Call function with arguments passed and return value (if any).
static int RECEIVER_METHOD_CALL(method) {
engine_receiver *this = RECEIVER_THIS(getThis());
char *name = RECEIVER_FUNC_NAME(method);
static int receiver_method_call(char *name, INTERNAL_FUNCTION_PARAMETERS) {
zval args;
engine_receiver *this = _receiver_this(getThis());
array_init_size(&args, ZEND_NUM_ARGS());
@ -93,8 +81,8 @@ static int RECEIVER_METHOD_CALL(method) {
// Create new method receiver instance and attach to instantiated PHP object.
// Returns an exception if method receiver failed to initialize for any reason.
static void receiver_new(INTERNAL_FUNCTION_PARAMETERS) {
engine_receiver *this = RECEIVER_THIS(getThis());
zval args;
engine_receiver *this = _receiver_this(getThis());
array_init_size(&args, ZEND_NUM_ARGS());
@ -113,49 +101,42 @@ static void receiver_new(INTERNAL_FUNCTION_PARAMETERS) {
// Fetch and return function definition for method receiver. The method call
// happens in the method handler, as returned by this function.
static zend_function *RECEIVER_METHOD_GET(object_ptr, name, len) {
zend_object *obj = RECEIVER_OBJECT(*object_ptr);
static zend_internal_function *receiver_method_get(zend_object *object) {
zend_internal_function *func = emalloc(sizeof(zend_internal_function));
func->type = ZEND_OVERLOADED_FUNCTION;
func->handler = NULL;
func->arg_info = NULL;
func->num_args = 0;
func->scope = obj->ce;
func->scope = object->ce;
func->fn_flags = ZEND_ACC_CALL_VIA_HANDLER;
func->function_name = RECEIVER_STRING_COPY(name);
RECEIVER_FUNC_SET_ARGFLAGS(func);
return (zend_function *) func;
return func;
}
// Fetch and return constructor function definition for method receiver. The
// construct call happens in the constructor handler, as returned by this
// function.
static zend_function *RECEIVER_CONSTRUCTOR_GET(object) {
zend_object *obj = RECEIVER_OBJECT(object);
static zend_internal_function *receiver_constructor_get(zend_object *object) {
static zend_internal_function func;
func.type = ZEND_INTERNAL_FUNCTION;
func.handler = receiver_new;
func.arg_info = NULL;
func.num_args = 0;
func.scope = obj->ce;
func.scope = object->ce;
func.fn_flags = 0;
func.function_name = obj->ce->name;
func.function_name = object->ce->name;
RECEIVER_FUNC_SET_ARGFLAGS(&func);
return (zend_function *) &func;
return &func;
}
// Table of handler functions for method receivers.
static zend_object_handlers receiver_handlers = {
ZEND_OBJECTS_STORE_HANDLERS,
receiver_get, // read_property
receiver_set, // write_property
_receiver_get, // read_property
_receiver_set, // write_property
NULL, // read_dimension
NULL, // write_dimension
@ -163,32 +144,19 @@ static zend_object_handlers receiver_handlers = {
NULL, // get
NULL, // set
receiver_exists, // has_property
_receiver_exists, // has_property
NULL, // unset_property
NULL, // has_dimension
NULL, // unset_dimension
NULL, // get_properties
receiver_method_get, // get_method
receiver_method_call, // call_method
_receiver_method_get, // get_method
_receiver_method_call, // call_method
receiver_constructor_get // get_constructor
_receiver_constructor_get // get_constructor
};
// Free storage for allocated method receiver instance.
static void RECEIVER_FREE(object) {
engine_receiver *this = (engine_receiver *) object;
RECEIVER_OBJECT_DESTROY(this);
}
// Initialize instance of method receiver object. The method receiver itself is
// attached in the constructor function call.
static RECEIVER_INIT(zend_class_entry *class_type) {
engine_receiver *this;
RECEIVER_OBJECT_CREATE(this, class_type);
}
// Define class with unique name.
void receiver_define(char *name) {
zend_class_entry tmp;
@ -196,14 +164,16 @@ void receiver_define(char *name) {
zend_class_entry *this = zend_register_internal_class(&tmp);
this->create_object = receiver_init;
this->create_object = _receiver_init;
this->ce_flags |= ZEND_ACC_FINAL;
// Set standard handlers for receiver.
RECEIVER_HANDLERS_SET(receiver_handlers);
_receiver_handlers_set(&receiver_handlers);
}
void receiver_destroy(char *name) {
name = php_strtolower(name, strlen(name));
RECEIVER_DESTROY(name);
_receiver_destroy(name);
}
#include "_receiver.c"

View File

@ -0,0 +1,93 @@
// Copyright 2016 Alexander Palaistras. All rights reserved.
// Use of this source code is governed by the MIT license that can be found in
// the LICENSE file.
static zval *_receiver_get(zval *object, zval *member, int type, const zend_literal *key) {
zval *retval = NULL;
MAKE_STD_ZVAL(retval);
engine_value *result = receiver_get(object, member);
if (result == NULL) {
ZVAL_NULL(retval);
return retval;
}
value_copy(retval, result->internal);
value_destroy(result);
return retval;
}
static void _receiver_set(zval *object, zval *member, zval *value, const zend_literal *key) {
receiver_set(object, member, value);
}
static int _receiver_exists(zval *object, zval *member, int check, const zend_literal *key) {
return receiver_exists(object, member, check);
}
static int _receiver_method_call(const char *method, INTERNAL_FUNCTION_PARAMETERS) {
return receiver_method_call((char *) method, INTERNAL_FUNCTION_PARAM_PASSTHRU);
}
static zend_function *_receiver_method_get(zval **object, char *name, int len, const zend_literal *key) {
zend_object *obj = &(_receiver_this(*object)->obj);
zend_internal_function *func = receiver_method_get(obj);
func->function_name = estrndup(name, len);
return (zend_function *) func;
}
static zend_function *_receiver_constructor_get(zval *object) {
zend_object *obj = &(_receiver_this(object)->obj);
zend_internal_function *func = receiver_constructor_get(obj);
return (zend_function *) func;
}
// Free storage for allocated method receiver instance.
static void _receiver_free(void *object) {
engine_receiver *this = (engine_receiver *) object;
zend_object_std_dtor(&(this->obj));
}
// Initialize instance of method receiver object. The method receiver itself is
// attached in the constructor function call.
static zend_object_value *_receiver_init(zend_class_entry *class_type) {
engine_receiver *this = emalloc(sizeof(engine_receiver));
memset(this, 0, sizeof(engine_receiver));
zend_object_std_init(&this->obj, class_type);
zend_object_value object;
object.handle = zend_objects_store_put(this, (zend_objects_store_dtor_t) zend_objects_destroy_object, (zend_objects_free_object_storage_t) receiver_free, NULL);
object.handlers = &receiver_handlers;
return object;
}
static void _receiver_destroy(char *name) {
zend_class_entry **class;
if (zend_hash_find(CG(class_table), name, strlen(name), (void **) &class) == SUCCESS) {
destroy_zend_class(class);
zend_hash_del_key_or_index(CG(class_table), name, strlen(name), 0, HASH_DEL_KEY);
}
}
static engine_receiver *_receiver_this(zval *object) {
return (engine_receiver *) zend_object_store_get_object(object);
}
static void _receiver_handlers_set(zend_object_handlers *handlers) {
zend_object_handlers *std = zend_get_std_object_handlers();
handlers.get_class_name = std->get_class_name;
handlers.get_class_entry = std->get_class_entry;
}
// Return class name for method receiver.
char *_receiver_get_name(engine_receiver *rcvr) {
return (char *) rcvr->obj.ce->name;
}

View File

@ -0,0 +1,88 @@
// Copyright 2016 Alexander Palaistras. All rights reserved.
// Use of this source code is governed by the MIT license that can be found in
// the LICENSE file.
static zval *_receiver_get(zval *object, zval *member, int type, void **cache_slot, zval *retval) {
engine_value *result = receiver_get(object, member);
if (result == NULL) {
ZVAL_NULL(retval);
return retval;
}
value_copy(retval, result->internal);
value_destroy(result);
return retval;
}
static void _receiver_set(zval *object, zval *member, zval *value, void **cache_slot) {
receiver_set(object, member, value);
}
static int _receiver_exists(zval *object, zval *member, int check, void **cache_slot) {
return receiver_exists(object, member, check);
}
static int _receiver_method_call(zend_string *method, zend_object *object, INTERNAL_FUNCTION_PARAMETERS) {
return receiver_method_call(method->val, INTERNAL_FUNCTION_PARAM_PASSTHRU);
}
static zend_function *_receiver_method_get(zend_object **object, zend_string *name, const zval *key) {
zend_internal_function *func = receiver_method_get(*object);
func->function_name = zend_string_copy(name);
zend_set_function_arg_flags((zend_function *) func);
return (zend_function *) func;
}
static zend_function *_receiver_constructor_get(zend_object *object) {
zend_internal_function *func = receiver_constructor_get(object);
zend_set_function_arg_flags((zend_function *) func);
return (zend_function *) func;
}
// Free storage for allocated method receiver instance.
static void _receiver_free(zend_object *object) {
engine_receiver *this = (engine_receiver *) object;
zend_object_std_dtor(&(this->obj));
}
// Initialize instance of method receiver object. The method receiver itself is
// attached in the constructor function call.
static zend_object *_receiver_init(zend_class_entry *class_type) {
engine_receiver *this = emalloc(sizeof(engine_receiver));
memset(this, 0, sizeof(engine_receiver));
zend_object_std_init(&(this->obj), class_type);
object_properties_init(&(this->obj), class_type);
this->obj.handlers = &receiver_handlers;
return &(this->obj);
}
static void _receiver_destroy(char *name) {
zval *class = zend_hash_str_find(CG(class_table), name, strlen(name));
if (class != NULL) {
destroy_zend_class(class);
zend_hash_str_del(CG(class_table), name, strlen(name));
}
}
static engine_receiver *_receiver_this(zval *object) {
return (engine_receiver *) Z_OBJ_P(object);
}
static void _receiver_handlers_set(zend_object_handlers *handlers) {
zend_object_handlers *std = zend_get_std_object_handlers();
handlers->get_class_name = std->get_class_name;
handlers->free_obj = _receiver_free;
}
// Return class name for method receiver.
char *_receiver_get_name(engine_receiver *rcvr) {
return rcvr->obj.ce->name->val;
}