LLVM OpenMP 22.0.0git
kmp_str.cpp
Go to the documentation of this file.
1/*
2 * kmp_str.cpp -- String manipulation routines.
3 */
4
5//===----------------------------------------------------------------------===//
6//
7// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
8// See https://llvm.org/LICENSE.txt for license information.
9// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
10//
11//===----------------------------------------------------------------------===//
12
13#include "kmp_str.h"
14
15#include <stdarg.h> // va_*
16#include <stdio.h> // vsnprintf()
17#include <stdlib.h> // malloc(), realloc()
18
19#include "kmp.h"
20#include "kmp_i18n.h"
21
22/* String buffer.
23
24 Usage:
25
26 // Declare buffer and initialize it.
27 kmp_str_buf_t buffer;
28 __kmp_str_buf_init( & buffer );
29
30 // Print to buffer.
31 __kmp_str_buf_print(& buffer, "Error in file \"%s\" line %d\n", "foo.c", 12);
32 __kmp_str_buf_print(& buffer, " <%s>\n", line);
33
34 // Use buffer contents. buffer.str is a pointer to data, buffer.used is a
35 // number of printed characters (not including terminating zero).
36 write( fd, buffer.str, buffer.used );
37
38 // Free buffer.
39 __kmp_str_buf_free( & buffer );
40
41 // Alternatively, you can detach allocated memory from buffer:
42 __kmp_str_buf_detach( & buffer );
43 return buffer.str; // That memory should be freed eventually.
44
45 Notes:
46
47 * Buffer users may use buffer.str and buffer.used. Users should not change
48 any fields of buffer directly.
49 * buffer.str is never NULL. If buffer is empty, buffer.str points to empty
50 string ("").
51 * For performance reasons, buffer uses stack memory (buffer.bulk) first. If
52 stack memory is exhausted, buffer allocates memory on heap by malloc(), and
53 reallocates it by realloc() as amount of used memory grows.
54 * Buffer doubles amount of allocated memory each time it is exhausted.
55*/
56
57// TODO: __kmp_str_buf_print() can use thread local memory allocator.
58
59#define KMP_STR_BUF_INVARIANT(b) \
60 { \
61 KMP_DEBUG_ASSERT((b)->str != NULL); \
62 KMP_DEBUG_ASSERT((b)->size >= sizeof((b)->bulk)); \
63 KMP_DEBUG_ASSERT((b)->size % sizeof((b)->bulk) == 0); \
64 KMP_DEBUG_ASSERT((unsigned)(b)->used < (b)->size); \
65 KMP_DEBUG_ASSERT( \
66 (b)->size == sizeof((b)->bulk) ? (b)->str == &(b)->bulk[0] : 1); \
67 KMP_DEBUG_ASSERT((b)->size > sizeof((b)->bulk) ? (b)->str != &(b)->bulk[0] \
68 : 1); \
69 }
70
73 if (buffer->used > 0) {
74 buffer->used = 0;
75 buffer->str[0] = 0;
76 }
78} // __kmp_str_buf_clear
79
83
84 if (buffer->size < (unsigned int)size) {
85 // Calculate buffer size.
86 do {
87 buffer->size *= 2;
88 } while (buffer->size < (unsigned int)size);
89
90 // Enlarge buffer.
91 if (buffer->str == &buffer->bulk[0]) {
92 buffer->str = (char *)KMP_INTERNAL_MALLOC(buffer->size);
93 if (buffer->str == NULL) {
94 KMP_FATAL(MemoryAllocFailed);
95 }
96 KMP_MEMCPY_S(buffer->str, buffer->size, buffer->bulk, buffer->used + 1);
97 } else {
98 buffer->str = (char *)KMP_INTERNAL_REALLOC(buffer->str, buffer->size);
99 if (buffer->str == NULL) {
100 KMP_FATAL(MemoryAllocFailed);
101 }
102 }
103 }
104
105 KMP_DEBUG_ASSERT(buffer->size > 0);
106 KMP_DEBUG_ASSERT(buffer->size >= (unsigned)size);
107 KMP_STR_BUF_INVARIANT(buffer);
108} // __kmp_str_buf_reserve
109
111 KMP_STR_BUF_INVARIANT(buffer);
112
113 // If internal bulk is used, allocate memory and copy it.
114 if (buffer->size <= sizeof(buffer->bulk)) {
115 buffer->str = (char *)KMP_INTERNAL_MALLOC(buffer->size);
116 if (buffer->str == NULL) {
117 KMP_FATAL(MemoryAllocFailed);
118 }
119 KMP_MEMCPY_S(buffer->str, buffer->size, buffer->bulk, buffer->used + 1);
120 }
121} // __kmp_str_buf_detach
122
124 KMP_STR_BUF_INVARIANT(buffer);
125 if (buffer->size > sizeof(buffer->bulk)) {
126 KMP_INTERNAL_FREE(buffer->str);
127 }
128 buffer->str = buffer->bulk;
129 buffer->size = sizeof(buffer->bulk);
130 buffer->used = 0;
131 KMP_STR_BUF_INVARIANT(buffer);
132} // __kmp_str_buf_free
133
134void __kmp_str_buf_cat(kmp_str_buf_t *buffer, char const *str, size_t len) {
135 KMP_STR_BUF_INVARIANT(buffer);
136 KMP_DEBUG_ASSERT(str != NULL);
137 KMP_DEBUG_ASSERT(len >= 0);
138
139 __kmp_str_buf_reserve(buffer, buffer->used + len + 1);
140 buffer->str[buffer->used] = '\0';
141 KMP_STRNCAT_S(buffer->str + buffer->used, len + 1, str, len);
142 __kmp_type_convert(buffer->used + len, &(buffer->used));
143 KMP_STR_BUF_INVARIANT(buffer);
144} // __kmp_str_buf_cat
145
147 KMP_DEBUG_ASSERT(dest);
148 KMP_DEBUG_ASSERT(src);
151 if (!src->str || !src->used)
152 return;
153 __kmp_str_buf_reserve(dest, dest->used + src->used + 1);
154 dest->str[dest->used] = '\0';
155 KMP_STRNCAT_S(dest->str + dest->used, src->used + 1, src->str, src->used);
156 dest->used += src->used;
158} // __kmp_str_buf_catbuf
159
160// Return the number of characters written
161int __kmp_str_buf_vprint(kmp_str_buf_t *buffer, char const *format,
162 va_list args) {
163 int rc;
164 KMP_STR_BUF_INVARIANT(buffer);
165
166 for (;;) {
167 int const free = buffer->size - buffer->used;
168 int size;
169
170 // Try to format string.
171 {
172 /* On Linux* OS Intel(R) 64, vsnprintf() modifies args argument, so
173 vsnprintf() crashes if it is called for the second time with the same
174 args. To prevent the crash, we have to pass a fresh intact copy of args
175 to vsnprintf() on each iteration.
176
177 Unfortunately, standard va_copy() macro is not available on Windows*
178 OS. However, it seems vsnprintf() does not modify args argument on
179 Windows* OS.
180 */
181
182#if !KMP_OS_WINDOWS
183 va_list _args;
184 va_copy(_args, args); // Make copy of args.
185#define args _args // Substitute args with its copy, _args.
186#endif // KMP_OS_WINDOWS
187 rc = KMP_VSNPRINTF(buffer->str + buffer->used, free, format, args);
188#if !KMP_OS_WINDOWS
189#undef args // Remove substitution.
190 va_end(_args);
191#endif // KMP_OS_WINDOWS
192 }
193
194 // No errors, string has been formatted.
195 if (rc >= 0 && rc < free) {
196 buffer->used += rc;
197 break;
198 }
199
200 // Error occurred, buffer is too small.
201 if (rc >= 0) {
202 // C99-conforming implementation of vsnprintf returns required buffer size
203 size = buffer->used + rc + 1;
204 } else {
205 // Older implementations just return -1. Double buffer size.
206 size = buffer->size * 2;
207 }
208
209 // Enlarge buffer.
211
212 // And try again.
213 }
214
215 KMP_DEBUG_ASSERT(buffer->size > 0);
216 KMP_STR_BUF_INVARIANT(buffer);
217 return rc;
218} // __kmp_str_buf_vprint
219
220// Return the number of characters written
221int __kmp_str_buf_print(kmp_str_buf_t *buffer, char const *format, ...) {
222 int rc;
223 va_list args;
224 va_start(args, format);
225 rc = __kmp_str_buf_vprint(buffer, format, args);
226 va_end(args);
227 return rc;
228} // __kmp_str_buf_print
229
230/* The function prints specified size to buffer. Size is expressed using biggest
231 possible unit, for example 1024 is printed as "1k". */
233 char const *names[] = {"", "k", "M", "G", "T", "P", "E", "Z", "Y"};
234 int const units = sizeof(names) / sizeof(char const *);
235 int u = 0;
236 if (size > 0) {
237 while ((size % 1024 == 0) && (u + 1 < units)) {
238 size = size / 1024;
239 ++u;
240 }
241 }
242
243 __kmp_str_buf_print(buf, "%" KMP_SIZE_T_SPEC "%s", size, names[u]);
244} // __kmp_str_buf_print_size
245
246void __kmp_str_fname_init(kmp_str_fname_t *fname, char const *path) {
247 fname->path = NULL;
248 fname->dir = NULL;
249 fname->base = NULL;
250
251 if (path != NULL) {
252 char *slash = NULL; // Pointer to the last character of dir.
253 char *base = NULL; // Pointer to the beginning of basename.
254 fname->path = __kmp_str_format("%s", path);
255 // Original code used strdup() function to copy a string, but on Windows* OS
256 // Intel(R) 64 it causes assertion id debug heap, so I had to replace
257 // strdup with __kmp_str_format().
258 if (KMP_OS_WINDOWS) {
259 __kmp_str_replace(fname->path, '\\', '/');
260 }
261 fname->dir = __kmp_str_format("%s", fname->path);
262 slash = strrchr(fname->dir, '/');
263 if (KMP_OS_WINDOWS &&
264 slash == NULL) { // On Windows* OS, if slash not found,
265 char first = (char)TOLOWER(fname->dir[0]); // look for drive.
266 if ('a' <= first && first <= 'z' && fname->dir[1] == ':') {
267 slash = &fname->dir[1];
268 }
269 }
270 base = (slash == NULL ? fname->dir : slash + 1);
271 fname->base = __kmp_str_format("%s", base); // Copy basename
272 *base = 0; // and truncate dir.
273 }
274
275} // kmp_str_fname_init
276
278 __kmp_str_free(&fname->path);
279 __kmp_str_free(&fname->dir);
280 __kmp_str_free(&fname->base);
281} // kmp_str_fname_free
282
283int __kmp_str_fname_match(kmp_str_fname_t const *fname, char const *pattern) {
284 int dir_match = 1;
285 int base_match = 1;
286
287 if (pattern != NULL) {
288 kmp_str_fname_t ptrn;
289 __kmp_str_fname_init(&ptrn, pattern);
290 dir_match = strcmp(ptrn.dir, "*/") == 0 ||
291 (fname->dir != NULL && __kmp_str_eqf(fname->dir, ptrn.dir));
292 base_match = strcmp(ptrn.base, "*") == 0 ||
293 (fname->base != NULL && __kmp_str_eqf(fname->base, ptrn.base));
295 }
296
297 return dir_match && base_match;
298} // __kmp_str_fname_match
299
300// Get the numeric fields from source location string.
301// For clang these fields are Line/Col of the start of the construct.
302// For icc these are LineBegin/LineEnd of the construct.
303// Function is fast as it does not duplicate string (which involves memory
304// allocation), and parses the string in place.
305void __kmp_str_loc_numbers(char const *Psource, int *LineBeg,
306 int *LineEndOrCol) {
307 char *Str;
308 KMP_DEBUG_ASSERT(LineBeg);
309 KMP_DEBUG_ASSERT(LineEndOrCol);
310 // Parse Psource string ";file;func;line;line_end_or_column;;" to get
311 // numbers only, skipping string fields "file" and "func".
312
313 // Find 1-st semicolon.
314 KMP_DEBUG_ASSERT(Psource);
315#ifdef __cplusplus
316 Str = strchr(CCAST(char *, Psource), ';');
317#else
318 Str = strchr(Psource, ';');
319#endif
320 // Check returned pointer to see if the format of Psource is broken.
321 if (Str) {
322 // Find 2-nd semicolon.
323 Str = strchr(Str + 1, ';');
324 }
325 if (Str) {
326 // Find 3-rd semicolon.
327 Str = strchr(Str + 1, ';');
328 }
329 if (Str) {
330 // Read begin line number.
331 *LineBeg = atoi(Str + 1);
332 // Find 4-th semicolon.
333 Str = strchr(Str + 1, ';');
334 } else {
335 // Broken format of input string, cannot read the number.
336 *LineBeg = 0;
337 }
338 if (Str) {
339 // Read end line or column number.
340 *LineEndOrCol = atoi(Str + 1);
341 } else {
342 // Broken format of input string, cannot read the number.
343 *LineEndOrCol = 0;
344 }
345}
346
347kmp_str_loc_t __kmp_str_loc_init(char const *psource, bool init_fname) {
349
350 loc._bulk = NULL;
351 loc.file = NULL;
352 loc.func = NULL;
353 loc.line = 0;
354 loc.col = 0;
355
356 if (psource != NULL) {
357 char *str = NULL;
358 char *dummy = NULL;
359 char *line = NULL;
360 char *col = NULL;
361
362 // Copy psource to keep it intact.
363 loc._bulk = __kmp_str_format("%s", psource);
364
365 // Parse psource string: ";file;func;line;col;;"
366 str = loc._bulk;
367 __kmp_str_split(str, ';', &dummy, &str);
368 __kmp_str_split(str, ';', &loc.file, &str);
369 __kmp_str_split(str, ';', &loc.func, &str);
370 __kmp_str_split(str, ';', &line, &str);
371 __kmp_str_split(str, ';', &col, &str);
372
373 // Convert line and col into numberic values.
374 if (line != NULL) {
375 loc.line = atoi(line);
376 if (loc.line < 0) {
377 loc.line = 0;
378 }
379 }
380 if (col != NULL) {
381 loc.col = atoi(col);
382 if (loc.col < 0) {
383 loc.col = 0;
384 }
385 }
386 }
387
388 __kmp_str_fname_init(&loc.fname, init_fname ? loc.file : NULL);
389
390 return loc;
391} // kmp_str_loc_init
392
394 __kmp_str_fname_free(&loc->fname);
395 __kmp_str_free(&(loc->_bulk));
396 loc->file = NULL;
397 loc->func = NULL;
398} // kmp_str_loc_free
399
400/* This function is intended to compare file names. On Windows* OS file names
401 are case-insensitive, so functions performs case-insensitive comparison. On
402 Linux* OS it performs case-sensitive comparison. Note: The function returns
403 *true* if strings are *equal*. */
404int __kmp_str_eqf( // True, if strings are equal, false otherwise.
405 char const *lhs, // First string.
406 char const *rhs // Second string.
407) {
408 int result;
409#if KMP_OS_WINDOWS
410 result = (_stricmp(lhs, rhs) == 0);
411#else
412 result = (strcmp(lhs, rhs) == 0);
413#endif
414 return result;
415} // __kmp_str_eqf
416
417/* This function is like sprintf, but it *allocates* new buffer, which must be
418 freed eventually by __kmp_str_free(). The function is very convenient for
419 constructing strings, it successfully replaces strdup(), strcat(), it frees
420 programmer from buffer allocations and helps to avoid buffer overflows.
421 Examples:
422
423 str = __kmp_str_format("%s", orig); //strdup() doesn't care about buffer size
424 __kmp_str_free( & str );
425 str = __kmp_str_format( "%s%s", orig1, orig2 ); // strcat(), doesn't care
426 // about buffer size.
427 __kmp_str_free( & str );
428 str = __kmp_str_format( "%s/%s.txt", path, file ); // constructing string.
429 __kmp_str_free( & str );
430
431 Performance note:
432 This function allocates memory with malloc() calls, so do not call it from
433 performance-critical code. In performance-critical code consider using
434 kmp_str_buf_t instead, since it uses stack-allocated buffer for short
435 strings.
436
437 Why does this function use malloc()?
438 1. __kmp_allocate() returns cache-aligned memory allocated with malloc().
439 There are no reasons in using __kmp_allocate() for strings due to extra
440 overhead while cache-aligned memory is not necessary.
441 2. __kmp_thread_malloc() cannot be used because it requires pointer to thread
442 structure. We need to perform string operations during library startup
443 (for example, in __kmp_register_library_startup()) when no thread
444 structures are allocated yet.
445 So standard malloc() is the only available option.
446*/
447
448char *__kmp_str_format( // Allocated string.
449 char const *format, // Format string.
450 ... // Other parameters.
451) {
452 va_list args;
453 int size = 512;
454 char *buffer = NULL;
455 int rc;
456
457 // Allocate buffer.
458 buffer = (char *)KMP_INTERNAL_MALLOC(size);
459 if (buffer == NULL) {
460 KMP_FATAL(MemoryAllocFailed);
461 }
462
463 for (;;) {
464 // Try to format string.
465 va_start(args, format);
466 rc = KMP_VSNPRINTF(buffer, size, format, args);
467 va_end(args);
468
469 // No errors, string has been formatted.
470 if (rc >= 0 && rc < size) {
471 break;
472 }
473
474 // Error occurred, buffer is too small.
475 if (rc >= 0) {
476 // C99-conforming implementation of vsnprintf returns required buffer
477 // size.
478 size = rc + 1;
479 } else {
480 // Older implementations just return -1.
481 size = size * 2;
482 }
483
484 // Enlarge buffer and try again.
485 buffer = (char *)KMP_INTERNAL_REALLOC(buffer, size);
486 if (buffer == NULL) {
487 KMP_FATAL(MemoryAllocFailed);
488 }
489 }
490
491 return buffer;
492} // func __kmp_str_format
493
494void __kmp_str_free(char **str) {
495 KMP_DEBUG_ASSERT(str != NULL);
496 KMP_INTERNAL_FREE(*str);
497 *str = NULL;
498} // func __kmp_str_free
499
500/* If len is zero, returns true iff target and data have exact case-insensitive
501 match. If len is negative, returns true iff target is a case-insensitive
502 substring of data. If len is positive, returns true iff target is a
503 case-insensitive substring of data or vice versa, and neither is shorter than
504 len. */
505int __kmp_str_match(char const *target, int len, char const *data) {
506 int i;
507 if (target == NULL || data == NULL) {
508 return FALSE;
509 }
510 for (i = 0; target[i] && data[i]; ++i) {
511 if (TOLOWER(target[i]) != TOLOWER(data[i])) {
512 return FALSE;
513 }
514 }
515 return ((len > 0) ? i >= len : (!target[i] && (len || !data[i])));
516} // __kmp_str_match
517
518// If data contains all of target, returns true, otherwise returns false.
519// len should be the length of target
520bool __kmp_str_contains(char const *target, int len, char const *data) {
521 int i = 0, j = 0, start = 0;
522 if (target == NULL || data == NULL) {
523 return FALSE;
524 }
525 while (target[i]) {
526 if (!data[j])
527 return FALSE;
528 if (TOLOWER(target[i]) != TOLOWER(data[j])) {
529 j = start + 1;
530 start = j;
531 i = 0;
532 } else {
533 if (i == 0)
534 start = j;
535 j++;
536 i++;
537 }
538 }
539
540 return i == len;
541} // __kmp_str_contains
542
543int __kmp_str_match_false(char const *data) {
544 int result =
545 __kmp_str_match("false", 1, data) || __kmp_str_match("off", 2, data) ||
546 __kmp_str_match("0", 1, data) || __kmp_str_match(".false.", 2, data) ||
547 __kmp_str_match(".f.", 2, data) || __kmp_str_match("no", 1, data) ||
548 __kmp_str_match("disabled", 0, data);
549 return result;
550} // __kmp_str_match_false
551
552int __kmp_str_match_true(char const *data) {
553 int result =
554 __kmp_str_match("true", 1, data) || __kmp_str_match("on", 2, data) ||
555 __kmp_str_match("1", 1, data) || __kmp_str_match(".true.", 2, data) ||
556 __kmp_str_match(".t.", 2, data) || __kmp_str_match("yes", 1, data) ||
557 __kmp_str_match("enabled", 0, data);
558 return result;
559} // __kmp_str_match_true
560
561void __kmp_str_replace(char *str, char search_for, char replace_with) {
562 char *found = NULL;
563
564 found = strchr(str, search_for);
565 while (found) {
566 *found = replace_with;
567 found = strchr(found + 1, search_for);
568 }
569} // __kmp_str_replace
570
571void __kmp_str_split(char *str, // I: String to split.
572 char delim, // I: Character to split on.
573 char **head, // O: Pointer to head (may be NULL).
574 char **tail // O: Pointer to tail (may be NULL).
575) {
576 char *h = str;
577 char *t = NULL;
578 if (str != NULL) {
579 char *ptr = strchr(str, delim);
580 if (ptr != NULL) {
581 *ptr = 0;
582 t = ptr + 1;
583 }
584 }
585 if (head != NULL) {
586 *head = h;
587 }
588 if (tail != NULL) {
589 *tail = t;
590 }
591} // __kmp_str_split
592
593/* strtok_r() is not available on Windows* OS. This function reimplements
594 strtok_r(). */
596 char *str, // String to split into tokens. Note: String *is* modified!
597 char const *delim, // Delimiters.
598 char **buf // Internal buffer.
599) {
600 char *token = NULL;
601#if KMP_OS_WINDOWS
602 // On Windows* OS there is no strtok_r() function. Let us implement it.
603 if (str != NULL) {
604 *buf = str; // First call, initialize buf.
605 }
606 *buf += strspn(*buf, delim); // Skip leading delimiters.
607 if (**buf != 0) { // Rest of the string is not yet empty.
608 token = *buf; // Use it as result.
609 *buf += strcspn(*buf, delim); // Skip non-delimiters.
610 if (**buf != 0) { // Rest of the string is not yet empty.
611 **buf = 0; // Terminate token here.
612 *buf += 1; // Advance buf to start with the next token next time.
613 }
614 }
615#else
616 // On Linux* OS and OS X*, strtok_r() is available. Let us use it.
617 token = strtok_r(str, delim, buf);
618#endif
619 return token;
620} // __kmp_str_token
621
622int __kmp_basic_str_to_int(char const *str) {
623 int result;
624 char const *t;
625
626 result = 0;
627
628 for (t = str; *t != '\0'; ++t) {
629 if (*t < '0' || *t > '9')
630 break;
631 // Cap parsing to create largest integer
632 if (result >= (INT_MAX - (*t - '0')) / 10) {
633 result = INT_MAX;
634 break;
635 }
636 result = (result * 10) + (*t - '0');
637 }
638
639 return result;
640}
641
642int __kmp_str_to_int(char const *str, char sentinel) {
643 int result, factor;
644 char const *t;
645
646 result = 0;
647
648 for (t = str; *t != '\0'; ++t) {
649 if (*t < '0' || *t > '9')
650 break;
651 // Cap parsing to create largest integer
652 if (result >= (INT_MAX - (*t - '0')) / 10) {
653 result = INT_MAX;
654 break;
655 }
656 result = (result * 10) + (*t - '0');
657 }
658
659 // Parse rest of large number by skipping the digits so t points to sentinel
660 if (result == INT_MAX)
661 for (t = str; *t != '\0'; ++t)
662 if (*t < '0' || *t > '9')
663 break;
664
665 switch (*t) {
666 case '\0': /* the current default for no suffix is bytes */
667 factor = 1;
668 break;
669 case 'b':
670 case 'B': /* bytes */
671 ++t;
672 factor = 1;
673 break;
674 case 'k':
675 case 'K': /* kilo-bytes */
676 ++t;
677 factor = 1024;
678 break;
679 case 'm':
680 case 'M': /* mega-bytes */
681 ++t;
682 factor = (1024 * 1024);
683 break;
684 default:
685 if (*t != sentinel)
686 return (-1);
687 t = "";
688 factor = 1;
689 }
690
691 if (result > (INT_MAX / factor))
692 result = INT_MAX;
693 else
694 result *= factor;
695
696 return (*t != 0 ? 0 : result);
697} // __kmp_str_to_int
698
699/* The routine parses input string. It is expected it is a unsigned integer with
700 optional unit. Units are: "b" for bytes, "kb" or just "k" for kilobytes, "mb"
701 or "m" for megabytes, ..., "yb" or "y" for yottabytes. :-) Unit name is
702 case-insensitive. The routine returns 0 if everything is ok, or error code:
703 -1 in case of overflow, -2 in case of unknown unit. *size is set to parsed
704 value. In case of overflow *size is set to KMP_SIZE_T_MAX, in case of unknown
705 unit *size is set to zero. */
706void __kmp_str_to_size( // R: Error code.
707 char const *str, // I: String of characters, unsigned number and unit ("b",
708 // "kb", etc).
709 size_t *out, // O: Parsed number.
710 size_t dfactor, // I: The factor if none of the letters specified.
711 char const **error // O: Null if everything is ok, error message otherwise.
712) {
713
714 size_t value = 0;
715 size_t factor = 0;
716 int overflow = 0;
717 int i = 0;
718 int digit;
719
720 KMP_DEBUG_ASSERT(str != NULL);
721
722 // Skip spaces.
723 while (str[i] == ' ' || str[i] == '\t') {
724 ++i;
725 }
726
727 // Parse number.
728 if (str[i] < '0' || str[i] > '9') {
729 *error = KMP_I18N_STR(NotANumber);
730 return;
731 }
732 do {
733 digit = str[i] - '0';
734 overflow = overflow || (value > (KMP_SIZE_T_MAX - digit) / 10);
735 value = (value * 10) + digit;
736 ++i;
737 } while (str[i] >= '0' && str[i] <= '9');
738
739 // Skip spaces.
740 while (str[i] == ' ' || str[i] == '\t') {
741 ++i;
742 }
743
744// Parse unit.
745#define _case(ch, exp) \
746 case ch: \
747 case ch - ('a' - 'A'): { \
748 size_t shift = (exp)*10; \
749 ++i; \
750 if (shift < sizeof(size_t) * 8) { \
751 factor = (size_t)(1) << shift; \
752 } else { \
753 overflow = 1; \
754 } \
755 } break;
756 switch (str[i]) {
757 _case('k', 1); // Kilo
758 _case('m', 2); // Mega
759 _case('g', 3); // Giga
760 _case('t', 4); // Tera
761 _case('p', 5); // Peta
762 _case('e', 6); // Exa
763 _case('z', 7); // Zetta
764 _case('y', 8); // Yotta
765 // Oops. No more units...
766 }
767#undef _case
768 if (str[i] == 'b' || str[i] == 'B') { // Skip optional "b".
769 if (factor == 0) {
770 factor = 1;
771 }
772 ++i;
773 }
774 if (!(str[i] == ' ' || str[i] == '\t' || str[i] == 0)) { // Bad unit
775 *error = KMP_I18N_STR(BadUnit);
776 return;
777 }
778
779 if (factor == 0) {
780 factor = dfactor;
781 }
782
783 // Apply factor.
784 overflow = overflow || (value > (KMP_SIZE_T_MAX / factor));
785 value *= factor;
786
787 // Skip spaces.
788 while (str[i] == ' ' || str[i] == '\t') {
789 ++i;
790 }
791
792 if (str[i] != 0) {
793 *error = KMP_I18N_STR(IllegalCharacters);
794 return;
795 }
796
797 if (overflow) {
798 *error = KMP_I18N_STR(ValueTooLarge);
799 *out = KMP_SIZE_T_MAX;
800 return;
801 }
802
803 *error = NULL;
804 *out = value;
805} // __kmp_str_to_size
806
807void __kmp_str_to_uint( // R: Error code.
808 char const *str, // I: String of characters, unsigned number.
809 kmp_uint64 *out, // O: Parsed number.
810 char const **error // O: Null if everything is ok, error message otherwise.
811) {
812 size_t value = 0;
813 int overflow = 0;
814 int i = 0;
815 int digit;
816
817 KMP_DEBUG_ASSERT(str != NULL);
818
819 // Skip spaces.
820 while (str[i] == ' ' || str[i] == '\t') {
821 ++i;
822 }
823
824 // Parse number.
825 if (str[i] < '0' || str[i] > '9') {
826 *error = KMP_I18N_STR(NotANumber);
827 return;
828 }
829 do {
830 digit = str[i] - '0';
831 overflow = overflow || (value > (KMP_SIZE_T_MAX - digit) / 10);
832 value = (value * 10) + digit;
833 ++i;
834 } while (str[i] >= '0' && str[i] <= '9');
835
836 // Skip spaces.
837 while (str[i] == ' ' || str[i] == '\t') {
838 ++i;
839 }
840
841 if (str[i] != 0) {
842 *error = KMP_I18N_STR(IllegalCharacters);
843 return;
844 }
845
846 if (overflow) {
847 *error = KMP_I18N_STR(ValueTooLarge);
848 *out = (kmp_uint64)-1;
849 return;
850 }
851
852 *error = NULL;
853 *out = value;
854} // __kmp_str_to_unit
855
856// end of file //
char buf[BUFFER_SIZE]
void * target(void *task)
int result[2]
void const char const char int ITT_FORMAT __itt_group_sync x void const char ITT_FORMAT __itt_group_sync s void ITT_FORMAT __itt_group_sync p void ITT_FORMAT p void ITT_FORMAT p no args __itt_suppress_mode_t unsigned int void size_t ITT_FORMAT d void ITT_FORMAT p void ITT_FORMAT p __itt_model_site __itt_model_site_instance ITT_FORMAT p __itt_model_task __itt_model_task_instance ITT_FORMAT p void ITT_FORMAT p void ITT_FORMAT p void size_t ITT_FORMAT d void ITT_FORMAT p const wchar_t ITT_FORMAT s const char ITT_FORMAT s const char ITT_FORMAT s const char ITT_FORMAT s no args void ITT_FORMAT p size_t ITT_FORMAT d no args const wchar_t const wchar_t ITT_FORMAT s __itt_heap_function void size_t int ITT_FORMAT d __itt_heap_function void ITT_FORMAT p __itt_heap_function void void size_t int ITT_FORMAT d no args no args unsigned int ITT_FORMAT u const __itt_domain __itt_id ITT_FORMAT lu const __itt_domain __itt_id __itt_id __itt_string_handle ITT_FORMAT p const __itt_domain __itt_id ITT_FORMAT p const __itt_domain __itt_id __itt_timestamp __itt_timestamp ITT_FORMAT lu const __itt_domain __itt_id __itt_id __itt_string_handle ITT_FORMAT p const __itt_domain ITT_FORMAT p const __itt_domain __itt_string_handle unsigned long long ITT_FORMAT lu const __itt_domain __itt_string_handle unsigned long long ITT_FORMAT lu const __itt_domain __itt_id __itt_string_handle __itt_metadata_type size_t void * data
void const char const char int ITT_FORMAT __itt_group_sync x void const char ITT_FORMAT __itt_group_sync s void ITT_FORMAT __itt_group_sync p void ITT_FORMAT p void ITT_FORMAT p no args __itt_suppress_mode_t unsigned int void size_t ITT_FORMAT d void ITT_FORMAT p void ITT_FORMAT p __itt_model_site __itt_model_site_instance ITT_FORMAT p __itt_model_task __itt_model_task_instance ITT_FORMAT p void ITT_FORMAT p void ITT_FORMAT p void size_t ITT_FORMAT d void ITT_FORMAT p const wchar_t ITT_FORMAT s const char ITT_FORMAT s const char ITT_FORMAT s const char ITT_FORMAT s no args void ITT_FORMAT p size_t ITT_FORMAT d no args const wchar_t const wchar_t ITT_FORMAT s __itt_heap_function void size_t int ITT_FORMAT d __itt_heap_function void ITT_FORMAT p __itt_heap_function void void size_t int ITT_FORMAT d no args no args unsigned int ITT_FORMAT u const __itt_domain __itt_id ITT_FORMAT lu const __itt_domain __itt_id __itt_id __itt_string_handle ITT_FORMAT p const __itt_domain __itt_id ITT_FORMAT p const __itt_domain __itt_id __itt_timestamp __itt_timestamp ITT_FORMAT lu const __itt_domain __itt_id __itt_id __itt_string_handle ITT_FORMAT p const __itt_domain ITT_FORMAT p const __itt_domain __itt_string_handle unsigned long long ITT_FORMAT lu const __itt_domain __itt_string_handle unsigned long long ITT_FORMAT lu const __itt_domain __itt_id __itt_string_handle __itt_metadata_type size_t void ITT_FORMAT p const __itt_domain __itt_id __itt_string_handle const wchar_t size_t ITT_FORMAT lu const __itt_domain __itt_id __itt_relation __itt_id ITT_FORMAT p const wchar_t int ITT_FORMAT __itt_group_mark d __itt_event ITT_FORMAT __itt_group_mark d void const wchar_t const wchar_t int ITT_FORMAT __itt_group_sync __itt_group_fsync x void const wchar_t int const wchar_t int int ITT_FORMAT __itt_group_sync __itt_group_fsync x void ITT_FORMAT __itt_group_sync __itt_group_fsync p void ITT_FORMAT __itt_group_sync __itt_group_fsync p void size_t ITT_FORMAT lu no args __itt_obj_prop_t __itt_obj_state_t ITT_FORMAT d const char ITT_FORMAT s const char ITT_FORMAT s __itt_frame ITT_FORMAT p __itt_counter ITT_FORMAT p __itt_counter unsigned long long ITT_FORMAT lu __itt_counter unsigned long long ITT_FORMAT lu __itt_counter __itt_clock_domain unsigned long long void ITT_FORMAT p const wchar_t ITT_FORMAT S __itt_mark_type const wchar_t ITT_FORMAT S __itt_mark_type const char ITT_FORMAT s __itt_mark_type ITT_FORMAT d __itt_caller ITT_FORMAT p __itt_caller ITT_FORMAT p no args const __itt_domain __itt_clock_domain unsigned long long __itt_id ITT_FORMAT lu const __itt_domain __itt_clock_domain unsigned long long __itt_id __itt_id void ITT_FORMAT p const __itt_domain __itt_id __itt_id __itt_string_handle ITT_FORMAT p const __itt_domain __itt_id ITT_FORMAT lu const __itt_domain __itt_clock_domain unsigned long long __itt_id __itt_string_handle __itt_scope ITT_FORMAT d const __itt_domain __itt_scope __itt_string_handle const char size_t ITT_FORMAT lu const __itt_domain __itt_clock_domain unsigned long long __itt_relation __itt_id ITT_FORMAT lu __itt_track_group __itt_string_handle __itt_track_group_type ITT_FORMAT d __itt_track ITT_FORMAT p void int const int int const char int ITT_FORMAT d void void const char * path
void const char const char int ITT_FORMAT __itt_group_sync x void const char ITT_FORMAT __itt_group_sync s void ITT_FORMAT __itt_group_sync p void ITT_FORMAT p void ITT_FORMAT p no args __itt_suppress_mode_t unsigned int void size_t ITT_FORMAT d void ITT_FORMAT p void ITT_FORMAT p __itt_model_site __itt_model_site_instance ITT_FORMAT p __itt_model_task __itt_model_task_instance ITT_FORMAT p void ITT_FORMAT p void ITT_FORMAT p void size_t ITT_FORMAT d void ITT_FORMAT p const wchar_t ITT_FORMAT s const char ITT_FORMAT s const char ITT_FORMAT s const char ITT_FORMAT s no args void ITT_FORMAT p size_t ITT_FORMAT d no args const wchar_t const wchar_t ITT_FORMAT s __itt_heap_function void size_t int ITT_FORMAT d __itt_heap_function void ITT_FORMAT p __itt_heap_function void void size_t int ITT_FORMAT d no args no args unsigned int ITT_FORMAT u const __itt_domain __itt_id ITT_FORMAT lu const __itt_domain __itt_id __itt_id __itt_string_handle ITT_FORMAT p const __itt_domain __itt_id ITT_FORMAT p const __itt_domain __itt_id __itt_timestamp __itt_timestamp ITT_FORMAT lu const __itt_domain __itt_id __itt_id __itt_string_handle ITT_FORMAT p const __itt_domain ITT_FORMAT p const __itt_domain __itt_string_handle unsigned long long value
void const char const char int ITT_FORMAT __itt_group_sync x void const char ITT_FORMAT __itt_group_sync s void ITT_FORMAT __itt_group_sync p void ITT_FORMAT p void ITT_FORMAT p no args __itt_suppress_mode_t unsigned int void size_t size
void const char const char int ITT_FORMAT __itt_group_sync x void const char ITT_FORMAT __itt_group_sync s void ITT_FORMAT __itt_group_sync p void ITT_FORMAT p void ITT_FORMAT p no args __itt_suppress_mode_t unsigned int void size_t ITT_FORMAT d void ITT_FORMAT p void ITT_FORMAT p __itt_model_site __itt_model_site_instance ITT_FORMAT p __itt_model_task __itt_model_task_instance ITT_FORMAT p void ITT_FORMAT p void ITT_FORMAT p void size_t ITT_FORMAT d void ITT_FORMAT p const wchar_t ITT_FORMAT s const char ITT_FORMAT s const char ITT_FORMAT s const char ITT_FORMAT s no args void ITT_FORMAT p size_t ITT_FORMAT d no args const wchar_t const wchar_t ITT_FORMAT s __itt_heap_function void size_t int ITT_FORMAT d __itt_heap_function void ITT_FORMAT p __itt_heap_function void void size_t int ITT_FORMAT d no args no args unsigned int ITT_FORMAT u const __itt_domain __itt_id ITT_FORMAT lu const __itt_domain __itt_id __itt_id __itt_string_handle ITT_FORMAT p const __itt_domain __itt_id ITT_FORMAT p const __itt_domain __itt_id __itt_timestamp __itt_timestamp ITT_FORMAT lu const __itt_domain __itt_id __itt_id __itt_string_handle ITT_FORMAT p const __itt_domain ITT_FORMAT p const __itt_domain __itt_string_handle unsigned long long ITT_FORMAT lu const __itt_domain __itt_string_handle unsigned long long ITT_FORMAT lu const __itt_domain __itt_id __itt_string_handle __itt_metadata_type size_t void ITT_FORMAT p const __itt_domain __itt_id __itt_string_handle const wchar_t size_t ITT_FORMAT lu const __itt_domain __itt_id head
void const char const char int ITT_FORMAT __itt_group_sync x void const char ITT_FORMAT __itt_group_sync s void ITT_FORMAT __itt_group_sync p void ITT_FORMAT p void ITT_FORMAT p no args __itt_suppress_mode_t unsigned int void size_t ITT_FORMAT d void ITT_FORMAT p void ITT_FORMAT p __itt_model_site __itt_model_site_instance ITT_FORMAT p __itt_model_task __itt_model_task_instance ITT_FORMAT p void ITT_FORMAT p void ITT_FORMAT p void size_t ITT_FORMAT d void ITT_FORMAT p const wchar_t ITT_FORMAT s const char ITT_FORMAT s const char ITT_FORMAT s const char ITT_FORMAT s no args void ITT_FORMAT p size_t ITT_FORMAT d no args const wchar_t const wchar_t ITT_FORMAT s __itt_heap_function h
void const char const char int ITT_FORMAT __itt_group_sync x void const char ITT_FORMAT __itt_group_sync s void ITT_FORMAT __itt_group_sync p void ITT_FORMAT p void ITT_FORMAT p no args __itt_suppress_mode_t unsigned int void size_t ITT_FORMAT d void ITT_FORMAT p void ITT_FORMAT p __itt_model_site __itt_model_site_instance ITT_FORMAT p __itt_model_task __itt_model_task_instance ITT_FORMAT p void ITT_FORMAT p void ITT_FORMAT p void size_t ITT_FORMAT d void ITT_FORMAT p const wchar_t ITT_FORMAT s const char ITT_FORMAT s const char ITT_FORMAT s const char ITT_FORMAT s no args void ITT_FORMAT p size_t ITT_FORMAT d no args const wchar_t const wchar_t ITT_FORMAT s __itt_heap_function void size_t int ITT_FORMAT d __itt_heap_function void ITT_FORMAT p __itt_heap_function void void size_t int ITT_FORMAT d no args no args unsigned int ITT_FORMAT u const __itt_domain __itt_id ITT_FORMAT lu const __itt_domain __itt_id __itt_id __itt_string_handle ITT_FORMAT p const __itt_domain __itt_id ITT_FORMAT p const __itt_domain __itt_id __itt_timestamp __itt_timestamp ITT_FORMAT lu const __itt_domain __itt_id __itt_id __itt_string_handle ITT_FORMAT p const __itt_domain ITT_FORMAT p const __itt_domain __itt_string_handle unsigned long long ITT_FORMAT lu const __itt_domain __itt_string_handle unsigned long long ITT_FORMAT lu const __itt_domain __itt_id __itt_string_handle __itt_metadata_type size_t void ITT_FORMAT p const __itt_domain __itt_id __itt_string_handle const wchar_t size_t ITT_FORMAT lu const __itt_domain __itt_id __itt_relation __itt_id tail
#define KMP_INTERNAL_MALLOC(sz)
Definition kmp.h:113
#define KMP_INTERNAL_REALLOC(p, sz)
Definition kmp.h:115
#define FALSE
Definition kmp.h:1349
#define KMP_INTERNAL_FREE(p)
Definition kmp.h:114
static void __kmp_type_convert(T1 src, T2 *dest)
Definition kmp.h:4884
#define KMP_DEBUG_ASSERT(cond)
Definition kmp_debug.h:61
unsigned long long kmp_uint64
#define KMP_I18N_STR(id)
Definition kmp_i18n.h:46
#define KMP_FATAL(...)
Definition kmp_i18n.h:146
#define KMP_SIZE_T_MAX
Definition kmp_os.h:195
#define CCAST(type, var)
Definition kmp_os.h:291
#define KMP_OS_WINDOWS
#define KMP_VSNPRINTF
#define KMP_STRNCAT_S(dst, bsz, src, cnt)
#define KMP_MEMCPY_S(dst, bsz, src, cnt)
int __kmp_str_to_int(char const *str, char sentinel)
Definition kmp_str.cpp:642
void __kmp_str_fname_init(kmp_str_fname_t *fname, char const *path)
Definition kmp_str.cpp:246
void __kmp_str_to_uint(char const *str, kmp_uint64 *out, char const **error)
Definition kmp_str.cpp:807
void __kmp_str_to_size(char const *str, size_t *out, size_t dfactor, char const **error)
Definition kmp_str.cpp:706
void __kmp_str_loc_numbers(char const *Psource, int *LineBeg, int *LineEndOrCol)
Definition kmp_str.cpp:305
void __kmp_str_fname_free(kmp_str_fname_t *fname)
Definition kmp_str.cpp:277
void __kmp_str_split(char *str, char delim, char **head, char **tail)
Definition kmp_str.cpp:571
void __kmp_str_buf_clear(kmp_str_buf_t *buffer)
Definition kmp_str.cpp:71
void __kmp_str_replace(char *str, char search_for, char replace_with)
Definition kmp_str.cpp:561
void __kmp_str_buf_detach(kmp_str_buf_t *buffer)
Definition kmp_str.cpp:110
#define _case(ch, exp)
bool __kmp_str_contains(char const *target, int len, char const *data)
Definition kmp_str.cpp:520
int __kmp_str_eqf(char const *lhs, char const *rhs)
Definition kmp_str.cpp:404
void __kmp_str_buf_reserve(kmp_str_buf_t *buffer, size_t size)
Definition kmp_str.cpp:80
#define KMP_STR_BUF_INVARIANT(b)
Definition kmp_str.cpp:59
int __kmp_str_match(char const *target, int len, char const *data)
Definition kmp_str.cpp:505
int __kmp_str_buf_vprint(kmp_str_buf_t *buffer, char const *format, va_list args)
Definition kmp_str.cpp:161
kmp_str_loc_t __kmp_str_loc_init(char const *psource, bool init_fname)
Definition kmp_str.cpp:347
void __kmp_str_buf_free(kmp_str_buf_t *buffer)
Definition kmp_str.cpp:123
int __kmp_str_fname_match(kmp_str_fname_t const *fname, char const *pattern)
Definition kmp_str.cpp:283
char * __kmp_str_format(char const *format,...)
Definition kmp_str.cpp:448
int __kmp_str_match_true(char const *data)
Definition kmp_str.cpp:552
void __kmp_str_buf_cat(kmp_str_buf_t *buffer, char const *str, size_t len)
Definition kmp_str.cpp:134
void __kmp_str_loc_free(kmp_str_loc_t *loc)
Definition kmp_str.cpp:393
int __kmp_basic_str_to_int(char const *str)
Definition kmp_str.cpp:622
char * __kmp_str_token(char *str, char const *delim, char **buf)
Definition kmp_str.cpp:595
void __kmp_str_buf_catbuf(kmp_str_buf_t *dest, const kmp_str_buf_t *src)
Definition kmp_str.cpp:146
#define args
int __kmp_str_buf_print(kmp_str_buf_t *buffer, char const *format,...)
Definition kmp_str.cpp:221
int __kmp_str_match_false(char const *data)
Definition kmp_str.cpp:543
void __kmp_str_free(char **str)
Definition kmp_str.cpp:494
void __kmp_str_buf_print_size(kmp_str_buf_t *buf, size_t size)
Definition kmp_str.cpp:232
struct kmp_str_fname kmp_str_fname_t
Definition kmp_str.h:72
struct kmp_str_loc kmp_str_loc_t
Definition kmp_str.h:100
struct kmp_str_buf kmp_str_buf_t
Definition kmp_str.h:38
#define TOLOWER(c)
Definition kmp_str.h:30
#define i
Definition kmp_stub.cpp:87
static id loc
char bulk[512]
Definition kmp_str.h:36
unsigned int size
Definition kmp_str.h:34
char * str
Definition kmp_str.h:33
char * base
Definition kmp_str.h:70
char * path
Definition kmp_str.h:68
char * dir
Definition kmp_str.h:69