]> git.sesse.net Git - vlc/blobdiff - src/config/chain.c
Remove Apple getopt_long bug-to-bug
[vlc] / src / config / chain.c
index 5423fb754d2151f09276027ff71095d2ecab011b..a9a6fce29713eeabfdeb0e8c94f4cda504bb25e4 100644 (file)
@@ -33,6 +33,7 @@
 
 #include <vlc_common.h>
 #include "libvlc.h"
+#include <vlc_charset.h>
 
 #include "vlc_interface.h"
 
@@ -54,7 +55,7 @@ static bool IsSpace( char c  )
     return c == ' ' || c == '\t';
 }
 
-#define SKIPSPACE( p ) do { while( *p && IsSpace( *p ) ) p++; } while(0)
+#define SKIPSPACE( p ) p += strspn( p, " \t" )
 #define SKIPTRAILINGSPACE( p, e ) \
     do { while( e > p && IsSpace( *(e-1) ) ) e--; } while(0)
 
@@ -174,107 +175,67 @@ static char *ChainGetValue( const char **ppsz_string )
     return psz_value;
 }
 
-char *config_ChainCreate( char **ppsz_name, config_chain_t **pp_cfg, const char *psz_chain )
+char *config_ChainCreate( char **ppsz_name, config_chain_t **pp_cfg,
+                          const char *psz_chain )
 {
-    config_chain_t *p_cfg = NULL;
-    const char *p = psz_chain;
+    config_chain_t **pp_next = pp_cfg;
+    size_t len;
 
     *ppsz_name = NULL;
     *pp_cfg    = NULL;
 
-    if( !p )
+    if( !psz_chain )
         return NULL;
+    SKIPSPACE( psz_chain );
 
-    /* Look for parameter(either a {...} or :...) or the end of name (space or nul) */
-    SKIPSPACE( p );
-
-    while( *p && *p != '{' && *p != ':' && !IsSpace( *p ) )
-        p++;
-
-    if( p == psz_chain )
-        return NULL;
-
-    /* Extract the name */
-    *ppsz_name = strndup( psz_chain, p - psz_chain );
+    /* Look for parameter (a {...} or :...) or end of name (space or nul) */
+    len = strcspn( psz_chain, "{: \t" );
+    *ppsz_name = strndup( psz_chain, len );
+    psz_chain += len;
 
     /* Parse the parameters */
-    SKIPSPACE( p );
-
-    if( *p == '{' )
+    SKIPSPACE( psz_chain );
+    if( *psz_chain == '{' )
     {
-        const char *psz_name;
-
-        /* Skip the opening '{' */
-        p++;
-
-        /* parse all name=value[,] elements */
-        for( ;; )
+        /* Parse all name=value[,] elements */
+        do
         {
-            SKIPSPACE( p );
-
-            psz_name = p;
+            psz_chain++; /* skip previous delimiter */
+            SKIPSPACE( psz_chain );
 
             /* Look for the end of the name (,={}_space_) */
-            while( *p && *p != '=' && *p != ',' && *p != '{' && *p != '}' && !IsSpace( *p ) )
-                p++;
+            len = strcspn( psz_chain, "=,{} \t" );
+            if( len == 0 )
+                continue; /* ignore empty parameter */
 
-            // fprintf( stderr, "name=%s - rest=%s\n", psz_name, p );
-            if( p == psz_name )
-            {
-                fprintf( stderr, "config_ChainCreate: invalid options (empty) \n" );
+            /* Append the new parameter */
+            config_chain_t *p_cfg = malloc( sizeof(*p_cfg) );
+            if( !p_cfg )
                 break;
-            }
-
-            /* */
-            config_chain_t cfg;
-            cfg.psz_name = strndup( psz_name, p - psz_name );
-            cfg.psz_value = NULL;
-            cfg.p_next = NULL;
+            p_cfg->psz_name = strndup( psz_chain, len );
+            psz_chain += len;
+            p_cfg->psz_value = NULL;
+            p_cfg->p_next = NULL;
 
-            /* Parse the option name parameter */
-            SKIPSPACE( p );
+            *pp_next = p_cfg;
+            pp_next = &p_cfg->p_next;
 
-            if( *p == '=' || *p == '{' )
+            /* Extract the option value */
+            SKIPSPACE( psz_chain );
+            if( strchr( "={", *psz_chain ) )
             {
-                cfg.psz_value = ChainGetValue( &p );
-
-                SKIPSPACE( p );
-            }
-
-            /* Append the new option */
-            config_chain_t *p_new = malloc( sizeof(*p_new) );
-            if( !p_new )
-            {
-                free( cfg.psz_name );
-                free( cfg.psz_value );
-                break;
-            }
-            *p_new = cfg;
-
-            if( p_cfg )
-            {
-                p_cfg->p_next = p_new;
-                p_cfg = p_cfg->p_next;
-            }
-            else
-            {
-                *pp_cfg = p_cfg = p_new;
-            }
-
-            /* */
-            if( *p == ',' )
-                p++;
-
-            if( *p == '}' )
-            {
-                p++;
-                break;
+                p_cfg->psz_value = ChainGetValue( &psz_chain );
+                SKIPSPACE( psz_chain );
             }
         }
+        while( !memchr( "}", *psz_chain, 2 ) );
+
+        if( *psz_chain ) psz_chain++; /* skip '}' */;
+        SKIPSPACE( psz_chain );
     }
 
-    if( *p == ':' )
-        return strdup( &p[1] );
+    if( *psz_chain == ':' )
+        return strdup( psz_chain + 1 );
 
     return NULL;
 }
@@ -295,8 +256,9 @@ void config_ChainDestroy( config_chain_t *p_cfg )
     }
 }
 
-void __config_ChainParse( vlc_object_t *p_this, const char *psz_prefix,
-                          const char *const *ppsz_options, config_chain_t *cfg )
+#undef config_ChainParse
+void config_ChainParse( vlc_object_t *p_this, const char *psz_prefix,
+                        const char *const *ppsz_options, config_chain_t *cfg )
 {
     if( psz_prefix == NULL ) psz_prefix = "";
     size_t plen = 1 + strlen( psz_prefix );
@@ -422,7 +384,7 @@ void __config_ChainParse( vlc_object_t *p_this, const char *psz_prefix,
                                     NULL, 0 );
                 break;
             case VLC_VAR_FLOAT:
-                val.f_float = atof( cfg->psz_value ? cfg->psz_value : "0" );
+                val.f_float = us_atof( cfg->psz_value ? cfg->psz_value : "0" );
                 break;
             case VLC_VAR_STRING:
             case VLC_VAR_MODULE:
@@ -452,6 +414,26 @@ void __config_ChainParse( vlc_object_t *p_this, const char *psz_prefix,
     }
 }
 
+config_chain_t *config_ChainDuplicate( const config_chain_t *p_src )
+{
+    config_chain_t *p_dst = NULL;
+    config_chain_t **pp_last = &p_dst;
+
+    for( ; p_src != NULL; p_src = p_src->p_next )
+    {
+        config_chain_t *p = malloc( sizeof(*p) );
+        if( !p )
+            break;
+        p->p_next    = NULL;
+        p->psz_name  = p_src->psz_name  ? strdup( p_src->psz_name )  : NULL;
+        p->psz_value = p_src->psz_value ? strdup( p_src->psz_value ) : NULL;
+
+        *pp_last = p;
+        pp_last = &p->p_next;
+    }
+    return p_dst;
+}
+
 char *config_StringUnescape( char *psz_string )
 {
     char *psz_src = psz_string;