filter_chain: make filter_chain_AppendFromString() iterative
authorRémi Denis-Courmont <remi@remlab.net>
Mon, 28 Jul 2014 18:22:14 +0000 (21:22 +0300)
committerRémi Denis-Courmont <remi@remlab.net>
Mon, 28 Jul 2014 20:16:07 +0000 (23:16 +0300)
(rather than recursive)

src/misc/filter_chain.c

index 460c5ff..4143fdc 100644 (file)
@@ -2,7 +2,7 @@
  * filter_chain.c : Handle chains of filter_t objects.
  *****************************************************************************
  * Copyright (C) 2008 VLC authors and VideoLAN
- * $Id$
+ * Copyright (C) 2008-2014 Rémi Denis-Courmont
  *
  * Author: Antoine Cellerier <dionoea at videolan dot org>
  *
@@ -92,8 +92,6 @@ static filter_t *filter_chain_AppendFilterInternal( filter_chain_t *,
                                                     const char *, config_chain_t *,
                                                     const es_format_t *, const es_format_t * );
 
-static int filter_chain_AppendFromStringInternal( filter_chain_t *, const char * );
-
 static int filter_chain_DeleteFilterInternal( filter_chain_t *, filter_t * );
 
 static int UpdateBufferFunctions( filter_chain_t * );
@@ -182,15 +180,50 @@ filter_t *filter_chain_AppendFilter( filter_chain_t *p_chain,
     return p_filter;
 }
 
-int filter_chain_AppendFromString( filter_chain_t *p_chain,
-                                   const char *psz_string )
+int filter_chain_AppendFromString( filter_chain_t *chain, const char *str )
 {
-    const int i_ret = filter_chain_AppendFromStringInternal( p_chain, psz_string );
-    if( i_ret < 0 )
-        return i_ret;
+    char *buf = NULL;
+    int ret = 0;
 
-    /* FIXME That one seems bad if a error is returned */
-    return UpdateBufferFunctions( p_chain );
+    while( str != NULL && str[0] != '\0' )
+    {
+        config_chain_t *cfg;
+        char *name;
+
+        char *next = config_ChainCreate( &name, &cfg, str );
+
+        str = next;
+        free( buf );
+        buf = next;
+
+        filter_t *filter = filter_chain_AppendFilterInternal( chain, name, cfg,
+                                                              NULL, NULL );
+        if( filter == NULL )
+        {
+            msg_Err( chain->p_this, "Failed while trying to append '%s' "
+                     "to filter chain", name );
+            free( name );
+            free( cfg );
+            goto error;
+        }
+
+        free( name );
+        ret++;
+    }
+
+    if( UpdateBufferFunctions( chain ) )
+        assert( 0 ); /* should never happen, vf2 alloc cannot fail */
+    free( buf );
+    return ret;
+
+error:
+    while( ret > 0 ) /* Unwind */
+    {
+        filter_chain_DeleteFilterInternal( chain, &chain->last->filter );
+        ret--;
+    }
+    free( buf );
+    return -1;
 }
 
 int filter_chain_DeleteFilter( filter_chain_t *p_chain, filter_t *p_filter )
@@ -447,42 +480,6 @@ error:
     return NULL;
 }
 
-
-static int filter_chain_AppendFromStringInternal( filter_chain_t *p_chain,
-                                                  const char *psz_string )
-{
-    config_chain_t *p_cfg = NULL;
-    char *psz_name = NULL;
-    char* psz_new_string;
-
-    if( !psz_string || !*psz_string )
-        return 0;
-
-    psz_new_string = config_ChainCreate( &psz_name, &p_cfg, psz_string );
-
-    filter_t *p_filter = filter_chain_AppendFilterInternal( p_chain, psz_name,
-                                                            p_cfg, NULL, NULL );
-    if( !p_filter )
-    {
-        msg_Err( p_chain->p_this, "Failed while trying to append '%s' "
-                 "to filter chain", psz_name );
-        free( psz_name );
-        free( p_cfg );
-        free( psz_new_string );
-        return -1;
-    }
-    free( psz_name );
-
-    const int i_ret = filter_chain_AppendFromStringInternal( p_chain, psz_new_string );
-    free( psz_new_string );
-    if( i_ret < 0 )
-    {
-        filter_chain_DeleteFilterInternal( p_chain, p_filter );
-        return i_ret;
-    }
-    return 1 + i_ret;
-}
-
 static int filter_chain_DeleteFilterInternal( filter_chain_t *p_chain,
                                               filter_t *p_filter )
 {