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