]> git.sesse.net Git - vlc/blobdiff - src/extras/libc.c
* src/extras/libc.c: Added an implementation of scandir (from directory.c).
[vlc] / src / extras / libc.c
index 2a1c8b8ab36098a809609dd7eed018d235f71c68..a8c425201feefb32741d85e95c31ccf8780d50b5 100644 (file)
@@ -1,12 +1,13 @@
 /*****************************************************************************
  * libc.c: Extra libc function for some systems.
  *****************************************************************************
- * Copyright (C) 2002 VideoLAN
+ * Copyright (C) 2002 the VideoLAN team
  * $Id$
  *
  * Authors: Jon Lech Johansen <jon-vl@nanocrew.net>
  *          Samuel Hocevar <sam@zoy.org>
  *          Gildas Bazin <gbazin@videolan.org>
+ *          Derk-Jan Hartman <hartman at videolan dot org>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -86,29 +87,20 @@ char *vlc_strndup( const char *string, size_t n )
 #if !defined( HAVE_STRCASECMP ) && !defined( HAVE_STRICMP )
 int vlc_strcasecmp( const char *s1, const char *s2 )
 {
-    int i_delta = 0;
+    int c1, c2;
     if( !s1 || !s2 ) return  -1;
 
-    while( !i_delta && *s1 && *s2 )
+    while( *s1 && *s2 )
     {
-        i_delta = *s1 - *s2;
-
-        if( *s1 >= 'A' && *s1 <= 'Z' )
-        {
-            i_delta -= ('A' - 'a');
-        }
-
-        if( *s2 >= 'A' && *s2 <= 'Z' )
-        {
-            i_delta += ('A' - 'a');
-        }
+        c1 = tolower(*s1);
+        c2 = tolower(*s2);
 
+        if( c1 != c2 ) return (c1 < c2 ? -1 : 1);
         s1++; s2++;
     }
 
-    if( !i_delta && (*s1 || *s2) ) i_delta = *s1 ? 1 : -1;
-
-    return i_delta;
+    if( !*s1 && !*s2 ) return 0;
+    else return (*s1 ? 1 : -1);
 }
 #endif
 
@@ -118,29 +110,20 @@ int vlc_strcasecmp( const char *s1, const char *s2 )
 #if !defined( HAVE_STRNCASECMP ) && !defined( HAVE_STRNICMP )
 int vlc_strncasecmp( const char *s1, const char *s2, size_t n )
 {
-    int i_delta = 0;
+    int c1, c2;
     if( !s1 || !s2 ) return  -1;
 
-    while( n-- && !i_delta && *s1 && *s2 )
+    while( n > 0 && *s1 && *s2 )
     {
-        i_delta = *s1 - *s2;
-
-        if( *s1 >= 'A' && *s1 <= 'Z' )
-        {
-            i_delta -= 'A' - 'a';
-        }
+        c1 = tolower(*s1);
+        c2 = tolower(*s2);
 
-        if( *s2 >= 'A' && *s2 <= 'Z' )
-        {
-            i_delta += 'A' - 'a';
-        }
-
-        s1++; s2++;
+        if( c1 != c2 ) return (c1 < c2 ? -1 : 1);
+        s1++; s2++; n--;
     }
 
-    if( !n && !i_delta && (*s1 || *s2) ) i_delta = *s1 ? 1 : -1;
-
-    return i_delta;
+    if( !n || (!*s1 && !*s2) ) return 0;
+    else return (*s1 ? 1 : -1);
 }
 #endif
 
@@ -340,14 +323,51 @@ int64_t vlc_atoll( const char *nptr )
 #endif
 
 /*****************************************************************************
- * lseek: reposition read/write file offset.
- *****************************************************************************
- * FIXME: this cast sucks!
+ * scandir: scan a directory alpha-sorted
  *****************************************************************************/
