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