From 57079c468e190b483eeed1dc905fcaa88d70475e Mon Sep 17 00:00:00 2001 From: Gisle Aas Date: Tue, 30 Jun 1998 15:34:07 +0200 Subject: [PATCH] applied patch with tweaks to prose Subject: [PATCH] Simplified AVHV support Message-ID: p4raw-id: //depot/perl@1286 --- ObjXSub.h | 14 ---- av.c | 196 +++++++------------------------------------------------ embed.h | 7 -- global.sym | 7 -- objpp.h | 14 ---- pod/perldiag.pod | 17 +++++ pp.c | 4 -- proto.h | 7 -- t/op/avhv.t | 5 +- 9 files changed, 42 insertions(+), 229 deletions(-) diff --git a/ObjXSub.h b/ObjXSub.h index b0890a0..6cb2baa 100644 --- a/ObjXSub.h +++ b/ObjXSub.h @@ -715,30 +715,16 @@ #define av_undef pPerl->Perl_av_undef #undef av_unshift #define av_unshift pPerl->Perl_av_unshift -#undef avhv_delete -#define avhv_delete pPerl->Perl_avhv_delete -#undef avhv_delete_ent -#define avhv_delete_ent pPerl->Perl_avhv_delete_ent -#undef avhv_exists -#define avhv_exists pPerl->Perl_avhv_exists #undef avhv_exists_ent #define avhv_exists_ent pPerl->Perl_avhv_exists_ent -#undef avhv_fetch -#define avhv_fetch pPerl->Perl_avhv_fetch #undef avhv_fetch_ent #define avhv_fetch_ent pPerl->Perl_avhv_fetch_ent #undef avhv_iternext #define avhv_iternext pPerl->Perl_avhv_iternext -#undef avhv_iternextsv -#define avhv_iternextsv pPerl->Perl_avhv_iternextsv #undef avhv_iterval #define avhv_iterval pPerl->Perl_avhv_iterval #undef avhv_keys #define avhv_keys pPerl->Perl_avhv_keys -#undef avhv_store -#define avhv_store pPerl->Perl_avhv_store -#undef avhv_store_ent -#define avhv_store_ent pPerl->Perl_avhv_store_ent #undef bind_match #define bind_match pPerl->Perl_bind_match #undef block_end diff --git a/av.c b/av.c index 6e41c2e..2e46053 100644 --- a/av.c +++ b/av.c @@ -590,14 +590,25 @@ av_fill(register AV *av, I32 fill) (void)av_store(av,fill,&sv_undef); } - + +/* AVHV: Support for treating arrays as if they were hashes. The + * first element of the array should be a hash reference that maps + * hash keys to array indices. + */ + +static I32 +avhv_index_sv(SV* sv) +{ + I32 index = SvIV(sv); + if (index < 1) + croak("Bad index while coercing array into hash"); + return index; +} + HV* avhv_keys(AV *av) { - SV **keysp; - HV *keys = Nullhv; - - keysp = av_fetch(av, 0, FALSE); + SV **keysp = av_fetch(av, 0, FALSE); if (keysp) { SV *sv = *keysp; if (SvGMAGICAL(sv)) @@ -605,34 +616,10 @@ avhv_keys(AV *av) if (SvROK(sv)) { sv = SvRV(sv); if (SvTYPE(sv) == SVt_PVHV) - keys = (HV*)sv; + return (HV*)sv; } } - if (!keys) - croak("Can't coerce array into hash"); - return keys; -} - -SV** -avhv_fetch(AV *av, char *key, U32 klen, I32 lval) -{ - SV **indsvp; - HV *keys = avhv_keys(av); - I32 ind; - - indsvp = hv_fetch(keys, key, klen, FALSE); - if (indsvp) { - ind = SvIV(*indsvp); - if (ind < 1) - croak("Bad index while coercing array into hash"); - } else { - if (!lval) - return 0; - - ind = AvFILL(av) + 1; - hv_store(keys, key, klen, newSViv(ind), 0); - } - return av_fetch(av, ind, lval); + croak("Can't coerce array into hash"); } SV** @@ -641,59 +628,11 @@ avhv_fetch_ent(AV *av, SV *keysv, I32 lval, U32 hash) SV **indsvp; HV *keys = avhv_keys(av); HE *he; - I32 ind; - - he = hv_fetch_ent(keys, keysv, FALSE, hash); - if (he) { - ind = SvIV(HeVAL(he)); - if (ind < 1) - croak("Bad index while coercing array into hash"); - } else { - if (!lval) - return 0; - - ind = AvFILL(av) + 1; - hv_store_ent(keys, keysv, newSViv(ind), 0); - } - return av_fetch(av, ind, lval); -} - -SV** -avhv_store(AV *av, char *key, U32 klen, SV *val, U32 hash) -{ - SV **indsvp; - HV *keys = avhv_keys(av); - I32 ind; - - indsvp = hv_fetch(keys, key, klen, FALSE); - if (indsvp) { - ind = SvIV(*indsvp); - if (ind < 1) - croak("Bad index while coercing array into hash"); - } else { - ind = AvFILL(av) + 1; - hv_store(keys, key, klen, newSViv(ind), hash); - } - return av_store(av, ind, val); -} - -SV** -avhv_store_ent(AV *av, SV *keysv, SV *val, U32 hash) -{ - HV *keys = avhv_keys(av); - HE *he; - I32 ind; he = hv_fetch_ent(keys, keysv, FALSE, hash); - if (he) { - ind = SvIV(HeVAL(he)); - if (ind < 1) - croak("Bad index while coercing array into hash"); - } else { - ind = AvFILL(av) + 1; - hv_store_ent(keys, keysv, newSViv(ind), hash); - } - return av_store(av, ind, val); + if (!he) + croak("No such array field"); + return av_fetch(av, avhv_index_sv(HeVAL(he)), lval); } bool @@ -703,69 +642,6 @@ avhv_exists_ent(AV *av, SV *keysv, U32 hash) return hv_exists_ent(keys, keysv, hash); } -bool -avhv_exists(AV *av, char *key, U32 klen) -{ - HV *keys = avhv_keys(av); - return hv_exists(keys, key, klen); -} - -/* avhv_delete leaks. Caller can re-index and compress if so desired. */ -SV * -avhv_delete(AV *av, char *key, U32 klen, I32 flags) -{ - HV *keys = avhv_keys(av); - SV *sv; - SV **svp; - I32 ind; - - sv = hv_delete(keys, key, klen, 0); - if (!sv) - return Nullsv; - ind = SvIV(sv); - if (ind < 1) - croak("Bad index while coercing array into hash"); - svp = av_fetch(av, ind, FALSE); - if (!svp) - return Nullsv; - if (flags & G_DISCARD) { - sv = Nullsv; - SvREFCNT_dec(*svp); - } else { - sv = sv_2mortal(*svp); - } - *svp = &sv_undef; - return sv; -} - -/* avhv_delete_ent leaks. Caller can re-index and compress if so desired. */ -SV * -avhv_delete_ent(AV *av, SV *keysv, I32 flags, U32 hash) -{ - HV *keys = avhv_keys(av); - SV *sv; - SV **svp; - I32 ind; - - sv = hv_delete_ent(keys, keysv, 0, hash); - if (!sv) - return Nullsv; - ind = SvIV(sv); - if (ind < 1) - croak("Bad index while coercing array into hash"); - svp = av_fetch(av, ind, FALSE); - if (!svp) - return Nullsv; - if (flags & G_DISCARD) { - sv = Nullsv; - SvREFCNT_dec(*svp); - } else { - sv = sv_2mortal(*svp); - } - *svp = &sv_undef; - return sv; -} - HE * avhv_iternext(AV *av) { @@ -776,32 +652,6 @@ avhv_iternext(AV *av) SV * avhv_iterval(AV *av, register HE *entry) { - HV *keys = avhv_keys(av); - SV *sv; - I32 ind; - - sv = hv_iterval(keys, entry); - ind = SvIV(sv); - if (ind < 1) - croak("Bad index while coercing array into hash"); - return *av_fetch(av, ind, TRUE); -} - -SV * -avhv_iternextsv(AV *av, char **key, I32 *retlen) -{ - HV *keys = avhv_keys(av); - HE *he; - SV *sv; - I32 ind; - - he = hv_iternext(keys); - if (!he) - return Nullsv; - *key = hv_iterkey(he, retlen); - sv = hv_iterval(keys, he); - ind = SvIV(sv); - if (ind < 1) - croak("Bad index while coercing array into hash"); - return *av_fetch(av, ind, TRUE); + SV *sv = hv_iterval(avhv_keys(av), entry); + return *av_fetch(av, avhv_index_sv(sv), TRUE); } diff --git a/embed.h b/embed.h index 53607f1..01813c9 100644 --- a/embed.h +++ b/embed.h @@ -46,18 +46,11 @@ #define av_store Perl_av_store #define av_undef Perl_av_undef #define av_unshift Perl_av_unshift -#define avhv_delete Perl_avhv_delete -#define avhv_delete_ent Perl_avhv_delete_ent -#define avhv_exists Perl_avhv_exists #define avhv_exists_ent Perl_avhv_exists_ent -#define avhv_fetch Perl_avhv_fetch #define avhv_fetch_ent Perl_avhv_fetch_ent #define avhv_iternext Perl_avhv_iternext -#define avhv_iternextsv Perl_avhv_iternextsv #define avhv_iterval Perl_avhv_iterval #define avhv_keys Perl_avhv_keys -#define avhv_store Perl_avhv_store -#define avhv_store_ent Perl_avhv_store_ent #define band_amg Perl_band_amg #define bind_match Perl_bind_match #define block_end Perl_block_end diff --git a/global.sym b/global.sym index 61bba97..44c8dbc 100644 --- a/global.sym +++ b/global.sym @@ -181,18 +181,11 @@ av_shift av_store av_undef av_unshift -avhv_delete -avhv_delete_ent -avhv_exists avhv_exists_ent -avhv_fetch avhv_fetch_ent avhv_iternext -avhv_iternextsv avhv_iterval avhv_keys -avhv_store -avhv_store_ent bind_match block_end block_gimme diff --git a/objpp.h b/objpp.h index 94837c7..ba12c25 100644 --- a/objpp.h +++ b/objpp.h @@ -51,28 +51,14 @@ #define av_unshift CPerlObj::Perl_av_unshift #undef avhv_keys #define avhv_keys CPerlObj::Perl_avhv_keys -#undef avhv_fetch -#define avhv_fetch CPerlObj::Perl_avhv_fetch #undef avhv_fetch_ent #define avhv_fetch_ent CPerlObj::Perl_avhv_fetch_ent -#undef avhv_store -#define avhv_store CPerlObj::Perl_avhv_store -#undef avhv_store_ent -#define avhv_store_ent CPerlObj::Perl_avhv_store_ent #undef avhv_exists_ent #define avhv_exists_ent CPerlObj::Perl_avhv_exists_ent -#undef avhv_exists -#define avhv_exists CPerlObj::Perl_avhv_exists -#undef avhv_delete -#define avhv_delete CPerlObj::Perl_avhv_delete -#undef avhv_delete_ent -#define avhv_delete_ent CPerlObj::Perl_avhv_delete_ent #undef avhv_iternext #define avhv_iternext CPerlObj::Perl_avhv_iternext #undef avhv_iterval #define avhv_iterval CPerlObj::Perl_avhv_iterval -#undef avhv_iternextsv -#define avhv_iternextsv CPerlObj::Perl_avhv_iternextsv #undef bad_type #define bad_type CPerlObj::bad_type #undef bind_match diff --git a/pod/perldiag.pod b/pod/perldiag.pod index 468e0a3..3851bac 100644 --- a/pod/perldiag.pod +++ b/pod/perldiag.pod @@ -321,6 +321,11 @@ system malloc(). (F) A field name of a typed variable was looked up in the %FIELDS hash, but the index found was not legal, i.e. less than 1. +=item Bad index while coercing array into hash + +(F) The index looked up in the hash found as 0'th element of the array +is not legal. Index values must be at 1 or greater. + =item Bad name after %s:: (F) You started to name a symbol by using a package prefix, and then didn't @@ -497,6 +502,12 @@ but then $foo no longer contains a glob. (F) Certain types of SVs, in particular real symbol table entries (typeglobs), can't be forced to stop being what they are. +=item Can't coerce array into hash + +(F) You used an array where a hash was expected, but the array has no +information on how to map from keys to array indices. You can do that +only with arrays that have a hash reference at index 0. + =item Can't create pipe mailbox (P) An error peculiar to VMS. The process is suffering from exhausted quotas @@ -1606,6 +1617,12 @@ your system. (F) The argument to B<-I> must follow the B<-I> immediately with no intervening space. +=item No such array field + +(F) You tried to access an array as a hash, but the field name used is +not defined. The hash at index 0 should map all valid field names to +array indices for that to work. + =item No such field "%s" in variable %s of type %s (F) You tried to access a field of a typed variable where the type diff --git a/pp.c b/pp.c index 55ab5d1..a927b3d 100644 --- a/pp.c +++ b/pp.c @@ -2358,8 +2358,6 @@ PP(pp_delete) while (++MARK <= SP) { if (hvtype == SVt_PVHV) sv = hv_delete_ent(hv, *MARK, discard, 0); - else if (hvtype == SVt_PVAV) - sv = avhv_delete_ent((AV*)hv, *MARK, discard, 0); else DIE("Not a HASH reference"); *MARK = sv ? sv : &sv_undef; @@ -2377,8 +2375,6 @@ PP(pp_delete) hv = (HV*)POPs; if (SvTYPE(hv) == SVt_PVHV) sv = hv_delete_ent(hv, keysv, discard, 0); - else if (SvTYPE(hv) == SVt_PVAV) - sv = avhv_delete_ent((AV*)hv, keysv, discard, 0); else DIE("Not a HASH reference"); if (!sv) diff --git a/proto.h b/proto.h index 0479480..5bbde48 100644 --- a/proto.h +++ b/proto.h @@ -21,18 +21,11 @@ VIRTUAL OP* append_elem _((I32 optype, OP* head, OP* tail)); VIRTUAL OP* append_list _((I32 optype, LISTOP* first, LISTOP* last)); VIRTUAL I32 apply _((I32 type, SV** mark, SV** sp)); VIRTUAL void assertref _((OP* o)); -VIRTUAL SV* avhv_delete _((AV *ar, char* key, U32 klen, I32 flags)); -VIRTUAL SV* avhv_delete_ent _((AV *ar, SV* keysv, I32 flags, U32 hash)); -VIRTUAL bool avhv_exists _((AV *ar, char* key, U32 klen)); VIRTUAL bool avhv_exists_ent _((AV *ar, SV* keysv, U32 hash)); -VIRTUAL SV** avhv_fetch _((AV *ar, char* key, U32 klen, I32 lval)); VIRTUAL SV** avhv_fetch_ent _((AV *ar, SV* keysv, I32 lval, U32 hash)); VIRTUAL HE* avhv_iternext _((AV *ar)); -VIRTUAL SV * avhv_iternextsv _((AV *ar, char** key, I32* retlen)); VIRTUAL SV* avhv_iterval _((AV *ar, HE* entry)); VIRTUAL HV* avhv_keys _((AV *ar)); -VIRTUAL SV** avhv_store _((AV *ar, char* key, U32 klen, SV* val, U32 hash)); -VIRTUAL SV** avhv_store_ent _((AV *av, SV *keysv, SV *val, U32 hash)); VIRTUAL void av_clear _((AV* ar)); VIRTUAL void av_extend _((AV* ar, I32 key)); VIRTUAL AV* av_fake _((I32 size, SV** svp)); diff --git a/t/op/avhv.t b/t/op/avhv.t index 84d3f27..e01201e 100755 --- a/t/op/avhv.t +++ b/t/op/avhv.t @@ -32,12 +32,11 @@ $a->[0] = $sch; $a->{'abc'} = 'ABC'; $a->{'def'} = 'DEF'; $a->{'jkl'} = 'JKL'; -$a->{'a'} = 'A'; #should extend schema @keys = keys %$a; @values = values %$a; -if ($#keys == 3 && $#values == 3) {print "ok 1\n";} else {print "not ok 1\n";} +if ($#keys == 2 && $#values == 2) {print "ok 1\n";} else {print "not ok 1\n";} $i = 0; # stop -w complaints @@ -48,7 +47,7 @@ while (($key,$value) = each %$a) { } } -if ($i == 4) {print "ok 2\n";} else {print "not ok 2\n";} +if ($i == 3) {print "ok 2\n";} else {print "not ok 2\n";} # quick check with tied array tie @fake, 'Tie::StdArray'; -- 2.7.4