2 * Copyright (c) 2020, Alliance for Open Media. All rights reserved
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.
11 #include "common/args_helper.h"
19 #define SET_ERR_STRING(...) \
20 if (err_msg) snprintf(err_msg, ARG_ERR_MSG_MAX_LEN, __VA_ARGS__)
22 struct arg
arg_init(char **argv
) {
33 int arg_match_helper(struct arg
*arg_
, const struct arg_def
*def
, char **argv
,
37 if (err_msg
) err_msg
[0] = '\0';
39 assert(def
->has_val
== 0 || def
->has_val
== 1 || def
->has_val
== -1);
41 if (!argv
[0] || argv
[0][0] != '-') return 0;
45 if (def
->short_name
&& !strcmp(arg
.argv
[0] + 1, def
->short_name
)) {
46 arg
.name
= arg
.argv
[0] + 1;
47 arg
.val
= def
->has_val
? arg
.argv
[1] : NULL
;
48 arg
.argv_step
= def
->has_val
? 2 : 1;
49 } else if (def
->long_name
) {
50 const size_t name_len
= strlen(def
->long_name
);
52 if (arg
.argv
[0][1] == '-' &&
53 !strncmp(arg
.argv
[0] + 2, def
->long_name
, name_len
) &&
54 (arg
.argv
[0][name_len
+ 2] == '=' ||
55 arg
.argv
[0][name_len
+ 2] == '\0')) {
56 arg
.name
= arg
.argv
[0] + 2;
57 arg
.val
= arg
.name
[name_len
] == '=' ? arg
.name
+ name_len
+ 1 : NULL
;
63 if (def
->has_val
== -1) {
69 if (!arg
.val
&& def
->has_val
) {
70 SET_ERR_STRING("Error: option %s requires argument.\n", arg
.name
);
74 if (arg
.val
&& !def
->has_val
) {
75 SET_ERR_STRING("Error: option %s requires no argument.\n", arg
.name
);
87 unsigned int arg_parse_uint_helper(const struct arg
*arg
, char *err_msg
) {
89 const unsigned long rawval
= strtoul(arg
->val
, &endptr
, 10); // NOLINT
91 if (err_msg
) err_msg
[0] = '\0';
93 if (arg
->val
[0] != '\0' && endptr
[0] == '\0') {
94 if (rawval
<= UINT_MAX
) return (unsigned int)rawval
;
95 SET_ERR_STRING("Option %s: Value %lu out of range for unsigned int\n",
99 SET_ERR_STRING("Option %s: Invalid character '%c'\n", arg
->name
, *endptr
);
103 int arg_parse_int_helper(const struct arg
*arg
, char *err_msg
) {
105 const long rawval
= strtol(arg
->val
, &endptr
, 10); // NOLINT
107 if (err_msg
) err_msg
[0] = '\0';
109 if (arg
->val
[0] != '\0' && endptr
[0] == '\0') {
110 if (rawval
>= INT_MIN
&& rawval
<= INT_MAX
) return (int)rawval
;
111 SET_ERR_STRING("Option %s: Value %ld out of range for signed int\n",
115 SET_ERR_STRING("Option %s: Invalid character '%c'\n", arg
->name
, *endptr
);
119 struct aom_rational
arg_parse_rational_helper(const struct arg
*arg
,
121 long rawval
; // NOLINT
123 struct aom_rational rat
= { 0, 1 };
125 if (err_msg
) err_msg
[0] = '\0';
127 /* parse numerator */
128 rawval
= strtol(arg
->val
, &endptr
, 10);
130 if (arg
->val
[0] != '\0' && endptr
[0] == '/') {
131 if (rawval
>= INT_MIN
&& rawval
<= INT_MAX
) {
132 rat
.num
= (int)rawval
;
134 SET_ERR_STRING("Option %s: Value %ld out of range for signed int\n",
139 SET_ERR_STRING("Option %s: Expected / at '%c'\n", arg
->name
, *endptr
);
143 /* parse denominator */
144 rawval
= strtol(endptr
+ 1, &endptr
, 10);
146 if (arg
->val
[0] != '\0' && endptr
[0] == '\0') {
147 if (rawval
>= INT_MIN
&& rawval
<= INT_MAX
) {
148 rat
.den
= (int)rawval
;
150 SET_ERR_STRING("Option %s: Value %ld out of range for signed int\n",
155 SET_ERR_STRING("Option %s: Invalid character '%c'\n", arg
->name
, *endptr
);
162 int arg_parse_enum_helper(const struct arg
*arg
, char *err_msg
) {
163 const struct arg_enum_list
*listptr
;
164 long rawval
; // NOLINT
167 if (err_msg
) err_msg
[0] = '\0';
169 /* First see if the value can be parsed as a raw value */
170 rawval
= strtol(arg
->val
, &endptr
, 10);
171 if (arg
->val
[0] != '\0' && endptr
[0] == '\0') {
172 /* Got a raw value, make sure it's valid */
173 for (listptr
= arg
->def
->enums
; listptr
->name
; listptr
++)
174 if (listptr
->val
== rawval
) return (int)rawval
;
177 /* Next see if it can be parsed as a string */
178 for (listptr
= arg
->def
->enums
; listptr
->name
; listptr
++)
179 if (!strcmp(arg
->val
, listptr
->name
)) return listptr
->val
;
181 SET_ERR_STRING("Option %s: Invalid value '%s'\n", arg
->name
, arg
->val
);
185 int arg_parse_enum_or_int_helper(const struct arg
*arg
, char *err_msg
) {
186 if (arg
->def
->enums
) return arg_parse_enum_helper(arg
, err_msg
);
187 return arg_parse_int_helper(arg
, err_msg
);
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
,
194 const char *ptr
= arg
->val
;
198 if (err_msg
) err_msg
[0] = '\0';
200 while (ptr
[0] != '\0') {
201 long rawval
= strtol(ptr
, &endptr
, 10); // NOLINT
202 if (rawval
< INT_MIN
|| rawval
> INT_MAX
) {
203 SET_ERR_STRING("Option %s: Value %ld out of range for signed int\n",
207 SET_ERR_STRING("Option %s: List has more than %d entries\n", arg
->name
,
210 } else if (*endptr
== ',') {
212 } else if (*endptr
!= '\0') {
213 SET_ERR_STRING("Option %s: Bad list separator '%c'\n", arg
->name
,
217 list
[i
++] = (int)rawval
;