Skip to content

Commit

Permalink
Support multi-inheritance in ini configs
Browse files Browse the repository at this point in the history
  • Loading branch information
laruence committed May 11, 2013
1 parent e206db0 commit 472ce2a
Show file tree
Hide file tree
Showing 3 changed files with 196 additions and 60 deletions.
182 changes: 122 additions & 60 deletions configs/yaf_config_ini.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
/* }}} */

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -242,21 +275,40 @@ 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) {
YAF_G(parsing_flag) = YAF_CONFIG_INI_PARSING_END;
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';
Expand All @@ -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)) {
Expand All @@ -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))) {
Expand All @@ -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;
Expand Down Expand Up @@ -442,61 +490,75 @@ 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) {
YAF_G(parsing_flag) = YAF_CONFIG_INI_PARSING_END;
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)) {
Expand Down
63 changes: 63 additions & 0 deletions tests/067.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
--TEST--
Check for multi inheritance of section
--SKIPIF--
<?php if (!extension_loaded("yaf")) print "skip"; ?>
--FILE--
<?php
$config = new Yaf_Config_Ini(dirname(__FILE__) . "/multi-section.ini");
print_r($config->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
)

)

)
11 changes: 11 additions & 0 deletions tests/multi-section.ini
Original file line number Diff line number Diff line change
@@ -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]

0 comments on commit 472ce2a

Please sign in to comment.