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