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: #define PetscAssertPointer_Private(ptr, arg) PetscAssert((ptr), PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Null Pointer: Parameter '" PetscStringize(ptr) "' # " PetscStringize(arg))

 36: /*@C
 37:   PetscStrtolower - Converts string to lower case

 39:   Not Collective, No Fortran Support

 41:   Input Parameters:
 42: . a - pointer to string

 44:   Level: intermediate

 46: .seealso: `PetscStrtoupper()`
 47: @*/
 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: }

 59: /*@C
 60:   PetscStrtoupper - Converts string to upper case

 62:   Not Collective, No Fortran Support

 64:   Input Parameters:
 65: . a - pointer to string

 67:   Level: intermediate

 69: .seealso: `PetscStrtolower()`
 70: @*/
 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: }

 82: /*@C
 83:   PetscStrlen - Gets length of a string

 85:   Not Collective, No Fortran Support

 87:   Input Parameters:
 88: . s - pointer to string

 90:   Output Parameter:
 91: . len - length in bytes

 93:   Level: intermediate

 95:   Notes:
 96:   This routine is analogous to `strlen()`. `NULL` string returns a length of zero.

 98: .seealso: `PetscStrallocpy()`
 99: @*/
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: }

116: /*@C
117:   PetscStrcpy - Copies a string

119:   Not Collective, No Fortran Support

121:   Input Parameters:
122: . t - pointer to string

124:   Output Parameter:
125: . s - the copied string

127:   Level: intermediate

129:   Notes:
130:   `NULL` strings returns a string starting with zero. It is recommended you use
131:   `PetscStrncpy()` (equivelently `PetscArraycpy()` or `PetscMemcpy()`) instead of this routine.

133: .seealso: `PetscStrncpy()`, `PetscStrcat()`, `PetscStrlcat()`, `PetscStrallocpy()`,
134:           `PetscArrycpy()`, `PetscMemcpy()`
135: @*/
136: static inline PetscErrorCode PetscStrcpy(char s[], const char t[])
137: {
138:   PetscFunctionBegin;
139:   if (t) {
140:     PetscAssertPointer_Private(s, 1);
141:     PetscAssertPointer_Private(t, 2);
142: #if PetscHasBuiltin(__builtin_strcpy)
143:     __builtin_strcpy(s, t);
144: #else
145:     strcpy(s, t);
146: #endif
147:   } else if (s) {
148:     s[0] = '\0';
149:   }
150:   PetscFunctionReturn(PETSC_SUCCESS);
151: }

153: /*@C
154:   PetscStrallocpy - Allocates space to hold a copy of a string then copies the string in the new space

156:   Not Collective, No Fortran Support

158:   Input Parameters:
159: . s - pointer to string

161:   Output Parameter:
162: . t - the copied string

164:   Level: intermediate

166:   Notes:
167:   `NULL` string returns a new `NULL` string.

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

172: .seealso: `PetscStrArrayallocpy()`, `PetscStrcpy()`, `PetscStrNArrayallocpy()`
173: @*/
174: static inline PetscErrorCode PetscStrallocpy(const char s[], char *t[])
175: {
176:   PetscFunctionBegin;
177:   PetscAssertPointer_Private(t, 2);
178:   *t = PETSC_NULLPTR;
179:   if (s) {
180:     size_t len;
181:     char  *tmp;

183:     PetscAssertPointer_Private(s, 1);
184:     PetscCall(PetscStrlen(s, &len));
185:     PetscCall(PetscMalloc1(len + 1, &tmp));
186: #if PetscHasBuiltin(__builtin_memcpy)
187:     __builtin_memcpy(tmp, s, len);
188: #else
189:     memcpy(tmp, s, len);
190: #endif
191:     tmp[len] = '\0';
192:     *t       = tmp;
193:   }
194:   PetscFunctionReturn(PETSC_SUCCESS);
195: }

