Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:26424 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 43965 invoked by uid 1010); 9 Nov 2006 00:34:11 -0000 Delivered-To: ezmlm-scan-internals@lists.php.net Delivered-To: ezmlm-internals@lists.php.net Received: (qmail 43949 invoked from network); 9 Nov 2006 00:34:11 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 9 Nov 2006 00:34:11 -0000 Authentication-Results: pb1.pair.com smtp.mail=php_lists@realplain.com; spf=permerror; sender-id=unknown Authentication-Results: pb1.pair.com header.from=php_lists@realplain.com; sender-id=unknown Received-SPF: error (pb1.pair.com: domain realplain.com from 69.179.208.43 cause and error) X-PHP-List-Original-Sender: php_lists@realplain.com X-Host-Fingerprint: 69.179.208.43 msa3-mx.centurytel.net Linux 2.4/2.6 Received: from [69.179.208.43] ([69.179.208.43:55815] helo=msa3-mx.centurytel.net) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id 4B/23-16868-28772554 for ; Wed, 08 Nov 2006 19:34:11 -0500 Received: from pc1 (72-161-146-107.dyn.centurytel.net [72.161.146.107]) by msa3-mx.centurytel.net (8.13.6/8.13.6) with SMTP id kA90Y5va020636; Wed, 8 Nov 2006 18:34:05 -0600 Message-ID: <004401c70396$c39d1d60$0201a8c0@pc1> To: , "Arnold Daniels" References: <4552230A.9090700@adaniels.nl> Date: Wed, 8 Nov 2006 18:34:05 -0600 MIME-Version: 1.0 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: 7bit X-Priority: 3 X-MSMail-Priority: Normal X-Mailer: Microsoft Outlook Express 6.00.2800.1807 X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1807 Subject: Re: [PHP-DEV] Newbie question: zend_hash_find From: php_lists@realplain.com ("Matt Wilmas") 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; > } > } > } >