// // php-armadillo/complex.cc // // @Author CismonX // #include "complex.hh" namespace php_arma { template zend_always_inline void property_declare(zend_class_entry *ce, const char *name) { zval property; zval_set_scalar(&property, static_cast(0)); zend_declare_property(ce, name, strlen(name), &property, ZEND_ACC_PUBLIC); } template PHP_ARMA_METHOD(complex, __construct, T) { zval *real, *imag; ZEND_PARSE_PARAMETERS_START(0, 2) Z_PARAM_OPTIONAL Z_PARAM_ZVAL(real) Z_PARAM_ZVAL(imag) ZEND_PARSE_PARAMETERS_END(); auto num_args = EX_NUM_ARGS(); auto has_imag = num_args == 2; auto has_real = num_args > 0; auto current = Z_OBJ_P(getThis()); if (EXPECTED(has_real)) { if (!zval_check_scalar(real)) { return; } object_set_property(current, 0, real); if (EXPECTED(has_imag)) { if (!zval_check_scalar(imag)) { return; } object_set_property(current, 1, imag); } } current->handlers = &handlers; } template void complex::write_property(zval *obj, zval *member, zval *value, void **unused) { // Theoretically we won't get non-string values here, add type check just in case. if (UNEXPECTED(Z_TYPE_P(member) != IS_STRING)) { zend_throw_exception(zend_ce_error, "Unexpected error. Please contact developer.", -2); return; } if (UNEXPECTED(!zval_check_scalar(value))) { return; } if (strcmp(Z_STRVAL_P(member), "real") == 0) { object_set_property(Z_OBJ_P(obj), 0, value); return; } if (strcmp(Z_STRVAL_P(member), "imag") == 0) { object_set_property(Z_OBJ_P(obj), 1, value); return; } zend_throw_exception_ex(zend_ce_exception, -2, "Bad property name for %s, expected 'real' or 'imag', '%s' given.", Z_OBJNAME_P(obj), Z_STRVAL_P(member)); } template zend_always_inline void complex::ce_init(const char *name, zend_class_entry *parent_ce) { ce = class_register(name, parent_ce, me); property_declare(ce, "real"); property_declare(ce, "imag"); object_handlers_init(&handlers); handlers.write_property = write_property; } void complex_init() { complex_ce = abstract_class_register("Complex"); complex::ce_init("CxDouble", complex_ce); } }