Re: Newbie question: zend_hash_find

From: Date: Wed, 08 Nov 2006 18:40:13 +0000
Subject: Re: Newbie question: zend_hash_find
References: 1  Groups: php.internals 
Request: Send a blank email to internals+get-26422@lists.php.net to get a copy of this message
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;
       }
} }


« previous php.internals (#26422) next »