Actual source code: petscstring.h

  1: #ifndef PETSC_STRING_H
  2: #define PETSC_STRING_H

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

  9: /* SUBMANSEC = Sys */

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

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

 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 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 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 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:   Notes:
 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 in 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:   If `t` has previously been allocated then that memory is lost, you may need to `PetscFree()`
136:   the array before calling this routine.

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;

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

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

178: /*@C
179:   PetscStrcmp - Compares two strings,

181:   Not Collective, No Fortran Support

183:   Input Parameters:
184: + a - pointer to string first string
185: - b - pointer to second string

187:   Output Parameter:
188: . flg - `PETSC_TRUE` if the two strings are equal

190:   Level: intermediate

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

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

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

218: /*@C
219:   PetscStrncpy - Copies a string up to a certain length

221:   Not Collective

223:   Input Parameters:
224: + t - pointer to string
225: - n - the length to copy

227:   Output Parameter:
228: . s - the copied string

230:   Level: intermediate

232:   Notes:
233:   `NULL` string returns a string starting with zero.

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.

239:   Developers Notes:
240:   Should this be `PetscStrlcpy()` to reflect its behavior which is like `strlcpy()` not
241:   `strncpy()`?

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

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

268:   Not Collective, No Fortran Support

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

275:   Level: intermediate

277:   Notes:
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()`.

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

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

303: #undef PETSC_SILENCE_WSTRINGOP_TRUNCATION_BEGIN
304: #undef PETSC_SILENCE_WSTRINGOP_TRUNCATION_END

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

309:   Not Collective, No Fortran Support

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

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

319:   Level: intermediate

321:   Notes:
322:   If `n` is `0`, `t` is set to `PETSC_FALSE`. `a` and/or `b` may be `NULL` in this case.

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

343: /*@C
344:   PetscStrrstr - Locates last occurrence of string in another string

346:   Not Collective, No Fortran Support

348:   Input Parameters:
349: + a - pointer to string
350: - b - string to find

352:   Output Parameter:
353: . tmp - location of occurrence

355:   Level: intermediate

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;

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

381: /*@C
382:   PetscStrstr - Locates first occurrence of string in another string

384:   Not Collective, No Fortran Support

386:   Input Parameters:
387: + haystack - string to search
388: - needle   - string to find

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

393:   Level: intermediate

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

413: /*@C
414:   PetscStrgrt - If first string is greater than the second

416:   Not Collective, No Fortran Support

418:   Input Parameters:
419: + a - pointer to first string
420: - b - pointer to second string

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

425:   Level: intermediate

427:   Notes:
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`.

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

453: /*@C
454:   PetscStrchr - Locates first occurrence of a character in a string

456:   Not Collective, No Fortran Support

458:   Input Parameters:
459: + a - pointer to string
460: - b - character

462:   Output Parameter:
463: . c - location of occurrence, `NULL` if not found

465:   Level: intermediate

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

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

486:   Not Collective, No Fortran Support

488:   Input Parameters:
489: + a - pointer to string
490: - b - character

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

495:   Level: intermediate

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

514: /*@C
515:   PetscStrendswith - Determines if a string ends with a certain string

517:   Not Collective, No Fortran Support

519:   Input Parameters:
520: + a - string to search
521: - b - string to end with

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

526:   Level: intermediate

528:   Notes:
529:   Both `a` and `b` may be `NULL` (in which case `flg` is set to `PETSC_FALSE`) bot not either.

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

539:   PetscFunctionBegin;
540:   PetscAssertPointer_Private(flg, 3);
541:   // do this here to silence stupid "may be used uninitialized"" warnings
542:   *flg = PETSC_FALSE;
543:   PetscCall(PetscStrlen(a, &na));
544:   PetscCall(PetscStrlen(b, &nb));
545:   if (na >= nb) {
546: #if PetscHasBuiltin(__builtin_memcmp)
547:     *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:   PetscFunctionReturn(PETSC_SUCCESS);
553: }

555: /*@C
556:   PetscStrbeginswith - Determines if a string begins with a certain string

558:   Not Collective, No Fortran Support

560:   Input Parameters:
561: + a - string to search
562: - b - string to begin with

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

567:   Level: intermediate

569:   Notes:
570:   Both `a` and `b` may be `NULL` (in which case `flg` is set to `PETSC_FALSE`) but not
571:   either. Both `a` and `b` may point to the same string.

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

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

590: #undef PetscAssertPointer_Private

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

597:    Not Collective

599:    Input Parameters:
600: +  b - pointer to initial memory space
601: .  a - pointer to copy space
602: -  n - length (in bytes) of space to copy

604:    Level: intermediate

606:    Notes:
607:    `PetscArraymove()` is preferred

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

611:    Developers Notes:
612:    This is inlined for performance

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

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

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

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

654:    Not Collective

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

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

663:    Level: intermediate

665:    Compile Option:
666:     `PETSC_PREFER_DCOPY_FOR_MEMCPY` will cause the BLAS dcopy() routine to be used
667:                                   for memory copies on double precision values.
668:     `PETSC_PREFER_COPY_FOR_MEMCPY` will cause C code to be used
669:                                   for memory copies on double precision values.
670:     `PETSC_PREFER_FORTRAN_FORMEMCPY` will cause Fortran code to be used
671:                                   for memory copies on double precision values.

673:    Notes:
674:    Prefer `PetscArraycpy()`

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

678:    Developer Notes:
679:    This is inlined for fastest performance

681: .seealso: `PetscMemzero()`, `PetscMemcmp()`, `PetscArrayzero()`, `PetscArraycmp()`, `PetscArraycpy()`, `PetscMemmove()`, `PetscStrallocpy()`
682: @*/
683: static inline PetscErrorCode PetscMemcpy(void *a, const void *b, size_t n)
684: {
685:   const PETSC_UINTPTR_T al = (PETSC_UINTPTR_T)a;
686:   const PETSC_UINTPTR_T bl = (PETSC_UINTPTR_T)b;

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

699: #if PetscDefined(PREFER_DCOPY_FOR_MEMCPY)
700:       {
701:         const PetscBLASInt one = 1;
702:         PetscBLASInt       blen;

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

719: /*@C
720:    PetscMemzero - Zeros the specified memory.

722:    Not Collective

724:    Input Parameters:
725: +  a - pointer to beginning memory location
726: -  n - length (in bytes) of memory to initialize

728:    Level: intermediate

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

734:    Notes:
735:    Prefer `PetscArrayzero()`

737:    Developer Notes:
738:    This is inlined for fastest performance

740: .seealso: `PetscMemcpy()`, `PetscMemcmp()`, `PetscArrayzero()`, `PetscArraycmp()`, `PetscArraycpy()`, `PetscMemmove()`, `PetscStrallocpy()`
741: @*/
742: static inline PetscErrorCode PetscMemzero(void *a, size_t n)
743: {
744:   PetscFunctionBegin;
745:   if (PetscUnlikely(n == 0)) PetscFunctionReturn(PETSC_SUCCESS);
746:   PetscAssert(a, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Trying to zero %zu bytes at a null pointer", n);
747:   if (PetscDefined(PREFER_ZERO_FOR_MEMZERO) || PetscDefined(PREFER_FORTRAN_FOR_MEMZERO)) {
748:     if (!(((PETSC_UINTPTR_T)a) % sizeof(PetscScalar)) && !(n % sizeof(PetscScalar))) {
749:       const size_t scalar_len = n / sizeof(PetscScalar);
750:       PetscScalar *x          = (PetscScalar *)a;

752:       if (PetscDefined(PREFER_ZERO_FOR_MEMZERO)) {
753:         for (size_t i = 0; i < scalar_len; ++i) x[i] = 0;
754:       } else {
755: #if PetscDefined(PREFER_FORTRAN_FOR_MEMZERO)
756:         fortranzero_(&scalar_len, x);
757: #else
758:         (void)scalar_len;
759:         (void)x;
760: #endif
761:       }
762:       PetscFunctionReturn(PETSC_SUCCESS);
763:     }
764:   }
765: #if PetscDefined(PREFER_BZERO)
766:   bzero(a, n);
767: #else
768:   memset(a, 0, n);
769: #endif
770:   PetscFunctionReturn(PETSC_SUCCESS);
771: }

773: /*MC
774:    PetscArraycmp - Compares two arrays in memory.

776:    Synopsis:
777: #include <petscstring.h>
778:     PetscErrorCode PetscArraycmp(const anytype *str1,const anytype *str2,size_t cnt,PetscBool *e)

780:    Not Collective

782:    Input Parameters:
783: +  str1 - First array
784: .  str2 - Second array
785: -  cnt  - Count of the array, not in bytes, but number of entries in the arrays

787:    Output Parameter:
788: .   e - `PETSC_TRUE` if equal else `PETSC_FALSE`.

790:    Level: intermediate

792:    Notes:
793:    This routine is a preferred replacement to `PetscMemcmp()`

795:    The arrays must be of the same type

797: .seealso: `PetscMemcpy()`, `PetscMemcmp()`, `PetscArrayzero()`, `PetscMemzero()`, `PetscArraycpy()`, `PetscMemmove()`, `PetscStrallocpy()`,
798:           `PetscArraymove()`
799: M*/
800: #define PetscArraycmp(str1, str2, cnt, e) ((sizeof(*(str1)) == sizeof(*(str2))) ? PetscMemcmp((str1), (str2), (size_t)(cnt) * sizeof(*(str1)), (e)) : PETSC_ERR_ARG_SIZ)

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

806:    Synopsis:
807: #include <petscstring.h>
808:     PetscErrorCode PetscArraymove(anytype *str1,const anytype *str2,size_t cnt)

810:    Not Collective

812:    Input Parameters:
813: +  str1 - First array
814: .  str2 - Second array
815: -  cnt  - Count of the array, not in bytes, but number of entries in the arrays

817:    Level: intermediate

819:    Notes:
820:    This routine is a preferred replacement to `PetscMemmove()`

822:    The arrays must be of the same type

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

828: /*MC
829:    PetscArraycpy - Copies from one array in memory to another

831:    Synopsis:
832: #include <petscstring.h>
833:     PetscErrorCode PetscArraycpy(anytype *str1,const anytype *str2,size_t cnt)

835:    Not Collective

837:    Input Parameters:
838: +  str1 - First array (destination)
839: .  str2 - Second array (source)
840: -  cnt  - Count of the array, not in bytes, but number of entries in the arrays

842:    Level: intermediate

844:    Notes:
845:    This routine is a preferred replacement to `PetscMemcpy()`

847:    The arrays must be of the same type

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

853: /*MC
854:    PetscArrayzero - Zeros an array in memory.

856:    Synopsis:
857: #include <petscstring.h>
858:     PetscErrorCode PetscArrayzero(anytype *str1,size_t cnt)

860:    Not Collective

862:    Input Parameters:
863: +  str1 - array
864: -  cnt  - Count of the array, not in bytes, but number of entries in the array

866:    Level: intermediate

868:    Notes:
869:    This routine is a preferred replacement to `PetscMemzero()`

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

875: #endif // PETSC_STRING_H