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