Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Faster Phalcon\Translate implementation using object handlers #1668

Merged
merged 3 commits into from Dec 11, 2013
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Faster Phalcon\Translate implementation
  • Loading branch information
sjinks committed Dec 11, 2013
commit 9241407d95df6e123ead37e3bb840b1896adccbd
118 changes: 84 additions & 34 deletions ext/translate/adapter.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,18 +42,85 @@
*/


PHALCON_STATIC zend_object_handlers phalcon_translate_adapter_object_handlers;

static zval* phalcon_translate_adapter_read_dimension(zval *object, zval *offset, int type TSRMLS_DC)
{
zval *ret = NULL;

if (Z_OBJCE_P(object)->type != ZEND_INTERNAL_CLASS) {
return zend_get_std_object_handlers()->read_dimension(object, offset, type TSRMLS_CC);
}

phalcon_call_method_params(ret, &ret, object, SL("query"), zend_inline_hash_func(SS("query")) TSRMLS_CC, 2, offset, PHALCON_GLOBAL(z_null));
return UNEXPECTED(EG(exception) != NULL) ? NULL : ret;
}

static void phalcon_translate_adapter_write_dimension(zval *object, zval *offset, zval *value TSRMLS_DC)
{
if (Z_OBJCE_P(object)->type != ZEND_INTERNAL_CLASS) {
zend_get_std_object_handlers()->write_dimension(object, offset, value TSRMLS_CC);
return;
}

zend_throw_exception_ex(phalcon_translate_exception_ce, 0 TSRMLS_CC, "'%s' is an immutable ArrayAccess object", "Phalcon\\Translate\\Adapter");
}

static int phalcon_translate_adapter_has_dimension(zval *object, zval *offset, int check_empty TSRMLS_DC)
{
zval *exists = NULL;
int retval;

if (Z_OBJCE_P(object)->type != ZEND_INTERNAL_CLASS) {
return zend_get_std_object_handlers()->has_dimension(object, offset, check_empty TSRMLS_CC);
}

phalcon_call_method_params(exists, &exists, object, SL("exists"), zend_inline_hash_func(SS("exists")) TSRMLS_CC, 1, offset);
if (UNEXPECTED(EG(exception) != NULL)) {
return 0;
}

retval = zend_is_true(exists);
zval_ptr_dtor(&exists);
return retval;
}

static void phalcon_translate_adapter_unset_dimension(zval *object, zval *offset TSRMLS_DC)
{
if (Z_OBJCE_P(object)->type != ZEND_INTERNAL_CLASS) {
zend_get_std_object_handlers()->unset_dimension(object, offset TSRMLS_CC);
return;
}

zend_throw_exception_ex(phalcon_translate_exception_ce, 0 TSRMLS_CC, "'%s' is an immutable ArrayAccess object", "Phalcon\\Translate\\Adapter");
}


/**
* Phalcon\Translate\Adapter initializer
*/
PHALCON_INIT_CLASS(Phalcon_Translate_Adapter){

PHALCON_REGISTER_CLASS(Phalcon\\Translate, Adapter, translate_adapter, phalcon_translate_adapter_method_entry, ZEND_ACC_EXPLICIT_ABSTRACT_CLASS);

phalcon_translate_adapter_object_handlers = *zend_get_std_object_handlers();
phalcon_translate_adapter_object_handlers.read_dimension = phalcon_translate_adapter_read_dimension;
phalcon_translate_adapter_object_handlers.write_dimension = phalcon_translate_adapter_write_dimension;
phalcon_translate_adapter_object_handlers.has_dimension = phalcon_translate_adapter_has_dimension;
phalcon_translate_adapter_object_handlers.unset_dimension = phalcon_translate_adapter_unset_dimension;

zend_class_implements(phalcon_translate_adapter_ce TSRMLS_CC, 1, zend_ce_arrayaccess);

return SUCCESS;
}