197: static inline void PetscStrcmpNoError(const char a[], const char b[], PetscBool *flg)
198: {
199:   if (!a && !b) {
200:     *flg = PETSC_TRUE;
201:   } else if (!a || !b) {
202:     *flg = PETSC_FALSE;
203:   } else {
204: #if PetscHasBuiltin(__builtin_strcmp)
205:     *flg = __builtin_strcmp(a, b) ? PETSC_FALSE : PETSC_TRUE;
206: #else
207:     *flg = strcmp(a, b) ? PETSC_FALSE : PETSC_TRUE;
208: #endif
209:   }
210: }

212: /*@C
213:   PetscStrcmp - Compares two strings,

215:   Not Collective, No Fortran Support

217:   Input Parameters:
218: + a - pointer to string first string
219: - b - pointer to second string

221:   Output Parameter:
222: . flg - `PETSC_TRUE` if the two strings are equal

224:   Level: intermediate

226: .seealso: `PetscStrgrt()`, `PetscStrncmp()`, `PetscStrcasecmp()`
227: @*/
228: static inline PetscErrorCode PetscStrcmp(const char a[], const char b[], PetscBool *flg)
229: {
230:   PetscFunctionBegin;
231:   PetscAssertPointer_Private(flg, 3);
232:   PetscStrcmpNoError(a, b, flg);
233:   PetscFunctionReturn(PETSC_SUCCESS);
234: }

236: /*@C
237:   PetscStrncpy - Copies a string up to a certain length

239:   Not Collective

241:   Input Parameters:
242: + t - pointer to string
243: - n - the length to copy

245:   Output Parameter:
246: . s - the copied string

248:   Level: intermediate

250:   Notes:
251:   `NULL` string returns a string starting with zero.

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

257:   Developers Notes:
258:   Should this be `PetscStrlcpy()` to reflect its behavior which is like `strlcpy()` not
259:   `strncpy()`?

261: .seealso: `PetscStrcpy()`, `PetscStrcat()`, `PetscStrlcat()`, `PetscStrallocpy()`
262: @*/
263: static inline PetscErrorCode PetscStrncpy(char s[], const char t[], size_t n)
264: {
265:   PetscFunctionBegin;
266:   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");
267:   if (t) {
268:     PetscAssertPointer_Private(s, 1);
269: #if defined(__GNUC__) && !defined(__clang__)
270:   #if __GNUC__ >= 8
271:     #pragma GCC diagnostic push
272:     #pragma GCC diagnostic ignored "-Wstringop-truncation"
273:   #endif
274: #endif
275: #if PetscHasBuiltin(__builtin_strncpy)
276:     __builtin_strncpy(s, t, n);
277: #else
278:     strncpy(s, t, n);
279: #endif
280: #if defined(__GNUC__) && !defined(__clang__)
281:   #if __GNUC__ >= 8
282:     #pragma GCC diagnostic pop
283:   #endif
284: #endif
285:     s[n - 1] = '\0';
286:   } else if (s) {
287:     s[0] = '\0';
288:   }
289:   PetscFunctionReturn(PETSC_SUCCESS);
290: }

292: /*@C
293:   PetscStrcat - Concatenates a string onto a given string

295:   Not Collective, No Fortran Support

297:   Input Parameters:
298: + s - string to be added to
299: - t - pointer to string to be added to end

301:   Level: intermediate

303:   Notes:
304:   It is recommended you use `PetscStrlcat()` instead of this routine.

306: .seealso: `PetscStrcpy()`, `PetscStrncpy()`, `PetscStrlcat()`
307: @*/
308: static inline PetscErrorCode PetscStrcat(char s[], const char t[])
309: {
310:   PetscFunctionBegin;
311:   if (!t) PetscFunctionReturn(PETSC_SUCCESS);
312:   PetscAssertPointer_Private(s, 1);
313: #if PetscHasBuiltin(__builtin_strcat)
314:   __builtin_strcat(s, t);
315: #else
316:   strcat(s, t);
317: #endif
318:   PetscFunctionReturn(PETSC_SUCCESS);
319: }

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

324:   Not Collective, No Fortran Support

326:   Input Parameters:
327: + s - pointer to string to be added to at end
328: . t - string to be added
329: - n - length of the original allocated string

331:   Level: intermediate

