master
c 189 lines 6.49 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 #include "rrdr_options.h"
4
5 static struct {
6 const char *name;
7 uint32_t hash;
8 RRDR_OPTIONS value;
9 } rrdr_options[] = {
10 { "nonzero" , 0 , RRDR_OPTION_NONZERO}
11 , {"flip" , 0 , RRDR_OPTION_REVERSED}
12 , {"reversed" , 0 , RRDR_OPTION_REVERSED}
13 , {"reverse" , 0 , RRDR_OPTION_REVERSED}
14 , {"jsonwrap" , 0 , RRDR_OPTION_JSON_WRAP}
15 , {"min2max" , 0 , RRDR_OPTION_DIMS_MIN2MAX} // rrdr2value() only
16 , {"average" , 0 , RRDR_OPTION_DIMS_AVERAGE} // rrdr2value() only
17 , {"min" , 0 , RRDR_OPTION_DIMS_MIN} // rrdr2value() only
18 , {"max" , 0 , RRDR_OPTION_DIMS_MAX} // rrdr2value() only
19 , {"ms" , 0 , RRDR_OPTION_MILLISECONDS}
20 , {"milliseconds" , 0 , RRDR_OPTION_MILLISECONDS}
21 , {"absolute" , 0 , RRDR_OPTION_ABSOLUTE}
22 , {"abs" , 0 , RRDR_OPTION_ABSOLUTE}
23 , {"absolute_sum" , 0 , RRDR_OPTION_ABSOLUTE}
24 , {"absolute-sum" , 0 , RRDR_OPTION_ABSOLUTE}
25 , {"display_absolute" , 0 , RRDR_OPTION_DISPLAY_ABS}
26 , {"display-absolute" , 0 , RRDR_OPTION_DISPLAY_ABS}
27 , {"seconds" , 0 , RRDR_OPTION_SECONDS}
28 , {"null2zero" , 0 , RRDR_OPTION_NULL2ZERO}
29 , {"objectrows" , 0 , RRDR_OPTION_OBJECTSROWS}
30 , {"google_json" , 0 , RRDR_OPTION_GOOGLE_JSON}
31 , {"google-json" , 0 , RRDR_OPTION_GOOGLE_JSON}
32 , {"percentage" , 0 , RRDR_OPTION_PERCENTAGE}
33 , {"unaligned" , 0 , RRDR_OPTION_NOT_ALIGNED}
34 , {"match_ids" , 0 , RRDR_OPTION_MATCH_IDS}
35 , {"match-ids" , 0 , RRDR_OPTION_MATCH_IDS}
36 , {"match_names" , 0 , RRDR_OPTION_MATCH_NAMES}
37 , {"match-names" , 0 , RRDR_OPTION_MATCH_NAMES}
38 , {"anomaly-bit" , 0 , RRDR_OPTION_ANOMALY_BIT}
39 , {"selected-tier" , 0 , RRDR_OPTION_SELECTED_TIER}
40 , {"raw" , 0 , RRDR_OPTION_RETURN_RAW}
41 , {"jw-anomaly-rates" , 0 , RRDR_OPTION_RETURN_JWAR}
42 , {"natural-points" , 0 , RRDR_OPTION_NATURAL_POINTS}
43 , {"virtual-points" , 0 , RRDR_OPTION_VIRTUAL_POINTS}
44 , {"all-dimensions" , 0 , RRDR_OPTION_ALL_DIMENSIONS}
45 , {"details" , 0 , RRDR_OPTION_SHOW_DETAILS}
46 , {"debug" , 0 , RRDR_OPTION_DEBUG}
47 , {"plan" , 0 , RRDR_OPTION_DEBUG}
48 , {"minify" , 0 , RRDR_OPTION_MINIFY}
49 , {"group-by-labels" , 0 , RRDR_OPTION_GROUP_BY_LABELS}
50 , {"label-quotes" , 0 , RRDR_OPTION_LABEL_QUOTES}
51 , {"minimal-stats" , 0 , RRDR_OPTION_MINIMAL_STATS}
52 , {"minimal" , 0 , RRDR_OPTION_MINIMAL_STATS}
53 , {"long-json-keys" , 0 , RRDR_OPTION_LONG_JSON_KEYS}
54 , {"long-keys" , 0 , RRDR_OPTION_LONG_JSON_KEYS}
55 , {"mcp-info" , 0 , RRDR_OPTION_MCP_INFO}
56 , {"rfc3339" , 0 , RRDR_OPTION_RFC3339}
57 , {NULL , 0 , 0}
58 };
59
60 RRDR_OPTIONS rrdr_options_parse_one(const char *o) {
61 RRDR_OPTIONS ret = 0;
62
63 if(!o || !*o) return ret;
64
65 uint32_t hash = simple_hash(o);
66 int i;
67 for(i = 0; rrdr_options[i].name ; i++) {
68 if (unlikely(hash == rrdr_options[i].hash && !strcmp(o, rrdr_options[i].name))) {
69 ret |= rrdr_options[i].value;
70 break;
71 }
72 }
73
74 return ret;
75 }
76
77 static inline bool rrdr_options_is_separator(char c) {
78 return c == ',' || c == ' ' || c == '|';
79 }
80
81 static inline bool rrdr_option_token_matches(const char *token, size_t len, const char *name) {
82 if(!name)
83 return false;
84
85 for(size_t i = 0; i < len; i++) {
86 if(!name[i] || token[i] != name[i])
87 return false;
88 }
89
90 return name[len] == '\0';
91 }
92
93 static RRDR_OPTIONS rrdr_options_parse_one_n(const char *o, size_t len) {
94 RRDR_OPTIONS ret = 0;
95
96 if(!o || !len) return ret;
97
98 for(int i = 0; ; i++) {
99 const char *name = rrdr_options[i].name;
100 if(!name)
101 break;
102
103 if (rrdr_option_token_matches(o, len, name)) {
104 ret |= rrdr_options[i].value;
105 break;
106 }
107 }
108
109 return ret;
110 }
111
112 RRDR_OPTIONS rrdr_options_parse(const char *options_str) {
113 RRDR_OPTIONS ret = 0;
114
115 if(!options_str || !*options_str)
116 return ret;
117
118 const char *s = options_str;
119 while(*s) {
120 while(*s && rrdr_options_is_separator(*s))
121 s++;
122
123 const char *tok = s;
124 while(*s && !rrdr_options_is_separator(*s))
125 s++;
126
127 ret |= rrdr_options_parse_one_n(tok, (size_t)(s - tok));
128 }
129
130 return ret;
131 }
132
133 void rrdr_options_to_buffer_json_array(BUFFER *wb, const char *key, RRDR_OPTIONS options) {
134 buffer_json_member_add_array(wb, key);
135
136 RRDR_OPTIONS used = 0; // to prevent adding duplicates
137 for(int i = 0; rrdr_options[i].name ; i++) {
138 if (unlikely((rrdr_options[i].value & options) && !(rrdr_options[i].value & used))) {
139 const char *name = rrdr_options[i].name;
140 used |= rrdr_options[i].value;
141
142 buffer_json_add_array_item_string(wb, name);
143 }
144 }
145
146 buffer_json_array_close(wb);
147 }
148
149 void rrdr_options_to_buffer(BUFFER *wb, RRDR_OPTIONS options) {
150 RRDR_OPTIONS used = 0; // to prevent adding duplicates
151 size_t added = 0;
152 for(int i = 0; rrdr_options[i].name ; i++) {
153 if (unlikely((rrdr_options[i].value & options) && !(rrdr_options[i].value & used))) {
154 const char *name = rrdr_options[i].name;
155 used |= rrdr_options[i].value;
156
157 if(added++) buffer_strcat(wb, " ");
158 buffer_strcat(wb, name);
159 }
160 }
161 }
162
163 void web_client_api_request_data_vX_options_to_string(char *buf, size_t size, RRDR_OPTIONS options) {
164 char *write = buf;
165 char *end = &buf[size - 1];
166
167 RRDR_OPTIONS used = 0; // to prevent adding duplicates
168 int added = 0;
169 for(int i = 0; rrdr_options[i].name ; i++) {
170 if (unlikely((rrdr_options[i].value & options) && !(rrdr_options[i].value & used))) {
171 const char *name = rrdr_options[i].name;
172 used |= rrdr_options[i].value;
173
174 if(added && write < end)
175 *write++ = ',';
176
177 while(*name && write < end)
178 *write++ = *name++;
179
180 added++;
181 }
182 }
183 *write = *end = '\0';
184 }
185
186 void rrdr_options_init(void) {
187 for(size_t i = 0; rrdr_options[i].name ; i++)
188 rrdr_options[i].hash = simple_hash(rrdr_options[i].name);
189 }