Fix two bugs in 4:4:4 chroma weightp analysis
[x262.git] / filters / filters.c
1 /*****************************************************************************
2  * filters.c: common filter functions
3  *****************************************************************************
4  * Copyright (C) 2010-2011 x264 project
5  *
6  * Authors: Diogo Franco <diogomfranco@gmail.com>
7  *          Steven Walters <kemuri9@gmail.com>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111, USA.
22  *
23  * This program is also available under a commercial proprietary license.
24  * For more information, contact us at licensing@x264.com.
25  *****************************************************************************/
26
27 #include "filters.h"
28 #define RETURN_IF_ERROR( cond, ... ) RETURN_IF_ERR( cond, "options", NULL, __VA_ARGS__ )
29
30 char **x264_split_string( char *string, char *sep, int limit )
31 {
32     if( !string )
33         return NULL;
34     int sep_count = 0;
35     char *tmp = string;
36     while( ( tmp = ( tmp = strstr( tmp, sep ) ) ? tmp + strlen( sep ) : 0 ) )
37         ++sep_count;
38     if( sep_count == 0 )
39     {
40         if( string[0] == '\0' )
41             return calloc( 1, sizeof( char** ) );
42         char **ret = calloc( 2, sizeof( char** ) );
43         ret[0] = strdup( string );
44         return ret;
45     }
46
47     char **split = calloc( ( limit > 0 ? limit : sep_count ) + 2, sizeof(char**) );
48     int i = 0;
49     char *str = strdup( string );
50     assert( str );
51     char *esc = NULL;
52     char *tok = str, *nexttok = str;
53     do
54     {
55         nexttok = strstr( nexttok, sep );
56         if( nexttok )
57             *nexttok++ = '\0';
58         if( ( limit > 0 && i >= limit ) ||
59             ( i > 0 && ( ( esc = strrchr( split[i-1], '\\' ) ) ? esc[1] == '\0' : 0 ) ) ) // Allow escaping
60         {
61             int j = i-1;
62             if( esc )
63                 esc[0] = '\0';
64             split[j] = realloc( split[j], strlen( split[j] ) + strlen( sep ) + strlen( tok ) + 1 );
65             assert( split[j] );
66             strcat( split[j], sep );
67             strcat( split[j], tok );
68             esc = NULL;
69         }
70         else
71         {
72             split[i++] = strdup( tok );
73             assert( split[i-1] );
74         }
75         tok = nexttok;
76     } while ( tok );
77     free( str );
78     assert( !split[i] );
79
80     return split;
81 }
82
83 void x264_free_string_array( char **array )
84 {
85     if( !array )
86         return;
87     for( int i = 0; array[i] != NULL; i++ )
88         free( array[i] );
89     free( array );
90 }
91
92 char **x264_split_options( const char *opt_str, const char *options[] )
93 {
94     if( !opt_str )
95         return NULL;
96     char *opt_str_dup = strdup( opt_str );
97     char **split = x264_split_string( opt_str_dup, ",", 0 );
98     free( opt_str_dup );
99     int split_count = 0;
100     while( split[split_count] != NULL )
101         ++split_count;
102
103     int options_count = 0;
104     while( options[options_count] != NULL )
105         ++options_count;
106
107     char **opts = calloc( split_count * 2 + 2, sizeof( char ** ) );
108     char **arg = NULL;
109     int opt = 0, found_named = 0, invalid = 0;
110     for( int i = 0; split[i] != NULL; i++, invalid = 0 )
111     {
112         arg = x264_split_string( split[i], "=", 2 );
113         if( arg == NULL )
114         {
115             if( found_named )
116                 invalid = 1;
117             else RETURN_IF_ERROR( i > options_count || options[i] == NULL, "Too many options given\n" )
118             else
119             {
120                 opts[opt++] = strdup( options[i] );
121                 opts[opt++] = strdup( "" );
122             }
123         }
124         else if( arg[0] == NULL || arg[1] == NULL )
125         {
126             if( found_named )
127                 invalid = 1;
128             else RETURN_IF_ERROR( i > options_count || options[i] == NULL, "Too many options given\n" )
129             else
130             {
131                 opts[opt++] = strdup( options[i] );
132                 if( arg[0] )
133                     opts[opt++] = strdup( arg[0] );
134                 else
135                     opts[opt++] = strdup( "" );
136             }
137         }
138         else
139         {
140             found_named = 1;
141             int j = 0;
142             while( options[j] != NULL && strcmp( arg[0], options[j] ) )
143                 ++j;
144             RETURN_IF_ERROR( options[j] == NULL, "Invalid option '%s'\n", arg[0] )
145             else
146             {
147                 opts[opt++] = strdup( arg[0] );
148                 opts[opt++] = strdup( arg[1] );
149             }
150         }
151         RETURN_IF_ERROR( invalid, "Ordered option given after named\n" )
152         x264_free_string_array( arg );
153     }
154     x264_free_string_array( split );
155     return opts;
156 }
157
158 char *x264_get_option( const char *name, char **split_options )
159 {
160     if( !split_options )
161         return NULL;
162     int last_i = -1;
163     for( int i = 0; split_options[i] != NULL; i += 2 )
164         if( !strcmp( split_options[i], name ) )
165             last_i = i;
166     if( last_i >= 0 )
167         return split_options[last_i+1][0] ? split_options[last_i+1] : NULL;
168     return NULL;
169 }
170
171 int x264_otob( char *str, int def )
172 {
173    int ret = def;
174    if( str )
175        ret = !strcasecmp( str, "true" ) ||
176              !strcmp( str, "1" ) ||
177              !strcasecmp( str, "yes" );
178    return ret;
179 }
180
181 double x264_otof( char *str, double def )
182 {
183    double ret = def;
184    if( str )
185    {
186        char *end;
187        ret = strtod( str, &end );
188        if( end == str || *end != '\0' )
189            ret = def;
190    }
191    return ret;
192 }
193
194 int x264_otoi( char *str, int def )
195 {
196     int ret = def;
197     if( str )
198     {
199         char *end;
200         ret = strtol( str, &end, 0 );
201         if( end == str || *end != '\0' )
202             ret = def;
203     }
204     return ret;
205 }
206
207 char *x264_otos( char *str, char *def )
208 {
209     return str ? str : def;
210 }