333:   Notes:
334:   Unlike the system call `strncat()`, the length passed in is the length of the
335:   original allocated space, not the length of the left-over space. This is
336:   similar to the BSD system call `strlcat()`.

338: .seealso: `PetscStrcpy()`, `PetscStrncpy()`, `PetscStrcat()`
339: @*/
340: static inline PetscErrorCode PetscStrlcat(char s[], const char t[], size_t n)
341: {
342:   size_t len;

344:   PetscFunctionBegin;
345:   if (!t) PetscFunctionReturn(PETSC_SUCCESS);
346:   PetscAssert(n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "String buffer length must be positive");
347:   PetscCall(PetscStrlen(t, &len));
348: #if PetscHasBuiltin(__builtin_strncat)
349:   __builtin_strncat(s, t, n - len);
350: #else
351:   strncat(s, t, n - len);
352: #endif
353:   s[n - 1] = '\0';
354:   PetscFunctionReturn(PETSC_SUCCESS);
355: }

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

360:   Not Collective, No Fortran Support

362:   Input Parameters:
363: + a - pointer to first string
364: . b - pointer to second string
365: - n - length to compare up to

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

370:   Level: intermediate

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

375: .seealso: `PetscStrgrt()`, `PetscStrcmp()`, `PetscStrcasecmp()`
376: @*/
377: static inline PetscErrorCode PetscStrncmp(const char a[], const char b[], size_t n, PetscBool *t)
378: {
379:   PetscFunctionBegin;
380:   PetscAssertPointer_Private(t, 4);
381:   *t = PETSC_FALSE;
382:   if (n) {
383:     PetscAssertPointer_Private(a, 1);
384:     PetscAssertPointer_Private(b, 2);
385:   }
386: #if PetscHasBuiltin(__builtin_strncmp)
387:   *t = __builtin_strncmp(a, b, n) ? PETSC_FALSE : PETSC_TRUE;
388: #else
389:   *t = strncmp(a, b, n) ? PETSC_FALSE : PETSC_TRUE;
390: #endif
391:   PetscFunctionReturn(PETSC_SUCCESS);
392: }

394: /*@C
395:   PetscStrrstr - Locates last occurrence of string in another string

397:   Not Collective, No Fortran Support

399:   Input Parameters:
400: + a - pointer to string
401: - b - string to find

403:   Output Parameter:
404: . tmp - location of occurrence

406:   Level: intermediate

408: .seealso: `PetscStrbeginswithwhich()`, `PetscStrendswith()`, `PetscStrtoupper`,
409:           `PetscStrtolower()`, `PetscStrrchr()`, `PetscStrchr()`, `PetscStrncmp()`, `PetscStrlen()`,
410:           `PetscStrcmp()`
411: @*/
412: static inline PetscErrorCode PetscStrrstr(const char a[], const char b[], char *tmp[])
413: {
414:   const char *ltmp = PETSC_NULLPTR;

416:   PetscFunctionBegin;
417:   PetscAssertPointer_Private(a, 1);
418:   PetscAssertPointer_Private(b, 2);
419:   PetscAssertPointer_Private(tmp, 3);
420:   while (a) {
421: #if PetscHasBuiltin(__builtin_strstr)
422:     a = (char *)__builtin_strstr(a, b);
423: #else
424:     a = (char *)strstr(a, b);
425: #endif
426:     if (a) ltmp = a++;
427:   }
428:   *tmp = (char *)ltmp;
429:   PetscFunctionReturn(PETSC_SUCCESS);
430: }

432: /*@C
433:   PetscStrstr - Locates first occurrence of string in another string

435:   Not Collective, No Fortran Support

437:   Input Parameters:
438: + haystack - string to search
439: - needle   - string to find

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

444:   Level: intermediate

446: .seealso: `PetscStrbeginswithwhich()`, `PetscStrendswith()`, `PetscStrtoupper`,
447:           `PetscStrtolower()`, `PetscStrrchr()`, `PetscStrchr()`, `PetscStrncmp()`, `PetscStrlen()`,
448:           `PetscStrcmp()`
449: @*/
450: static inline PetscErrorCode PetscStrstr(const char haystack[], const char needle[], char *tmp[])
451: {
452:   PetscFunctionBegin;
453:   PetscAssertPointer_Private(haystack, 1);
454:   PetscAssertPointer_Private(needle, 2);
455:   PetscAssertPointer_Private(tmp, 3);
456: #if PetscHasBuiltin(__builtin_strstr)
457:   *tmp = (char *)__builtin_strstr(haystack, needle);
458: #else
459:   *tmp = (char *)strstr(haystack, needle);
460: #endif
461:   PetscFunctionReturn(PETSC_SUCCESS);
462: }

