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;
       }
   }
}


--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to