/src/aom/common/args_helper.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright (c) 2020, Alliance for Open Media. All rights reserved. |
3 | | * |
4 | | * This source code is subject to the terms of the BSD 2 Clause License and |
5 | | * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License |
6 | | * was not distributed with this source code in the LICENSE file, you can |
7 | | * obtain it at www.aomedia.org/license/software. If the Alliance for Open |
8 | | * Media Patent License 1.0 was not distributed with this source code in the |
9 | | * PATENTS file, you can obtain it at www.aomedia.org/license/patent. |
10 | | */ |
11 | | #include "common/args_helper.h" |
12 | | |
13 | | #include <assert.h> |
14 | | #include <stdio.h> |
15 | | #include <stdlib.h> |
16 | | #include <string.h> |
17 | | #include <limits.h> |
18 | | |
19 | | #define SET_ERR_STRING(...) \ |
20 | 0 | if (err_msg) snprintf(err_msg, ARG_ERR_MSG_MAX_LEN, __VA_ARGS__) |
21 | | |
22 | 0 | static struct arg arg_init(char **argv) { |
23 | 0 | struct arg a; |
24 | |
|
25 | 0 | a.argv = argv; |
26 | 0 | a.argv_step = 1; |
27 | 0 | a.name = NULL; |
28 | 0 | a.val = NULL; |
29 | 0 | a.def = NULL; |
30 | 0 | return a; |
31 | 0 | } |
32 | | |
33 | | int arg_match_helper(struct arg *arg_, const struct arg_def *def, char **argv, |
34 | 0 | char *err_msg) { |
35 | 0 | struct arg arg; |
36 | |
|
37 | 0 | if (err_msg) err_msg[0] = '\0'; |
38 | |
|
39 | 0 | assert(def->has_val == 0 || def->has_val == 1 || def->has_val == -1); |
40 | |
|
41 | 0 | if (!argv[0] || argv[0][0] != '-') return 0; |
42 | | |
43 | 0 | arg = arg_init(argv); |
44 | |
|
45 | 0 | if (def->short_name && !strcmp(arg.argv[0] + 1, def->short_name)) { |
46 | 0 | arg.name = arg.argv[0] + 1; |
47 | 0 | arg.val = def->has_val ? arg.argv[1] : NULL; |
48 | 0 | arg.argv_step = def->has_val ? 2 : 1; |
49 | 0 | } else if (def->long_name) { |
50 | 0 | const size_t name_len = strlen(def->long_name); |
51 | |
|
52 | 0 | if (arg.argv[0][1] == '-' && |
53 | 0 | !strncmp(arg.argv[0] + 2, def->long_name, name_len) && |
54 | 0 | (arg.argv[0][name_len + 2] == '=' || |
55 | 0 | arg.argv[0][name_len + 2] == '\0')) { |
56 | 0 | arg.name = arg.argv[0] + 2; |
57 | 0 | arg.val = arg.name[name_len] == '=' ? arg.name + name_len + 1 : NULL; |
58 | 0 | arg.argv_step = 1; |
59 | 0 | } |
60 | 0 | } |
61 | |
|
62 | 0 | if (arg.name) { |
63 | 0 | if (def->has_val == -1) { |
64 | 0 | arg.def = def; |
65 | 0 | *arg_ = arg; |
66 | 0 | return 1; |
67 | 0 | } |
68 | | |
69 | 0 | if (!arg.val && def->has_val) { |
70 | 0 | SET_ERR_STRING("Error: option %s requires argument.\n", arg.name); |
71 | 0 | return 0; |
72 | 0 | } |
73 | | |
74 | 0 | if (arg.val && !def->has_val) { |
75 | 0 | SET_ERR_STRING("Error: option %s requires no argument.\n", arg.name); |
76 | 0 | return 0; |
77 | 0 | } |
78 | | |
79 | 0 | arg.def = def; |
80 | 0 | *arg_ = arg; |
81 | 0 | return 1; |
82 | 0 | } |
83 | | |
84 | 0 | return 0; |
85 | 0 | } |
86 | | |
87 | 0 | unsigned int arg_parse_uint_helper(const struct arg *arg, char *err_msg) { |
88 | 0 | char *endptr; |
89 | 0 | const unsigned long rawval = strtoul(arg->val, &endptr, 10); // NOLINT |
90 | |
|
91 | 0 | if (err_msg) err_msg[0] = '\0'; |
92 | |
|
93 | 0 | if (arg->val[0] != '\0' && endptr[0] == '\0') { |
94 | 0 | if (rawval <= UINT_MAX) return (unsigned int)rawval; |
95 | 0 | SET_ERR_STRING("Option %s: Value %lu out of range for unsigned int\n", |
96 | 0 | arg->name, rawval); |
97 | 0 | return 0; |
98 | 0 | } |
99 | 0 | SET_ERR_STRING("Option %s: Invalid character '%c'\n", arg->name, *endptr); |
100 | 0 | return 0; |
101 | 0 | } |
102 | | |
103 | 0 | int arg_parse_int_helper(const struct arg *arg, char *err_msg) { |
104 | 0 | char *endptr; |
105 | 0 | const long rawval = strtol(arg->val, &endptr, 10); // NOLINT |
106 | |
|
107 | 0 | if (err_msg) err_msg[0] = '\0'; |
108 | |
|
109 | 0 | if (arg->val[0] != '\0' && endptr[0] == '\0') { |
110 | 0 | if (rawval >= INT_MIN && rawval <= INT_MAX) return (int)rawval; |
111 | 0 | SET_ERR_STRING("Option %s: Value %ld out of range for signed int\n", |
112 | 0 | arg->name, rawval); |
113 | 0 | return 0; |
114 | 0 | } |
115 | 0 | SET_ERR_STRING("Option %s: Invalid character '%c'\n", arg->name, *endptr); |
116 | 0 | return 0; |
117 | 0 | } |
118 | | |
119 | | struct aom_rational arg_parse_rational_helper(const struct arg *arg, |
120 | 0 | char *err_msg) { |
121 | 0 | long rawval; // NOLINT |
122 | 0 | char *endptr; |
123 | 0 | struct aom_rational rat = { 0, 1 }; |
124 | |
|
125 | 0 | if (err_msg) err_msg[0] = '\0'; |
126 | | |
127 | | /* parse numerator */ |
128 | 0 | rawval = strtol(arg->val, &endptr, 10); |
129 | |
|
130 | 0 | if (arg->val[0] != '\0' && endptr[0] == '/') { |
131 | 0 | if (rawval >= INT_MIN && rawval <= INT_MAX) { |
132 | 0 | rat.num = (int)rawval; |
133 | 0 | } else { |
134 | 0 | SET_ERR_STRING("Option %s: Value %ld out of range for signed int\n", |
135 | 0 | arg->name, rawval); |
136 | 0 | return rat; |
137 | 0 | } |
138 | 0 | } else { |
139 | 0 | SET_ERR_STRING("Option %s: Expected / at '%c'\n", arg->name, *endptr); |
140 | 0 | return rat; |
141 | 0 | } |
142 | | |
143 | | /* parse denominator */ |
144 | 0 | rawval = strtol(endptr + 1, &endptr, 10); |
145 | |
|
146 | 0 | if (arg->val[0] != '\0' && endptr[0] == '\0') { |
147 | 0 | if (rawval >= INT_MIN && rawval <= INT_MAX) { |
148 | 0 | rat.den = (int)rawval; |
149 | 0 | } else { |
150 | 0 | SET_ERR_STRING("Option %s: Value %ld out of range for signed int\n", |
151 | 0 | arg->name, rawval); |
152 | 0 | return rat; |
153 | 0 | } |
154 | 0 | } else { |
155 | 0 | SET_ERR_STRING("Option %s: Invalid character '%c'\n", arg->name, *endptr); |
156 | 0 | return rat; |
157 | 0 | } |
158 | | |
159 | 0 | return rat; |
160 | 0 | } |
161 | | |
162 | 0 | int arg_parse_enum_helper(const struct arg *arg, char *err_msg) { |
163 | 0 | const struct arg_enum_list *listptr; |
164 | 0 | long rawval; // NOLINT |
165 | 0 | char *endptr; |
166 | |
|
167 | 0 | if (err_msg) err_msg[0] = '\0'; |
168 | | |
169 | | /* First see if the value can be parsed as a raw value */ |
170 | 0 | rawval = strtol(arg->val, &endptr, 10); |
171 | 0 | if (arg->val[0] != '\0' && endptr[0] == '\0') { |
172 | | /* Got a raw value, make sure it's valid */ |
173 | 0 | for (listptr = arg->def->enums; listptr->name; listptr++) |
174 | 0 | if (listptr->val == rawval) return (int)rawval; |
175 | 0 | } |
176 | | |
177 | | /* Next see if it can be parsed as a string */ |
178 | 0 | for (listptr = arg->def->enums; listptr->name; listptr++) |
179 | 0 | if (!strcmp(arg->val, listptr->name)) return listptr->val; |
180 | | |
181 | 0 | SET_ERR_STRING("Option %s: Invalid value '%s'\n", arg->name, arg->val); |
182 | 0 | return 0; |
183 | 0 | } |
184 | | |
185 | 0 | int arg_parse_enum_or_int_helper(const struct arg *arg, char *err_msg) { |
186 | 0 | if (arg->def->enums) return arg_parse_enum_helper(arg, err_msg); |
187 | 0 | return arg_parse_int_helper(arg, err_msg); |
188 | 0 | } |
189 | | |
190 | | // parse a comma separated list of at most n integers |
191 | | // return the number of elements in the list |
192 | | int arg_parse_list_helper(const struct arg *arg, int *list, int n, |
193 | 0 | char *err_msg) { |
194 | 0 | const char *ptr = arg->val; |
195 | 0 | char *endptr; |
196 | 0 | int i = 0; |
197 | |
|
198 | 0 | if (err_msg) err_msg[0] = '\0'; |
199 | |
|
200 | 0 | while (ptr[0] != '\0') { |
201 | 0 | long rawval = strtol(ptr, &endptr, 10); // NOLINT |
202 | 0 | if (rawval < INT_MIN || rawval > INT_MAX) { |
203 | 0 | SET_ERR_STRING("Option %s: Value %ld out of range for signed int\n", |
204 | 0 | arg->name, rawval); |
205 | 0 | return 0; |
206 | 0 | } else if (i >= n) { |
207 | 0 | SET_ERR_STRING("Option %s: List has more than %d entries\n", arg->name, |
208 | 0 | n); |
209 | 0 | return 0; |
210 | 0 | } else if (*endptr == ',') { |
211 | 0 | endptr++; |
212 | 0 | } else if (*endptr != '\0') { |
213 | 0 | SET_ERR_STRING("Option %s: Bad list separator '%c'\n", arg->name, |
214 | 0 | *endptr); |
215 | 0 | return 0; |
216 | 0 | } |
217 | 0 | list[i++] = (int)rawval; |
218 | 0 | ptr = endptr; |
219 | 0 | } |
220 | 0 | return i; |
221 | 0 | } |