From 472ce2ad11a918bb5ac8246e62adf4bc1f24f54c Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Sat, 11 May 2013 13:32:11 +0800 Subject: [PATCH] Support multi-inheritance in ini configs --- configs/yaf_config_ini.c | 182 ++++++++++++++++++++++++++------------- tests/067.phpt | 63 ++++++++++++++ tests/multi-section.ini | 11 +++ 3 files changed, 196 insertions(+), 60 deletions(-) create mode 100644 tests/067.phpt create mode 100644 tests/multi-section.ini diff --git a/configs/yaf_config_ini.c b/configs/yaf_config_ini.c index 75e237c7..f3151c50 100644 --- a/configs/yaf_config_ini.c +++ b/configs/yaf_config_ini.c @@ -69,28 +69,60 @@ ZEND_BEGIN_ARG_INFO_EX(yaf_config_ini_isset_arginfo, 0, 0, 1) ZEND_END_ARG_INFO() /* }}} */ -/* {{{ static void yaf_config_ini_zval_deep_copy(zval **p) +/** {{{ static inline php_yaf_deep_copy_section(zval *dst, zval *src TSRMLS_DC) */ -static void yaf_config_ini_zval_deep_copy(zval **p) { - zval *value; - ALLOC_ZVAL(value); - *value = **p; +static inline php_yaf_deep_copy_section(zval *dst, zval *src TSRMLS_DC) { + zval **ppzval, **dstppzval, *value; + HashTable *ht; + ulong idx; + char *key; + uint key_len; + + ht = Z_ARRVAL_P(src); + for(zend_hash_internal_pointer_reset(ht); + zend_hash_has_more_elements(ht) == SUCCESS; + zend_hash_move_forward(ht)) { + if (zend_hash_get_current_data(ht, (void **)&ppzval) == FAILURE) { + continue; + } - switch (Z_TYPE_PP(p)) { - case IS_ARRAY: - { - array_init(value); - zend_hash_copy(Z_ARRVAL_P(value), Z_ARRVAL_PP(p), - (copy_ctor_func_t)yaf_config_ini_zval_deep_copy, NULL, sizeof(zval *)); - } - break; - default: - zval_copy_ctor(value); - Z_TYPE_P(value) = Z_TYPE_PP(p); + switch (zend_hash_get_current_key_ex(ht, &key, &key_len, &idx, 0, NULL)) { + case HASH_KEY_IS_STRING: + if (Z_TYPE_PP(ppzval) == IS_ARRAY + && zend_hash_find(Z_ARRVAL_P(dst), key, key_len, (void **)&dstppzval) == SUCCESS + && Z_TYPE_PP(dstppzval) == IS_ARRAY) { + MAKE_STD_ZVAL(value); + array_init(value); + php_yaf_deep_copy_section(value, *dstppzval); + php_yaf_deep_copy_section(value, *ppzval); + } else { + ALLOC_ZVAL(value); + *value = **ppzval; + zval_copy_ctor(value); + INIT_PZVAL(value); + } + zend_hash_update(Z_ARRVAL_P(dst), key, key_len, (void *)&value, sizeof(zval *), NULL); + break; + case HASH_KEY_IS_LONG: + if (Z_TYPE_PP(ppzval) == IS_ARRAY + && zend_hash_index_find(Z_ARRVAL_P(dst), idx, (void **)&dstppzval) == SUCCESS + && Z_TYPE_PP(dstppzval) == IS_ARRAY) { + MAKE_STD_ZVAL(value); + array_init(value); + php_yaf_deep_copy_section(value, *dstppzval); + php_yaf_deep_copy_section(value, *ppzval); + } else { + ALLOC_ZVAL(value); + *value = **ppzval; + zval_copy_ctor(value); + INIT_PZVAL(value); + } + zend_hash_index_update(Z_ARRVAL_P(dst), idx, (void *)&value, sizeof(zval *), NULL); + break; + case HASH_KEY_NON_EXISTANT: + break; + } } - - INIT_PZVAL(value); - *p = value; } /* }}} */ @@ -140,6 +172,7 @@ static void yaf_config_ini_simple_parser_cb(zval *key, zval *value, zval *index, break; } } else { + SEPARATE_ZVAL(ppzval); if (IS_ARRAY != Z_TYPE_PP(ppzval)) { if (seg) { zval *tmp; @@ -242,7 +275,7 @@ static void yaf_config_ini_parser_cb(zval *key, zval *value, zval *index, int ca if (callback_type == ZEND_INI_PARSER_SECTION) { zval **parent; - char *seg, *skey; + char *seg, *skey, *skey_orig; uint skey_len; if (YAF_G(parsing_flag) == YAF_CONFIG_INI_PARSING_PROCESS) { @@ -250,13 +283,32 @@ static void yaf_config_ini_parser_cb(zval *key, zval *value, zval *index, int ca return; } - skey = estrndup(Z_STRVAL_P(key), Z_STRLEN_P(key)); + skey_orig = skey = estrndup(Z_STRVAL_P(key), Z_STRLEN_P(key)); + skey_len = Z_STRLEN_P(key); + while (*skey == ' ') { + *(skey++) = '\0'; + skey_len--; + } + if (skey_len > 1) { + seg = skey + skey_len - 1; + while (*seg == ' ' || *seg == ':') { + *(seg--) = '\0'; + skey_len--; + } + } MAKE_STD_ZVAL(YAF_G(active_ini_file_section)); array_init(YAF_G(active_ini_file_section)); if ((seg = strchr(skey, ':'))) { - char *section; + char *section, *p; + + if (seg > skey) { + p = seg - 1; + while (*p == ' ' || *p == ':') { + *(p--) = '\0'; + } + } while (*(seg) == ' ' || *(seg) == ':') { *(seg++) = '\0'; @@ -265,38 +317,33 @@ static void yaf_config_ini_parser_cb(zval *key, zval *value, zval *index, int ca if ((section = strrchr(seg, ':'))) { /* muilt-inherit */ do { + if (section > seg) { + p = section - 1; + while (*p == ' ' || *p == ':') { + *(p--) = '\0'; + } + } while (*(section) == ' ' || *(section) == ':') { *(section++) = '\0'; } if (zend_symtable_find(Z_ARRVAL_P(arr), section, strlen(section) + 1, (void **)&parent) == SUCCESS) { - zend_hash_copy(Z_ARRVAL_P(YAF_G(active_ini_file_section)), Z_ARRVAL_PP(parent), - (copy_ctor_func_t)yaf_config_ini_zval_deep_copy, NULL, sizeof(zval *)); + php_yaf_deep_copy_section(YAF_G(active_ini_file_section), *parent TSRMLS_CC); } } while ((section = strrchr(seg, ':'))); } - /* remove the tail space, thinking of 'foo : bar : test' */ - section = seg + strlen(seg) - 1; - while (*section == ' ' || *section == ':') { - *(section--) = '\0'; - } - if (zend_symtable_find(Z_ARRVAL_P(arr), seg, strlen(seg) + 1, (void **)&parent) == SUCCESS) { - zend_hash_copy(Z_ARRVAL_P(YAF_G(active_ini_file_section)), Z_ARRVAL_PP(parent), - (copy_ctor_func_t)yaf_config_ini_zval_deep_copy, NULL, sizeof(zval *)); + php_yaf_deep_copy_section(YAF_G(active_ini_file_section), *parent TSRMLS_CC); } + skey_len = strlen(skey); } - seg = skey + strlen(skey) - 1; - while (*seg == ' ' || *seg == ':') { - *(seg--) = '\0'; - } - skey_len = strlen(skey); + zend_symtable_update(Z_ARRVAL_P(arr), skey, skey_len + 1, &YAF_G(active_ini_file_section), sizeof(zval *), NULL); if (YAF_G(ini_wanted_section) && Z_STRLEN_P(YAF_G(ini_wanted_section)) == skey_len && !strncasecmp(Z_STRVAL_P(YAF_G(ini_wanted_section)), skey, skey_len)) { YAF_G(parsing_flag) = YAF_CONFIG_INI_PARSING_PROCESS; } - efree(skey); + efree(skey_orig); } else if (value) { zval *active_arr; if (YAF_G(active_ini_file_section)) { @@ -322,7 +369,7 @@ static void yaf_config_ini_simple_parser_cb(zval *key, zval *value, int callback if (!value) { break; } - + dst = arr; skey = estrndup(Z_STRVAL_P(key), Z_STRLEN_P(key)); if ((seg = php_strtok_r(skey, ".", &ptr))) { @@ -344,6 +391,7 @@ static void yaf_config_ini_simple_parser_cb(zval *key, zval *value, int callback break; } } else { + SEPARATE_ZVAL(ppzval); if (IS_ARRAY != Z_TYPE_PP(ppzval)) { if (seg) { zval *tmp; @@ -442,7 +490,7 @@ static void yaf_config_ini_parser_cb(zval *key, zval *value, int callback_type, if (callback_type == ZEND_INI_PARSER_SECTION) { zval **parent; - char *seg, *skey; + char *seg, *skey, *skey_orig; uint skey_len; if (YAF_G(parsing_flag) == YAF_CONFIG_INI_PARSING_PROCESS) { @@ -450,53 +498,67 @@ static void yaf_config_ini_parser_cb(zval *key, zval *value, int callback_type, return; } - skey = estrndup(Z_STRVAL_P(key), Z_STRLEN_P(key)); + skey_orig = skey = estrndup(Z_STRVAL_P(key), Z_STRLEN_P(key)); + skey_len = Z_STRLEN_P(key); + while (*skey == ' ') { + *(skey++) = '\0'; + skey_len--; + } + if (skey_len > 1) { + seg = skey + skey_len - 1; + while (*seg == ' ' || *seg == ':') { + *(seg--) = '\0'; + skey_len--; + } + } MAKE_STD_ZVAL(YAF_G(active_ini_file_section)); array_init(YAF_G(active_ini_file_section)); if ((seg = strchr(skey, ':'))) { - char *section; + char *section, *p; - while (*(seg) == ' ' || *(seg) == ':') { + if (seg > skey) { + p = seg - 1; + while (*p == ' ' || *p == ':') { + *(p--) = '\0'; + } + } + + while (*seg == ' ' || *seg == ':') { *(seg++) = '\0'; } if ((section = strrchr(seg, ':'))) { /* muilt-inherit */ do { - while (*(section) == ' ' || *(section) == ':') { + if (section > seg) { + p = section - 1; + while (*p == ' ' || *p == ':') { + *(p--) = '\0'; + } + } + while (*section == ' ' || *section == ':') { *(section++) = '\0'; } if (zend_symtable_find(Z_ARRVAL_P(arr), section, strlen(section) + 1, (void **)&parent) == SUCCESS) { - zend_hash_copy(Z_ARRVAL_P(YAF_G(active_ini_file_section)), Z_ARRVAL_PP(parent), - (copy_ctor_func_t)yaf_config_ini_zval_deep_copy, NULL, sizeof(zval *)); + php_yaf_deep_copy_section(YAF_G(active_ini_file_section), *parent TSRMLS_CC); } } while ((section = strrchr(seg, ':'))); } - /* remove the tail space, thinking of 'foo : bar : test' */ - section = seg + strlen(seg) - 1; - while (*section == ' ' || *section == ':') { - *(section--) = '\0'; - } - if (zend_symtable_find(Z_ARRVAL_P(arr), seg, strlen(seg) + 1, (void **)&parent) == SUCCESS) { - zend_hash_copy(Z_ARRVAL_P(YAF_G(active_ini_file_section)), Z_ARRVAL_PP(parent), - (copy_ctor_func_t)yaf_config_ini_zval_deep_copy, NULL, sizeof(zval *)); + php_yaf_deep_copy_section(YAF_G(active_ini_file_section), *parent TSRMLS_CC); } + skey_len = strlen(skey); } - seg = skey + strlen(skey) - 1; - while (*seg == ' ' || *seg == ':') { - *(seg--) = '\0'; - } - skey_len = strlen(skey); + zend_symtable_update(Z_ARRVAL_P(arr), skey, skey_len + 1, &YAF_G(active_ini_file_section), sizeof(zval *), NULL); if (YAF_G(ini_wanted_section) && Z_STRLEN_P(YAF_G(ini_wanted_section)) == skey_len && !strncasecmp(Z_STRVAL_P(YAF_G(ini_wanted_section)), skey, Z_STRLEN_P(YAF_G(ini_wanted_section)))) { YAF_G(parsing_flag) = YAF_CONFIG_INI_PARSING_PROCESS; } - efree(skey); + efree(skey_orig); } else if (value) { zval *active_arr; if (YAF_G(active_ini_file_section)) { diff --git a/tests/067.phpt b/tests/067.phpt new file mode 100644 index 00000000..7ae89b34 --- /dev/null +++ b/tests/067.phpt @@ -0,0 +1,63 @@ +--TEST-- +Check for multi inheritance of section +--SKIPIF-- + +--FILE-- +toArray()); + +?> +--EXPECTF-- +Array +( + [base] => Array + ( + [base] => Array + ( + [a] => 1 + [b] => 2 + ) + + ) + + [extra] => Array + ( + [base] => Array + ( + [c] => 3 + ) + + ) + + [foo] => Array + ( + [base] => Array + ( + [d] => 4 + ) + + ) + + [multi] => Array + ( + [base] => Array + ( + [d] => 4 + [a] => 1 + [b] => 2 + [c] => 3 + ) + + ) + + [] => Array + ( + [base] => Array + ( + [d] => 4 + ) + + ) + +) diff --git a/tests/multi-section.ini b/tests/multi-section.ini new file mode 100644 index 00000000..b019de69 --- /dev/null +++ b/tests/multi-section.ini @@ -0,0 +1,11 @@ +[base ] +base.a=1 +base.b=2 +[ extra] +base.c=3 +[ foo] +base.d=4 + +[ multi:: extra: base : foo ] +[ ::multi2::::: base:] +[: : :: : foo]