464: /*@C
465:   PetscStrgrt - If first string is greater than the second

467:   Not Collective, No Fortran Support

469:   Input Parameters:
470: + a - pointer to first string
471: - b - pointer to second string

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

476:   Level: intermediate

478:   Notes:
479:   `NULL` arguments are OK, a `NULL` string is considered smaller than all others. If both `a`
480:   and `b` are `NULL` then `t` is set to `PETSC_FALSE`.

482: .seealso: `PetscStrcmp()`, `PetscStrncmp()`, `PetscStrcasecmp()`
483: @*/
484: static inline PetscErrorCode PetscStrgrt(const char a[], const char b[], PetscBool *t)
485: {
486:   PetscFunctionBegin;
487:   PetscAssertPointer_Private(t, 3);
488:   if (!a && !b) {
489:     *t = PETSC_FALSE;
490:   } else if (a && !b) {
491:     *t = PETSC_TRUE;
492:   } else if (!a && b) {
493:     *t = PETSC_FALSE;
494:   } else {
495: #if PetscHasBuiltin(__builtin_strcmp)
496:     *t = __builtin_strcmp(a, b) > 0 ? PETSC_TRUE : PETSC_FALSE;
497: #else
498:     *t = strcmp(a, b) > 0 ? PETSC_TRUE : PETSC_FALSE;
499: #endif
500:   }
501:   PetscFunctionReturn(PETSC_SUCCESS);
502: }

504: /*@C
505:   PetscStrchr - Locates first occurrence of a character in a string

507:   Not Collective, No Fortran Support

509:   Input Parameters:
510: + a - pointer to string
511: - b - character

513:   Output Parameter:
514: . c - location of occurrence, `NULL` if not found

516:   Level: intermediate

518: .seealso: `PetscStrrchr()`, `PetscTokenCreate()`, `PetscStrendswith()`, `PetscStrbeginsswith()`
519: @*/
520: static inline PetscErrorCode PetscStrchr(const char a[], char b, char *c[])
521: {
522:   PetscFunctionBegin;
523:   PetscAssertPointer_Private(a, 1);
524:   PetscAssertPointer_Private(c, 3);
525: #if PetscHasBuiltin(__builtin_strchr)
526:   *c = (char *)__builtin_strchr(a, b);
527: #else
528:   *c = (char *)strchr(a, b);
529: #endif
530:   PetscFunctionReturn(PETSC_SUCCESS);
531: }

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

537:   Not Collective, No Fortran Support

539:   Input Parameters:
540: + a - pointer to string
541: - b - character

543:   Output Parameter:
544: . tmp - one past location of `b` in `a`, or `a` if `b` was not found

546:   Level: intermediate

548: .seealso: `PetscStrchr()`, `PetscTokenCreate()`, `PetscStrendswith()`, `PetscStrbeginsswith()`
549: @*/
550: static inline PetscErrorCode PetscStrrchr(const char a[], char b, char *tmp[])
551: {
552:   PetscFunctionBegin;
553:   PetscAssertPointer_Private(a, 1);
554:   PetscAssertPointer_Private(tmp, 3);
555: #if PetscHasBuiltin(__builtin_strrchr)
556:   *tmp = (char *)__builtin_strrchr(a, b);
557: #else
558:   *tmp = (char *)strrchr(a, b);
559: #endif
560:   if (!*tmp) {
561:     *tmp = (char *)a;
562:   } else {
563:     *tmp = *tmp + 1;
564:   }
565:   PetscFunctionReturn(PETSC_SUCCESS);
566: }

