]> git.vpit.fr Git - perl/modules/Scope-Upper.git/commitdiff
Add slice syntax to localize_{elem,delete} slice
authorVincent Pit <vince@profvince.com>
Tue, 30 Dec 2008 18:31:51 +0000 (19:31 +0100)
committerVincent Pit <vince@profvince.com>
Tue, 30 Dec 2008 18:31:51 +0000 (19:31 +0100)
Upper.xs
t/39-localize_elem-target.t

index e54e42cda5767985ed2bd9a2942dd3dd87bdf326..5c3dec6a65ce1913e42dc5c8bcf4f0d419bde191 100644 (file)
--- a/Upper.xs
+++ b/Upper.xs
@@ -115,8 +115,9 @@ STATIC void su_save_adelete(pTHX_ AV *av, I32 key) {
 
 #endif /* SAVEADELETE */
 
-STATIC void su_save_aelem(pTHX_ AV *av, SV *key, SV *val) {
+STATIC void su_save_aelem(pTHX_ void *av_, SV *key, SV *val) {
 #define su_save_aelem(A, K, V) su_save_aelem(aTHX_ (A), (K), (V))
+ AV *av = av_;
  I32 idx;
  I32 preeminent;
  SV **svp;
@@ -152,8 +153,9 @@ STATIC I32 su_hv_preeminent(pTHX_ HV *hv, SV *keysv) {
  return 1;
 }
 
-STATIC void su_save_helem(pTHX_ HV *hv, SV *keysv, SV *val) {
+STATIC void su_save_helem(pTHX_ void *hv_, SV *keysv, SV *val) {
 #define su_save_helem(H, K, V) su_save_helem(aTHX_ (H), (K), (V))
+ HV *hv = hv_;
  I32 preeminent;
  HE *he;
  SV **svp;
@@ -271,6 +273,32 @@ typedef struct {
  SV *elem;
 } su_ud_localize;
 
+STATIC void su_localize_elem(pTHX_ void *obj, SV *elem, SV *val, void (*do_elem)(pTHX_ void *, SV *, SV *)) {
+#define su_localize_elem(O, E, V, D) su_localize_elem(aTHX_ (O), (E), (V), (D))
+ AV *aelem, *aval;
+ if (SvROK(elem) && (aelem = (AV *) SvRV(elem), SvTYPE(aelem) == SVt_PVAV)) {
+  I32 i, last = av_len(aelem);
+  SV **svpe, **svpv;
+  if (!val) {
+   for (i = 0; i <= last; ++i) {
+    svpe = av_fetch(aelem, i, 0);
+    if (!svpe) continue;
+    do_elem(aTHX_ obj, *svpe, NULL);
+   }
+  } else if (SvROK(val) && (aval = (AV *) SvRV(val), SvTYPE(aval) == SVt_PVAV)){
+   for (i = 0; i <= last; ++i) {
+    svpe = av_fetch(aelem, i, 0);
+    if (!svpe) continue;
+    svpv = av_fetch(aval,  i, 0);
+    if (!svpv) continue;
+    do_elem(aTHX_ obj, *svpe, *svpv);
+   }
+  }
+ } else {
+  do_elem(aTHX_ obj, elem, val);
+ }
+}
+
 STATIC void su_localize(pTHX_ void *ud_) {
 #define su_localize(U) su_localize(aTHX_ (U))
  su_ud_localize *ud = (su_ud_localize *) ud_;
@@ -332,16 +360,14 @@ STATIC void su_localize(pTHX_ void *ud_) {
  switch (t) {
   case SVt_PVAV:
    if (elem) {
-    AV *av = GvAV(gv);
-    su_save_aelem(av, elem, val);
+    su_localize_elem(GvAV(gv), elem, val, su_save_aelem);
     goto done;
    } else
     save_ary(gv);
    break;
   case SVt_PVHV:
    if (elem) {
-    HV *hv = GvHV(gv);
-    su_save_helem(hv, elem, val);
+    su_localize_elem(GvHV(gv), elem, val, su_save_helem);
     goto done;
    } else
     save_hash(gv);
@@ -553,7 +579,7 @@ void
 localize_elem(SV *sv, SV *elem, SV *val, ...)
 PROTOTYPE: $$$;$
 PREINIT:
- I32 level = 0;
+ I32 level = 0, slots = 1;
  su_ud_localize *ud;
 CODE:
  SU_GET_LEVEL(3);
@@ -565,13 +591,15 @@ CODE:
  ud->val  = newSVsv(val);
  SvREFCNT_inc(elem);
  ud->elem = elem;
- su_init(level, ud, 4);
+ if (SvROK(elem) && (elem = SvRV(elem), SvTYPE(elem) == SVt_PVAV))
+  slots = 1 + av_len((AV *) elem);
+ su_init(level, ud, slots * 4);
 
 void
 localize_delete(SV *sv, SV *elem, ...)
 PROTOTYPE: $$;$
 PREINIT:
- I32 level = 0;
+ I32 level = 0, slots = 1;
  su_ud_localize *ud;
 CODE:
  SU_GET_LEVEL(2);
@@ -583,4 +611,6 @@ CODE:
  ud->val  = NULL;
  SvREFCNT_inc(elem);
  ud->elem = elem;
- su_init(level, ud, 4);
+ if (SvROK(elem) && (elem = SvRV(elem), SvTYPE(elem) == SVt_PVAV))
+  slots = 1 + av_len((AV *) elem);
+ su_init(level, ud, slots * 3);
index ecff42bb2ab765847e25e74b89561ac4075cef50..9afafbe96fb864e79bc2f3bc25b0919fd9224dcf 100644 (file)
@@ -3,7 +3,7 @@
 use strict;
 use warnings;
 
-use Test::More tests => 17;
+use Test::More tests => 22;
 
 use Scope::Upper qw/localize_elem/;
 
@@ -29,6 +29,15 @@ our @a;
  is_deeply \@a, [ 4 .. 6 ], 'localize_elem "@a", 4, 8, 0 [end]';
 }
 
+{
+ local @a = (4 .. 6);
+ {
+  localize_elem '@main::a', [ 2, 4 ], [ 7, 8 ], 0;
+  is_deeply \@a, [ 4, 5, 7, undef, 8 ], 'localize_elem "@a", [ 2, 4 ], [ 7, 8 ], 0 [ok]';
+ }
+ is_deeply \@a, [ 4 .. 6 ], 'localize_elem "@a", [ 2, 4], [ 7, 8 ], 0 [end]';
+}
+
 {
  local @a = (4 .. 6);
  {
@@ -55,6 +64,19 @@ our @a;
  is_deeply \@a, [ 4 .. 6 ], 'localize_elem "@a", 4, 12, 1 [end]';
 }
 
+{
+ local @a = (4 .. 6);
+ {
+  local @a = (5 .. 7);
+  {
+   localize_elem '@main::a', [ 3, 4 ], [ 11, 12 ], 1;
+   is_deeply \@a, [ 5 .. 7 ], 'localize_elem "@a", [ 2, 4 ], [ 11, 12 ], 1 [not yet]';
+  }
+  is_deeply \@a, [ 5, 6, 7, 11, 12 ], 'localize_elem "@a", [ 2, 4 ], [ 11, 12 ], 1 [ok]';
+ }
+ is_deeply \@a, [ 4 .. 6 ], 'localize_elem "@a", [ 2, 4 ], [ 11, 12 ], 1 [end]';
+}
+
 # Hashes
 
 our %h;