From: Vincent Pit <vince@profvince.com>
Date: Sun, 28 Dec 2008 17:12:16 +0000 (+0100)
Subject: Localized nonexistant array elements should be deleted when their time comes, so... 
X-Git-Tag: v0.02~6
X-Git-Url: http://git.vpit.fr/?a=commitdiff_plain;h=a1bace73dbcb4d0ea1dba44209e5b51e5742409d;p=perl%2Fmodules%2FScope-Upper.git

Localized nonexistant array elements should be deleted when their time comes, so that the array recovers its original length
---

diff --git a/Upper.xs b/Upper.xs
index 3c024b5..e9228f1 100644
--- a/Upper.xs
+++ b/Upper.xs
@@ -146,6 +146,59 @@ typedef struct {
    )
 #endif
 
+STATIC I32 su_av_preeminent(pTHX_ AV *av, I32 key) {
+#define su_av_preeminent(A, K) su_av_preeminent(aTHX_ (A), (K))
+ MAGIC *mg;
+ HV *stash;
+
+ if (!av)
+  return 0;
+ if (SvCANEXISTDELETE(av))
+  return av_exists(av, key);
+
+ return 1;
+}
+
+#ifndef SAVEADELETE
+
+typedef struct {
+ AV *av;
+ I32 key;
+} su_ud_adelete;
+
+STATIC void su_adelete(pTHX_ void *ud_) {
+ su_ud_adelete *ud = ud_;
+
+ av_delete(ud->av, ud->key, G_DISCARD);
+ SvREFCNT_dec(ud->av);
+
+ Safefree(ud);
+}
+
+STATIC void su_save_adelete(pTHX_ AV *av, I32 key) {
+#define su_save_adelete(A, K) su_save_adelete(aTHX_ (A), (K))
+ su_ud_adelete *ud;
+
+ Newx(ud, 1, su_ud_adelete);
+ ud->av  = av;
+ ud->key = key;
+ SvREFCNT_inc(av);
+
+ SAVEDESTRUCTOR_X(su_adelete, ud);
+}
+
+#define SAVEADELETE(A, K) su_save_adelete((A), (K))
+
+#endif /* SAVEADELETE */
+
+STATIC void su_save_aelem(pTHX_ AV *av, I32 key, SV **svp, I32 preeminent) {
+#define su_save_aelem(A, K, S, P) su_save_aelem(aTHX_ (A), (K), (S), (P))
+ if (preeminent)
+  save_aelem(av, key, svp);
+ else
+  SAVEADELETE(av, key);
+}
+
 STATIC I32 su_hv_preeminent(pTHX_ HV *hv, SV *keysv) {
 #define su_hv_preeminent(H, K) su_hv_preeminent(aTHX_ (H), (K))
  MAGIC *mg;
@@ -234,9 +287,10 @@ STATIC void su_localize(pTHX_ void *ud_) {
    if (elem) {
     I32 idx  = SvIV(elem);
     AV *av   = GvAV(gv);
+    I32 preeminent = su_av_preeminent(av, idx);
     SV **svp = av_fetch(av, idx, 1);
     if (!*svp || *svp == &PL_sv_undef) croak(PL_no_aelem, idx);
-    save_aelem(av, idx, svp);
+    su_save_aelem(av, idx, svp, preeminent);
     gv = (GV *) *svp;
     goto maybe_deref;
    } else
diff --git a/t/39-localize_elem-target.t b/t/39-localize_elem-target.t
index 6a83407..786ce55 100644
--- a/t/39-localize_elem-target.t
+++ b/t/39-localize_elem-target.t
@@ -26,7 +26,7 @@ our @a;
   localize_elem '@main::a', 4, 8, 0;
   is_deeply \@a, [ 4 .. 6, undef, 8 ], 'localize_elem "@a", 4, 8, 0 [ok]';
  }
- is_deeply \@a, [ 4 .. 6, undef, undef ], 'localize_elem "@a", 4, 8, 0 [end]';
+ is_deeply \@a, [ 4 .. 6 ], 'localize_elem "@a", 4, 8, 0 [end]';
 }
 
 {