Actual source code: petscstring.h

  1: #pragma once

  3: #include <petscsystypes.h>
  4: #include <petscerror.h>
  5: #include <petscmacros.h>
  6: #include <petscsys.h>

  8: /* SUBMANSEC = Sys */

 10: #include <stddef.h> /* size_t */
 11: #include <string.h> /* for memcpy, memset */

 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[], ...);

 25: PETSC_EXTERN PetscErrorCode PetscTokenCreate(const char[], char, PetscToken *);
 26: PETSC_EXTERN PetscErrorCode PetscTokenFind(PetscToken, char *[]);
 27: PETSC_EXTERN PetscErrorCode PetscTokenDestroy(PetscToken *);

 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 *);

 34: PETSC_EXTERN PetscErrorCode PetscStrcat(char[], const char[]);
 35: PETSC_EXTERN PetscErrorCode PetscStrcpy(char[], const char[]);

 37: #define PetscAssertPointer_Private(ptr, arg) PetscAssert((ptr), PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Null Pointer: Parameter '" PetscStringize(ptr) "' # " PetscStringize(arg))

 39: /*@C
 40:   PetscStrtolower - Converts a string to lower case

 42:   Not Collective, No Fortran Support

 44:   Input Parameter:
 45: . a - pointer to string

 47:   Level: intermediate

 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: }

 62: /*@C
 63:   PetscStrtoupper - Converts a string to upper case

 65:   Not Collective, No Fortran Support

 67:   Input Parameter:
 68: . a - pointer to string

 70:   Level: intermediate

 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: }

 85: /*@C
 86:   PetscStrlen - Gets the length of a string

 88:   Not Collective, No Fortran Support

 90:   Input Parameter:
 91: . s - pointer to string

 93:   Output Parameter:
 94: . len - length in bytes

 96:   Level: intermediate

 98:   Note:
 99:   This routine is analogous to `strlen()`. `NULL` string returns a length of zero.

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: }

119: /*@C
120:   PetscStrallocpy - Allocates space to hold a copy of a string then copies the string into the new space

122:   Not Collective, No Fortran Support

124:   Input Parameter:
125: . s - pointer to string

127:   Output Parameter:
128: . t - the copied string

130:   Level: intermediate

132:   Notes:
133:   `NULL` string returns a new `NULL` string.

135:   Use `PetscFree()` to release the data when it is no longer needed.

137:   If `t` has previously been allocated then that memory is lost, you may need to `PetscFree()`
138:   the array before calling this routine.

140: .seealso: `PetscStrArrayallocpy()`, `PetscStrNArrayallocpy()`
141: @*/
142: static inline PetscErrorCode PetscStrallocpy(const char s[], char *t[])
143: {
144:   PetscFunctionBegin;
145:   PetscAssertPointer_Private(t, 2);
146:   *t = PETSC_NULLPTR;
147:   if (s) {
148:     size_t len;
149:     char  *tmp;

151:     PetscAssertPointer_Private(s, 1);
152:     PetscCall(PetscStrlen(s, &len));
153:     PetscCall(PetscMalloc1(len + 1, &tmp));
154: #if PetscHasBuiltin(__builtin_memcpy)
155:     __builtin_memcpy(tmp, s, len);
156: #else
157:     memcpy(tmp, s, len);
158: #endif
159:     tmp[len] = '\0';
160:     *t       = tmp;
161:   }
162:   PetscFunctionReturn(PETSC_SUCCESS);
163: }

165: static inline void PetscStrcmpNoError(const char a[], const char b[], PetscBool *flg)
166: {
167:   if (!a && !b) {
168:     *flg = PETSC_TRUE;
169:   } else if (!a || !b) {
170:     *flg = PETSC_FALSE;
171:   } else {
172: #if PetscHasBuiltin(__builtin_strcmp)
173:     *flg = __builtin_strcmp(a, b) ? PETSC_FALSE : PETSC_TRUE;
174: #else
175:     *flg = strcmp(a, b) ? PETSC_FALSE : PETSC_TRUE;
176: #endif
177:   }
178: }