568: /*@C
569:   PetscStrendswith - Determines if a string ends with a certain string

571:   Not Collective, No Fortran Support

573:   Input Parameters:
574: + a - string to search
575: - b - string to end with

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

580:   Level: intermediate

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

585: .seealso: `PetscStrendswithwhich()`, `PetscStrbeginswith()`, `PetscStrtoupper`,
586:           `PetscStrtolower()`, `PetscStrrchr()`, `PetscStrchr()`, `PetscStrncmp()`, `PetscStrlen()`,
587:           `PetscStrcmp()`
588: @*/
589: static inline PetscErrorCode PetscStrendswith(const char a[], const char b[], PetscBool *flg)
590: {
591:   size_t na = 0, nb = 0;

593:   PetscFunctionBegin;
594:   PetscAssertPointer_Private(flg, 3);
595:   // do this here to silence stupid "may be used uninitialized"" warnings
596:   *flg = PETSC_FALSE;
597:   PetscCall(PetscStrlen(a, &na));
598:   PetscCall(PetscStrlen(b, &nb));
599:   if (na >= nb) {
600: #if PetscHasBuiltin(__builtin_memcmp)
601:     *flg = __builtin_memcmp(b, a + (na - nb), nb) == 0 ? PETSC_TRUE : PETSC_FALSE;
602: #else
603:     *flg = memcmp(b, a + (na - nb), nb) == 0 ? PETSC_TRUE : PETSC_FALSE;
604: #endif
605:   }
606:   PetscFunctionReturn(PETSC_SUCCESS);
607: }

609: /*@C
610:   PetscStrbeginswith - Determines if a string begins with a certain string

612:   Not Collective, No Fortran Support

614:   Input Parameters:
615: + a - string to search
616: - b - string to begin with

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

621:   Level: intermediate

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

627: .seealso: `PetscStrendswithwhich()`, `PetscStrendswith()`, `PetscStrtoupper`,
628:           `PetscStrtolower()`, `PetscStrrchr()`, `PetscStrchr()`, `PetscStrncmp()`, `PetscStrlen()`,
629:           `PetscStrcmp()`
630: @*/
631: static inline PetscErrorCode PetscStrbeginswith(const char a[], const char b[], PetscBool *flg)
632: {
633:   size_t len = 0;

635:   PetscFunctionBegin;
636:   PetscAssertPointer_Private(flg, 3);
637:   // do this here to silence stupid "may be used uninitialized"" warnings
638:   *flg = PETSC_FALSE;
639:   PetscCall(PetscStrlen(b, &len));
640:   PetscCall(PetscStrncmp(a, b, len, flg));
641:   PetscFunctionReturn(PETSC_SUCCESS);
642: }

644: #undef PetscAssertPointer_Private

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

651:    Not Collective

653:    Input Parameters:
654: +  b - pointer to initial memory space
655: .  a - pointer to copy space
656: -  n - length (in bytes) of space to copy

658:    Level: intermediate

660:    Notes:
661:    `PetscArraymove()` is preferred

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

665:    Developers Notes:
666:    This is inlined for performance

