Actual source code: petscstring.h

  1: #pragma once

  3: #include <petscsys.h>

  5: /* SUBMANSEC = Sys */

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

 10: PETSC_EXTERN PetscErrorCode PetscMemcmp(const void *, const void *, size_t, PetscBool *);
 11: PETSC_EXTERN PetscErrorCode PetscStrToArray(const char[], char, int *, char ***);
 12: PETSC_EXTERN PetscErrorCode PetscStrToArrayDestroy(int, char **);
 13: PETSC_EXTERN PetscErrorCode PetscStrcasecmp(const char[], const char[], PetscBool *);
 14: PETSC_EXTERN PetscErrorCode PetscStrendswithwhich(const char[], const char *const *, PetscInt *);
 15: PETSC_EXTERN PetscErrorCode PetscStrArrayallocpy(const char *const *, char ***);
 16: PETSC_EXTERN PetscErrorCode PetscStrArrayDestroy(char ***);
 17: PETSC_EXTERN PetscErrorCode PetscStrNArrayallocpy(PetscInt, const char *const *, char ***);
 18: PETSC_EXTERN PetscErrorCode PetscStrNArrayDestroy(PetscInt, char ***);
 19: PETSC_EXTERN PetscErrorCode PetscStrreplace(MPI_Comm, const char[], char[], size_t);
 20: PETSC_EXTERN PetscErrorCode PetscStrcmpAny(const char[], PetscBool *, const char[], ...);

 22: PETSC_EXTERN PetscErrorCode PetscTokenCreate(const char[], char, PetscToken *);
 23: PETSC_EXTERN PetscErrorCode PetscTokenFind(PetscToken, const char *[]);
 24: PETSC_EXTERN PetscErrorCode PetscTokenDestroy(PetscToken *);

 26: PETSC_EXTERN PetscErrorCode PetscStrInList(const char[], const char[], char, PetscBool *);
 27: PETSC_EXTERN const char    *PetscBasename(const char[]);
 28: PETSC_EXTERN PetscErrorCode PetscEListFind(PetscInt, const char *const *, const char *, PetscInt *, PetscBool *);
 29: PETSC_EXTERN PetscErrorCode PetscEnumFind(const char *const *, const char *, PetscEnum *, PetscBool *);

 31: PETSC_EXTERN PetscErrorCode PetscStrcat(char[], const char[]);
 32: PETSC_EXTERN PetscErrorCode PetscStrcpy(char[], const char[]);

 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 a string to lower case

 39:   Not Collective, No Fortran Support

 41:   Input Parameter:
 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 a string to upper case

 62:   Not Collective, No Fortran Support

 64:   Input Parameter:
 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 the length of a string

 85:   Not Collective, No Fortran Support

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

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

 93:   Level: intermediate

 95:   Note:
 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:   PetscStrallocpy - Allocates space to hold a copy of a string then copies the string into the new space

119:   Not Collective, No Fortran Support

121:   Input Parameter:
122: . s - pointer to string

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

127:   Level: intermediate

129:   Notes:
130:   `NULL` string returns a new `NULL` string.

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

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

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

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

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

