Line data Source code
1 : #pragma once
2 :
3 : #include <petscsystypes.h>
4 : #include <petscerror.h>
5 : #include <petscmacros.h>
6 : #include <petscsys.h>
7 :
8 : /* SUBMANSEC = Sys */
9 :
10 : #include <stddef.h> /* size_t */
11 : #include <string.h> /* for memcpy, memset */
12 :
13 : PETSC_EXTERN PetscErrorCode PetscMemcmp(const void *, const void *, size_t, PetscBool *);
14 : PETSC_EXTERN PetscErrorCode PetscStrToArray(const char[], char, int *, char ***);
15 : PETSC_EXTERN PetscErrorCode PetscStrToArrayDestroy(int, char **);
16 : PETSC_EXTERN PetscErrorCode PetscStrcasecmp(const char[], const char[], PetscBool *);
17 : PETSC_EXTERN PetscErrorCode PetscStrendswithwhich(const char[], const char *const *, PetscInt *);
18 : PETSC_EXTERN PetscErrorCode PetscStrArrayallocpy(const char *const *, char ***);
19 : PETSC_EXTERN PetscErrorCode PetscStrArrayDestroy(char ***);
20 : PETSC_EXTERN PetscErrorCode PetscStrNArrayallocpy(PetscInt, const char *const *, char ***);
21 : PETSC_EXTERN PetscErrorCode PetscStrNArrayDestroy(PetscInt, char ***);
22 : PETSC_EXTERN PetscErrorCode PetscStrreplace(MPI_Comm, const char[], char[], size_t);
23 : PETSC_EXTERN PetscErrorCode PetscStrcmpAny(const char[], PetscBool *, const char[], ...);
24 :
25 : PETSC_EXTERN PetscErrorCode PetscTokenCreate(const char[], char, PetscToken *);
26 : PETSC_EXTERN PetscErrorCode PetscTokenFind(PetscToken, char *[]);
27 : PETSC_EXTERN PetscErrorCode PetscTokenDestroy(PetscToken *);
28 :
29 : PETSC_EXTERN PetscErrorCode PetscStrInList(const char[], const char[], char, PetscBool *);
30 : PETSC_EXTERN const char *PetscBasename(const char[]);
31 : PETSC_EXTERN PetscErrorCode PetscEListFind(PetscInt, const char *const *, const char *, PetscInt *, PetscBool *);
32 : PETSC_EXTERN PetscErrorCode PetscEnumFind(const char *const *, const char *, PetscEnum *, PetscBool *);
33 :
34 : PETSC_EXTERN PetscErrorCode PetscStrcat(char[], const char[]);
35 : PETSC_EXTERN PetscErrorCode PetscStrcpy(char[], const char[]);
36 :
37 : #define PetscAssertPointer_Private(ptr, arg) PetscAssert((ptr), PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Null Pointer: Parameter '" PetscStringize(ptr) "' # " PetscStringize(arg))
38 :
39 : /*@C
40 : PetscStrtolower - Converts a string to lower case
41 :
42 : Not Collective, No Fortran Support
43 :
44 : Input Parameter:
45 : . a - pointer to string
46 :
47 : Level: intermediate
48 :
49 : .seealso: `PetscStrtoupper()`
50 : @*/
51 2 : static inline PetscErrorCode PetscStrtolower(char a[])
52 : {
53 2 : PetscFunctionBegin;
54 2 : PetscAssertPointer_Private(a, 1);
55 18 : while (*a) {
56 16 : if (*a >= 'A' && *a <= 'Z') *a += 'a' - 'A';
57 16 : a++;
58 : }
59 2 : PetscFunctionReturn(PETSC_SUCCESS);
60 : }
61 :
62 : /*@C
63 : PetscStrtoupper - Converts a string to upper case
64 :
65 : Not Collective, No Fortran Support
66 :
67 : Input Parameter:
68 : . a - pointer to string
69 :
70 : Level: intermediate
71 :
72 : .seealso: `PetscStrtolower()`
73 : @*/
74 : static inline PetscErrorCode PetscStrtoupper(char a[])
75 : {
76 : PetscFunctionBegin;
77 : PetscAssertPointer_Private(a, 1);
78 : while (*a) {
79 : if (*a >= 'a' && *a <= 'z') *a += 'A' - 'a';
80 : a++;
81 : }
82 : PetscFunctionReturn(PETSC_SUCCESS);
83 : }
84 :
85 : /*@C
86 : PetscStrlen - Gets the length of a string
87 :
88 : Not Collective, No Fortran Support
89 :
90 : Input Parameter:
91 : . s - pointer to string
92 :
93 : Output Parameter:
94 : . len - length in bytes
95 :
96 : Level: intermediate
97 :
98 : Note:
99 : This routine is analogous to `strlen()`. `NULL` string returns a length of zero.
100 :
101 : .seealso: `PetscStrallocpy()`
102 : @*/
103 46637 : static inline PetscErrorCode PetscStrlen(const char s[], size_t *len)
104 : {
105 46637 : PetscFunctionBegin;
106 46637 : PetscAssertPointer_Private(len, 2);
107 46637 : if (s) {
108 : #if PetscHasBuiltin(__builtin_strlen)
109 46637 : *len = __builtin_strlen(s);
110 : #else
111 : *len = strlen(s);
112 : #endif
113 : } else {
114 0 : *len = 0;
115 : }
116 46637 : PetscFunctionReturn(PETSC_SUCCESS);
117 : }
118 :
119 : /*@C
120 : PetscStrallocpy - Allocates space to hold a copy of a string then copies the string into the new space
121 :
122 : Not Collective, No Fortran Support
123 :
124 : Input Parameter:
125 : . s - pointer to string
126 :
127 : Output Parameter:
128 : . t - the copied string
129 :
130 : Level: intermediate
131 :
132 : Notes:
133 : `NULL` string returns a new `NULL` string.
134 :
135 : If `t` has previously been allocated then that memory is lost, you may need to `PetscFree()`
136 : the array before calling this routine.
137 :
138 : .seealso: `PetscStrArrayallocpy()`, `PetscStrNArrayallocpy()`
139 : @*/
140 14806 : static inline PetscErrorCode PetscStrallocpy(const char s[], char *t[])
141 : {
142 14806 : PetscFunctionBegin;
143 14806 : PetscAssertPointer_Private(t, 2);
144 14806 : *t = PETSC_NULLPTR;
145 14806 : if (s) {
146 14806 : size_t len;
147 14806 : char *tmp;
148 :
149 0 : PetscAssertPointer_Private(s, 1);
150 14806 : PetscCall(PetscStrlen(s, &len));
151 14806 : PetscCall(PetscMalloc1(len + 1, &tmp));
152 : #if PetscHasBuiltin(__builtin_memcpy)
153 14806 : __builtin_memcpy(tmp, s, len);
154 : #else
155 : memcpy(tmp, s, len);
156 : #endif
157 14806 : tmp[len] = '\0';
158 14806 : *t = tmp;
159 : }
160 14806 : PetscFunctionReturn(PETSC_SUCCESS);
161 : }
162 :
163 43262 : static inline void PetscStrcmpNoError(const char a[], const char b[], PetscBool *flg)
164 : {
165 43262 : if (!a && !b) {
166 0 : *flg = PETSC_TRUE;
167 43262 : } else if (!a || !b) {
168 0 : *flg = PETSC_FALSE;
169 : } else {
170 : #if PetscHasBuiltin(__builtin_strcmp)
171 43262 : *flg = __builtin_strcmp(a, b) ? PETSC_FALSE : PETSC_TRUE;
172 : #else
173 : *flg = strcmp(a, b) ? PETSC_FALSE : PETSC_TRUE;
174 : #endif
175 : }
176 43262 : }
177 :
178 : /*@C
179 : PetscStrcmp - Compares two strings
180 :
181 : Not Collective, No Fortran Support
182 :
183 : Input Parameters:
184 : + a - pointer to string first string
185 : - b - pointer to second string
186 :
187 : Output Parameter:
188 : . flg - `PETSC_TRUE` if the two strings are equal
189 :
190 : Level: intermediate
191 :
192 : .seealso: `PetscStrcmpAny()`, `PetscStrgrt()`, `PetscStrncmp()`, `PetscStrcasecmp()`
193 : @*/
194 43262 : static inline PetscErrorCode PetscStrcmp(const char a[], const char b[], PetscBool *flg)
195 : {
196 43262 : PetscFunctionBegin;
197 43262 : PetscAssertPointer_Private(flg, 3);
198 43262 : PetscStrcmpNoError(a, b, flg);
199 43262 : PetscFunctionReturn(PETSC_SUCCESS);
200 : }
201 :
202 : #if defined(__GNUC__) && !defined(__clang__)
203 : #if __GNUC__ >= 8
204 : #define PETSC_SILENCE_WSTRINGOP_TRUNCATION_BEGIN \
205 : do { \
206 : _Pragma("GCC diagnostic push"); \
207 : _Pragma("GCC diagnostic ignored \"-Wstringop-truncation\""); \
208 : } while (0)
209 : #define PETSC_SILENCE_WSTRINGOP_TRUNCATION_END _Pragma("GCC diagnostic pop")
210 : #endif
211 : #endif
212 :
213 : #ifndef PETSC_SILENCE_WSTRINGOP_TRUNCATION_BEGIN
214 : #define PETSC_SILENCE_WSTRINGOP_TRUNCATION_BEGIN (void)0
215 : #define PETSC_SILENCE_WSTRINGOP_TRUNCATION_END (void)0
216 : #endif
217 :
218 : /*@C
219 : PetscStrncpy - Copies a string up to a certain length
220 :
221 : Not Collective
222 :
223 : Input Parameters:
224 : + t - pointer to string
225 : - n - the length to copy
226 :
227 : Output Parameter:
228 : . s - the copied string
229 :
230 : Level: intermediate
231 :
232 : Notes:
233 : `NULL` string returns a string starting with zero.
234 :
235 : If the string that is being copied is of length `n` or larger, then the entire string is not
236 : copied and the final location of `s` is set to `NULL`. This is different then the behavior of
237 : `strncpy()` which leaves `s` non-terminated if there is not room for the entire string.
238 :
239 : Developer Note:
240 : Should this be `PetscStrlcpy()` to reflect its behavior which is like `strlcpy()` not
241 : `strncpy()`?
242 :
243 : .seealso: `PetscStrlcat()`, `PetscStrallocpy()`
244 : @*/
245 7377 : static inline PetscErrorCode PetscStrncpy(char s[], const char t[], size_t n)
246 : {
247 7377 : PetscFunctionBegin;
248 7377 : if (s) PetscAssert(n, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Requires an output string of length at least 1 to hold the termination character");
249 7377 : if (t) {
250 7377 : PetscAssertPointer_Private(s, 1);
251 7377 : PETSC_SILENCE_WSTRINGOP_TRUNCATION_BEGIN;
252 : #if PetscHasBuiltin(__builtin_strncpy)
253 7377 : __builtin_strncpy(s, t, n);
254 : #else
255 : strncpy(s, t, n);
256 : #endif
257 7377 : PETSC_SILENCE_WSTRINGOP_TRUNCATION_END;
258 7377 : s[n - 1] = '\0';
259 0 : } else if (s) {
260 0 : s[0] = '\0';
261 : }
262 7377 : PetscFunctionReturn(PETSC_SUCCESS);
263 : }
264 :
265 : /*@C
266 : PetscStrlcat - Concatenates a string onto a given string, up to a given length
267 :
268 : Not Collective, No Fortran Support
269 :
270 : Input Parameters:
271 : + s - pointer to string to be added to at end
272 : . t - string to be added
273 : - n - length of the original allocated string
274 :
275 : Level: intermediate
276 :
277 : Note:
278 : Unlike the system call `strncat()`, the length passed in is the length of the
279 : original allocated space, not the length of the left-over space. This is
280 : similar to the BSD system call `strlcat()`.
281 :
282 : .seealso: `PetscStrncpy()`
283 : @*/
284 28308 : static inline PetscErrorCode PetscStrlcat(char s[], const char t[], size_t n)
285 : {
286 28308 : size_t len;
287 :
288 28308 : PetscFunctionBegin;
289 28308 : if (!t) PetscFunctionReturn(PETSC_SUCCESS);
290 28308 : PetscAssert(n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "String buffer length must be positive");
291 28308 : PetscCall(PetscStrlen(s, &len));
292 28308 : PETSC_SILENCE_WSTRINGOP_TRUNCATION_BEGIN;
293 : #if PetscHasBuiltin(__builtin_strncat)
294 28308 : __builtin_strncat(s, t, n - len);
295 : #else
296 : strncat(s, t, n - len);
297 : #endif
298 28308 : PETSC_SILENCE_WSTRINGOP_TRUNCATION_END;
299 28308 : s[n - 1] = '\0';
300 28308 : PetscFunctionReturn(PETSC_SUCCESS);
301 : }
302 :
303 : #undef PETSC_SILENCE_WSTRINGOP_TRUNCATION_BEGIN
304 : #undef PETSC_SILENCE_WSTRINGOP_TRUNCATION_END
305 :
306 : /*@C
307 : PetscStrncmp - Compares two strings, up to a certain length
308 :
309 : Not Collective, No Fortran Support
310 :
311 : Input Parameters:
312 : + a - pointer to first string
313 : . b - pointer to second string
314 : - n - length to compare up to
315 :
316 : Output Parameter:
317 : . t - `PETSC_TRUE` if the two strings are equal, `PETSC_FALSE` otherwise
318 :
319 : Level: intermediate
320 :
321 : Note:
322 : If `n` is `0`, `t` is set to `PETSC_FALSE`. `a` and/or `b` may be `NULL` in this case.
323 :
324 : .seealso: `PetscStrgrt()`, `PetscStrcmp()`, `PetscStrcasecmp()`
325 : @*/
326 : static inline PetscErrorCode PetscStrncmp(const char a[], const char b[], size_t n, PetscBool *t)
327 : {
328 : PetscFunctionBegin;
329 : PetscAssertPointer_Private(t, 4);
330 : *t = PETSC_FALSE;
331 : if (n) {
332 : PetscAssertPointer_Private(a, 1);
333 : PetscAssertPointer_Private(b, 2);
334 : }
335 : #if PetscHasBuiltin(__builtin_strncmp)
336 : *t = __builtin_strncmp(a, b, n) ? PETSC_FALSE : PETSC_TRUE;
337 : #else
338 : *t = strncmp(a, b, n) ? PETSC_FALSE : PETSC_TRUE;
339 : #endif
340 : PetscFunctionReturn(PETSC_SUCCESS);
341 : }
342 :
343 : /*@C
344 : PetscStrrstr - Locates last occurrence of string in another string
345 :
346 : Not Collective, No Fortran Support
347 :
348 : Input Parameters:
349 : + a - pointer to string
350 : - b - string to find
351 :
352 : Output Parameter:
353 : . tmp - location of occurrence
354 :
355 : Level: intermediate
356 :
357 : .seealso: `PetscStrbeginswithwhich()`, `PetscStrendswith()`, `PetscStrtoupper`,
358 : `PetscStrtolower()`, `PetscStrrchr()`, `PetscStrchr()`, `PetscStrncmp()`, `PetscStrlen()`,
359 : `PetscStrcmp()`
360 : @*/
361 : static inline PetscErrorCode PetscStrrstr(const char a[], const char b[], char *tmp[])
362 : {
363 : const char *ltmp = PETSC_NULLPTR;
364 :
365 : PetscFunctionBegin;
366 : PetscAssertPointer_Private(a, 1);
367 : PetscAssertPointer_Private(b, 2);
368 : PetscAssertPointer_Private(tmp, 3);
369 : while (a) {
370 : #if PetscHasBuiltin(__builtin_strstr)
371 : a = (char *)__builtin_strstr(a, b);
372 : #else
373 : a = (char *)strstr(a, b);
374 : #endif
375 : if (a) ltmp = a++;
376 : }
377 : *tmp = (char *)ltmp;
378 : PetscFunctionReturn(PETSC_SUCCESS);
379 : }
380 :
381 : /*@C
382 : PetscStrstr - Locates first occurrence of string in another string
383 :
384 : Not Collective, No Fortran Support
385 :
386 : Input Parameters:
387 : + haystack - string to search
388 : - needle - string to find
389 :
390 : Output Parameter:
391 : . tmp - location of `needle` within `haystack`, `NULL` if `needle` is not found
392 :
393 : Level: intermediate
394 :
395 : .seealso: `PetscStrbeginswithwhich()`, `PetscStrendswith()`, `PetscStrtoupper`,
396 : `PetscStrtolower()`, `PetscStrrchr()`, `PetscStrchr()`, `PetscStrncmp()`, `PetscStrlen()`,
397 : `PetscStrcmp()`
398 : @*/
399 2 : static inline PetscErrorCode PetscStrstr(const char haystack[], const char needle[], char *tmp[])
400 : {
401 2 : PetscFunctionBegin;
402 2 : PetscAssertPointer_Private(haystack, 1);
403 2 : PetscAssertPointer_Private(needle, 2);
404 2 : PetscAssertPointer_Private(tmp, 3);
405 : #if PetscHasBuiltin(__builtin_strstr)
406 2 : *tmp = (char *)__builtin_strstr(haystack, needle);
407 : #else
408 : *tmp = (char *)strstr(haystack, needle);
409 : #endif
410 2 : PetscFunctionReturn(PETSC_SUCCESS);
411 : }
412 :
413 : /*@C
414 : PetscStrgrt - If first string is greater than the second
415 :
416 : Not Collective, No Fortran Support
417 :
418 : Input Parameters:
419 : + a - pointer to first string
420 : - b - pointer to second string
421 :
422 : Output Parameter:
423 : . flg - `PETSC_TRUE` if `a` is strictly greater than `b`, `PETSC_FALSE` otherwise
424 :
425 : Level: intermediate
426 :
427 : Note:
428 : `NULL` arguments are OK, a `NULL` string is considered smaller than all others. If both `a`
429 : and `b` are `NULL` then `t` is set to `PETSC_FALSE`.
430 :
431 : .seealso: `PetscStrcmp()`, `PetscStrncmp()`, `PetscStrcasecmp()`
432 : @*/
433 : static inline PetscErrorCode PetscStrgrt(const char a[], const char b[], PetscBool *t)
434 : {
435 : PetscFunctionBegin;
436 : PetscAssertPointer_Private(t, 3);
437 : if (!a && !b) {
438 : *t = PETSC_FALSE;
439 : } else if (a && !b) {
440 : *t = PETSC_TRUE;
441 : } else if (!a && b) {
442 : *t = PETSC_FALSE;
443 : } else {
444 : #if PetscHasBuiltin(__builtin_strcmp)
445 : *t = __builtin_strcmp(a, b) > 0 ? PETSC_TRUE : PETSC_FALSE;
446 : #else
447 : *t = strcmp(a, b) > 0 ? PETSC_TRUE : PETSC_FALSE;
448 : #endif
449 : }
450 : PetscFunctionReturn(PETSC_SUCCESS);
451 : }
452 :
453 : /*@C
454 : PetscStrchr - Locates first occurrence of a character in a string
455 :
456 : Not Collective, No Fortran Support
457 :
458 : Input Parameters:
459 : + a - pointer to string
460 : - b - character
461 :
462 : Output Parameter:
463 : . c - location of occurrence, `NULL` if not found
464 :
465 : Level: intermediate
466 :
467 : .seealso: `PetscStrrchr()`, `PetscTokenCreate()`, `PetscStrendswith()`, `PetscStrbeginsswith()`
468 : @*/
469 : static inline PetscErrorCode PetscStrchr(const char a[], char b, char *c[])
470 : {
471 : PetscFunctionBegin;
472 : PetscAssertPointer_Private(a, 1);
473 : PetscAssertPointer_Private(c, 3);
474 : #if PetscHasBuiltin(__builtin_strchr)
475 : *c = (char *)__builtin_strchr(a, b);
476 : #else
477 : *c = (char *)strchr(a, b);
478 : #endif
479 : PetscFunctionReturn(PETSC_SUCCESS);
480 : }
481 :
482 : /*@C
483 : PetscStrrchr - Locates one location past the last occurrence of a character in a string, if
484 : the character is not found then returns entire string
485 :
486 : Not Collective, No Fortran Support
487 :
488 : Input Parameters:
489 : + a - pointer to string
490 : - b - character
491 :
492 : Output Parameter:
493 : . c - one past location of `b` in `a`, or `a` if `b` was not found
494 :
495 : Level: intermediate
496 :
497 : .seealso: `PetscStrchr()`, `PetscTokenCreate()`, `PetscStrendswith()`, `PetscStrbeginsswith()`
498 : @*/
499 : static inline PetscErrorCode PetscStrrchr(const char a[], char b, char *c[])
500 : {
501 : PetscFunctionBegin;
502 : PetscAssertPointer_Private(a, 1);
503 : PetscAssertPointer_Private(c, 3);
504 : #if PetscHasBuiltin(__builtin_strrchr)
505 : *c = (char *)__builtin_strrchr(a, b);
506 : #else
507 : *c = (char *)strrchr(a, b);
508 : #endif
509 : if (!*c) *c = (char *)a;
510 : else *c = *c + 1;
511 : PetscFunctionReturn(PETSC_SUCCESS);
512 : }
513 :
514 : /*@C
515 : PetscStrendswith - Determines if a string ends with a certain string
516 :
517 : Not Collective, No Fortran Support
518 :
519 : Input Parameters:
520 : + a - string to search
521 : - b - string to end with
522 :
523 : Output Parameter:
524 : . flg - `PETSC_TRUE` if `a` ends with `b`, `PETSC_FALSE` otherwise
525 :
526 : Level: intermediate
527 :
528 : Note:
529 : Both `a` and `b` may be `NULL` (in which case `flg` is set to `PETSC_FALSE`) bot not either.
530 :
531 : .seealso: `PetscStrendswithwhich()`, `PetscStrbeginswith()`, `PetscStrtoupper`,
532 : `PetscStrtolower()`, `PetscStrrchr()`, `PetscStrchr()`, `PetscStrncmp()`, `PetscStrlen()`,
533 : `PetscStrcmp()`
534 : @*/
535 3 : static inline PetscErrorCode PetscStrendswith(const char a[], const char b[], PetscBool *flg)
536 : {
537 3 : size_t na = 0, nb = 0;
538 :
539 3 : PetscFunctionBegin;
540 3 : PetscAssertPointer_Private(flg, 3);
541 : // do this here to silence stupid "may be used uninitialized"" warnings
542 3 : *flg = PETSC_FALSE;
543 3 : PetscCall(PetscStrlen(a, &na));
544 3 : PetscCall(PetscStrlen(b, &nb));
545 3 : if (na >= nb) {
546 : #if PetscHasBuiltin(__builtin_memcmp)
547 3 : *flg = __builtin_memcmp(b, a + (na - nb), nb) == 0 ? PETSC_TRUE : PETSC_FALSE;
548 : #else
549 : *flg = memcmp(b, a + (na - nb), nb) == 0 ? PETSC_TRUE : PETSC_FALSE;
550 : #endif
551 : }
552 3 : PetscFunctionReturn(PETSC_SUCCESS);
553 : }
554 :
555 : /*@C
556 : PetscStrbeginswith - Determines if a string begins with a certain string
557 :
558 : Not Collective, No Fortran Support
559 :
560 : Input Parameters:
561 : + a - string to search
562 : - b - string to begin with
563 :
564 : Output Parameter:
565 : . flg - `PETSC_TRUE` if `a` begins with `b`, `PETSC_FALSE` otherwise
566 :
567 : Level: intermediate
568 :
569 : Notes:
570 : Both `a` and `b` may be `NULL` (in which case `flg` is set to `PETSC_FALSE`) but not
571 : either.
572 :
573 : `a` and `b` may point to the same string.
574 :
575 : .seealso: `PetscStrendswithwhich()`, `PetscStrendswith()`, `PetscStrtoupper`,
576 : `PetscStrtolower()`, `PetscStrrchr()`, `PetscStrchr()`, `PetscStrncmp()`, `PetscStrlen()`,
577 : `PetscStrcmp()`
578 : @*/
579 : static inline PetscErrorCode PetscStrbeginswith(const char a[], const char b[], PetscBool *flg)
580 : {
581 : size_t len = 0;
582 :
583 : PetscFunctionBegin;
584 : PetscAssertPointer_Private(flg, 3);
585 : // do this here to silence stupid "may be used uninitialized"" warnings
586 : *flg = PETSC_FALSE;
587 : PetscCall(PetscStrlen(b, &len));
588 : PetscCall(PetscStrncmp(a, b, len, flg));
589 : PetscFunctionReturn(PETSC_SUCCESS);
590 : }
591 :
592 : #undef PetscAssertPointer_Private
593 :
594 : /*@C
595 : PetscMemmove - Copies `n` bytes, beginning at location `b`, to the space
596 : beginning at location `a`. Copying between regions that overlap will
597 : take place correctly. Use `PetscMemcpy()` if the locations do not overlap
598 :
599 : Not Collective, No Fortran Support
600 :
601 : Input Parameters:
602 : + b - pointer to initial memory space
603 : . a - pointer to copy space
604 : - n - length (in bytes) of space to copy
605 :
606 : Level: intermediate
607 :
608 : Notes:
609 : `PetscArraymove()` is preferred
610 :
611 : This routine is analogous to `memmove()`.
612 :
613 : .seealso: `PetscMemcpy()`, `PetscMemcmp()`, `PetscArrayzero()`, `PetscMemzero()`, `PetscArraycmp()`, `PetscArraycpy()`, `PetscStrallocpy()`,
614 : `PetscArraymove()`
615 : @*/
616 : static inline PetscErrorCode PetscMemmove(void *a, const void *b, size_t n)
617 : {
618 : PetscFunctionBegin;
619 : if (PetscUnlikely((n == 0) || (a == b))) PetscFunctionReturn(PETSC_SUCCESS);
620 : PetscAssert(a, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Trying to copy %zu bytes to null pointer (Argument #1)", n);
621 : PetscAssert(b, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Trying to copy %zu bytes from a null pointer (Argument #2)", n);
622 : #if PetscDefined(HAVE_MEMMOVE)
623 : memmove((char *)a, (const char *)b, n);
624 : #else
625 : if (a < b) {
626 : if ((char *)a <= (char *)b - n) {
627 : memcpy(a, b, n);
628 : } else {
629 : const size_t ptr_diff = (size_t)((char *)b - (char *)a);
630 :
631 : memcpy(a, b, ptr_diff);
632 : PetscCall(PetscMemmove((void *)b, (char *)b + ptr_diff, n - ptr_diff));
633 : }
634 : } else {
635 : if ((char *)b <= (char *)a - n) {
636 : memcpy(a, b, n);
637 : } else {
638 : const size_t ptr_diff = (size_t)((char *)a - (char *)b);
639 :
640 : memcpy((void *)((char *)b + n), (char *)b + (n - ptr_diff), ptr_diff);
641 : PetscCall(PetscMemmove(a, b, n - ptr_diff));
642 : }
643 : }
644 : #endif
645 : PetscFunctionReturn(PETSC_SUCCESS);
646 : }
647 :
648 : /*@C
649 : PetscMemcpy - Copies `n` bytes, beginning at location `b`, to the space
650 : beginning at location `a`. The two memory regions CANNOT overlap, use
651 : `PetscMemmove()` in that case.
652 :
653 : Not Collective, No Fortran Support
654 :
655 : Input Parameters:
656 : + b - pointer to initial memory space
657 : - n - length (in bytes) of space to copy
658 :
659 : Output Parameter:
660 : . a - pointer to copy space
661 :
662 : Level: intermediate
663 :
664 : Compile Options\:
665 : + `PETSC_PREFER_DCOPY_FOR_MEMCPY` - cause the BLAS `dcopy()` routine to be used for memory copies on double precision values.
666 : . `PETSC_PREFER_COPY_FOR_MEMCPY` - cause C code to be used for memory copies on double precision values.
667 : - `PETSC_PREFER_FORTRAN_FORMEMCPY` - cause Fortran code to be used for memory copies on double precision values.
668 :
669 : Notes:
670 : Prefer `PetscArraycpy()`
671 :
672 : This routine is analogous to `memcpy()`.
673 :
674 : .seealso: `PetscMemzero()`, `PetscMemcmp()`, `PetscArrayzero()`, `PetscArraycmp()`, `PetscArraycpy()`, `PetscMemmove()`, `PetscStrallocpy()`
675 : @*/
676 2101398 : static inline PetscErrorCode PetscMemcpy(void *a, const void *b, size_t n)
677 : {
678 2101398 : const PETSC_UINTPTR_T al = (PETSC_UINTPTR_T)a;
679 2101398 : const PETSC_UINTPTR_T bl = (PETSC_UINTPTR_T)b;
680 :
681 2101398 : PetscFunctionBegin;
682 2101398 : if (PetscUnlikely((n == 0) || (a == b))) PetscFunctionReturn(PETSC_SUCCESS);
683 2096453 : PetscAssert(a, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Trying to copy %zu bytes to a null pointer (Argument #1)", n);
684 2096453 : PetscAssert(b, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Trying to copy %zu bytes from a null pointer (Argument #2)", n);
685 2096453 : PetscAssert(!(((al > bl) && (al - bl) < n) || (bl - al) < n), PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Memory regions overlap: either use PetscMemmove(), or make sure your copy regions and lengths are correct. Length (bytes) %zu first address %" PRIxPTR " second address %" PRIxPTR, n, al, bl);
686 2096453 : if (PetscDefined(PREFER_DCOPY_FOR_MEMCPY) || PetscDefined(PREFER_COPY_FOR_MEMCPY) || PetscDefined(PREFER_FORTRAN_FORMEMCPY)) {
687 : if (!(al % sizeof(PetscScalar)) && !(n % sizeof(PetscScalar))) {
688 : const size_t scalar_len = n / sizeof(PetscScalar);
689 : const PetscScalar *x = (PetscScalar *)b;
690 : PetscScalar *y = (PetscScalar *)a;
691 :
692 : #if PetscDefined(PREFER_DCOPY_FOR_MEMCPY)
693 : {
694 : const PetscBLASInt one = 1;
695 : PetscBLASInt blen;
696 :
697 : PetscCall(PetscBLASIntCast(scalar_len, &blen));
698 : PetscCallBLAS("BLAScopy", BLAScopy_(&blen, x, &one, y, &one));
699 : }
700 : #elif PetscDefined(PREFER_FORTRAN_FORMEMCPY)
701 : fortrancopy_(&scalar_len, x, y);
702 : #else
703 : for (size_t i = 0; i < scalar_len; i++) y[i] = x[i];
704 : #endif
705 2096453 : PetscFunctionReturn(PETSC_SUCCESS);
706 : }
707 : }
708 2096453 : memcpy(a, b, n);
709 2096453 : PetscFunctionReturn(PETSC_SUCCESS);
710 : }
711 :
712 : /*@C
713 : PetscMemzero - Zeros the specified memory.
714 :
715 : Not Collective, No Fortran Support
716 :
717 : Input Parameters:
718 : + a - pointer to beginning memory location
719 : - n - length (in bytes) of memory to initialize
720 :
721 : Level: intermediate
722 :
723 : Compile Option:
724 : `PETSC_PREFER_BZERO` - on certain machines (the IBM RS6000) the bzero() routine happens
725 : to be faster than the memset() routine. This flag causes the bzero() routine to be used.
726 :
727 : Note:
728 : Prefer `PetscArrayzero()`
729 :
730 : .seealso: `PetscMemcpy()`, `PetscMemcmp()`, `PetscArrayzero()`, `PetscArraycmp()`, `PetscArraycpy()`, `PetscMemmove()`, `PetscStrallocpy()`
731 : @*/
732 547330 : static inline PetscErrorCode PetscMemzero(void *a, size_t n)
733 : {
734 547330 : PetscFunctionBegin;
735 547330 : if (PetscUnlikely(n == 0)) PetscFunctionReturn(PETSC_SUCCESS);
736 547327 : PetscAssert(a, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Trying to zero %zu bytes at a null pointer", n);
737 547327 : if (PetscDefined(PREFER_ZERO_FOR_MEMZERO) || PetscDefined(PREFER_FORTRAN_FOR_MEMZERO)) {
738 : if (!(((PETSC_UINTPTR_T)a) % sizeof(PetscScalar)) && !(n % sizeof(PetscScalar))) {
739 : const size_t scalar_len = n / sizeof(PetscScalar);
740 : PetscScalar *x = (PetscScalar *)a;
741 :
742 : if (PetscDefined(PREFER_ZERO_FOR_MEMZERO)) {
743 : for (size_t i = 0; i < scalar_len; ++i) x[i] = 0;
744 : } else {
745 : #if PetscDefined(PREFER_FORTRAN_FOR_MEMZERO)
746 : fortranzero_(&scalar_len, x);
747 : #else
748 : (void)scalar_len;
749 : (void)x;
750 : #endif
751 : }
752 547327 : PetscFunctionReturn(PETSC_SUCCESS);
753 : }
754 : }
755 : #if PetscDefined(PREFER_BZERO)
756 : bzero(a, n);
757 : #else
758 547327 : memset(a, 0, n);
759 : #endif
760 547327 : PetscFunctionReturn(PETSC_SUCCESS);
761 : }
762 :
763 : /*MC
764 : PetscArraycmp - Compares two arrays in memory.
765 :
766 : Synopsis:
767 : #include <petscstring.h>
768 : PetscErrorCode PetscArraycmp(const anytype *str1, const anytype *str2, size_t cnt, PetscBool *e)
769 :
770 : Not Collective
771 :
772 : Input Parameters:
773 : + str1 - First array
774 : . str2 - Second array
775 : - cnt - Count of the array, not in bytes, but number of entries in the arrays
776 :
777 : Output Parameter:
778 : . e - `PETSC_TRUE` if equal else `PETSC_FALSE`.
779 :
780 : Level: intermediate
781 :
782 : Notes:
783 : This routine is a preferred replacement to `PetscMemcmp()`
784 :
785 : The arrays must be of the same type
786 :
787 : .seealso: `PetscMemcpy()`, `PetscMemcmp()`, `PetscArrayzero()`, `PetscMemzero()`, `PetscArraycpy()`, `PetscMemmove()`, `PetscStrallocpy()`,
788 : `PetscArraymove()`
789 : M*/
790 : #define PetscArraycmp(str1, str2, cnt, e) ((sizeof(*(str1)) == sizeof(*(str2))) ? PetscMemcmp((str1), (str2), (size_t)(cnt) * sizeof(*(str1)), (e)) : PETSC_ERR_ARG_SIZ)
791 :
792 : /*MC
793 : PetscArraymove - Copies from one array in memory to another, the arrays may overlap. Use `PetscArraycpy()` when the arrays
794 : do not overlap
795 :
796 : Synopsis:
797 : #include <petscstring.h>
798 : PetscErrorCode PetscArraymove(anytype *str1, const anytype *str2, size_t cnt)
799 :
800 : Not Collective
801 :
802 : Input Parameters:
803 : + str1 - First array
804 : . str2 - Second array
805 : - cnt - Count of the array, not in bytes, but number of entries in the arrays
806 :
807 : Level: intermediate
808 :
809 : Notes:
810 : This routine is a preferred replacement to `PetscMemmove()`
811 :
812 : The arrays must be of the same type
813 :
814 : .seealso: `PetscMemcpy()`, `PetscMemcmp()`, `PetscArrayzero()`, `PetscMemzero()`, `PetscArraycpy()`, `PetscMemmove()`, `PetscArraycmp()`, `PetscStrallocpy()`
815 : M*/
816 : #define PetscArraymove(str1, str2, cnt) ((sizeof(*(str1)) == sizeof(*(str2))) ? PetscMemmove((str1), (str2), (size_t)(cnt) * sizeof(*(str1))) : PETSC_ERR_ARG_SIZ)
817 :
818 : /*MC
819 : PetscArraycpy - Copies from one array in memory to another
820 :
821 : Synopsis:
822 : #include <petscstring.h>
823 : PetscErrorCode PetscArraycpy(anytype *str1, const anytype *str2, size_t cnt)
824 :
825 : Not Collective
826 :
827 : Input Parameters:
828 : + str1 - First array (destination)
829 : . str2 - Second array (source)
830 : - cnt - Count of the array, not in bytes, but number of entries in the arrays
831 :
832 : Level: intermediate
833 :
834 : Notes:
835 : This routine is a preferred replacement to `PetscMemcpy()`
836 :
837 : The arrays must be of the same type
838 :
839 : .seealso: `PetscMemcpy()`, `PetscMemcmp()`, `PetscArrayzero()`, `PetscMemzero()`, `PetscArraymove()`, `PetscMemmove()`, `PetscArraycmp()`, `PetscStrallocpy()`
840 : M*/
841 : #define PetscArraycpy(str1, str2, cnt) ((sizeof(*(str1)) == sizeof(*(str2))) ? PetscMemcpy((str1), (str2), (size_t)(cnt) * sizeof(*(str1))) : PETSC_ERR_ARG_SIZ)
842 :
843 : /*MC
844 : PetscArrayzero - Zeros an array in memory.
845 :
846 : Synopsis:
847 : #include <petscstring.h>
848 : PetscErrorCode PetscArrayzero(anytype *str1, size_t cnt)
849 :
850 : Not Collective
851 :
852 : Input Parameters:
853 : + str1 - array
854 : - cnt - Count of the array, not in bytes, but number of entries in the array
855 :
856 : Level: intermediate
857 :
858 : Note:
859 : This routine is a preferred replacement to `PetscMemzero()`
860 :
861 : .seealso: `PetscMemcpy()`, `PetscMemcmp()`, `PetscMemzero()`, `PetscArraycmp()`, `PetscArraycpy()`, `PetscMemmove()`, `PetscStrallocpy()`, `PetscArraymove()`
862 : M*/
863 : #define PetscArrayzero(str1, cnt) PetscMemzero((str1), ((size_t)(cnt)) * sizeof(*(str1)))
|