dte test coverage


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