180: /*@C
181:   PetscStrcmp - Compares two strings

183:   Not Collective, No Fortran Support

185:   Input Parameters:
186: + a - pointer to string first string
187: - b - pointer to second string

189:   Output Parameter:
190: . flg - `PETSC_TRUE` if the two strings are equal

192:   Level: intermediate

194: .seealso: `PetscStrcmpAny()`, `PetscStrgrt()`, `PetscStrncmp()`, `PetscStrcasecmp()`
195: @*/
196: static inline PetscErrorCode PetscStrcmp(const char a[], const char b[], PetscBool *flg)
197: {
198:   PetscFunctionBegin;
199:   PetscAssertPointer_Private(flg, 3);
200:   PetscStrcmpNoError(a, b, flg);
201:   PetscFunctionReturn(PETSC_SUCCESS);
202: }

204: #if defined(__GNUC__) && !defined(__clang__)
205:   #if __GNUC__ >= 8
206:     #define PETSC_SILENCE_WSTRINGOP_TRUNCATION_BEGIN \
207:       do { \
208:         _Pragma("GCC diagnostic push"); \
209:         _Pragma("GCC diagnostic ignored \"-Wstringop-truncation\""); \
210:       } while (0)
211:     #define PETSC_SILENCE_WSTRINGOP_TRUNCATION_END _Pragma("GCC diagnostic pop")
212:   #endif
213: #endif

215: #ifndef PETSC_SILENCE_WSTRINGOP_TRUNCATION_BEGIN
216:   #define PETSC_SILENCE_WSTRINGOP_TRUNCATION_BEGIN (void)0
217:   #define PETSC_SILENCE_WSTRINGOP_TRUNCATION_END   (void)0
218: #endif

220: /*@C
221:   PetscStrncpy - Copies a string up to a certain length

223:   Not Collective

225:   Input Parameters:
226: + t - pointer to string
227: - n - the length to copy

229:   Output Parameter:
230: . s - the copied string

232:   Level: intermediate

234:   Notes:
235:   `NULL` string returns a string starting with zero.

237:   If the string that is being copied is of length `n` or larger, then the entire string is not
238:   copied and the final location of `s` is set to `NULL`. This is different then the behavior of
239:   `strncpy()` which leaves `s` non-terminated if there is not room for the entire string.

241:   Developer Note:
242:   Should this be `PetscStrlcpy()` to reflect its behavior which is like `strlcpy()` not
243:   `strncpy()`?

245: .seealso: `PetscStrlcat()`, `PetscStrallocpy()`
246: @*/
247: static inline PetscErrorCode PetscStrncpy(char s[], const char t[], size_t n)
248: {
249:   PetscFunctionBegin;
250:   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");
251:   if (t) {
252:     PetscAssertPointer_Private(s, 1);
253:     PETSC_SILENCE_WSTRINGOP_TRUNCATION_BEGIN;
254: #if PetscHasBuiltin(__builtin_strncpy)
255:     __builtin_strncpy(s, t, n);
256: #else
257:     strncpy(s, t, n);
258: #endif
259:     PETSC_SILENCE_WSTRINGOP_TRUNCATION_END;
260:     s[n - 1] = '\0';
261:   } else if (s) {
262:     s[0] = '\0';
263:   }
264:   PetscFunctionReturn(PETSC_SUCCESS);
265: }

267: /*@C
268:   PetscStrlcat - Concatenates a string onto a given string, up to a given length

270:   Not Collective, No Fortran Support

272:   Input Parameters:
273: + s - pointer to string to be added to at end
274: . t - string to be added
275: - n - length of the original allocated string

277:   Level: intermediate

279:   Note:
280:   Unlike the system call `strncat()`, the length passed in is the length of the
281:   original allocated space, not the length of the left-over space. This is
282:   similar to the BSD system call `strlcat()`.

284: .seealso: `PetscStrncpy()`
285: @*/
286: static inline PetscErrorCode PetscStrlcat(char s[], const char t[], size_t n)
287: {
288:   size_t len;

290:   PetscFunctionBegin;
291:   if (!t) PetscFunctionReturn(PETSC_SUCCESS);
292:   PetscAssert(n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "String buffer length must be positive");
293:   PetscCall(PetscStrlen(s, &len));
294:   PETSC_SILENCE_WSTRINGOP_TRUNCATION_BEGIN;
295: #if PetscHasBuiltin(__builtin_strncat)
296:   __builtin_strncat(s, t, n - len);
297: #else
298:   strncat(s, t, n - len);
299: #endif
300:   PETSC_SILENCE_WSTRINGOP_TRUNCATION_END;
301:   s[n - 1] = '\0';
302:   PetscFunctionReturn(PETSC_SUCCESS);
303: }

