Mercurial > mplayer.hg
annotate subopt-helper.c @ 32334:541a774ce8e4
Drop removal of AAC encoder from list of FFmpeg encoders.
The original reason to drop this particular encoder, that it
failed to build on many platforms, should no longer be the case.
author | diego |
---|---|
date | Fri, 01 Oct 2010 16:04:43 +0000 |
parents | 32725ca88fed |
children | fdf3f93c2828 |
rev | line source |
---|---|
30429
c1a3f1bbba26
Add license header to all top-level files missing them.
diego
parents:
30123
diff
changeset
|
1 /* |
c1a3f1bbba26
Add license header to all top-level files missing them.
diego
parents:
30123
diff
changeset
|
2 * This file is part of MPlayer. |
c1a3f1bbba26
Add license header to all top-level files missing them.
diego
parents:
30123
diff
changeset
|
3 * |
c1a3f1bbba26
Add license header to all top-level files missing them.
diego
parents:
30123
diff
changeset
|
4 * MPlayer is free software; you can redistribute it and/or modify |
c1a3f1bbba26
Add license header to all top-level files missing them.
diego
parents:
30123
diff
changeset
|
5 * it under the terms of the GNU General Public License as published by |
c1a3f1bbba26
Add license header to all top-level files missing them.
diego
parents:
30123
diff
changeset
|
6 * the Free Software Foundation; either version 2 of the License, or |
c1a3f1bbba26
Add license header to all top-level files missing them.
diego
parents:
30123
diff
changeset
|
7 * (at your option) any later version. |
c1a3f1bbba26
Add license header to all top-level files missing them.
diego
parents:
30123
diff
changeset
|
8 * |
c1a3f1bbba26
Add license header to all top-level files missing them.
diego
parents:
30123
diff
changeset
|
9 * MPlayer is distributed in the hope that it will be useful, |
c1a3f1bbba26
Add license header to all top-level files missing them.
diego
parents:
30123
diff
changeset
|
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
c1a3f1bbba26
Add license header to all top-level files missing them.
diego
parents:
30123
diff
changeset
|
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
c1a3f1bbba26
Add license header to all top-level files missing them.
diego
parents:
30123
diff
changeset
|
12 * GNU General Public License for more details. |
c1a3f1bbba26
Add license header to all top-level files missing them.
diego
parents:
30123
diff
changeset
|
13 * |
c1a3f1bbba26
Add license header to all top-level files missing them.
diego
parents:
30123
diff
changeset
|
14 * You should have received a copy of the GNU General Public License along |
c1a3f1bbba26
Add license header to all top-level files missing them.
diego
parents:
30123
diff
changeset
|
15 * with MPlayer; if not, write to the Free Software Foundation, Inc., |
c1a3f1bbba26
Add license header to all top-level files missing them.
diego
parents:
30123
diff
changeset
|
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
c1a3f1bbba26
Add license header to all top-level files missing them.
diego
parents:
30123
diff
changeset
|
17 */ |
c1a3f1bbba26
Add license header to all top-level files missing them.
diego
parents:
30123
diff
changeset
|
18 |
29252 | 19 /** |
14281 | 20 * \file subopt-helper.c |
21 * | |
22 * \brief Compensates the suboption parsing code duplication a bit. | |
23 * | |
24 * The routines defined below are there to help you with the | |
25 * suboption parsing. Meaning extracting the options and their | |
26 * values for you and also outputting generic help message if | |
27 * a parse error is encountered. | |
28 * | |
29 * Most stuff happens in the subopt_parse function: if you call it | |
30 * it parses for the passed opts in the passed string. It calls some | |
31 * extra functions for explicit argument parsing ( where the option | |
32 * itself isn't the argument but a value given after the argument | |
33 * delimiter ('='). It also calls your test function if you supplied | |
34 * one. | |
35 * | |
36 */ | |
37 | |
38 #include "subopt-helper.h" | |
39 #include "mp_msg.h" | |
40 | |
41 #include <stdlib.h> | |
42 #include <string.h> | |
14538
00c3c4111017
New suboption type: malloc'ed, zero terminated string
reimar
parents:
14294
diff
changeset
|
43 #include <limits.h> |
14281 | 44 #include <assert.h> |
45 | |
46 #ifndef MPDEBUG | |
47 #define NDEBUG | |
48 #endif | |
49 | |
50 /* prototypes for argument parsing */ | |
51 static char const * parse_int( char const * const str, int * const valp ); | |
52 static char const * parse_str( char const * const str, strarg_t * const valp ); | |
16720 | 53 static char const * parse_float( char const * const str, float * const valp ); |
14281 | 54 |
55 /** | |
56 * \brief Try to parse all options in str and fail if it was not possible. | |
57 * | |
58 * \param str Pointer to the zero terminated string to be parsed. | |
59 * \param opts Pointer to a options array. The array must be terminated | |
60 * with an element having set name to NULL in its opt_t structure. | |
61 * | |
62 * \return The return value is zero if the string could be parsed | |
63 * else a non-zero value is returned. | |
64 * | |
65 */ | |
28827
2b021e3e1000
Get rid of the "set" member of the subopt-parser struct, it made
reimar
parents:
22283
diff
changeset
|
66 int subopt_parse( char const * const str, const opt_t * opts ) |
14281 | 67 { |
68 int parse_err = 0, idx; | |
69 unsigned int parse_pos = 0; | |
70 | |
71 if ( str ) | |
72 { | |
73 while ( str[parse_pos] && !parse_err ) | |
74 { | |
75 int next = 0; | |
76 | |
77 idx = 0; // reset index for the below loop | |
78 while ( opts[idx].name ) | |
79 { | |
80 int opt_len; | |
81 int substr_len; | |
82 | |
83 // get length of the option we test against */ | |
84 opt_len = strlen( opts[idx].name ); | |
85 | |
86 // get length of the current substring of str */ | |
87 { | |
88 char * delim, * arg_delim; | |
89 | |
29252 | 90 /* search nearest delimiter ( option or argument delimiter ) */ |
14281 | 91 delim = strchr( &str[parse_pos], ':' ); |
92 arg_delim = strchr( &str[parse_pos], '=' ); | |
93 | |
94 if ( ( delim && arg_delim && delim > arg_delim ) || | |
95 delim == NULL ) | |
96 { | |
97 delim = strchr( &str[parse_pos], '=' ); | |
98 } | |
29252 | 99 |
14281 | 100 substr_len = delim ? // is a delim present |
101 delim - &str[parse_pos] : // yes | |
102 strlen( &str[parse_pos] ); // no, end of string | |
103 } | |
104 | |
105 //printf( "substr_len=%d, opt_len=%d\n", substr_len, opt_len ); | |
106 | |
107 /* Check if the length of the current option matches the * | |
108 * length of the option we want to test again. */ | |
109 if ( substr_len == opt_len ) | |
110 { | |
111 /* check if option was activated/deactivated */ | |
112 if( strncmp( &str[parse_pos], opts[idx].name, opt_len ) == 0 ) | |
113 { | |
114 /* option was found */ | |
28827
2b021e3e1000
Get rid of the "set" member of the subopt-parser struct, it made
reimar
parents:
22283
diff
changeset
|
115 next = 1; |
14281 | 116 |
117 assert( opts[idx].valp && "Need a pointer to store the arg!" ); | |
118 | |
119 /* type specific code */ | |
120 if ( opts[idx].type == OPT_ARG_BOOL ) | |
121 { | |
22283
bc9e95184521
cosmetics: Fix some common typos, sepErate --> sepArate, deciSSion --> deciSion.
diego
parents:
19104
diff
changeset
|
122 /* Handle OPT_ARG_BOOL separately so * |
14281 | 123 * the others can share code. */ |
124 | |
125 /* set option to true */ | |
126 *((int *)(opts[idx].valp)) = 1; | |
127 | |
128 /* increment position */ | |
129 parse_pos += opt_len; | |
130 } | |
131 else | |
132 { | |
133 /* Type is not OPT_ARG_BOOL, means we have to parse * | |
134 * for the arg delimiter character and eventually * | |
135 * call a test function. */ | |
136 char const * last; | |
137 | |
138 /* increment position to check for arg */ | |
139 parse_pos += opt_len; | |
140 | |
141 if ( str[parse_pos] != '=' ) | |
142 { | |
143 parse_err = 1; break; | |
144 } | |
145 | |
146 /* '=' char was there, so let's move after it */ | |
147 ++parse_pos; | |
148 | |
149 switch ( opts[idx].type ) | |
150 { | |
151 case OPT_ARG_INT: | |
152 last = parse_int( &str[parse_pos], | |
153 (int *)opts[idx].valp ); | |
154 | |
155 break; | |
156 case OPT_ARG_STR: | |
157 last = parse_str( &str[parse_pos], | |
158 (strarg_t *)opts[idx].valp ); | |
159 break; | |
14538
00c3c4111017
New suboption type: malloc'ed, zero terminated string
reimar
parents:
14294
diff
changeset
|
160 case OPT_ARG_MSTRZ: |
00c3c4111017
New suboption type: malloc'ed, zero terminated string
reimar
parents:
14294
diff
changeset
|
161 { |
00c3c4111017
New suboption type: malloc'ed, zero terminated string
reimar
parents:
14294
diff
changeset
|
162 char **valp = opts[idx].valp; |
00c3c4111017
New suboption type: malloc'ed, zero terminated string
reimar
parents:
14294
diff
changeset
|
163 strarg_t tmp; |
00c3c4111017
New suboption type: malloc'ed, zero terminated string
reimar
parents:
14294
diff
changeset
|
164 tmp.str = NULL; |
00c3c4111017
New suboption type: malloc'ed, zero terminated string
reimar
parents:
14294
diff
changeset
|
165 tmp.len = 0; |
00c3c4111017
New suboption type: malloc'ed, zero terminated string
reimar
parents:
14294
diff
changeset
|
166 last = parse_str( &str[parse_pos], &tmp ); |
00c3c4111017
New suboption type: malloc'ed, zero terminated string
reimar
parents:
14294
diff
changeset
|
167 if (*valp) |
00c3c4111017
New suboption type: malloc'ed, zero terminated string
reimar
parents:
14294
diff
changeset
|
168 free(*valp); |
00c3c4111017
New suboption type: malloc'ed, zero terminated string
reimar
parents:
14294
diff
changeset
|
169 *valp = NULL; |
00c3c4111017
New suboption type: malloc'ed, zero terminated string
reimar
parents:
14294
diff
changeset
|
170 if (tmp.str && tmp.len > 0) { |
00c3c4111017
New suboption type: malloc'ed, zero terminated string
reimar
parents:
14294
diff
changeset
|
171 *valp = malloc(tmp.len + 1); |
00c3c4111017
New suboption type: malloc'ed, zero terminated string
reimar
parents:
14294
diff
changeset
|
172 memcpy(*valp, tmp.str, tmp.len); |
14572 | 173 (*valp)[tmp.len] = 0; |
14538
00c3c4111017
New suboption type: malloc'ed, zero terminated string
reimar
parents:
14294
diff
changeset
|
174 } |
00c3c4111017
New suboption type: malloc'ed, zero terminated string
reimar
parents:
14294
diff
changeset
|
175 break; |
00c3c4111017
New suboption type: malloc'ed, zero terminated string
reimar
parents:
14294
diff
changeset
|
176 } |
16720 | 177 case OPT_ARG_FLOAT: |
178 last = parse_float( &str[parse_pos], | |
179 (float *)opts[idx].valp ); | |
180 break; | |
14281 | 181 default: |
182 assert( 0 && "Arg type of suboption doesn't exist!" ); | |
183 last = NULL; // break parsing! | |
184 } | |
185 | |
186 /* was the conversion succesful? */ | |
187 if ( !last ) | |
188 { | |
189 parse_err = 1; break; | |
190 } | |
191 | |
192 /* make test if supplied */ | |
193 if ( opts[idx].test && !opts[idx].test( opts[idx].valp ) ) | |
194 { | |
195 parse_err = 1; break; | |
196 } | |
197 | |
198 /* we succeded, set position */ | |
199 parse_pos = last - str; | |
200 } | |
201 } | |
202 } | |
203 else if ( substr_len == opt_len+2 ) | |
204 { | |
205 if ( opts[idx].type == OPT_ARG_BOOL && // check for no<opt> | |
206 strncmp( &str[parse_pos], "no", 2 ) == 0 && | |
207 strncmp( &str[parse_pos+2], opts[idx].name, opt_len ) == 0 ) | |
208 { | |
209 /* option was found but negated */ | |
28827
2b021e3e1000
Get rid of the "set" member of the subopt-parser struct, it made
reimar
parents:
22283
diff
changeset
|
210 next = 1; |
14281 | 211 |
212 /* set arg to false */ | |
213 *((int *)(opts[idx].valp)) = 0; | |
214 | |
215 /* increment position */ | |
216 parse_pos += opt_len+2; | |
217 } | |
218 } | |
219 | |
220 ++idx; // test against next option | |
221 | |
222 /* break out of the loop, if this subopt is processed */ | |
223 if ( next ) { break; } | |
224 } | |
29252 | 225 |
14281 | 226 /* if we had a valid suboption the current pos should * |
227 * equal the delimiter char, which should be ':' for * | |
228 * suboptions. */ | |
229 if ( !parse_err && str[parse_pos] == ':' ) { ++parse_pos; } | |
230 else if ( str[parse_pos] ) { parse_err = 1; } | |
231 } | |
232 } | |
233 | |
234 /* if an error was encountered */ | |
235 if (parse_err) | |
236 { | |
237 unsigned int i; | |
238 mp_msg( MSGT_VO, MSGL_FATAL, "Could not parse arguments at the position indicated below:\n%s\n", str ); | |
239 for ( i = 0; i < parse_pos; ++i ) | |
240 { | |
241 mp_msg(MSGT_VO, MSGL_FATAL, " "); | |
242 } | |
243 mp_msg(MSGT_VO, MSGL_FATAL, "^\n"); | |
244 | |
245 return -1; | |
246 } | |
247 | |
248 /* we could parse everything */ | |
249 return 0; | |
250 } | |
251 | |
252 static char const * parse_int( char const * const str, int * const valp ) | |
253 { | |
254 char * endp; | |
255 | |
256 assert( str && "parse_int(): str == NULL" ); | |
257 | |
258 *valp = (int)strtol( str, &endp, 0 ); | |
259 | |
260 /* nothing was converted */ | |
261 if ( str == endp ) { return NULL; } | |
262 | |
263 return endp; | |
264 } | |
265 | |
16720 | 266 static char const * parse_float( char const * const str, float * const valp ) |
267 { | |
268 char * endp; | |
269 | |
270 assert( str && "parse_float(): str == NULL" ); | |
271 | |
16725
2a7220c457a7
1l, strtof is only C99, strtod is ANSI C, so use that instead.
reimar
parents:
16720
diff
changeset
|
272 *valp = strtod( str, &endp ); |
16720 | 273 |
274 /* nothing was converted */ | |
275 if ( str == endp ) { return NULL; } | |
276 | |
277 return endp; | |
278 } | |
279 | |
15733
e678e306068e
support lenght-quoting of strings in subopt parser.
reimar
parents:
14736
diff
changeset
|
280 #define QUOTE_CHAR '%' |
e678e306068e
support lenght-quoting of strings in subopt parser.
reimar
parents:
14736
diff
changeset
|
281 static char const * parse_str( char const * str, strarg_t * const valp ) |
14281 | 282 { |
283 char const * match = strchr( str, ':' ); | |
284 | |
15733
e678e306068e
support lenght-quoting of strings in subopt parser.
reimar
parents:
14736
diff
changeset
|
285 if (str[0] == QUOTE_CHAR) { |
e678e306068e
support lenght-quoting of strings in subopt parser.
reimar
parents:
14736
diff
changeset
|
286 int len = 0; |
e678e306068e
support lenght-quoting of strings in subopt parser.
reimar
parents:
14736
diff
changeset
|
287 str = &str[1]; |
e678e306068e
support lenght-quoting of strings in subopt parser.
reimar
parents:
14736
diff
changeset
|
288 len = (int)strtol(str, (char **)&str, 0); |
e678e306068e
support lenght-quoting of strings in subopt parser.
reimar
parents:
14736
diff
changeset
|
289 if (!str || str[0] != QUOTE_CHAR || (len > strlen(str) - 1)) |
e678e306068e
support lenght-quoting of strings in subopt parser.
reimar
parents:
14736
diff
changeset
|
290 return NULL; |
e678e306068e
support lenght-quoting of strings in subopt parser.
reimar
parents:
14736
diff
changeset
|
291 str = &str[1]; |
e678e306068e
support lenght-quoting of strings in subopt parser.
reimar
parents:
14736
diff
changeset
|
292 match = &str[len]; |
e678e306068e
support lenght-quoting of strings in subopt parser.
reimar
parents:
14736
diff
changeset
|
293 } |
e678e306068e
support lenght-quoting of strings in subopt parser.
reimar
parents:
14736
diff
changeset
|
294 else |
16609 | 295 if (str[0] == '"') { |
296 str = &str[1]; | |
297 match = strchr(str, '"'); | |
298 if (!match) | |
299 return NULL; | |
300 valp->len = match - str; | |
301 valp->str = str; | |
302 return &match[1]; | |
303 } | |
14281 | 304 if ( !match ) |
14294
90bcd37dba7f
fix string argument parsing (e.g. one char strings were not accepted)
reimar
parents:
14281
diff
changeset
|
305 match = &str[strlen(str)]; |
90bcd37dba7f
fix string argument parsing (e.g. one char strings were not accepted)
reimar
parents:
14281
diff
changeset
|
306 |
90bcd37dba7f
fix string argument parsing (e.g. one char strings were not accepted)
reimar
parents:
14281
diff
changeset
|
307 // empty string or too long |
14538
00c3c4111017
New suboption type: malloc'ed, zero terminated string
reimar
parents:
14294
diff
changeset
|
308 if ((match == str) || (match - str > INT_MAX)) |
14294
90bcd37dba7f
fix string argument parsing (e.g. one char strings were not accepted)
reimar
parents:
14281
diff
changeset
|
309 return NULL; |
14281 | 310 |
311 valp->len = match - str; | |
312 valp->str = str; | |
313 | |
314 return match; | |
315 } | |
14736 | 316 |
317 | |
318 /*** common test functions ***/ | |
319 | |
320 /** \brief Test if i is not negative */ | |
30122
1772a5171ac7
Fix function declarations to avoid casting function pointers.
reimar
parents:
29252
diff
changeset
|
321 int int_non_neg(void *iptr) |
14736 | 322 { |
30122
1772a5171ac7
Fix function declarations to avoid casting function pointers.
reimar
parents:
29252
diff
changeset
|
323 int *i = iptr; |
30123
0f5f75b4a015
Simplify range-checking functions for subopt parsing.
reimar
parents:
30122
diff
changeset
|
324 return *i >= 0; |
14736 | 325 } |
326 /** \brief Test if i is positive. */ | |
30122
1772a5171ac7
Fix function declarations to avoid casting function pointers.
reimar
parents:
29252
diff
changeset
|
327 int int_pos(void *iptr) |
14736 | 328 { |
30122
1772a5171ac7
Fix function declarations to avoid casting function pointers.
reimar
parents:
29252
diff
changeset
|
329 int *i = iptr; |
30123
0f5f75b4a015
Simplify range-checking functions for subopt parsing.
reimar
parents:
30122
diff
changeset
|
330 return *i > 0; |
14736 | 331 } |
15734
7e4fa8fc255c
helper functions for comparing strarg_t "strings".
reimar
parents:
15733
diff
changeset
|
332 |
7e4fa8fc255c
helper functions for comparing strarg_t "strings".
reimar
parents:
15733
diff
changeset
|
333 /*** little helpers */ |
7e4fa8fc255c
helper functions for comparing strarg_t "strings".
reimar
parents:
15733
diff
changeset
|
334 |
7e4fa8fc255c
helper functions for comparing strarg_t "strings".
reimar
parents:
15733
diff
changeset
|
335 /** \brief compare the stings just as strcmp does */ |
19104
2ec2301183cd
marks several read-only string parameters which aren't modified inside the called function as const. Patch by Stefan Huehner, stefan AT huehner-org
reynaldo
parents:
16725
diff
changeset
|
336 int strargcmp(strarg_t *arg, const char *str) { |
15734
7e4fa8fc255c
helper functions for comparing strarg_t "strings".
reimar
parents:
15733
diff
changeset
|
337 int res = strncmp(arg->str, str, arg->len); |
7e4fa8fc255c
helper functions for comparing strarg_t "strings".
reimar
parents:
15733
diff
changeset
|
338 if (!res && arg->len != strlen(str)) |
7e4fa8fc255c
helper functions for comparing strarg_t "strings".
reimar
parents:
15733
diff
changeset
|
339 res = arg->len - strlen(str); |
7e4fa8fc255c
helper functions for comparing strarg_t "strings".
reimar
parents:
15733
diff
changeset
|
340 return res; |
7e4fa8fc255c
helper functions for comparing strarg_t "strings".
reimar
parents:
15733
diff
changeset
|
341 } |
7e4fa8fc255c
helper functions for comparing strarg_t "strings".
reimar
parents:
15733
diff
changeset
|
342 |
7e4fa8fc255c
helper functions for comparing strarg_t "strings".
reimar
parents:
15733
diff
changeset
|
343 /** \brief compare the stings just as strcasecmp does */ |
7e4fa8fc255c
helper functions for comparing strarg_t "strings".
reimar
parents:
15733
diff
changeset
|
344 int strargcasecmp(strarg_t *arg, char *str) { |
7e4fa8fc255c
helper functions for comparing strarg_t "strings".
reimar
parents:
15733
diff
changeset
|
345 int res = strncasecmp(arg->str, str, arg->len); |
7e4fa8fc255c
helper functions for comparing strarg_t "strings".
reimar
parents:
15733
diff
changeset
|
346 if (!res && arg->len != strlen(str)) |
7e4fa8fc255c
helper functions for comparing strarg_t "strings".
reimar
parents:
15733
diff
changeset
|
347 res = arg->len - strlen(str); |
7e4fa8fc255c
helper functions for comparing strarg_t "strings".
reimar
parents:
15733
diff
changeset
|
348 return res; |
7e4fa8fc255c
helper functions for comparing strarg_t "strings".
reimar
parents:
15733
diff
changeset
|
349 } |