source: branches/0.9x/libtransmission/utils.c @ 3972

Last change on this file since 3972 was 3972, checked in by charles, 15 years ago

fix crash on startup reported by Gimp_

  • Property svn:keywords set to Date Rev Author Id
File size: 21.1 KB
Line 
1/******************************************************************************
2 * $Id: utils.c 3972 2007-11-26 05:03:34Z charles $
3 *
4 * Copyright (c) 2005-2007 Transmission authors and contributors
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 *****************************************************************************/
24
25#include <assert.h>
26#include <ctype.h>
27#include <errno.h>
28#include <stdarg.h>
29#include <stdio.h>
30#include <stdlib.h>
31#include <string.h>
32
33#include <sys/time.h>
34#include <sys/types.h>
35#include <sys/stat.h>
36#include <unistd.h> /* usleep, stat */
37
38#ifdef WIN32
39    #include <windows.h> /* for Sleep */
40#elif defined(__BEOS__)
41    #include <kernel/OS.h>
42    extern int vasprintf( char **, const char *, va_list );
43#endif
44
45#include "transmission.h"
46#include "trcompat.h"
47#include "utils.h"
48#include "platform.h"
49
50#define SPRINTF_BUFSIZE         100
51
52static tr_lock      * messageLock = NULL;
53static int            messageLevel = 0;
54static int            messageQueuing = FALSE;
55static tr_msg_list *  messageQueue = NULL;
56static tr_msg_list ** messageQueueTail = &messageQueue;
57
58void tr_msgInit( void )
59{
60    if( !messageLock )
61         messageLock = tr_lockNew( );
62}
63
64FILE*
65tr_getLog( void )
66{
67    static int initialized = FALSE;
68    static FILE * file= NULL;
69
70    if( !initialized )
71    {
72        const char * str = getenv( "TR_DEBUG_FD" );
73        int fd;
74        if( str && *str )
75            fd = atoi( str );
76        switch( fd ) {
77            case 1: file = stdout; break;
78            case 2: file = stderr; break;
79            default: file = NULL; break;
80        }
81        initialized = TRUE;
82    }
83
84    return file;
85}
86
87char*
88tr_getLogTimeStr( char * buf, int buflen )
89{
90    char tmp[64];
91    time_t now;
92    struct tm now_tm;
93    struct timeval tv;
94    int milliseconds;
95
96    now = time( NULL );
97    gettimeofday( &tv, NULL );
98
99    localtime_r( &now, &now_tm );
100    strftime( tmp, sizeof(tmp), "%H:%M:%S", &now_tm );
101    milliseconds = (int)(tv.tv_usec / 1000);
102    snprintf( buf, buflen, "%s.%03d", tmp, milliseconds );
103
104    return buf;
105}
106
107void
108tr_setMessageLevel( int level )
109{
110    tr_msgInit();
111    tr_lockLock( messageLock );
112    messageLevel = MAX( 0, level );
113    tr_lockUnlock( messageLock );
114}
115
116int tr_getMessageLevel( void )
117{
118    int ret;
119
120    tr_msgInit();
121    tr_lockLock( messageLock );
122    ret = messageLevel;
123    tr_lockUnlock( messageLock );
124
125    return ret;
126}
127
128void tr_setMessageQueuing( int enabled )
129{
130    tr_msgInit();
131    tr_lockLock( messageLock );
132    messageQueuing = enabled;
133    tr_lockUnlock( messageLock );
134}
135
136tr_msg_list * tr_getQueuedMessages( void )
137{
138    tr_msg_list * ret;
139
140    assert( NULL != messageLock );
141    tr_lockLock( messageLock );
142    ret = messageQueue;
143    messageQueue = NULL;
144    messageQueueTail = &messageQueue;
145    tr_lockUnlock( messageLock );
146
147    return ret;
148}
149
150void tr_freeMessageList( tr_msg_list * list )
151{
152    tr_msg_list * next;
153
154    while( NULL != list )
155    {
156        next = list->next;
157        free( list->message );
158        free( list );
159        list = next;
160    }
161}
162
163void tr_msg( int level, const char * msg, ... )
164{
165    va_list       args1, args2;
166    tr_msg_list * newmsg;
167    int           len1, len2;
168    FILE        * fp;
169
170    assert( NULL != messageLock );
171    tr_lockLock( messageLock );
172
173    fp = tr_getLog( );
174
175    if( !messageLevel )
176    {
177        char * env;
178        env          = getenv( "TR_DEBUG" );
179        messageLevel = ( env ? atoi( env ) : 0 ) + 1;
180        messageLevel = MAX( 1, messageLevel );
181    }
182
183    if( messageLevel >= level )
184    {
185        va_start( args1, msg );
186        if( messageQueuing )
187        {
188            newmsg = calloc( 1, sizeof( *newmsg ) );
189            if( NULL != newmsg )
190            {
191                newmsg->level = level;
192                newmsg->when = time( NULL );
193                len1 = len2 = 0;
194                va_start( args2, msg );
195                tr_vsprintf( &newmsg->message, &len1, &len2, msg,
196                             args1, args2 );
197                va_end( args2 );
198                if( fp != NULL )
199                    fprintf( fp, "%s\n", newmsg->message );
200                if( NULL == newmsg->message )
201                {
202                    free( newmsg );
203                }
204                else
205                {
206                    *messageQueueTail = newmsg;
207                    messageQueueTail = &newmsg->next;
208                }
209            }
210        }
211        else
212        {
213            if( fp == NULL )
214                fp = stderr;
215            vfprintf( fp, msg, args1 );
216            fputc( '\n', fp );
217            fflush( fp );
218        }
219        va_end( args1 );
220    }
221
222    tr_lockUnlock( messageLock );
223}
224
225int tr_rand( int sup )
226{
227    static int init = 0;
228
229    assert( sup > 0 );
230
231    if( !init )
232    {
233        srand( tr_date() );
234        init = 1;
235    }
236    return rand() % sup;
237}
238
239/***
240****
241***/
242
243void
244tr_set_compare( const void * va, size_t aCount,
245                const void * vb, size_t bCount,
246                int compare( const void * a, const void * b ),
247                size_t elementSize,
248                tr_set_func in_a_cb,
249                tr_set_func in_b_cb,
250                tr_set_func in_both_cb,
251                void * userData )
252{
253    const uint8_t * a = (const uint8_t *) va;
254    const uint8_t * b = (const uint8_t *) vb;
255    const uint8_t * aend = a + elementSize*aCount;
256    const uint8_t * bend = b + elementSize*bCount;
257
258    while( a!=aend || b!=bend )
259    {
260        if( a==aend )
261        {
262            (*in_b_cb)( (void*)b, userData );
263            b += elementSize;
264        }
265        else if ( b==bend )
266        {
267            (*in_a_cb)( (void*)a, userData );
268            a += elementSize;
269        }
270        else
271        {
272            const int val = (*compare)( a, b );
273
274            if( !val )
275            {
276                (*in_both_cb)( (void*)a, userData );
277                a += elementSize;
278                b += elementSize;
279            }
280            else if( val < 0 )
281            {
282                (*in_a_cb)( (void*)a, userData );
283                a += elementSize;
284            }
285            else if( val > 0 )
286            {
287                (*in_b_cb)( (void*)b, userData );
288                b += elementSize;
289            }
290        }
291    }
292}
293
294/***
295****
296***/
297
298void * tr_memmem ( const void *vbig, size_t big_len,
299                   const void *vlittle, size_t little_len )
300{
301    const char *big = vbig;
302    const char *little = vlittle;
303    size_t ii, jj;
304
305    if( 0 == big_len || 0 == little_len )
306    {
307        return NULL;
308    }
309
310    for( ii = 0; ii + little_len <= big_len; ii++ )
311    {
312        for( jj = 0; jj < little_len; jj++ )
313        {
314            if( big[ii + jj] != little[jj] )
315            {
316                break;
317            }
318        }
319        if( jj == little_len )
320        {
321            return (char*)big + ii;
322        }
323    }
324
325    return NULL;
326}
327
328/**
329***
330**/
331
332int
333tr_compareUint16( uint16_t a, uint16_t b )
334{
335    if( a < b ) return -1;
336    if( a > b ) return 1;
337    return 0;
338}
339
340int
341tr_compareUint32( uint32_t a, uint32_t b )
342{
343    if( a < b ) return -1;
344    if( a > b ) return 1;
345    return 0;
346}
347
348/**
349***
350**/
351
352struct timeval
353timevalMsec( uint64_t milliseconds )
354{
355    struct timeval ret;
356    const uint64_t microseconds = milliseconds * 1000;
357    ret.tv_sec  = microseconds / 1000000;
358    ret.tv_usec = microseconds % 1000000;
359    return ret;
360}
361
362uint8_t *
363tr_loadFile( const char * path, size_t * size )
364{
365    uint8_t    * buf;
366    struct stat  sb;
367    FILE       * file;
368
369    /* try to stat the file */
370    errno = 0;
371    if( stat( path, &sb ) )
372    {
373        tr_err( "Couldn't get information for file \"%s\" %s", path, strerror(errno) );
374        return NULL;
375    }
376
377    if( ( sb.st_mode & S_IFMT ) != S_IFREG )
378    {
379        tr_err( "Not a regular file (%s)", path );
380        return NULL;
381    }
382
383    /* Load the torrent file into our buffer */
384    file = fopen( path, "rb" );
385    if( !file )
386    {
387        tr_err( "Couldn't open file \"%s\" %s", path, strerror(errno) );
388        return NULL;
389    }
390    buf = malloc( sb.st_size );
391    if( NULL == buf )
392    {
393        tr_err( "Couldn't allocate memory (%"PRIu64" bytes)",
394                ( uint64_t )sb.st_size );
395        fclose( file );
396    }
397    fseek( file, 0, SEEK_SET );
398    if( fread( buf, sb.st_size, 1, file ) != 1 )
399    {
400        tr_err( "Error reading \"%s\" %s", path, strerror(errno) );
401        free( buf );
402        fclose( file );
403        return NULL;
404    }
405    fclose( file );
406
407    *size = sb.st_size;
408
409    return buf;
410}
411
412int
413tr_mkdir( const char * path, int permissions
414#ifdef WIN32
415                                             UNUSED
416#endif
417                                                    )
418{
419#ifdef WIN32
420    return mkdir( path );
421#else
422    return mkdir( path, permissions );
423#endif
424}
425
426int
427tr_mkdirp( const char * path_in, int permissions )
428{
429    char * path = tr_strdup( path_in );
430    char * p, * pp;
431    struct stat sb;
432    int done;
433
434    /* walk past the root */
435    p = path;
436    while( *p == TR_PATH_DELIMITER )
437        ++p;
438
439    pp = p;
440    done = 0;
441    while( ( p = strchr( pp, TR_PATH_DELIMITER ) ) || ( p = strchr( pp, '\0' ) ) )
442    {
443        if( !*p )
444            done = 1;
445        else
446            *p = '\0';
447
448        if( stat( path, &sb ) )
449        {
450            /* Folder doesn't exist yet */
451            if( tr_mkdir( path, permissions ) )
452            {
453                tr_err( "Could not create directory %s (%s)", path,
454                        strerror( errno ) );
455                tr_free( path );
456                return 1;
457            }
458        }
459        else if( ( sb.st_mode & S_IFMT ) != S_IFDIR )
460        {
461            /* Node exists but isn't a folder */
462            tr_err( "Remove %s, it's in the way.", path );
463            tr_free( path );
464            return 1;
465        }
466
467        if( done )
468            break;
469
470        *p = TR_PATH_DELIMITER;
471        p++;
472        pp = p;
473    }
474
475    tr_free( path );
476    return 0;
477}
478
479int
480tr_strncasecmp( const char * s1, const char * s2, size_t n )
481{
482    if ( !n )
483        return 0;
484
485    while( n-- != 0 && tolower( *s1 ) == tolower( *s2 ) ) {
486        if( !n || !*s1 || !*s2 )
487            break;
488        ++s1;
489        ++s2;
490    }
491
492    return tolower(*(unsigned char *) s1) - tolower(*(unsigned char *) s2);
493}
494
495int tr_sprintf( char ** buf, int * used, int * max, const char * format, ... )
496{
497    va_list ap1, ap2;
498    int     ret;
499
500    va_start( ap1, format );
501    va_start( ap2, format );
502    ret = tr_vsprintf( buf, used, max, format, ap1, ap2 );
503    va_end( ap2 );
504    va_end( ap1 );
505
506    return ret;
507}
508
509int tr_vsprintf( char ** buf, int * used, int * max, const char * fmt,
510                 va_list ap1, va_list ap2 )
511{
512    int     want;
513
514    want = vsnprintf( NULL, 0, fmt, ap1 );
515
516    if( tr_concat( buf, used, max, NULL, want ) )
517    {
518        return 1;
519    }
520    assert( *used + want + 1 <= *max );
521
522    *used += vsnprintf( *buf + *used, *max - *used, fmt, ap2 );
523
524    return 0;
525}
526
527#ifndef HAVE_ASPRINTF
528
529int
530asprintf( char ** buf, const char * format, ... )
531{
532    va_list ap;
533    int     ret;
534
535    va_start( ap, format );
536    ret = vasprintf( buf, format, ap );
537    va_end( ap );
538
539    return ret;
540}
541
542int
543vasprintf( char ** buf, const char * format, va_list ap )
544{
545    va_list ap2;
546    int     used, max;
547
548    va_copy( ap2, ap );
549
550    *buf = NULL;
551    used = 0;
552    max  = 0;
553
554    if( tr_vsprintf( buf, &used, &max, format, ap, ap2 ) )
555    {
556        free( *buf );
557        return -1;
558    }
559
560    return used;
561}
562
563#endif /* HAVE_ASPRINTF */
564
565int tr_concat( char ** buf, int * used, int * max, const char * data, int len )
566{
567    int     newmax;
568    char  * newbuf;
569
570    newmax = *max;
571    while( *used + len + 1 > newmax )
572    {
573        newmax += SPRINTF_BUFSIZE;
574    }
575    if( newmax > *max )
576    {
577        newbuf = realloc( *buf, newmax );
578        if( NULL == newbuf )
579        {
580            return 1;
581        }
582        *buf = newbuf;
583        *max = newmax;
584    }
585
586    if( NULL != data )
587    {
588        memcpy( *buf + *used, data, len );
589        *used += len;
590    }
591
592    return 0;
593}
594
595void
596tr_buildPath ( char *buf, size_t buflen, const char *first_element, ... )
597{
598    va_list vl;
599    char* walk = buf;
600    const char * element = first_element;
601
602    if( first_element == NULL )
603        return;
604
605    va_start( vl, first_element );
606    for( ;; ) {
607        const size_t n = strlen( element );
608        memcpy( walk, element, n );
609        walk += n;
610        element = (const char*) va_arg( vl, const char* );
611        if( element == NULL )
612            break;
613        *walk++ = TR_PATH_DELIMITER;
614    }
615    *walk = '\0';
616    assert( walk-buf <= (int)buflen );
617}
618
619int
620tr_ioErrorFromErrno( void )
621{
622    switch( errno )
623    {
624        case EACCES:
625        case EROFS:
626            return TR_ERROR_IO_PERMISSIONS;
627        case ENOSPC:
628            return TR_ERROR_IO_SPACE;
629        case EMFILE:
630            return TR_ERROR_IO_OPEN_FILES;
631        case EFBIG:
632            return TR_ERROR_IO_FILE_TOO_BIG;
633        default:
634            tr_dbg( "generic i/o errno from errno: %s", strerror( errno ) );
635            return TR_ERROR_IO_OTHER;
636    }
637}
638
639char *
640tr_errorString( int code )
641{
642    switch( code )
643    {
644        case TR_OK:
645            return "No error";
646        case TR_ERROR:
647            return "Generic error";
648        case TR_ERROR_ASSERT:
649            return "Assert error";
650        case TR_ERROR_IO_PERMISSIONS:
651            return "Insufficient permissions";
652        case TR_ERROR_IO_SPACE:
653            return "Insufficient free space";
654        case TR_ERROR_IO_DUP_DOWNLOAD:
655            return "Already active transfer with same name and download folder";
656        case TR_ERROR_IO_FILE_TOO_BIG:
657            return "File too large";
658        case TR_ERROR_IO_OPEN_FILES:
659            return "Too many open files";
660        case TR_ERROR_IO_OTHER:
661            return "Generic I/O error";
662    }
663    return "Unknown error";
664}
665
666/****
667*****
668****/
669
670char*
671tr_strdup( const char * in )
672{
673    return tr_strndup( in, in ? strlen(in) : 0 );
674}
675
676char*
677tr_strndup( const char * in, int len )
678{
679    char * out = NULL;
680
681    if( len < 0 )
682    {
683        out = tr_strdup( in );
684    }
685    else if( in != NULL )
686    {
687        out = tr_malloc( len+1 );
688        memcpy( out, in, len );
689        out[len] = '\0';
690    }
691    return out;
692}
693
694void*
695tr_calloc( size_t nmemb, size_t size )
696{
697    return nmemb && size ? calloc( nmemb, size ) : NULL;
698}
699
700void*
701tr_malloc( size_t size )
702{
703    return size ? malloc( size ) : NULL;
704}
705
706void*
707tr_malloc0( size_t size )
708{
709    void * ret = tr_malloc( size );
710    memset( ret, 0, size );
711    return ret;
712}
713
714void
715tr_free( void * p )
716{
717    if( p )
718        free( p );
719}
720
721/****
722*****
723****/
724
725/* note that the argument is how many bits are needed, not bytes */
726tr_bitfield*
727tr_bitfieldNew( size_t bitcount )
728{
729    tr_bitfield * ret = calloc( 1, sizeof(tr_bitfield) );
730    if( NULL == ret )
731        return NULL;
732
733    ret->len = (bitcount+7u) / 8u;
734    ret->bits = calloc( ret->len, 1 );
735    if( NULL == ret->bits ) {
736        free( ret );
737        return NULL;
738    }
739
740    return ret;
741}
742
743tr_bitfield*
744tr_bitfieldDup( const tr_bitfield * in )
745{
746    tr_bitfield * ret = calloc( 1, sizeof(tr_bitfield) );
747    ret->len = in->len;
748    ret->bits = malloc( ret->len );
749    memcpy( ret->bits, in->bits, ret->len );
750    return ret;
751}
752
753void tr_bitfieldFree( tr_bitfield * bitfield )
754{
755    if( bitfield )
756    {
757        free( bitfield->bits );
758        free( bitfield );
759    }
760}
761
762void
763tr_bitfieldClear( tr_bitfield * bitfield )
764{
765    memset( bitfield->bits, 0, bitfield->len );
766}
767
768int
769tr_bitfieldIsEmpty( const tr_bitfield * bitfield )
770{
771    unsigned int i;
772
773    for( i=0; i<bitfield->len; ++i )
774        if( bitfield->bits[i] )
775            return 0;
776
777    return 1;
778}
779
780int
781tr_bitfieldHas( const tr_bitfield * bitfield, size_t nth )
782{
783    static const uint8_t ands[8] = { 128, 64, 32, 16, 8, 4, 2, 1 };
784    return bitfield!=NULL && (bitfield->bits[nth>>3u] & ands[nth&7u] );
785}
786
787void
788tr_bitfieldAdd( tr_bitfield  * bitfield, size_t nth )
789{
790    static const uint8_t ands[8] = { 128, 64, 32, 16, 8, 4, 2, 1 };
791    bitfield->bits[nth>>3u] |= ands[nth&7u];
792    assert( tr_bitfieldHas( bitfield, nth ) );
793}
794
795void
796tr_bitfieldAddRange( tr_bitfield  * bitfield,
797                     size_t         begin,
798                     size_t         end )
799{
800    /* TODO: there are faster ways to do this */
801    unsigned int i;
802    for( i=begin; i<end; ++i )
803        tr_bitfieldAdd( bitfield, i );
804}
805
806void
807tr_bitfieldRem( tr_bitfield   * bitfield,
808                size_t          nth )
809{
810    static const uint8_t rems[8] = { 127, 191, 223, 239, 247, 251, 253, 254 };
811
812    if( bitfield != NULL )
813        bitfield->bits[nth>>3u] &= rems[nth&7u];
814
815    assert( !tr_bitfieldHas( bitfield, nth ) );
816}
817
818void
819tr_bitfieldRemRange ( tr_bitfield  * b,
820                      size_t         begin,
821                      size_t         end )
822{
823    /* TODO: there are faster ways to do this */
824    unsigned int i;
825    for( i=begin; i<end; ++i )
826        tr_bitfieldRem( b, i );
827}
828
829tr_bitfield*
830tr_bitfieldOr( tr_bitfield * a, const tr_bitfield * b )
831{
832    uint8_t *ait;
833    const uint8_t *aend, *bit;
834
835    assert( a->len == b->len );
836
837    for( ait=a->bits, bit=b->bits, aend=ait+a->len; ait!=aend; ++ait, ++bit )
838        *ait |= *bit;
839
840    return a;
841}
842
843size_t
844tr_bitfieldCountTrueBits( const tr_bitfield* b )
845{
846    size_t ret = 0;
847    const uint8_t *it, *end;
848    static const int trueBitCount[512] = {
849        0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
850        1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
851        1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
852        2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
853        1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
854        2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
855        2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
856        3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
857        1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
858        2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
859        2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
860        3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
861        2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
862        3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
863        3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
864        4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9
865    };
866
867    if( !b )
868        return 0;
869
870    for( it=b->bits, end=it+b->len; it!=end; ++it )
871        ret += trueBitCount[*it];
872
873    return ret;
874}
875
876/***
877****
878***/
879
880uint64_t
881tr_date( void )
882{
883    struct timeval tv;
884    gettimeofday( &tv, NULL );
885    return (uint64_t) tv.tv_sec * 1000 + ( tv.tv_usec / 1000 );
886}
887
888void
889tr_wait( uint64_t delay_milliseconds )
890{
891#ifdef __BEOS__
892    snooze( 1000 * delay_milliseconds );
893#elif defined(WIN32)
894    Sleep( (DWORD)delay_milliseconds );
895#else
896    usleep( 1000 * delay_milliseconds );
897#endif
898}
899
900/***
901****
902***/
903
904
905#ifndef HAVE_STRLCPY
906
907/*
908 * Copy src to string dst of size siz.  At most siz-1 characters
909 * will be copied.  Always NUL terminates (unless siz == 0).
910 * Returns strlen(src); if retval >= siz, truncation occurred.
911 */
912size_t
913strlcpy(char *dst, const char *src, size_t siz)
914{
915        char *d = dst;
916        const char *s = src;
917        size_t n = siz;
918
919        /* Copy as many bytes as will fit */
920        if (n != 0) {
921                while (--n != 0) {
922                        if ((*d++ = *s++) == '\0')
923                                break;
924                }
925        }
926
927        /* Not enough room in dst, add NUL and traverse rest of src */
928        if (n == 0) {
929                if (siz != 0)
930                        *d = '\0';              /* NUL-terminate dst */
931                while (*s++)
932                        ;
933        }
934
935        return(s - src - 1);    /* count does not include NUL */
936}
937
938#endif /* HAVE_STRLCPY */
939
940
941#ifndef HAVE_STRLCAT
942
943/*
944 * Appends src to string dst of size siz (unlike strncat, siz is the
945 * full size of dst, not space left).  At most siz-1 characters
946 * will be copied.  Always NUL terminates (unless siz <= strlen(dst)).
947 * Returns strlen(src) + MIN(siz, strlen(initial dst)).
948 * If retval >= siz, truncation occurred.
949 */
950size_t
951strlcat(char *dst, const char *src, size_t siz)
952{
953        char *d = dst;
954        const char *s = src;
955        size_t n = siz;
956        size_t dlen;
957
958        /* Find the end of dst and adjust bytes left but don't go past end */
959        while (n-- != 0 && *d != '\0')
960                d++;
961        dlen = d - dst;
962        n = siz - dlen;
963
964        if (n == 0)
965                return(dlen + strlen(s));
966        while (*s != '\0') {
967                if (n != 1) {
968                        *d++ = *s;
969                        n--;
970                }
971                s++;
972        }
973        *d = '\0';
974
975        return(dlen + (s - src));       /* count does not include NUL */
976}
977
978#endif /* HAVE_STRLCAT */
Note: See TracBrowser for help on using the repository browser.