177: /*@C
178:   PetscStrcmp - Compares two strings

180:   Not Collective, No Fortran Support

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

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

189:   Level: intermediate

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

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

212: #ifndef PETSC_SILENCE_WSTRINGOP_TRUNCATION_BEGIN
213:   #define PETSC_SILENCE_WSTRINGOP_TRUNCATION_BEGIN (void)0
214:   #define PETSC_SILENCE_WSTRINGOP_TRUNCATION_END   (void)0
215: #endif

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

220:   Not Collective

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

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

229:   Level: intermediate

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

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

238:   Developer Note:
239:   Should this be `PetscStrlcpy()` to reflect its behavior which is like `strlcpy()` not
240:   `strncpy()`?

242: .seealso: `PetscStrlcat()`, `PetscStrallocpy()`
243: @*/
244: static inline PetscErrorCode PetscStrncpy(char s[], const char t[], size_t n)
245: {
246:   PetscFunctionBegin;
247:   if (s) PetscAssert(n, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Requires an output string of length at least 1 to hold the termination character");
248:   if (t) {
249:     PetscAssertPointer_Private(s, 1);
250:     PETSC_SILENCE_WSTRINGOP_TRUNCATION_BEGIN;
251: #if PetscHasBuiltin(__builtin_strncpy)
252:     __builtin_strncpy(s, t, n);
253: #else
254:     strncpy(s, t, n);
255: #endif
256:     PETSC_SILENCE_WSTRINGOP_TRUNCATION_END;
257:     s[n - 1] = '\0';
258:   } else if (s) {
259:     s[0] = '\0';
260:   }
261:   PetscFunctionReturn(PETSC_SUCCESS);
262: }

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

267:   Not Collective, No Fortran Support

269:   Input Parameters:
270: + s - pointer to string to be added to at end
271: . t - string to be added
272: - n - length of the original allocated string

274:   Level: intermediate

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

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

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

302: #undef PETSC_SILENCE_WSTRINGOP_TRUNCATION_BEGIN
303: #undef PETSC_SILENCE_WSTRINGOP_TRUNCATION_END

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

308:   Not Collective, No Fortran Support

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

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

318:   Level: intermediate

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

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

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

345:   Not Collective, No Fortran Support

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

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

354:   Level: intermediate

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

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

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

383:   Not Collective, No Fortran Support

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

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

392:   Level: intermediate

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

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

415:   Not Collective, No Fortran Support

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

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

424:   Level: intermediate

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

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

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

455:   Not Collective, No Fortran Support

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

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

464:   Level: intermediate

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

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

485:   Not Collective, No Fortran Support

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

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

494:   Level: intermediate

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

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

516:   Not Collective, No Fortran Support

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

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

525:   Level: intermediate

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

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

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

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

557:   Not Collective, No Fortran Support

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

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

566:   Level: intermediate

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

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

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

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

591: #undef PetscAssertPointer_Private

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

598:    Not Collective, No Fortran Support

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

605:    Level: intermediate

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

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

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

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

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

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

652:    Not Collective, No Fortran Support

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

658:    Output Parameter:
659: .  a - pointer to copy space

661:    Level: intermediate

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

668:    Notes:
669:    Prefer `PetscArraycpy()`

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

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

680:   PetscFunctionBegin;
681:   if (PetscUnlikely((n == 0) || (a == b))) PetscFunctionReturn(PETSC_SUCCESS);
682:   PetscAssert(a, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Trying to copy %zu bytes to a null pointer (Argument #1)", n);
683:   PetscAssert(b, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Trying to copy %zu bytes from a null pointer (Argument #2)", n);
684:   PetscAssert(!(((al > bl) && (al - bl) < n) || (bl - al) < n), PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Memory regions overlap: either use PetscMemmove(), or make sure your copy regions and lengths are correct. Length (bytes) %zu first address %" PRIxPTR " second address %" PRIxPTR, n, al, bl);
685:   if (PetscDefined(PREFER_DCOPY_FOR_MEMCPY) || PetscDefined(PREFER_COPY_FOR_MEMCPY) || PetscDefined(PREFER_FORTRAN_FORMEMCPY)) {
686:     if (!(al % sizeof(PetscScalar)) && !(n % sizeof(PetscScalar))) {
687:       const size_t       scalar_len = n / sizeof(PetscScalar);
688:       const PetscScalar *x          = (PetscScalar *)b;
689:       PetscScalar       *y          = (PetscScalar *)a;

691: #if PetscDefined(PREFER_DCOPY_FOR_MEMCPY)
692:       {
693:         const PetscBLASInt one = 1;
694:         PetscBLASInt       blen;

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

711: /*@C
712:    PetscMemzero - Zeros the specified memory.

714:    Not Collective, No Fortran Support

716:    Input Parameters:
717: +  a - pointer to beginning memory location
718: -  n - length (in bytes) of memory to initialize

720:    Level: intermediate

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

726:    Note:
727:    Prefer `PetscArrayzero()`

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

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

762: /*MC
763:    PetscArraycmp - Compares two arrays in memory.

765:    Synopsis:
766: #include <petscstring.h>
767:     PetscErrorCode PetscArraycmp(const anytype *str1, const anytype *str2, size_t cnt, PetscBool *e)

769:    Not Collective

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

776:    Output Parameter:
777: .   e - `PETSC_TRUE` if equal else `PETSC_FALSE`.

779:    Level: intermediate

781:    Notes:
782:    This routine is a preferred replacement to `PetscMemcmp()`

784:    The arrays must be of the same type

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

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

795:    Synopsis:
796: #include <petscstring.h>
797:     PetscErrorCode PetscArraymove(anytype *str1, const anytype *str2, size_t cnt)

799:    Not Collective

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

806:    Level: intermediate

808:    Notes:
809:    This routine is a preferred replacement to `PetscMemmove()`

811:    The arrays must be of the same type

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

817: /*MC
818:    PetscArraycpy - Copies from one array in memory to another

820:    Synopsis:
821: #include <petscstring.h>
822:     PetscErrorCode PetscArraycpy(anytype *str1, const anytype *str2, size_t cnt)

824:    Not Collective

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

831:    Level: intermediate

833:    Notes:
834:    This routine is a preferred replacement to `PetscMemcpy()`

836:    The arrays must be of the same type

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

842: /*MC
843:    PetscArrayzero - Zeros an array in memory.

845:    Synopsis:
846: #include <petscstring.h>
847:     PetscErrorCode PetscArrayzero(anytype *str1, size_t cnt)

849:    Not Collective

851:    Input Parameters:
852: +  str1 - array
853: -  cnt  - Count of the array, not in bytes, but number of entries in the array

855:    Level: intermediate

857:    Note:
858:    This routine is a preferred replacement to `PetscMemzero()`

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