Problem with a hash of hashes I build in a C function
| From: | yves at realnames dot com | Date: | Wed, 19 Apr 2000 18:30:02 +0000 |
| Subject: | Problem with a hash of hashes I build in a C function | ||
| Groups: | php.dev | ||
| Request: | Send a blank email to php-dev+get-18043@lists.php.net to get a copy of this message | ||
Hi,
I am writing a PHP module that will offer a simple interface to do
charset conversions. (I plan to donate the module to both ICU and PHP
once it's finished.) One of my functions returns a hash of hashes. Each
value of the hash I return is itself a hash with keys "mime", "iana" and
"aliases". I have a problem, though, which is that if I do:
<?php
$charsets = charsets();
while (list($key, $val) = each($charsets)) {
echo "charset: $charset has MIME name: ", $val["mime"],
"<br>\n";
}
?>
I see things like:
charset: utf-8 has MIME name:
charset: utf-16 has MIME name:
that is, $val["mime"] is empty. If I do this, however:
<?php
$charsets = charsets();
while (list($key, $val) = each($charsets)) {
echo "charset: $charset has MIME name: ";
while (list($vkey, $vval) = each($val)) {
if ($vkey == "mime") {
echo $vval, "(", $val["mime"], ")<br>\n";
}
}
}
?>
then I see:
charset: utf-8 has MIME name: utf-8 ()
charset: utf-16 has MIME name: utf-7 ()
That puzzles me. Why can I iterate over the keys/values of $val but
can't access them through []. This is with php 3.0.16 on Debian
GNU/Linux woody, in Apache.
Below is some of the code that is used to build the return value of my
function. Do I do anything wrong (I hope I do, and you'll know what!)?
Also, another minor inconvenience is that if I dump $vkey and $vval in
the above loop, I get the "aliases" key twice. Maybe that's the symptom
of the problem I'm experiencing right now.
Thanks a lot for any help!
Yves.
PS: who can I get in touch to dicuss supporting Unicode in PHP too?
[---- Following is some of my module code ----]
/*
* The following macros abstract the different ways PHP 3 and 4 expect
* hashes to be manipulated.
*
*/
#if PHP_API_VERSION < 19990421
typedef pval phpx_hash_pval;
#define phpx_make_hash_pval(p)
#define phpx_val_hash_pval(p) (p)
#define phpx_ptr_hash_pval(p) (&(p))
#define zend_list_addref(l)
#define IS_RESOURCE IS_LONG
#else
typedef pval *phpx_hash_pval;
#define phpx_make_hash_pval(p) do { \
MAKE_STD_ZVAL(p); \
} while (0)
#define phpx_val_hash_pval(p) (*(p))
#define phpx_ptr_hash_pval(p) (p)
#endif
/* {{{ proto array charsets()
Return an array with information about supported charsets.
The array is a hash whose keys are internal names of charsets. For
each key, the array value is a hash with the following valid keys:
aliases the value is an array of aliases names for this charset
mime the value is the MIME name for this charset, if any
iana the value is the IANA name for this charset, if any
Note that at this time the mime and iana keys are not fully supported.
*/
/*
* Example: $csets = charsets();
*
*/
PHP_FUNCTION(charsets) {
int argc;
char thisfunc[] = "charsets";
argc = ARG_COUNT(ht);
if (argc != 0) {
WRONG_PARAM_COUNT;
}
if (array_init(return_value) == FAILURE) {
php3_error(E_ERROR, "Couldn't initialize a charsets array in %s()
call", thisfunc);
} else {
int i, count = yconv_maxencnum();
for (i = 0; i < count; ++i) {
int j;
const char *charset = yconv_encnam(i), *mime = charset, *iana = 0;
size_t charsetlen = strlen(charset) + 1;
const void *aliases = yconv_encaliasfst(i);
phpx_hash_pval valhash;
pval *valhash_ptr;
phpx_hash_pval aliaseshash;
pval *aliaseshash_ptr;
phpx_make_hash_pval(valhash);
valhash_ptr = phpx_ptr_hash_pval(valhash);
phpx_make_hash_pval(aliaseshash);
aliaseshash_ptr = phpx_ptr_hash_pval(aliaseshash);
if (array_init(valhash_ptr) == FAILURE) {
php3_error(E_ERROR, "Couldn't initialize a charset
description array in %s() call", thisfunc);
break; // XXX Should we free the other arrays we
created?
}
if (array_init(aliaseshash_ptr) == FAILURE) {
php3_error(E_ERROR, "Couldn't initialize an aliases
array in %s() call", thisfunc);
break; // XXX Should we free the other arrays we
created?
}
for (j = 0; aliases; aliases = yconv_encaliasnxt(aliases), ++j) {
const char *alias = yconv_encaliasnam(aliases);
phpx_hash_pval entry;
pval *entry_ptr;
phpx_make_hash_pval(entry);
entry_ptr = phpx_ptr_hash_pval(entry);
entry_ptr->value.str.len = strlen(alias);
strncpy(entry_ptr->value.str.val = (char *)
ecalloc(entry_ptr->value.str.len + 1, 1), alias,
entry_ptr->value.str.len);
entry_ptr->type = IS_STRING;
_php3_hash_index_update(aliaseshash_ptr->value.ht, j, &entry,
sizeof(entry), NULL);
/* XXX This is such a lame shortcut! */
if (strchr(alias, ':')) {
iana = alias;
} else if (entry_ptr->value.str.len > 5 && !strncmp(alias +
entry_ptr->value.str.len - 5, "-19", 3)) {
iana = alias;
}
}
_php3_hash_update(valhash_ptr->value.ht, "aliases",
sizeof("aliases") + 1, &aliaseshash, sizeof(aliaseshash), NULL);
if (mime) {
phpx_hash_pval entry;
pval *entry_ptr;
phpx_make_hash_pval(entry);
entry_ptr = phpx_ptr_hash_pval(entry);
entry_ptr->value.str.len = strlen(mime);
strncpy(entry_ptr->value.str.val = (char *)
ecalloc(entry_ptr->value.str.len + 1, 1), mime,
entry_ptr->value.str.len);
entry_ptr->type = IS_STRING;
_php3_hash_update(valhash_ptr->value.ht, "mime", sizeof("mime") +
1, &entry, sizeof(entry), NULL);
}
if (iana) {
phpx_hash_pval entry;
pval *entry_ptr;
phpx_make_hash_pval(entry);
entry_ptr = phpx_ptr_hash_pval(entry);
entry_ptr->value.str.len = strlen(iana);
strncpy(entry_ptr->value.str.val = (char *)
ecalloc(entry_ptr->value.str.len + 1, 1), iana,
entry_ptr->value.str.len);
entry_ptr->type = IS_STRING;
_php3_hash_update(valhash_ptr->value.ht, "iana", sizeof("iana") +
1, &entry, sizeof(entry), NULL);
}
_php3_hash_update(return_value->value.ht, (char *) charset,
charsetlen + 1, &valhash, sizeof(valhash), NULL);
}
}
}
/* }}} */