]> git.sesse.net Git - vlc/blob - src/extras/libc.c
* src/extras/libc.c: shut up compiler warnings.
[vlc] / src / extras / libc.c
1 /*****************************************************************************
2  * libc.c: Extra libc function for some systems.
3  *****************************************************************************
4  * Copyright (C) 2002 VideoLAN
5  * $Id$
6  *
7  * Authors: Jon Lech Johansen <jon-vl@nanocrew.net>
8  *          Samuel Hocevar <sam@zoy.org>
9  *          Gildas Bazin <gbazin@videolan.org>
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
24  *****************************************************************************/
25 #include <string.h>                                              /* strdup() */
26 #include <stdlib.h>
27 #include <ctype.h>
28
29 #include <vlc/vlc.h>
30
31 #undef iconv_t
32 #undef iconv_open
33 #undef iconv
34 #undef iconv_close
35
36 #if defined(HAVE_ICONV)
37 #   include <iconv.h>
38 #endif
39
40 /*****************************************************************************
41  * getenv: just in case, but it should never be called
42  *****************************************************************************/
43 #if !defined( HAVE_GETENV )
44 char *vlc_getenv( const char *name )
45 {
46     return NULL;
47 }
48 #endif
49
50 /*****************************************************************************
51  * strdup: returns a malloc'd copy of a string
52  *****************************************************************************/
53 #if !defined( HAVE_STRDUP )
54 char *vlc_strdup( const char *string )
55 {
56     return strndup( string, strlen( string ) );
57 }
58 #endif
59
60 /*****************************************************************************
61  * strndup: returns a malloc'd copy of at most n bytes of string
62  * Does anyone know whether or not it will be present in Jaguar?
63  *****************************************************************************/
64 #if !defined( HAVE_STRNDUP )
65 char *vlc_strndup( const char *string, size_t n )
66 {
67     char *psz;
68     size_t len = strlen( string );
69
70     len = __MIN( len, n );
71     psz = (char*)malloc( len + 1 );
72
73     if( psz != NULL )
74     {
75         memcpy( (void*)psz, (const void*)string, len );
76         psz[ len ] = 0;
77     }
78
79     return psz;
80 }
81 #endif
82
83 /*****************************************************************************
84  * strcasecmp: compare two strings ignoring case
85  *****************************************************************************/
86 #if !defined( HAVE_STRCASECMP ) && !defined( HAVE_STRICMP )
87 int vlc_strcasecmp( const char *s1, const char *s2 )
88 {
89     int i_delta = 0;
90
91     while( !i_delta && *s1 && *s2 )
92     {
93         i_delta = *s1 - *s2;
94
95         if( *s1 >= 'A' && *s1 <= 'Z' )
96         {
97             i_delta -= 'A' - 'a';
98         }
99
100         if( *s2 >= 'A' && *s2 <= 'Z' )
101         {
102             i_delta += 'A' - 'a';
103         }
104
105         s1++; s2++;
106     }
107
108     return i_delta;
109 }
110 #endif
111
112 /*****************************************************************************
113  * strncasecmp: compare n chars from two strings ignoring case
114  *****************************************************************************/
115 #if !defined( HAVE_STRNCASECMP ) && !defined( HAVE_STRNICMP )
116 int vlc_strncasecmp( const char *s1, const char *s2, size_t n )
117 {
118     int i_delta = 0;
119
120     while( n-- && !i_delta && *s1 )
121     {
122         i_delta = *s1 - *s2;
123
124         if( *s1 >= 'A' && *s1 <= 'Z' )
125         {
126             i_delta -= 'A' - 'a';
127         }
128
129         if( *s2 >= 'A' && *s2 <= 'Z' )
130         {
131             i_delta += 'A' - 'a';
132         }
133
134         s1++; s2++;
135     }
136
137     return i_delta;
138 }
139 #endif
140
141 /******************************************************************************
142  * strcasestr: find a substring (little) in another substring (big)
143  * Case sensitive. Return NULL if not found, return big if little == null
144  *****************************************************************************/
145 #if !defined( HAVE_STRCASESTR ) && !defined( HAVE_STRISTR )
146 char * vlc_strcasestr( const char *psz_big, const char *psz_little )
147 {
148     char *p_pos = (char *)psz_big;
149
150     if( !psz_big || !psz_little || !*psz_little ) return p_pos;
151  
152     while( *p_pos ) 
153     {
154         if( toupper( *p_pos ) == toupper( *psz_little ) )
155         {
156             char * psz_cur1 = p_pos + 1;
157             char * psz_cur2 = (char *)psz_little + 1;
158             while( *psz_cur1 && *psz_cur2 &&
159                    toupper( *psz_cur1 ) == toupper( *psz_cur2 ) )
160             {
161                 psz_cur1++;
162                 psz_cur2++;
163             }
164             if( !*psz_cur2 ) return p_pos;
165         }
166         p_pos++;
167     }
168     return NULL;
169 }
170 #endif
171
172 /*****************************************************************************
173  * vasprintf:
174  *****************************************************************************/
175 #if !defined(HAVE_VASPRINTF) || defined(SYS_DARWIN) || defined(SYS_BEOS)
176 int vlc_vasprintf(char **strp, const char *fmt, va_list ap)
177 {
178     /* Guess we need no more than 100 bytes. */
179     int     i_size = 100;
180     char    *p = malloc( i_size );
181     int     n;
182
183     if( p == NULL )
184     {
185         *strp = NULL;
186         return -1;
187     }
188
189     for( ;; )
190     {
191         /* Try to print in the allocated space. */
192         n = vsnprintf( p, i_size, fmt, ap );
193
194         /* If that worked, return the string. */
195         if (n > -1 && n < i_size)
196         {
197             *strp = p;
198             return strlen( p );
199         }
200         /* Else try again with more space. */
201         if (n > -1)    /* glibc 2.1 */
202         {
203            i_size = n+1; /* precisely what is needed */
204         }
205         else           /* glibc 2.0 */
206         {
207            i_size *= 2;  /* twice the old size */
208         }
209         if( (p = realloc( p, i_size ) ) == NULL)
210         {
211             *strp = NULL;
212             return -1;
213         }
214     }
215 }
216 #endif
217
218 /*****************************************************************************
219  * asprintf:
220  *****************************************************************************/
221 #if !defined(HAVE_ASPRINTF) || defined(SYS_DARWIN) || defined(SYS_BEOS)
222 int vlc_asprintf( char **strp, const char *fmt, ... )
223 {
224     va_list args;
225     int i_ret;
226
227     va_start( args, fmt );
228     i_ret = vasprintf( strp, fmt, args );
229     va_end( args );
230
231     return i_ret;
232 }
233 #endif
234
235 /*****************************************************************************
236  * atof: convert a string to a double.
237  *****************************************************************************/
238 #if !defined( HAVE_ATOF )
239 double vlc_atof( const char *nptr )
240 {
241     double f_result;
242     wchar_t *psz_tmp;
243     int i_len = strlen( nptr ) + 1;
244
245     psz_tmp = malloc( i_len * sizeof(wchar_t) );
246     MultiByteToWideChar( CP_ACP, 0, nptr, -1, psz_tmp, i_len );
247     f_result = wcstod( psz_tmp, NULL );
248     free( psz_tmp );
249
250     return f_result;
251 }
252 #endif
253
254 /*****************************************************************************
255  * strtoll: convert a string to a 64 bits int.
256  *****************************************************************************/
257 #if !defined( HAVE_STRTOLL )
258 int64_t vlc_strtoll( const char *nptr, char **endptr, int base )
259 {
260     int64_t i_value = 0;
261     int sign = 1, newbase = base ? base : 10;
262
263     while( isspace(*nptr) ) nptr++;
264
265     if( *nptr == '-' )
266     {
267         sign = -1;
268         nptr++;
269     }
270
271     /* Try to detect base */
272     if( *nptr == '0' )
273     {
274         newbase = 8;
275         nptr++;
276
277         if( *nptr == 'x' )
278         {
279             newbase = 16;
280             nptr++;
281         }
282     }
283
284     if( base && newbase != base )
285     {
286         if( endptr ) *endptr = (char *)nptr;
287         return i_value;
288     }
289
290     switch( newbase )
291     {
292         case 10:
293             while( *nptr >= '0' && *nptr <= '9' )
294             {
295                 i_value *= 10;
296                 i_value += ( *nptr++ - '0' );
297             }
298             if( endptr ) *endptr = (char *)nptr;
299             break;
300
301         case 16:
302             while( (*nptr >= '0' && *nptr <= '9') ||
303                    (*nptr >= 'a' && *nptr <= 'f') ||
304                    (*nptr >= 'A' && *nptr <= 'F') )
305             {
306                 int i_valc = 0;
307                 if(*nptr >= '0' && *nptr <= '9') i_valc = *nptr - '0';
308                 else if(*nptr >= 'a' && *nptr <= 'f') i_valc = *nptr - 'a' +10;
309                 else if(*nptr >= 'A' && *nptr <= 'F') i_valc = *nptr - 'A' +10;
310                 i_value *= 16;
311                 i_value += i_valc;
312                 nptr++;
313             }
314             if( endptr ) *endptr = (char *)nptr;
315             break;
316
317         default:
318             i_value = strtol( nptr, endptr, newbase );
319             break;
320     }
321
322     return i_value * sign;
323 }
324 #endif
325
326 /*****************************************************************************
327  * atoll: convert a string to a 64 bits int.
328  *****************************************************************************/
329 #if !defined( HAVE_ATOLL )
330 int64_t vlc_atoll( const char *nptr )
331 {
332     return strtoll( nptr, (char **)NULL, 10 );
333 }
334 #endif
335
336 /*****************************************************************************
337  * lseek: reposition read/write file offset.
338  *****************************************************************************
339  * FIXME: this cast sucks!
340  *****************************************************************************/
341 #if !defined( HAVE_LSEEK )
342 off_t vlc_lseek( int fildes, off_t offset, int whence )
343 {
344     return SetFilePointer( (HANDLE)fildes, (long)offset, NULL, whence );
345 }
346 #endif
347
348 /*****************************************************************************
349  * dgettext: gettext for plugins.
350  *****************************************************************************/
351 char *vlc_dgettext( const char *package, const char *msgid )
352 {
353 #if defined( ENABLE_NLS ) \
354      && ( defined(HAVE_GETTEXT) || defined(HAVE_INCLUDED_GETTEXT) )
355     return dgettext( package, msgid );
356 #else
357     return (char *)msgid;
358 #endif
359 }
360
361 /*****************************************************************************
362  * count_utf8_string: returns the number of characters in the string.
363  *****************************************************************************/
364 static int count_utf8_string( const char *psz_string )
365 {
366     int i = 0, i_count = 0;
367     while( psz_string[ i ] != 0 )
368     {
369         if( ((unsigned char *)psz_string)[ i ] <  0x80UL ) i_count++;
370         i++;
371     }
372     return i_count;
373 }
374
375 /*****************************************************************************
376  * wraptext: inserts \n at convenient places to wrap the text.
377  *           Returns the modified string in a new buffer.
378  *****************************************************************************/
379 char *vlc_wraptext( const char *psz_text, int i_line, vlc_bool_t b_utf8 )
380 {
381     int i_len;
382     char *psz_line, *psz_new_text;
383
384     psz_line = psz_new_text = strdup( psz_text );
385
386     if( b_utf8 )
387         i_len = count_utf8_string( psz_text );
388     else
389         i_len = strlen( psz_text );
390
391     while( i_len > i_line )
392     {
393         /* Look if there is a newline somewhere. */
394         char *psz_parser = psz_line;
395         int i_count = 0;
396         while( i_count <= i_line && *psz_parser != '\n' )
397         {
398             if( b_utf8 )
399             {
400                 while( *((unsigned char *)psz_parser) >= 0x80UL ) psz_parser++;
401             }
402             psz_parser++;
403             i_count++;
404         }
405         if( *psz_parser == '\n' )
406         {
407             i_len -= (i_count + 1);
408             psz_line = psz_parser + 1;
409             continue;
410         }
411
412         /* Find the furthest space. */
413         while( psz_parser > psz_line && *psz_parser != ' ' )
414         {
415             if( b_utf8 )
416             {
417                 while( *((unsigned char *)psz_parser) >= 0x80UL ) psz_parser--;
418             }
419             psz_parser--;
420             i_count--;
421         }
422         if( *psz_parser == ' ' )
423         {
424             *psz_parser = '\n';
425             i_len -= (i_count + 1);
426             psz_line = psz_parser + 1;
427             continue;
428         }
429
430         /* Wrapping has failed. Find the first space or newline */
431         while( i_count < i_len && *psz_parser != ' ' && *psz_parser != '\n' )
432         {
433             if( b_utf8 )
434             {
435                 while( *((unsigned char *)psz_parser) >= 0x80UL ) psz_parser++;
436             }
437             psz_parser++;
438             i_count++;
439         }
440         if( i_count < i_len ) *psz_parser = '\n';
441         i_len -= (i_count + 1);
442         psz_line = psz_parser + 1;
443     }
444
445     return psz_new_text;
446 }
447
448 /*****************************************************************************
449  * iconv wrapper
450  *****************************************************************************/
451 vlc_iconv_t vlc_iconv_open( const char *tocode, const char *fromcode )
452 {
453 #if defined(HAVE_ICONV)
454     return iconv_open( tocode, fromcode );
455 #else
456     return NULL;
457 #endif
458 }
459
460 size_t vlc_iconv( vlc_iconv_t cd, char **inbuf, size_t *inbytesleft,
461                   char **outbuf, size_t *outbytesleft )
462 {
463 #if defined(HAVE_ICONV)
464     return iconv( cd, inbuf, inbytesleft, outbuf, outbytesleft );
465 #else
466     int i_bytes = __MIN(*inbytesleft, *outbytesleft);
467     if( !inbuf || !outbuf || !i_bytes ) return (size_t)(-1);
468     memcpy( *outbuf, *inbuf, i_bytes );
469     inbuf += i_bytes;
470     outbuf += i_bytes;
471     inbytesleft -= i_bytes;
472     outbytesleft -= i_bytes;
473     return i_bytes;
474 #endif
475 }
476
477 int vlc_iconv_close( vlc_iconv_t cd )
478 {
479 #if defined(HAVE_ICONV)
480     return iconv_close( cd );
481 #else
482     return 0;
483 #endif
484 }
485
486 /*****************************************************************************
487  * reduce a fraction
488  *   (adapted from libavcodec, author Michael Niedermayer <michaelni@gmx.at>)
489  *****************************************************************************/
490 vlc_bool_t vlc_reduce( int *pi_dst_nom, int *pi_dst_den,
491                        int64_t i_nom, int64_t i_den, int64_t i_max )
492 {
493     vlc_bool_t b_exact = 1, b_sign = 0;
494     int64_t i_gcd;
495
496     if( i_den == 0 )
497     {
498         *pi_dst_nom = 0;
499         *pi_dst_den = 1;
500         return 1;
501     }
502
503     if( i_den < 0 )
504     {
505         i_den = - i_den;
506         i_nom = - i_nom;
507     }
508
509     if( i_nom < 0 )
510     {
511         i_nom = - i_nom;
512         b_sign = 1;
513     }
514
515     i_gcd = GCD( i_nom, i_den );
516     i_nom /= i_gcd;
517     i_den /= i_gcd;
518
519     if( i_max == 0 ) i_max = I64C(0xFFFFFFFF);
520
521     if( i_nom > i_max || i_den > i_max )
522     {
523         int i_a0_num = 0, i_a0_den = 1, i_a1_num = 1, i_a1_den = 0;
524         b_exact = 0;
525
526         for( ; ; )
527         {
528             int64_t i_x = i_nom / i_den;
529             int64_t i_a2n = i_x * i_a1_num + i_a0_num;
530             int64_t i_a2d = i_x * i_a1_den + i_a0_den;
531
532             if( i_a2n > i_max || i_a2d > i_max ) break;
533
534             i_nom %= i_den;
535
536             i_a0_num = i_a1_num; i_a0_den = i_a1_den;
537             i_a1_num = i_a2n; i_a1_den = i_a2d;
538             if( i_nom == 0 ) break;
539             i_x = i_nom; i_nom = i_den; i_den = i_x;
540         }
541         i_nom = i_a1_num;
542         i_den = i_a1_den;
543     }
544
545     if( b_sign ) i_nom = - i_nom;
546
547     *pi_dst_nom = i_nom;
548     *pi_dst_den = i_den;
549
550     return b_exact;
551 }