I need to process hash value depends on value type. Here is code with problem:
I32 keys = hv_iterinit(hash);
for (I32 i = 0; i < keys; i++)
{
char *key = NULL;
I32 key_length = 0;
SV *value = hv_iternextsv(hash, &key, &key_length);
// SvROK(value);
if (SvTYPE(SvRV(value)) < SVt_PVAV)
{
// handle scalar
printf("key %s has scalar value\n", key);
}
else if (SvTYPE(SvRV(value)) == SVt_PVAV)
{
// handle array
printf("key %s has array value\n", key);
}
else if (SvTYPE(SvRV(value)) == SVt_PVHV)
{
// handle hash
printf("key %s has hash value\n", key);
}
}
If I don't use commented line, I have problem with scalar values. For example with following hash {a => "b", c => {d => "e"}} is produce output:
key c has hash value
key d has scalar value
So here are my questions:
hv_iternextsv() or sometimes it returns scalar?a.Update.
My mistake was in working with result of hv_iternextsv(). I was thinking that is always a reference. Here is how working code looks like:
I32 keys = hv_iterinit(hash);
for (I32 i = 0; i < keys; i++)
{
char *key = NULL;
I32 key_length = 0;
SV *value = hv_iternextsv(hash, &key, &key_length);
if (!SvROK(value))
{
// handle scalar
}
else
{
if (SvTYPE(SvRV(value)) == SVt_PVAV)
{
// handle array
}
else if (SvTYPE(SvRV(value)) == SVt_PVHV)
{
// handle hash
}
}
}
Do we always have reference returned from
hv_iternextsv()or sometimes it returns scalar?
It always returns a scalar. Hashes values can only be scalars. Those scalars can be references ($h{x} = [];), but need not be ($h{y} = 123;).
Why I don't see scalar value output for key a.
There's no way your could possibly return what you said it does, seeing as your hash has no key named d. For the hash you provided, your code outputs the following:
key a has scalar value
key c has hash value
But it's more of a coincidence than anything else that you got the right answer. SvTYPE(SvRV(value)) when value isn't a reference??? That makes no sense! The fixed code follows:
use strict;
use warnings;
use Inline C => <<'__EOI__';
void print_keys(HV* hash) {
char *key;
I32 key_length;
SV *value;
hv_iterinit(hash);
while (value = hv_iternextsv(hash, &key, &key_length)) {
if (SvROK(value)) {
SV * const referenced = SvRV(value);
if (SvTYPE(referenced) == SVt_PVAV) {
printf("The value at key %s is reference to an array\n", key);
}
else if (SvTYPE(referenced) == SVt_PVHV) {
printf("The value at key %s is a reference to a hash\n", key);
}
else {
printf("The value at key %s is a reference\n", key);
}
} else {
printf("The value at key %s is not a reference\n", key);
}
}
}
__EOI__
print_keys({a => "b", c => {d => "e"}});
Output:
The value at key a is not a reference
The value at key c is a reference to a hash
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With