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