/src/wpantund/src/util/string-utils.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * |
3 | | * Copyright (c) 2016 Nest Labs, Inc. |
4 | | * All rights reserved. |
5 | | * |
6 | | * Licensed under the Apache License, Version 2.0 (the "License"); |
7 | | * you may not use this file except in compliance with the License. |
8 | | * You may obtain a copy of the License at |
9 | | * |
10 | | * http://www.apache.org/licenses/LICENSE-2.0 |
11 | | * |
12 | | * Unless required by applicable law or agreed to in writing, software |
13 | | * distributed under the License is distributed on an "AS IS" BASIS, |
14 | | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
15 | | * See the License for the specific language governing permissions and |
16 | | * limitations under the License. |
17 | | * |
18 | | * Description: |
19 | | * This file defines utility functions for manipulating and comparing |
20 | | * C-strings or other buffers. |
21 | | * |
22 | | */ |
23 | | |
24 | | #if HAVE_CONFIG_H |
25 | | #include <config.h> |
26 | | #endif |
27 | | |
28 | | #include <stdio.h> |
29 | | #include "string-utils.h" |
30 | | #include <ctype.h> |
31 | | #include <inttypes.h> |
32 | | #include <stdlib.h> |
33 | | |
34 | | #ifndef __USE_GNU |
35 | | #define __USE_GNU // Needed for `strcasestr` |
36 | | #endif |
37 | | |
38 | | #include <string.h> |
39 | | |
40 | | // Declare function to avoid compile warning: comparison between pointer and integer. |
41 | | extern char *strcasestr(const char *, const char *); |
42 | | |
43 | | void |
44 | | memcpyrev(void *dest_, const void *src_, size_t len) |
45 | 0 | { |
46 | 0 | uint8_t* const dest = dest_; |
47 | 0 | const uint8_t* const src = src_; |
48 | 0 | size_t i; |
49 | |
|
50 | 0 | for (i = 0; i < len; i++) { |
51 | 0 | dest[i] = src[len - 1 - i]; |
52 | 0 | } |
53 | 0 | } |
54 | | |
55 | | int |
56 | | memcmprev(const void *dest_, const void *src_, size_t len) |
57 | 0 | { |
58 | 0 | const uint8_t* const dest = dest_; |
59 | 0 | const uint8_t* const src = src_; |
60 | 0 | int ret = 0; |
61 | 0 | size_t i; |
62 | |
|
63 | 0 | for (i = 0; i < len && !ret; i++) { |
64 | 0 | ret = dest[i] - src[len - 1 - i]; |
65 | 0 | } |
66 | 0 | return ret; |
67 | 0 | } |
68 | | |
69 | | void |
70 | | reverse_bytes(uint8_t *bytes, size_t count) |
71 | 0 | { |
72 | 0 | size_t i; |
73 | |
|
74 | 0 | for (i = 0; i < count / 2; i++) { |
75 | 0 | uint8_t x = bytes[i]; |
76 | 0 | bytes[i] = bytes[count - i - 1]; |
77 | 0 | bytes[count - i - 1] = x; |
78 | 0 | } |
79 | 0 | } |
80 | | |
81 | | int |
82 | | parse_string_into_data(uint8_t* buffer, size_t len, const char* c_str) |
83 | 736 | { |
84 | 736 | int ret = 0; |
85 | | |
86 | 736 | if (NULL == buffer) { |
87 | 0 | len = 0; |
88 | 0 | } |
89 | | |
90 | 14.6k | while ((*c_str != 0) && (len > 0)) { |
91 | 14.1k | int c = tolower(*c_str++); |
92 | 14.1k | if (!(isdigit(c) || (c >= 'a' && c <= 'f'))) { |
93 | 4.23k | continue; |
94 | 4.23k | } |
95 | 9.87k | c = isdigit(c) ? (c - '0') : (c - 'a' + 10); |
96 | 9.87k | if (len > 0) { |
97 | 9.87k | *buffer = (c << 4); |
98 | 9.87k | len--; |
99 | 9.87k | } |
100 | 9.87k | ret++; |
101 | 9.87k | if (!*c_str) { |
102 | 172 | break; |
103 | 172 | } |
104 | 9.69k | c = tolower(*c_str++); |
105 | 9.69k | if (!(isdigit(c) || (c >= 'a' && c <= 'f'))) { |
106 | 1.64k | continue; |
107 | 1.64k | } |
108 | 8.05k | c = isdigit(c) ? (c - '0') : (c - 'a' + 10); |
109 | 8.05k | *buffer++ |= c; |
110 | 8.05k | } |
111 | | |
112 | 736 | return ret; |
113 | 736 | } |
114 | | |
115 | | int |
116 | | encode_data_into_string(const uint8_t *buffer, size_t len, char *c_str, size_t c_str_max_len, int pad_to) |
117 | 1.29k | { |
118 | 1.29k | int ret = 0; |
119 | | |
120 | 7.25k | while (len && (c_str_max_len > 2)) { |
121 | 5.95k | uint8_t byte = *buffer++; |
122 | 5.95k | len--; |
123 | 5.95k | pad_to--; |
124 | 5.95k | *c_str++ = int_to_hex_digit(byte >> 4); |
125 | 5.95k | *c_str++ = int_to_hex_digit(byte & 0xF); |
126 | 5.95k | c_str_max_len -= 2; |
127 | 5.95k | ret += 2; |
128 | 5.95k | } |
129 | | |
130 | 1.29k | while (pad_to > 0 && (c_str_max_len > 2)) { |
131 | 0 | pad_to--; |
132 | 0 | *c_str++ = '0'; |
133 | 0 | *c_str++ = '0'; |
134 | 0 | c_str_max_len -= 2; |
135 | 0 | ret += 2; |
136 | 0 | } |
137 | | |
138 | 1.29k | c_str_max_len--; |
139 | 1.29k | *c_str++ = 0; |
140 | 1.29k | return ret; |
141 | 1.29k | } |
142 | | |
143 | | bool |
144 | | strtobool(const char* string) |
145 | 0 | { |
146 | 0 | bool ret = false; |
147 | 0 | switch(string[0]) { |
148 | 0 | case 'y': |
149 | 0 | case 'Y': |
150 | 0 | case 't': |
151 | 0 | case 'T': |
152 | 0 | ret = true; |
153 | 0 | break; |
154 | | |
155 | 0 | case 'n': |
156 | 0 | case 'N': |
157 | 0 | case 'f': |
158 | 0 | case 'F': |
159 | 0 | ret = false; |
160 | 0 | break; |
161 | | |
162 | 0 | default: |
163 | 0 | ret = (strtol(string, NULL, 0) != 0); |
164 | 0 | break; |
165 | 0 | } |
166 | 0 | return ret; |
167 | 0 | } |
168 | | |
169 | | uint32_t |
170 | | strtomask_uint32(const char* in_string) |
171 | 0 | { |
172 | 0 | char *tmp_string = strdup(in_string); |
173 | 0 | char *chan_ranges; // points to a channel num or a range of channels |
174 | 0 | char *dash_location; // points to location of the dash in a range of channels |
175 | 0 | int channel_start = 0; |
176 | 0 | int channel_stop = 0; |
177 | 0 | uint32_t mask = 0; |
178 | |
|
179 | 0 | chan_ranges = strtok(tmp_string, ","); |
180 | 0 | while(chan_ranges != NULL) { |
181 | | // loop to parse channels by comma (,) |
182 | | // each fragment may include a range (-) of channels |
183 | |
|
184 | 0 | dash_location = strchr(chan_ranges, '-'); |
185 | 0 | if (dash_location != NULL) { |
186 | | // process a range of channels |
187 | 0 | *dash_location = '\0'; |
188 | 0 | dash_location++; |
189 | 0 | if (atoi(chan_ranges) < atoi(dash_location)) { |
190 | 0 | channel_start = atoi(chan_ranges); |
191 | 0 | channel_stop = atoi(dash_location); |
192 | 0 | } else { |
193 | 0 | channel_stop = atoi(chan_ranges); |
194 | 0 | channel_start = atoi(dash_location); |
195 | 0 | } |
196 | |
|
197 | 0 | while (channel_start <= channel_stop) { |
198 | 0 | mask |= (1 << channel_start); |
199 | 0 | channel_start++; |
200 | 0 | } |
201 | 0 | } else { |
202 | | // no range, just add channel to the scan mask |
203 | |
|
204 | 0 | mask |= (1 << strtol(chan_ranges, NULL, 0)); |
205 | 0 | } |
206 | 0 | chan_ranges = strtok(NULL, ","); |
207 | 0 | } |
208 | 0 | free(tmp_string); |
209 | 0 | return mask; |
210 | 0 | } |
211 | | |
212 | | #include <syslog.h> |
213 | | |
214 | | int |
215 | | strtologmask(const char* value, int prev_mask) |
216 | 0 | { |
217 | 0 | int mask = (int)strtol(value, NULL, 0); |
218 | |
|
219 | 0 | if (mask == 0) { |
220 | 0 | mask = prev_mask; |
221 | |
|
222 | 0 | if(strcasestr(value, "all") != NULL) { |
223 | 0 | if (strcasestr(value, "-all") != NULL) { |
224 | 0 | mask &= 0; |
225 | 0 | } else { |
226 | 0 | mask |= ~0; |
227 | 0 | } |
228 | 0 | } |
229 | 0 | if (strcasestr(value, "emerg") != NULL) { |
230 | 0 | if (strcasestr(value, "-emerg") != NULL) { |
231 | 0 | mask &= ~LOG_MASK(LOG_EMERG); |
232 | 0 | } else { |
233 | 0 | mask |= LOG_MASK(LOG_EMERG); |
234 | 0 | } |
235 | 0 | } |
236 | 0 | if (strcasestr(value, "alert") != NULL) { |
237 | 0 | if (strcasestr(value, "-alert") != NULL) { |
238 | 0 | mask &= ~LOG_MASK(LOG_ALERT); |
239 | 0 | } else { |
240 | 0 | mask |= LOG_MASK(LOG_ALERT); |
241 | 0 | } |
242 | 0 | } |
243 | 0 | if (strcasestr(value, "crit") != NULL) { |
244 | 0 | if (strcasestr(value, "-crit") != NULL) { |
245 | 0 | mask &= ~LOG_MASK(LOG_CRIT); |
246 | 0 | } else { |
247 | 0 | mask |= LOG_MASK(LOG_CRIT); |
248 | 0 | } |
249 | 0 | } |
250 | 0 | if (strcasestr(value, "err") != NULL) { |
251 | 0 | if (strcasestr(value, "-err") != NULL) { |
252 | 0 | mask &= ~LOG_MASK(LOG_ERR); |
253 | 0 | } else { |
254 | 0 | mask |= LOG_MASK(LOG_ERR); |
255 | 0 | } |
256 | 0 | } |
257 | 0 | if (strcasestr(value, "warn") != NULL) { |
258 | 0 | if (strcasestr(value, "-warn") != NULL) { |
259 | 0 | mask &= ~LOG_MASK(LOG_WARNING); |
260 | 0 | } else { |
261 | 0 | mask |= LOG_MASK(LOG_WARNING); |
262 | 0 | } |
263 | 0 | } |
264 | 0 | if (strcasestr(value, "notice") != NULL) { |
265 | 0 | if (strcasestr(value, "-notice") != NULL) { |
266 | 0 | mask &= ~LOG_MASK(LOG_NOTICE); |
267 | 0 | } else { |
268 | 0 | mask |= LOG_MASK(LOG_NOTICE); |
269 | 0 | } |
270 | 0 | } |
271 | 0 | if (strcasestr(value, "info") != NULL) { |
272 | 0 | if (strcasestr(value, "-info") != NULL) { |
273 | 0 | mask &= ~LOG_MASK(LOG_INFO); |
274 | 0 | } else { |
275 | 0 | mask |= LOG_MASK(LOG_INFO); |
276 | 0 | } |
277 | 0 | } |
278 | 0 | if (strcasestr(value, "debug") != NULL) { |
279 | 0 | if (strcasestr(value, "-debug") != NULL) { |
280 | 0 | mask &= ~LOG_MASK(LOG_DEBUG); |
281 | 0 | } else { |
282 | 0 | mask |= LOG_MASK(LOG_DEBUG); |
283 | 0 | } |
284 | 0 | } |
285 | 0 | } |
286 | |
|
287 | 0 | return mask; |
288 | 0 | } |
289 | | |
290 | | bool |
291 | | buffer_is_nonzero(const uint8_t* buffer, size_t len) |
292 | 3.19k | { |
293 | 12.6k | while (len--) { |
294 | 11.8k | if (*buffer++ != 0) { |
295 | 2.46k | return true; |
296 | 2.46k | } |
297 | 11.8k | } |
298 | 735 | return false; |
299 | 3.19k | } |
300 | | |
301 | | bool |
302 | | is_hex(const uint8_t* buff, size_t len) |
303 | 0 | { |
304 | 0 | while (len--) { |
305 | 0 | if (!isxdigit(*buff++)) { |
306 | 0 | return false; |
307 | 0 | } |
308 | 0 | } |
309 | 0 | return true; |
310 | 0 | } |
311 | | |
312 | | bool |
313 | | is_uppercase_or_digit(const uint8_t* buff, size_t len) |
314 | 0 | { |
315 | 0 | while (len--) { |
316 | 0 | if (!(isupper(*buff) || isdigit(*buff))) { |
317 | 0 | return false; |
318 | 0 | } |
319 | 0 | buff++; |
320 | 0 | } |
321 | 0 | return true; |
322 | 0 | } |