Re: A better strlcat()
| From: | Andi Gutmans | Date: | Thu, 02 May 2002 17:15:17 +0000 |
| Subject: | Re: A better strlcat() | ||
| References: | 1 | Groups: | php.dev |
| Request: | Send a blank email to php-dev+get-83616@lists.php.net to get a copy of this message | ||
Are you sure it behaves *exactly* like the existing one?
I stole the implementation from OpenBSD so it might be a good idea for you to send it to them.
They are the best to shed light on this and see if it's exactly the same and faster.
Andi
At 09:00 02/05/2002 -0700, Preston L. Bannister wrote:
Was looking at the strlcat() implementation in the PHP source and saw that it does not take advantage of history :). Look at xxx_strlcat() in the following example. You are almost always better off using the compiler's built-in string functions, due to the optimizations built-in (many years ago) to improve Dhrystone benchmark scores. The benchmark turned out to be a bit bogus, but the improvements made to the string functions are a benefit to us all :). This is more readable (and thus more likely correct), slightly faster (about 4% in my testing), and in the debug build better checked. Full comparison benchmark program: ----- #include <stdlib.h> #include <stdio.h> #include <string.h> #include <time.h> #include <assert.h> /* * Appends src to string dst of size siz (unlike strncat, siz is the * full size of dst, not space left). At most siz-1 characters * will be copied. Always NUL terminates (unless siz == 0). * Returns strlen(src); if retval >= siz, truncation occurred. */ size_t php_strlcat(char* dst,const char* src,size_t siz) {register char *d = dst; register const char *s = src; register size_t n = siz; size_t dlen;/* Find the end of dst and adjust bytes left but don't go past end */ while (*d != '\0' && n-- != 0) d++; dlen = d - dst; n = siz - dlen;if (n == 0) return(dlen + strlen(s)); while (*s != '\0') { if (n != 1) { *d++ = *s; n--; } s++; } *d = '\0';return(dlen + (s - src)); /* count does not include NUL */} /* * Take full advantage of any compiler/library optimizations built in * to the standard string routines. Look up the history of compiler * comparisons with Dhrystone benchmark to understand why this wins. * Pre-Internet history - check Google's USENET archive. */ size_t xxx_strlcat(char* s1,const char* s2,size_t nMax) {size_t n1 = strlen(s1); size_t n2 = strlen(s2); size_t nCopy = (nMax <= (n1+n2)) ? (nMax - n1 - 1) : n2;/* Better to leave this out and require a valid string return */ if (!nMax) return 0;assert(n1 < nMax); /* Catch pre-existing oversize strings */ assert(0 < nMax); /* Insure return is always a valid string */memcpy(s1+n1,s2,nCopy); s1[n1+nCopy] = 0; return n1+n2; /* as documented for strlcat() */ /*return n1+nCopy; /* actual number of characters */} /* * */ int main(int ac, char** av) {clock_t t1,dt;#ifdef WIN32__int64 nTotal;#elselong long nTotal;#endifchar s1[85]; static char s2[] = "1234567890"; int nLoops = 10;if (1 < ac) { nLoops = atoi(av[1]); }printf("Compare two strlcat() implementations for %d iterations.\n",nLoops);t1 = clock(); nTotal = 0; for (int i=0; i<nLoops; ++i) { s1[0] = 0; nTotal += php_strlcat(s1,s2,sizeof(s1)); nTotal += php_strlcat(s1,s2,sizeof(s1)); nTotal += php_strlcat(s1,s2,sizeof(s1)); nTotal += php_strlcat(s1,s2,sizeof(s1)); nTotal += php_strlcat(s1,s2,sizeof(s1)); nTotal += php_strlcat(s1,s2,sizeof(s1)); nTotal += php_strlcat(s1,s2,sizeof(s1)); nTotal += php_strlcat(s1,s2,sizeof(s1)); nTotal += php_strlcat(s1,s2,sizeof(s1)); nTotal += php_strlcat(s1,s2,sizeof(s1)); } dt = clock() - t1;printf("php_strlcat() copied %1.0f characters in %ld ticks\n",(double)nTotal,(long)dt);t1 = clock(); nTotal = 0; for (i=0; i<nLoops; ++i) { s1[0] = 0; nTotal += xxx_strlcat(s1,s2,sizeof(s1)); nTotal += xxx_strlcat(s1,s2,sizeof(s1)); nTotal += xxx_strlcat(s1,s2,sizeof(s1)); nTotal += xxx_strlcat(s1,s2,sizeof(s1)); nTotal += xxx_strlcat(s1,s2,sizeof(s1)); nTotal += xxx_strlcat(s1,s2,sizeof(s1)); nTotal += xxx_strlcat(s1,s2,sizeof(s1)); nTotal += xxx_strlcat(s1,s2,sizeof(s1)); nTotal += xxx_strlcat(s1,s2,sizeof(s1)); nTotal += xxx_strlcat(s1,s2,sizeof(s1)); } dt = clock() - t1;printf("xxx_strlcat() copied %1.0f characters in %ld ticks\n",(double)nTotal,(long)dt);return 0;} ----- -- Preston L. Bannister http://members.cox.net/preston.bannister/ pbannister on Yahoo Messenger -- PHP Development Mailing List <http://www.php.net/> To unsubscribe, visit: http://www.php.net/unsub.php