305: #undef PETSC_SILENCE_WSTRINGOP_TRUNCATION_BEGIN
306: #undef PETSC_SILENCE_WSTRINGOP_TRUNCATION_END

308: /*@C
309:   PetscStrncmp - Compares two strings, up to a certain length

311:   Not Collective, No Fortran Support

313:   Input Parameters:
314: + a - pointer to first string
315: . b - pointer to second string
316: - n - length to compare up to

318:   Output Parameter:
319: . t - `PETSC_TRUE` if the two strings are equal, `PETSC_FALSE` otherwise

321:   Level: intermediate

323:   Note:
324:   If `n` is `0`, `t` is set to `PETSC_FALSE`. `a` and/or `b` may be `NULL` in this case.

326: .seealso: `PetscStrgrt()`, `PetscStrcmp()`, `PetscStrcasecmp()`
327: @*/
328: static inline PetscErrorCode PetscStrncmp(const char a[], const char b[], size_t n, PetscBool *t)
329: {
330:   PetscFunctionBegin;
331:   PetscAssertPointer_Private(t, 4);
332:   *t = PETSC_FALSE;
333:   if (n) {
334:     PetscAssertPointer_Private(a, 1);
335:     PetscAssertPointer_Private(b, 2);
336:   }
337: #if PetscHasBuiltin(__builtin_strncmp)
338:   *t = __builtin_strncmp(a, b, n) ? PETSC_FALSE : PETSC_TRUE;
339: #else
340:   *t = strncmp(a, b, n) ? PETSC_FALSE : PETSC_TRUE;
341: #endif
342:   PetscFunctionReturn(PETSC_SUCCESS);
343: }

345: /*@C
346:   PetscStrrstr - Locates last occurrence of string in another string

348:   Not Collective, No Fortran Support

350:   Input Parameters:
351: + a - pointer to string
352: - b - string to find

354:   Output Parameter:
355: . tmp - location of occurrence

357:   Level: intermediate

359: .seealso: `PetscStrbeginswithwhich()`, `PetscStrendswith()`, `PetscStrtoupper`,
360:           `PetscStrtolower()`, `PetscStrrchr()`, `PetscStrchr()`, `PetscStrncmp()`, `PetscStrlen()`,
361:           `PetscStrcmp()`
362: @*/
363: static inline PetscErrorCode PetscStrrstr(const char a[], const char b[], char *tmp[])
364: {
365:   const char *ltmp = PETSC_NULLPTR;

367:   PetscFunctionBegin;
368:   PetscAssertPointer_Private(a, 1);
369:   PetscAssertPointer_Private(b, 2);
370:   PetscAssertPointer_Private(tmp, 3);
371:   while (a) {
372: #if PetscHasBuiltin(__builtin_strstr)
373:     a = (char *)__builtin_strstr(a, b);
374: #else
375:     a = (char *)strstr(a, b);
376: #endif
377:     if (a) ltmp = a++;
378:   }
379:   *tmp = (char *)ltmp;
380:   PetscFunctionReturn(PETSC_SUCCESS);
381: }