/**
* Class constructore
*/
PHP_METHOD(Phalcon_Translate_Adapter, __construct)
{
Z_OBJ_HT_P(getThis()) = &phalcon_translate_adapter_object_handlers;
}
/**
* Returns the translation string of the given key
*
Expand All @@ -65,16 +132,16 @@ PHP_METHOD(Phalcon_Translate_Adapter, _){

zval *translate_key, *placeholders = NULL;

PHALCON_MM_GROW();
phalcon_fetch_params(0, 1, 1, &translate_key, &placeholders);

phalcon_fetch_params(1, 1, 1, &translate_key, &placeholders);

if (!placeholders) {
placeholders = PHALCON_GLOBAL(z_null);
}

phalcon_call_method_p2(return_value, this_ptr, "query", translate_key, placeholders);
RETURN_MM();

phalcon_call_method_params(return_value, return_value_ptr, this_ptr, SL("query"), zend_inline_hash_func(SS("query")) TSRMLS_CC, 2, translate_key, placeholders);
if (return_value_ptr && EG(exception)) {
ALLOC_INIT_ZVAL(*return_value_ptr);
}
}

/**
Expand All @@ -85,12 +152,7 @@ PHP_METHOD(Phalcon_Translate_Adapter, _){
*/
PHP_METHOD(Phalcon_Translate_Adapter, offsetSet){

zval *offset, *value;

phalcon_fetch_params(0, 2, 0, &offset, &value);

PHALCON_THROW_EXCEPTION_STRW(phalcon_translate_exception_ce, "Translate is an immutable ArrayAccess object");
return;
zend_throw_exception_ex(phalcon_translate_exception_ce, 0 TSRMLS_CC, "'%s' is an immutable ArrayAccess object", "Phalcon\\Translate\\Adapter");
}

/**
Expand All @@ -101,14 +163,12 @@ PHP_METHOD(Phalcon_Translate_Adapter, offsetSet){
*/
PHP_METHOD(Phalcon_Translate_Adapter, offsetExists){

zval *translate_key;
zval **translate_key;
int exists;

PHALCON_MM_GROW();

phalcon_fetch_params(1, 1, 0, &translate_key);

phalcon_call_method_p1(return_value, this_ptr, "exists", translate_key);
RETURN_MM();
phalcon_fetch_params_ex(1, 0, &translate_key);
exists = phalcon_translate_adapter_has_dimension(getThis(), *translate_key, 1 TSRMLS_CC);
RETURN_BOOL(exists);
}

/**
Expand All @@ -118,12 +178,7 @@ PHP_METHOD(Phalcon_Translate_Adapter, offsetExists){
*/
PHP_METHOD(Phalcon_Translate_Adapter, offsetUnset){

zval *offset;

phalcon_fetch_params(0, 1, 0, &offset);

PHALCON_THROW_EXCEPTION_STRW(phalcon_translate_exception_ce, "Translate is an immutable ArrayAccess object");
return;
zend_throw_exception_ex(phalcon_translate_exception_ce, 0 TSRMLS_CC, "'%s' is an immutable ArrayAccess object", "Phalcon\\Translate\\Adapter");
}

/**
Expand All @@ -134,14 +189,9 @@ PHP_METHOD(Phalcon_Translate_Adapter, offsetUnset){
*/
PHP_METHOD(Phalcon_Translate_Adapter, offsetGet){

zval *translate_key, *null_value;
zval **translate_key, *res;

PHALCON_MM_GROW();

phalcon_fetch_params(1, 1, 0, &translate_key);

PHALCON_INIT_VAR(null_value);
phalcon_call_method_p2(return_value, this_ptr, "query", translate_key, null_value);
RETURN_MM();
phalcon_fetch_params_ex(1, 0, &translate_key);
res = phalcon_translate_adapter_read_dimension(getThis(), *translate_key, BP_VAR_R TSRMLS_CC);
RETURN_ZVAL(res, 1, 0);
}

3 changes: 3 additions & 0 deletions ext/translate/adapter.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,11 @@
*/

extern zend_class_entry *phalcon_translate_adapter_ce;
zend_object_handlers phalcon_translate_adapter_object_handlers;

PHALCON_INIT_CLASS(Phalcon_Translate_Adapter);

PHP_METHOD(Phalcon_Translate_Adapter, __construct);
PHP_METHOD(Phalcon_Translate_Adapter, _);
PHP_METHOD(Phalcon_Translate_Adapter, offsetSet);
PHP_METHOD(Phalcon_Translate_Adapter, offsetExists);
Expand Down Expand Up @@ -50,6 +52,7 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_phalcon_translate_adapter_offsetget, 0, 0, 1)
ZEND_END_ARG_INFO()

