Stas Bekman <[EMAIL PROTECTED]> writes:
[...]
Check this out. It seems to work now. Here is a complete patch. You will have to rebuild the whole thing, because of the API change.
[...]
+static MP_INLINE +const char *mpxs_APR__Table_FETCH(pTHX_ SV *tsv, const char *key) +{ + apr_table_t *t = mp_xs_sv2_APR__Table(tsv); + + if (!t) { + return ""; + } + + if (!mpxs_apr_table_iterix(tsv)) { + return apr_table_get(t, key); + } + else { + const apr_array_header_t *arr = apr_table_elts(t); + apr_table_entry_t *elts = (apr_table_entry_t *)arr->elts; + return elts[mpxs_apr_table_iterix(tsv)-1].val; + } }
Although I haven't tested the patch, I still don't think this is a good approach. The problem is that this introduces "state" into
FETCH, and normal perl hashes don't have this. Look at this
(albeit contrived) example:
# do something to each entry until the "foo" key is encountered
sub foo_do { my $t = shift;
my ($k, $v) = each %$t; return if not defined $k or $k eq "foo";
# ...do stuff here... }
foo_do($t);
my $bar = $t->{bar}; # do we get foo's value here, or bar's value ?
If the "foo" key is ever present in $t, the iterator state (SvCUR)
for $t will remain positive, so a subsequent normal FETCH will
not produce accurate results. $bar will likely wind up holding foo's value here.
With a normal hash, there's no problem here because perl calls hv_iterval (not hv_fetch) when it wants to do an "iterative" fetch.
It seems to me that the TIEHASH API isn't as flexible as it needs to be- IMO it _should_ call FIRST_KEY and NEXT_KEY in list context when it needs to produce each(%$t) (or values (%$t)) in a list context (of course, it doesn't- all TIE methods are called in
scalar context by the Perl_magic_*pack functions in mg.c.
That's true. My "fix" takes it a bit further, but as your example shows it introduces the state problem. The solution I see is to store the id in the key, so when FETCH is called in the SCALAR context it checks whether the key has an id and uses it to get the appropriate value. Otherwise it calls apr_table_get(). Does this work? This is in addition to the existing each/keys solution.
__________________________________________________________________ Stas Bekman JAm_pH ------> Just Another mod_perl Hacker http://stason.org/ mod_perl Guide ---> http://perl.apache.org mailto:[EMAIL PROTECTED] http://use.perl.org http://apacheweek.com http://modperlbook.org http://apache.org http://ticketmaster.com
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