383: /*@C
384:   PetscStrstr - Locates first occurrence of string in another string

386:   Not Collective, No Fortran Support

388:   Input Parameters:
389: + haystack - string to search
390: - needle   - string to find

392:   Output Parameter:
393: . tmp - location of `needle` within `haystack`, `NULL` if `needle` is not found

395:   Level: intermediate

397: .seealso: `PetscStrbeginswithwhich()`, `PetscStrendswith()`, `PetscStrtoupper`,
398:           `PetscStrtolower()`, `PetscStrrchr()`, `PetscStrchr()`, `PetscStrncmp()`, `PetscStrlen()`,
399:           `PetscStrcmp()`
400: @*/
401: static inline PetscErrorCode PetscStrstr(const char haystack[], const char needle[], char *tmp[])
402: {
403:   PetscFunctionBegin;
404:   PetscAssertPointer_Private(haystack, 1);
405:   PetscAssertPointer_Private(needle, 2);
406:   PetscAssertPointer_Private(tmp, 3);
407: #if PetscHasBuiltin(__builtin_strstr)
408:   *tmp = (char *)__builtin_strstr(haystack, needle);
409: #else
410:   *tmp = (char *)strstr(haystack, needle);
411: #endif
412:   PetscFunctionReturn(PETSC_SUCCESS);
413: }

415: /*@C
416:   PetscStrgrt - If first string is greater than the second

418:   Not Collective, No Fortran Support

420:   Input Parameters:
421: + a - pointer to first string
422: - b - pointer to second string

424:   Output Parameter:
425: . flg - `PETSC_TRUE` if `a` is strictly greater than `b`, `PETSC_FALSE` otherwise

427:   Level: intermediate

429:   Note:
430:   `NULL` arguments are OK, a `NULL` string is considered smaller than all others. If both `a`
431:   and `b` are `NULL` then `t` is set to `PETSC_FALSE`.

433: .seealso: `PetscStrcmp()`, `PetscStrncmp()`, `PetscStrcasecmp()`
434: @*/
435: static inline PetscErrorCode PetscStrgrt(const char a[], const char b[], PetscBool *t)
436: {
437:   PetscFunctionBegin;
438:   PetscAssertPointer_Private(t, 3);
439:   if (!a && !b) {
440:     *t = PETSC_FALSE;
441:   } else if (a && !b) {
442:     *t = PETSC_TRUE;
443:   } else if (!a && b) {
444:     *t = PETSC_FALSE;
445:   } else {
446: #if PetscHasBuiltin(__builtin_strcmp)
447:     *t = __builtin_strcmp(a, b) > 0 ? PETSC_TRUE : PETSC_FALSE;
448: #else
449:     *t = strcmp(a, b) > 0 ? PETSC_TRUE : PETSC_FALSE;
450: #endif
451:   }
452:   PetscFunctionReturn(PETSC_SUCCESS);
453: }

455: /*@C
456:   PetscStrchr - Locates first occurrence of a character in a string

458:   Not Collective, No Fortran Support

460:   Input Parameters:
461: + a - pointer to string
462: - b - character

464:   Output Parameter:
465: . c - location of occurrence, `NULL` if not found

467:   Level: intermediate

469: .seealso: `PetscStrrchr()`, `PetscTokenCreate()`, `PetscStrendswith()`, `PetscStrbeginsswith()`
470: @*/
471: static inline PetscErrorCode PetscStrchr(const char a[], char b, char *c[])
472: {
473:   PetscFunctionBegin;
474:   PetscAssertPointer_Private(a, 1);
475:   PetscAssertPointer_Private(c, 3);
476: #if PetscHasBuiltin(__builtin_strchr)
477:   *c = (char *)__builtin_strchr(a, b);
478: #else
479:   *c = (char *)strchr(a, b);
480: #endif
481:   PetscFunctionReturn(PETSC_SUCCESS);
482: }

484: /*@C
485:   PetscStrrchr - Locates one location past the last occurrence of a character in a string, if
486:   the character is not found then returns entire string

488:   Not Collective, No Fortran Support

490:   Input Parameters:
491: + a - pointer to string
492: - b - character

494:   Output Parameter:
495: . c - one past location of `b` in `a`, or `a` if `b` was not found

497:   Level: intermediate

499: .seealso: `PetscStrchr()`, `PetscTokenCreate()`, `PetscStrendswith()`, `PetscStrbeginsswith()`
500: @*/
501: static inline PetscErrorCode PetscStrrchr(const char a[], char b, char *c[])
502: {
503:   PetscFunctionBegin;
504:   PetscAssertPointer_Private(a, 1);
505:   PetscAssertPointer_Private(c, 3);
506: #if PetscHasBuiltin(__builtin_strrchr)
507:   *c = (char *)__builtin_strrchr(a, b);
508: #else
509:   *c = (char *)strrchr(a, b);
510: #endif
511:   if (!*c) *c = (char *)a;
512:   else *c = *c + 1;
513:   PetscFunctionReturn(PETSC_SUCCESS);
514: }

