From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 4483 invoked by alias); 20 Nov 2016 19:37:04 -0000 Mailing-List: contact zsh-workers-help@zsh.org; run by ezmlm Precedence: bulk X-No-Archive: yes List-Id: Zsh Workers List List-Post: List-Help: X-Seq: 39995 Received: (qmail 14071 invoked from network); 20 Nov 2016 19:37:04 -0000 X-Qmail-Scanner-Diagnostics: from know-smtprelay-omc-8.server.virginmedia.net by f.primenet.com.au (envelope-from , uid 7791) with qmail-scanner-2.11 (clamdscan: 0.99.2/21882. spamassassin: 3.4.1. Clear:RC:0(80.0.253.72):SA:0(-0.0/5.0):. Processed in 1.526869 secs); 20 Nov 2016 19:37:04 -0000 X-Spam-Checker-Version: SpamAssassin 3.4.1 (2015-04-28) on f.primenet.com.au X-Spam-Level: X-Spam-Status: No, score=-0.0 required=5.0 tests=RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2,SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.1 X-Envelope-From: p.w.stephenson@ntlworld.com X-Qmail-Scanner-Mime-Attachments: | X-Qmail-Scanner-Zip-Files: | Received-SPF: pass (ns1.primenet.com.au: SPF record at _smtprelay.virginmedia.com designates 80.0.253.72 as permitted sender) X-Originating-IP: [86.21.219.59] X-Spam: 0 X-Authority: v=2.1 cv=OPLapnuB c=1 sm=1 tr=0 a=utowdAHh8RITBM/6U1BPxA==:117 a=utowdAHh8RITBM/6U1BPxA==:17 a=L9H7d07YOLsA:10 a=9cW_t1CCXrUA:10 a=s5jvgZ67dGcA:10 a=IkcTkHD0fZMA:10 a=ZLGELXoPAAAA:8 a=K38l5m9qJH7oXf3TScMA:9 a=QEXdDO2ut3YA:10 a=CFiPc5v16LZhaT-MVE1c:22 Date: Sun, 20 Nov 2016 19:36:58 +0000 From: Peter Stephenson To: zsh-workers@zsh.org Subject: Re: Significant assignstrvalue optimization Message-ID: <20161120193658.781d95da@ntlworld.com> In-Reply-To: <1479484285.1417315.792234625.763D6EEB@webmail.messagingengine.com> References: <1479484285.1417315.792234625.763D6EEB@webmail.messagingengine.com> X-Mailer: Claws Mail 3.11.1 (GTK+ 2.24.28; x86_64-redhat-linux-gnu) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable On Fri, 18 Nov 2016 07:51:25 -0800 Sebastian Gniazdowski wrote: > Second: the same that I did with setarrvalue =E2=80=93 if we assign a[10]= =3D"a", > and 10-th element already exists, i.e. size of string doesn't change, > then instead of: >=20 > x =3D (char *) zalloc(newsize + 1); > strncpy(x, z, v->start); > strcpy(x + v->start, val); > strcat(x + v->start, z + v->end); > v->pm->gsu.s->setfn(v->pm, x); >=20 > It is done: >=20 > /* Size doesn't change, can limit actions to only > * overwriting bytes in already allocated string */ > strncpy(z + v->start, val, vlen); It might be safer both to check explicitly if the setter is the standard string one, and to implement the remaining functionality of that if it is. This shouldn't hit any of the standard cases and I think is now transparently equivalent to the old code. diff --git a/Src/params.c b/Src/params.c index 9d741cb..a79debc 100644 --- a/Src/params.c +++ b/Src/params.c @@ -2436,9 +2436,10 @@ assignstrvalue(Value v, char *val, int flags) v->pm->width =3D strlen(val); } else { char *z, *x; - int zlen; + int zlen, vlen, newsize; =20 - z =3D dupstring_glen(v->pm->gsu.s->getfn(v->pm), (unsigned*) &zlen); + z =3D v->pm->gsu.s->getfn(v->pm); + zlen =3D strlen(z); =20 if ((v->flags & VALFLAG_INV) && unset(KSHARRAYS)) v->start--, v->end--; @@ -2469,12 +2470,34 @@ assignstrvalue(Value v, char *val, int flags) } else if (v->end > zlen) v->end =3D zlen; - x =3D (char *) zalloc(v->start + strlen(val) + zlen - v->end + 1); - strncpy(x, z, v->start); - strcpy(x + v->start, val); - strcat(x + v->start, z + v->end); - v->pm->gsu.s->setfn(v->pm, x); - zsfree(val); + + vlen =3D strlen(val); + /* Characters preceding start index + + characters of what is assigned + + characters following end index */ + newsize =3D v->start + vlen + (zlen - v->end); + + /* Does new size differ? */ + if (newsize !=3D zlen || v->pm->gsu.s->setfn !=3D strsetfn) { + x =3D (char *) zalloc(newsize + 1); + strncpy(x, z, v->start); + strcpy(x + v->start, val); + strcat(x + v->start, z + v->end); + v->pm->gsu.s->setfn(v->pm, x); + } else { + Param pm =3D v->pm; + /* Size doesn't change, can limit actions to only + * overwriting bytes in already allocated string */ + strncpy(z + v->start, val, vlen); + /* Implement remainder of strsetfn */ + if (!(pm->node.flags & PM_HASHELEM) && + ((pm->node.flags & PM_NAMEDDIR) || + isset(AUTONAMEDIRS))) { + pm->node.flags |=3D PM_NAMEDDIR; + adduserdir(pm->node.nam, z, 0, 0); + } + } + zsfree(val); } break; case PM_INTEGER: diff --git a/Test/A06assign.ztst b/Test/A06assign.ztst index da4e3b0..bf39aee 100644 --- a/Test/A06assign.ztst +++ b/Test/A06assign.ztst @@ -489,3 +489,143 @@ print $array 0:slice beyond length of array >FIRST + +# tests of string assignments + + a=3D"abc" + a[1]=3Dx + print $a +0:overwrite first character in string +>xbc + + a=3D"abc" + a[2]=3D"x" + print $a +0:overwrite middle character in string +>axc + + a=3D"abc" + a[3]=3D"x" + print $a +0:overwrite last character in string +>abx + + a=3D"abc" + a[-1]=3D"x" + print $a +0:overwrite -1 character in string +>abx + + a=3D"abc" + a[-2]=3D"x" + print $a +0:overwrite -2 character (middle) in string +>axc + + a=3D"ab" + a[-2]=3D"x" + print $a +0:overwrite -2 character (first) in string +>xb + + a=3D"abc" + a[-3]=3D"x" + print $a +0:overwrite -3 character (first) in string +>xbc + + a=3D"abc" + a[-4]=3D"x" + print $a +0:overwrite -4 character (before first) in string +>xabc + + a=3D"abc" + a[-5]=3D"x" + print $a +0:overwrite -5 character (before-before first) in string +>xabc + + a=3D"abc" + a[-4,0]=3D"x" + print $a +0:overwrite [-4,0] characters (before first) in string +>xabc + + a=3D"abc" + a[-4,-4]=3D"x" + print $a +0:overwrite [-4,-4] character (before first) in string +>xabc + + a=3D"abc" + a[-40,-30]=3D"x" + print $a +0:overwrite [-40,-30] characters (far before first) in string +>xabc + + a=3D"abc" + a[-40,1]=3D"x" + print $a +0:overwrite [-40,1] characters in short string +>xbc + + a=3D"abc" + a[-40,40]=3D"x" + print $a +0:overwrite [-40,40] characters in short string +>x + + a=3D"abc" + a[2,40]=3D"x" + print $a +0:overwrite [2,40] characters in short string +>ax + + a=3D"abc" + a[2,-1]=3D"x" + print $a +0:overwrite [2,-1] characters in short string +>ax + + a=3D"abc" + a[-2,-1]=3D"x" + print $a +0:overwrite [-2,-1] characters in short string +>ax + + a=3D"a" + a[-1]=3D"xx" + print $a +0:overwrite [-1] character with "xx" +>xx + + a=3D"a" + a[-2]=3D"xx" + print $a +0:overwrite [-2] character (before first) with "xx" +>xxa + + a=3D"a" + a[2]=3D"xx" + print $a +0:overwrite [2] character (after last) with "xx" +>axx + + a=3D"" + a[1]=3D"xx" + print $a +0:overwrite [1] character (string: "") with "xx" +>xx + + a=3D"" + a[-1]=3D"xx" + print $a +0:overwrite [-1] character (string: "") with "xx" +>xx + + a=3D"" + a[2]=3D"xx" + print $a +0:overwrite [2] character (string: "") with "xx" +>xx