Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:26422 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 39905 invoked by uid 1010); 8 Nov 2006 18:40:02 -0000 Delivered-To: ezmlm-scan-internals@lists.php.net Delivered-To: ezmlm-internals@lists.php.net Received: (qmail 39890 invoked from network); 8 Nov 2006 18:40:02 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 8 Nov 2006 18:40:02 -0000 Authentication-Results: pb1.pair.com header.from=tularis@php.net; sender-id=unknown Authentication-Results: pb1.pair.com smtp.mail=tularis@php.net; spf=permerror; sender-id=unknown Received-SPF: error (pb1.pair.com: domain php.net from 195.121.247.8 cause and error) X-PHP-List-Original-Sender: tularis@php.net X-Host-Fingerprint: 195.121.247.8 smtp17.wxs.nl NetCache Data OnTap 5.x Received: from [195.121.247.8] ([195.121.247.8:56832] helo=smtp17.wxs.nl) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id AF/BE-40701-08422554 for ; Wed, 08 Nov 2006 13:40:01 -0500 Received: from [192.168.1.2] (ip3e830243.speed.planet.nl [62.131.2.67]) by smtp17.wxs.nl (iPlanet Messaging Server 5.2 Patch 2 (built Jul 14 2004)) with ESMTP id <0J8F00MHRD6LAK@smtp17.wxs.nl> for internals@lists.php.net; Wed, 08 Nov 2006 19:39:58 +0100 (CET) Date: Wed, 08 Nov 2006 19:40:13 +0100 In-reply-to: <4552230A.9090700@adaniels.nl> To: Arnold Daniels Cc: internals@lists.php.net Message-ID: <4552248D.90403@php.net> MIME-version: 1.0 Content-type: text/plain; charset=ISO-8859-1; format=flowed Content-transfer-encoding: 7BIT User-Agent: Thunderbird 1.5.0.7 (Windows/20060909) References: <4552230A.9090700@adaniels.nl> Subject: Re: Newbie question: zend_hash_find From: tularis@php.net ("M.Sokolewicz") hi, Have you tried looking at how the parse_ini_file function works? that should answer your questions on this. - tul Arnold Daniels wrote: > 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; > } > } > } >