516: /*@C
517:   PetscStrendswith - Determines if a string ends with a certain string

519:   Not Collective, No Fortran Support

521:   Input Parameters:
522: + a - string to search
523: - b - string to end with

525:   Output Parameter:
526: . flg - `PETSC_TRUE` if `a` ends with `b`, `PETSC_FALSE` otherwise

528:   Level: intermediate

530:   Note:
531:   Both `a` and `b` may be `NULL` (in which case `flg` is set to `PETSC_FALSE`) bot not either.

533: .seealso: `PetscStrendswithwhich()`, `PetscStrbeginswith()`, `PetscStrtoupper`,
534:           `PetscStrtolower()`, `PetscStrrchr()`, `PetscStrchr()`, `PetscStrncmp()`, `PetscStrlen()`,
535:           `PetscStrcmp()`
536: @*/
537: static inline PetscErrorCode PetscStrendswith(const char a[], const char b[], PetscBool *flg)
538: {
539:   size_t na = 0, nb = 0;

541:   PetscFunctionBegin;
542:   PetscAssertPointer_Private(flg, 3);
543:   // do this here to silence stupid "may be used uninitialized"" warnings
544:   *flg = PETSC_FALSE;
545:   PetscCall(PetscStrlen(a, &na));
546:   PetscCall(PetscStrlen(b, &nb));
547:   if (na >= nb) {
548: #if PetscHasBuiltin(__builtin_memcmp)
549:     *flg = __builtin_memcmp(b, a + (na - nb), nb) == 0 ? PETSC_TRUE : PETSC_FALSE;
550: #else
551:     *flg = memcmp(b, a + (na - nb), nb) == 0 ? PETSC_TRUE : PETSC_FALSE;
552: #endif
553:   }
554:   PetscFunctionReturn(PETSC_SUCCESS);
555: }

557: /*@C
558:   PetscStrbeginswith - Determines if a string begins with a certain string

560:   Not Collective, No Fortran Support

562:   Input Parameters:
563: + a - string to search
564: - b - string to begin with

566:   Output Parameter:
567: . flg - `PETSC_TRUE` if `a` begins with `b`, `PETSC_FALSE` otherwise

569:   Level: intermediate

571:   Notes:
572:   Both `a` and `b` may be `NULL` (in which case `flg` is set to `PETSC_FALSE`) but not
573:   either.

575:   `a` and `b` may point to the same string.

577: .seealso: `PetscStrendswithwhich()`, `PetscStrendswith()`, `PetscStrtoupper`,
578:           `PetscStrtolower()`, `PetscStrrchr()`, `PetscStrchr()`, `PetscStrncmp()`, `PetscStrlen()`,
579:           `PetscStrcmp()`
580: @*/
581: static inline PetscErrorCode PetscStrbeginswith(const char a[], const char b[], PetscBool *flg)
582: {
583:   size_t len = 0;

585:   PetscFunctionBegin;
586:   PetscAssertPointer_Private(flg, 3);
587:   // do this here to silence stupid "may be used uninitialized"" warnings
588:   *flg = PETSC_FALSE;
589:   PetscCall(PetscStrlen(b, &len));
590:   PetscCall(PetscStrncmp(a, b, len, flg));
591:   PetscFunctionReturn(PETSC_SUCCESS);
592: }

594: #undef PetscAssertPointer_Private

