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

Reply via email to