]> git.sesse.net Git - vlc/blob - src/extras/libc.c
* backport of local_stristr to vlc_strcasestr in libc.c
[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  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
23  *****************************************************************************/
24 #include <string.h>                                              /* strdup() */
25 #include <stdlib.h>
26
27 #include <vlc/vlc.h>
28
29 /*****************************************************************************
30  * getenv: just in case, but it should never be called
31  *****************************************************************************/
32 #if !defined( HAVE_GETENV )
33 char *vlc_getenv( const char *name )
34 {
35     return NULL;
36 }
37 #endif
38
39 /*****************************************************************************
40  * strdup: returns a malloc'd copy of a string
41  *****************************************************************************/
42 #if !defined( HAVE_STRDUP )
43 char *vlc_strdup( const char *string )
44 {
45     return strndup( string, strlen( string ) );
46 }
47 #endif
48
49 /*****************************************************************************
50  * strndup: returns a malloc'd copy of at most n bytes of string
51  * Does anyone know whether or not it will be present in Jaguar?
52  *****************************************************************************/
53 #if !defined( HAVE_STRNDUP )
54 char *vlc_strndup( const char *string, size_t n )
55 {
56     char *psz;
57     size_t len = strlen( string );
58
59     len = __MIN( len, n );
60     psz = (char*)malloc( len + 1 );
61
62     if( psz != NULL )
63     {
64         memcpy( (void*)psz, (const void*)string, len );
65         psz[ len ] = 0;
66     }
67
68     return psz;
69 }
70 #endif
71
72 /*****************************************************************************
73  * strcasecmp: compare two strings ignoring case
74  *****************************************************************************/
75 #if !defined( HAVE_STRCASECMP ) && !defined( HAVE_STRICMP )
76 int vlc_strcasecmp( const char *s1, const char *s2 )
77 {
78     int i_delta = 0;
79
80     while( !i_delta && *s1 && *s2 )
81     {
82         i_delta = *s1 - *s2;
83
84         if( *s1 >= 'A' && *s1 <= 'Z' )
85         {
86             i_delta -= 'A' - 'a';
87         }
88
89         if( *s2 >= 'A' && *s2 <= 'Z' )
90         {
91             i_delta += 'A' - 'a';
92         }
93
94         s1++; s2++;
95     }
96
97     return i_delta;
98 }
99 #endif
100
101 /*****************************************************************************
102  * strncasecmp: compare n chars from two strings ignoring case
103  *****************************************************************************/
104 #if !defined( HAVE_STRNCASECMP ) && !defined( HAVE_STRNICMP )
105 int vlc_strncasecmp( const char *s1, const char *s2, size_t n )
106 {
107     int i_delta = 0;
108
109     while( n-- && !i_delta && *s1 )
110     {
111         i_delta = *s1 - *s2;
112
113         if( *s1 >= 'A' && *s1 <= 'Z' )
114         {
115             i_delta -= 'A' - 'a';
116         }
117
118         if( *s2 >= 'A' && *s2 <= 'Z' )
119         {
120             i_delta += 'A' - 'a';
121         }
122
123         s1++; s2++;
124     }
125
126     return i_delta;
127 }
128 #endif
129
130 /******************************************************************************
131  * strcasestr: find a substring (little) in another substring (big)
132  * Case sensitive. Return NULL if not found, return big if little == null
133  *****************************************************************************/
134 #if !defined( HAVE_STRCASESTR ) && !defined( HAVE_STRISTR )
135 static char * vlc_strncasestr( const char *psz_big, const char *psz_little )
136 {
137     char *p_pox = psz_big;
138
139     if( !psz_big || !psz_little || !*psz_little ) return psz_big;
140  
141     while( *p_pos ) 
142     {
143         if( toupper( *p_pos ) == toupper( *psz_little ) )
144         {
145             char * psz_cur1 = p_pos + 1;
146             char * psz_cur2 = psz_little + 1;
147             while( *psz_cur1 && *psz_cur2 && toupper( *psz_cur1 ) == toupper( *psz_cur2 ) )
148             {
149                 psz_cur1++;
150                 psz_cur2++;
151             }
152             if( !*psz_cur2 ) return p_pos;
153         }
154         p_pos++;
155     }
156     return NULL;
157 }
158 #endif
159
160 /*****************************************************************************
161  * vasprintf:
162  *****************************************************************************/
163 #if !defined(HAVE_VASPRINTF) || defined(SYS_DARWIN) || defined(SYS_BEOS)
164 int vlc_vasprintf(char **strp, const char *fmt, va_list ap)
165 {
166     /* Guess we need no more than 100 bytes. */
167     int     i_size = 100;
168     char    *p = malloc( i_size );
169     int     n;
170
171     if( p == NULL )
172     {
173         *strp = NULL;
174         return -1;
175     }
176
177     for( ;; )
178     {
179         /* Try to print in the allocated space. */
180         n = vsnprintf( p, i_size, fmt, ap );
181
182         /* If that worked, return the string. */
183         if (n > -1 && n < i_size)
184         {
185             *strp = p;
186             return strlen( p );
187         }
188         /* Else try again with more space. */
189         if (n > -1)    /* glibc 2.1 */
190         {
191            i_size = n+1; /* precisely what is needed */
192         }
193         else           /* glibc 2.0 */
194         {
195            i_size *= 2;  /* twice the old size */
196         }
197         if( (p = realloc( p, i_size ) ) == NULL)
198         {
199             *strp = NULL;
200             return -1;
201         }
202     }
203 }
204 #endif
205
206 /*****************************************************************************
207  * asprintf:
208  *****************************************************************************/
209 #if !defined(HAVE_ASPRINTF) || defined(SYS_DARWIN) || defined(SYS_BEOS)
210 int vlc_asprintf( char **strp, const char *fmt, ... )
211 {
212     va_list args;
213     int i_ret;
214
215     va_start( args, fmt );
216     i_ret = vasprintf( strp, fmt, args );
217     va_end( args );
218
219     return i_ret;
220 }
221 #endif
222
223 /*****************************************************************************
224  * atof: convert a string to a double.
225  *****************************************************************************/
226 #if !defined( HAVE_ATOF )
227 double vlc_atof( const char *nptr )
228 {
229     double f_result;
230     wchar_t *psz_tmp;
231     int i_len = strlen( nptr ) + 1;
232
233     psz_tmp = malloc( i_len * sizeof(wchar_t) );
234     MultiByteToWideChar( CP_ACP, 0, nptr, -1, psz_tmp, i_len );
235     f_result = wcstod( psz_tmp, NULL );
236     free( psz_tmp );
237
238     return f_result;
239 }
240 #endif
241
242 /*****************************************************************************
243  * atoll: convert a string to a 64 bits int.
244  *****************************************************************************/
245 #if !defined( HAVE_ATOLL )
246 int64_t vlc_atoll( const char *str )
247 {
248     int64_t i_value = 0;
249     int sign = 1;
250
251     if( *str == '-' )
252     {
253         sign = -1;
254     }
255
256     while( *str >= '0' && *str <= '9' )
257     {
258         i_value = i_value * 10 + ( *str++ - '0' );
259     }
260
261     return i_value * sign;
262 }
263 #endif
264
265 /*****************************************************************************
266  * lseek: reposition read/write file offset.
267  *****************************************************************************
268  * FIXME: this cast sucks!
269  *****************************************************************************/
270 #if !defined( HAVE_LSEEK )
271 off_t vlc_lseek( int fildes, off_t offset, int whence )
272 {
273     return SetFilePointer( (HANDLE)fildes, (long)offset, NULL, whence );
274 }
275 #endif
276
277 /*****************************************************************************
278  * dgettext: gettext for plugins.
279  *****************************************************************************/
280 char *vlc_dgettext( const char *package, const char *msgid )
281 {
282 #if defined( ENABLE_NLS ) \
283      && ( defined(HAVE_GETTEXT) || defined(HAVE_INCLUDED_GETTEXT) )
284     return dgettext( package, msgid );
285 #else
286     return (char *)msgid;
287 #endif
288 }
289
290 /*****************************************************************************
291  * count_utf8_string: returns the number of characters in the string.
292  *****************************************************************************/
293 static int count_utf8_string( const char *psz_string )
294 {
295     int i = 0, i_count = 0;
296     while( psz_string[ i ] != 0 )
297     {
298         if( ((unsigned char *)psz_string)[ i ] <  0x80UL ) i_count++;
299         i++;
300     }
301     return i_count;
302 }
303
304 /*****************************************************************************
305  * wraptext: inserts \n at convenient places to wrap the text.
306  *           Returns the modified string in a new buffer.
307  *****************************************************************************/
308 char *vlc_wraptext( const char *psz_text, int i_line, vlc_bool_t b_utf8 )
309 {
310     int i_len;
311     char *psz_line, *psz_new_text;
312
313     psz_line = psz_new_text = strdup( psz_text );
314
315     if( b_utf8 )
316         i_len = count_utf8_string( psz_text );
317     else
318         i_len = strlen( psz_text );
319
320     while( i_len > i_line )
321     {
322         /* Look if there is a newline somewhere. */
323         char *psz_parser = psz_line;
324         int i_count = 0;
325         while( i_count <= i_line && *psz_parser != '\n' )
326         {
327             if( b_utf8 )
328             {
329                 while( *((unsigned char *)psz_parser) >= 0x80UL ) psz_parser++;
330             }
331             psz_parser++;
332             i_count++;
333         }
334         if( *psz_parser == '\n' )
335         {
336             i_len -= (i_count + 1);
337             psz_line = psz_parser + 1;
338             continue;
339         }
340
341         /* Find the furthest space. */
342         while( psz_parser > psz_line && *psz_parser != ' ' )
343         {
344             if( b_utf8 )
345             {
346                 while( *((unsigned char *)psz_parser) >= 0x80UL ) psz_parser--;
347             }
348             psz_parser--;
349             i_count--;
350         }
351         if( *psz_parser == ' ' )
352         {
353             *psz_parser = '\n';
354             i_len -= (i_count + 1);
355             psz_line = psz_parser + 1;
356             continue;
357         }
358
359         /* Wrapping has failed. Find the first space or newline */
360         while( i_count < i_len && *psz_parser != ' ' && *psz_parser != '\n' )
361         {
362             if( b_utf8 )
363             {
364                 while( *((unsigned char *)psz_parser) >= 0x80UL ) psz_parser++;
365             }
366             psz_parser++;
367             i_count++;
368         }
369         if( i_count < i_len ) *psz_parser = '\n';
370         i_len -= (i_count + 1);
371         psz_line = psz_parser + 1;
372     }
373
374     return psz_new_text;
375 }