596: /*@C
597:    PetscMemmove - Copies `n` bytes, beginning at location `b`, to the space
598:    beginning at location `a`. Copying  between regions that overlap will
599:    take place correctly. Use `PetscMemcpy()` if the locations do not overlap

601:    Not Collective, No Fortran Support

603:    Input Parameters:
604: +  b - pointer to initial memory space
605: .  a - pointer to copy space
606: -  n - length (in bytes) of space to copy

608:    Level: intermediate

610:    Notes:
611:    `PetscArraymove()` is preferred

613:    This routine is analogous to `memmove()`.

615: .seealso: `PetscMemcpy()`, `PetscMemcmp()`, `PetscArrayzero()`, `PetscMemzero()`, `PetscArraycmp()`, `PetscArraycpy()`, `PetscStrallocpy()`,
616:           `PetscArraymove()`
617: @*/
618: static inline PetscErrorCode PetscMemmove(void *a, const void *b, size_t n)
619: {
620:   PetscFunctionBegin;
621:   if (PetscUnlikely((n == 0) || (a == b))) PetscFunctionReturn(PETSC_SUCCESS);
622:   PetscAssert(a, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Trying to copy %zu bytes to null pointer (Argument #1)", n);
623:   PetscAssert(b, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Trying to copy %zu bytes from a null pointer (Argument #2)", n);
624: #if PetscDefined(HAVE_MEMMOVE)
625:   memmove((char *)a, (const char *)b, n);
626: #else
627:   if (a < b) {
628:     if ((char *)a <= (char *)b - n) {
629:       memcpy(a, b, n);
630:     } else {
631:       const size_t ptr_diff = (size_t)((char *)b - (char *)a);

633:       memcpy(a, b, ptr_diff);
634:       PetscCall(PetscMemmove((void *)b, (char *)b + ptr_diff, n - ptr_diff));
635:     }
636:   } else {
637:     if ((char *)b <= (char *)a - n) {
638:       memcpy(a, b, n);
639:     } else {
640:       const size_t ptr_diff = (size_t)((char *)a - (char *)b);

642:       memcpy((void *)((char *)b + n), (char *)b + (n - ptr_diff), ptr_diff);
643:       PetscCall(PetscMemmove(a, b, n - ptr_diff));
644:     }
645:   }
646: #endif
647:   PetscFunctionReturn(PETSC_SUCCESS);
648: }

650: /*@C
651:    PetscMemcpy - Copies `n` bytes, beginning at location `b`, to the space
652:    beginning at location `a`. The two memory regions CANNOT overlap, use
653:    `PetscMemmove()` in that case.

655:    Not Collective, No Fortran Support

657:    Input Parameters:
658: +  b - pointer to initial memory space
659: -  n - length (in bytes) of space to copy

661:    Output Parameter:
662: .  a - pointer to copy space

664:    Level: intermediate

666:    Compile Options\:
667: +  `PETSC_PREFER_DCOPY_FOR_MEMCPY` - cause the BLAS `dcopy()` routine to be used for memory copies on double precision values.
668: .  `PETSC_PREFER_COPY_FOR_MEMCPY` - cause C code to be used for memory copies on double precision values.
669: -  `PETSC_PREFER_FORTRAN_FORMEMCPY` - cause Fortran code to be used for memory copies on double precision values.

671:    Notes:
672:    Prefer `PetscArraycpy()`

674:    This routine is analogous to `memcpy()`.

676: .seealso: `PetscMemzero()`, `PetscMemcmp()`, `PetscArrayzero()`, `PetscArraycmp()`, `PetscArraycpy()`, `PetscMemmove()`, `PetscStrallocpy()`
677: @*/
678: static inline PetscErrorCode PetscMemcpy(void *a, const void *b, size_t n)
679: {
680:   const PETSC_UINTPTR_T al = (PETSC_UINTPTR_T)a;
681:   const PETSC_UINTPTR_T bl = (PETSC_UINTPTR_T)b;

683:   PetscFunctionBegin;
684:   if (PetscUnlikely((n == 0) || (a == b))) PetscFunctionReturn(PETSC_SUCCESS);
685:   PetscAssert(a, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Trying to copy %zu bytes to a null pointer (Argument #1)", n);
686:   PetscAssert(b, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Trying to copy %zu bytes from a null pointer (Argument #2)", n);
687:   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);
688:   if (PetscDefined(PREFER_DCOPY_FOR_MEMCPY) || PetscDefined(PREFER_COPY_FOR_MEMCPY) || PetscDefined(PREFER_FORTRAN_FORMEMCPY)) {
689:     if (!(al % sizeof(PetscScalar)) && !(n % sizeof(PetscScalar))) {
690:       const size_t       scalar_len = n / sizeof(PetscScalar);
691:       const PetscScalar *x          = (PetscScalar *)b;
692:       PetscScalar       *y          = (PetscScalar *)a;

694: #if PetscDefined(PREFER_DCOPY_FOR_MEMCPY)
695:       {
696:         const PetscBLASInt one = 1;
697:         PetscBLASInt       blen;

699:         PetscCall(PetscBLASIntCast(scalar_len, &blen));
700:         PetscCallBLAS("BLAScopy", BLAScopy_(&blen, x, &one, y, &one));
701:       }
702: #elif PetscDefined(PREFER_FORTRAN_FORMEMCPY)
703:       fortrancopy_(&scalar_len, x, y);
704: #else
705:       for (size_t i = 0; i < scalar_len; i++) y[i] = x[i];
706: #endif
707:       PetscFunctionReturn(PETSC_SUCCESS);
708:     }
709:   }
710:   memcpy(a, b, n);
711:   PetscFunctionReturn(PETSC_SUCCESS);
712: }

714: /*@C
715:    PetscMemzero - Zeros the specified memory.

717:    Not Collective, No Fortran Support

719:    Input Parameters:
720: +  a - pointer to beginning memory location
721: -  n - length (in bytes) of memory to initialize

723:    Level: intermediate

725:    Compile Option:
726:    `PETSC_PREFER_BZERO` - on certain machines (the IBM RS6000) the bzero() routine happens
727:    to be faster than the memset() routine. This flag causes the bzero() routine to be used.

729:    Note:
730:    Prefer `PetscArrayzero()`

732: .seealso: `PetscMemcpy()`, `PetscMemcmp()`, `PetscArrayzero()`, `PetscArraycmp()`, `PetscArraycpy()`, `PetscMemmove()`, `PetscStrallocpy()`
733: @*/
734: static inline PetscErrorCode PetscMemzero(void *a, size_t n)
735: {
736:   PetscFunctionBegin;
737:   if (PetscUnlikely(n == 0)) PetscFunctionReturn(PETSC_SUCCESS);
738:   PetscAssert(a, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Trying to zero %zu bytes at a null pointer", n);
739:   if (PetscDefined(PREFER_ZERO_FOR_MEMZERO) || PetscDefined(PREFER_FORTRAN_FOR_MEMZERO)) {
740:     if (!(((PETSC_UINTPTR_T)a) % sizeof(PetscScalar)) && !(n % sizeof(PetscScalar))) {
741:       const size_t scalar_len = n / sizeof(PetscScalar);
742:       PetscScalar *x          = (PetscScalar *)a;

744:       if (PetscDefined(PREFER_ZERO_FOR_MEMZERO)) {
745:         for (size_t i = 0; i < scalar_len; ++i) x[i] = 0;
746:       } else {
747: #if PetscDefined(PREFER_FORTRAN_FOR_MEMZERO)
748:         fortranzero_(&scalar_len, x);
749: #else
750:         (void)scalar_len;
751:         (void)x;
752: #endif
753:       }
754:       PetscFunctionReturn(PETSC_SUCCESS);
755:     }
756:   }
757: #if PetscDefined(PREFER_BZERO)
758:   bzero(a, n);
759: #else
760:   memset(a, 0, n);
761: #endif
762:   PetscFunctionReturn(PETSC_SUCCESS);
763: }

765: /*MC
766:    PetscArraycmp - Compares two arrays in memory.

768:    Synopsis:
769: #include <petscstring.h>
770:     PetscErrorCode PetscArraycmp(const anytype *str1, const anytype *str2, size_t cnt, PetscBool *e)

772:    Not Collective

774:    Input Parameters:
775: +  str1 - First array
776: .  str2 - Second array
777: -  cnt  - Count of the array, not in bytes, but number of entries in the arrays

779:    Output Parameter:
780: .   e - `PETSC_TRUE` if equal else `PETSC_FALSE`.

782:    Level: intermediate

784:    Notes:
785:    This routine is a preferred replacement to `PetscMemcmp()`

787:    The arrays must be of the same type

789: .seealso: `PetscMemcpy()`, `PetscMemcmp()`, `PetscArrayzero()`, `PetscMemzero()`, `PetscArraycpy()`, `PetscMemmove()`, `PetscStrallocpy()`,
790:           `PetscArraymove()`
791: M*/
792: #define PetscArraycmp(str1, str2, cnt, e) ((sizeof(*(str1)) == sizeof(*(str2))) ? PetscMemcmp((str1), (str2), (size_t)(cnt) * sizeof(*(str1)), (e)) : PETSC_ERR_ARG_SIZ)

794: /*MC
795:    PetscArraymove - Copies from one array in memory to another, the arrays may overlap. Use `PetscArraycpy()` when the arrays
796:                     do not overlap

798:    Synopsis:
799: #include <petscstring.h>
800:     PetscErrorCode PetscArraymove(anytype *str1, const anytype *str2, size_t cnt)

802:    Not Collective

804:    Input Parameters:
805: +  str1 - First array
806: .  str2 - Second array
807: -  cnt  - Count of the array, not in bytes, but number of entries in the arrays

809:    Level: intermediate

811:    Notes:
812:    This routine is a preferred replacement to `PetscMemmove()`

814:    The arrays must be of the same type

816: .seealso: `PetscMemcpy()`, `PetscMemcmp()`, `PetscArrayzero()`, `PetscMemzero()`, `PetscArraycpy()`, `PetscMemmove()`, `PetscArraycmp()`, `PetscStrallocpy()`
817: M*/
818: #define PetscArraymove(str1, str2, cnt) ((sizeof(*(str1)) == sizeof(*(str2))) ? PetscMemmove((str1), (str2), (size_t)(cnt) * sizeof(*(str1))) : PETSC_ERR_ARG_SIZ)

820: /*MC
821:    PetscArraycpy - Copies from one array in memory to another

823:    Synopsis:
824: #include <petscstring.h>
825:     PetscErrorCode PetscArraycpy(anytype *str1, const anytype *str2, size_t cnt)

827:    Not Collective

829:    Input Parameters:
830: +  str1 - First array (destination)
831: .  str2 - Second array (source)
832: -  cnt  - Count of the array, not in bytes, but number of entries in the arrays

834:    Level: intermediate

836:    Notes:
837:    This routine is a preferred replacement to `PetscMemcpy()`

839:    The arrays must be of the same type

841: .seealso: `PetscMemcpy()`, `PetscMemcmp()`, `PetscArrayzero()`, `PetscMemzero()`, `PetscArraymove()`, `PetscMemmove()`, `PetscArraycmp()`, `PetscStrallocpy()`
842: M*/
843: #define PetscArraycpy(str1, str2, cnt) ((sizeof(*(str1)) == sizeof(*(str2))) ? PetscMemcpy((str1), (str2), (size_t)(cnt) * sizeof(*(str1))) : PETSC_ERR_ARG_SIZ)

845: /*MC
846:    PetscArrayzero - Zeros an array in memory.

848:    Synopsis:
849: #include <petscstring.h>
850:     PetscErrorCode PetscArrayzero(anytype *str1, size_t cnt)

852:    Not Collective

854:    Input Parameters:
855: +  str1 - array
856: -  cnt  - Count of the array, not in bytes, but number of entries in the array

858:    Level: intermediate

860:    Note:
861:    This routine is a preferred replacement to `PetscMemzero()`

863: .seealso: `PetscMemcpy()`, `PetscMemcmp()`, `PetscMemzero()`, `PetscArraycmp()`, `PetscArraycpy()`, `PetscMemmove()`, `PetscStrallocpy()`, `PetscArraymove()`
864: M*/
865: #define PetscArrayzero(str1, cnt) PetscMemzero((str1), ((size_t)(cnt)) * sizeof(*(str1)))