}
SV**
+avhv_fetch_ent(av, keysv, lval, hash)
+AV *av;
+SV *keysv;
+I32 lval;
+U32 hash;
+{
+ SV **keys, **indsvp;
+ HE *he;
+ I32 ind;
+
+ keys = av_fetch(av, 0, FALSE);
+ if (!keys || !SvROK(*keys) || SvTYPE(SvRV(*keys)) != SVt_PVHV)
+ croak("Can't coerce array into hash");
+ he = hv_fetch_ent((HV*)SvRV(*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((HV*)SvRV(*keys), keysv, newSViv(ind), 0);
+ }
+ return av_fetch(av, ind, lval);
+}
+
+SV**
avhv_store(av, key, klen, val, hash)
AV *av;
char *key;
}
bool
+avhv_exists_ent(av, keysv, hash)
+AV *av;
+SV *keysv;
+U32 hash;
+{
+ SV **keys;
+
+ keys = av_fetch(av, 0, FALSE);
+ if (!keys || !SvROK(*keys) || SvTYPE(SvRV(*keys)) != SVt_PVHV)
+ croak("Can't coerce array into hash");
+ return hv_exists_ent((HV*)SvRV(*keys), keysv, hash);
+}
+
+bool
avhv_exists(av, key, klen)
AV *av;
char *key;
return sv;
}
+/* avhv_delete_ent leaks. Caller can re-index and compress if so desired. */
+SV *
+avhv_delete_ent(av, keysv, flags, hash)
+AV *av;
+SV *keysv;
+I32 flags;
+U32 hash;
+{
+ SV **keys;
+ SV *sv;
+ SV **svp;
+ I32 ind;
+
+ keys = av_fetch(av, 0, FALSE);
+ if (!keys || !SvROK(*keys) || SvTYPE(SvRV(*keys)) != SVt_PVHV)
+ croak("Can't coerce array into hash");
+ sv = hv_delete_ent((HV*)SvRV(*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;
+}
+
I32
avhv_iterinit(av)
AV *av;
OUTPUT:
RETVAL
->>>> ORIGINAL VERSION
-BOOT:
- newXS("DB_File::TIEARRAY", XS_DB_File_db_TIEHASH, file);
-
-==== THEIR VERSION
-==== YOUR VERSION
-BOOT:
- newXS("DB_File::TIEARRAY", XS_DB_File_TIEHASH, file);
-
-<<<<
int
db_DESTROY(db)
DB_File db
--- /dev/null
+package Class::Fields;
+use Carp;
+
+sub import {
+ my $class = shift;
+ my ($package) = caller;
+ my $fields = \%{"$package\::FIELDS"};
+ my $i = $fields->{__MAX__};
+ foreach my $f (@_) {
+ if (defined($fields->{$f})) {
+ croak "Field name $f already used by a base class"
+ }
+ $fields->{$f} = ++$i;
+ }
+ $fields->{__MAX__} = $i;
+ push(@{"$package\::ISA"}, "Class::Fields");
+}
+
+sub new {
+ my $class = shift;
+ bless [\%{"$class\::FIELDS"}, @_], $class;
+}
+
+sub ISA {
+ my ($class, $package) = @_;
+ my $from_fields = \%{"$class\::FIELDS"};
+ my $to_fields = \%{"$package\::FIELDS"};
+ return unless defined %$from_fields;
+ croak "Ambiguous inheritance for %FIELDS" if defined %$to_fields;
+ %$to_fields = %$from_fields;
+}
+
+1;
--- /dev/null
+package ISA;
+use Carp;
+
+sub import {
+ my $class = shift;
+ my ($package) = caller;
+ foreach my $base (@_) {
+ croak qq(No such class "$base") unless defined %{"$base\::"};
+ eval {
+ $base->ISA($package);
+ };
+ if ($@ && $@ !~ /^Can't locate object method/) {
+ $@ =~ s/ at .*? line \d+\n$//;
+ croak $@;
+ }
+ }
+ push(@{"$package\::ISA"}, @_);
+}
+
+1;
if (perldb && DBsingle)
sv_setiv(DBsingle, 1);
if (restartav)
- calllist(restartav);
+ call_list(oldscope, restartav);
}
/* do it */
if (op->op_private & OPpSLICE) {
dMARK; dORIGMARK;
+ U32 hvtype;
hv = (HV*)POPs;
- U32 hvtype = SvTYPE(hv);
+ hvtype = SvTYPE(hv);
while (++MARK <= SP) {
if (hvtype == SVt_PVHV)
sv = hv_delete_ent(hv, *MARK, discard, 0);
else {
SV *keysv = POPs;
hv = (HV*)POPs;
- if (SvTYPE(hv) != SVt_PVHV)
+ 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");
- sv = hv_delete_ent(hv, keysv, discard, 0);
if (!sv)
sv = &sv_undef;
if (!discard)
he = hv_fetch_ent(hv, keysv, lval, 0);
svp = he ? &HeVAL(he) : 0;
} else {
- svp = avhv_fetch_ent((AV*)hv, keysv, lval);
+ svp = avhv_fetch_ent((AV*)hv, keysv, lval, 0);
}
if (lval) {
if (!he || HeVAL(he) == &sv_undef)
if (SvTYPE(hv) == SVt_PVHV) {
he = hv_fetch_ent(hv, keysv, lval && !defer, 0);
- svp = he ? &Heval(he) : 0;
+ svp = he ? &HeVAL(he) : 0;
}
else if (SvTYPE(hv) == SVt_PVAV) {
- svp = avhv_fetch_ent((AV*)hv, keysv, lval);
+ svp = avhv_fetch_ent((AV*)hv, keysv, lval && !defer, 0);
}
else {
RETPUSHUNDEF;
}
-<<<<
if (lval) {
- if (svp || *svp == &sv_undef) {
+ if (!svp || *svp == &sv_undef) {
SV* lv;
SV* key2;
if (!defer)
I32 apply _((I32 type, SV** mark, SV** sp));
void assertref _((OP* op));
SV* avhv_delete _((AV *ar, char* key, U32 klen, I32 flags));
+SV* avhv_delete_ent _((AV *ar, SV* keysv, I32 flags, U32 hash));
bool avhv_exists _((AV *ar, char* key, U32 klen));
+bool avhv_exists_ent _((AV *ar, SV* keysv, U32 hash));
SV** avhv_fetch _((AV *ar, char* key, U32 klen, I32 lval));
+SV** avhv_fetch_ent _((AV *ar, SV* keysv, I32 lval, U32 hash));
I32 avhv_iterinit _((AV *ar));
HE* avhv_iternext _((AV *ar));
SV * avhv_iternextsv _((AV *ar, char** key, I32* retlen));
in_my = TRUE;
s = skipspace(s);
if (isIDFIRST(*s)) {
- s = scan_word(s, tokenbuf, TRUE, &len);
+ s = scan_word(s, tokenbuf, sizeof tokenbuf, TRUE, &len);
in_my_stash = gv_stashpv(tokenbuf, FALSE);
if (!in_my_stash) {
char tmpbuf[1024];