#include "filters.h"
#define RETURN_IF_ERROR( cond, ... ) RETURN_IF_ERR( cond, "options", NULL, __VA_ARGS__ )
char **x264_split_string( char *string, char *sep, int limit )
{
if( !string )
return NULL;
int sep_count = 0;
int sep_len = strlen( sep );
char *tmp = string;
while( ( tmp = ( tmp = strstr( tmp, sep ) ) ? tmp + sep_len : 0 ) )
++sep_count;
if( sep_count == 0 )
{
if( string[0] == '\0' )
return calloc( 1, sizeof( char* ) );
char **ret = calloc( 2, sizeof( char* ) );
ret[0] = strdup( string );
return ret;
}
char **split = calloc( ( limit > 0 ? limit : sep_count ) + 2, sizeof(char*) );
int i = 0;
char *str = strdup( string );
assert( str );
char *esc = NULL;
char *tok = str, *nexttok = str;
do
{
nexttok = strstr( nexttok, sep );
if( nexttok )
*nexttok++ = '\0';
if( ( limit > 0 && i >= limit ) ||
( i > 0 && ( ( esc = strrchr( split[i-1], '\\' ) ) ? esc[1] == '\0' : 0 ) ) )
{
int j = i-1;
if( esc )
esc[0] = '\0';
split[j] = realloc( split[j], strlen( split[j] ) + sep_len + strlen( tok ) + 1 );
assert( split[j] );
strcat( split[j], sep );
strcat( split[j], tok );
esc = NULL;
}
else
{
split[i++] = strdup( tok );
assert( split[i-1] );
}
tok = nexttok;
} while ( tok );
free( str );
assert( !split[i] );
return split;
}
void x264_free_string_array( char **array )
{
if( !array )
return;
for( int i = 0; array[i] != NULL; i++ )
free( array[i] );
free( array );
}
char **x264_split_options( const char *opt_str, const char *options[] )
{
if( !opt_str )
return NULL;
char *opt_str_dup = strdup( opt_str );
char **split = x264_split_string( opt_str_dup, ",", 0 );
free( opt_str_dup );
int split_count = 0;
while( split[split_count] != NULL )
++split_count;
int options_count = 0;
while( options[options_count] != NULL )
++options_count;
char **opts = calloc( split_count * 2 + 2, sizeof( char * ) );
char **arg = NULL;
int opt = 0, found_named = 0, invalid = 0;
for( int i = 0; split[i] != NULL; i++, invalid = 0 )
{
arg = x264_split_string( split[i], "=", 2 );
if( arg == NULL )
{
if( found_named )
invalid = 1;
else RETURN_IF_ERROR( i > options_count || options[i] == NULL, "Too many options given\n" )
else
{
opts[opt++] = strdup( options[i] );
opts[opt++] = strdup( "" );
}
}
else if( arg[0] == NULL || arg[1] == NULL )
{
if( found_named )
invalid = 1;
else RETURN_IF_ERROR( i > options_count || options[i] == NULL, "Too many options given\n" )
else
{
opts[opt++] = strdup( options[i] );
if( arg[0] )
opts[opt++] = strdup( arg[0] );
else
opts[opt++] = strdup( "" );
}
}
else
{
found_named = 1;
int j = 0;
while( options[j] != NULL && strcmp( arg[0], options[j] ) )
++j;
RETURN_IF_ERROR( options[j] == NULL, "Invalid option '%s'\n", arg[0] )
else
{
opts[opt++] = strdup( arg[0] );
opts[opt++] = strdup( arg[1] );
}
}
RETURN_IF_ERROR( invalid, "Ordered option given after named\n" )
x264_free_string_array( arg );
}
x264_free_string_array( split );
return opts;
}
char *x264_get_option( const char *name, char **split_options )
{
if( !split_options )
return NULL;
int last_i = -1;
for( int i = 0; split_options[i] != NULL; i += 2 )
if( !strcmp( split_options[i], name ) )
last_i = i;
if( last_i >= 0 )
return split_options[last_i+1][0] ? split_options[last_i+1] : NULL;
return NULL;
}
int x264_otob( char *str, int def )
{
int ret = def;
if( str )
ret = !strcasecmp( str, "true" ) ||
!strcmp( str, "1" ) ||
!strcasecmp( str, "yes" );
return ret;
}
double x264_otof( char *str, double def )
{
double ret = def;
if( str )
{
char *end;
ret = strtod( str, &end );
if( end == str || *end != '\0' )
ret = def;
}
return ret;
}
int x264_otoi( char *str, int def )
{
int ret = def;
if( str )
{
char *end;
ret = strtol( str, &end, 0 );
if( end == str || *end != '\0' )
ret = def;
}
return ret;
}
char *x264_otos( char *str, char *def )
{
return str ? str : def;
}