kmp_str.cpp 24 KB

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