Date: 2025-03-29T05:58:18+00:00

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, const 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)))