blob: 5338edf7243ee135a63c26de16ef44c24d036b20 [file] [log] [blame]
Jim Cownie5e8470a2013-09-27 10:38:44 +00001/*
Jonathan Peytonde4749b2016-12-14 23:01:24 +00002 * kmp_str.cpp -- String manipulation routines.
Jim Cownie5e8470a2013-09-27 10:38:44 +00003 */
4
Jim Cownie5e8470a2013-09-27 10:38:44 +00005//===----------------------------------------------------------------------===//
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
Jim Cownie5e8470a2013-09-27 10:38:44 +000014#include "kmp_str.h"
15
Jonathan Peyton30419822017-05-12 18:01:32 +000016#include <stdarg.h> // va_*
17#include <stdio.h> // vsnprintf()
18#include <stdlib.h> // malloc(), realloc()
Jim Cownie5e8470a2013-09-27 10:38:44 +000019
20#include "kmp.h"
21#include "kmp_i18n.h"
22
Jonathan Peyton30419822017-05-12 18:01:32 +000023/* String buffer.
Jim Cownie5e8470a2013-09-27 10:38:44 +000024
Jonathan Peyton30419822017-05-12 18:01:32 +000025 Usage:
Jim Cownie5e8470a2013-09-27 10:38:44 +000026
Jonathan Peyton30419822017-05-12 18:01:32 +000027 // Declare buffer and initialize it.
28 kmp_str_buf_t buffer;
29 __kmp_str_buf_init( & buffer );
Jim Cownie5e8470a2013-09-27 10:38:44 +000030
Jonathan Peyton30419822017-05-12 18:01:32 +000031 // 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);
Jim Cownie5e8470a2013-09-27 10:38:44 +000034
Jonathan Peyton30419822017-05-12 18:01:32 +000035 // 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 );
Jim Cownie5e8470a2013-09-27 10:38:44 +000038
Jonathan Peyton30419822017-05-12 18:01:32 +000039 // Free buffer.
40 __kmp_str_buf_free( & buffer );
Jim Cownie5e8470a2013-09-27 10:38:44 +000041
Jonathan Peyton30419822017-05-12 18:01:32 +000042 // Alternatively, you can detach allocated memory from buffer:
43 __kmp_str_buf_detach( & buffer );
44 return buffer.str; // That memory should be freed eventually.
Jim Cownie5e8470a2013-09-27 10:38:44 +000045
Jonathan Peyton30419822017-05-12 18:01:32 +000046 Notes:
Jim Cownie5e8470a2013-09-27 10:38:44 +000047
Jonathan Peyton30419822017-05-12 18:01:32 +000048 * 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.
Jim Cownie5e8470a2013-09-27 10:38:44 +000056*/
57
58// TODO: __kmp_str_buf_print() can use thread local memory allocator.
59
Jonathan Peyton30419822017-05-12 18:01:32 +000060#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 }
Jim Cownie5e8470a2013-09-27 10:38:44 +000071
Jonathan Peyton30419822017-05-12 18:01:32 +000072void __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;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +000077 }
Jonathan Peyton30419822017-05-12 18:01:32 +000078 KMP_STR_BUF_INVARIANT(buffer);
Jim Cownie5e8470a2013-09-27 10:38:44 +000079} // __kmp_str_buf_clear
80
Jonathan Peyton30419822017-05-12 18:01:32 +000081void __kmp_str_buf_reserve(kmp_str_buf_t *buffer, int size) {
82 KMP_STR_BUF_INVARIANT(buffer);
83 KMP_DEBUG_ASSERT(size >= 0);
Jim Cownie5e8470a2013-09-27 10:38:44 +000084
Jonathan Peyton30419822017-05-12 18:01:32 +000085 if (buffer->size < (unsigned int)size) {
86 // Calculate buffer size.
87 do {
88 buffer->size *= 2;
89 } while (buffer->size < (unsigned int)size);
Jim Cownie5e8470a2013-09-27 10:38:44 +000090
Jonathan Peyton30419822017-05-12 18:01:32 +000091 // 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);
Jonathan Peytonbd3a7632017-09-27 20:36:27 +000096 }
Jonathan Peyton30419822017-05-12 18:01:32 +000097 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);
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000102 }
103 }
104 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000105
Jonathan Peyton30419822017-05-12 18:01:32 +0000106 KMP_DEBUG_ASSERT(buffer->size > 0);
107 KMP_DEBUG_ASSERT(buffer->size >= (unsigned)size);
108 KMP_STR_BUF_INVARIANT(buffer);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000109} // __kmp_str_buf_reserve
110
Jonathan Peyton30419822017-05-12 18:01:32 +0000111void __kmp_str_buf_detach(kmp_str_buf_t *buffer) {
112 KMP_STR_BUF_INVARIANT(buffer);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000113
Jonathan Peyton30419822017-05-12 18:01:32 +0000114 // 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);
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000119 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000120 KMP_MEMCPY_S(buffer->str, buffer->size, buffer->bulk, buffer->used + 1);
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000121 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000122} // __kmp_str_buf_detach
123
Jonathan Peyton30419822017-05-12 18:01:32 +0000124void __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);
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000128 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000129 buffer->str = buffer->bulk;
130 buffer->size = sizeof(buffer->bulk);
131 buffer->used = 0;
132 KMP_STR_BUF_INVARIANT(buffer);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000133} // __kmp_str_buf_free
134
Jonathan Peyton30419822017-05-12 18:01:32 +0000135void __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);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000144} // __kmp_str_buf_cat
145
Jonathan Peyton6d88e042018-12-13 23:14:24 +0000146void __kmp_str_buf_catbuf(kmp_str_buf_t *dest, const kmp_str_buf_t *src) {
147 KMP_DEBUG_ASSERT(dest);
148 KMP_DEBUG_ASSERT(src);
149 KMP_STR_BUF_INVARIANT(dest);
150 KMP_STR_BUF_INVARIANT(src);
151 if (!src->str || !src->used)
152 return;
153 __kmp_str_buf_reserve(dest, dest->used + src->used + 1);
154 KMP_MEMCPY(dest->str + dest->used, src->str, src->used);
155 dest->str[dest->used + src->used] = 0;
156 dest->used += src->used;
157 KMP_STR_BUF_INVARIANT(dest);
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;
Jonathan Peyton30419822017-05-12 18:01:32 +0000164 KMP_STR_BUF_INVARIANT(buffer);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000165
Jonathan Peyton30419822017-05-12 18:01:32 +0000166 for (;;) {
167 int const free = buffer->size - buffer->used;
Jonathan Peyton30419822017-05-12 18:01:32 +0000168 int size;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000169
Jonathan Peyton30419822017-05-12 18:01:32 +0000170 // Try to format string.
171 {
172/* On Linux* OS Intel(R) 64, vsnprintf() modifies args argument, so vsnprintf()
173 crashes if it is called for the second time with the same args. To prevent
174 the crash, we have to pass a fresh intact copy of args to vsnprintf() on each
175 iteration.
Jim Cownie5e8470a2013-09-27 10:38:44 +0000176
Jonathan Peyton30419822017-05-12 18:01:32 +0000177 Unfortunately, standard va_copy() macro is not available on Windows* OS.
178 However, it seems vsnprintf() does not modify args argument on Windows* OS.
Jim Cownie5e8470a2013-09-27 10:38:44 +0000179*/
180
Jonathan Peyton30419822017-05-12 18:01:32 +0000181#if !KMP_OS_WINDOWS
182 va_list _args;
Jonathan Peyton04477082017-08-19 23:53:36 +0000183 va_copy(_args, args); // Make copy of args.
Jonathan Peyton30419822017-05-12 18:01:32 +0000184#define args _args // Substitute args with its copy, _args.
185#endif // KMP_OS_WINDOWS
186 rc = KMP_VSNPRINTF(buffer->str + buffer->used, free, format, args);
187#if !KMP_OS_WINDOWS
188#undef args // Remove substitution.
189 va_end(_args);
190#endif // KMP_OS_WINDOWS
191 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000192
Jonathan Peyton30419822017-05-12 18:01:32 +0000193 // No errors, string has been formatted.
194 if (rc >= 0 && rc < free) {
195 buffer->used += rc;
196 break;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000197 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000198
Jonathan Peyton30419822017-05-12 18:01:32 +0000199 // Error occurred, buffer is too small.
200 if (rc >= 0) {
201 // C99-conforming implementation of vsnprintf returns required buffer size
202 size = buffer->used + rc + 1;
203 } else {
204 // Older implementations just return -1. Double buffer size.
205 size = buffer->size * 2;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000206 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000207
Jonathan Peyton30419822017-05-12 18:01:32 +0000208 // Enlarge buffer.
209 __kmp_str_buf_reserve(buffer, size);
210
211 // And try again.
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000212 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000213
214 KMP_DEBUG_ASSERT(buffer->size > 0);
215 KMP_STR_BUF_INVARIANT(buffer);
Jonathan Peyton6d88e042018-12-13 23:14:24 +0000216 return rc;
Jonathan Peyton30419822017-05-12 18:01:32 +0000217} // __kmp_str_buf_vprint
218
Jonathan Peyton6d88e042018-12-13 23:14:24 +0000219// Return the number of characters written
220int __kmp_str_buf_print(kmp_str_buf_t *buffer, char const *format, ...) {
221 int rc;
Jonathan Peyton30419822017-05-12 18:01:32 +0000222 va_list args;
223 va_start(args, format);
Jonathan Peyton6d88e042018-12-13 23:14:24 +0000224 rc = __kmp_str_buf_vprint(buffer, format, args);
Jonathan Peyton30419822017-05-12 18:01:32 +0000225 va_end(args);
Jonathan Peyton6d88e042018-12-13 23:14:24 +0000226 return rc;
Jonathan Peyton30419822017-05-12 18:01:32 +0000227} // __kmp_str_buf_print
228
229/* The function prints specified size to buffer. Size is expressed using biggest
230 possible unit, for example 1024 is printed as "1k". */
231void __kmp_str_buf_print_size(kmp_str_buf_t *buf, size_t size) {
232 char const *names[] = {"", "k", "M", "G", "T", "P", "E", "Z", "Y"};
233 int const units = sizeof(names) / sizeof(char const *);
234 int u = 0;
235 if (size > 0) {
236 while ((size % 1024 == 0) && (u + 1 < units)) {
237 size = size / 1024;
238 ++u;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000239 }
240 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000241
242 __kmp_str_buf_print(buf, "%" KMP_SIZE_T_SPEC "%s", size, names[u]);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000243} // __kmp_str_buf_print_size
244
Jonathan Peyton30419822017-05-12 18:01:32 +0000245void __kmp_str_fname_init(kmp_str_fname_t *fname, char const *path) {
246 fname->path = NULL;
247 fname->dir = NULL;
248 fname->base = NULL;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000249
Jonathan Peyton30419822017-05-12 18:01:32 +0000250 if (path != NULL) {
251 char *slash = NULL; // Pointer to the last character of dir.
252 char *base = NULL; // Pointer to the beginning of basename.
253 fname->path = __kmp_str_format("%s", path);
254 // Original code used strdup() function to copy a string, but on Windows* OS
255 // Intel(R) 64 it causes assertioon id debug heap, so I had to replace
256 // strdup with __kmp_str_format().
257 if (KMP_OS_WINDOWS) {
258 __kmp_str_replace(fname->path, '\\', '/');
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000259 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000260 fname->dir = __kmp_str_format("%s", fname->path);
261 slash = strrchr(fname->dir, '/');
262 if (KMP_OS_WINDOWS &&
263 slash == NULL) { // On Windows* OS, if slash not found,
264 char first = TOLOWER(fname->dir[0]); // look for drive.
265 if ('a' <= first && first <= 'z' && fname->dir[1] == ':') {
266 slash = &fname->dir[1];
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000267 }
268 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000269 base = (slash == NULL ? fname->dir : slash + 1);
270 fname->base = __kmp_str_format("%s", base); // Copy basename
271 *base = 0; // and truncate dir.
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000272 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000273
274} // kmp_str_fname_init
275
Jonathan Peyton30419822017-05-12 18:01:32 +0000276void __kmp_str_fname_free(kmp_str_fname_t *fname) {
Jonas Hahnfeldaeb40ad2017-11-09 15:52:25 +0000277 __kmp_str_free(&fname->path);
278 __kmp_str_free(&fname->dir);
279 __kmp_str_free(&fname->base);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000280} // kmp_str_fname_free
281
Jonathan Peyton30419822017-05-12 18:01:32 +0000282int __kmp_str_fname_match(kmp_str_fname_t const *fname, char const *pattern) {
283 int dir_match = 1;
284 int base_match = 1;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000285
Jonathan Peyton30419822017-05-12 18:01:32 +0000286 if (pattern != NULL) {
287 kmp_str_fname_t ptrn;
288 __kmp_str_fname_init(&ptrn, pattern);
289 dir_match = strcmp(ptrn.dir, "*/") == 0 ||
290 (fname->dir != NULL && __kmp_str_eqf(fname->dir, ptrn.dir));
291 base_match = strcmp(ptrn.base, "*") == 0 ||
292 (fname->base != NULL && __kmp_str_eqf(fname->base, ptrn.base));
293 __kmp_str_fname_free(&ptrn);
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000294 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000295
Jonathan Peyton30419822017-05-12 18:01:32 +0000296 return dir_match && base_match;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000297} // __kmp_str_fname_match
298
Jonathan Peyton30419822017-05-12 18:01:32 +0000299kmp_str_loc_t __kmp_str_loc_init(char const *psource, int init_fname) {
300 kmp_str_loc_t loc;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000301
Jonathan Peyton30419822017-05-12 18:01:32 +0000302 loc._bulk = NULL;
303 loc.file = NULL;
304 loc.func = NULL;
305 loc.line = 0;
306 loc.col = 0;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000307
Jonathan Peyton30419822017-05-12 18:01:32 +0000308 if (psource != NULL) {
309 char *str = NULL;
310 char *dummy = NULL;
311 char *line = NULL;
312 char *col = NULL;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000313
Jonathan Peyton30419822017-05-12 18:01:32 +0000314 // Copy psource to keep it intact.
315 loc._bulk = __kmp_str_format("%s", psource);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000316
Jonathan Peyton30419822017-05-12 18:01:32 +0000317 // Parse psource string: ";file;func;line;col;;"
318 str = loc._bulk;
319 __kmp_str_split(str, ';', &dummy, &str);
320 __kmp_str_split(str, ';', &loc.file, &str);
321 __kmp_str_split(str, ';', &loc.func, &str);
322 __kmp_str_split(str, ';', &line, &str);
323 __kmp_str_split(str, ';', &col, &str);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000324
Jonathan Peyton30419822017-05-12 18:01:32 +0000325 // Convert line and col into numberic values.
326 if (line != NULL) {
327 loc.line = atoi(line);
328 if (loc.line < 0) {
329 loc.line = 0;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000330 }
331 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000332 if (col != NULL) {
333 loc.col = atoi(col);
334 if (loc.col < 0) {
335 loc.col = 0;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000336 }
337 }
338 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000339
Jonathan Peyton30419822017-05-12 18:01:32 +0000340 __kmp_str_fname_init(&loc.fname, init_fname ? loc.file : NULL);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000341
Jonathan Peyton30419822017-05-12 18:01:32 +0000342 return loc;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000343} // kmp_str_loc_init
344
Jonathan Peyton30419822017-05-12 18:01:32 +0000345void __kmp_str_loc_free(kmp_str_loc_t *loc) {
346 __kmp_str_fname_free(&loc->fname);
Jonas Hahnfeldaeb40ad2017-11-09 15:52:25 +0000347 __kmp_str_free(&(loc->_bulk));
Jonathan Peyton30419822017-05-12 18:01:32 +0000348 loc->file = NULL;
349 loc->func = NULL;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000350} // kmp_str_loc_free
351
Jonathan Peyton30419822017-05-12 18:01:32 +0000352/* This function is intended to compare file names. On Windows* OS file names
353 are case-insensitive, so functions performs case-insensitive comparison. On
354 Linux* OS it performs case-sensitive comparison. Note: The function returns
355 *true* if strings are *equal*. */
356int __kmp_str_eqf( // True, if strings are equal, false otherwise.
357 char const *lhs, // First string.
358 char const *rhs // Second string.
359 ) {
360 int result;
361#if KMP_OS_WINDOWS
362 result = (_stricmp(lhs, rhs) == 0);
363#else
364 result = (strcmp(lhs, rhs) == 0);
365#endif
366 return result;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000367} // __kmp_str_eqf
368
Jonathan Peyton30419822017-05-12 18:01:32 +0000369/* This function is like sprintf, but it *allocates* new buffer, which must be
370 freed eventually by __kmp_str_free(). The function is very convenient for
371 constructing strings, it successfully replaces strdup(), strcat(), it frees
372 programmer from buffer allocations and helps to avoid buffer overflows.
373 Examples:
Jim Cownie5e8470a2013-09-27 10:38:44 +0000374
Jonathan Peyton30419822017-05-12 18:01:32 +0000375 str = __kmp_str_format("%s", orig); //strdup() doesn't care about buffer size
376 __kmp_str_free( & str );
377 str = __kmp_str_format( "%s%s", orig1, orig2 ); // strcat(), doesn't care
378 // about buffer size.
379 __kmp_str_free( & str );
380 str = __kmp_str_format( "%s/%s.txt", path, file ); // constructing string.
381 __kmp_str_free( & str );
Jim Cownie5e8470a2013-09-27 10:38:44 +0000382
Jonathan Peyton30419822017-05-12 18:01:32 +0000383 Performance note:
384 This function allocates memory with malloc() calls, so do not call it from
385 performance-critical code. In performance-critical code consider using
386 kmp_str_buf_t instead, since it uses stack-allocated buffer for short
387 strings.
Jim Cownie5e8470a2013-09-27 10:38:44 +0000388
Jonathan Peyton30419822017-05-12 18:01:32 +0000389 Why does this function use malloc()?
390 1. __kmp_allocate() returns cache-aligned memory allocated with malloc().
391 There are no reasons in using __kmp_allocate() for strings due to extra
392 overhead while cache-aligned memory is not necessary.
393 2. __kmp_thread_malloc() cannot be used because it requires pointer to thread
394 structure. We need to perform string operations during library startup
395 (for example, in __kmp_register_library_startup()) when no thread
396 structures are allocated yet.
397 So standard malloc() is the only available option.
Jim Cownie5e8470a2013-09-27 10:38:44 +0000398*/
399
Jonathan Peyton30419822017-05-12 18:01:32 +0000400char *__kmp_str_format( // Allocated string.
401 char const *format, // Format string.
402 ... // Other parameters.
403 ) {
404 va_list args;
405 int size = 512;
406 char *buffer = NULL;
407 int rc;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000408
Jonathan Peyton30419822017-05-12 18:01:32 +0000409 // Allocate buffer.
410 buffer = (char *)KMP_INTERNAL_MALLOC(size);
411 if (buffer == NULL) {
412 KMP_FATAL(MemoryAllocFailed);
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000413 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000414
Jonathan Peyton30419822017-05-12 18:01:32 +0000415 for (;;) {
416 // Try to format string.
417 va_start(args, format);
418 rc = KMP_VSNPRINTF(buffer, size, format, args);
419 va_end(args);
420
421 // No errors, string has been formatted.
422 if (rc >= 0 && rc < size) {
423 break;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000424 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000425
Jonathan Peyton30419822017-05-12 18:01:32 +0000426 // Error occurred, buffer is too small.
427 if (rc >= 0) {
428 // C99-conforming implementation of vsnprintf returns required buffer
429 // size.
430 size = rc + 1;
431 } else {
432 // Older implementations just return -1.
433 size = size * 2;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000434 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000435
Jonathan Peyton30419822017-05-12 18:01:32 +0000436 // Enlarge buffer and try again.
437 buffer = (char *)KMP_INTERNAL_REALLOC(buffer, size);
438 if (buffer == NULL) {
439 KMP_FATAL(MemoryAllocFailed);
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000440 }
441 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000442
Jonathan Peyton30419822017-05-12 18:01:32 +0000443 return buffer;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000444} // func __kmp_str_format
445
Jonas Hahnfeldaeb40ad2017-11-09 15:52:25 +0000446void __kmp_str_free(char **str) {
Jonathan Peyton30419822017-05-12 18:01:32 +0000447 KMP_DEBUG_ASSERT(str != NULL);
Jonas Hahnfeldaeb40ad2017-11-09 15:52:25 +0000448 KMP_INTERNAL_FREE(*str);
Jonathan Peyton30419822017-05-12 18:01:32 +0000449 *str = NULL;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000450} // func __kmp_str_free
451
Jonathan Peyton30419822017-05-12 18:01:32 +0000452/* If len is zero, returns true iff target and data have exact case-insensitive
453 match. If len is negative, returns true iff target is a case-insensitive
454 substring of data. If len is positive, returns true iff target is a
455 case-insensitive substring of data or vice versa, and neither is shorter than
456 len. */
457int __kmp_str_match(char const *target, int len, char const *data) {
458 int i;
459 if (target == NULL || data == NULL) {
460 return FALSE;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000461 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000462 for (i = 0; target[i] && data[i]; ++i) {
463 if (TOLOWER(target[i]) != TOLOWER(data[i])) {
464 return FALSE;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000465 }
466 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000467 return ((len > 0) ? i >= len : (!target[i] && (len || !data[i])));
Jim Cownie5e8470a2013-09-27 10:38:44 +0000468} // __kmp_str_match
469
Jonathan Peyton30419822017-05-12 18:01:32 +0000470int __kmp_str_match_false(char const *data) {
471 int result =
472 __kmp_str_match("false", 1, data) || __kmp_str_match("off", 2, data) ||
473 __kmp_str_match("0", 1, data) || __kmp_str_match(".false.", 2, data) ||
Jonathan Peyton60eec6f2018-09-26 20:19:44 +0000474 __kmp_str_match(".f.", 2, data) || __kmp_str_match("no", 1, data) ||
475 __kmp_str_match("disabled", 0, data);
Jonathan Peyton30419822017-05-12 18:01:32 +0000476 return result;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000477} // __kmp_str_match_false
478
Jonathan Peyton30419822017-05-12 18:01:32 +0000479int __kmp_str_match_true(char const *data) {
480 int result =
481 __kmp_str_match("true", 1, data) || __kmp_str_match("on", 2, data) ||
482 __kmp_str_match("1", 1, data) || __kmp_str_match(".true.", 2, data) ||
Jonathan Peyton60eec6f2018-09-26 20:19:44 +0000483 __kmp_str_match(".t.", 2, data) || __kmp_str_match("yes", 1, data) ||
484 __kmp_str_match("enabled", 0, data);
Jonathan Peyton30419822017-05-12 18:01:32 +0000485 return result;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000486} // __kmp_str_match_true
487
Jonathan Peyton30419822017-05-12 18:01:32 +0000488void __kmp_str_replace(char *str, char search_for, char replace_with) {
489 char *found = NULL;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000490
Jonathan Peyton30419822017-05-12 18:01:32 +0000491 found = strchr(str, search_for);
492 while (found) {
493 *found = replace_with;
494 found = strchr(found + 1, search_for);
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000495 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000496} // __kmp_str_replace
497
Jonathan Peyton30419822017-05-12 18:01:32 +0000498void __kmp_str_split(char *str, // I: String to split.
499 char delim, // I: Character to split on.
500 char **head, // O: Pointer to head (may be NULL).
501 char **tail // O: Pointer to tail (may be NULL).
502 ) {
503 char *h = str;
504 char *t = NULL;
505 if (str != NULL) {
506 char *ptr = strchr(str, delim);
507 if (ptr != NULL) {
508 *ptr = 0;
509 t = ptr + 1;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000510 }
511 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000512 if (head != NULL) {
513 *head = h;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000514 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000515 if (tail != NULL) {
516 *tail = t;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000517 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000518} // __kmp_str_split
519
Jonathan Peyton30419822017-05-12 18:01:32 +0000520/* strtok_r() is not available on Windows* OS. This function reimplements
521 strtok_r(). */
522char *__kmp_str_token(
523 char *str, // String to split into tokens. Note: String *is* modified!
524 char const *delim, // Delimiters.
525 char **buf // Internal buffer.
526 ) {
527 char *token = NULL;
528#if KMP_OS_WINDOWS
529 // On Windows* OS there is no strtok_r() function. Let us implement it.
530 if (str != NULL) {
531 *buf = str; // First call, initialize buf.
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000532 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000533 *buf += strspn(*buf, delim); // Skip leading delimiters.
534 if (**buf != 0) { // Rest of the string is not yet empty.
535 token = *buf; // Use it as result.
536 *buf += strcspn(*buf, delim); // Skip non-delimiters.
537 if (**buf != 0) { // Rest of the string is not yet empty.
538 **buf = 0; // Terminate token here.
539 *buf += 1; // Advance buf to start with the next token next time.
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000540 }
541 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000542#else
543 // On Linux* OS and OS X*, strtok_r() is available. Let us use it.
544 token = strtok_r(str, delim, buf);
545#endif
546 return token;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000547} // __kmp_str_token
Jim Cownie5e8470a2013-09-27 10:38:44 +0000548
Jonathan Peyton30419822017-05-12 18:01:32 +0000549int __kmp_str_to_int(char const *str, char sentinel) {
550 int result, factor;
551 char const *t;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000552
Jonathan Peyton30419822017-05-12 18:01:32 +0000553 result = 0;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000554
Jonathan Peyton30419822017-05-12 18:01:32 +0000555 for (t = str; *t != '\0'; ++t) {
556 if (*t < '0' || *t > '9')
557 break;
558 result = (result * 10) + (*t - '0');
559 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000560
Jonathan Peyton30419822017-05-12 18:01:32 +0000561 switch (*t) {
562 case '\0': /* the current default for no suffix is bytes */
563 factor = 1;
564 break;
565 case 'b':
566 case 'B': /* bytes */
567 ++t;
568 factor = 1;
569 break;
570 case 'k':
571 case 'K': /* kilo-bytes */
572 ++t;
573 factor = 1024;
574 break;
575 case 'm':
576 case 'M': /* mega-bytes */
577 ++t;
578 factor = (1024 * 1024);
579 break;
580 default:
581 if (*t != sentinel)
582 return (-1);
583 t = "";
584 factor = 1;
585 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000586
Jonathan Peyton30419822017-05-12 18:01:32 +0000587 if (result > (INT_MAX / factor))
588 result = INT_MAX;
589 else
590 result *= factor;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000591
Jonathan Peyton30419822017-05-12 18:01:32 +0000592 return (*t != 0 ? 0 : result);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000593} // __kmp_str_to_int
594
Jonathan Peyton30419822017-05-12 18:01:32 +0000595/* The routine parses input string. It is expected it is a unsigned integer with
596 optional unit. Units are: "b" for bytes, "kb" or just "k" for kilobytes, "mb"
597 or "m" for megabytes, ..., "yb" or "y" for yottabytes. :-) Unit name is
598 case-insensitive. The routine returns 0 if everything is ok, or error code:
599 -1 in case of overflow, -2 in case of unknown unit. *size is set to parsed
600 value. In case of overflow *size is set to KMP_SIZE_T_MAX, in case of unknown
601 unit *size is set to zero. */
602void __kmp_str_to_size( // R: Error code.
603 char const *str, // I: String of characters, unsigned number and unit ("b",
604 // "kb", etc).
605 size_t *out, // O: Parsed number.
606 size_t dfactor, // I: The factor if none of the letters specified.
607 char const **error // O: Null if everything is ok, error message otherwise.
608 ) {
Jim Cownie5e8470a2013-09-27 10:38:44 +0000609
Jonathan Peyton30419822017-05-12 18:01:32 +0000610 size_t value = 0;
611 size_t factor = 0;
612 int overflow = 0;
613 int i = 0;
614 int digit;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000615
Jonathan Peyton30419822017-05-12 18:01:32 +0000616 KMP_DEBUG_ASSERT(str != NULL);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000617
Jonathan Peyton30419822017-05-12 18:01:32 +0000618 // Skip spaces.
619 while (str[i] == ' ' || str[i] == '\t') {
620 ++i;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000621 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000622
Jonathan Peyton30419822017-05-12 18:01:32 +0000623 // Parse number.
624 if (str[i] < '0' || str[i] > '9') {
625 *error = KMP_I18N_STR(NotANumber);
626 return;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000627 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000628 do {
629 digit = str[i] - '0';
630 overflow = overflow || (value > (KMP_SIZE_T_MAX - digit) / 10);
631 value = (value * 10) + digit;
632 ++i;
633 } while (str[i] >= '0' && str[i] <= '9');
Jim Cownie5e8470a2013-09-27 10:38:44 +0000634
Jonathan Peyton30419822017-05-12 18:01:32 +0000635 // Skip spaces.
636 while (str[i] == ' ' || str[i] == '\t') {
637 ++i;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000638 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000639
Jonathan Peyton30419822017-05-12 18:01:32 +0000640// Parse unit.
641#define _case(ch, exp) \
642 case ch: \
643 case ch - ('a' - 'A'): { \
644 size_t shift = (exp)*10; \
645 ++i; \
646 if (shift < sizeof(size_t) * 8) { \
647 factor = (size_t)(1) << shift; \
648 } else { \
649 overflow = 1; \
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000650 } \
Jonathan Peyton30419822017-05-12 18:01:32 +0000651 } break;
652 switch (str[i]) {
653 _case('k', 1); // Kilo
654 _case('m', 2); // Mega
655 _case('g', 3); // Giga
656 _case('t', 4); // Tera
657 _case('p', 5); // Peta
658 _case('e', 6); // Exa
659 _case('z', 7); // Zetta
660 _case('y', 8); // Yotta
661 // Oops. No more units...
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000662 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000663#undef _case
664 if (str[i] == 'b' || str[i] == 'B') { // Skip optional "b".
665 if (factor == 0) {
666 factor = 1;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000667 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000668 ++i;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000669 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000670 if (!(str[i] == ' ' || str[i] == '\t' || str[i] == 0)) { // Bad unit
671 *error = KMP_I18N_STR(BadUnit);
672 return;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000673 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000674
Jonathan Peyton30419822017-05-12 18:01:32 +0000675 if (factor == 0) {
676 factor = dfactor;
677 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000678
Jonathan Peyton30419822017-05-12 18:01:32 +0000679 // Apply factor.
680 overflow = overflow || (value > (KMP_SIZE_T_MAX / factor));
681 value *= factor;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000682
Jonathan Peyton30419822017-05-12 18:01:32 +0000683 // Skip spaces.
684 while (str[i] == ' ' || str[i] == '\t') {
685 ++i;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000686 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000687
Jonathan Peyton30419822017-05-12 18:01:32 +0000688 if (str[i] != 0) {
689 *error = KMP_I18N_STR(IllegalCharacters);
690 return;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000691 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000692
Jonathan Peyton30419822017-05-12 18:01:32 +0000693 if (overflow) {
694 *error = KMP_I18N_STR(ValueTooLarge);
695 *out = KMP_SIZE_T_MAX;
696 return;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000697 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000698
Jonathan Peyton30419822017-05-12 18:01:32 +0000699 *error = NULL;
700 *out = value;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000701} // __kmp_str_to_size
702
Jonathan Peyton30419822017-05-12 18:01:32 +0000703void __kmp_str_to_uint( // R: Error code.
704 char const *str, // I: String of characters, unsigned number.
705 kmp_uint64 *out, // O: Parsed number.
706 char const **error // O: Null if everything is ok, error message otherwise.
707 ) {
708 size_t value = 0;
709 int overflow = 0;
710 int i = 0;
711 int digit;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000712
Jonathan Peyton30419822017-05-12 18:01:32 +0000713 KMP_DEBUG_ASSERT(str != NULL);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000714
Jonathan Peyton30419822017-05-12 18:01:32 +0000715 // Skip spaces.
716 while (str[i] == ' ' || str[i] == '\t') {
717 ++i;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000718 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000719
Jonathan Peyton30419822017-05-12 18:01:32 +0000720 // Parse number.
721 if (str[i] < '0' || str[i] > '9') {
722 *error = KMP_I18N_STR(NotANumber);
723 return;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000724 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000725 do {
726 digit = str[i] - '0';
727 overflow = overflow || (value > (KMP_SIZE_T_MAX - digit) / 10);
728 value = (value * 10) + digit;
729 ++i;
730 } while (str[i] >= '0' && str[i] <= '9');
Jim Cownie5e8470a2013-09-27 10:38:44 +0000731
Jonathan Peyton30419822017-05-12 18:01:32 +0000732 // Skip spaces.
733 while (str[i] == ' ' || str[i] == '\t') {
734 ++i;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000735 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000736
Jonathan Peyton30419822017-05-12 18:01:32 +0000737 if (str[i] != 0) {
738 *error = KMP_I18N_STR(IllegalCharacters);
739 return;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000740 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000741
Jonathan Peyton30419822017-05-12 18:01:32 +0000742 if (overflow) {
743 *error = KMP_I18N_STR(ValueTooLarge);
744 *out = (kmp_uint64)-1;
745 return;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000746 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000747
Jonathan Peyton30419822017-05-12 18:01:32 +0000748 *error = NULL;
749 *out = value;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000750} // __kmp_str_to_unit
751
Jim Cownie5e8470a2013-09-27 10:38:44 +0000752// end of file //