perl-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Joe Schaefer <joe+gm...@sunstarsys.com>
Subject Re: [Fwd: Re: [rfc] APR::Table & polymorphic values]
Date Tue, 10 Jun 2003 13:46:17 GMT
"Philippe M. Chiasson" <gozer@cpan.org> writes:

[...]

> One thing I _do_ remember is that while (my($a, $b) = each %$table) { }
> did iterate over all key/value pairs when I initially implemented the
> TIE'ed stuff.. But once again, it's been a long time since I looked at
> that stuff.

It always iterated over the keys correctly, just not the (multi-)values.
The problem really lies in perl's tiehash implementation of each();
internally it's doing the moral equivalent of

  sub each {
    my $t = shift;
    my $key = $t->NEXTKEY($prev_key) or return;
    return wantarray ? ($key, $t->FETCH($key)) : $key;
  }

IOW, each() really calls FETCH to get the value.  As long as FETCH
doesn't work, each() in list context doesn't work either.

> But one thing is for sure, this patch (and this thread also, actually)
> is indeed quite ugly (no offense meant)...

Agreed.  btw- I'm never offended by code critiques.  Go ahead, 
feel free to fire away  :-)

> There _has_ to be a simpler to make this work...

Looking over things again, it seems we might be able to make
use of the xpvhv slots in the underlying HV (which are mostly
unused because of the tie magic).  I just looked at hv.h and picked
xhv_array and xhv_eiter.  I've no clue what they're used for
wrt tied hashes, but these implementations of NEXTKEY & FETCH
seems to work (all tests pass):

static MP_INLINE SV *mpxs_APR__Table_NEXTKEY(pTHX_ SV *tsv, SV *key)
{
    apr_table_t *t = mp_xs_sv2_APR__Table(tsv); 
    if (apr_is_empty_table(t)) {
        return Nullsv;
    }

    if (mpxs_apr_table_iterix(tsv) < apr_table_elts(t)->nelts) {
        apr_table_entry_t *e = ((apr_table_entry_t *)
            apr_table_elts(t)->elts) + mpxs_apr_table_iterix(tsv)++;
        STRLEN len = strlen(e->key);
        SV *sv = newSVpv(e->key, 0);
        XPVHV *xhv = (XPVHV *)SvANY(SvRV(tsv));
        xhv->xhv_eiter = (HE *)e;
        xhv->xhv_array = SvPVX(sv);
        return sv;
    }
    mpxs_apr_table_iterix(tsv) = 0; /* done */
    return &PL_sv_undef;
}

static MP_INLINE
const char *mpxs_APR__Table_FETCH(pTHX_ SV *tsv, SV *sv)
{
    apr_table_t *t = mp_xs_sv2_APR__Table(tsv);
    MAGIC *mg;
    XPVHV *xhv = (XPVHV *)SvANY(SvRV(tsv));
    if (!t) {
        return NULL;
    }

    if (xhv->xhv_array == SvPV_nolen(sv))
    {
        apr_table_entry_t *e = (apr_table_entry_t *)xhv->xhv_eiter;
        fprintf(stderr, "ITERATOR CALL: %s => %s\n", e->key, e->val);
        return e->val;
    }   
    else {
        return apr_table_get(t, SvPV_nolen(sv));
    }
}

-- 
Joe Schaefer


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org


Mime
View raw message