1#include "internal.h"
2
3enum errno cmdline_extract_bool(struct cmdline_value *val, bool *out) {
4 if (!val || !out)
5 return ERR_INVAL;
6
7 if (val->mode == CMDLINE_MODE_TYPED && val->write_to &&
8 val->c_type == TYPE_BOOL) {
9 *out = *(bool *) val->write_to;
10 return ERR_OK;
11 }
12
13 if (val->type == CMDLINE_TYPE_BOOL) {
14 *out = val->b;
15 return ERR_OK;
16 }
17
18 return ERR_INVAL;
19}
20
21enum errno cmdline_extract_u64(struct cmdline_value *val, uint64_t *out) {
22 if (!val || !out)
23 return ERR_INVAL;
24
25 if (val->mode == CMDLINE_MODE_TYPED && val->write_to) {
26 switch (val->c_type) {
27 case TYPE_UINT64: *out = *(uint64_t *) val->write_to; return ERR_OK;
28 case TYPE_INT64: {
29 int64_t v = *(int64_t *) val->write_to;
30 if (v < 0)
31 return ERR_OVERFLOW;
32 *out = (uint64_t) v;
33 return ERR_OK;
34 }
35 case TYPE_UINT32: *out = *(uint32_t *) val->write_to; return ERR_OK;
36 case TYPE_INT32: {
37 int32_t v = *(int32_t *) val->write_to;
38 if (v < 0)
39 return ERR_OVERFLOW;
40 *out = (uint64_t) v;
41 return ERR_OK;
42 }
43 case TYPE_UINT16: *out = *(uint16_t *) val->write_to; return ERR_OK;
44 case TYPE_INT16: {
45 int16_t v = *(int16_t *) val->write_to;
46 if (v < 0)
47 return ERR_OVERFLOW;
48 *out = (uint64_t) v;
49 return ERR_OK;
50 }
51 case TYPE_UINT8: *out = *(uint8_t *) val->write_to; return ERR_OK;
52 case TYPE_INT8: {
53 int8_t v = *(int8_t *) val->write_to;
54 if (v < 0)
55 return ERR_OVERFLOW;
56 *out = (uint64_t) v;
57 return ERR_OK;
58 }
59 default: return ERR_INVAL;
60 }
61 }
62
63 if (val->type == CMDLINE_TYPE_INT) {
64 if (val->i64 < 0)
65 return ERR_OVERFLOW;
66 *out = (uint64_t) val->i64;
67 return ERR_OK;
68 }
69
70 if (val->type == CMDLINE_TYPE_UINT || val->type == CMDLINE_TYPE_DATA_SIZE ||
71 val->type == CMDLINE_TYPE_DURATION || val->type == CMDLINE_TYPE_MAC) {
72 *out = val->u64;
73 return ERR_OK;
74 }
75
76 return ERR_INVAL;
77}
78
79enum errno cmdline_extract_i64(struct cmdline_value *val, int64_t *out) {
80 if (!val || !out)
81 return ERR_INVAL;
82
83 if (val->mode == CMDLINE_MODE_TYPED && val->write_to) {
84 switch (val->c_type) {
85 case TYPE_INT64: *out = *(int64_t *) val->write_to; return ERR_OK;
86 case TYPE_UINT64: {
87 uint64_t v = *(uint64_t *) val->write_to;
88 if (v > (uint64_t) INT64_MAX)
89 return ERR_OVERFLOW;
90 *out = (int64_t) v;
91 return ERR_OK;
92 }
93 case TYPE_INT32: *out = *(int32_t *) val->write_to; return ERR_OK;
94 case TYPE_UINT32: *out = *(uint32_t *) val->write_to; return ERR_OK;
95 case TYPE_INT16: *out = *(int16_t *) val->write_to; return ERR_OK;
96 case TYPE_UINT16: *out = *(uint16_t *) val->write_to; return ERR_OK;
97 case TYPE_INT8: *out = *(int8_t *) val->write_to; return ERR_OK;
98 case TYPE_UINT8: *out = *(uint8_t *) val->write_to; return ERR_OK;
99 default: return ERR_INVAL;
100 }
101 }
102
103 if (val->type == CMDLINE_TYPE_INT) {
104 *out = val->i64;
105 return ERR_OK;
106 }
107
108 if (val->type == CMDLINE_TYPE_UINT || val->type == CMDLINE_TYPE_DATA_SIZE ||
109 val->type == CMDLINE_TYPE_DURATION) {
110 if (val->u64 > (uint64_t) INT64_MAX)
111 return ERR_OVERFLOW;
112 *out = (int64_t) val->u64;
113 return ERR_OK;
114 }
115
116 return ERR_INVAL;
117}
118
119enum errno cmdline_extract_u32(struct cmdline_value *val, uint32_t *out) {
120 if (!val || !out)
121 return ERR_INVAL;
122
123 if (val->mode == CMDLINE_MODE_TYPED && val->write_to) {
124 switch (val->c_type) {
125 case TYPE_UINT32: *out = *(uint32_t *) val->write_to; return ERR_OK;
126 case TYPE_INT32: {
127 int32_t v = *(int32_t *) val->write_to;
128 if (v < 0)
129 return ERR_OVERFLOW;
130 *out = (uint32_t) v;
131 return ERR_OK;
132 }
133 case TYPE_UINT64: {
134 uint64_t v = *(uint64_t *) val->write_to;
135 if (v > UINT32_MAX)
136 return ERR_OVERFLOW;
137 *out = (uint32_t) v;
138 return ERR_OK;
139 }
140 case TYPE_INT64: {
141 int64_t v = *(int64_t *) val->write_to;
142 if (v < 0 || (uint64_t) v > UINT32_MAX)
143 return ERR_OVERFLOW;
144 *out = (uint32_t) v;
145 return ERR_OK;
146 }
147 case TYPE_UINT16: *out = *(uint16_t *) val->write_to; return ERR_OK;
148 case TYPE_INT16: {
149 int16_t v = *(int16_t *) val->write_to;
150 if (v < 0)
151 return ERR_OVERFLOW;
152 *out = (uint32_t) v;
153 return ERR_OK;
154 }
155 case TYPE_UINT8: *out = *(uint8_t *) val->write_to; return ERR_OK;
156 case TYPE_INT8: {
157 int8_t v = *(int8_t *) val->write_to;
158 if (v < 0)
159 return ERR_OVERFLOW;
160 *out = (uint32_t) v;
161 return ERR_OK;
162 }
163 default: return ERR_INVAL;
164 }
165 }
166
167 if (val->type == CMDLINE_TYPE_UINT || val->type == CMDLINE_TYPE_DATA_SIZE ||
168 val->type == CMDLINE_TYPE_DURATION) {
169 uint64_t v = val->u64;
170 if (v > UINT32_MAX)
171 return ERR_OVERFLOW;
172 *out = (uint32_t) v;
173 return ERR_OK;
174 }
175
176 if (val->type == CMDLINE_TYPE_INT) {
177 int64_t v = val->i64;
178 if (v < 0 || (uint64_t) v > UINT32_MAX)
179 return ERR_OVERFLOW;
180 *out = (uint32_t) v;
181 return ERR_OK;
182 }
183
184 return ERR_INVAL;
185}
186
187enum errno cmdline_extract_i32(struct cmdline_value *val, int32_t *out) {
188 if (!val || !out)
189 return ERR_INVAL;
190
191 if (val->mode == CMDLINE_MODE_TYPED && val->write_to) {
192 switch (val->c_type) {
193 case TYPE_INT32: *out = *(int32_t *) val->write_to; return ERR_OK;
194 case TYPE_UINT32: {
195 uint32_t v = *(uint32_t *) val->write_to;
196 if (v > (uint32_t) INT32_MAX)
197 return ERR_OVERFLOW;
198 *out = (int32_t) v;
199 return ERR_OK;
200 }
201 case TYPE_INT64: {
202 int64_t v = *(int64_t *) val->write_to;
203 if (v < INT32_MIN || v > INT32_MAX)
204 return ERR_OVERFLOW;
205 *out = (int32_t) v;
206 return ERR_OK;
207 }
208 case TYPE_UINT64: {
209 uint64_t v = *(uint64_t *) val->write_to;
210 if (v > (uint64_t) INT32_MAX)
211 return ERR_OVERFLOW;
212 *out = (int32_t) v;
213 return ERR_OK;
214 }
215 case TYPE_INT16: *out = *(int16_t *) val->write_to; return ERR_OK;
216 case TYPE_UINT16: *out = *(uint16_t *) val->write_to; return ERR_OK;
217 case TYPE_INT8: *out = *(int8_t *) val->write_to; return ERR_OK;
218 case TYPE_UINT8: *out = *(uint8_t *) val->write_to; return ERR_OK;
219 default: return ERR_INVAL;
220 }
221 }
222
223 if (val->type == CMDLINE_TYPE_INT) {
224 int64_t v = val->i64;
225 if (v < INT32_MIN || v > INT32_MAX)
226 return ERR_OVERFLOW;
227 *out = (int32_t) v;
228 return ERR_OK;
229 }
230
231 if (val->type == CMDLINE_TYPE_UINT || val->type == CMDLINE_TYPE_DATA_SIZE ||
232 val->type == CMDLINE_TYPE_DURATION) {
233 uint64_t v = val->u64;
234 if (v > (uint64_t) INT32_MAX)
235 return ERR_OVERFLOW;
236 *out = (int32_t) v;
237 return ERR_OK;
238 }
239
240 return ERR_INVAL;
241}
242
243enum errno cmdline_extract_fx(struct cmdline_value *val, fx32_32_t *out) {
244 if (!val || !out)
245 return ERR_INVAL;
246
247 if (val->type == CMDLINE_TYPE_FX) {
248 *out = val->fx;
249 return ERR_OK;
250 }
251
252 return ERR_INVAL;
253}
254
255enum errno cmdline_extract_duration(struct cmdline_value *val, time_ns_t *out) {
256 if (!val || !out)
257 return ERR_INVAL;
258
259 if (val->type == CMDLINE_TYPE_DURATION) {
260 *out = val->duration;
261 return ERR_OK;
262 }
263
264 return ERR_INVAL;
265}
266
267enum errno cmdline_extract_mac(struct cmdline_value *val, uint64_t *out) {
268 if (!val || !out)
269 return ERR_INVAL;
270
271 if (val->type == CMDLINE_TYPE_MAC) {
272 *out = val->u64;
273 return ERR_OK;
274 }
275
276 return ERR_INVAL;
277}
278
279enum errno cmdline_extract_range(struct cmdline_value *val,
280 struct cmdline_range *out) {
281 if (!val || !out || val->type != CMDLINE_TYPE_RANGE || !val->data)
282 return ERR_INVAL;
283 *out = *(struct cmdline_range *) val->data;
284 return ERR_OK;
285}
286
287enum errno cmdline_extract_cpu_mask(struct cmdline_value *val,
288 struct cpu_mask *out) {
289 if (!val || !out)
290 return ERR_INVAL;
291
292 if (val->type == CMDLINE_TYPE_CPU_MASK && val->data) {
293 *out = *(struct cpu_mask *) val->data;
294 return ERR_OK;
295 }
296
297 return ERR_INVAL;
298}
299
300enum errno cmdline_extract_string(struct cmdline_value *val, char **out) {
301 if (!val || !out)
302 return ERR_INVAL;
303
304 if (val->type == CMDLINE_TYPE_STRING && val->data) {
305 *out = (char *) val->data;
306 return ERR_OK;
307 }
308
309 return ERR_INVAL;
310}
311
312enum errno cmdline_extract_const_string(struct cmdline_value *val,
313 const char **out) {
314 return cmdline_extract_string(val, out: (char **) out);
315}
316
317enum errno cmdline_extract_list(struct cmdline_value *val,
318 struct cmdline_list *out) {
319 if (!val || !out)
320 return ERR_INVAL;
321
322 if (val->type == CMDLINE_TYPE_LIST && val->data) {
323 *out = *(struct cmdline_list *) val->data;
324 return ERR_OK;
325 }
326
327 return ERR_INVAL;
328}
329
330enum errno cmdline_extract_u16(struct cmdline_value *val, uint16_t *out) {
331 if (!val || !out)
332 return ERR_INVAL;
333 uint32_t v = 0;
334 enum errno err = cmdline_extract_u32(val, out: &v);
335 if (err != ERR_OK)
336 return err;
337 if (v > UINT16_MAX)
338 return ERR_OVERFLOW;
339 *out = (uint16_t) v;
340 return ERR_OK;
341}
342
343enum errno cmdline_extract_i16(struct cmdline_value *val, int16_t *out) {
344 if (!val || !out)
345 return ERR_INVAL;
346 int32_t v = 0;
347 enum errno err = cmdline_extract_i32(val, out: &v);
348 if (err != ERR_OK)
349 return err;
350 if (v < INT16_MIN || v > INT16_MAX)
351 return ERR_OVERFLOW;
352 *out = (int16_t) v;
353 return ERR_OK;
354}
355
356enum errno cmdline_extract_u8(struct cmdline_value *val, uint8_t *out) {
357 if (!val || !out)
358 return ERR_INVAL;
359 uint32_t v = 0;
360 enum errno err = cmdline_extract_u32(val, out: &v);
361 if (err != ERR_OK)
362 return err;
363 if (v > UINT8_MAX)
364 return ERR_OVERFLOW;
365 *out = (uint8_t) v;
366 return ERR_OK;
367}
368
369enum errno cmdline_extract_i8(struct cmdline_value *val, int8_t *out) {
370 if (!val || !out)
371 return ERR_INVAL;
372 int32_t v = 0;
373 enum errno err = cmdline_extract_i32(val, out: &v);
374 if (err != ERR_OK)
375 return err;
376 if (v < INT8_MIN || v > INT8_MAX)
377 return ERR_OVERFLOW;
378 *out = (int8_t) v;
379 return ERR_OK;
380}
381
382uint64_t cmdline_entry_value_u64(const struct cmdline_entry *e) {
383 if (!e)
384 return 0;
385
386 if (cmdline_value_is_typed(val: &e->value) && e->value.write_to) {
387 switch (e->value.c_type) {
388 case TYPE_BOOL: return *(const bool *) e->value.write_to;
389 case TYPE_INT8: return (uint64_t) *(const int8_t *) e->value.write_to;
390 case TYPE_UINT8: return *(const uint8_t *) e->value.write_to;
391 case TYPE_INT16: return (uint64_t) *(const int16_t *) e->value.write_to;
392 case TYPE_UINT16: return *(const uint16_t *) e->value.write_to;
393 case TYPE_INT32: return (uint64_t) *(const int32_t *) e->value.write_to;
394 case TYPE_UINT32: return *(const uint32_t *) e->value.write_to;
395 case TYPE_INT64: return (uint64_t) *(const int64_t *) e->value.write_to;
396 case TYPE_UINT64: return *(const uint64_t *) e->value.write_to;
397 default: return *(const uint64_t *) e->value.write_to;
398 }
399 }
400
401 if (e->types >= (1ULL << CMDLINE_TYPE_OFFSET)) {
402 if (e->value.type == CMDLINE_TYPE_STRING ||
403 e->value.type == CMDLINE_TYPE_LIST ||
404 e->value.type == CMDLINE_TYPE_CPU_MASK ||
405 e->value.type == CMDLINE_TYPE_RANGE) {
406 panic("CMDLINE_VALUE called on non-scalar cmdline entry '%s'",
407 e->name);
408 }
409 }
410
411 return e->value.u64;
412}
413