From 8522e996ecc88697344dcc4814367ec7e32e7deb Mon Sep 17 00:00:00 2001 From: Sebastian Gniazdowski Date: Sat, 4 Mar 2017 15:35:19 -0800 Subject: 40781: optimize array assignment, similar to 39995 for string assignment --- ChangeLog | 3 +++ Src/params.c | 63 ++++++++++++++++++++++++++++++++++++++------------ Test/A06assign.ztst | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 117 insertions(+), 15 deletions(-) diff --git a/ChangeLog b/ChangeLog index ecbae823e..40972a0b9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2017-03-04 Barton E. Schaefer + * Sebastian: 40781: Src/params.c, Test/A06assign.ztst: optimize + array assignment, similar to 39995 for string assignment + * 40654: Src/exec.c: exit cleanly from special POSIXBUILTINS in subshells diff --git a/Src/params.c b/Src/params.c index 19cbb1c84..8942fefc2 100644 --- a/Src/params.c +++ b/Src/params.c @@ -2723,24 +2723,57 @@ setarrvalue(Value v, char **val) *p++ = *r++; } } else { - p = new = (char **) zalloc(sizeof(char *) - * (post_assignment_length + 1)); - - for (i = 0; i < v->start; i++) - *p++ = i < pre_assignment_length ? ztrdup(*q++) : ztrdup(""); - for (r = val; *r;) { - /* Give away ownership of the string */ - *p++ = *r++; - } - if (v->end < pre_assignment_length) - for (q = old + v->end; *q;) - *p++ = ztrdup(*q++); - *p = NULL; + /* arr+=( ... ) + * arr[${#arr}+x,...]=( ... ) */ + if (post_assignment_length > pre_assignment_length && + pre_assignment_length <= v->start && + pre_assignment_length > 0 && + v->pm->gsu.a->setfn == arrsetfn) + { + p = new = (char **) zrealloc(old, sizeof(char *) + * (post_assignment_length + 1)); + + p += pre_assignment_length; /* after old elements */ + + /* Consider 1 < 0, case for a=( 1 ); a[1,..] = + * 1 < 1, case for a=( 1 ); a[2,..] = */ + if (pre_assignment_length < v->start) { + for (i = pre_assignment_length; i < v->start; i++) { + *p++ = ztrdup(""); + } + } + + for (r = val; *r;) { + /* Give away ownership of the string */ + *p++ = *r++; + } + + /* v->end doesn't matter: + * a=( 1 2 ); a[4,100]=( a b ); echo "${(q@)a}" + * 1 2 '' a b */ + *p = NULL; + + v->pm->u.arr = NULL; + v->pm->gsu.a->setfn(v->pm, new); + } else { + p = new = (char **) zalloc(sizeof(char *) + * (post_assignment_length + 1)); + for (i = 0; i < v->start; i++) + *p++ = i < pre_assignment_length ? ztrdup(*q++) : ztrdup(""); + for (r = val; *r;) { + /* Give away ownership of the string */ + *p++ = *r++; + } + if (v->end < pre_assignment_length) + for (q = old + v->end; *q;) + *p++ = ztrdup(*q++); + *p = NULL; + + v->pm->gsu.a->setfn(v->pm, new); + } DPUTS2(p - new != post_assignment_length, "setarrvalue: wrong allocation: %d 1= %lu", post_assignment_length, (unsigned long)(p - new)); - - v->pm->gsu.a->setfn(v->pm, new); } /* Ownership of all strings has been diff --git a/Test/A06assign.ztst b/Test/A06assign.ztst index bf39aee7f..fd2b4177c 100644 --- a/Test/A06assign.ztst +++ b/Test/A06assign.ztst @@ -133,6 +133,72 @@ >1 2 42 43 44 5 >1 2 42 100 99 5 +# (subsection: append to array) + + array=( ) + array[5,6]=( 1 2 3 ) + print $array + print "${(q@)array}" +0:Append to empty array by range +>1 2 3 +>'' '' '' '' 1 2 3 + + array=( a ) + array[5,6]=( 1 2 3 ) + print $array + print "${(q@)array}" +0:Append to 1-element array by range +>a 1 2 3 +>a '' '' '' 1 2 3 + + array=( a b ) + array[5,6]=( 1 2 3 ) + print $array + print "${(q@)array}" +0:Append to 2-element array by range +>a b 1 2 3 +>a b '' '' 1 2 3 + + array=( a b ) + array[5,5]=( 1 2 3 ) + print $array + print "${(q@)array}" +0:Append to 2-element array by [a,a] range +>a b 1 2 3 +>a b '' '' 1 2 3 + + array=( a b c d ) + array[5,6]=( 1 2 3 ) + print $array + print "${(q@)array}" +0:Append array by range, continuously +>a b c d 1 2 3 +>a b c d 1 2 3 + + array=( a b c d ) + array[5,5]=( 1 2 3 ) + print $array + print "${(q@)array}" +0:Append array by [a,a] range, continuously +>a b c d 1 2 3 +>a b c d 1 2 3 + + array=( ) + array+=( 1 2 3 ) + print $array + print "${(q@)array}" +0:Append empty array via += +>1 2 3 +>1 2 3 + + array=( a ) + array+=( 1 2 3 ) + print $array + print "${(q@)array}" +0:Append 1-element array via += +>a 1 2 3 +>a 1 2 3 + # tests of var+=scalar s+=foo -- cgit 1.4.1