PHALCON_INIT_FUNCS(phalcon_translate_adapter_method_entry){
PHP_ME(Phalcon_Translate_Adapter, __construct, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR)
PHP_ME(Phalcon_Translate_Adapter, _, arginfo_phalcon_translate_adapter__, ZEND_ACC_PUBLIC)
PHP_ME(Phalcon_Translate_Adapter, offsetSet, arginfo_phalcon_translate_adapter_offsetset, ZEND_ACC_PUBLIC)
PHP_ME(Phalcon_Translate_Adapter, offsetExists, arginfo_phalcon_translate_adapter_offsetexists, ZEND_ACC_PUBLIC)
Expand Down
139 changes: 79 additions & 60 deletions ext/translate/adapter/nativearray.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,40 @@
*
*/

static zend_object_handlers phalcon_translate_adapter_nativearray_object_handlers;

static zval* phalcon_translate_adapter_nativearray_read_dimension(zval *object, zval *offset, int type TSRMLS_DC)
{
zval *translate, *translation;

if (Z_OBJCE_P(object)->type != ZEND_INTERNAL_CLASS) {
return zend_get_std_object_handlers()->read_dimension(object, offset, type TSRMLS_CC);
}

translate = phalcon_fetch_nproperty_this(object, SL("_translate"), PH_NOISY_CC);
if (phalcon_array_isset_fetch(&translation, translate, offset)) {
return translation;
}

return offset;
}

static int phalcon_translate_adapter_nativearray_has_dimension(zval *object, zval *offset, int check_empty TSRMLS_DC)
{
zval *translate, *translation;

if (Z_OBJCE_P(object)->type != ZEND_INTERNAL_CLASS) {
return zend_get_std_object_handlers()->has_dimension(object, offset, check_empty TSRMLS_CC);
}

translate = phalcon_fetch_nproperty_this(object, SL("_translate"), PH_NOISY_CC);
if (!phalcon_array_isset_fetch(&translation, translate, offset)) {
return 0;
}

return (1 == check_empty) ? zend_is_true(translation) : 1;
}


/**
* Phalcon\Translate\Adapter\NativeArray initializer
Expand All @@ -60,6 +94,10 @@ PHALCON_INIT_CLASS(Phalcon_Translate_Adapter_NativeArray){

zend_class_implements(phalcon_translate_adapter_nativearray_ce TSRMLS_CC, 1, phalcon_translate_adapterinterface_ce);

phalcon_translate_adapter_nativearray_object_handlers = phalcon_translate_adapter_object_handlers;
phalcon_translate_adapter_nativearray_object_handlers.read_dimension = phalcon_translate_adapter_nativearray_read_dimension;
phalcon_translate_adapter_nativearray_object_handlers.has_dimension = phalcon_translate_adapter_nativearray_has_dimension;

return SUCCESS;
}

Expand All @@ -72,29 +110,26 @@ PHP_METHOD(Phalcon_Translate_Adapter_NativeArray, __construct){

zval *options, *data;

PHALCON_MM_GROW();

phalcon_fetch_params(1, 1, 0, &options);
phalcon_fetch_params(0, 1, 0, &options);

if (Z_TYPE_P(options) != IS_ARRAY) {
PHALCON_THROW_EXCEPTION_STR(phalcon_translate_exception_ce, "Invalid options");
PHALCON_THROW_EXCEPTION_STRW(phalcon_translate_exception_ce, "Invalid options");
return;
}
if (!phalcon_array_isset_string(options, SS("content"))) {
PHALCON_THROW_EXCEPTION_STR(phalcon_translate_exception_ce, "Translation content was not provided");

if (!phalcon_array_isset_string_fetch(&data, options, SS("content"))) {
PHALCON_THROW_EXCEPTION_STRW(phalcon_translate_exception_ce, "Translation content was not provided");
return;
}

PHALCON_OBS_VAR(data);
phalcon_array_fetch_string(&data, options, SL("content"), PH_NOISY);

if (Z_TYPE_P(data) != IS_ARRAY) {
PHALCON_THROW_EXCEPTION_STR(phalcon_translate_exception_ce, "Translation data must be an array");
PHALCON_THROW_EXCEPTION_STRW(phalcon_translate_exception_ce, "Translation data must be an array");
return;
}

phalcon_update_property_this(this_ptr, SL("_translate"), data TSRMLS_CC);
PHALCON_MM_RESTORE();

Z_OBJ_HT_P(getThis()) = &phalcon_translate_adapter_nativearray_object_handlers;
}

/**
Expand All @@ -107,52 +142,47 @@ PHP_METHOD(Phalcon_Translate_Adapter_NativeArray, __construct){
PHP_METHOD(Phalcon_Translate_Adapter_NativeArray, query){

zval *index, *placeholders = NULL, *translate, *translation = NULL;
zval *value = NULL, *key = NULL, *key_placeholder = NULL, *replaced = NULL;
HashTable *ah0;
zval *key_placeholder, *replaced;
HashPosition hp0;
zval **hd;

PHALCON_MM_GROW();
zval **value;

phalcon_fetch_params(1, 1, 1, &index, &placeholders);
phalcon_fetch_params(0, 1, 1, &index, &placeholders);

if (!placeholders) {
placeholders = PHALCON_GLOBAL(z_null);
}

PHALCON_OBS_VAR(translate);
phalcon_read_property_this(&translate, this_ptr, SL("_translate"), PH_NOISY_CC);
if (phalcon_array_isset(translate, index)) {

PHALCON_OBS_VAR(translation);
phalcon_array_fetch(&translation, translate, index, PH_NOISY);
if (Z_TYPE_P(placeholders) == IS_ARRAY) {
if (phalcon_fast_count_ev(placeholders TSRMLS_CC)) {

phalcon_is_iterable(placeholders, &ah0, &hp0, 0, 0);

while (zend_hash_get_current_data_ex(ah0, (void**) &hd, &hp0) == SUCCESS) {

PHALCON_GET_HKEY(key, ah0, hp0);
PHALCON_GET_HVALUE(value);

PHALCON_INIT_NVAR(key_placeholder);
PHALCON_CONCAT_SVS(key_placeholder, "%", key, "%");

PHALCON_INIT_NVAR(replaced);
phalcon_fast_str_replace(replaced, key_placeholder, value, translation);
PHALCON_CPY_WRT(translation, replaced);

zend_hash_move_forward_ex(ah0, &hp0);
}

translate = phalcon_fetch_nproperty_this(this_ptr, SL("_translate"), PH_NOISY_CC);
if (phalcon_array_isset_fetch(&translation, translate, index)) {
if (Z_TYPE_P(placeholders) == IS_ARRAY && zend_hash_num_elements(Z_ARRVAL_P(placeholders))) {

ALLOC_INIT_ZVAL(key_placeholder);

for (
zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(placeholders), &hp0);
zend_hash_get_current_data_ex(Z_ARRVAL_P(placeholders), (void**)&value, &hp0) == SUCCESS;
zend_hash_move_forward_ex(Z_ARRVAL_P(placeholders), &hp0)
) {
zval key = phalcon_get_current_key_w(Z_ARRVAL_P(placeholders), &hp0);

PHALCON_CONCAT_SVS(key_placeholder, "%", &key, "%");

ALLOC_INIT_ZVAL(replaced);
phalcon_fast_str_replace(replaced, key_placeholder, *value, translation);
zval_dtor(key_placeholder);

translation = replaced;
}

ZVAL_NULL(key_placeholder);
zval_ptr_dtor(&key_placeholder);
RETURN_ZVAL(translation, 1, 1);
}

RETURN_CTOR(translation);
RETURN_ZVAL(translation, 1, 0);
}

RETURN_CTOR(index);
RETURN_ZVAL(index, 1, 0);
}

/**
Expand All @@ -163,19 +193,8 @@ PHP_METHOD(Phalcon_Translate_Adapter_NativeArray, query){
*/
PHP_METHOD(Phalcon_Translate_Adapter_NativeArray, exists){

zval *index, *translate, *exists = NULL;
zval *r0 = NULL;

PHALCON_MM_GROW();
zval **index;

phalcon_fetch_params(1, 1, 0, &index);

PHALCON_OBS_VAR(translate);
phalcon_read_property_this(&translate, this_ptr, SL("_translate"), PH_NOISY_CC);

PHALCON_INIT_VAR(r0);
ZVAL_BOOL(r0, phalcon_array_isset(translate, index));
PHALCON_CPY_WRT(exists, r0);
RETURN_NCTOR(exists);
phalcon_fetch_params_ex(1, 0, &index);
RETURN_BOOL(phalcon_translate_adapter_nativearray_has_dimension(getThis(), *index, 0 TSRMLS_CC));
}