Hi Arnold,

zend_hash_find() is always returning FAILURE because its "key_length"
parameter *includes* the terminating '\0'. :-)  So you need strlen(key) + 1.

BTW, are any of your keys going to have numeric values ([123] sections
etc.)?  Then you'll also have a problem with hash_find() as it doesn't
handle numeric string keys since PHP 5 (converting them to a true number
index like when you use $arr['123']), but the add_assoc_* functions do. If
that's an issue, you have to use zend_symtable_find() since PHP 5, which
works exactly like hash_find() in PHP 4.

Hope that helps.


Matt


----- Original Message -----
From: "Arnold Daniels"
Sent: Wednesday, November 08, 2006


> Hi,
>
> I'm new at PHP internals and have read the 'Extension Writing' tutorial
> (part 1-3) of devzone.zend.com. I'm writing a set of parsers, to parse
> different kind of configuration formats. The first is an .ini parser.
> The code almost works correctly. The only problem I have is that
> sections get overwritten if appear multiple times in the .ini content.
>
> [abc]
> test = 1
> [abc]
> xyz = 2
>
> Should result in: array('abc'=>array('test'=>1, 'xyz'=>2))
> but instead returns: array('abc'=>array('xyz'=>2))
>
> The logical conclusion is that my zend_hash_find call doesn't work
> correctly and is always returning FAILURE. Though I've got no clue
> what's wrong. Perhaps someone could have a quick look at the code.
>
> Thanks a lot,
> Arnold
>
>
> --------------------
>
> /**
>  * Parse .ini content into a zend array
>  */
> PHP_FUNCTION(qconf_ini_parse)
> {
>     char *content;
>     int len;
>
>     char *c;
>     char *ln_start;
>     char key[ASCIILINESZ+1];
>     char val[ASCIILINESZ+1];
>     zval *cur_out;
>     zval **fnd_sec;
>
>     char t; // boolean: trim value yes/no
>
>     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &content,
> &len) == FAILURE) {
>         RETURN_NULL();
>     }
>
>     array_init(return_value);
>
>     cur_out = return_value;
>     ln_start = content;
>
>     for (c=content; c <= content+len; c++) {
>         if (*c == '\n' || *c == '\0' || c == content+len) {
>             *c = '\0';
>
>             t = 0;
>             ln_start = strskp(ln_start); /* Skip leading spaces */
>             if (*ln_start!=';' && *ln_start!='#' && *ln_start!=0) { /*
> Skip comment lines */
>                 if (sscanf(ln_start, "[%[^]]", key)==1) {
>                     /* Valid section name */
>                     if (zend_hash_find(Z_ARRVAL_P(return_value), key,
> strlen(key), (void**)&fnd_sec) == FAILURE) {
>                         ALLOC_INIT_ZVAL(cur_out);
>                         array_init(cur_out);
>                         add_assoc_zval(return_value, key, cur_out);
>                     } else {
>                         cur_out = *fnd_sec;
>                     }
>                 } else if (sscanf (ln_start, "%[^=] = \"%[^\"]\"", key,
> val) == 2
>                        ||  sscanf (ln_start, "%[^=] = '%[^\']'", key,
> val) == 2
>                        ||  (t=1 && sscanf (ln_start, "%[^=] = %[^;#]",
> key, val) == 2)) {
>                     strcpy(key, strlwc(strcrop(key)));
>                     /*
>                      * sscanf cannot handle "" or '' as empty value,
>                      * this is done here
>                      */
>                     if (!strcmp(val, "\"\"") || !strcmp(val, "''")) {
>                         val[0] = (char)0;
>                     } else if (t)  {
>                         strcpy(val, strcrop(val));
>                     }
>                     add_assoc_string(cur_out, key, val, 1);
>                 }
>             }
>
>             ln_start = c+1;
>         }
>     }
> }
>

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to