From 92f58c43bde97ec55ab2877f0bd57427aedf39b3 Mon Sep 17 00:00:00 2001 From: John Boehr Date: Wed, 22 Jul 2015 23:27:27 -0700 Subject: [PATCH 1/7] PHP 7 support --- .travis.yml | 17 +- mustache_ast.cpp | 291 ++++++++++++-------- mustache_ast.hpp | 42 +++ mustache_code.cpp | 312 ++++------------------ mustache_code.hpp | 22 ++ mustache_data.cpp | 563 ++++++++++++++++++++++++-------------- mustache_data.hpp | 38 +++ mustache_exceptions.cpp | 78 ++++-- mustache_exceptions.hpp | 30 +++ mustache_mustache.cpp | 578 +++++++++++++++++++++------------------- mustache_mustache.hpp | 52 ++++ mustache_private.hpp | 69 +++++ mustache_template.cpp | 240 ++--------------- mustache_template.hpp | 21 ++ php_mustache.cpp | 135 +++------- php_mustache.h | 2 + php_mustache.hpp | 61 ----- test_mem.sh | 5 + 18 files changed, 1330 insertions(+), 1226 deletions(-) create mode 100644 mustache_ast.hpp create mode 100644 mustache_code.hpp create mode 100644 mustache_data.hpp create mode 100644 mustache_exceptions.hpp create mode 100644 mustache_mustache.hpp create mode 100644 mustache_private.hpp create mode 100644 mustache_template.hpp create mode 100755 test_mem.sh diff --git a/.travis.yml b/.travis.yml index cd50fd6..c8c6663 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,15 @@ language: php +php: + - 5.3 + - 5.4 + - 5.5 + - 5.6 + +branches: + only: + - master + before_install: - git submodule update --init --recursive - git clone git://github.com/jbboehr/libmustache.git libmustache @@ -7,14 +17,9 @@ before_install: - autoreconf -i && ./configure && make && sudo make install - cd .. -php: - - 5.3 - - 5.4 - - 5.5 - - 5.6 - script: - phpize - ./configure --enable-mustache - make - echo n | make test + diff --git a/mustache_ast.cpp b/mustache_ast.cpp index bffd1c6..c9805ce 100644 --- a/mustache_ast.cpp +++ b/mustache_ast.cpp @@ -1,20 +1,12 @@ -#include "php_mustache.hpp" +#include "mustache_private.hpp" +/* {{{ ZE2 OO definitions */ +zend_class_entry * MustacheAST_ce_ptr; +static zend_object_handlers MustacheAST_obj_handlers; +/* }}} */ - -// Declarations ---------------------------------------------------------------- - -PHP_METHOD(MustacheAST, __construct); -PHP_METHOD(MustacheAST, __sleep); -PHP_METHOD(MustacheAST, toArray); -PHP_METHOD(MustacheAST, __toString); -PHP_METHOD(MustacheAST, __wakeup); - - - -// Argument Info --------------------------------------------------------------- - +/* {{{ arginfo */ ZEND_BEGIN_ARG_INFO_EX(MustacheAST____construct_args, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 0) ZEND_ARG_INFO(0, vars) ZEND_END_ARG_INFO() @@ -30,17 +22,9 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(MustacheAST____wakeup_args, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 0) ZEND_END_ARG_INFO() +/* }}} */ - - -// Class Entries --------------------------------------------------------------- - -zend_class_entry * MustacheAST_ce_ptr; - - - -// Method Entries -------------------------------------------------------------- - +/* {{{ MustacheAST_methods */ static zend_function_entry MustacheAST_methods[] = { PHP_ME(MustacheAST, __construct, MustacheAST____construct_args, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR) PHP_ME(MustacheAST, __sleep, MustacheAST____sleep_args, ZEND_ACC_PUBLIC) @@ -49,11 +33,9 @@ static zend_function_entry MustacheAST_methods[] = { PHP_ME(MustacheAST, __wakeup, MustacheAST____wakeup_args, ZEND_ACC_PUBLIC) { NULL, NULL, NULL } }; +/* }}} */ - - -// Helpers --------------------------------------------------------------------- - +/* {{{ mustache_node_from_binary_string */ void mustache_node_from_binary_string(mustache::Node ** node, char * str, int len) { std::vector uint_str; @@ -66,7 +48,9 @@ void mustache_node_from_binary_string(mustache::Node ** node, char * str, int le size_t vpos = 0; *node = mustache::Node::unserialize(uint_str, 0, &vpos); } +/* }}} */ +/* {{{ mustache_node_to_binary_string */ void mustache_node_to_binary_string(mustache::Node * node, char ** estr, int * elen) { std::vector * serialPtr = node->serialize(); @@ -83,10 +67,13 @@ void mustache_node_to_binary_string(mustache::Node * node, char ** estr, int * e *elen = serialLen; *estr = str; } +/* }}} */ +/* {{{ mustache_node_to_zval */ void mustache_node_to_zval(mustache::Node * node, zval * current TSRMLS_DC) { - zval * children = NULL; + _DECLARE_ZVAL(children); + _DECLARE_ZVAL(child); array_init(current); @@ -94,18 +81,17 @@ void mustache_node_to_zval(mustache::Node * node, zval * current TSRMLS_DC) add_assoc_long(current, "type", node->type); add_assoc_long(current, "flags", node->flags); if( NULL != node->data && node->data->length() > 0 ) { - add_assoc_stringl(current, "data", (char *) node->data->c_str(), node->data->length(), 1); + _add_assoc_stringl_ex(current, _STRS("data"), (char *) node->data->c_str(), node->data->length()); } // Children if( node->children.size() > 0 ) { - ALLOC_INIT_ZVAL(children); + _ALLOC_INIT_ZVAL(children); array_init(children); mustache::Node::Children::iterator it; for ( it = node->children.begin() ; it != node->children.end(); it++ ) { - zval * child; - ALLOC_INIT_ZVAL(child); + _ALLOC_INIT_ZVAL(child); mustache_node_to_zval(*it, child TSRMLS_CC); add_next_index_zval(children, child); } @@ -116,13 +102,12 @@ void mustache_node_to_zval(mustache::Node * node, zval * current TSRMLS_DC) // Partials if( node->partials.size() > 0 ) { - ALLOC_INIT_ZVAL(children); + _ALLOC_INIT_ZVAL(children); array_init(children); mustache::Node::Partials::iterator it; for ( it = node->partials.begin() ; it != node->partials.end(); it++ ) { - zval * child; - ALLOC_INIT_ZVAL(child); + _ALLOC_INIT_ZVAL(child); mustache_node_to_zval(&(it->second), child TSRMLS_CC); add_assoc_zval(children, it->first.c_str(), child); } @@ -131,17 +116,32 @@ void mustache_node_to_zval(mustache::Node * node, zval * current TSRMLS_DC) children = NULL; } } +/* }}} */ +/* {{{ php_mustache_ast_object_fetch_object */ +#if PHP_MAJOR_VERSION < 7 +struct php_obj_MustacheAST * php_mustache_ast_object_fetch_object(zval * zv TSRMLS_DC) { + return (struct php_obj_MustacheAST *) zend_object_store_get_object(zv TSRMLS_CC); +} +#else +static inline struct php_obj_MustacheAST * php_mustache_ast_fetch_object(zend_object * obj TSRMLS_DC) +{ + return (struct php_obj_MustacheAST *)((char*)(obj) - XtOffsetOf(struct php_obj_MustacheAST, std)); +} +struct php_obj_MustacheAST * php_mustache_ast_object_fetch_object(zval * zv TSRMLS_DC) +{ + return php_mustache_ast_fetch_object(Z_OBJ_P(zv) TSRMLS_CC); +} +#endif +/* }}} */ -// Object Handlers ------------------------------------------------------------- - -static zend_object_handlers MustacheAST_obj_handlers; - +/* {{{ MustacheAST_obj_free */ +#if PHP_MAJOR_VERSION < 7 static void MustacheAST_obj_free(void *object TSRMLS_DC) { try { - php_obj_MustacheAST * payload = (php_obj_MustacheAST *) object; + struct php_obj_MustacheAST * payload = (struct php_obj_MustacheAST *) object; if( payload->node != NULL ) { delete payload->node; @@ -155,31 +155,50 @@ static void MustacheAST_obj_free(void *object TSRMLS_DC) mustache_exception_handler(TSRMLS_C); } } +#else +static void MustacheAST_obj_free(zend_object * object TSRMLS_DC) +{ + try { + struct php_obj_MustacheAST * payload = php_mustache_ast_fetch_object(object TSRMLS_CC); + + if( payload->node != NULL ) { + delete payload->node; + } + + zend_object_std_dtor((zend_object *)object TSRMLS_CC); + } catch(...) { + mustache_exception_handler(TSRMLS_C); + } +} +#endif +/* }}} */ -static zend_object_value MustacheAST_obj_create(zend_class_entry *class_type TSRMLS_DC) +/* {{{ MustacheAST_obj_create */ +#if PHP_MAJOR_VERSION < 7 +static zend_object_value MustacheAST_obj_create(zend_class_entry * class_type TSRMLS_DC) { zend_object_value retval; try { - php_obj_MustacheAST * payload; + struct php_obj_MustacheAST * payload; zval * tmp; - payload = (php_obj_MustacheAST *) emalloc(sizeof(php_obj_MustacheAST)); - memset(payload, 0, sizeof(php_obj_MustacheAST)); + payload = (struct php_obj_MustacheAST *) emalloc(sizeof(struct php_obj_MustacheAST)); + memset(payload, 0, sizeof(struct php_obj_MustacheAST)); zend_object_std_init((zend_object *) payload, class_type TSRMLS_CC); #if PHP_VERSION_ID < 50399 - zend_hash_copy(payload->obj.properties, &(class_type->default_properties), + zend_hash_copy(payload->std.properties, &(class_type->default_properties), (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval*)); #else - object_properties_init(&payload->obj, class_type); + object_properties_init(&payload->std, class_type); #endif payload->node = NULL; //new mustache::Node(); retval.handle = zend_objects_store_put(payload, NULL, (zend_objects_free_object_storage_t) MustacheAST_obj_free, NULL TSRMLS_CC); - retval.handlers = &MustacheAST_obj_handlers; + retval.handlers = (zend_object_handlers *) &MustacheAST_obj_handlers; } catch(...) { mustache_exception_handler(TSRMLS_C); @@ -187,17 +206,36 @@ static zend_object_value MustacheAST_obj_create(zend_class_entry *class_type TSR return retval; } +#else +static zend_object * MustacheAST_obj_create(zend_class_entry * ce TSRMLS_DC) +{ + struct php_obj_MustacheAST * intern; + + try { + intern = (struct php_obj_MustacheAST *) ecalloc(1, sizeof(struct php_obj_MustacheAST) + zend_object_properties_size(ce)); + zend_object_std_init(&intern->std, ce TSRMLS_CC); + intern->std.handlers = &MustacheAST_obj_handlers; + intern->node = NULL; + } catch(...) { + mustache_exception_handler(TSRMLS_C); + } + + return &intern->std; +} +#endif +/* }}} */ - - -// MINIT ----------------------------------------------------------------------- - +/* {{{ PHP_MINIT_FUNCTION */ PHP_MINIT_FUNCTION(mustache_ast) { try { zend_class_entry ce; memcpy(&MustacheAST_obj_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); +#if PHP_MAJOR_VERSION >= 7 + MustacheAST_obj_handlers.offset = XtOffsetOf(struct php_obj_MustacheAST, std); + MustacheAST_obj_handlers.free_obj = MustacheAST_obj_free; +#endif MustacheAST_obj_handlers.clone_obj = NULL; INIT_CLASS_ENTRY(ce, "MustacheAST", MustacheAST_methods); @@ -214,13 +252,9 @@ PHP_MINIT_FUNCTION(mustache_ast) return FAILURE; } } +/* }}} */ - - -// Methods --------------------------------------------------------------------- - -/* {{{ proto void __construct(string binaryString) - */ +/* {{{ proto void MustacheAST::__construct(string binaryString) */ PHP_METHOD(MustacheAST, __construct) { try { @@ -238,8 +272,7 @@ PHP_METHOD(MustacheAST, __construct) // Class parameters _this_zval = getThis(); zend_class_entry * _this_ce = Z_OBJCE_P(_this_zval); - php_obj_MustacheAST * payload = - (php_obj_MustacheAST *) zend_object_store_get_object(_this_zval TSRMLS_CC); + struct php_obj_MustacheAST * payload = php_mustache_ast_object_fetch_object(_this_zval TSRMLS_CC); // Check payload if( payload->node != NULL ) { @@ -253,10 +286,9 @@ PHP_METHOD(MustacheAST, __construct) mustache_exception_handler(TSRMLS_C); } } -/* }}} __construct */ +/* }}} MustacheAST::__construct */ -/* {{{ proto void __sleep() - */ +/* {{{ proto void MustacheAST::__sleep() */ PHP_METHOD(MustacheAST, __sleep) { try { @@ -270,8 +302,7 @@ PHP_METHOD(MustacheAST, __sleep) // Class parameters _this_zval = getThis(); zend_class_entry * _this_ce = Z_OBJCE_P(_this_zval); - php_obj_MustacheAST * payload = - (php_obj_MustacheAST *) zend_object_store_get_object(_this_zval TSRMLS_CC); + struct php_obj_MustacheAST * payload = php_mustache_ast_object_fetch_object(_this_zval TSRMLS_CC); array_init(return_value); @@ -284,7 +315,7 @@ PHP_METHOD(MustacheAST, __sleep) if( str != NULL ) { zend_update_property_stringl(MustacheAST_ce_ptr, _this_zval, ZEND_STRL("binaryString"), str, len TSRMLS_CC); - add_next_index_string(return_value, "binaryString", 1); + _add_next_index_string(return_value, "binaryString"); efree(str); } } @@ -293,10 +324,9 @@ PHP_METHOD(MustacheAST, __sleep) mustache_exception_handler(TSRMLS_C); } } -/* }}} __sleep */ +/* }}} MustacheAST::__sleep */ -/* {{{ proto array toArray() - */ +/* {{{ proto array MustacheAST::toArray() */ PHP_METHOD(MustacheAST, toArray) { try { @@ -310,8 +340,7 @@ PHP_METHOD(MustacheAST, toArray) // Class parameters _this_zval = getThis(); zend_class_entry * _this_ce = Z_OBJCE_P(_this_zval); - php_obj_MustacheAST * payload = - (php_obj_MustacheAST *) zend_object_store_get_object(_this_zval TSRMLS_CC); + struct php_obj_MustacheAST * payload = php_mustache_ast_object_fetch_object(_this_zval TSRMLS_CC); // Check payload if( payload->node == NULL ) { @@ -325,10 +354,9 @@ PHP_METHOD(MustacheAST, toArray) mustache_exception_handler(TSRMLS_C); } } -/* }}} toArray */ +/* }}} MustacheAST::toArray */ -/* {{{ proto string __toString() - */ +/* {{{ proto string MustacheAST::__toString() */ PHP_METHOD(MustacheAST, __toString) { try { @@ -342,8 +370,7 @@ PHP_METHOD(MustacheAST, __toString) // Class parameters _this_zval = getThis(); zend_class_entry * _this_ce = Z_OBJCE_P(_this_zval); - php_obj_MustacheAST * payload = - (php_obj_MustacheAST *) zend_object_store_get_object(_this_zval TSRMLS_CC); + struct php_obj_MustacheAST * payload = php_mustache_ast_object_fetch_object(_this_zval TSRMLS_CC); // Check payload if( payload->node == NULL ) { @@ -355,34 +382,23 @@ PHP_METHOD(MustacheAST, __toString) int len = 0; mustache_node_to_binary_string(payload->node, &str, &len); - if( str != NULL && len > 0 ) { - RETURN_STRINGL(str, len, 0); + if( str != NULL ) { + _RETVAL_STRINGL(str, len); + efree(str); } } catch(...) { mustache_exception_handler(TSRMLS_C); } } -/* }}} __toString */ +/* }}} MustacheAST::__toString */ - -/* {{{ proto void __wakeup() - */ -PHP_METHOD(MustacheAST, __wakeup) +/* {{{ proto void MustacheAST::__wakeup() */ +#if PHP_MAJOR_VERSION < 7 +static inline void php_mustache_ast_wakeup(zval * _this_zval, zval * return_value TSRMLS_DC) { - try { - // Check parameters - zval * _this_zval = NULL; - if( zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), (char *) "O", - &_this_zval, MustacheAST_ce_ptr) == FAILURE) { - throw PhpInvalidParameterException(); - } - - // Class parameters - _this_zval = getThis(); zend_class_entry * _this_ce = Z_OBJCE_P(_this_zval); - php_obj_MustacheAST * payload = - (php_obj_MustacheAST *) zend_object_store_get_object(_this_zval TSRMLS_CC); + struct php_obj_MustacheAST * payload = php_mustache_ast_object_fetch_object(_this_zval TSRMLS_CC); // Get object properties // @todo should be able to convert this to use zend_hash_find @@ -394,35 +410,86 @@ PHP_METHOD(MustacheAST, __wakeup) HashPosition data_pointer = NULL; zval **data_entry = NULL; long data_count = 0; - if( Z_OBJ_HT_P(_this_zval)->get_properties != NULL ) { - data_hash = Z_OBJ_HT_P(_this_zval)->get_properties(_this_zval TSRMLS_CC); - data_count = zend_hash_num_elements(data_hash); + char * prop_name; + char * class_name; + + if( Z_OBJ_HT_P(_this_zval)->get_properties == NULL ) { + return; } - if( data_hash != NULL ) { - char *prop_name, *class_name; - zend_hash_internal_pointer_reset_ex(data_hash, &data_pointer); - while( zend_hash_get_current_data_ex(data_hash, (void**) &data_entry, &data_pointer) == SUCCESS ) { + + data_hash = Z_OBJ_HT_P(_this_zval)->get_properties(_this_zval TSRMLS_CC); + data_count = zend_hash_num_elements(data_hash); + + if( data_hash == NULL ) { + return; + } + + zend_hash_internal_pointer_reset_ex(data_hash, &data_pointer); + while( zend_hash_get_current_data_ex(data_hash, (void**) &data_entry, &data_pointer) == SUCCESS ) { if( zend_hash_get_current_key_ex(data_hash, &key_str, &key_len, &key_nindex, false, &data_pointer) == HASH_KEY_IS_STRING ) { #if PHP_API_VERSION >= 20100412 - zend_unmangle_property_name(key_str, key_len-1, (const char **) &class_name, (const char **) &prop_name); + zend_unmangle_property_name(key_str, key_len-1, (const char **) &class_name, (const char **) &prop_name); #else - zend_unmangle_property_name(key_str, key_len-1, &class_name, &prop_name); + zend_unmangle_property_name(key_str, key_len-1, &class_name, &prop_name); #endif - if( strcmp(prop_name, "binaryString") == 0 && Z_TYPE_PP(data_entry) == IS_STRING ) { - if( payload->node != NULL ) { - delete payload->node; - payload->node = NULL; + if( strcmp(prop_name, "binaryString") == 0 && Z_TYPE_PP(data_entry) == IS_STRING ) { + mustache_node_from_binary_string(&payload->node, Z_STRVAL_PP(data_entry), Z_STRLEN_PP(data_entry)); } - mustache_node_from_binary_string(&payload->node, Z_STRVAL_PP(data_entry), Z_STRLEN_PP(data_entry)); - } } zend_hash_move_forward_ex(data_hash, &data_pointer); - } + } +} +#else +static inline void php_mustache_ast_wakeup(zval * _this_zval, zval * return_value TSRMLS_DC) +{ + zend_class_entry * _this_ce = Z_OBJCE_P(_this_zval); + struct php_obj_MustacheAST * payload = php_mustache_ast_object_fetch_object(_this_zval TSRMLS_CC); + + HashTable * data_hash = NULL; + long data_count = 0; + ulong key_nindex = 0; + zend_string * key; + zval * data_entry = NULL; + const char * prop_name; + const char * class_name; + + if( Z_OBJ_HT_P(_this_zval)->get_properties == NULL ) { + return; + } + + data_hash = Z_OBJ_HT_P(_this_zval)->get_properties(_this_zval TSRMLS_CC); + data_count = zend_hash_num_elements(data_hash); + + if( data_hash == NULL ) { + return; + } + + ZEND_HASH_FOREACH_KEY_VAL(data_hash, key_nindex, key, data_entry) { + if( key ) { + zend_unmangle_property_name(key, &class_name, &prop_name); + if( strcmp(prop_name, "binaryString") == 0 && Z_TYPE_P(data_entry) == IS_STRING ) { + mustache_node_from_binary_string(&payload->node, Z_STRVAL_P(data_entry), Z_STRLEN_P(data_entry)); + } + } + } ZEND_HASH_FOREACH_END(); +} +#endif + +PHP_METHOD(MustacheAST, __wakeup) +{ + try { + // Check parameters + zval * _this_zval = NULL; + if( zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), (char *) "O", + &_this_zval, MustacheAST_ce_ptr) == FAILURE) { + throw PhpInvalidParameterException(); } + php_mustache_ast_wakeup(getThis(), return_value TSRMLS_CC); } catch(...) { mustache_exception_handler(TSRMLS_C); } } -/* }}} __wakeup */ +/* }}} MustacheAST::__wakeup */ + diff --git a/mustache_ast.hpp b/mustache_ast.hpp new file mode 100644 index 0000000..31a770a --- /dev/null +++ b/mustache_ast.hpp @@ -0,0 +1,42 @@ + +#ifndef PHP_MUSTACHE_AST_HPP +#define PHP_MUSTACHE_AST_HPP + +#ifdef __cplusplus +extern "C" { +#endif + +#if PHP_MAJOR_VERSION < 7 +struct php_obj_MustacheAST { + zend_object std; + mustache::Node * node; +}; +#else +struct php_obj_MustacheAST { + mustache::Node * node; + zend_object std; +}; +#endif + +extern zend_class_entry * MustacheAST_ce_ptr; + +void mustache_node_from_binary_string(mustache::Node ** node, char * str, int len); +void mustache_node_to_binary_string(mustache::Node * node, char ** estr, int * elen); +void mustache_node_to_zval(mustache::Node * node, zval * current TSRMLS_DC); + +struct php_obj_MustacheAST * php_mustache_ast_object_fetch_object(zval * zv TSRMLS_DC); + +PHP_MINIT_FUNCTION(mustache_ast); + +PHP_METHOD(MustacheAST, __construct); +PHP_METHOD(MustacheAST, __sleep); +PHP_METHOD(MustacheAST, toArray); +PHP_METHOD(MustacheAST, __toString); +PHP_METHOD(MustacheAST, __wakeup); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* PHP_MUSTACHE_AST_HPP */ + diff --git a/mustache_code.cpp b/mustache_code.cpp index 45bcaa5..b246f65 100644 --- a/mustache_code.cpp +++ b/mustache_code.cpp @@ -1,72 +1,51 @@ -#include "php_mustache.hpp" - - - -// Class Entries --------------------------------------------------------------- +#include "mustache_private.hpp" +/* {{{ ZE2 OO definitions */ zend_class_entry * MustacheCode_ce_ptr; +/* }}} */ +/* {{{ arginfo */ +ZEND_BEGIN_ARG_INFO_EX(MustacheCode____construct_args, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 0) + ZEND_ARG_INFO(0, codeString) +ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_INFO_EX(MustacheCode__toReadableString_args, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 0) +ZEND_END_ARG_INFO() -// Object Handlers ------------------------------------------------------------- - -static zend_object_handlers MustacheCode_obj_handlers; - -static void MustacheCode_obj_free(void *object TSRMLS_DC) -{ - try { - php_obj_MustacheCode * payload = (php_obj_MustacheCode *) object; - - if( payload->codes != NULL ) { - free(payload->codes); - } - - zend_object_std_dtor((zend_object *)object TSRMLS_CC); +ZEND_BEGIN_ARG_INFO_EX(MustacheCode____toString_args, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 0) +ZEND_END_ARG_INFO() +/* }}} */ - efree(object); - - } catch(...) { - mustache_exception_handler(TSRMLS_C); - } -} +/* {{{ MustacheCode_methods */ +static zend_function_entry MustacheCode_methods[] = { + PHP_ME(MustacheCode, __construct, MustacheCode____construct_args, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR) + PHP_ME(MustacheCode, toReadableString, MustacheCode__toReadableString_args, ZEND_ACC_PUBLIC) + PHP_ME(MustacheCode, __toString, MustacheCode____toString_args, ZEND_ACC_PUBLIC) + { NULL, NULL, NULL } +}; +/* }}} */ -static zend_object_value MustacheCode_obj_create(zend_class_entry *class_type TSRMLS_DC) +/* {{{ PHP_MINIT_FUNCTION */ +PHP_MINIT_FUNCTION(mustache_code) { - zend_object_value retval; - try { - php_obj_MustacheCode * payload; - zval * tmp; + zend_class_entry ce; - payload = (php_obj_MustacheCode *) emalloc(sizeof(php_obj_MustacheCode)); - memset(payload, 0, sizeof(php_obj_MustacheCode)); - - zend_object_std_init((zend_object *) payload, class_type TSRMLS_CC); - -#if PHP_VERSION_ID < 50399 - zend_hash_copy(payload->obj.properties, &(class_type->default_properties), - (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval*)); -#else - object_properties_init(&payload->obj, class_type); -#endif + INIT_CLASS_ENTRY(ce, "MustacheCode", MustacheCode_methods); + MustacheCode_ce_ptr = zend_register_internal_class(&ce TSRMLS_CC); - retval.handle = zend_objects_store_put(payload, NULL, (zend_objects_free_object_storage_t) MustacheCode_obj_free, NULL TSRMLS_CC); - retval.handlers = &MustacheCode_obj_handlers; + zend_declare_property_null(MustacheCode_ce_ptr, "binaryString", sizeof("binaryString") - 1, ZEND_ACC_PROTECTED TSRMLS_CC); + return SUCCESS; } catch(...) { mustache_exception_handler(TSRMLS_C); + return FAILURE; } - - return retval; } +/* }}} */ - - -// Methods --------------------------------------------------------------------- - -/* {{{ proto void __construct(string binaryString) - */ +/* {{{ proto void MustacheCode::__construct(string binaryString) */ PHP_METHOD(MustacheCode, __construct) { try { @@ -83,68 +62,20 @@ PHP_METHOD(MustacheCode, __construct) // Class parameters _this_zval = getThis(); - zend_class_entry * _this_ce = Z_OBJCE_P(_this_zval); - php_obj_MustacheCode * payload = - (php_obj_MustacheCode *) zend_object_store_get_object(_this_zval TSRMLS_CC); - - // Check payload - if( payload->codes != NULL ) { - throw InvalidParameterException("MustacheCode is already initialized"); - } - - // Copy - if( str_len > 0 ) { - payload->codes = (uint8_t *) malloc(sizeof(uint8_t) * str_len); - memcpy(payload->codes, str, str_len); - payload->length = str_len; - } - - } catch(...) { - mustache_exception_handler(TSRMLS_C); - } -} -/* }}} __construct */ -/* {{{ proto void __sleep() - */ -PHP_METHOD(MustacheCode, __sleep) -{ - try { - // Check parameters - zval * _this_zval = NULL; - if( zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), (char *) "O", - &_this_zval, MustacheCode_ce_ptr) == FAILURE) { - throw PhpInvalidParameterException(); - } - - // Class parameters - _this_zval = getThis(); - zend_class_entry * _this_ce = Z_OBJCE_P(_this_zval); - php_obj_MustacheCode * payload = - (php_obj_MustacheCode *) zend_object_store_get_object(_this_zval TSRMLS_CC); - - array_init(return_value); - - // Check payload - if( payload->codes != NULL ) { - // Serialize and store - if( payload->codes != NULL ) { - zend_update_property_stringl(MustacheCode_ce_ptr, _this_zval, - ZEND_STRL("binaryString"), (const char *) payload->codes, - payload->length TSRMLS_CC); - - add_next_index_string(return_value, "binaryString", 1); - } + // Check if data was null + if( str != NULL ) { + zend_update_property_stringl(MustacheCode_ce_ptr, _this_zval, + "binaryString", sizeof("binaryString") - 1, str, str_len TSRMLS_CC); } } catch(...) { mustache_exception_handler(TSRMLS_C); } } -/* }}} __sleep */ +/* }}} MustacheCode::__construct */ -/* {{{ proto string toReadableString() - */ +/* {{{ proto string MustacheCode::toReadableString() */ PHP_METHOD(MustacheCode, toReadableString) { try { @@ -157,34 +88,32 @@ PHP_METHOD(MustacheCode, toReadableString) // Class parameters _this_zval = getThis(); - zend_class_entry * _this_ce = Z_OBJCE_P(_this_zval); - php_obj_MustacheCode * payload = - (php_obj_MustacheCode *) zend_object_store_get_object(_this_zval TSRMLS_CC); - - // Check payload - if( payload->codes == NULL ) { - throw InvalidParameterException("MustacheCode was not initialized properly"); + + zval rv; + zval * value = _zend_read_property(Z_OBJCE_P(_this_zval), _this_zval, "binaryString", sizeof("binaryString")-1, 1, &rv); + if( !value || Z_TYPE_P(value) != IS_STRING ) { + RETURN_FALSE; } - + + uint8_t * tmp = (uint8_t *) Z_STRVAL_P(value); + size_t tmp_len = Z_STRLEN_P(value) * sizeof(uint8_t) / sizeof(char); + // Print codes - std::string * output = mustache::Compiler::print(payload->codes, payload->length); + std::string * output = mustache::Compiler::print(tmp, tmp_len); // Copy if( output != NULL ) { - int length = output->length(); - char * str = (char *) estrndup((char *) output->c_str(), length); + _RETVAL_STRINGL((char *) output->c_str(), output->length()); delete output; - RETURN_STRINGL(str, length, 0); } } catch(...) { mustache_exception_handler(TSRMLS_C); } } -/* }}} toReadableString */ +/* }}} MustacheCode::toReadableString */ -/* {{{ proto string __toString() - */ +/* {{{ proto string MustacheCode::__toString() */ PHP_METHOD(MustacheCode, __toString) { try { @@ -197,147 +126,16 @@ PHP_METHOD(MustacheCode, __toString) // Class parameters _this_zval = getThis(); - zend_class_entry * _this_ce = Z_OBJCE_P(_this_zval); - php_obj_MustacheCode * payload = - (php_obj_MustacheCode *) zend_object_store_get_object(_this_zval TSRMLS_CC); - - // Check payload - if( payload->codes == NULL ) { - throw InvalidParameterException("MustacheCode was not initialized properly"); - } - - // Copy - if( payload->length > 0 ) { - char * str = (char *) estrndup((char *) payload->codes, payload->length); - RETURN_STRINGL(str, payload->length, 0); - } - - } catch(...) { - mustache_exception_handler(TSRMLS_C); - } -} -/* }}} __toString */ - -/* {{{ proto void __wakeup() - */ -PHP_METHOD(MustacheCode, __wakeup) -{ - try { - // Check parameters - zval * _this_zval = NULL; - if( zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), (char *) "O", - &_this_zval, MustacheCode_ce_ptr) == FAILURE) { - throw PhpInvalidParameterException(); - } - - // Class parameters - _this_zval = getThis(); - zend_class_entry * _this_ce = Z_OBJCE_P(_this_zval); - php_obj_MustacheCode * payload = - (php_obj_MustacheCode *) zend_object_store_get_object(_this_zval TSRMLS_CC); - - // Get object properties - // @todo should be able to convert this to use zend_hash_find - int key_type = 0; - char * key_str = NULL; - uint key_len = 0; - ulong key_nindex = 0; - HashTable * data_hash = NULL; - HashPosition data_pointer = NULL; - zval **data_entry = NULL; - long data_count = 0; - if( Z_OBJ_HT_P(_this_zval)->get_properties != NULL ) { - data_hash = Z_OBJ_HT_P(_this_zval)->get_properties(_this_zval TSRMLS_CC); - data_count = zend_hash_num_elements(data_hash); - } - if( data_hash != NULL ) { - char *prop_name, *class_name; - zend_hash_internal_pointer_reset_ex(data_hash, &data_pointer); - while( zend_hash_get_current_data_ex(data_hash, (void**) &data_entry, &data_pointer) == SUCCESS ) { - if( zend_hash_get_current_key_ex(data_hash, &key_str, &key_len, - &key_nindex, false, &data_pointer) == HASH_KEY_IS_STRING ) { -#if PHP_API_VERSION >= 20100412 - zend_unmangle_property_name(key_str, key_len-1, (const char **) &class_name, (const char **) &prop_name); -#else - zend_unmangle_property_name(key_str, key_len-1, &class_name, &prop_name); -#endif - if( strcmp(prop_name, "binaryString") == 0 && Z_TYPE_PP(data_entry) == IS_STRING ) { - if( payload->codes != NULL ) { - free(payload->codes); - payload->codes = NULL; - } - payload->length = Z_STRLEN_PP(data_entry); - payload->codes = (uint8_t *) malloc(sizeof(uint8_t) * payload->length); - memcpy(payload->codes, Z_STRVAL_PP(data_entry), payload->length); - } - } - zend_hash_move_forward_ex(data_hash, &data_pointer); - } - } + // Return + zval rv; + zval * value = _zend_read_property(Z_OBJCE_P(_this_zval), _this_zval, "binaryString", sizeof("binaryString")-1, 1, &rv); + convert_to_string(value); + RETURN_ZVAL(value, 1, 0); } catch(...) { mustache_exception_handler(TSRMLS_C); } } -/* }}} __wakeup */ - - - -// Argument Info --------------------------------------------------------------- - -ZEND_BEGIN_ARG_INFO_EX(MustacheCode____construct_args, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 0) - ZEND_ARG_INFO(0, codeString) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(MustacheCode____sleep_args, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 0) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(MustacheCode__toReadableString_args, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 0) -ZEND_END_ARG_INFO() +/* }}} MustacheCode::__toString */ -ZEND_BEGIN_ARG_INFO_EX(MustacheCode____toString_args, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 0) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(MustacheCode____wakeup_args, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 0) -ZEND_END_ARG_INFO() - - - -// Method Entries -------------------------------------------------------------- - -static zend_function_entry MustacheCode_methods[] = { - PHP_ME(MustacheCode, __construct, MustacheCode____construct_args, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR) - PHP_ME(MustacheCode, __sleep, MustacheCode____sleep_args, ZEND_ACC_PUBLIC) - PHP_ME(MustacheCode, toReadableString, MustacheCode__toReadableString_args, ZEND_ACC_PUBLIC) - PHP_ME(MustacheCode, __toString, MustacheCode____toString_args, ZEND_ACC_PUBLIC) - PHP_ME(MustacheCode, __wakeup, MustacheCode____wakeup_args, ZEND_ACC_PUBLIC) - { NULL, NULL, NULL } -}; - - - -// MINIT ----------------------------------------------------------------------- - -PHP_MINIT_FUNCTION(mustache_code) -{ - try { - zend_class_entry ce; - - memcpy(&MustacheCode_obj_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); - MustacheCode_obj_handlers.clone_obj = NULL; - - INIT_CLASS_ENTRY(ce, "MustacheCode", MustacheCode_methods); - ce.create_object = MustacheCode_obj_create; - - MustacheCode_ce_ptr = zend_register_internal_class(&ce TSRMLS_CC); - MustacheCode_ce_ptr->create_object = MustacheCode_obj_create; - - zend_declare_property_null(MustacheCode_ce_ptr, ZEND_STRL("binaryString"), ZEND_ACC_PROTECTED TSRMLS_CC); - - return SUCCESS; - } catch(...) { - mustache_exception_handler(TSRMLS_C); - return FAILURE; - } -} diff --git a/mustache_code.hpp b/mustache_code.hpp new file mode 100644 index 0000000..a4d9007 --- /dev/null +++ b/mustache_code.hpp @@ -0,0 +1,22 @@ + +#ifndef PHP_MUSTACHE_CODE_HPP +#define PHP_MUSTACHE_CODE_HPP + +#ifdef __cplusplus +extern "C" { +#endif + +extern zend_class_entry * MustacheCode_ce_ptr; + +PHP_MINIT_FUNCTION(mustache_code); + +PHP_METHOD(MustacheCode, __construct); +PHP_METHOD(MustacheCode, toReadableString); +PHP_METHOD(MustacheCode, __toString); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* PHP_MUSTACHE_CODE_HPP */ + diff --git a/mustache_data.cpp b/mustache_data.cpp index 57dfb43..4e3f903 100644 --- a/mustache_data.cpp +++ b/mustache_data.cpp @@ -1,45 +1,145 @@ -#include "php_mustache.hpp" +#include "mustache_private.hpp" +/* {{{ ZE2 OO definitions */ +zend_class_entry * MustacheData_ce_ptr; +static zend_object_handlers MustacheData_obj_handlers; +/* }}} */ - -// Declarations ---------------------------------------------------------------- - -PHP_METHOD(MustacheData, __construct); -PHP_METHOD(MustacheData, toValue); - - - -// Argument Info --------------------------------------------------------------- - +/* {{{ arginfo */ ZEND_BEGIN_ARG_INFO_EX(MustacheData____construct_args, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 1) ZEND_ARG_INFO(0, tmpl) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(MustacheData__toValue_args, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 0) ZEND_END_ARG_INFO() +/* }}} */ +/* {{{ MustacheData_methods */ +static zend_function_entry MustacheData_methods[] = { + PHP_ME(MustacheData, __construct, MustacheData____construct_args, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR) + PHP_ME(MustacheData, toValue, MustacheData__toValue_args, ZEND_ACC_PUBLIC) + { NULL, NULL, NULL } +}; +/* }}} */ +/* {{{ php_mustache_data_object_fetch_object */ +#if PHP_MAJOR_VERSION < 7 +struct php_obj_MustacheData * php_mustache_data_object_fetch_object(zval * zv TSRMLS_DC) +{ + return (struct php_obj_MustacheData *) zend_object_store_get_object(zv TSRMLS_CC); +} +#else +static inline struct php_obj_MustacheData * php_mustache_data_fetch_object(zend_object * obj TSRMLS_DC) +{ + return (struct php_obj_MustacheData *)((char*)(obj) - XtOffsetOf(struct php_obj_MustacheData, std)); +} -// Class Entries --------------------------------------------------------------- +struct php_obj_MustacheData * php_mustache_data_object_fetch_object(zval * zv TSRMLS_DC) +{ + return php_mustache_data_fetch_object(Z_OBJ_P(zv) TSRMLS_CC); +} +#endif +/* }}} */ -zend_class_entry * MustacheData_ce_ptr; +/* {{{ MustacheData_obj_free */ +#if PHP_MAJOR_VERSION < 7 +static void MustacheData_obj_free(void *object TSRMLS_DC) +{ + try { + struct php_obj_MustacheData * payload = (struct php_obj_MustacheData *) object; + + if( payload->data != NULL ) { + delete payload->data; + } + efree(object); + } catch(...) { + mustache_exception_handler(TSRMLS_C); + } +} +#else +static void MustacheData_obj_free(zend_object *object TSRMLS_DC) +{ + try { + struct php_obj_MustacheData * payload = php_mustache_data_fetch_object(object TSRMLS_CC); + + if( payload->data != NULL ) { + delete payload->data; + } + + zend_object_std_dtor((zend_object *)object TSRMLS_CC); + } catch(...) { + mustache_exception_handler(TSRMLS_C); + } +} +#endif +/* }}} */ +/* {{{ MustacheData_obj_create */ +#if PHP_MAJOR_VERSION < 7 +static zend_object_value MustacheData_obj_create(zend_class_entry *class_type TSRMLS_DC) +{ + zend_object_value retval; + + try { + struct php_obj_MustacheData * payload; -// Method Entries -------------------------------------------------------------- + payload = (struct php_obj_MustacheData *) emalloc(sizeof(struct php_obj_MustacheData)); + memset(payload, 0, sizeof(struct php_obj_MustacheData)); + payload->std.ce = class_type; -static zend_function_entry MustacheData_methods[] = { - PHP_ME(MustacheData, __construct, MustacheData____construct_args, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR) - PHP_ME(MustacheData, toValue, MustacheData__toValue_args, ZEND_ACC_PUBLIC) - { NULL, NULL, NULL } -}; + payload->data = NULL; + + retval.handle = zend_objects_store_put(payload, NULL, (zend_objects_free_object_storage_t) MustacheData_obj_free, NULL TSRMLS_CC); + retval.handlers = &MustacheData_obj_handlers; + } catch(...) { + mustache_exception_handler(TSRMLS_C); + } + return retval; +} +#else +static zend_object * MustacheData_obj_create(zend_class_entry * ce TSRMLS_DC) +{ + struct php_obj_MustacheData * intern; + + try { + intern = (struct php_obj_MustacheData *) ecalloc(1, sizeof(struct php_obj_MustacheData) + zend_object_properties_size(ce)); + zend_object_std_init(&intern->std, ce TSRMLS_CC); + intern->std.handlers = &MustacheData_obj_handlers; + } catch(...) { + mustache_exception_handler(TSRMLS_C); + } + + return &intern->std; +} +#endif +/* }}} */ -// Utility --------------------------------------------------------------------- +/* {{{ PHP_MINIT_FUNCTION */ +PHP_MINIT_FUNCTION(mustache_data) +{ + zend_class_entry ce; -void mustache_data_from_zval(mustache::Data * node, zval * current TSRMLS_DC) + INIT_CLASS_ENTRY(ce, "MustacheData", MustacheData_methods); + ce.create_object = MustacheData_obj_create; + MustacheData_ce_ptr = zend_register_internal_class(&ce TSRMLS_CC); + memcpy(&MustacheData_obj_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); +#if PHP_MAJOR_VERSION >= 7 + MustacheData_obj_handlers.offset = XtOffsetOf(struct php_obj_MustacheData, std); + MustacheData_obj_handlers.free_obj = MustacheData_obj_free; +#endif + MustacheData_obj_handlers.clone_obj = NULL; + + return SUCCESS; +} +/* }}} */ + +/* {{{ mustache_data_from_array_zval */ +#if PHP_MAJOR_VERSION < 7 +static zend_always_inline void mustache_data_from_array_zval(mustache::Data * node, zval * current TSRMLS_DC) { HashTable * data_hash = NULL; HashPosition data_pointer = NULL; @@ -55,102 +155,247 @@ void mustache_data_from_zval(mustache::Data * node, zval * current TSRMLS_DC) int ArrayPos = 0; mustache::Data * child = NULL; zend_class_entry * ce = NULL; + + node->type = mustache::Data::TypeNone; + + data_hash = HASH_OF(current); + data_count = zend_hash_num_elements(data_hash); + zend_hash_internal_pointer_reset_ex(data_hash, &data_pointer); + while( zend_hash_get_current_data_ex(data_hash, (void**) &data_entry, &data_pointer) == SUCCESS ) { + // Get current key + key_type = zend_hash_get_current_key_ex(data_hash, &key_str, &key_len, &key_nindex, false, &data_pointer); + // Check key type + if( key_type == HASH_KEY_IS_LONG ) { + if( node->type == mustache::Data::TypeNone ) { + node->init(mustache::Data::TypeArray, data_count); + } else if( node->type != mustache::Data::TypeArray ) { + php_error(E_WARNING, "Mixed numeric and associative arrays are not supported"); + return; // EXIT + } + } else { + if( node->type == mustache::Data::TypeNone ) { + node->type = mustache::Data::TypeMap; + } else if( node->type != mustache::Data::TypeMap ) { + php_error(E_WARNING, "Mixed numeric and associative arrays are not supported"); + return; // EXIT + } + } + + // Store value + if( node->type == mustache::Data::TypeArray ) { + child = new mustache::Data(); + mustache_data_from_zval(child, *data_entry TSRMLS_CC); + node->array[ArrayPos++] = child; + node->length = ArrayPos; + } else if( node->type == mustache::Data::TypeMap ) { + child = new mustache::Data; + mustache_data_from_zval(child, *data_entry TSRMLS_CC); + ckey.assign(key_str); + node->data.insert(std::pair(ckey,child)); + } else { + php_error(E_WARNING, "Weird data conflict"); + // Whoops + } + zend_hash_move_forward_ex(data_hash, &data_pointer); + } +} +#else +static zend_always_inline void mustache_data_from_array_zval(mustache::Data * node, zval * current TSRMLS_DC) +{ + HashTable * data_hash = NULL; + long data_count = 0; + ulong key_nindex = 0; + zend_string * key; + std::string ckey; + zval * data_entry = NULL; - switch( Z_TYPE_P(current) ) { - case IS_NULL: - case IS_LONG: - case IS_BOOL: - case IS_DOUBLE: - case IS_STRING: - convert_to_string(current); - node->type = mustache::Data::TypeString; - node->val = new std::string(Z_STRVAL_P(current)/*, (size_t) Z_STRLEN_P(current)*/); - break; - case IS_ARRAY: // START IS_ARRAY ----------------------------------------- - node->type = mustache::Data::TypeNone; - - data_hash = HASH_OF(current); - data_count = zend_hash_num_elements(data_hash); - zend_hash_internal_pointer_reset_ex(data_hash, &data_pointer); - while( zend_hash_get_current_data_ex(data_hash, (void**) &data_entry, &data_pointer) == SUCCESS ) { - // Get current key - key_type = zend_hash_get_current_key_ex(data_hash, &key_str, &key_len, &key_nindex, false, &data_pointer); - // Check key type - if( key_type == HASH_KEY_IS_LONG ) { - if( node->type == mustache::Data::TypeNone ) { - node->init(mustache::Data::TypeArray, data_count); - } else if( node->type != mustache::Data::TypeArray ) { - php_error(E_WARNING, "Mixed numeric and associative arrays are not supported"); - return; // EXIT - } - } else { - if( node->type == mustache::Data::TypeNone ) { - node->type = mustache::Data::TypeMap; - } else if( node->type != mustache::Data::TypeMap ) { - php_error(E_WARNING, "Mixed numeric and associative arrays are not supported"); - return; // EXIT - } - } - - // Store value - if( node->type == mustache::Data::TypeArray ) { - child = new mustache::Data(); - mustache_data_from_zval(child, *data_entry TSRMLS_CC); - node->array[ArrayPos++] = child; - node->length = ArrayPos; - } else if( node->type == mustache::Data::TypeMap ) { - child = new mustache::Data; - mustache_data_from_zval(child, *data_entry TSRMLS_CC); - ckey.assign(key_str); - node->data.insert(std::pair(ckey,child)); - } else { - php_error(E_WARNING, "Weird data conflict"); - // Whoops - } - zend_hash_move_forward_ex(data_hash, &data_pointer); - } + int ArrayPos = 0; + mustache::Data * child = NULL; + zend_class_entry * ce = NULL; + + node->type = mustache::Data::TypeNone; + + data_hash = HASH_OF(current); + data_count = zend_hash_num_elements(data_hash); + ZEND_HASH_FOREACH_KEY_VAL(data_hash, key_nindex, key, data_entry) { + if( !key ) { + if( node->type == mustache::Data::TypeNone ) { + node->init(mustache::Data::TypeArray, data_count); + } else if( node->type != mustache::Data::TypeArray ) { + php_error(E_WARNING, "Mixed numeric and associative arrays are not supported"); + return; // EXIT + } + } else { + if( node->type == mustache::Data::TypeNone ) { + node->type = mustache::Data::TypeMap; + } else if( node->type != mustache::Data::TypeMap ) { + php_error(E_WARNING, "Mixed numeric and associative arrays are not supported"); + return; // EXIT + } + } + + // Store value + if( node->type == mustache::Data::TypeArray ) { + child = new mustache::Data(); + mustache_data_from_zval(child, data_entry TSRMLS_CC); + node->array[ArrayPos++] = child; + node->length = ArrayPos; + } else if( node->type == mustache::Data::TypeMap ) { + child = new mustache::Data; + mustache_data_from_zval(child, data_entry TSRMLS_CC); + ckey.assign(key->val); + node->data.insert(std::pair(ckey, child)); + } else { + php_error(E_WARNING, "Weird data conflict"); + // Whoops + } + } ZEND_HASH_FOREACH_END(); +} +#endif +/* }}} mustache_data_from_array_zval */ + +/* {{{ mustache_data_from_object_zval */ +#if PHP_MAJOR_VERSION < 7 +static zend_always_inline void mustache_data_from_object_zval(mustache::Data * node, zval * current TSRMLS_DC) +{ + HashTable * data_hash = NULL; + HashPosition data_pointer = NULL; + zval **data_entry = NULL; + long data_count = 0; - break; // END IS_ARRAY ------------------------------------------------- - case IS_OBJECT: - node->type = mustache::Data::TypeNone; - - if( Z_OBJCE_P(current) == MustacheData_ce_ptr ) { - // @todo - php_error(E_WARNING, "MustacheData not implemented here"); - } else { - // Get object properties - if( Z_OBJ_HT_P(current)->get_properties != NULL ) { - data_hash = Z_OBJ_HT_P(current)->get_properties(current TSRMLS_CC); - data_count = zend_hash_num_elements(data_hash); - } - if( data_hash != NULL ) { - char *prop_name, *class_name; - node->type = mustache::Data::TypeMap; - zend_hash_internal_pointer_reset_ex(data_hash, &data_pointer); - while( zend_hash_get_current_data_ex(data_hash, (void**) &data_entry, &data_pointer) == SUCCESS ) { - if( zend_hash_get_current_key_ex(data_hash, &key_str, &key_len, - &key_nindex, false, &data_pointer) == HASH_KEY_IS_STRING ) { + int key_type = 0; + char * key_str = NULL; + uint key_len = 0; + ulong key_nindex = 0; + std::string ckey; + + int ArrayPos = 0; + mustache::Data * child = NULL; + zend_class_entry * ce = NULL; + + node->type = mustache::Data::TypeNone; + + if( Z_OBJCE_P(current) == MustacheData_ce_ptr ) { + // @todo + php_error(E_WARNING, "MustacheData not implemented here"); + } else { + // Get object properties + if( Z_OBJ_HT_P(current)->get_properties != NULL ) { + data_hash = Z_OBJ_HT_P(current)->get_properties(current TSRMLS_CC); + data_count = zend_hash_num_elements(data_hash); + } + if( data_hash != NULL ) { + char *prop_name, *class_name; + node->type = mustache::Data::TypeMap; + zend_hash_internal_pointer_reset_ex(data_hash, &data_pointer); + while( zend_hash_get_current_data_ex(data_hash, (void**) &data_entry, &data_pointer) == SUCCESS ) { + if( zend_hash_get_current_key_ex(data_hash, &key_str, &key_len, + &key_nindex, false, &data_pointer) == HASH_KEY_IS_STRING ) { #if PHP_API_VERSION >= 20100412 - zend_unmangle_property_name(key_str, key_len-1, (const char **) &class_name, (const char **) &prop_name); + zend_unmangle_property_name(key_str, key_len-1, (const char **) &class_name, (const char **) &prop_name); #else - zend_unmangle_property_name(key_str, key_len-1, &class_name, &prop_name); + zend_unmangle_property_name(key_str, key_len-1, &class_name, &prop_name); #endif - child = new mustache::Data; - mustache_data_from_zval(child, *data_entry TSRMLS_CC); - ckey.assign(prop_name); - node->data.insert(std::pair(ckey,child)); - } - zend_hash_move_forward_ex(data_hash, &data_pointer); - } + child = new mustache::Data; + mustache_data_from_zval(child, *data_entry TSRMLS_CC); + ckey.assign(prop_name); + node->data.insert(std::pair(ckey,child)); } + zend_hash_move_forward_ex(data_hash, &data_pointer); } - break; - default: - php_error(E_WARNING, "Invalid data type: %d", Z_TYPE_P(current)); - break; + } } } +#else +static zend_always_inline void mustache_data_from_object_zval(mustache::Data * node, zval * current TSRMLS_DC) +{ + HashTable * data_hash = NULL; + long data_count = 0; + ulong key_nindex = 0; + zend_string * key; + std::string ckey; + zval * data_entry = NULL; + + int ArrayPos = 0; + mustache::Data * child = NULL; + zend_class_entry * ce = NULL; + + node->type = mustache::Data::TypeNone; + + data_hash = Z_OBJ_HT_P(current)->get_properties(current TSRMLS_CC); + data_count = zend_hash_num_elements(data_hash); + ZEND_HASH_FOREACH_KEY_VAL(data_hash, key_nindex, key, data_entry) { + if( !key ) { + if( node->type == mustache::Data::TypeNone ) { + node->init(mustache::Data::TypeArray, data_count); + } else if( node->type != mustache::Data::TypeArray ) { + php_error(E_WARNING, "Mixed numeric and associative arrays are not supported"); + return; // EXIT + } + } else { + if( node->type == mustache::Data::TypeNone ) { + node->type = mustache::Data::TypeMap; + } else if( node->type != mustache::Data::TypeMap ) { + php_error(E_WARNING, "Mixed numeric and associative arrays are not supported"); + return; // EXIT + } + } + + // Store value + if( node->type == mustache::Data::TypeArray ) { + child = new mustache::Data(); + mustache_data_from_zval(child, data_entry TSRMLS_CC); + node->array[ArrayPos++] = child; + node->length = ArrayPos; + } else if( node->type == mustache::Data::TypeMap ) { + child = new mustache::Data; + mustache_data_from_zval(child, data_entry TSRMLS_CC); + ckey.assign(key->val); + node->data.insert(std::pair(ckey, child)); + } else { + php_error(E_WARNING, "Weird data conflict"); + // Whoops + } + } ZEND_HASH_FOREACH_END(); +} +#endif +/* }}} mustache_data_from_object_zval */ + +/* {{{ mustache_data_from_zval */ +void mustache_data_from_zval(mustache::Data * node, zval * current TSRMLS_DC) +{ + if (Z_TYPE_P(current) == IS_INDIRECT) { + current = Z_INDIRECT_P(current); + } + switch( Z_TYPE_P(current) ) { + case IS_NULL: + case IS_LONG: +#if PHP_MAJOR_VERSION < 7 + case IS_BOOL: +#else + case IS_TRUE: + case IS_FALSE: +#endif + case IS_DOUBLE: + case IS_STRING: + convert_to_string(current); + node->type = mustache::Data::TypeString; + node->val = new std::string(Z_STRVAL_P(current)/*, (size_t) Z_STRLEN_P(current)*/); + break; + case IS_ARRAY: + mustache_data_from_array_zval(node, current); + break; + case IS_OBJECT: + mustache_data_from_object_zval(node, current); + break; + default: + php_error(E_WARNING, "Invalid data type: %d", Z_TYPE_P(current)); + break; + } +} +/* }}} mustache_data_from_zval */ +/* {{{ mustache_data_to_zval */ void mustache_data_to_zval(mustache::Data * node, zval * current TSRMLS_DC) { mustache::Data::Array::iterator a_it; @@ -158,21 +403,20 @@ void mustache_data_to_zval(mustache::Data * node, zval * current TSRMLS_DC) mustache::Data::Map::iterator m_it; mustache::Data::Array childNode; int pos = 0; - + _DECLARE_ZVAL(child); + + switch( node->type ) { case mustache::Data::TypeNone: - Z_TYPE_P(current) = IS_NULL; + ZVAL_NULL(current); break; case mustache::Data::TypeString: - Z_TYPE_P(current) = IS_STRING; - Z_STRVAL_P(current) = (char *) estrdup(node->val->c_str()); - Z_STRLEN_P(current) = node->val->length(); + _ZVAL_STRINGL(current, node->val->c_str(), node->val->length()); break; case mustache::Data::TypeArray: array_init(current); for( pos = 0; pos < node->length; pos++ ) { - zval * child = NULL; - ALLOC_INIT_ZVAL(child); + _ALLOC_INIT_ZVAL(child); mustache_data_to_zval(node->array[pos], child TSRMLS_CC); add_next_index_zval(current, child); } @@ -192,8 +436,7 @@ void mustache_data_to_zval(mustache::Data * node, zval * current TSRMLS_DC) case mustache::Data::TypeList: array_init(current); for ( l_it = node->children.begin() ; l_it != node->children.end(); l_it++ ) { - zval * child = NULL; - ALLOC_INIT_ZVAL(child); + _ALLOC_INIT_ZVAL(child); mustache_data_to_zval(*l_it, child TSRMLS_CC); add_next_index_zval(current, child); } @@ -201,86 +444,20 @@ void mustache_data_to_zval(mustache::Data * node, zval * current TSRMLS_DC) case mustache::Data::TypeMap: array_init(current); for ( m_it = node->data.begin() ; m_it != node->data.end(); m_it++ ) { - zval * child = NULL; - ALLOC_INIT_ZVAL(child); + _ALLOC_INIT_ZVAL(child); mustache_data_to_zval((*m_it).second, child TSRMLS_CC); add_assoc_zval(current, (*m_it).first.c_str(), child); } break; default: - Z_TYPE_P(current) = IS_NULL; + ZVAL_NULL(current); php_error(E_WARNING, "Invalid data type"); break; } } +/* }}} mustache_data_to_zval */ - - -// Object Handlers ------------------------------------------------------------- - -static zend_object_handlers MustacheData_obj_handlers; - -static void MustacheData_obj_free(void *object TSRMLS_DC) -{ - try { - php_obj_MustacheData * payload = (php_obj_MustacheData *) object; - - if( payload->data != NULL ) { - delete payload->data; - } - - efree(object); - } catch(...) { - mustache_exception_handler(TSRMLS_C); - } -} - -static zend_object_value MustacheData_obj_create(zend_class_entry *class_type TSRMLS_DC) -{ - zend_object_value retval; - - try { - php_obj_MustacheData * payload; - - payload = (php_obj_MustacheData *) emalloc(sizeof(php_obj_MustacheData)); - memset(payload, 0, sizeof(php_obj_MustacheData)); - payload->obj.ce = class_type; - - payload->data = NULL; - - retval.handle = zend_objects_store_put(payload, NULL, (zend_objects_free_object_storage_t) MustacheData_obj_free, NULL TSRMLS_CC); - retval.handlers = &MustacheData_obj_handlers; - - } catch(...) { - mustache_exception_handler(TSRMLS_C); - } - - return retval; -} - - - -// MINIT ----------------------------------------------------------------------- - -PHP_MINIT_FUNCTION(mustache_data) -{ - zend_class_entry ce; - - INIT_CLASS_ENTRY(ce, "MustacheData", MustacheData_methods); - ce.create_object = MustacheData_obj_create; - MustacheData_ce_ptr = zend_register_internal_class(&ce TSRMLS_CC); - memcpy(&MustacheData_obj_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); - MustacheData_obj_handlers.clone_obj = NULL; - - return SUCCESS; -} - - - -// Methods --------------------------------------------------------------------- - -/* {{{ proto void __construct() - */ +/* {{{ proto void MustacheData::__construct() */ PHP_METHOD(MustacheData, __construct) { try { @@ -297,8 +474,7 @@ PHP_METHOD(MustacheData, __construct) // Class parameters _this_zval = getThis(); zend_class_entry * _this_ce = Z_OBJCE_P(_this_zval); - php_obj_MustacheData * payload = - (php_obj_MustacheData *) zend_object_store_get_object(_this_zval TSRMLS_CC); + struct php_obj_MustacheData * payload = php_mustache_data_object_fetch_object(_this_zval TSRMLS_CC); // Check if argument was given if( data == NULL ) { @@ -313,10 +489,9 @@ PHP_METHOD(MustacheData, __construct) mustache_exception_handler(TSRMLS_C); } } -/* }}} __construct */ +/* }}} MustacheData::__construct */ -/* {{{ proto mixed toValue() - */ +/* {{{ proto mixed MustacheData::toValue() */ PHP_METHOD(MustacheData, toValue) { try { @@ -329,8 +504,7 @@ PHP_METHOD(MustacheData, toValue) _this_zval = getThis(); zend_class_entry * _this_ce = Z_OBJCE_P(_this_zval); - php_obj_MustacheData * payload = - (php_obj_MustacheData *) zend_object_store_get_object(_this_zval TSRMLS_CC); + struct php_obj_MustacheData * payload = php_mustache_data_object_fetch_object(_this_zval TSRMLS_CC); // Check if data was initialized if( payload->data == NULL ) { @@ -346,4 +520,5 @@ PHP_METHOD(MustacheData, toValue) mustache_exception_handler(TSRMLS_C); } } -/* }}} toValue */ +/* }}} MustacheData::toValue */ + diff --git a/mustache_data.hpp b/mustache_data.hpp new file mode 100644 index 0000000..0e48ac1 --- /dev/null +++ b/mustache_data.hpp @@ -0,0 +1,38 @@ + +#ifndef PHP_MUSTACHE_DATA_HPP +#define PHP_MUSTACHE_DATA_HPP + +#ifdef __cplusplus + extern "C" { +#endif + +#if PHP_MAJOR_VERSION < 7 +struct php_obj_MustacheData { + zend_object std; + mustache::Data * data; +}; +#else +struct php_obj_MustacheData { + mustache::Data * data; + zend_object std; +}; +#endif + +extern zend_class_entry * MustacheData_ce_ptr; + +struct php_obj_MustacheData * php_mustache_data_object_fetch_object(zval * zv TSRMLS_DC); + +PHP_MINIT_FUNCTION(mustache_data); + +void mustache_data_from_zval(mustache::Data * node, zval * current TSRMLS_DC); +void mustache_data_to_zval(mustache::Data * node, zval * current TSRMLS_DC); + +PHP_METHOD(MustacheData, __construct); +PHP_METHOD(MustacheData, toValue); + +#ifdef __cplusplus + } // extern "C" +#endif + +#endif /* PHP_MUSTACHE_DATA_HPP */ + diff --git a/mustache_exceptions.cpp b/mustache_exceptions.cpp index de12543..bee0e69 100644 --- a/mustache_exceptions.cpp +++ b/mustache_exceptions.cpp @@ -1,17 +1,12 @@ -#include "php_mustache.hpp" - - - -// Class Entries -------------------------------------------------------------- +#include "mustache_private.hpp" +/* {{{ ZE2 OO definitions */ zend_class_entry * MustacheException_ce_ptr; zend_class_entry * MustacheParserException_ce_ptr; +/* }}} */ - - -// MINIT ----------------------------------------------------------------------- - +/* {{{ PHP_MINIT_FUNCTION */ PHP_MINIT_FUNCTION(mustache_exceptions) { try { @@ -19,16 +14,14 @@ PHP_MINIT_FUNCTION(mustache_exceptions) // MustacheException zend_class_entry mustache_exception_ce; - INIT_CLASS_ENTRY_EX(mustache_exception_ce, "MustacheException", strlen("MustacheException"), NULL); - MustacheException_ce_ptr = zend_register_internal_class_ex(&mustache_exception_ce, - exception_ce, NULL TSRMLS_CC); + INIT_CLASS_ENTRY(mustache_exception_ce, "MustacheException", NULL); + MustacheException_ce_ptr = _zend_register_internal_class_ex(&mustache_exception_ce, exception_ce TSRMLS_CC); MustacheException_ce_ptr->create_object = exception_ce->create_object; // MustacheParserException zend_class_entry mustache_parser_exception_ce; - INIT_CLASS_ENTRY_EX(mustache_parser_exception_ce, "MustacheParserException", strlen("MustacheParserException"), NULL); - MustacheParserException_ce_ptr = zend_register_internal_class_ex(&mustache_parser_exception_ce, - MustacheException_ce_ptr, NULL TSRMLS_CC); + INIT_CLASS_ENTRY(mustache_parser_exception_ce, "MustacheParserException", NULL); + MustacheParserException_ce_ptr = _zend_register_internal_class_ex(&mustache_parser_exception_ce, MustacheException_ce_ptr TSRMLS_CC); MustacheParserException_ce_ptr->create_object = MustacheException_ce_ptr->create_object; return SUCCESS; @@ -37,3 +30,58 @@ PHP_MINIT_FUNCTION(mustache_exceptions) return FAILURE; } } +/* }}} */ + +/* {{{ mustache_exception_handler */ +void mustache_exception_handler(TSRMLS_D) +{ +#if PHP_MUSTACHE_THROW_EXCEPTIONS + throw; +#else + try { + throw; + } catch( mustache::TokenizerException& e ) { + zval * exception; +#if PHP_API_VERSION < 20131218 + exception = zend_throw_exception_ex(MustacheParserException_ce_ptr, + 0 TSRMLS_CC, (char *) e.what(), "MustacheParserException"); +#else + zval ex; + zend_object * obj = zend_throw_exception_ex(MustacheParserException_ce_ptr, + 0 TSRMLS_CC, (char *) e.what(), "MustacheParserException"); + ZVAL_OBJ(&ex, obj); + exception = &ex; +/* + zend_update_property_long(base_exception_ce, &ex, "severity", sizeof("severity")-1, severity); + return obj; + zval exception; + zend_object * exceptionobj = zend_throw_exception_ex(MustacheParserException_ce_ptr, + 0 TSRMLS_CC, (char *) e.what(), "MustacheParserException"); + zval * exception = Z_OBJ_P(exceptionobj); +*/ +#endif + + zend_update_property_long(MustacheParserException_ce_ptr, exception, + (char *) "templateLineNo", strlen("templateLineNo"), e.lineNo TSRMLS_CC); + zend_update_property_long(MustacheParserException_ce_ptr, exception, + (char *) "templateCharNo", strlen("templateCharNo"), e.charNo TSRMLS_CC); + } catch( mustache::Exception& e ) { + zend_throw_exception_ex(MustacheException_ce_ptr, 0 TSRMLS_CC, + (char *) e.what(), "MustacheException"); + //php_error_docref(NULL TSRMLS_CC, E_WARNING, e.what()); + } catch( InvalidParameterException& e ) { + // @todo change this to an exception + php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", e.what()); + } catch( PhpInvalidParameterException& e ) { + // The error message should be handled by PHP + } catch( std::bad_alloc& e ) { + php_error_docref(NULL TSRMLS_CC, E_ERROR, "%s", "Memory allocation failed."); + } catch( std::runtime_error& e ) { + php_error_docref(NULL TSRMLS_CC, E_ERROR, "%s", e.what()); + } catch(...) { + php_error_docref(NULL TSRMLS_CC, E_ERROR, "%s", "An unknown error has occurred."); + } +#endif +} +/* }}} */ + diff --git a/mustache_exceptions.hpp b/mustache_exceptions.hpp new file mode 100644 index 0000000..5558240 --- /dev/null +++ b/mustache_exceptions.hpp @@ -0,0 +1,30 @@ + +#ifndef PHP_MUSTACHE_EXCEPTIONS_HPP +#define PHP_MUSTACHE_EXCEPTIONS_HPP + +#ifdef __cplusplus + extern "C" { +#endif + +extern zend_class_entry * MustacheException_ce_ptr; +extern zend_class_entry * MustacheParserException_ce_ptr; + +PHP_MINIT_FUNCTION(mustache_exceptions); + +void mustache_exception_handler(TSRMLS_D); + +#ifdef __cplusplus + } // extern "C" +#endif + +class PhpInvalidParameterException : public std::exception { + public: +}; + +class InvalidParameterException : public std::runtime_error { + public: + InvalidParameterException(const std::string& desc) : std::runtime_error(desc) { } +}; + +#endif /* PHP_MUSTACHE_EXCEPTIONS_HPP */ + diff --git a/mustache_mustache.cpp b/mustache_mustache.cpp index 57a68c1..55f09bb 100644 --- a/mustache_mustache.cpp +++ b/mustache_mustache.cpp @@ -1,35 +1,107 @@ -#include "php_mustache.hpp" +#include "mustache_private.hpp" +/* {{{ ZE2 OO definitions */ +zend_class_entry * Mustache_ce_ptr; +static zend_object_handlers Mustache_obj_handlers; +/* }}} */ +/* {{{ arginfo */ +ZEND_BEGIN_ARG_INFO_EX(Mustache____construct_args, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 0) +ZEND_END_ARG_INFO() -// Declarations ---------------------------------------------------------------- +ZEND_BEGIN_ARG_INFO_EX(Mustache__getEscapeByDefault_args, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 0) +ZEND_END_ARG_INFO() -extern void mustache_data_from_zval(mustache::Data * node, zval * current TSRMLS_DC); -extern void mustache_data_to_zval(mustache::Data * node, zval * current TSRMLS_DC); -extern void mustache_node_to_zval(mustache::Node * node, zval * current TSRMLS_DC); +ZEND_BEGIN_ARG_INFO_EX(Mustache__getStartSequence_args, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(Mustache__getStopSequence_args, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(Mustache__setEscapeByDefault_args, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 1) + ZEND_ARG_INFO(0, escapeByDefault) +ZEND_END_ARG_INFO() -extern zend_class_entry * MustacheAST_ce_ptr; -extern zend_class_entry * MustacheCode_ce_ptr; -extern zend_class_entry * MustacheData_ce_ptr; -extern zend_class_entry * MustacheTemplate_ce_ptr; +ZEND_BEGIN_ARG_INFO_EX(Mustache__setStartSequence_args, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 1) + ZEND_ARG_INFO(0, startSequence) +ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_INFO_EX(Mustache__setStopSequence_args, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 1) + ZEND_ARG_INFO(0, stopSequence) +ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_INFO_EX(Mustache__compile_args, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 1) + ZEND_ARG_INFO(0, tmpl) +ZEND_END_ARG_INFO() -// Class Entries -------------------------------------------------------------- +ZEND_BEGIN_ARG_INFO_EX(Mustache__execute_args, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 1) + ZEND_ARG_INFO(0, code) +ZEND_END_ARG_INFO() -zend_class_entry * Mustache_ce_ptr; +ZEND_BEGIN_ARG_INFO_EX(Mustache__parse_args, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 1) + ZEND_ARG_INFO(0, tmpl) +ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_INFO_EX(Mustache__render_args, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 3) + ZEND_ARG_INFO(0, str) + ZEND_ARG_INFO(0, vars) + ZEND_ARG_INFO(0, partials) +ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_INFO_EX(Mustache__tokenize_args, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 1) + ZEND_ARG_INFO(0, tmpl) +ZEND_END_ARG_INFO() -// Object Handlers ------------------------------------------------------------- +ZEND_BEGIN_ARG_INFO_EX(Mustache__debugDataStructure_args, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 1) + ZEND_ARG_INFO(0, vars) +ZEND_END_ARG_INFO() +/* }}} */ -static zend_object_handlers Mustache_obj_handlers; +/* {{{ Mustache_methods */ +static zend_function_entry Mustache_methods[] = { + PHP_ME(Mustache, __construct, Mustache____construct_args, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR) + PHP_ME(Mustache, getEscapeByDefault, Mustache__getEscapeByDefault_args, ZEND_ACC_PUBLIC) + PHP_ME(Mustache, getStartSequence, Mustache__getStartSequence_args, ZEND_ACC_PUBLIC) + PHP_ME(Mustache, getStopSequence, Mustache__getStopSequence_args, ZEND_ACC_PUBLIC) + PHP_ME(Mustache, setEscapeByDefault, Mustache__setEscapeByDefault_args, ZEND_ACC_PUBLIC) + PHP_ME(Mustache, setStartSequence, Mustache__setStartSequence_args, ZEND_ACC_PUBLIC) + PHP_ME(Mustache, setStopSequence, Mustache__setStopSequence_args, ZEND_ACC_PUBLIC) + PHP_ME(Mustache, compile, Mustache__compile_args, ZEND_ACC_PUBLIC) + PHP_ME(Mustache, execute, Mustache__execute_args, ZEND_ACC_PUBLIC) + PHP_ME(Mustache, parse, Mustache__parse_args, ZEND_ACC_PUBLIC) + PHP_ME(Mustache, render, Mustache__render_args, ZEND_ACC_PUBLIC) + PHP_ME(Mustache, tokenize, Mustache__tokenize_args, ZEND_ACC_PUBLIC) + PHP_ME(Mustache, debugDataStructure, Mustache__debugDataStructure_args, ZEND_ACC_PUBLIC) + { NULL, NULL, NULL } +}; +/* }}} */ +/* {{{ php_mustache_mustache_object_fetch_object */ +#if PHP_MAJOR_VERSION < 7 +struct php_obj_Mustache * php_mustache_mustache_object_fetch_object(zval * zv TSRMLS_DC) +{ + return (struct php_obj_Mustache *) zend_object_store_get_object(zv TSRMLS_CC); +} +#else +static inline struct php_obj_Mustache * php_mustache_mustache_fetch_object(zend_object * obj TSRMLS_DC) +{ + return (struct php_obj_Mustache *) ((char *)(obj) - XtOffsetOf(struct php_obj_Mustache, std)); +} + +struct php_obj_Mustache * php_mustache_mustache_object_fetch_object(zval * zv TSRMLS_DC) +{ + return php_mustache_mustache_fetch_object(Z_OBJ_P(zv) TSRMLS_CC); +} +#endif +/* }}} */ + +/* {{{ Mustache_obj_free */ +#if PHP_MAJOR_VERSION < 7 static void Mustache_obj_free(void *object TSRMLS_DC) { try { - php_obj_Mustache * payload = (php_obj_Mustache *)object; + struct php_obj_Mustache * payload = (struct php_obj_Mustache *) object; if( payload->mustache != NULL ) { delete payload->mustache; @@ -41,18 +113,37 @@ static void Mustache_obj_free(void *object TSRMLS_DC) mustache_exception_handler(TSRMLS_C); } } +#else +static void Mustache_obj_free(zend_object * object TSRMLS_DC) +{ + try { + struct php_obj_Mustache * payload = php_mustache_mustache_fetch_object(object TSRMLS_CC); + + if( payload->mustache != NULL ) { + delete payload->mustache; + } + + zend_object_std_dtor((zend_object *) object TSRMLS_CC); + } catch(...) { + mustache_exception_handler(TSRMLS_C); + } +} +#endif +/* }}} */ +/* {{{ Mustache_obj_create */ +#if PHP_MAJOR_VERSION < 7 static zend_object_value Mustache_obj_create(zend_class_entry *class_type TSRMLS_DC) { zend_object_value retval; try { - php_obj_Mustache * payload = NULL; + struct php_obj_Mustache * payload = NULL; zval * tmp = NULL; - payload = (php_obj_Mustache *) emalloc(sizeof(php_obj_Mustache)); + payload = (struct php_obj_Mustache *) emalloc(sizeof(php_obj_Mustache)); memset(payload, 0, sizeof(php_obj_Mustache)); - payload->obj.ce = class_type; + payload->std.ce = class_type; payload->mustache = new mustache::Mustache; @@ -79,18 +170,71 @@ static zend_object_value Mustache_obj_create(zend_class_entry *class_type TSRMLS return retval; } +#else +static zend_object * Mustache_obj_create(zend_class_entry * ce TSRMLS_DC) +{ + struct php_obj_Mustache * intern; + + try { + intern = (struct php_obj_Mustache *) ecalloc(1, sizeof(php_obj_Mustache) + zend_object_properties_size(ce)); + zend_object_std_init(&intern->std, ce TSRMLS_CC); + intern->std.handlers = &Mustache_obj_handlers; + intern->mustache = new mustache::Mustache; + + // Set ini settings + if( MUSTACHEG(default_escape_by_default) ) { + intern->mustache->setEscapeByDefault(true); + } else { + intern->mustache->setEscapeByDefault(false); + } + if( MUSTACHEG(default_start_sequence) ) { + intern->mustache->setStartSequence(MUSTACHEG(default_start_sequence), 0); + } + if( MUSTACHEG(default_stop_sequence) ) { + intern->mustache->setStopSequence(MUSTACHEG(default_stop_sequence), 0); + } + } catch(...) { + mustache_exception_handler(TSRMLS_C); + } + + return &intern->std; +} +#endif +/* }}} */ +/* {{{ PHP_MINIT_FUNCTION */ +PHP_MINIT_FUNCTION(mustache_mustache) +{ + try { + zend_class_entry ce; -// Utility --------------------------------------------------------------------- + INIT_CLASS_ENTRY(ce, "Mustache", Mustache_methods); + ce.create_object = Mustache_obj_create; + Mustache_ce_ptr = zend_register_internal_class(&ce TSRMLS_CC); + memcpy(&Mustache_obj_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); +#if PHP_MAJOR_VERSION >= 7 + Mustache_obj_handlers.offset = XtOffsetOf(php_obj_Mustache, std); + Mustache_obj_handlers.free_obj = Mustache_obj_free; +#endif + Mustache_obj_handlers.clone_obj = NULL; + return SUCCESS; + } catch(...) { + mustache_exception_handler(TSRMLS_C); + return FAILURE; + } +} +/* }}} */ + +/* {{{ mustache_parse_data_param */ bool mustache_parse_data_param(zval * data, mustache::Mustache * mustache, mustache::Data ** node TSRMLS_DC) { - php_obj_MustacheData * mdPayload = NULL; + struct php_obj_MustacheData * mdPayload = NULL; if( Z_TYPE_P(data) == IS_OBJECT ) { if( Z_OBJCE_P(data) == MustacheData_ce_ptr ) { - mdPayload = (php_obj_MustacheData *) zend_object_store_get_object(data TSRMLS_CC); + mdPayload = php_mustache_data_object_fetch_object(data TSRMLS_CC); *node = mdPayload->data; return true; } else { @@ -102,76 +246,99 @@ bool mustache_parse_data_param(zval * data, mustache::Mustache * mustache, musta return true; } } +/* }}} */ -bool mustache_parse_partials_param(zval * array, mustache::Mustache * mustache, - mustache::Node::Partials * partials TSRMLS_DC) +/* {{{ mustache_parse_partials_param */ +static inline void mustache_parse_partial_param(char * key, zval * data, + mustache::Mustache * mustache, mustache::Node::Partials * partials TSRMLS_DC) { - HashTable * data_hash = NULL; - HashPosition data_pointer = NULL; - zval **data_entry = NULL; - long data_count = 0; - - int key_type = 0; - char * key_str = NULL; - uint key_len = 0; - ulong key_nindex = 0; - std::string ckey; - - std::string tmpl; - mustache::Node node; - mustache::Node * nodePtr = NULL; - - php_obj_MustacheTemplate * mtPayload = NULL; - php_obj_MustacheAST * maPayload = NULL; - - // Ignore if not an array - if( array == NULL || Z_TYPE_P(array) != IS_ARRAY ) { - return false; - } - - // Iterate over input data - data_hash = HASH_OF(array); - data_count = zend_hash_num_elements(data_hash); - zend_hash_internal_pointer_reset_ex(data_hash, &data_pointer); - while( zend_hash_get_current_data_ex(data_hash, (void**) &data_entry, &data_pointer) == SUCCESS ) { - // Get current key - key_type = zend_hash_get_current_key_ex(data_hash, &key_str, &key_len, &key_nindex, false, &data_pointer); - // Check key type - if( key_type != HASH_KEY_IS_STRING ) { - // Non-string key - php_error(E_WARNING, "Partial array contains a non-string key"); - } else if( Z_TYPE_PP(data_entry) == IS_STRING ) { + std::string ckey; + std::string tmpl; + mustache::Node node; + mustache::Node * nodePtr = NULL; + struct php_obj_MustacheAST * maPayload; + + if( Z_TYPE_P(data) == IS_STRING ) { // String key, string value - ckey.assign(key_str); - tmpl.assign(Z_STRVAL_PP(data_entry)); + ckey.assign(key); + tmpl.assign(Z_STRVAL_P(data)); partials->insert(std::make_pair(ckey, node)); mustache->tokenize(&tmpl, &(*partials)[ckey]); - } else if( Z_TYPE_PP(data_entry) == IS_OBJECT ) { - // String key, object value - if( Z_OBJCE_PP(data_entry) == MustacheTemplate_ce_ptr ) { - ckey.assign(key_str); - mtPayload = (php_obj_MustacheTemplate *) zend_object_store_get_object(*data_entry TSRMLS_CC); - partials->insert(std::make_pair(ckey, node)); - mustache->tokenize(mtPayload->tmpl, &(*partials)[ckey]); - } else if( Z_OBJCE_PP(data_entry) == MustacheAST_ce_ptr ) { - ckey.assign(key_str); - maPayload = (php_obj_MustacheAST *) zend_object_store_get_object(*data_entry TSRMLS_CC); - partials->insert(std::make_pair(ckey, node)); - - // This is kind of hack-ish - nodePtr = &(*partials)[ckey]; - nodePtr->type = mustache::Node::TypeContainer; - nodePtr->child = maPayload->node; - } else { - php_error(E_WARNING, "Object not an instance of MustacheTemplate or MustacheAST"); - } + } else if( Z_TYPE_P(data) == IS_OBJECT ) { + // String key, object value + if( Z_OBJCE_P(data) == MustacheTemplate_ce_ptr ) { + zval rv; + zval * value = _zend_read_property(Z_OBJCE_P(data), data, "template", sizeof("template")-1, 1, &rv); + convert_to_string(value); + std::string tmpstr(Z_STRVAL_P(value)); + ckey.assign(key); + partials->insert(std::make_pair(ckey, node)); + mustache->tokenize(&tmpstr, &(*partials)[ckey]); + } else if( Z_OBJCE_P(data) == MustacheAST_ce_ptr ) { + ckey.assign(key); + maPayload = php_mustache_ast_object_fetch_object(data TSRMLS_CC); + partials->insert(std::make_pair(ckey, node)); + nodePtr = &(*partials)[ckey]; + nodePtr->type = mustache::Node::TypeContainer; + nodePtr->child = maPayload->node; + } else { + php_error(E_WARNING, "Object not an instance of MustacheTemplate or MustacheAST"); + } } else { - php_error(E_WARNING, "Partial array contains an invalid value"); + php_error(E_WARNING, "Partial array contains an invalid value"); } - zend_hash_move_forward_ex(data_hash, &data_pointer); - } } +bool mustache_parse_partials_param(zval * array, mustache::Mustache * mustache, + mustache::Node::Partials * partials TSRMLS_DC) +{ + HashTable * data_hash = NULL; + ulong key_nindex = 0; + + // Ignore if not an array + if( array == NULL || Z_TYPE_P(array) != IS_ARRAY ) { + return false; + } + + data_hash = HASH_OF(array); + +#if PHP_MAJOR_VERSION < 7 + do { + HashPosition data_pointer = NULL; + zval ** data_entry = NULL; + int key_type = 0; + char * key_str = NULL; + uint key_len = 0; + + zend_hash_internal_pointer_reset_ex(data_hash, &data_pointer); + while( zend_hash_get_current_data_ex(data_hash, (void**) &data_entry, &data_pointer) == SUCCESS ) { + key_type = zend_hash_get_current_key_ex(data_hash, &key_str, &key_len, &key_nindex, false, &data_pointer); + if( key_type != HASH_KEY_IS_STRING ) { + php_error(E_WARNING, "Partial array contains a non-string key"); + } else { + mustache_parse_partial_param(key_str, *data_entry, mustache, partials); + } + zend_hash_move_forward_ex(data_hash, &data_pointer); + } + } while(0); +#else + do { + zval * data_entry = NULL; + zend_string * key = NULL; + + ZEND_HASH_FOREACH_KEY_VAL(data_hash, key_nindex, key, data_entry) { + if( !key ) { + php_error(E_WARNING, "Partial array contains a non-string key"); + } else { + mustache_parse_partial_param(key->val, data_entry, mustache, partials); + } + } ZEND_HASH_FOREACH_END(); + } while(0); +#endif +} +/* }}} */ + +/* {{{ mustache_parse_template_param */ bool mustache_parse_template_param(zval * tmpl, mustache::Mustache * mustache, mustache::Node ** node TSRMLS_DC) { @@ -193,16 +360,18 @@ bool mustache_parse_template_param(zval * tmpl, mustache::Mustache * mustache, } else if( Z_TYPE_P(tmpl) == IS_OBJECT ) { // Use compiled template if( Z_OBJCE_P(tmpl) == MustacheTemplate_ce_ptr ) { - php_obj_MustacheTemplate * mtPayload = - (php_obj_MustacheTemplate *) zend_object_store_get_object(tmpl TSRMLS_CC); + zval rv; + zval * value = _zend_read_property(Z_OBJCE_P(tmpl), tmpl, "template", sizeof("template")-1, 1, &rv); + convert_to_string(value); + std::string tmpstr(Z_STRVAL_P(value)); - if( mtPayload->tmpl == NULL ) { + if( !tmpstr.length() ) { php_error(E_WARNING, "Empty MustacheTemplate"); return false; } else { *node = new mustache::Node(); try { - mustache->tokenize(mtPayload->tmpl, *node); + mustache->tokenize(&tmpstr, *node); } catch(...) { delete *node; // Prevent leaks *node = NULL; @@ -211,8 +380,7 @@ bool mustache_parse_template_param(zval * tmpl, mustache::Mustache * mustache, } return true; } else if( Z_OBJCE_P(tmpl) == MustacheAST_ce_ptr ) { - php_obj_MustacheAST * maPayload = - (php_obj_MustacheAST *) zend_object_store_get_object(tmpl TSRMLS_CC); + struct php_obj_MustacheAST * maPayload = php_mustache_ast_object_fetch_object(tmpl TSRMLS_CC); if( maPayload->node == NULL ) { php_error(E_WARNING, "Empty MustacheAST"); return false; @@ -228,13 +396,9 @@ bool mustache_parse_template_param(zval * tmpl, mustache::Mustache * mustache, return false; } } +/* }}} */ - - -// Methods --------------------------------------------------------------------- - -/* {{{ proto void __construct() - */ +/* {{{ proto void Mustache::__construct() */ PHP_METHOD(Mustache, __construct) { try { @@ -248,17 +412,15 @@ PHP_METHOD(Mustache, __construct) // Class parameters _this_zval = getThis(); zend_class_entry * _this_ce = Z_OBJCE_P(_this_zval); - php_obj_Mustache * payload = - (php_obj_Mustache *) zend_object_store_get_object(_this_zval TSRMLS_CC); + struct php_obj_Mustache * payload = php_mustache_mustache_object_fetch_object(_this_zval TSRMLS_CC); } catch(...) { mustache_exception_handler(TSRMLS_C); } } -/* }}} __construct */ +/* }}} Mustache::__construct */ -/* {{{ proto boolean getEscapeByDefault() - */ +/* {{{ proto boolean Mustache::getEscapeByDefault() */ PHP_METHOD(Mustache, getEscapeByDefault) { try { @@ -272,8 +434,7 @@ PHP_METHOD(Mustache, getEscapeByDefault) // Class parameters _this_zval = getThis(); zend_class_entry * _this_ce = Z_OBJCE_P(_this_zval); - php_obj_Mustache * payload = - (php_obj_Mustache *) zend_object_store_get_object(_this_zval TSRMLS_CC); + struct php_obj_Mustache * payload = php_mustache_mustache_object_fetch_object(_this_zval TSRMLS_CC); // Main if( payload->mustache->getEscapeByDefault() ) { @@ -286,10 +447,9 @@ PHP_METHOD(Mustache, getEscapeByDefault) mustache_exception_handler(TSRMLS_C); } } -/* }}} getEscapeByDefault */ +/* }}} Mustache::getEscapeByDefault */ -/* {{{ proto string getStartSequence() - */ +/* {{{ proto string Mustache::getStartSequence() */ PHP_METHOD(Mustache, getStartSequence) { try { @@ -303,21 +463,19 @@ PHP_METHOD(Mustache, getStartSequence) // Class parameters _this_zval = getThis(); zend_class_entry * _this_ce = Z_OBJCE_P(_this_zval); - php_obj_Mustache * payload = - (php_obj_Mustache *) zend_object_store_get_object(_this_zval TSRMLS_CC); + struct php_obj_Mustache * payload = php_mustache_mustache_object_fetch_object(_this_zval TSRMLS_CC); // Main const std::string & str = payload->mustache->getStartSequence(); - RETURN_STRING(str.c_str(), 1); + _RETVAL_STRINGL(str.c_str(), str.length()); } catch(...) { mustache_exception_handler(TSRMLS_C); } } -/* }}} getStartSequence */ +/* }}} Mustache::getStartSequence */ -/* {{{ proto string getStopSequence() - */ +/* {{{ proto string Mustache::getStopSequence() */ PHP_METHOD(Mustache, getStopSequence) { try { @@ -331,21 +489,19 @@ PHP_METHOD(Mustache, getStopSequence) // Class parameters _this_zval = getThis(); zend_class_entry * _this_ce = Z_OBJCE_P(_this_zval); - php_obj_Mustache * payload = - (php_obj_Mustache *) zend_object_store_get_object(_this_zval TSRMLS_CC); + struct php_obj_Mustache * payload = php_mustache_mustache_object_fetch_object(_this_zval TSRMLS_CC); // Main const std::string & str = payload->mustache->getStopSequence(); - RETURN_STRING(str.c_str(), 1); + _RETVAL_STRINGL(str.c_str(), str.length()); } catch(...) { mustache_exception_handler(TSRMLS_C); } } -/* }}} getStopSequence */ +/* }}} Mustache::getStopSequence */ -/* {{{ proto boolean setStartSequence(bool flag) - */ +/* {{{ proto boolean Mustache::setStartSequence(bool flag) */ PHP_METHOD(Mustache, setEscapeByDefault) { try { @@ -362,8 +518,7 @@ PHP_METHOD(Mustache, setEscapeByDefault) // Class parameters _this_zval = getThis(); zend_class_entry * _this_ce = Z_OBJCE_P(_this_zval); - php_obj_Mustache * payload = - (php_obj_Mustache *) zend_object_store_get_object(_this_zval TSRMLS_CC); + struct php_obj_Mustache * payload = php_mustache_mustache_object_fetch_object(_this_zval TSRMLS_CC); // Main payload->mustache->setEscapeByDefault((bool) flag != 0); @@ -373,10 +528,9 @@ PHP_METHOD(Mustache, setEscapeByDefault) mustache_exception_handler(TSRMLS_C); } } -/* }}} setEscapeByDefault */ +/* }}} Mustache::setEscapeByDefault */ -/* {{{ proto boolean setStartSequence(string str) - */ +/* {{{ proto boolean Mustache::setStartSequence(string str) */ PHP_METHOD(Mustache, setStartSequence) { try { @@ -394,8 +548,7 @@ PHP_METHOD(Mustache, setStartSequence) // Class parameters _this_zval = getThis(); zend_class_entry * _this_ce = Z_OBJCE_P(_this_zval); - php_obj_Mustache * payload = - (php_obj_Mustache *) zend_object_store_get_object(_this_zval TSRMLS_CC); + struct php_obj_Mustache * payload = php_mustache_mustache_object_fetch_object(_this_zval TSRMLS_CC); // Main payload->mustache->setStartSequence(str/*, str_len*/); @@ -405,10 +558,9 @@ PHP_METHOD(Mustache, setStartSequence) mustache_exception_handler(TSRMLS_C); } } -/* }}} setStartSequence */ +/* }}} Mustache::setStartSequence */ -/* {{{ proto boolean setStopSequence(string str) - */ +/* {{{ proto boolean Mustache::setStopSequence(string str) */ PHP_METHOD(Mustache, setStopSequence) { try { @@ -426,8 +578,7 @@ PHP_METHOD(Mustache, setStopSequence) // Class parameters _this_zval = getThis(); zend_class_entry * _this_ce = Z_OBJCE_P(_this_zval); - php_obj_Mustache * payload = - (php_obj_Mustache *) zend_object_store_get_object(_this_zval TSRMLS_CC); + struct php_obj_Mustache * payload = php_mustache_mustache_object_fetch_object(_this_zval TSRMLS_CC); // Main payload->mustache->setStopSequence(str/*, str_len*/); @@ -437,11 +588,9 @@ PHP_METHOD(Mustache, setStopSequence) mustache_exception_handler(TSRMLS_C); } } -/* }}} setStartSequence */ +/* }}} Mustache::setStartSequence */ - -/* {{{ proto MustacheCode compile(string template) - */ +/* {{{ proto MustacheCode Mustache::compile(string template) */ PHP_METHOD(Mustache, compile) { try { @@ -459,8 +608,7 @@ PHP_METHOD(Mustache, compile) // Class parameters _this_zval = getThis(); zend_class_entry * _this_ce = Z_OBJCE_P(_this_zval); - php_obj_Mustache * payload = - (php_obj_Mustache *) zend_object_store_get_object(_this_zval TSRMLS_CC); + struct php_obj_Mustache * payload = php_mustache_mustache_object_fetch_object(_this_zval TSRMLS_CC); // Prepare template tree mustache::Node templateNode; @@ -481,19 +629,16 @@ PHP_METHOD(Mustache, compile) // Initialize new object object_init_ex(return_value, MustacheCode_ce_ptr); - php_obj_MustacheCode * intern = - (php_obj_MustacheCode *) zend_objects_get_address(return_value TSRMLS_CC); - intern->codes = codes; - intern->length = codes_length; + zend_update_property_stringl(MustacheCode_ce_ptr, return_value, + "binaryString", sizeof("binaryString") - 1, (char *) codes, codes_length TSRMLS_CC); } catch(...) { mustache_exception_handler(TSRMLS_C); } } -/* }}} compile */ +/* }}} Mustache::compile */ -/* {{{ proto string execute(MustacheCode code) - */ +/* {{{ proto string Mustache::execute(MustacheCode code) */ PHP_METHOD(Mustache, execute) { try { @@ -511,36 +656,36 @@ PHP_METHOD(Mustache, execute) // Class parameters _this_zval = getThis(); zend_class_entry * _this_ce = Z_OBJCE_P(_this_zval); - php_obj_Mustache * payload = - (php_obj_Mustache *) zend_object_store_get_object(_this_zval TSRMLS_CC); + struct php_obj_Mustache * payload = php_mustache_mustache_object_fetch_object(_this_zval TSRMLS_CC); // Prepare code - php_obj_MustacheCode * codePayload = - (php_obj_MustacheCode *) zend_object_store_get_object(code TSRMLS_CC); - + zval rv; + zval * value = _zend_read_property(Z_OBJCE_P(code), code, "binaryString", sizeof("binaryString")-1, 1, &rv); + if( !value || Z_TYPE_P(value) != IS_STRING ) { + throw PhpInvalidParameterException(); + } + // Prepare template data mustache::Data templateData; mustache::Data * templateDataPtr = &templateData; if( !mustache_parse_data_param(data, payload->mustache, &templateDataPtr TSRMLS_CC) ) { RETURN_FALSE; - return; } // Execute bytecode std::string output; - payload->mustache->execute(codePayload->codes, codePayload->length, templateDataPtr, &output); + payload->mustache->execute((uint8_t *) Z_STRVAL_P(value), Z_STRLEN_P(value), templateDataPtr, &output); // Output - RETURN_STRING(output.c_str(), 1); // Yes reallocate + _RETVAL_STRINGL(output.c_str(), output.length()); } catch(...) { mustache_exception_handler(TSRMLS_C); } } -/* }}} execute */ +/* }}} Mustache::execute */ -/* {{{ proto MustacheAST parse(string template) - */ +/* {{{ proto MustacheAST Mustache::parse(string template) */ PHP_METHOD(Mustache, parse) { try { @@ -557,8 +702,7 @@ PHP_METHOD(Mustache, parse) // Class parameters _this_zval = getThis(); zend_class_entry * _this_ce = Z_OBJCE_P(_this_zval); - php_obj_Mustache * payload = - (php_obj_Mustache *) zend_object_store_get_object(_this_zval TSRMLS_CC); + struct php_obj_Mustache * payload = php_mustache_mustache_object_fetch_object(_this_zval TSRMLS_CC); // Check template parameter mustache::Node * templateNodePtr = NULL; @@ -579,9 +723,7 @@ PHP_METHOD(Mustache, parse) // Initialize new object object_init_ex(return_value, MustacheAST_ce_ptr); - php_obj_MustacheAST * intern = - (php_obj_MustacheAST *) zend_objects_get_address(return_value TSRMLS_CC); - + struct php_obj_MustacheAST * intern = php_mustache_ast_object_fetch_object(return_value TSRMLS_CC); intern->node = templateNodePtr; // Ref - not sure if this is required @@ -598,10 +740,9 @@ PHP_METHOD(Mustache, parse) mustache_exception_handler(TSRMLS_C); } } -/* }}} parse */ +/* }}} Mustache::parse */ -/* {{{ proto string render(mixed template, array data, array partials) - */ +/* {{{ proto string Mustache::render(mixed template, array data, array partials) */ PHP_METHOD(Mustache, render) { try { @@ -620,8 +761,7 @@ PHP_METHOD(Mustache, render) // Class parameters _this_zval = getThis(); zend_class_entry * _this_ce = Z_OBJCE_P(_this_zval); - php_obj_Mustache * payload = - (php_obj_Mustache *) zend_object_store_get_object(_this_zval TSRMLS_CC); + struct php_obj_Mustache * payload = php_mustache_mustache_object_fetch_object(_this_zval TSRMLS_CC); // Prepare template tree mustache::Node templateNode; @@ -653,16 +793,15 @@ PHP_METHOD(Mustache, render) payload->mustache->render(templateNodePtr, templateDataPtr, &templatePartials, &output); // Output - RETURN_STRING(output.c_str(), 1); // Yes reallocate + _RETVAL_STRINGL(output.c_str(), output.length()); } catch(...) { mustache_exception_handler(TSRMLS_C); } } -/* }}} render */ +/* }}} Mustache::render */ -/* {{{ proto array tokenize(string template) - */ +/* {{{ proto array Mustache::tokenize(string template) */ PHP_METHOD(Mustache, tokenize) { try { @@ -680,8 +819,7 @@ PHP_METHOD(Mustache, tokenize) // Class parameters _this_zval = getThis(); zend_class_entry * _this_ce = Z_OBJCE_P(_this_zval); - php_obj_Mustache * payload = - (php_obj_Mustache *) zend_object_store_get_object(_this_zval TSRMLS_CC); + struct php_obj_Mustache * payload = php_mustache_mustache_object_fetch_object(_this_zval TSRMLS_CC); // Assign template to string std::string templateStr(template_str/*, template_len*/); @@ -697,10 +835,9 @@ PHP_METHOD(Mustache, tokenize) mustache_exception_handler(TSRMLS_C); } } -/* }}} tokenize */ +/* }}} Mustache::tokenize */ -/* {{{ proto array debugDataStructure(array data) - */ +/* {{{ proto array Mustache::debugDataStructure(array data) */ PHP_METHOD(Mustache, debugDataStructure) { try { @@ -717,8 +854,7 @@ PHP_METHOD(Mustache, debugDataStructure) // Class parameters _this_zval = getThis(); zend_class_entry * _this_ce = Z_OBJCE_P(_this_zval); - php_obj_Mustache * payload = - (php_obj_Mustache *) zend_object_store_get_object(_this_zval TSRMLS_CC); + struct php_obj_Mustache * payload = php_mustache_mustache_object_fetch_object(_this_zval TSRMLS_CC); // Prepare template data mustache::Data templateData; @@ -731,101 +867,5 @@ PHP_METHOD(Mustache, debugDataStructure) mustache_exception_handler(TSRMLS_C); } } -/* }}} debugDataStructure */ - - - -// Argument Info --------------------------------------------------------------- - -ZEND_BEGIN_ARG_INFO_EX(Mustache____construct_args, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 0) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(Mustache__getEscapeByDefault_args, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 0) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(Mustache__getStartSequence_args, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 0) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(Mustache__getStopSequence_args, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 0) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(Mustache__setEscapeByDefault_args, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 1) - ZEND_ARG_INFO(0, escapeByDefault) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(Mustache__setStartSequence_args, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 1) - ZEND_ARG_INFO(0, startSequence) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(Mustache__setStopSequence_args, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 1) - ZEND_ARG_INFO(0, stopSequence) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(Mustache__compile_args, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 1) - ZEND_ARG_INFO(0, tmpl) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(Mustache__execute_args, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 1) - ZEND_ARG_INFO(0, code) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(Mustache__parse_args, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 1) - ZEND_ARG_INFO(0, tmpl) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(Mustache__render_args, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 3) - ZEND_ARG_INFO(0, str) - ZEND_ARG_INFO(0, vars) - ZEND_ARG_INFO(0, partials) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(Mustache__tokenize_args, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 1) - ZEND_ARG_INFO(0, tmpl) -ZEND_END_ARG_INFO() +/* }}} Mustache::debugDataStructure */ -ZEND_BEGIN_ARG_INFO_EX(Mustache__debugDataStructure_args, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 1) - ZEND_ARG_INFO(0, vars) -ZEND_END_ARG_INFO() - - - -// Method Entries -------------------------------------------------------------- - -static zend_function_entry Mustache_methods[] = { - PHP_ME(Mustache, __construct, Mustache____construct_args, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR) - PHP_ME(Mustache, getEscapeByDefault, Mustache__getEscapeByDefault_args, ZEND_ACC_PUBLIC) - PHP_ME(Mustache, getStartSequence, Mustache__getStartSequence_args, ZEND_ACC_PUBLIC) - PHP_ME(Mustache, getStopSequence, Mustache__getStopSequence_args, ZEND_ACC_PUBLIC) - PHP_ME(Mustache, setEscapeByDefault, Mustache__setEscapeByDefault_args, ZEND_ACC_PUBLIC) - PHP_ME(Mustache, setStartSequence, Mustache__setStartSequence_args, ZEND_ACC_PUBLIC) - PHP_ME(Mustache, setStopSequence, Mustache__setStopSequence_args, ZEND_ACC_PUBLIC) - PHP_ME(Mustache, compile, Mustache__compile_args, ZEND_ACC_PUBLIC) - PHP_ME(Mustache, execute, Mustache__execute_args, ZEND_ACC_PUBLIC) - PHP_ME(Mustache, parse, Mustache__parse_args, ZEND_ACC_PUBLIC) - PHP_ME(Mustache, render, Mustache__render_args, ZEND_ACC_PUBLIC) - PHP_ME(Mustache, tokenize, Mustache__tokenize_args, ZEND_ACC_PUBLIC) - PHP_ME(Mustache, debugDataStructure, Mustache__debugDataStructure_args, ZEND_ACC_PUBLIC) - { NULL, NULL, NULL } -}; - - - -// MINIT ----------------------------------------------------------------------- - -PHP_MINIT_FUNCTION(mustache_mustache) -{ - try { - zend_class_entry ce; - - INIT_CLASS_ENTRY(ce, "Mustache", Mustache_methods); - ce.create_object = Mustache_obj_create; - Mustache_ce_ptr = zend_register_internal_class(&ce TSRMLS_CC); - memcpy(&Mustache_obj_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); - Mustache_obj_handlers.clone_obj = NULL; - - return SUCCESS; - } catch(...) { - mustache_exception_handler(TSRMLS_C); - return FAILURE; - } -} diff --git a/mustache_mustache.hpp b/mustache_mustache.hpp new file mode 100644 index 0000000..b28123d --- /dev/null +++ b/mustache_mustache.hpp @@ -0,0 +1,52 @@ + +#ifndef PHP_MUSTACHE_MUSTACHE_HPP +#define PHP_MUSTACHE_MUSTACHE_HPP + +#ifdef __cplusplus + extern "C" { +#endif + +#if PHP_MAJOR_VERSION < 7 +struct php_obj_Mustache { + zend_object std; + mustache::Mustache * mustache; +}; +#else +struct php_obj_Mustache { + mustache::Mustache * mustache; + zend_object std; +}; +#endif + +php_obj_Mustache * php_mustache_mustache_object_fetch_object(zval * zv TSRMLS_DC); + +PHP_MINIT_FUNCTION(mustache_mustache); + +void mustache_data_from_zval(mustache::Data * node, zval * current TSRMLS_DC); +bool mustache_parse_data_param(zval * data, mustache::Mustache * mustache, + mustache::Data ** node TSRMLS_DC); +bool mustache_parse_partials_param(zval * array, mustache::Mustache * mustache, + mustache::Node::Partials * partials TSRMLS_DC); +bool mustache_parse_template_param(zval * tmpl, mustache::Mustache * mustache, + mustache::Node ** node TSRMLS_DC); + +PHP_METHOD(Mustache, __construct); +PHP_METHOD(Mustache, getEscapeByDefault); +PHP_METHOD(Mustache, getStartSequence); +PHP_METHOD(Mustache, getStopSequence); +PHP_METHOD(Mustache, setEscapeByDefault); +PHP_METHOD(Mustache, setStartSequence); +PHP_METHOD(Mustache, setStopSequence); +PHP_METHOD(Mustache, compile); +PHP_METHOD(Mustache, execute); +PHP_METHOD(Mustache, parse); +PHP_METHOD(Mustache, render); +PHP_METHOD(Mustache, tokenize); +PHP_METHOD(Mustache, debugDataStructure); + +#ifdef __cplusplus + } // extern "C" +#endif + +#endif /* PHP_MUSTACHE_MUSTACHE_HPP */ + diff --git a/mustache_private.hpp b/mustache_private.hpp new file mode 100644 index 0000000..117fe69 --- /dev/null +++ b/mustache_private.hpp @@ -0,0 +1,69 @@ + +#ifndef PHP_MUSTACHE_PRIVATE_HPP +#define PHP_MUSTACHE_PRIVATE_HPP + +#ifdef __cplusplus + extern "C" { +#endif + +#include "php_mustache.h" + +#include + +#if PHP_MAJOR_VERSION >= 7 +#include +#endif + +#if PHP_MAJOR_VERSION < 7 +#define _add_next_index_string(...) add_next_index_string(__VA_ARGS__, 1) +#define _add_assoc_string(...) add_assoc_string(__VA_ARGS__, 1) +#define _add_assoc_string_ex(...) add_assoc_string_ex(__VA_ARGS__, 1) +#define _add_assoc_stringl_ex(...) add_assoc_stringl_ex(__VA_ARGS__, 1) +#define _RETURN_STRING(a) RETURN_STRING(a, 1) +#define _RETVAL_STRING(a) RETVAL_STRING(a, 1) +#define _RETVAL_STRINGL(a, b) RETVAL_STRINGL(a, b, 1) +#define _DECLARE_ZVAL(name) zval * name +#define _INIT_ZVAL INIT_ZVAL +#define _ALLOC_INIT_ZVAL(name) ALLOC_INIT_ZVAL(name) +#define _STRS ZEND_STRS +#define _zend_read_property(a, b, c, d, e, f) zend_read_property(a, b, c, d, e TSRMLS_CC) +#define _zend_register_internal_class_ex(class, parent) zend_register_internal_class_ex(class, parent, NULL TSRMLS_CC) +#define _ZVAL_STRINGL(a, b, c) ZVAL_STRINGL(a, b, c, 1) +typedef int strsize_t; +#else +#define _add_next_index_string add_next_index_string +#define _add_assoc_string(z, k, s) add_assoc_string_ex(z, k, strlen(k)+1, s) +#define _add_assoc_string_ex add_assoc_string_ex +#define _add_assoc_stringl_ex add_assoc_stringl_ex +#define _RETURN_STRING(a) RETURN_STRING(a) +#define _RETVAL_STRING(a) RETVAL_STRING(a) +#define _RETVAL_STRINGL RETVAL_STRINGL +#define _DECLARE_ZVAL(name) zval name ## _v; zval * name = &name ## _v +#define _INIT_ZVAL ZVAL_NULL +#define _ALLOC_INIT_ZVAL(name) ZVAL_NULL(name) +#define _STRS ZEND_STRL +#define _zend_read_property(a, b, c, d, e, f) zend_read_property(a, b, c, d, e, f) +#define _zend_register_internal_class_ex zend_register_internal_class_ex +#define _ZVAL_STRINGL ZVAL_STRINGL +typedef size_t strsize_t; +#endif + +#ifdef __cplusplus + } // extern "C" +#endif + +#include +#include +#include + +#include "mustache.hpp" + +#include "mustache_ast.hpp" +#include "mustache_code.hpp" +#include "mustache_data.hpp" +#include "mustache_exceptions.hpp" +#include "mustache_mustache.hpp" +#include "mustache_template.hpp" + +#endif /* PHP_MUSTACHE_PRIVATE_HPP */ + diff --git a/mustache_template.cpp b/mustache_template.cpp index 8c79a1f..c8b15b4 100644 --- a/mustache_template.cpp +++ b/mustache_template.cpp @@ -1,125 +1,37 @@ -#include "php_mustache.hpp" +#include "mustache_private.hpp" +/* {{{ ZE2 OO definitions */ +zend_class_entry * MustacheTemplate_ce_ptr; +/* }}} */ - -// Declarations ---------------------------------------------------------------- - -PHP_METHOD(MustacheTemplate, __construct); -PHP_METHOD(MustacheTemplate, __sleep); -PHP_METHOD(MustacheTemplate, __toString); -PHP_METHOD(MustacheTemplate, __wakeup); - - - -// Argument Info --------------------------------------------------------------- - +/* {{{ arginfo */ ZEND_BEGIN_ARG_INFO_EX(MustacheTemplate____construct_args, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 0) ZEND_ARG_INFO(0, vars) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_INFO_EX(MustacheTemplate____sleep_args, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 0) -ZEND_END_ARG_INFO() - ZEND_BEGIN_ARG_INFO_EX(MustacheTemplate____toString_args, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 0) ZEND_END_ARG_INFO() +/* }}} */ -ZEND_BEGIN_ARG_INFO_EX(MustacheTemplate____wakeup_args, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 0) -ZEND_END_ARG_INFO() - - - -// Class Entries --------------------------------------------------------------- - -zend_class_entry * MustacheTemplate_ce_ptr; - - - -// Method Entries -------------------------------------------------------------- - +/* {{{ MustacheTemplate_methods */ static zend_function_entry MustacheTemplate_methods[] = { PHP_ME(MustacheTemplate, __construct, MustacheTemplate____construct_args, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR) - PHP_ME(MustacheTemplate, __sleep, MustacheTemplate____sleep_args, ZEND_ACC_PUBLIC) PHP_ME(MustacheTemplate, __toString, MustacheTemplate____toString_args, ZEND_ACC_PUBLIC) - PHP_ME(MustacheTemplate, __wakeup, MustacheTemplate____wakeup_args, ZEND_ACC_PUBLIC) { NULL, NULL, NULL } }; +/* }}} */ - - -// Object Handlers ------------------------------------------------------------- - -static zend_object_handlers MustacheTemplate_obj_handlers; - -static void MustacheTemplate_obj_free(void *object TSRMLS_DC) -{ - try { - php_obj_MustacheTemplate * payload = (php_obj_MustacheTemplate *) object; - - if( payload->tmpl != NULL ) { - delete payload->tmpl; - } - - zend_object_std_dtor((zend_object *)object TSRMLS_CC); - - efree(object); - - } catch(...) { - mustache_exception_handler(TSRMLS_C); - } -} - -static zend_object_value MustacheTemplate_obj_create(zend_class_entry *class_type TSRMLS_DC) -{ - zend_object_value retval; - - try { - php_obj_MustacheTemplate * payload; - zval * tmp; - - payload = (php_obj_MustacheTemplate *) emalloc(sizeof(php_obj_MustacheTemplate)); - memset(payload, 0, sizeof(php_obj_MustacheTemplate)); - - zend_object_std_init((zend_object *) payload, class_type TSRMLS_CC); - -#if PHP_VERSION_ID < 50399 - zend_hash_copy(payload->obj.properties, &(class_type->default_properties), - (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval*)); -#else - object_properties_init(&payload->obj, class_type); -#endif - - payload->tmpl = NULL; //new std::string(); - - retval.handle = zend_objects_store_put(payload, NULL, (zend_objects_free_object_storage_t) MustacheTemplate_obj_free, NULL TSRMLS_CC); - retval.handlers = &MustacheTemplate_obj_handlers; - - } catch(...) { - mustache_exception_handler(TSRMLS_C); - } - - return retval; -} - - - -// MINIT ----------------------------------------------------------------------- - +/* {{{ PHP_MINIT_FUNCTION */ PHP_MINIT_FUNCTION(mustache_template) { try { zend_class_entry ce; - memcpy(&MustacheTemplate_obj_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); - MustacheTemplate_obj_handlers.clone_obj = NULL; - INIT_CLASS_ENTRY(ce, "MustacheTemplate", MustacheTemplate_methods); - ce.create_object = MustacheTemplate_obj_create; - MustacheTemplate_ce_ptr = zend_register_internal_class(&ce TSRMLS_CC); - MustacheTemplate_ce_ptr->create_object = MustacheTemplate_obj_create; - zend_declare_property_null(MustacheTemplate_ce_ptr, ZEND_STRL("template"), ZEND_ACC_PROTECTED TSRMLS_CC); + zend_declare_property_null(MustacheTemplate_ce_ptr, "template", sizeof("template") - 1, ZEND_ACC_PROTECTED TSRMLS_CC); return SUCCESS; } catch(...) { @@ -127,13 +39,9 @@ PHP_MINIT_FUNCTION(mustache_template) return FAILURE; } } +/* }}} */ - - -// Methods --------------------------------------------------------------------- - -/* {{{ proto void __construct(string tmpl) - */ +/* {{{ proto void MustacheTemplate::__construct(string tmpl) */ PHP_METHOD(MustacheTemplate, __construct) { try { @@ -147,63 +55,23 @@ PHP_METHOD(MustacheTemplate, __construct) &_this_zval, MustacheTemplate_ce_ptr, &template_str, &template_len) == FAILURE) { throw PhpInvalidParameterException(); } - + // Class parameters _this_zval = getThis(); - zend_class_entry * _this_ce = Z_OBJCE_P(_this_zval); - php_obj_MustacheTemplate * payload = - (php_obj_MustacheTemplate *) zend_object_store_get_object(_this_zval TSRMLS_CC); // Check if data was null if( template_len > 0 && template_str != NULL ) { - // Store template - payload->tmpl = new std::string(template_str/*, template_len*/); - } - - } catch(...) { - mustache_exception_handler(TSRMLS_C); - } -} -/* }}} __construct */ - -/* {{{ proto void __sleep() - */ -PHP_METHOD(MustacheTemplate, __sleep) -{ - try { - // Check parameters - zval * _this_zval = NULL; - if( zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), (char *) "O", - &_this_zval, MustacheTemplate_ce_ptr) == FAILURE) { - throw PhpInvalidParameterException(); - } - - // Class parameters - _this_zval = getThis(); - zend_class_entry * _this_ce = Z_OBJCE_P(_this_zval); - php_obj_MustacheTemplate * payload = - (php_obj_MustacheTemplate *) zend_object_store_get_object(_this_zval TSRMLS_CC); - - array_init(return_value); - - if( payload->tmpl != NULL ) { - // Store zend_update_property_stringl(MustacheTemplate_ce_ptr, _this_zval, - ZEND_STRL("template"), - (char *) payload->tmpl->c_str(), - payload->tmpl->length() TSRMLS_CC); - - add_next_index_string(return_value, "template", 1); + "template", sizeof("template") - 1, template_str, template_len TSRMLS_CC); } } catch(...) { mustache_exception_handler(TSRMLS_C); } } -/* }}} __sleep */ +/* }}} MustacheTemplate::__construct */ -/* {{{ proto string __toString() - */ +/* {{{ proto string MustacheTemplate::__toString() */ PHP_METHOD(MustacheTemplate, __toString) { try { @@ -216,82 +84,16 @@ PHP_METHOD(MustacheTemplate, __toString) // Class parameters _this_zval = getThis(); - zend_class_entry * _this_ce = Z_OBJCE_P(_this_zval); - php_obj_MustacheTemplate * payload = - (php_obj_MustacheTemplate *) zend_object_store_get_object(_this_zval TSRMLS_CC); - - // Check payload - if( payload->tmpl == NULL ) { - throw InvalidParameterException("MustacheTemplate was not initialized properly"); - } // Return - RETURN_STRING(payload->tmpl->c_str(), 1); // Yes reallocate + zval rv; + zval * value = _zend_read_property(Z_OBJCE_P(_this_zval), _this_zval, "template", sizeof("template")-1, 1, &rv); + convert_to_string(value); + RETURN_ZVAL(value, 1, 0); } catch(...) { mustache_exception_handler(TSRMLS_C); } } -/* }}} __toString */ - +/* }}} MustacheTemplate::__toString */ -/* {{{ proto void __wakeup() - */ -PHP_METHOD(MustacheTemplate, __wakeup) -{ - try { - // Check parameters - zval * _this_zval = NULL; - if( zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), (char *) "O", - &_this_zval, MustacheTemplate_ce_ptr) == FAILURE) { - throw PhpInvalidParameterException(); - } - - // Class parameters - _this_zval = getThis(); - zend_class_entry * _this_ce = Z_OBJCE_P(_this_zval); - php_obj_MustacheTemplate * payload = - (php_obj_MustacheTemplate *) zend_object_store_get_object(_this_zval TSRMLS_CC); - - // Get object properties - // @todo should be able to convert this to use zend_hash_find - int key_type = 0; - char * key_str = NULL; - uint key_len = 0; - ulong key_nindex = 0; - HashTable * data_hash = NULL; - HashPosition data_pointer = NULL; - zval **data_entry = NULL; - long data_count = 0; - if( Z_OBJ_HT_P(_this_zval)->get_properties != NULL ) { - data_hash = Z_OBJ_HT_P(_this_zval)->get_properties(_this_zval TSRMLS_CC); - data_count = zend_hash_num_elements(data_hash); - } - if( data_hash != NULL ) { - char *prop_name, *class_name; - zend_hash_internal_pointer_reset_ex(data_hash, &data_pointer); - while( zend_hash_get_current_data_ex(data_hash, (void**) &data_entry, &data_pointer) == SUCCESS ) { - if( zend_hash_get_current_key_ex(data_hash, &key_str, &key_len, - &key_nindex, false, &data_pointer) == HASH_KEY_IS_STRING ) { -#if PHP_API_VERSION >= 20100412 - zend_unmangle_property_name(key_str, key_len-1, (const char **) &class_name, (const char **) &prop_name); -#else - zend_unmangle_property_name(key_str, key_len-1, &class_name, &prop_name); -#endif - if( strcmp(prop_name, "template") == 0 && Z_TYPE_PP(data_entry) == IS_STRING ) { - if( payload->tmpl == NULL ) { - payload->tmpl = new std::string(Z_STRVAL_PP(data_entry)); - } else { - payload->tmpl->assign(Z_STRVAL_PP(data_entry)); - } - } - } - zend_hash_move_forward_ex(data_hash, &data_pointer); - } - } - - } catch(...) { - mustache_exception_handler(TSRMLS_C); - } -} -/* }}} __wakeup */ diff --git a/mustache_template.hpp b/mustache_template.hpp new file mode 100644 index 0000000..80a91ea --- /dev/null +++ b/mustache_template.hpp @@ -0,0 +1,21 @@ + +#ifndef PHP_MUSTACHE_TEMPLATE_HPP +#define PHP_MUSTACHE_TEMPLATE_HPP + +#ifdef __cplusplus + extern "C" { +#endif + +extern zend_class_entry * MustacheTemplate_ce_ptr; + +PHP_MINIT_FUNCTION(mustache_template); + +PHP_METHOD(MustacheTemplate, __construct); +PHP_METHOD(MustacheTemplate, __toString); + +#ifdef __cplusplus + } // extern "C" +#endif + +#endif /* PHP_MUSTACHE_TEMPLATE_HPP */ + diff --git a/php_mustache.cpp b/php_mustache.cpp index fadc23d..cd03ee0 100644 --- a/php_mustache.cpp +++ b/php_mustache.cpp @@ -1,65 +1,19 @@ -#include "php_mustache.hpp" - - - -/* {{{ Declarations --------------------------------------------------------- */ +#include "mustache_private.hpp" +/* {{{ prototypes */ ZEND_DECLARE_MODULE_GLOBALS(mustache) -static PHP_MINIT_FUNCTION(mustache); -static PHP_MSHUTDOWN_FUNCTION(mustache); -static PHP_MINFO_FUNCTION(mustache); -static PHP_GINIT_FUNCTION(mustache); - -extern zend_class_entry * MustacheData_ce_ptr; -extern zend_class_entry * MustacheException_ce_ptr; -extern zend_class_entry * MustacheParserException_ce_ptr; - -extern PHP_MINIT_FUNCTION(mustache_ast); -extern PHP_MINIT_FUNCTION(mustache_code); -extern PHP_MINIT_FUNCTION(mustache_data); -extern PHP_MINIT_FUNCTION(mustache_exceptions); -extern PHP_MINIT_FUNCTION(mustache_mustache); -extern PHP_MINIT_FUNCTION(mustache_template); - -/* }}} ---------------------------------------------------------------------- */ -/* {{{ Module Entry --------------------------------------------------------- */ - -zend_module_entry mustache_module_entry = { - STANDARD_MODULE_HEADER, - (char *) PHP_MUSTACHE_NAME, /* Name */ - NULL, /* Functions */ - PHP_MINIT(mustache), /* MINIT */ - NULL, /* MSHUTDOWN */ - NULL, /* RINIT */ - NULL, /* RSHUTDOWN */ - PHP_MINFO(mustache), /* MINFO */ - (char *) PHP_MUSTACHE_VERSION, /* Version */ - PHP_MODULE_GLOBALS(mustache), /* Globals */ - PHP_GINIT(mustache), /* GINIT */ - NULL, - NULL, - 0, 0, NULL, 0, (char *) ZEND_MODULE_BUILD_ID /* STANDARD_MODULE_PROPERTIES_EX */ -}; - -#ifdef COMPILE_DL_MUSTACHE -extern "C" { - ZEND_GET_MODULE(mustache) // Common for all PHP extensions which are build as shared modules -} -#endif - -/* }}} ---------------------------------------------------------------------- */ -/* {{{ INI Settings --------------------------------------------------------- */ +/* }}} */ +/* {{{ php.ini directive registration */ PHP_INI_BEGIN() STD_PHP_INI_BOOLEAN((char *) "mustache.default_escape", (char *) "1", PHP_INI_ALL, OnUpdateBool, default_escape_by_default, zend_mustache_globals, mustache_globals) STD_PHP_INI_ENTRY((char *) "mustache.default_start", (char *) "{{", PHP_INI_ALL, OnUpdateString, default_start_sequence, zend_mustache_globals, mustache_globals) STD_PHP_INI_ENTRY((char *) "mustache.default_stop", (char *) "}}", PHP_INI_ALL, OnUpdateString, default_stop_sequence, zend_mustache_globals, mustache_globals) PHP_INI_END() +/* }}} */ -/* }}} ---------------------------------------------------------------------- */ -/* {{{ Module Hooks --------------------------------------------------------- */ - +/* {{{ PHP_MINIT_FUNCTION */ static PHP_MINIT_FUNCTION(mustache) { REGISTER_INI_ENTRIES(); @@ -73,21 +27,18 @@ static PHP_MINIT_FUNCTION(mustache) return SUCCESS; } +/* }}} */ +/* {{{ PHP_MSHUTDOWN_FUNCTION */ static PHP_MSHUTDOWN_FUNCTION(mustache) { UNREGISTER_INI_ENTRIES(); return SUCCESS; } +/* }}} */ -static PHP_GINIT_FUNCTION(mustache) -{ - mustache_globals->default_escape_by_default = 1; - mustache_globals->default_start_sequence = (char *) "{{"; - mustache_globals->default_stop_sequence = (char *) "}}"; -} - +/* {{{ PHP_MINFO_FUNCTION */ static PHP_MINFO_FUNCTION(mustache) { char opsize[3]; @@ -110,41 +61,39 @@ static PHP_MINFO_FUNCTION(mustache) DISPLAY_INI_ENTRIES(); } +/* }}} */ -/* }}} ---------------------------------------------------------------------- */ -/* {{{ Utils ---------------------------------------------------------------- */ - -void mustache_exception_handler(TSRMLS_D) +/* {{{ PHP_GINIT_FUNCTION */ +static PHP_GINIT_FUNCTION(mustache) { -#if PHP_MUSTACHE_THROW_EXCEPTIONS - throw; -#else - try { - throw; - } catch( mustache::TokenizerException& e ) { - zval * exception = zend_throw_exception_ex(MustacheParserException_ce_ptr, - 0 TSRMLS_CC, (char *) e.what(), "MustacheParserException"); - zend_update_property_long(MustacheParserException_ce_ptr, exception, - (char *) "templateLineNo", strlen("templateLineNo"), e.lineNo TSRMLS_CC); - zend_update_property_long(MustacheParserException_ce_ptr, exception, - (char *) "templateCharNo", strlen("templateCharNo"), e.charNo TSRMLS_CC); - } catch( mustache::Exception& e ) { - zend_throw_exception_ex(MustacheException_ce_ptr, 0 TSRMLS_CC, - (char *) e.what(), "MustacheException"); - //php_error_docref(NULL TSRMLS_CC, E_WARNING, e.what()); - } catch( InvalidParameterException& e ) { - // @todo change this to an exception - php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", e.what()); - } catch( PhpInvalidParameterException& e ) { - // The error message should be handled by PHP - } catch( std::bad_alloc& e ) { - php_error_docref(NULL TSRMLS_CC, E_ERROR, "%s", "Memory allocation failed."); - } catch( std::runtime_error& e ) { - php_error_docref(NULL TSRMLS_CC, E_ERROR, "%s", e.what()); - } catch(...) { - php_error_docref(NULL TSRMLS_CC, E_ERROR, "%s", "An unknown error has occurred."); - } -#endif + mustache_globals->default_escape_by_default = 1; + mustache_globals->default_start_sequence = (char *) "{{"; + mustache_globals->default_stop_sequence = (char *) "}}"; } +/* }}} */ + +/* {{{ mustache_module_entry */ +zend_module_entry mustache_module_entry = { + STANDARD_MODULE_HEADER, + (char *) PHP_MUSTACHE_NAME, /* Name */ + NULL, /* Functions */ + PHP_MINIT(mustache), /* MINIT */ + NULL, /* MSHUTDOWN */ + NULL, /* RINIT */ + NULL, /* RSHUTDOWN */ + PHP_MINFO(mustache), /* MINFO */ + (char *) PHP_MUSTACHE_VERSION, /* Version */ + PHP_MODULE_GLOBALS(mustache), /* Globals */ + PHP_GINIT(mustache), /* GINIT */ + NULL, + NULL, + 0, 0, NULL, 0, (char *) ZEND_MODULE_BUILD_ID /* STANDARD_MODULE_PROPERTIES_EX */ +}; +/* }}} */ + +#ifdef COMPILE_DL_MUSTACHE +extern "C" { + ZEND_GET_MODULE(mustache) // Common for all PHP extensions which are build as shared modules +} +#endif -/* }}} ---------------------------------------------------------------------- */ diff --git a/php_mustache.h b/php_mustache.h index 4a3cda3..5393145 100644 --- a/php_mustache.h +++ b/php_mustache.h @@ -53,8 +53,10 @@ ZEND_END_MODULE_GLOBALS(mustache) ZEND_EXTERN_MODULE_GLOBALS(mustache); + #ifdef __cplusplus } // extern "C" #endif #endif /* PHP_MUSTACHE_H */ + diff --git a/php_mustache.hpp b/php_mustache.hpp index 8720599..e69de29 100644 --- a/php_mustache.hpp +++ b/php_mustache.hpp @@ -1,61 +0,0 @@ - -#ifndef PHP_MUSTACHE_HPP -#define PHP_MUSTACHE_HPP - -#include "php_mustache.h" - -#include -#include -#include -#include - -#include "mustache.hpp" - -// Parameter exception -class PhpInvalidParameterException : public std::exception { - public: -}; -class InvalidParameterException : public std::runtime_error { - public: - InvalidParameterException(const std::string& desc) : std::runtime_error(desc) { } -}; - -// Utils - -#ifdef __cplusplus - extern "C" { -#endif - -typedef struct _php_obj_Mustache { - zend_object obj; - mustache::Mustache * mustache; -} php_obj_Mustache; - -typedef struct _php_obj_MustacheAST { - zend_object obj; - mustache::Node * node; -} php_obj_MustacheAST; - -typedef struct _php_obj_MustacheCode { - zend_object obj; - uint8_t * codes; - size_t length; -} php_obj_MustacheCode; - -typedef struct _php_obj_MustacheData { - zend_object obj; - mustache::Data * data; -} php_obj_MustacheData; - -typedef struct _php_obj_MustacheTemplate { - zend_object obj; - std::string * tmpl; -} php_obj_MustacheTemplate; - -void mustache_exception_handler(TSRMLS_D); - -#ifdef __cplusplus - } // extern "C" -#endif - -#endif /* PHP_MUSTACHE_HPP */ diff --git a/test_mem.sh b/test_mem.sh new file mode 100755 index 0000000..03e5cc8 --- /dev/null +++ b/test_mem.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +# sed really doesn't like me +php -r 'file_put_contents("run-tests.php", str_replace("([0-9])", "([0-9]+)", file_get_contents("run-tests.php")));' +TEST_PHP_ARGS=-m make test $@ From eb70535515ad8e2e44234e8141a3ef55dfd64ec3 Mon Sep 17 00:00:00 2001 From: John Boehr Date: Wed, 22 Jul 2015 23:35:26 -0700 Subject: [PATCH 2/7] Fix compile error on PHP 5 --- mustache_mustache.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mustache_mustache.cpp b/mustache_mustache.cpp index 55f09bb..87578e5 100644 --- a/mustache_mustache.cpp +++ b/mustache_mustache.cpp @@ -316,7 +316,7 @@ bool mustache_parse_partials_param(zval * array, mustache::Mustache * mustache, if( key_type != HASH_KEY_IS_STRING ) { php_error(E_WARNING, "Partial array contains a non-string key"); } else { - mustache_parse_partial_param(key_str, *data_entry, mustache, partials); + mustache_parse_partial_param(key_str, *data_entry, mustache, partials TSRMLS_CC); } zend_hash_move_forward_ex(data_hash, &data_pointer); } @@ -330,7 +330,7 @@ bool mustache_parse_partials_param(zval * array, mustache::Mustache * mustache, if( !key ) { php_error(E_WARNING, "Partial array contains a non-string key"); } else { - mustache_parse_partial_param(key->val, data_entry, mustache, partials); + mustache_parse_partial_param(key->val, data_entry, mustache, partials TSRMLS_CC); } } ZEND_HASH_FOREACH_END(); } while(0); From ee0435e3be1978e492fedfcc3d6912b5f1a2b924 Mon Sep 17 00:00:00 2001 From: John Boehr Date: Wed, 22 Jul 2015 23:35:51 -0700 Subject: [PATCH 3/7] Add PHP 7 to TravisCI configuration --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index c8c6663..248101f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,6 +5,7 @@ php: - 5.4 - 5.5 - 5.6 + - 7.0 branches: only: From c118b81824b60d323835fc304f0425570755f34c Mon Sep 17 00:00:00 2001 From: John Boehr Date: Thu, 23 Jul 2015 12:30:06 -0700 Subject: [PATCH 4/7] Fix compile error on PHP5 ZTS --- mustache_data.cpp | 6 ++++-- mustache_exceptions.cpp | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/mustache_data.cpp b/mustache_data.cpp index 4e3f903..464c7da 100644 --- a/mustache_data.cpp +++ b/mustache_data.cpp @@ -364,9 +364,11 @@ static zend_always_inline void mustache_data_from_object_zval(mustache::Data * n /* {{{ mustache_data_from_zval */ void mustache_data_from_zval(mustache::Data * node, zval * current TSRMLS_DC) { +#if PHP_MAJOR_VERSION >= 7 if (Z_TYPE_P(current) == IS_INDIRECT) { current = Z_INDIRECT_P(current); } +#endif switch( Z_TYPE_P(current) ) { case IS_NULL: case IS_LONG: @@ -383,10 +385,10 @@ void mustache_data_from_zval(mustache::Data * node, zval * current TSRMLS_DC) node->val = new std::string(Z_STRVAL_P(current)/*, (size_t) Z_STRLEN_P(current)*/); break; case IS_ARRAY: - mustache_data_from_array_zval(node, current); + mustache_data_from_array_zval(node, current TSRMLS_CC); break; case IS_OBJECT: - mustache_data_from_object_zval(node, current); + mustache_data_from_object_zval(node, current TSRMLS_CC); break; default: php_error(E_WARNING, "Invalid data type: %d", Z_TYPE_P(current)); diff --git a/mustache_exceptions.cpp b/mustache_exceptions.cpp index bee0e69..4744312 100644 --- a/mustache_exceptions.cpp +++ b/mustache_exceptions.cpp @@ -15,13 +15,13 @@ PHP_MINIT_FUNCTION(mustache_exceptions) // MustacheException zend_class_entry mustache_exception_ce; INIT_CLASS_ENTRY(mustache_exception_ce, "MustacheException", NULL); - MustacheException_ce_ptr = _zend_register_internal_class_ex(&mustache_exception_ce, exception_ce TSRMLS_CC); + MustacheException_ce_ptr = _zend_register_internal_class_ex(&mustache_exception_ce, exception_ce); MustacheException_ce_ptr->create_object = exception_ce->create_object; // MustacheParserException zend_class_entry mustache_parser_exception_ce; INIT_CLASS_ENTRY(mustache_parser_exception_ce, "MustacheParserException", NULL); - MustacheParserException_ce_ptr = _zend_register_internal_class_ex(&mustache_parser_exception_ce, MustacheException_ce_ptr TSRMLS_CC); + MustacheParserException_ce_ptr = _zend_register_internal_class_ex(&mustache_parser_exception_ce, MustacheException_ce_ptr); MustacheParserException_ce_ptr->create_object = MustacheException_ce_ptr->create_object; return SUCCESS; From 20971b30db75400511258f87535cef41fc208921 Mon Sep 17 00:00:00 2001 From: John Boehr Date: Thu, 23 Jul 2015 12:38:55 -0700 Subject: [PATCH 5/7] Add no interaction to make test --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 248101f..bda1be1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -22,5 +22,5 @@ script: - phpize - ./configure --enable-mustache - make - - echo n | make test + - make test NO_INTERACTION=1 From d6a0272b276ccef96827df99a28af456d5355eb2 Mon Sep 17 00:00:00 2001 From: John Boehr Date: Mon, 27 Jul 2015 12:16:40 -0700 Subject: [PATCH 6/7] Try to fix issue with INT64_mAX --- php_mustache.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/php_mustache.h b/php_mustache.h index 5393145..0bb052c 100644 --- a/php_mustache.h +++ b/php_mustache.h @@ -17,6 +17,10 @@ #define PHP_MUSTACHE_THROW_EXCEPTIONS 0 #endif +#ifndef __STDC_LIMIT_MACROS +#define __STDC_LIMIT_MACROS +#endif + #ifdef HAVE_CONFIG_H #include "config.h" #endif From 71a41bf75e35d0e8fcd55b9d54dcbd768bb41f2e Mon Sep 17 00:00:00 2001 From: John Boehr Date: Wed, 19 Aug 2015 00:11:26 -0700 Subject: [PATCH 7/7] Update .travis.yml --- .travis.yml | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index bda1be1..5567106 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,17 +10,28 @@ php: branches: only: - master + - php7 + +sudo: false before_install: - - git submodule update --init --recursive - - git clone git://github.com/jbboehr/libmustache.git libmustache + - travis_retry git submodule update --init --recursive + - travis_retry git clone git://github.com/jbboehr/libmustache.git libmustache - cd libmustache - - autoreconf -i && ./configure && make && sudo make install + - autoreconf -fiv + - ./configure --prefix=$HOME/libmustache + - make + - make install - cd .. -script: +install: - phpize - - ./configure --enable-mustache + - ./configure --enable-mustache --with-libmustache=$HOME/libmustache - make - - make test NO_INTERACTION=1 +script: + - export NO_INTERACTION=1 + - export REPORT_EXIT_STATUS=1 + - export TEST_PHP_EXECUTABLE=`which php` + - php run-tests.php -d extension=mustache.so -d extension_dir=modules -n ./tests/*.phpt + - for i in `ls tests/*.out 2>/dev/null`; do echo "-- START ${i}"; cat $i; echo "-- END"; done