first version upgrade
[devspec.git] / devspec.en_US / project / recutils / src / rec-utils.c
blob99d101b9e9c9f8e45e932aacb4bba4a76f85a397
1 /* -*- mode: C -*-
3 * File: rec-utils.c
4 * Date: Fri Apr 9 19:45:00 2010
6 * GNU recutils - Miscellanea utilities
8 */
10 /* Copyright (C) 2010-2019 Jose E. Marchesi */
12 /* This program is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation, either version 3 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program. If not, see <http://www.gnu.org/licenses/>.
26 #include <config.h>
28 #include <regex.h>
29 #include <stdlib.h>
30 #include <gettext.h>
31 #define _(str) dgettext (PACKAGE, str)
32 #include <string.h>
33 #include <locale.h>
35 #include <rec-utils.h>
37 bool
38 rec_atoi (const char *str,
39 int *number)
41 bool res;
42 long int li;
43 char *end;
44 int base = 0;
46 res = false;
48 li = strtol (str, &end, base);
49 if ((*str != '\0') && (*end == '\0'))
51 /* The entire string is valid. */
52 res = true;
53 *number = (int) li;
56 return res;
59 bool
60 rec_atod (const char *str,
61 double *number)
63 bool res;
64 char *end;
66 res = false;
68 setlocale (LC_NUMERIC, "C"); /* We want the dot to always be the
69 decimal separator. */
70 *number = strtod (str, &end);
71 setlocale (LC_NUMERIC, ""); /* Restore the locale from the
72 environment. */
74 if ((*str != '\0') && (*end == '\0'))
76 /* The entire string is valid. */
77 res = true;
80 return res;
83 char *
84 rec_extract_file (const char *str)
86 regex_t regexp;
87 regmatch_t matches;
88 char *rec_file = NULL;
89 size_t rec_file_length = 0;
91 if (regcomp (&regexp, "[ \n\t]" REC_FILE_REGEXP, REG_EXTENDED) != 0)
93 fprintf (stderr, _("internal error: rec_int_rec_extract_file: error compiling regexp.\n"));
94 return NULL;
97 if ((regexec (&regexp, str, 1, &matches, 0) == 0)
98 && (matches.rm_so != -1))
100 /* Get the match. */
101 rec_file_length = matches.rm_eo - matches.rm_so;
102 rec_file = malloc (rec_file_length + 1);
103 memcpy (rec_file, str + matches.rm_so + 1, rec_file_length - 1);
104 rec_file[rec_file_length - 1] = '\0';
107 regfree (&regexp);
108 return rec_file;
111 char *
112 rec_extract_url (const char *str)
114 regex_t regexp;
115 regmatch_t matches;
116 char *rec_url = NULL;
117 size_t rec_url_length = 0;
119 if (regcomp (&regexp, REC_URL_REGEXP, REG_EXTENDED) != 0)
121 fprintf (stderr, _("internal error: rec_int_rec_extract_url: error compiling regexp.\n"));
122 return NULL;
125 if ((regexec (&regexp, str, 1, &matches, 0) == 0)
126 && (matches.rm_so != -1))
128 /* Get the match. */
129 rec_url_length = matches.rm_eo - matches.rm_so;
130 rec_url = malloc (rec_url_length + 1);
131 memcpy (rec_url, str + matches.rm_so, rec_url_length);
132 rec_url[rec_url_length] = '\0';
135 regfree (&regexp);
136 return rec_url;
139 char *
140 rec_extract_type (const char *str)
142 regex_t regexp;
143 regmatch_t matches;
144 char *rec_type = NULL;
145 size_t rec_type_length = 0;
147 /* TODO: use a REC_TYPE_NAME_RE */
148 if (regcomp (&regexp, REC_FNAME_RE, REG_EXTENDED) != 0)
150 fprintf (stderr, _("internal error: rec_int_rec_extract_url: error compiling regexp.\n"));
151 return NULL;
154 if ((regexec (&regexp, str, 1, &matches, 0) == 0)
155 && (matches.rm_so != -1))
157 /* Get the match. */
158 rec_type_length = matches.rm_eo - matches.rm_so;
159 rec_type = malloc (rec_type_length + 1);
160 memcpy (rec_type, str + matches.rm_so, rec_type_length);
161 rec_type[rec_type_length] = '\0';
164 regfree (&regexp);
165 return rec_type;
168 bool
169 rec_parse_int (const char **str, int *num)
171 bool ret;
172 const char *p, *b;
173 char number[30];
175 ret = true;
176 p = *str;
178 b = p;
179 while (rec_digit_p (*p)
180 || ((p == b) && (*p == '-'))
181 || ((*p >= 'a') && (*p <= 'f'))
182 || ((*p >= 'A') && (*p <= 'F'))
183 || (*p == 'x')
184 || (*p == 'X'))
186 number[p - b] = *p;
187 p++;
189 number[p - b] = '\0';
191 if (!rec_atoi (number, num))
193 ret = false;
196 if (ret)
198 *str = p;
201 return ret;
204 bool
205 rec_parse_regexp (const char **str, const char *re, char **result)
207 bool ret;
208 const char *p;
209 regex_t regexp;
210 regmatch_t pm;
212 ret = true;
213 p = *str;
215 /* Compile the regexp. */
216 if (regcomp (&regexp, re, REG_EXTENDED) != 0)
218 ret = false;
221 if (ret)
223 /* Try to match the regexp. */
224 if (regexec (&regexp, p, 1, &pm, 0) == 0)
226 if (result)
228 /* Get the match into 'result'. Note that
229 since the pattern starts with a ^ rm_so shall be 0 and we
230 can use rm_eo relative to *p. */
231 *result = malloc (pm.rm_eo + 1);
232 memcpy (*result, p, pm.rm_eo);
233 (*result)[pm.rm_eo] = '\0';
236 /* Advance 'p'. */
237 p = p + pm.rm_eo;
239 else
241 ret = false;
242 if (result)
244 *result = NULL;
248 regfree (&regexp);
251 if (ret)
253 *str = p;
256 return ret;
259 void
260 rec_skip_blanks (const char **str)
262 const char *p;
264 p = *str;
265 while (rec_blank_p (*p))
267 p++;
270 *str = p;
273 bool
274 rec_blank_p (char c)
276 return ((c == ' ')
277 || (c == '\n')
278 || (c == '\t'));
281 bool
282 rec_digit_p (char c)
284 return ((c >= '0') && (c <= '9'));
287 bool
288 rec_letter_p (char c)
290 return (((c >= 'a') && (c <= 'z'))
291 || ((c >= 'A') && (c <= 'Z')));
294 static bool
295 rec_match_int (const char *str,
296 const char *reg,
297 int flags)
299 bool ret;
300 regex_t regexp;
302 if (regcomp (&regexp, reg, flags) != 0)
304 fprintf (stderr, _("internal error: rec_match: error compiling regexp.\n"));
305 return false;
308 ret = (regexec (&regexp, str, 0, NULL, 0) == 0);
309 regfree (&regexp);
311 return ret;
314 bool
315 rec_match (const char *str,
316 const char *reg)
318 return rec_match_int (str, reg, REG_EXTENDED);
321 bool
322 rec_match_insensitive (const char *str,
323 const char *reg)
325 return rec_match_int (str, reg, REG_EXTENDED | REG_ICASE);
328 size_t
329 rec_extract_size (const char *str)
331 const char *p;
332 char *condition_str;
333 int res;
335 if (!rec_match (str, REC_INT_SIZE_RE))
337 return 0;
340 p = str;
341 rec_skip_blanks (&p);
342 rec_parse_regexp (&p, "^[><]=?", &condition_str);
343 rec_skip_blanks (&p);
344 rec_parse_int (&p, &res);
346 return (size_t) res;
349 enum rec_size_condition_e
350 rec_extract_size_condition (const char *str)
352 const char *p;
353 char *condition_str = NULL;
354 enum rec_size_condition_e condition;
356 if (!rec_match (str, REC_INT_SIZE_RE))
358 return SIZE_COND_E;
361 p = str;
362 rec_skip_blanks (&p);
363 rec_parse_regexp (&p, "^[><]=?", &condition_str);
365 if (condition_str)
367 if (strcmp (condition_str, ">") == 0)
369 condition = SIZE_COND_G;
371 else if (strcmp (condition_str, ">=") == 0)
373 condition = SIZE_COND_GE;
375 else if (strcmp (condition_str, "<") == 0)
377 condition = SIZE_COND_L;
379 else if (strcmp (condition_str, "<=") == 0)
381 condition = SIZE_COND_LE;
383 else
385 fprintf (stderr, "internal error: rec_extract_size_condition: invalid condition.\n");
386 return SIZE_COND_E;
389 free (condition_str);
391 else
393 condition = SIZE_COND_E;
396 return condition;
400 rec_timespec_subtract (struct timespec *result,
401 struct timespec *x,
402 struct timespec *y)
404 result->tv_sec = x->tv_sec - y->tv_sec;
405 result->tv_nsec = x->tv_nsec - y->tv_nsec;
406 if (result->tv_nsec < 0)
408 /* Overflow. Subtract one second. */
409 result->tv_sec--;
410 result->tv_nsec += 1000000000;
413 /* Return whether there is an overflow in the 'tv_sec' field. */
414 return (result->tv_sec < 0);
417 uint32_t
418 rec_endian_swap (uint32_t number)
420 uint32_t res;
422 res = (number >> 24)
423 | ((number << 8) & 0x00FF0000)
424 | ((number >> 8) & 0x0000FF00)
425 | (number << 24);
427 return res;
430 char *
431 rec_concat_strings (const char *str1,
432 const char *str2,
433 const char *str3)
435 char *res = malloc (strlen (str1) + strlen (str2) + strlen (str3) + 1);
437 if (res)
439 memcpy (res, str1, strlen (str1));
440 memcpy (res + strlen (str1), str2, strlen (str2));
441 memcpy (res + strlen (str1) + strlen (str2), str3, strlen (str3) + 1);
444 return res;
447 /* End of rec-utils.c */