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; #else long long nTotal; #endif char 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