source: trunk/libtransmission/utils.h @ 11209

Last change on this file since 11209 was 11209, checked in by Longinus00, 12 years ago

switch trackerRemove and trackerReplace rpc calls to use tracker id instead of announce urls as identifiers

  • Property svn:keywords set to Date Rev Author Id
File size: 19.2 KB
Line 
1/*
2 * This file Copyright (C) 2009-2010 Mnemosyne LLC
3 *
4 * This file is licensed by the GPL version 2.  Works owned by the
5 * Transmission project are granted a special exemption to clause 2(b)
6 * so that the bulk of its code can remain under the MIT license.
7 * This exemption does not extend to derived works not owned by
8 * the Transmission project.
9 *
10 * $Id: utils.h 11209 2010-09-14 06:23:48Z Longinus00 $
11 */
12
13#ifndef TR_UTILS_H
14#define TR_UTILS_H 1
15
16#include <inttypes.h>
17#include <stddef.h> /* size_t */
18#include <stdio.h> /* FILE* */
19#include <string.h> /* memcpy()* */
20#include <stdlib.h> /* malloc() */
21#include <time.h> /* time_t */
22
23#ifdef __cplusplus
24extern "C" {
25#endif
26
27/***
28****
29***/
30
31/**
32 * @addtogroup utils Utilities
33 * @{
34 */
35
36#ifndef FALSE
37 #define FALSE 0
38#endif
39
40#ifndef TRUE
41 #define TRUE 1
42#endif
43
44#ifndef UNUSED
45 #ifdef __GNUC__
46  #define UNUSED __attribute__ ( ( unused ) )
47 #else
48  #define UNUSED
49 #endif
50#endif
51
52#ifndef TR_GNUC_PRINTF
53 #ifdef __GNUC__
54  #define TR_GNUC_PRINTF( fmt, args ) __attribute__ ( ( format ( printf, fmt, args ) ) )
55 #else
56  #define TR_GNUC_PRINTF( fmt, args )
57 #endif
58#endif
59
60#ifndef TR_GNUC_NONNULL
61 #ifdef __GNUC__
62  #define TR_GNUC_NONNULL( ... ) __attribute__((nonnull (__VA_ARGS__)))
63 #else
64  #define TR_GNUC_NONNULL( ... )
65 #endif
66#endif
67
68#ifndef TR_GNUC_NULL_TERMINATED
69 #if __GNUC__ > 4 || ( __GNUC__ == 4 && __GNUC_MINOR__ >= 3 )
70  #define TR_GNUC_NULL_TERMINATED __attribute__ ( ( __sentinel__ ) )
71  #define TR_GNUC_HOT __attribute ( ( hot ) )
72 #else
73  #define TR_GNUC_NULL_TERMINATED
74  #define TR_GNUC_HOT
75 #endif
76#endif
77
78#if __GNUC__ > 2 || ( __GNUC__ == 2 && __GNUC_MINOR__ >= 96 )
79 #define TR_GNUC_PURE __attribute__ ( ( __pure__ ) )
80 #define TR_GNUC_MALLOC __attribute__ ( ( __malloc__ ) )
81#else
82 #define TR_GNUC_PURE
83 #define TR_GNUC_MALLOC
84#endif
85
86
87/***
88****
89***/
90
91const char * tr_strip_positional_args( const char * fmt );
92
93#if !defined( _ )
94 #if defined( HAVE_LIBINTL_H ) && !defined( SYS_DARWIN )
95  #include <libintl.h>
96  #define _( a ) gettext ( a )
97 #else
98  #define _( a ) ( a )
99 #endif
100#endif
101
102/* #define DISABLE_GETTEXT */
103#ifndef DISABLE_GETTEXT
104 #if defined(WIN32) || defined(TR_EMBEDDED)
105   #define DISABLE_GETTEXT
106 #endif
107#endif
108#ifdef DISABLE_GETTEXT
109 #undef _
110 #define _( a ) tr_strip_positional_args( a )
111#endif
112
113/****
114*****
115****/
116
117void tr_msgInit( void );
118
119#define TR_MAX_MSG_LOG 10000
120
121extern tr_msg_level messageLevel;
122
123static inline tr_bool tr_msgLoggingIsActive( tr_msg_level level )
124{
125    return messageLevel >= level;
126}
127
128void tr_msg( const char * file, int line,
129             tr_msg_level level,
130             const char * torrent,
131             const char * fmt, ... ) TR_GNUC_PRINTF( 5, 6 );
132
133#define tr_nerr( n, ... ) \
134    do { \
135        if( tr_msgLoggingIsActive( TR_MSG_ERR ) ) \
136            tr_msg( __FILE__, __LINE__, TR_MSG_ERR, n, __VA_ARGS__ ); \
137    } while( 0 )
138
139#define tr_ninf( n, ... ) \
140    do { \
141        if( tr_msgLoggingIsActive( TR_MSG_INF) ) \
142            tr_msg( __FILE__, __LINE__, TR_MSG_INF, n, __VA_ARGS__ ); \
143    } while( 0 )
144
145#define tr_ndbg( n, ... ) \
146    do { \
147        if( tr_msgLoggingIsActive( TR_MSG_DBG) ) \
148            tr_msg( __FILE__, __LINE__, TR_MSG_DBG, n, __VA_ARGS__ ); \
149    } while( 0 )
150
151#define tr_torerr( tor, ... ) \
152    do { \
153        if( tr_msgLoggingIsActive( TR_MSG_ERR ) ) \
154            tr_msg( __FILE__, __LINE__, TR_MSG_ERR, tor->info.name, __VA_ARGS__ ); \
155    } while( 0 )
156
157#define tr_torinf( tor, ... ) \
158    do { \
159        if( tr_msgLoggingIsActive( TR_MSG_INF ) ) \
160            tr_msg( __FILE__, __LINE__, TR_MSG_INF, tor->info.name, __VA_ARGS__ ); \
161    } while( 0 )
162
163#define tr_tordbg( tor, ... ) \
164    do { \
165        if( tr_msgLoggingIsActive( TR_MSG_DBG ) ) \
166            tr_msg( __FILE__, __LINE__, TR_MSG_DBG, tor->info.name, __VA_ARGS__ ); \
167    } while( 0 )
168
169#define tr_err( ... ) \
170    do { \
171        if( tr_msgLoggingIsActive( TR_MSG_ERR ) ) \
172            tr_msg( __FILE__, __LINE__, TR_MSG_ERR, NULL, __VA_ARGS__ ); \
173    } while( 0 )
174
175#define tr_inf( ... ) \
176    do { \
177        if( tr_msgLoggingIsActive( TR_MSG_INF ) ) \
178            tr_msg( __FILE__, __LINE__, TR_MSG_INF, NULL, __VA_ARGS__ ); \
179    } while( 0 )
180
181#define tr_dbg( ... ) \
182    do { \
183        if( tr_msgLoggingIsActive( TR_MSG_DBG ) ) \
184            tr_msg( __FILE__, __LINE__, TR_MSG_DBG, NULL, __VA_ARGS__ ); \
185    } while( 0 )
186
187
188
189FILE*          tr_getLog( void );
190
191/** @brief return true if deep logging has been enabled by the user; false otherwise */
192tr_bool tr_deepLoggingIsActive( void );
193
194void           tr_deepLog( const char * file,
195                           int          line,
196                           const char * name,
197                           const char * fmt,
198                           ... ) TR_GNUC_PRINTF( 4, 5 ) TR_GNUC_NONNULL(1,4);
199
200/** @brief set the buffer with the current time formatted for deep logging. */
201char* tr_getLogTimeStr( char * buf, int buflen ) TR_GNUC_NONNULL(1);
202
203
204/**
205 * @brief Rich Salz's classic implementation of shell-style pattern matching for ?, \, [], and * characters.
206 * @return 1 if the pattern matches, 0 if it doesn't, or -1 if an error occured
207 */
208int tr_wildmat( const char * text, const char * pattern ) TR_GNUC_NONNULL(1,2);
209
210/** @brief Portability wrapper for basename() that uses the system implementation if available */
211char* tr_basename( const char * path ) TR_GNUC_MALLOC;
212
213/** @brief Portability wrapper for dirname() that uses the system implementation if available */
214char* tr_dirname( const char * path ) TR_GNUC_MALLOC;
215
216/**
217 * @brief Portability wrapper for mkdir()
218 *
219 * A portability wrapper around mkdir().
220 * On WIN32, the `permissions' argument is unused.
221 *
222 * @return zero on success, or -1 if an error occurred
223 * (in which case errno is set appropriately).
224 */
225int tr_mkdir( const char * path, int permissions ) TR_GNUC_NONNULL(1);
226
227/**
228 * Like mkdir, but makes parent directories as needed.
229 *
230 * @return zero on success, or -1 if an error occurred
231 * (in which case errno is set appropriately).
232 */
233int tr_mkdirp( const char * path, int permissions ) TR_GNUC_NONNULL(1);
234
235
236/**
237 * @brief Loads a file and returns its contents.
238 * On failure, NULL is returned and errno is set.
239 */
240uint8_t* tr_loadFile( const char * filename, size_t * size ) TR_GNUC_MALLOC
241                                                             TR_GNUC_NONNULL(1);
242
243
244/** @brief build a filename from a series of elements using the
245           platform's correct directory separator. */
246char* tr_buildPath( const char * first_element, ... ) TR_GNUC_NULL_TERMINATED
247                                                      TR_GNUC_MALLOC;
248
249struct event;
250
251/**
252 * @brief Convenience wrapper around timer_add() to have a timer wake up in a number of seconds and microseconds
253 * @param timer
254 * @param seconds
255 * @param microseconds
256 */
257void tr_timerAdd( struct event * timer, int seconds, int microseconds ) TR_GNUC_NONNULL(1);
258
259/**
260 * @brief Convenience wrapper around timer_add() to have a timer wake up in a number of milliseconds
261 * @param timer
262 * @param milliseconds
263 */
264void tr_timerAddMsec( struct event * timer, int milliseconds ) TR_GNUC_NONNULL(1);
265
266
267/** @brief return the current date in milliseconds */
268uint64_t tr_time_msec( void );
269
270/** @brief sleep the specified number of milliseconds */
271void tr_wait_msec( long int delay_milliseconds );
272
273/**
274 * @brief make a copy of 'str' whose non-utf8 content has been corrected or stripped
275 * @return a newly-allocated string that must be freed with tr_free()
276 * @param str the string to make a clean copy of
277 * @param len the length of the string to copy.  If -1, the entire string is used.
278 */
279char* tr_utf8clean( const char * str, int len ) TR_GNUC_MALLOC;
280
281
282/***
283****
284***/
285
286/* Sometimes the system defines MAX/MIN, sometimes not.
287   In the latter case, define those here since we will use them */
288#ifndef MAX
289 #define MAX( a, b ) ( ( a ) > ( b ) ? ( a ) : ( b ) )
290#endif
291#ifndef MIN
292 #define MIN( a, b ) ( ( a ) > ( b ) ? ( b ) : ( a ) )
293#endif
294
295/***
296****
297***/
298
299/** @brief Portability wrapper around malloc() in which `0' is a safe argument */
300static inline void* tr_malloc( size_t size )
301{
302    return size ? malloc( size ) : NULL;
303}
304
305/** @brief Portability wrapper around calloc() in which `0' is a safe argument */
306static inline void* tr_malloc0( size_t size )
307{
308    return size ? calloc( 1, size ) : NULL;
309}
310
311/** @brief Portability wrapper around free() in which `NULL' is a safe argument */
312static inline void tr_free( void * p )
313{
314    if( p != NULL )
315        free( p );
316}
317
318/**
319 * @brief make a newly-allocated copy of a chunk of memory
320 * @param src the memory to copy
321 * @param byteCount the number of bytes to copy
322 * @return a newly-allocated copy of `src' that can be freed with tr_free()
323 */
324static inline void* tr_memdup( const void * src, size_t byteCount )
325{
326    return memcpy( tr_malloc( byteCount ), src, byteCount );
327}
328
329#define tr_new( struct_type, n_structs )           \
330    ( (struct_type *) tr_malloc ( ( (size_t) sizeof ( struct_type ) ) * ( ( size_t) ( n_structs ) ) ) )
331
332#define tr_new0( struct_type, n_structs )          \
333    ( (struct_type *) tr_malloc0 ( ( (size_t) sizeof ( struct_type ) ) * ( ( size_t) ( n_structs ) ) ) )
334
335#define tr_renew( struct_type, mem, n_structs )    \
336    ( (struct_type *) realloc ( ( mem ), ( (size_t) sizeof ( struct_type ) ) * ( ( size_t) ( n_structs ) ) ) )
337
338void* tr_valloc( size_t bufLen );
339
340/**
341 * @brief make a newly-allocated copy of a substring
342 * @param in is a void* so that callers can pass in both signed & unsigned without a cast
343 * @param len length of the substring to copy.  if a length less than zero is passed in, strlen( len ) is used
344 * @return a newly-allocated copy of `in' that can be freed with tr_free()
345 */
346char* tr_strndup( const void * in, int len ) TR_GNUC_MALLOC;
347
348/**
349 * @brief make a newly-allocated copy of a string
350 * @param in is a void* so that callers can pass in both signed & unsigned without a cast
351 * @return a newly-allocated copy of `in' that can be freed with tr_free()
352 */
353static inline char* tr_strdup( const void * in )
354{
355    return tr_strndup( in, in ? (int)strlen((const char *)in) : 0 );
356}
357
358/** @brief similar to bsearch() but returns the index of the lower bound */
359int tr_lowerBound( const void * key,
360                   const void * base,
361                   size_t       nmemb,
362                   size_t       size,
363                   int       (* compar)(const void* key, const void* arrayMember),
364                   tr_bool    * exact_match ) TR_GNUC_HOT TR_GNUC_NONNULL(1,5,6);
365
366
367/**
368 * @brief sprintf() a string into a newly-allocated buffer large enough to hold it
369 * @return a newly-allocated string that can be freed with tr_free()
370 */
371char* tr_strdup_printf( const char * fmt, ... ) TR_GNUC_PRINTF( 1, 2 )
372                                                TR_GNUC_MALLOC;
373
374/**
375 * @brief Translate a block of bytes into base64
376 * @return a newly-allocated string that can be freed with tr_free()
377 */
378char* tr_base64_encode( const void * input,
379                        int          inlen,
380                        int        * outlen ) TR_GNUC_MALLOC;
381
382/**
383 * @brief Translate a block of bytes from base64 into raw form
384 * @return a newly-allocated string that can be freed with tr_free()
385 */
386char* tr_base64_decode( const void * input,
387                        int          inlen,
388                        int        * outlen ) TR_GNUC_MALLOC;
389
390/** @brief Portability wrapper for strlcpy() that uses the system implementation if available */
391size_t tr_strlcpy( char * dst, const void * src, size_t siz );
392
393/** @brief Portability wrapper for snprintf() that uses the system implementation if available */
394int tr_snprintf( char * buf, size_t buflen,
395                 const char * fmt, ... ) TR_GNUC_PRINTF( 3, 4 ) TR_GNUC_NONNULL(1,3);
396
397/** @brief Convenience wrapper around strerorr() guaranteed to not return NULL
398    @param errno */
399const char* tr_strerror( int );
400
401/** @brief strips leading and trailing whitspace from a string
402    @return the stripped string */
403char* tr_strstrip( char * str );
404
405/** @brief Returns true if the string ends with the specified case-insensitive suffix */
406tr_bool tr_str_has_suffix( const char *str, const char *suffix );
407
408
409/** @brief Portability wrapper for memmem() that uses the system implementation if available */
410const char* tr_memmem( const char * haystack, size_t haystack_len,
411                       const char * needle, size_t needle_len );
412
413/***
414****
415***/
416
417typedef void ( tr_set_func )( void * element, void * userData );
418
419/**
420 * @brief find the differences and commonalities in two sorted sets
421 * @param a the first set
422 * @param aCount the number of elements in the set 'a'
423 * @param b the second set
424 * @param bCount the number of elements in the set 'b'
425 * @param compare the sorting method for both sets
426 * @param elementSize the sizeof the element in the two sorted sets
427 * @param in_a called for items in set 'a' but not set 'b'
428 * @param in_b called for items in set 'b' but not set 'a'
429 * @param in_both called for items that are in both sets
430 * @param userData user data passed along to in_a, in_b, and in_both
431 */
432void tr_set_compare( const void * a, size_t aCount,
433                     const void * b, size_t bCount,
434                     int compare( const void * a, const void * b ),
435                     size_t elementSize,
436                     tr_set_func in_a_cb,
437                     tr_set_func in_b_cb,
438                     tr_set_func in_both_cb,
439                     void * userData );
440
441int compareInt( const void * va, const void * vb );
442
443void tr_sha1_to_hex( char * out, const uint8_t * sha1 ) TR_GNUC_NONNULL(1,2);
444
445void tr_hex_to_sha1( uint8_t * out, const char * hex ) TR_GNUC_NONNULL(1,2);
446
447/** @brief convenience function to determine if an address is an IP address (IPv4 or IPv6) */
448tr_bool tr_addressIsIP( const char * address );
449
450/** @brief return TRUE if the url is a http or https url that Transmission understands */
451tr_bool tr_urlIsValidTracker( const char * url ) TR_GNUC_NONNULL(1);
452
453/** @brief return TRUE if the url is a [ http, https, ftp, ftps ] url that Transmission understands */
454tr_bool tr_urlIsValid( const char * url, int url_len ) TR_GNUC_NONNULL(1);
455
456/** @brief parse a URL into its component parts
457    @return zero on success or an error number if an error occurred */
458int  tr_urlParse( const char * url,
459                  int          url_len,
460                  char      ** setme_scheme,
461                  char      ** setme_host,
462                  int        * setme_port,
463                  char      ** setme_path ) TR_GNUC_NONNULL(1);
464
465
466/** @brief return TR_RATIO_NA, TR_RATIO_INF, or a number in [0..1]
467    @return TR_RATIO_NA, TR_RATIO_INF, or a number in [0..1] */
468double tr_getRatio( uint64_t numerator, uint64_t denominator );
469
470/**
471 * @brief Given a string like "1-4" or "1-4,6,9,14-51", this returns a
472 *        newly-allocated array of all the integers in the set.
473 * @return a newly-allocated array of integers that must be freed with tr_free(),
474 *         or NULL if a fragment of the string can't be parsed.
475 *
476 * For example, "5-8" will return [ 5, 6, 7, 8 ] and setmeCount will be 4.
477 */
478int* tr_parseNumberRange( const char * str,
479                          int str_len,
480                          int * setmeCount ) TR_GNUC_MALLOC TR_GNUC_NONNULL(1);
481
482
483/**
484 * @brief truncate a double value at a given number of decimal places.
485 *
486 * this can be used to prevent a printf() call from rounding up:
487 * call with the decimal_places argument equal to the number of
488 * decimal places in the printf()'s precision:
489 *
490 * - printf("%.2f%%",           99.999    ) ==> "100.00%"
491 *
492 * - printf("%.2f%%", tr_truncd(99.999, 2)) ==>  "99.99%"
493 *             ^                        ^
494 *             |   These should match   |
495 *             +------------------------+
496 */
497double tr_truncd( double x, int decimal_places );
498
499/* return a percent formatted string of either x.xx, xx.x or xxx */
500char* tr_strpercent( char * buf, double x, size_t buflen );
501
502/**
503 * @param buf the buffer to write the string to
504 * @param buflef buf's size
505 * @param ratio the ratio to convert to a string
506 * @param the string represntation of "infinity"
507 */
508char* tr_strratio( char * buf, size_t buflen, double ratio, const char * infinity ) TR_GNUC_NONNULL(1,4);
509
510/* return a truncated double as a string */
511char* tr_strtruncd( char * buf, double x, int precision, size_t buflen );
512
513/** @brief Portability wrapper for localtime_r() that uses the system implementation if available */
514struct tm * tr_localtime_r( const time_t *_clock, struct tm *_result );
515
516
517/**
518 * @brief move a file
519 * @return 0 on success; otherwise, return -1 and set errno
520 */
521int tr_moveFile( const char * oldpath, const char * newpath,
522                 tr_bool * renamed ) TR_GNUC_NONNULL(1,2);
523
524/** @brief convenience function to remove an item from an array */
525static inline void tr_removeElementFromArray( void         * array,
526                                              unsigned int   index_to_remove,
527                                              size_t         sizeof_element,
528                                              size_t         nmemb )
529{
530    char * a = (char*) array;
531
532    memmove( a + sizeof_element * index_to_remove,
533             a + sizeof_element * ( index_to_remove  + 1 ),
534             sizeof_element * ( --nmemb - index_to_remove ) );
535}
536
537/***
538****
539***/
540
541/** @brief Private libtransmission variable that's visible only for inlining in tr_time() */
542extern time_t transmission_now;
543
544/**
545 * @brief very inexpensive form of time(NULL)
546 * @return the current epoch time in seconds
547 *
548 * This function returns a second counter that is updated once per second.
549 * If something blocks the libtransmission thread for more than a second,
550 * that counter may be thrown off, so this function is not guaranteed
551 * to always be accurate.  However, it is *much* faster when 100% accuracy
552 * isn't needed
553 */
554static inline time_t tr_time( void ) { return transmission_now; }
555
556/** @brief Private libtransmission function to update tr_time()'s counter */
557static inline void tr_timeUpdate( time_t now ) { transmission_now = now; }
558
559/** @brief Portability wrapper for realpath() that uses the system implementation if available */
560char* tr_realpath( const char *path, char * resolved_path );
561
562/***
563****
564***/
565
566/* example: tr_formatter_size_init( 1024, _("KiB"), _("MiB"), _("GiB"), _("TiB") ); */
567
568void tr_formatter_size_init( unsigned int kilo, const char * kb, const char * mb,
569                                                const char * gb, const char * tb );
570
571void tr_formatter_speed_init( unsigned int kilo, const char * kb, const char * mb,
572                                                 const char * gb, const char * tb );
573
574void tr_formatter_mem_init( unsigned int kilo, const char * kb, const char * mb,
575                                               const char * gb, const char * tb );
576
577extern unsigned int tr_speed_K;
578extern unsigned int tr_mem_K;
579extern unsigned int tr_size_K;
580
581/* format a speed from KBps into a user-readable string. */
582char* tr_formatter_speed_KBps( char * buf, double KBps, size_t buflen );
583
584/* format a memory size from bytes into a user-readable string. */
585char* tr_formatter_mem_B( char * buf, uint64_t bytes, size_t buflen );
586
587/* format a memory size from MB into a user-readable string. */
588static inline char* tr_formatter_mem_MB( char * buf, double MBps, size_t buflen ) { return tr_formatter_mem_B( buf, MBps * tr_mem_K * tr_mem_K, buflen ); }
589
590/* format a file size from bytes into a user-readable string. */
591char* tr_formatter_size_B( char * buf, uint64_t bytes, size_t buflen );
592
593
594/***
595****
596***/
597
598#ifdef __cplusplus
599}
600#endif
601
602/** @} */
603
604#endif
Note: See TracBrowser for help on using the repository browser.