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[]) PeNS
    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: #if !defined(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) PeNS
    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[]) PeNS
    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[]) PeNS
    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[]) PeNS
    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[]) PeNS
    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: #endif
    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:   #elif PetscDefined(PREFER_FORTRAN_FOR_MEMZERO)
    744:     fortranzero_(&scalar_len, x);
    745:   #endif
    746:     PetscFunctionReturn(PETSC_SUCCESS);
    747:   }
    748: #endif
    749: #if PetscDefined(PREFER_BZERO)
    750:   bzero(a, n);
    751: #else
    752:   memset(a, 0, n);
    753: #endif
    754:   PetscFunctionReturn(PETSC_SUCCESS);
    755: }

    757: /*MC
    758:    PetscArraycmp - Compares two arrays in memory.

    760:    Synopsis:
    761: #include <petscstring.h>
    762:     PetscErrorCode PetscArraycmp(const anytype *str1, const anytype *str2, size_t cnt, PetscBool *e)

    764:    Not Collective

    766:    Input Parameters:
    767: +  str1 - First array
    768: .  str2 - Second array
    769: -  cnt  - Count of the array, not in bytes, but number of entries in the arrays

    771:    Output Parameter:
    772: .   e - `PETSC_TRUE` if equal else `PETSC_FALSE`.

    774:    Level: intermediate

    776:    Notes:
    777:    This routine is a preferred replacement to `PetscMemcmp()`

    779:    The arrays must be of the same type

    781: .seealso: `PetscMemcpy()`, `PetscMemcmp()`, `PetscArrayzero()`, `PetscMemzero()`, `PetscArraycpy()`, `PetscMemmove()`, `PetscStrallocpy()`,
    782:           `PetscArraymove()`
    783: M*/
    784: #define PetscArraycmp(str1, str2, cnt, e) ((sizeof(*(str1)) == sizeof(*(str2))) ? PetscMemcmp((str1), (str2), (size_t)(cnt) * sizeof(*(str1)), (e)) : PETSC_ERR_ARG_SIZ)

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

    790:    Synopsis:
    791: #include <petscstring.h>
    792:     PetscErrorCode PetscArraymove(anytype *str1, const anytype *str2, size_t cnt)

    794:    Not Collective

    796:    Input Parameters:
    797: +  str1 - First array
    798: .  str2 - Second array
    799: -  cnt  - Count of the array, not in bytes, but number of entries in the arrays

    801:    Level: intermediate

    803:    Notes:
    804:    This routine is a preferred replacement to `PetscMemmove()`

    806:    The arrays must be of the same type

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

    812: /*MC
    813:    PetscArraycpy - Copies from one array in memory to another

    815:    Synopsis:
    816: #include <petscstring.h>
    817:     PetscErrorCode PetscArraycpy(anytype *str1, const anytype *str2, size_t cnt)

    819:    Not Collective

    821:    Input Parameters:
    822: +  str1 - First array (destination)
    823: .  str2 - Second array (source)
    824: -  cnt  - Count of the array, not in bytes, but number of entries in the arrays

    826:    Level: intermediate

    828:    Notes:
    829:    This routine is a preferred replacement to `PetscMemcpy()`

    831:    The arrays must be of the same type

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

    837: /*MC
    838:    PetscArrayzero - Zeros an array in memory.

    840:    Synopsis:
    841: #include <petscstring.h>
    842:     PetscErrorCode PetscArrayzero(anytype *str1, size_t cnt)

    844:    Not Collective

    846:    Input Parameters:
    847: +  str1 - array
    848: -  cnt  - Count of the array, not in bytes, but number of entries in the array

    850:    Level: intermediate

    852:    Note:
    853:    This routine is a preferred replacement to `PetscMemzero()`

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