]> git.sesse.net Git - vlc/blob - src/extras/libc.c
* src/misc/*, src/extras/libc.c: bunch of WinCE fixes.
[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     if( !s1 || !s2 ) return  -1;
91
92     while( !i_delta && *s1 && *s2 )
93     {
94         i_delta = *s1 - *s2;
95
96         if( *s1 >= 'A' && *s1 <= 'Z' )
97         {
98             i_delta -= ('A' - 'a');
99         }
100
101         if( *s2 >= 'A' && *s2 <= 'Z' )
102         {
103             i_delta += ('A' - 'a');
104         }
105
106         s1++; s2++;
107     }
108
109     if( !i_delta && (*s1 || *s2) ) i_delta = *s1 ? 1 : -1;
110
111     return i_delta;
112 }
113 #endif
114
115 /*****************************************************************************
116  * strncasecmp: compare n chars from two strings ignoring case
117  *****************************************************************************/
118 #if !defined( HAVE_STRNCASECMP ) && !defined( HAVE_STRNICMP )
119 int vlc_strncasecmp( const char *s1, const char *s2, size_t n )
120 {
121     int i_delta = 0;
122     if( !s1 || !s2 ) return  -1;
123
124     while( n-- && !i_delta && *s1 && *s2 )
125     {
126         i_delta = *s1 - *s2;
127
128         if( *s1 >= 'A' && *s1 <= 'Z' )
129         {
130             i_delta -= 'A' - 'a';
131         }
132
133         if( *s2 >= 'A' && *s2 <= 'Z' )
134         {
135             i_delta += 'A' - 'a';
136         }
137
138         s1++; s2++;
139     }
140
141     if( !n && !i_delta && (*s1 || *s2) ) i_delta = *s1 ? 1 : -1;
142
143     return i_delta;
144 }
145 #endif
146
147 /******************************************************************************
148  * strcasestr: find a substring (little) in another substring (big)
149  * Case sensitive. Return NULL if not found, return big if little == null
150  *****************************************************************************/
151 #if !defined( HAVE_STRCASESTR ) && !defined( HAVE_STRISTR )
152 char * vlc_strcasestr( const char *psz_big, const char *psz_little )
153 {
154     char *p_pos = (char *)psz_big;
155
156     if( !psz_big || !psz_little || !*psz_little ) return p_pos;
157  
158     while( *p_pos ) 
159     {
160         if( toupper( *p_pos ) == toupper( *psz_little ) )
161         {
162             char * psz_cur1 = p_pos + 1;
163             char * psz_cur2 = (char *)psz_little + 1;
164             while( *psz_cur1 && *psz_cur2 &&
165                    toupper( *psz_cur1 ) == toupper( *psz_cur2 ) )
166             {
167                 psz_cur1++;
168                 psz_cur2++;
169             }
170             if( !*psz_cur2 ) return p_pos;
171         }
172         p_pos++;
173     }
174     return NULL;
175 }
176 #endif
177
178 /*****************************************************************************
179  * vasprintf:
180  *****************************************************************************/
181 #if !defined(HAVE_VASPRINTF) || defined(SYS_DARWIN) || defined(SYS_BEOS)
182 int vlc_vasprintf(char **strp, const char *fmt, va_list ap)
183 {
184     /* Guess we need no more than 100 bytes. */
185     int     i_size = 100;
186     char    *p = malloc( i_size );
187     int     n;
188
189     if( p == NULL )
190     {
191         *strp = NULL;
192         return -1;
193     }
194
195     for( ;; )
196     {
197         /* Try to print in the allocated space. */
198         n = vsnprintf( p, i_size, fmt, ap );
199
200         /* If that worked, return the string. */
201         if (n > -1 && n < i_size)
202         {
203             *strp = p;
204             return strlen( p );
205         }
206         /* Else try again with more space. */
207         if (n > -1)    /* glibc 2.1 */
208         {
209            i_size = n+1; /* precisely what is needed */
210         }
211         else           /* glibc 2.0 */
212         {
213            i_size *= 2;  /* twice the old size */
214         }
215         if( (p = realloc( p, i_size ) ) == NULL)
216         {
217             *strp = NULL;
218             return -1;
219         }
220     }
221 }
222 #endif
223
224 /*****************************************************************************
225  * asprintf:
226  *****************************************************************************/
227 #if !defined(HAVE_ASPRINTF) || defined(SYS_DARWIN) || defined(SYS_BEOS)
228 int vlc_asprintf( char **strp, const char *fmt, ... )
229 {
230     va_list args;
231     int i_ret;
232
233     va_start( args, fmt );
234     i_ret = vasprintf( strp, fmt, args );
235     va_end( args );
236
237     return i_ret;
238 }
239 #endif
240
241 /*****************************************************************************
242  * atof: convert a string to a double.
243  *****************************************************************************/
244 #if !defined( HAVE_ATOF )
245 double vlc_atof( const char *nptr )
246 {
247     double f_result;
248     wchar_t *psz_tmp;
249     int i_len = strlen( nptr ) + 1;
250
251     psz_tmp = malloc( i_len * sizeof(wchar_t) );
252     MultiByteToWideChar( CP_ACP, 0, nptr, -1, psz_tmp, i_len );
253     f_result = wcstod( psz_tmp, NULL );
254     free( psz_tmp );
255
256     return f_result;
257 }
258 #endif
259
260 /*****************************************************************************
261  * strtoll: convert a string to a 64 bits int.
262  *****************************************************************************/
263 #if !defined( HAVE_STRTOLL )
264 int64_t vlc_strtoll( const char *nptr, char **endptr, int base )
265 {
266     int64_t i_value = 0;
267     int sign = 1, newbase = base ? base : 10;
268
269     while( isspace(*nptr) ) nptr++;
270
271     if( *nptr == '-' )
272     {
273         sign = -1;
274         nptr++;
275     }
276
277     /* Try to detect base */
278     if( *nptr == '0' )
279     {
280         newbase = 8;
281         nptr++;
282
283         if( *nptr == 'x' )
284         {
285             newbase = 16;
286             nptr++;
287         }
288     }
289
290     if( base && newbase != base )
291     {
292         if( endptr ) *endptr = (char *)nptr;
293         return i_value;
294     }
295
296     switch( newbase )
297     {
298         case 10:
299             while( *nptr >= '0' && *nptr <= '9' )
300             {
301                 i_value *= 10;
302                 i_value += ( *nptr++ - '0' );
303             }
304             if( endptr ) *endptr = (char *)nptr;
305             break;
306
307         case 16:
308             while( (*nptr >= '0' && *nptr <= '9') ||
309                    (*nptr >= 'a' && *nptr <= 'f') ||
310                    (*nptr >= 'A' && *nptr <= 'F') )
311             {
312                 int i_valc = 0;
313                 if(*nptr >= '0' && *nptr <= '9') i_valc = *nptr - '0';
314                 else if(*nptr >= 'a' && *nptr <= 'f') i_valc = *nptr - 'a' +10;
315                 else if(*nptr >= 'A' && *nptr <= 'F') i_valc = *nptr - 'A' +10;
316                 i_value *= 16;
317                 i_value += i_valc;
318                 nptr++;
319             }
320             if( endptr ) *endptr = (char *)nptr;
321             break;
322
323         default:
324             i_value = strtol( nptr, endptr, newbase );
325             break;
326     }
327
328     return i_value * sign;
329 }
330 #endif
331
332 /*****************************************************************************
333  * atoll: convert a string to a 64 bits int.
334  *****************************************************************************/
335 #if !defined( HAVE_ATOLL )
336 int64_t vlc_atoll( const char *nptr )
337 {
338     return strtoll( nptr, (char **)NULL, 10 );
339 }
340 #endif
341
342 /*****************************************************************************
343  * lseek: reposition read/write file offset.
344  *****************************************************************************
345  * FIXME: this cast sucks!
346  *****************************************************************************/
347 #if !defined( HAVE_LSEEK )
348 off_t vlc_lseek( int fildes, off_t offset, int whence )
349 {
350     return SetFilePointer( (HANDLE)fildes, (long)offset, NULL, whence );
351 }
352 #endif
353
354 /*****************************************************************************
355  * dgettext: gettext for plugins.
356  *****************************************************************************/
357 char *vlc_dgettext( const char *package, const char *msgid )
358 {
359 #if defined( ENABLE_NLS ) \
360      && ( defined(HAVE_GETTEXT) || defined(HAVE_INCLUDED_GETTEXT) )
361     return dgettext( package, msgid );
362 #else
363     return (char *)msgid;
364 #endif
365 }
366
367 /*****************************************************************************
368  * count_utf8_string: returns the number of characters in the string.
369  *****************************************************************************/
370 static int count_utf8_string( const char *psz_string )
371 {
372     int i = 0, i_count = 0;
373     while( psz_string[ i ] != 0 )
374     {
375         if( ((unsigned char *)psz_string)[ i ] <  0x80UL ) i_count++;
376         i++;
377     }
378     return i_count;
379 }
380
381 /*****************************************************************************
382  * wraptext: inserts \n at convenient places to wrap the text.
383  *           Returns the modified string in a new buffer.
384  *****************************************************************************/
385 char *vlc_wraptext( const char *psz_text, int i_line, vlc_bool_t b_utf8 )
386 {
387     int i_len;
388     char *psz_line, *psz_new_text;
389
390     psz_line = psz_new_text = strdup( psz_text );
391
392     if( b_utf8 )
393         i_len = count_utf8_string( psz_text );
394     else
395         i_len = strlen( psz_text );
396
397     while( i_len > i_line )
398     {
399         /* Look if there is a newline somewhere. */
400         char *psz_parser = psz_line;
401         int i_count = 0;
402         while( i_count <= i_line && *psz_parser != '\n' )
403         {
404             if( b_utf8 )
405             {
406                 while( *((unsigned char *)psz_parser) >= 0x80UL ) psz_parser++;
407             }
408             psz_parser++;
409             i_count++;
410         }
411         if( *psz_parser == '\n' )
412         {
413             i_len -= (i_count + 1);
414             psz_line = psz_parser + 1;
415             continue;
416         }
417
418         /* Find the furthest space. */
419         while( psz_parser > psz_line && *psz_parser != ' ' )
420         {
421             if( b_utf8 )
422             {
423                 while( *((unsigned char *)psz_parser) >= 0x80UL ) psz_parser--;
424             }
425             psz_parser--;
426             i_count--;
427         }
428         if( *psz_parser == ' ' )
429         {
430             *psz_parser = '\n';
431             i_len -= (i_count + 1);
432             psz_line = psz_parser + 1;
433             continue;
434         }
435
436         /* Wrapping has failed. Find the first space or newline */
437         while( i_count < i_len && *psz_parser != ' ' && *psz_parser != '\n' )
438         {
439             if( b_utf8 )
440             {
441                 while( *((unsigned char *)psz_parser) >= 0x80UL ) psz_parser++;
442             }
443             psz_parser++;
444             i_count++;
445         }
446         if( i_count < i_len ) *psz_parser = '\n';
447         i_len -= (i_count + 1);
448         psz_line = psz_parser + 1;
449     }
450
451     return psz_new_text;
452 }
453
454 /*****************************************************************************
455  * iconv wrapper
456  *****************************************************************************/
457 vlc_iconv_t vlc_iconv_open( const char *tocode, const char *fromcode )
458 {
459 #if defined(HAVE_ICONV)
460     return iconv_open( tocode, fromcode );
461 #else
462     return NULL;
463 #endif
464 }
465
466 size_t vlc_iconv( vlc_iconv_t cd, char **inbuf, size_t *inbytesleft,
467                   char **outbuf, size_t *outbytesleft )
468 {
469 #if defined(HAVE_ICONV)
470     return iconv( cd, inbuf, inbytesleft, outbuf, outbytesleft );
471 #else
472     int i_bytes = __MIN(*inbytesleft, *outbytesleft);
473     if( !inbuf || !outbuf || !i_bytes ) return (size_t)(-1);
474     memcpy( *outbuf, *inbuf, i_bytes );
475     inbuf += i_bytes;
476     outbuf += i_bytes;
477     inbytesleft -= i_bytes;
478     outbytesleft -= i_bytes;
479     return i_bytes;
480 #endif
481 }
482
483 int vlc_iconv_close( vlc_iconv_t cd )
484 {
485 #if defined(HAVE_ICONV)
486     return iconv_close( cd );
487 #else
488     return 0;
489 #endif
490 }
491
492 /*****************************************************************************
493  * reduce a fraction
494  *   (adapted from libavcodec, author Michael Niedermayer <michaelni@gmx.at>)
495  *****************************************************************************/
496 vlc_bool_t vlc_reduce( int *pi_dst_nom, int *pi_dst_den,
497                        int64_t i_nom, int64_t i_den, int64_t i_max )
498 {
499     vlc_bool_t b_exact = 1, b_sign = 0;
500     int64_t i_gcd;
501
502     if( i_den == 0 )
503     {
504         *pi_dst_nom = 0;
505         *pi_dst_den = 1;
506         return 1;
507     }
508
509     if( i_den < 0 )
510     {
511         i_den = - i_den;
512         i_nom = - i_nom;
513     }
514
515     if( i_nom < 0 )
516     {
517         i_nom = - i_nom;
518         b_sign = 1;
519     }
520
521     i_gcd = GCD( i_nom, i_den );
522     i_nom /= i_gcd;
523     i_den /= i_gcd;
524
525     if( i_max == 0 ) i_max = I64C(0xFFFFFFFF);
526
527     if( i_nom > i_max || i_den > i_max )
528     {
529         int i_a0_num = 0, i_a0_den = 1, i_a1_num = 1, i_a1_den = 0;
530         b_exact = 0;
531
532         for( ; ; )
533         {
534             int64_t i_x = i_nom / i_den;
535             int64_t i_a2n = i_x * i_a1_num + i_a0_num;
536             int64_t i_a2d = i_x * i_a1_den + i_a0_den;
537
538             if( i_a2n > i_max || i_a2d > i_max ) break;
539
540             i_nom %= i_den;
541
542             i_a0_num = i_a1_num; i_a0_den = i_a1_den;
543             i_a1_num = i_a2n; i_a1_den = i_a2d;
544             if( i_nom == 0 ) break;
545             i_x = i_nom; i_nom = i_den; i_den = i_x;
546         }
547         i_nom = i_a1_num;
548         i_den = i_a1_den;
549     }
550
551     if( b_sign ) i_nom = - i_nom;
552
553     *pi_dst_nom = i_nom;
554     *pi_dst_den = i_den;
555
556     return b_exact;
557 }