-#if !defined( HAVE_LSEEK )
-off_t vlc_lseek( int fildes, off_t offset, int whence )
+#if !defined( HAVE_SCANDIR )
+int vlc_alphasort( const struct dirent **a, const struct dirent **b )
+{
+    return strcoll( (*a)->d_name, (*b)->d_name );
+}
+
+int vlc_scandir( const char *name, struct dirent ***namelist,
+                    int (*filter) ( const struct dirent * ),
+                    int (*compar) ( const struct dirent **,
+                                    const struct dirent ** ) )
 {
-    return SetFilePointer( (HANDLE)fildes, (long)offset, NULL, whence );
+    DIR            * p_dir;
+    struct dirent  * p_content;
+    struct dirent ** pp_list;
+    int              ret, size;
+
+    if( !namelist || !( p_dir = opendir( name ) ) ) return -1;
+
+    ret     = 0;
+    pp_list = NULL;
+    while( ( p_content = readdir( p_dir ) ) )
+    {
+        if( filter && !filter( p_content ) )
+        {
+            continue;
+        }
+        pp_list = realloc( pp_list, ( ret + 1 ) * sizeof( struct dirent * ) );
+        size = sizeof( struct dirent ) + strlen( p_content->d_name ) + 1;
+        pp_list[ret] = malloc( size );
+        memcpy( pp_list[ret], p_content, size );
+        ret++;
+    }
+
+    closedir( p_dir );
+
+    if( compar )
+    {
+        qsort( pp_list, ret, sizeof( struct dirent * ),
+               (int (*)(const void *, const void *)) compar );
+    }
+
+    *namelist = pp_list;
+    return ret;
 }
 #endif
 
@@ -493,11 +513,11 @@ int vlc_iconv_close( vlc_iconv_t cd )
  * reduce a fraction
  *   (adapted from libavcodec, author Michael Niedermayer <michaelni@gmx.at>)
  *****************************************************************************/
-vlc_bool_t vlc_reduce( int *pi_dst_nom, int *pi_dst_den,
-                       int64_t i_nom, int64_t i_den, int64_t i_max )
+vlc_bool_t vlc_ureduce( unsigned *pi_dst_nom, unsigned *pi_dst_den,
+                        uint64_t i_nom, uint64_t i_den, uint64_t i_max )
 {
-    vlc_bool_t b_exact = 1, b_sign = 0;
-    int64_t i_gcd;
+    vlc_bool_t b_exact = 1;
+    uint64_t i_gcd;
 
     if( i_den == 0 )
     {
@@ -506,18 +526,6 @@ vlc_bool_t vlc_reduce( int *pi_dst_nom, int *pi_dst_den,
         return 1;
     }
 
-    if( i_den < 0 )
-    {
-        i_den = - i_den;
-        i_nom = - i_nom;
-    }
-
-    if( i_nom < 0 )
-    {
-        i_nom = - i_nom;
-        b_sign = 1;
-    }
-
     i_gcd = GCD( i_nom, i_den );
     i_nom /= i_gcd;
     i_den /= i_gcd;
@@ -526,14 +534,14 @@ vlc_bool_t vlc_reduce( int *pi_dst_nom, int *pi_dst_den,
 
     if( i_nom > i_max || i_den > i_max )
     {
-        int i_a0_num = 0, i_a0_den = 1, i_a1_num = 1, i_a1_den = 0;
+        uint64_t i_a0_num = 0, i_a0_den = 1, i_a1_num = 1, i_a1_den = 0;
         b_exact = 0;
 
         for( ; ; )
         {
-            int64_t i_x = i_nom / i_den;
-            int64_t i_a2n = i_x * i_a1_num + i_a0_num;
-            int64_t i_a2d = i_x * i_a1_den + i_a0_den;
+            uint64_t i_x = i_nom / i_den;
+            uint64_t i_a2n = i_x * i_a1_num + i_a0_num;
+            uint64_t i_a2d = i_x * i_a1_den + i_a0_den;
 
             if( i_a2n > i_max || i_a2d > i_max ) break;
 
@@ -548,8 +556,6 @@ vlc_bool_t vlc_reduce( int *pi_dst_nom, int *pi_dst_den,
         i_den = i_a1_den;
     }
 
-    if( b_sign ) i_nom = - i_nom;
-
     *pi_dst_nom = i_nom;
     *pi_dst_den = i_den;
 
@@ -621,12 +627,12 @@ char **vlc_parse_cmdline( const char *psz_cmdline, int *i_args )
 {
     int argc = 0;
     char **argv = 0;
-    char *s, *psz_parser, *psz_arg;
+    char *s, *psz_parser, *psz_arg, *psz_orig;
     int i_bcount = 0;
 
     if( !psz_cmdline ) return 0;
-    psz_cmdline = strdup( psz_cmdline );
-    psz_arg = psz_parser = s = psz_cmdline;
+    psz_orig = strdup( psz_cmdline );
+    psz_arg = psz_parser = s = psz_orig;
 
     while( *s )
     {
@@ -686,6 +692,6 @@ char **vlc_parse_cmdline( const char *psz_cmdline, int *i_args )
     }
 
     if( i_args ) *i_args = argc;
-    free( psz_cmdline );
+    free( psz_orig );
     return argv;
 }