dte test coverage


Directory: ./
File: src/command/args.h
Date: 2025-02-14 16:55:22
Exec Total Coverage
Lines: 30 30 100.0%
Functions: 7 7 100.0%
Branches: 9 12 75.0%

Line Branch Exec Source
1 #ifndef COMMAND_ARGS_H
2 #define COMMAND_ARGS_H
3
4 #include <stdbool.h>
5 #include <stddef.h>
6 #include <stdint.h>
7 #include "error.h"
8 #include "run.h"
9 #include "util/base64.h"
10 #include "util/debug.h"
11 #include "util/macros.h"
12
13 typedef enum {
14 ARGERR_NONE,
15 ARGERR_INVALID_OPTION,
16 ARGERR_TOO_MANY_OPTIONS,
17 ARGERR_OPTION_ARGUMENT_MISSING,
18 ARGERR_OPTION_ARGUMENT_NOT_SEPARATE,
19 ARGERR_TOO_FEW_ARGUMENTS,
20 ARGERR_TOO_MANY_ARGUMENTS,
21 } ArgParseError;
22
23 typedef struct {
24 char ch;
25 unsigned int val;
26 } FlagMapping;
27
28 8411 static inline CommandArgs cmdargs_new(char **args)
29 {
30 8411 return (CommandArgs){.args = args};
31 }
32
33 // Map ASCII alphanumeric characters to values between 1 and 62,
34 // for use as bitset indices in CommandArgs::flag_set
35 11579 static inline unsigned int cmdargs_flagset_idx(unsigned char c)
36 {
37 // We use base64_decode() here simply because it does a similar byte
38 // mapping to the one we want and allows us to share the lookup table.
39 // There's no "real" base64 encoding involved.
40 11579 static_assert(BASE64_INVALID > 63);
41
1/2
✗ Branch 0 (2→3) not taken.
✓ Branch 1 (2→4) taken 11579 times.
11579 unsigned int idx = IS_CT_CONSTANT(c) ? base64_decode_branchy(c) : base64_decode(c);
42 11579 BUG_ON(idx > 61);
43 11579 return idx + 1;
44 }
45
46 11510 static inline uint_least64_t cmdargs_flagset_value(unsigned char flag)
47 {
48 11510 return UINT64_C(1) << cmdargs_flagset_idx(flag);
49 }
50
51 9094 static inline bool cmdargs_has_flag(const CommandArgs *a, unsigned char flag)
52 {
53 9094 uint_least64_t bitmask = cmdargs_flagset_value(flag);
54 9094 static_assert_compatible_types(bitmask, a->flag_set);
55 9094 return (a->flag_set & bitmask) != 0;
56 }
57
58 61 static inline char cmdargs_pick_winning_flag_from_set(const CommandArgs *a, uint_least64_t flagset)
59 {
60
2/2
✓ Branch 0 (2→3) taken 3 times.
✓ Branch 1 (2→10) taken 58 times.
61 if (!(a->flag_set & flagset)) {
61 return 0;
62 }
63
64 3 BUG_ON(a->nr_flags > ARRAYLEN(a->flags));
65
1/2
✓ Branch 0 (9→6) taken 3 times.
✗ Branch 1 (9→10) not taken.
3 for (size_t n = a->nr_flags, i = n - 1; i < n; i--) {
66 3 char flag = a->flags[i];
67
1/2
✗ Branch 0 (7→8) not taken.
✓ Branch 1 (7→10) taken 3 times.
3 if (flagset & cmdargs_flagset_value(flag)) {
68 return flag;
69 }
70 }
71
72 return 0;
73 }
74
75 54 static inline char cmdargs_pick_winning_flag(const CommandArgs *a, char f1, char f2)
76 {
77 54 uint_least64_t set = cmdargs_flagset_value(f1) | cmdargs_flagset_value(f2);
78 54 char flag = cmdargs_pick_winning_flag_from_set(a, set);
79 54 BUG_ON(flag && flag != f1 && flag != f2);
80 54 return flag;
81 }
82
83 // Convert CommandArgs::flag_set to bit flags of a different format,
84 // by using a set of mappings
85 21 static inline unsigned int cmdargs_convert_flags (
86 const CommandArgs *a,
87 const FlagMapping *map,
88 size_t map_len
89 ) {
90 21 unsigned int val = 0;
91 UNROLL_LOOP(16)
92
2/2
✓ Branch 0 (7→3) taken 82 times.
✓ Branch 1 (7→8) taken 21 times.
103 for (size_t i = 0; i < map_len; i++, map++) {
93
2/2
✓ Branch 0 (4→5) taken 13 times.
✓ Branch 1 (4→6) taken 69 times.
82 if (cmdargs_has_flag(a, map->ch)) {
94 13 val |= map->val;
95 }
96 }
97 21 return val;
98 }
99
100 bool parse_args(const Command *cmd, CommandArgs *a, ErrorBuffer *ebuf) NONNULL_ARGS WARN_UNUSED_RESULT;
101 ArgParseError do_parse_args(const Command *cmd, CommandArgs *a) NONNULL_ARGS WARN_UNUSED_RESULT;
102
103 #endif
104