668: .seealso: `PetscMemcpy()`, `PetscMemcmp()`, `PetscArrayzero()`, `PetscMemzero()`, `PetscArraycmp()`, `PetscArraycpy()`, `PetscStrallocpy()`,
669:           `PetscArraymove()`
670: @*/
671: static inline PetscErrorCode PetscMemmove(void *a, const void *b, size_t n)
672: {
673:   PetscFunctionBegin;
674:   if (PetscUnlikely((n == 0) || (a == b))) PetscFunctionReturn(PETSC_SUCCESS);
675:   PetscAssert(a, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Trying to copy %zu bytes to null pointer (Argument #1)", n);
676:   PetscAssert(b, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Trying to copy %zu bytes from a null pointer (Argument #2)", n);
677: #if PetscDefined(HAVE_MEMMOVE)
678:   memmove((char *)a, (const char *)b, n);
679: #else
680:   if (a < b) {
681:     if ((char *)a <= (char *)b - n) {
682:       memcpy(a, b, n);
683:     } else {
684:       const size_t ptr_diff = (size_t)((char *)b - (char *)a);

686:       memcpy(a, b, ptr_diff);
687:       PetscCall(PetscMemmove((void *)b, (char *)b + ptr_diff, n - ptr_diff));
688:     }
689:   } else {
690:     if ((char *)b <= (char *)a - n) {
691:       memcpy(a, b, n);
692:     } else {
693:       const size_t ptr_diff = (size_t)((char *)a - (char *)b);

695:       memcpy((void *)((char *)b + n), (char *)b + (n - ptr_diff), ptr_diff);
696:       PetscCall(PetscMemmove(a, b, n - ptr_diff));
697:     }
698:   }
699: #endif
700:   PetscFunctionReturn(PETSC_SUCCESS);
701: }

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

708:    Not Collective

710:    Input Parameters:
711: +  b - pointer to initial memory space
712: -  n - length (in bytes) of space to copy

714:    Output Parameter:
715: .  a - pointer to copy space

717:    Level: intermediate

719:    Compile Option:
720:     `PETSC_PREFER_DCOPY_FOR_MEMCPY` will cause the BLAS dcopy() routine to be used
721:                                   for memory copies on double precision values.
722:     `PETSC_PREFER_COPY_FOR_MEMCPY` will cause C code to be used
723:                                   for memory copies on double precision values.
724:     `PETSC_PREFER_FORTRAN_FORMEMCPY` will cause Fortran code to be used
725:                                   for memory copies on double precision values.

727:    Notes:
728:    Prefer `PetscArraycpy()`

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

732:    Developer Notes:
733:    This is inlined for fastest performance

735: .seealso: `PetscMemzero()`, `PetscMemcmp()`, `PetscArrayzero()`, `PetscArraycmp()`, `PetscArraycpy()`, `PetscMemmove()`, `PetscStrallocpy()`
736: @*/
737: static inline PetscErrorCode PetscMemcpy(void *a, const void *b, size_t n)
738: {
739:   const PETSC_UINTPTR_T al = (PETSC_UINTPTR_T)a;
740:   const PETSC_UINTPTR_T bl = (PETSC_UINTPTR_T)b;

742:   PetscFunctionBegin;
743:   if (PetscUnlikely((n == 0) || (a == b))) PetscFunctionReturn(PETSC_SUCCESS);
744:   PetscAssert(a, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Trying to copy %zu bytes to a null pointer (Argument #1)", n);
745:   PetscAssert(b, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Trying to copy %zu bytes from a null pointer (Argument #2)", n);
746:   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);
747:   if (PetscDefined(PREFER_DCOPY_FOR_MEMCPY) || PetscDefined(PREFER_COPY_FOR_MEMCPY) || PetscDefined(PREFER_FORTRAN_FORMEMCPY)) {
748:     if (!(al % sizeof(PetscScalar)) && !(n % sizeof(PetscScalar))) {
749:       const size_t       scalar_len = n / sizeof(PetscScalar);
750:       const PetscScalar *x          = (PetscScalar *)b;
751:       PetscScalar       *y          = (PetscScalar *)a;

753: #if PetscDefined(PREFER_DCOPY_FOR_MEMCPY)
754:       {
755:         const PetscBLASInt one = 1;
756:         PetscBLASInt       blen;

758:         PetscCall(PetscBLASIntCast(scalar_len, &blen));
759:         PetscCallBLAS("BLAScopy", BLAScopy_(&blen, x, &one, y, &one));
760:       }
761: #elif PetscDefined(PREFER_FORTRAN_FORMEMCPY)
762:       fortrancopy_(&scalar_len, x, y);
763: #else
764:       for (size_t i = 0; i < scalar_len; i++) y[i] = x[i];
765: #endif
766:       PetscFunctionReturn(PETSC_SUCCESS);
767:     }
768:   }
769:   memcpy(a, b, n);
770:   PetscFunctionReturn(PETSC_SUCCESS);
771: }

773: /*@C
774:    PetscMemzero - Zeros the specified memory.

776:    Not Collective

778:    Input Parameters:
779: +  a - pointer to beginning memory location
780: -  n - length (in bytes) of memory to initialize

782:    Level: intermediate

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

788:    Notes:
789:    Prefer `PetscArrayzero()`

791:    Developer Notes:
792:    This is inlined for fastest performance

794: .seealso: `PetscMemcpy()`, `PetscMemcmp()`, `PetscArrayzero()`, `PetscArraycmp()`, `PetscArraycpy()`, `PetscMemmove()`, `PetscStrallocpy()`
795: @*/
796: static inline PetscErrorCode PetscMemzero(void *a, size_t n)
797: {
798:   PetscFunctionBegin;
799:   if (PetscUnlikely(n == 0)) PetscFunctionReturn(PETSC_SUCCESS);
800:   PetscAssert(a, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Trying to zero %zu bytes at a null pointer", n);
801:   if (PetscDefined(PREFER_ZERO_FOR_MEMZERO) || PetscDefined(PREFER_FORTRAN_FOR_MEMZERO)) {
802:     if (!(((PETSC_UINTPTR_T)a) % sizeof(PetscScalar)) && !(n % sizeof(PetscScalar))) {
803:       const size_t scalar_len = n / sizeof(PetscScalar);
804:       PetscScalar *x          = (PetscScalar *)a;

806:       if (PetscDefined(PREFER_ZERO_FOR_MEMZERO)) {
807:         for (size_t i = 0; i < scalar_len; ++i) x[i] = 0;
808:       } else {
809: #if PetscDefined(PREFER_FORTRAN_FOR_MEMZERO)
810:         fortranzero_(&scalar_len, x);
811: #else
812:         (void)scalar_len;
813:         (void)x;
814: #endif
815:       }
816:       PetscFunctionReturn(PETSC_SUCCESS);
817:     }
818:   }
819: #if PetscDefined(PREFER_BZERO)
820:   bzero(a, n);
821: #else
822:   memset(a, 0, n);
823: #endif
824:   PetscFunctionReturn(PETSC_SUCCESS);
825: }

827: /*MC
828:    PetscArraycmp - Compares two arrays in memory.

830:    Synopsis:
831: #include <petscstring.h>
832:     PetscErrorCode PetscArraycmp(const anytype *str1,const anytype *str2,size_t cnt,PetscBool *e)

834:    Not Collective

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

841:    Output Parameters:
842: .   e - `PETSC_TRUE` if equal else `PETSC_FALSE`.

844:    Level: intermediate

846:    Notes:
847:    This routine is a preferred replacement to `PetscMemcmp()`

849:    The arrays must be of the same type

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

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

860:    Synopsis:
861: #include <petscstring.h>
862:     PetscErrorCode PetscArraymove(anytype *str1,const anytype *str2,size_t cnt)

864:    Not Collective

866:    Input Parameters:
867: +  str1 - First array
868: .  str2 - Second array
869: -  cnt  - Count of the array, not in bytes, but number of entries in the arrays

871:    Level: intermediate

873:    Notes:
874:    This routine is a preferred replacement to `PetscMemmove()`

876:    The arrays must be of the same type

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

882: /*MC
883:    PetscArraycpy - Copies from one array in memory to another

885:    Synopsis:
886: #include <petscstring.h>
887:     PetscErrorCode PetscArraycpy(anytype *str1,const anytype *str2,size_t cnt)

889:    Not Collective

891:    Input Parameters:
892: +  str1 - First array (destination)
893: .  str2 - Second array (source)
894: -  cnt  - Count of the array, not in bytes, but number of entries in the arrays

896:    Level: intermediate

898:    Notes:
899:    This routine is a preferred replacement to `PetscMemcpy()`

901:    The arrays must be of the same type

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

907: /*MC
908:    PetscArrayzero - Zeros an array in memory.

910:    Synopsis:
911: #include <petscstring.h>
912:     PetscErrorCode PetscArrayzero(anytype *str1,size_t cnt)

914:    Not Collective

916:    Input Parameters:
917: +  str1 - array
918: -  cnt  - Count of the array, not in bytes, but number of entries in the array

920:    Level: intermediate

922:    Notes:
923:    This routine is a preferred replacement to `PetscMemzero()`

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

929: #endif // PETSC_STRING_H