]> git.sesse.net Git - vlc/blobdiff - src/misc/variables.c
Mark unreachable code on GCC even if NDEBUG
[vlc] / src / misc / variables.c
index 9dbe20874562dba16e7f0a9bb7c165f814d3ac5f..3a89b4156b90b7c0474b826ec349824a042cce4d 100644 (file)
@@ -32,6 +32,7 @@
 # include <search.h>
 #endif
 #include <assert.h>
+#include <float.h>
 #include <math.h>
 #include <limits.h>
 #ifdef __GLIBC__
@@ -98,26 +99,6 @@ static void DupString( vlc_value_t *p_val )
 static void FreeDummy( vlc_value_t *p_val ) { (void)p_val; /* unused */ }
 static void FreeString( vlc_value_t *p_val ) { free( p_val->psz_string ); }
 
-static void FreeList( vlc_value_t *p_val )
-{
-    int i;
-    for( i = 0; i < p_val->p_list->i_count; i++ )
-    {
-        switch( p_val->p_list->i_type & VLC_VAR_CLASS )
-        {
-        case VLC_VAR_STRING:
-            FreeString( &p_val->p_list->p_values[i] );
-            break;
-        default:
-            break;
-        }
-    }
-
-    if( p_val->p_list->i_count )
-        free( p_val->p_list->p_values );
-    free( p_val->p_list );
-}
-
 static const struct variable_ops_t
 void_ops   = { NULL,       DupDummy,  FreeDummy,  },
 addr_ops   = { CmpAddress, DupDummy,  FreeDummy,  },
@@ -274,7 +255,7 @@ int var_Create( vlc_object_t *p_this, const char *psz_name, int i_type )
             p_var->ops = &void_ops;
             break;
         default:
-            assert (0);
+            vlc_assert_unreachable ();
     }
 
     if( (i_type & VLC_VAR_DOINHERIT)
@@ -551,23 +532,16 @@ int var_Change( vlc_object_t *p_this, const char *psz_name,
             p_var->ops->pf_free( &oldval );
             break;
         case VLC_VAR_GETCHOICES:
-        case VLC_VAR_GETLIST:
-            p_val->p_list = malloc( sizeof(vlc_list_t) );
-            if( p_val2 ) p_val2->p_list = malloc( sizeof(vlc_list_t) );
-            if( p_var->choices.i_count )
-            {
-                p_val->p_list->p_values = malloc( p_var->choices.i_count
-                                                  * sizeof(vlc_value_t) );
-                if( p_val2 )
-                {
-                    p_val2->p_list->p_values =
-                        malloc( p_var->choices.i_count * sizeof(vlc_value_t) );
-                }
-            }
+            p_val->p_list = xmalloc( sizeof(vlc_list_t) );
+            p_val->p_list->p_values =
+                xmalloc( p_var->choices.i_count * sizeof(vlc_value_t) );
             p_val->p_list->i_type = p_var->i_type;
             p_val->p_list->i_count = p_var->choices.i_count;
             if( p_val2 )
             {
+                p_val2->p_list = xmalloc( sizeof(vlc_list_t) );
+                p_val2->p_list->p_values =
+                    xmalloc( p_var->choices.i_count * sizeof(vlc_value_t) );
                 p_val2->p_list->i_type = VLC_VAR_STRING;
                 p_val2->p_list->i_count = p_var->choices.i_count;
             }
@@ -698,8 +672,11 @@ int var_Type( vlc_object_t *p_this, const char *psz_name )
 
     p_var = Lookup( p_this, psz_name );
     if( p_var != NULL )
+    {
         i_type = p_var->i_type;
-
+        if( p_var->choices.i_count > 0 )
+            i_type |= VLC_VAR_HASCHOICE;
+    }
     vlc_mutex_unlock( &p_priv->var_lock );
 
     return i_type;
@@ -927,7 +904,7 @@ static int DelCallback( vlc_object_t *p_this, const char *psz_name,
         if( b_found_similar )
             fprintf( stderr, "Calling var_DelCallback for '%s' with the same "
                              "function but not the same data.", psz_name );
-        assert( 0 );
+        vlc_assert_unreachable();
 #endif
         vlc_mutex_unlock( &p_priv->var_lock );
         return VLC_EGENERIC;
@@ -1298,7 +1275,7 @@ int var_Inherit( vlc_object_t *p_this, const char *psz_name, int i_type,
             p_val->b_bool = config_GetInt( p_this, psz_name );
             break;
         default:
-            assert(0);
+            vlc_assert_unreachable();
         case VLC_VAR_ADDRESS:
             return VLC_ENOOBJ;
     }
@@ -1331,19 +1308,28 @@ int (var_InheritURational)(vlc_object_t *object,
     unsigned d = strtol(*next ? &next[1] : "0", NULL, 0);
 
     if (*next == '.') {
-        /* Interpret as a float number */
-        double r = us_atof(tmp);
-        double c = ceil(r);
-        if (c >= UINT_MAX)
-            goto error;
-        unsigned m = c;
-        if (m > 0) {
-            d = UINT_MAX / m;
-            n = r * d;
-        } else {
-            n = 0;
-            d = 0;
-        }
+        /* Interpret as a (finite positive) float number */
+        const int ubits = CHAR_BIT * sizeof (unsigned);
+        int exp;
+        double f = frexp(us_atof(tmp), &exp);
+
+        if (!isgreaterequal(f, 0.))
+            goto error; /* negative or not a number */
+
+        if (exp <= 1 - ubits) {
+            n = 0; /* too small */
+            d = 1;
+        } else if (exp <= 0) {
+            n = floor(scalbn(f, ubits - 1 + exp));
+#if (FLT_RADIX != 2)
+# error Floating point configuration not supported.
+#endif
+            d = 1u << (ubits - 1);
+        } else if (exp <= ubits) {
+            n = floor(scalbn(f, ubits));
+            d = 1u << (ubits - exp);
+        } else
+            goto error; /* too big */
     } else if ( *next == '\0' ) {
         /* plain integer given */
         *num = n;
@@ -1435,13 +1421,25 @@ static int TriggerListCallback( vlc_object_t *p_this, variable_t *p_var,
  */
 void var_FreeList( vlc_value_t *p_val, vlc_value_t *p_val2 )
 {
-    FreeList( p_val );
-    if( p_val2 && p_val2->p_list )
+    switch( p_val->p_list->i_type & VLC_VAR_CLASS )
     {
+        case VLC_VAR_STRING:
+            for( int i = 0; i < p_val->p_list->i_count; i++ )
+                free( p_val->p_list->p_values[i].psz_string );
+            break;
+    }
+
+    free( p_val->p_list->p_values );
+    free( p_val->p_list );
+
+    if( p_val2 != NULL )
+    {
+        assert( p_val2->p_list != NULL );
+        assert( p_val2->p_list->i_type == VLC_VAR_STRING );
+
         for( int i = 0; i < p_val2->p_list->i_count; i++ )
             free( p_val2->p_list->p_values[i].psz_string );
-        if( p_val2->p_list->i_count )
-            free( p_val2->p_list->p_values );
+        free( p_val2->p_list->p_values );
         free( p_val2->p_list );
     }
 }