1 #ifndef PETSC_STRING_H 2 #define PETSC_STRING_H 3 4 #include <petscsystypes.h> 5 #include <petscerror.h> 6 #include <petscmacros.h> 7 #include <petscsys.h> 8 9 /* SUBMANSEC = Sys */ 10 11 #include <stddef.h> /* size_t */ 12 #include <string.h> /* for memcpy, memset */ 13 14 PETSC_EXTERN PetscErrorCode PetscMemcmp(const void *, const void *, size_t, PetscBool *); 15 PETSC_EXTERN PetscErrorCode PetscStrToArray(const char[], char, int *, char ***); 16 PETSC_EXTERN PetscErrorCode PetscStrToArrayDestroy(int, char **); 17 PETSC_EXTERN PetscErrorCode PetscStrcasecmp(const char[], const char[], PetscBool *); 18 PETSC_EXTERN PetscErrorCode PetscStrendswithwhich(const char[], const char *const *, PetscInt *); 19 PETSC_EXTERN PetscErrorCode PetscStrArrayallocpy(const char *const *, char ***); 20 PETSC_EXTERN PetscErrorCode PetscStrArrayDestroy(char ***); 21 PETSC_EXTERN PetscErrorCode PetscStrNArrayallocpy(PetscInt, const char *const *, char ***); 22 PETSC_EXTERN PetscErrorCode PetscStrNArrayDestroy(PetscInt, char ***); 23 PETSC_EXTERN PetscErrorCode PetscStrreplace(MPI_Comm, const char[], char[], size_t); 24 PETSC_EXTERN PetscErrorCode PetscStrcmpAny(const char[], PetscBool *, const char[], ...); 25 26 PETSC_EXTERN PetscErrorCode PetscTokenCreate(const char[], char, PetscToken *); 27 PETSC_EXTERN PetscErrorCode PetscTokenFind(PetscToken, char *[]); 28 PETSC_EXTERN PetscErrorCode PetscTokenDestroy(PetscToken *); 29 30 PETSC_EXTERN PetscErrorCode PetscStrInList(const char[], const char[], char, PetscBool *); 31 PETSC_EXTERN const char *PetscBasename(const char[]); 32 PETSC_EXTERN PetscErrorCode PetscEListFind(PetscInt, const char *const *, const char *, PetscInt *, PetscBool *); 33 PETSC_EXTERN PetscErrorCode PetscEnumFind(const char *const *, const char *, PetscEnum *, PetscBool *); 34 35 PETSC_EXTERN PetscErrorCode PetscStrcat(char[], const char[]); 36 PETSC_EXTERN PetscErrorCode PetscStrcpy(char[], const char[]); 37 38 #define PetscAssertPointer_Private(ptr, arg) PetscAssert((ptr), PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Null Pointer: Parameter '" PetscStringize(ptr) "' # " PetscStringize(arg)) 39 40 /*@C 41 PetscStrtolower - Converts a string to lower case 42 43 Not Collective, No Fortran Support 44 45 Input Parameter: 46 . a - pointer to string 47 48 Level: intermediate 49 50 .seealso: `PetscStrtoupper()` 51 @*/ 52 static inline PetscErrorCode PetscStrtolower(char a[]) 53 { 54 PetscFunctionBegin; 55 PetscAssertPointer_Private(a, 1); 56 while (*a) { 57 if (*a >= 'A' && *a <= 'Z') *a += 'a' - 'A'; 58 a++; 59 } 60 PetscFunctionReturn(PETSC_SUCCESS); 61 } 62 63 /*@C 64 PetscStrtoupper - Converts a string to upper case 65 66 Not Collective, No Fortran Support 67 68 Input Parameter: 69 . a - pointer to string 70 71 Level: intermediate 72 73 .seealso: `PetscStrtolower()` 74 @*/ 75 static inline PetscErrorCode PetscStrtoupper(char a[]) 76 { 77 PetscFunctionBegin; 78 PetscAssertPointer_Private(a, 1); 79 while (*a) { 80 if (*a >= 'a' && *a <= 'z') *a += 'A' - 'a'; 81 a++; 82 } 83 PetscFunctionReturn(PETSC_SUCCESS); 84 } 85 86 /*@C 87 PetscStrlen - Gets the length of a string 88 89 Not Collective, No Fortran Support 90 91 Input Parameter: 92 . s - pointer to string 93 94 Output Parameter: 95 . len - length in bytes 96 97 Level: intermediate 98 99 Notes: 100 This routine is analogous to `strlen()`. `NULL` string returns a length of zero. 101 102 .seealso: `PetscStrallocpy()` 103 @*/ 104 static inline PetscErrorCode PetscStrlen(const char s[], size_t *len) 105 { 106 PetscFunctionBegin; 107 PetscAssertPointer_Private(len, 2); 108 if (s) { 109 #if PetscHasBuiltin(__builtin_strlen) 110 *len = __builtin_strlen(s); 111 #else 112 *len = strlen(s); 113 #endif 114 } else { 115 *len = 0; 116 } 117 PetscFunctionReturn(PETSC_SUCCESS); 118 } 119 120 /*@C 121 PetscStrallocpy - Allocates space to hold a copy of a string then copies the string into the new space 122 123 Not Collective, No Fortran Support 124 125 Input Parameter: 126 . s - pointer to string 127 128 Output Parameter: 129 . t - the copied string 130 131 Level: intermediate 132 133 Notes: 134 `NULL` string returns a new `NULL` string. 135 136 If `t` has previously been allocated then that memory is lost, you may need to `PetscFree()` 137 the array before calling this routine. 138 139 .seealso: `PetscStrArrayallocpy()`, `PetscStrNArrayallocpy()` 140 @*/ 141 static inline PetscErrorCode PetscStrallocpy(const char s[], char *t[]) 142 { 143 PetscFunctionBegin; 144 PetscAssertPointer_Private(t, 2); 145 *t = PETSC_NULLPTR; 146 if (s) { 147 size_t len; 148 char *tmp; 149 150 PetscAssertPointer_Private(s, 1); 151 PetscCall(PetscStrlen(s, &len)); 152 PetscCall(PetscMalloc1(len + 1, &tmp)); 153 #if PetscHasBuiltin(__builtin_memcpy) 154 __builtin_memcpy(tmp, s, len); 155 #else 156 memcpy(tmp, s, len); 157 #endif 158 tmp[len] = '\0'; 159 *t = tmp; 160 } 161 PetscFunctionReturn(PETSC_SUCCESS); 162 } 163 164 static inline void PetscStrcmpNoError(const char a[], const char b[], PetscBool *flg) 165 { 166 if (!a && !b) { 167 *flg = PETSC_TRUE; 168 } else if (!a || !b) { 169 *flg = PETSC_FALSE; 170 } else { 171 #if PetscHasBuiltin(__builtin_strcmp) 172 *flg = __builtin_strcmp(a, b) ? PETSC_FALSE : PETSC_TRUE; 173 #else 174 *flg = strcmp(a, b) ? PETSC_FALSE : PETSC_TRUE; 175 #endif 176 } 177 } 178 179 /*@C 180 PetscStrcmp - Compares two strings 181 182 Not Collective, No Fortran Support 183 184 Input Parameters: 185 + a - pointer to string first string 186 - b - pointer to second string 187 188 Output Parameter: 189 . flg - `PETSC_TRUE` if the two strings are equal 190 191 Level: intermediate 192 193 .seealso: `PetscStrcmpAny()`, `PetscStrgrt()`, `PetscStrncmp()`, `PetscStrcasecmp()` 194 @*/ 195 static inline PetscErrorCode PetscStrcmp(const char a[], const char b[], PetscBool *flg) 196 { 197 PetscFunctionBegin; 198 PetscAssertPointer_Private(flg, 3); 199 PetscStrcmpNoError(a, b, flg); 200 PetscFunctionReturn(PETSC_SUCCESS); 201 } 202 203 #if defined(__GNUC__) && !defined(__clang__) 204 #if __GNUC__ >= 8 205 #define PETSC_SILENCE_WSTRINGOP_TRUNCATION_BEGIN \ 206 do { \ 207 _Pragma("GCC diagnostic push"); \ 208 _Pragma("GCC diagnostic ignored \"-Wstringop-truncation\""); \ 209 } while (0) 210 #define PETSC_SILENCE_WSTRINGOP_TRUNCATION_END _Pragma("GCC diagnostic pop") 211 #endif 212 #endif 213 214 #ifndef PETSC_SILENCE_WSTRINGOP_TRUNCATION_BEGIN 215 #define PETSC_SILENCE_WSTRINGOP_TRUNCATION_BEGIN (void)0 216 #define PETSC_SILENCE_WSTRINGOP_TRUNCATION_END (void)0 217 #endif 218 219 /*@C 220 PetscStrncpy - Copies a string up to a certain length 221 222 Not Collective 223 224 Input Parameters: 225 + t - pointer to string 226 - n - the length to copy 227 228 Output Parameter: 229 . s - the copied string 230 231 Level: intermediate 232 233 Notes: 234 `NULL` string returns a string starting with zero. 235 236 If the string that is being copied is of length `n` or larger, then the entire string is not 237 copied and the final location of `s` is set to `NULL`. This is different then the behavior of 238 `strncpy()` which leaves `s` non-terminated if there is not room for the entire string. 239 240 Developers Notes: 241 Should this be `PetscStrlcpy()` to reflect its behavior which is like `strlcpy()` not 242 `strncpy()`? 243 244 .seealso: `PetscStrlcat()`, `PetscStrallocpy()` 245 @*/ 246 static inline PetscErrorCode PetscStrncpy(char s[], const char t[], size_t n) 247 { 248 PetscFunctionBegin; 249 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"); 250 if (t) { 251 PetscAssertPointer_Private(s, 1); 252 PETSC_SILENCE_WSTRINGOP_TRUNCATION_BEGIN; 253 #if PetscHasBuiltin(__builtin_strncpy) 254 __builtin_strncpy(s, t, n); 255 #else 256 strncpy(s, t, n); 257 #endif 258 PETSC_SILENCE_WSTRINGOP_TRUNCATION_END; 259 s[n - 1] = '\0'; 260 } else if (s) { 261 s[0] = '\0'; 262 } 263 PetscFunctionReturn(PETSC_SUCCESS); 264 } 265 266 /*@C 267 PetscStrlcat - Concatenates a string onto a given string, up to a given length 268 269 Not Collective, No Fortran Support 270 271 Input Parameters: 272 + s - pointer to string to be added to at end 273 . t - string to be added 274 - n - length of the original allocated string 275 276 Level: intermediate 277 278 Notes: 279 Unlike the system call `strncat()`, the length passed in is the length of the 280 original allocated space, not the length of the left-over space. This is 281 similar to the BSD system call `strlcat()`. 282 283 .seealso: `PetscStrncpy()` 284 @*/ 285 static inline PetscErrorCode PetscStrlcat(char s[], const char t[], size_t n) 286 { 287 size_t len; 288 289 PetscFunctionBegin; 290 if (!t) PetscFunctionReturn(PETSC_SUCCESS); 291 PetscAssert(n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "String buffer length must be positive"); 292 PetscCall(PetscStrlen(s, &len)); 293 PETSC_SILENCE_WSTRINGOP_TRUNCATION_BEGIN; 294 #if PetscHasBuiltin(__builtin_strncat) 295 __builtin_strncat(s, t, n - len); 296 #else 297 strncat(s, t, n - len); 298 #endif 299 PETSC_SILENCE_WSTRINGOP_TRUNCATION_END; 300 s[n - 1] = '\0'; 301 PetscFunctionReturn(PETSC_SUCCESS); 302 } 303 304 #undef PETSC_SILENCE_WSTRINGOP_TRUNCATION_BEGIN 305 #undef PETSC_SILENCE_WSTRINGOP_TRUNCATION_END 306 307 /*@C 308 PetscStrncmp - Compares two strings, up to a certain length 309 310 Not Collective, No Fortran Support 311 312 Input Parameters: 313 + a - pointer to first string 314 . b - pointer to second string 315 - n - length to compare up to 316 317 Output Parameter: 318 . t - `PETSC_TRUE` if the two strings are equal, `PETSC_FALSE` otherwise 319 320 Level: intermediate 321 322 Note: 323 If `n` is `0`, `t` is set to `PETSC_FALSE`. `a` and/or `b` may be `NULL` in this case. 324 325 .seealso: `PetscStrgrt()`, `PetscStrcmp()`, `PetscStrcasecmp()` 326 @*/ 327 static inline PetscErrorCode PetscStrncmp(const char a[], const char b[], size_t n, PetscBool *t) 328 { 329 PetscFunctionBegin; 330 PetscAssertPointer_Private(t, 4); 331 *t = PETSC_FALSE; 332 if (n) { 333 PetscAssertPointer_Private(a, 1); 334 PetscAssertPointer_Private(b, 2); 335 } 336 #if PetscHasBuiltin(__builtin_strncmp) 337 *t = __builtin_strncmp(a, b, n) ? PETSC_FALSE : PETSC_TRUE; 338 #else 339 *t = strncmp(a, b, n) ? PETSC_FALSE : PETSC_TRUE; 340 #endif 341 PetscFunctionReturn(PETSC_SUCCESS); 342 } 343 344 /*@C 345 PetscStrrstr - Locates last occurrence of string in another string 346 347 Not Collective, No Fortran Support 348 349 Input Parameters: 350 + a - pointer to string 351 - b - string to find 352 353 Output Parameter: 354 . tmp - location of occurrence 355 356 Level: intermediate 357 358 .seealso: `PetscStrbeginswithwhich()`, `PetscStrendswith()`, `PetscStrtoupper`, 359 `PetscStrtolower()`, `PetscStrrchr()`, `PetscStrchr()`, `PetscStrncmp()`, `PetscStrlen()`, 360 `PetscStrcmp()` 361 @*/ 362 static inline PetscErrorCode PetscStrrstr(const char a[], const char b[], char *tmp[]) 363 { 364 const char *ltmp = PETSC_NULLPTR; 365 366 PetscFunctionBegin; 367 PetscAssertPointer_Private(a, 1); 368 PetscAssertPointer_Private(b, 2); 369 PetscAssertPointer_Private(tmp, 3); 370 while (a) { 371 #if PetscHasBuiltin(__builtin_strstr) 372 a = (char *)__builtin_strstr(a, b); 373 #else 374 a = (char *)strstr(a, b); 375 #endif 376 if (a) ltmp = a++; 377 } 378 *tmp = (char *)ltmp; 379 PetscFunctionReturn(PETSC_SUCCESS); 380 } 381 382 /*@C 383 PetscStrstr - Locates first occurrence of string in another string 384 385 Not Collective, No Fortran Support 386 387 Input Parameters: 388 + haystack - string to search 389 - needle - string to find 390 391 Output Parameter: 392 . tmp - location of `needle` within `haystack`, `NULL` if `needle` is not found 393 394 Level: intermediate 395 396 .seealso: `PetscStrbeginswithwhich()`, `PetscStrendswith()`, `PetscStrtoupper`, 397 `PetscStrtolower()`, `PetscStrrchr()`, `PetscStrchr()`, `PetscStrncmp()`, `PetscStrlen()`, 398 `PetscStrcmp()` 399 @*/ 400 static inline PetscErrorCode PetscStrstr(const char haystack[], const char needle[], char *tmp[]) 401 { 402 PetscFunctionBegin; 403 PetscAssertPointer_Private(haystack, 1); 404 PetscAssertPointer_Private(needle, 2); 405 PetscAssertPointer_Private(tmp, 3); 406 #if PetscHasBuiltin(__builtin_strstr) 407 *tmp = (char *)__builtin_strstr(haystack, needle); 408 #else 409 *tmp = (char *)strstr(haystack, needle); 410 #endif 411 PetscFunctionReturn(PETSC_SUCCESS); 412 } 413 414 /*@C 415 PetscStrgrt - If first string is greater than the second 416 417 Not Collective, No Fortran Support 418 419 Input Parameters: 420 + a - pointer to first string 421 - b - pointer to second string 422 423 Output Parameter: 424 . flg - `PETSC_TRUE` if `a` is strictly greater than `b`, `PETSC_FALSE` otherwise 425 426 Level: intermediate 427 428 Notes: 429 `NULL` arguments are OK, a `NULL` string is considered smaller than all others. If both `a` 430 and `b` are `NULL` then `t` is set to `PETSC_FALSE`. 431 432 .seealso: `PetscStrcmp()`, `PetscStrncmp()`, `PetscStrcasecmp()` 433 @*/ 434 static inline PetscErrorCode PetscStrgrt(const char a[], const char b[], PetscBool *t) 435 { 436 PetscFunctionBegin; 437 PetscAssertPointer_Private(t, 3); 438 if (!a && !b) { 439 *t = PETSC_FALSE; 440 } else if (a && !b) { 441 *t = PETSC_TRUE; 442 } else if (!a && b) { 443 *t = PETSC_FALSE; 444 } else { 445 #if PetscHasBuiltin(__builtin_strcmp) 446 *t = __builtin_strcmp(a, b) > 0 ? PETSC_TRUE : PETSC_FALSE; 447 #else 448 *t = strcmp(a, b) > 0 ? PETSC_TRUE : PETSC_FALSE; 449 #endif 450 } 451 PetscFunctionReturn(PETSC_SUCCESS); 452 } 453 454 /*@C 455 PetscStrchr - Locates first occurrence of a character in a string 456 457 Not Collective, No Fortran Support 458 459 Input Parameters: 460 + a - pointer to string 461 - b - character 462 463 Output Parameter: 464 . c - location of occurrence, `NULL` if not found 465 466 Level: intermediate 467 468 .seealso: `PetscStrrchr()`, `PetscTokenCreate()`, `PetscStrendswith()`, `PetscStrbeginsswith()` 469 @*/ 470 static inline PetscErrorCode PetscStrchr(const char a[], char b, char *c[]) 471 { 472 PetscFunctionBegin; 473 PetscAssertPointer_Private(a, 1); 474 PetscAssertPointer_Private(c, 3); 475 #if PetscHasBuiltin(__builtin_strchr) 476 *c = (char *)__builtin_strchr(a, b); 477 #else 478 *c = (char *)strchr(a, b); 479 #endif 480 PetscFunctionReturn(PETSC_SUCCESS); 481 } 482 483 /*@C 484 PetscStrrchr - Locates one location past the last occurrence of a character in a string, if 485 the character is not found then returns entire string 486 487 Not Collective, No Fortran Support 488 489 Input Parameters: 490 + a - pointer to string 491 - b - character 492 493 Output Parameter: 494 . c - one past location of `b` in `a`, or `a` if `b` was not found 495 496 Level: intermediate 497 498 .seealso: `PetscStrchr()`, `PetscTokenCreate()`, `PetscStrendswith()`, `PetscStrbeginsswith()` 499 @*/ 500 static inline PetscErrorCode PetscStrrchr(const char a[], char b, char *c[]) 501 { 502 PetscFunctionBegin; 503 PetscAssertPointer_Private(a, 1); 504 PetscAssertPointer_Private(c, 3); 505 #if PetscHasBuiltin(__builtin_strrchr) 506 *c = (char *)__builtin_strrchr(a, b); 507 #else 508 *c = (char *)strrchr(a, b); 509 #endif 510 if (!*c) *c = (char *)a; 511 else *c = *c + 1; 512 PetscFunctionReturn(PETSC_SUCCESS); 513 } 514 515 /*@C 516 PetscStrendswith - Determines if a string ends with a certain string 517 518 Not Collective, No Fortran Support 519 520 Input Parameters: 521 + a - string to search 522 - b - string to end with 523 524 Output Parameter: 525 . flg - `PETSC_TRUE` if `a` ends with `b`, `PETSC_FALSE` otherwise 526 527 Level: intermediate 528 529 Notes: 530 Both `a` and `b` may be `NULL` (in which case `flg` is set to `PETSC_FALSE`) bot not either. 531 532 .seealso: `PetscStrendswithwhich()`, `PetscStrbeginswith()`, `PetscStrtoupper`, 533 `PetscStrtolower()`, `PetscStrrchr()`, `PetscStrchr()`, `PetscStrncmp()`, `PetscStrlen()`, 534 `PetscStrcmp()` 535 @*/ 536 static inline PetscErrorCode PetscStrendswith(const char a[], const char b[], PetscBool *flg) 537 { 538 size_t na = 0, nb = 0; 539 540 PetscFunctionBegin; 541 PetscAssertPointer_Private(flg, 3); 542 // do this here to silence stupid "may be used uninitialized"" warnings 543 *flg = PETSC_FALSE; 544 PetscCall(PetscStrlen(a, &na)); 545 PetscCall(PetscStrlen(b, &nb)); 546 if (na >= nb) { 547 #if PetscHasBuiltin(__builtin_memcmp) 548 *flg = __builtin_memcmp(b, a + (na - nb), nb) == 0 ? PETSC_TRUE : PETSC_FALSE; 549 #else 550 *flg = memcmp(b, a + (na - nb), nb) == 0 ? PETSC_TRUE : PETSC_FALSE; 551 #endif 552 } 553 PetscFunctionReturn(PETSC_SUCCESS); 554 } 555 556 /*@C 557 PetscStrbeginswith - Determines if a string begins with a certain string 558 559 Not Collective, No Fortran Support 560 561 Input Parameters: 562 + a - string to search 563 - b - string to begin with 564 565 Output Parameter: 566 . flg - `PETSC_TRUE` if `a` begins with `b`, `PETSC_FALSE` otherwise 567 568 Level: intermediate 569 570 Notes: 571 Both `a` and `b` may be `NULL` (in which case `flg` is set to `PETSC_FALSE`) but not 572 either. 573 574 `a` and `b` may point to the same string. 575 576 .seealso: `PetscStrendswithwhich()`, `PetscStrendswith()`, `PetscStrtoupper`, 577 `PetscStrtolower()`, `PetscStrrchr()`, `PetscStrchr()`, `PetscStrncmp()`, `PetscStrlen()`, 578 `PetscStrcmp()` 579 @*/ 580 static inline PetscErrorCode PetscStrbeginswith(const char a[], const char b[], PetscBool *flg) 581 { 582 size_t len = 0; 583 584 PetscFunctionBegin; 585 PetscAssertPointer_Private(flg, 3); 586 // do this here to silence stupid "may be used uninitialized"" warnings 587 *flg = PETSC_FALSE; 588 PetscCall(PetscStrlen(b, &len)); 589 PetscCall(PetscStrncmp(a, b, len, flg)); 590 PetscFunctionReturn(PETSC_SUCCESS); 591 } 592 593 #undef PetscAssertPointer_Private 594 595 /*@C 596 PetscMemmove - Copies `n` bytes, beginning at location `b`, to the space 597 beginning at location `a`. Copying between regions that overlap will 598 take place correctly. Use `PetscMemcpy()` if the locations do not overlap 599 600 Not Collective 601 602 Input Parameters: 603 + b - pointer to initial memory space 604 . a - pointer to copy space 605 - n - length (in bytes) of space to copy 606 607 Level: intermediate 608 609 Notes: 610 `PetscArraymove()` is preferred 611 612 This routine is analogous to `memmove()`. 613 614 .seealso: `PetscMemcpy()`, `PetscMemcmp()`, `PetscArrayzero()`, `PetscMemzero()`, `PetscArraycmp()`, `PetscArraycpy()`, `PetscStrallocpy()`, 615 `PetscArraymove()` 616 @*/ 617 static inline PetscErrorCode PetscMemmove(void *a, const void *b, size_t n) 618 { 619 PetscFunctionBegin; 620 if (PetscUnlikely((n == 0) || (a == b))) PetscFunctionReturn(PETSC_SUCCESS); 621 PetscAssert(a, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Trying to copy %zu bytes to null pointer (Argument #1)", n); 622 PetscAssert(b, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Trying to copy %zu bytes from a null pointer (Argument #2)", n); 623 #if PetscDefined(HAVE_MEMMOVE) 624 memmove((char *)a, (const char *)b, n); 625 #else 626 if (a < b) { 627 if ((char *)a <= (char *)b - n) { 628 memcpy(a, b, n); 629 } else { 630 const size_t ptr_diff = (size_t)((char *)b - (char *)a); 631 632 memcpy(a, b, ptr_diff); 633 PetscCall(PetscMemmove((void *)b, (char *)b + ptr_diff, n - ptr_diff)); 634 } 635 } else { 636 if ((char *)b <= (char *)a - n) { 637 memcpy(a, b, n); 638 } else { 639 const size_t ptr_diff = (size_t)((char *)a - (char *)b); 640 641 memcpy((void *)((char *)b + n), (char *)b + (n - ptr_diff), ptr_diff); 642 PetscCall(PetscMemmove(a, b, n - ptr_diff)); 643 } 644 } 645 #endif 646 PetscFunctionReturn(PETSC_SUCCESS); 647 } 648 649 /*@C 650 PetscMemcpy - Copies `n` bytes, beginning at location `b`, to the space 651 beginning at location `a`. The two memory regions CANNOT overlap, use 652 `PetscMemmove()` in that case. 653 654 Not Collective 655 656 Input Parameters: 657 + b - pointer to initial memory space 658 - n - length (in bytes) of space to copy 659 660 Output Parameter: 661 . a - pointer to copy space 662 663 Level: intermediate 664 665 Compile Option: 666 `PETSC_PREFER_DCOPY_FOR_MEMCPY` will cause the BLAS `dcopy()` routine to be used 667 for memory copies on double precision values. 668 `PETSC_PREFER_COPY_FOR_MEMCPY` will cause C code to be used 669 for memory copies on double precision values. 670 `PETSC_PREFER_FORTRAN_FORMEMCPY` will cause Fortran code to be used 671 for memory copies on double precision values. 672 673 Notes: 674 Prefer `PetscArraycpy()` 675 676 This routine is analogous to `memcpy()`. 677 678 .seealso: `PetscMemzero()`, `PetscMemcmp()`, `PetscArrayzero()`, `PetscArraycmp()`, `PetscArraycpy()`, `PetscMemmove()`, `PetscStrallocpy()` 679 @*/ 680 static inline PetscErrorCode PetscMemcpy(void *a, const void *b, size_t n) 681 { 682 const PETSC_UINTPTR_T al = (PETSC_UINTPTR_T)a; 683 const PETSC_UINTPTR_T bl = (PETSC_UINTPTR_T)b; 684 685 PetscFunctionBegin; 686 if (PetscUnlikely((n == 0) || (a == b))) PetscFunctionReturn(PETSC_SUCCESS); 687 PetscAssert(a, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Trying to copy %zu bytes to a null pointer (Argument #1)", n); 688 PetscAssert(b, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Trying to copy %zu bytes from a null pointer (Argument #2)", n); 689 PetscAssert(!(((al > bl) && (al - bl) < n) || (bl - al) < n), PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Memory regions overlap: either use PetscMemmove()\nor make sure your copy regions and lengths are correct.\nLength (bytes) %zu first address %" PRIxPTR " second address %" PRIxPTR, n, al, bl); 690 if (PetscDefined(PREFER_DCOPY_FOR_MEMCPY) || PetscDefined(PREFER_COPY_FOR_MEMCPY) || PetscDefined(PREFER_FORTRAN_FORMEMCPY)) { 691 if (!(al % sizeof(PetscScalar)) && !(n % sizeof(PetscScalar))) { 692 const size_t scalar_len = n / sizeof(PetscScalar); 693 const PetscScalar *x = (PetscScalar *)b; 694 PetscScalar *y = (PetscScalar *)a; 695 696 #if PetscDefined(PREFER_DCOPY_FOR_MEMCPY) 697 { 698 const PetscBLASInt one = 1; 699 PetscBLASInt blen; 700 701 PetscCall(PetscBLASIntCast(scalar_len, &blen)); 702 PetscCallBLAS("BLAScopy", BLAScopy_(&blen, x, &one, y, &one)); 703 } 704 #elif PetscDefined(PREFER_FORTRAN_FORMEMCPY) 705 fortrancopy_(&scalar_len, x, y); 706 #else 707 for (size_t i = 0; i < scalar_len; i++) y[i] = x[i]; 708 #endif 709 PetscFunctionReturn(PETSC_SUCCESS); 710 } 711 } 712 memcpy(a, b, n); 713 PetscFunctionReturn(PETSC_SUCCESS); 714 } 715 716 /*@C 717 PetscMemzero - Zeros the specified memory. 718 719 Not Collective 720 721 Input Parameters: 722 + a - pointer to beginning memory location 723 - n - length (in bytes) of memory to initialize 724 725 Level: intermediate 726 727 Compile Option: 728 `PETSC_PREFER_BZERO` - on certain machines (the IBM RS6000) the bzero() routine happens 729 to be faster than the memset() routine. This flag causes the bzero() routine to be used. 730 731 Notes: 732 Prefer `PetscArrayzero()` 733 734 .seealso: `PetscMemcpy()`, `PetscMemcmp()`, `PetscArrayzero()`, `PetscArraycmp()`, `PetscArraycpy()`, `PetscMemmove()`, `PetscStrallocpy()` 735 @*/ 736 static inline PetscErrorCode PetscMemzero(void *a, size_t n) 737 { 738 PetscFunctionBegin; 739 if (PetscUnlikely(n == 0)) PetscFunctionReturn(PETSC_SUCCESS); 740 PetscAssert(a, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Trying to zero %zu bytes at a null pointer", n); 741 if (PetscDefined(PREFER_ZERO_FOR_MEMZERO) || PetscDefined(PREFER_FORTRAN_FOR_MEMZERO)) { 742 if (!(((PETSC_UINTPTR_T)a) % sizeof(PetscScalar)) && !(n % sizeof(PetscScalar))) { 743 const size_t scalar_len = n / sizeof(PetscScalar); 744 PetscScalar *x = (PetscScalar *)a; 745 746 if (PetscDefined(PREFER_ZERO_FOR_MEMZERO)) { 747 for (size_t i = 0; i < scalar_len; ++i) x[i] = 0; 748 } else { 749 #if PetscDefined(PREFER_FORTRAN_FOR_MEMZERO) 750 fortranzero_(&scalar_len, x); 751 #else 752 (void)scalar_len; 753 (void)x; 754 #endif 755 } 756 PetscFunctionReturn(PETSC_SUCCESS); 757 } 758 } 759 #if PetscDefined(PREFER_BZERO) 760 bzero(a, n); 761 #else 762 memset(a, 0, n); 763 #endif 764 PetscFunctionReturn(PETSC_SUCCESS); 765 } 766 767 /*MC 768 PetscArraycmp - Compares two arrays in memory. 769 770 Synopsis: 771 #include <petscstring.h> 772 PetscErrorCode PetscArraycmp(const anytype *str1,const anytype *str2,size_t cnt,PetscBool *e) 773 774 Not Collective 775 776 Input Parameters: 777 + str1 - First array 778 . str2 - Second array 779 - cnt - Count of the array, not in bytes, but number of entries in the arrays 780 781 Output Parameter: 782 . e - `PETSC_TRUE` if equal else `PETSC_FALSE`. 783 784 Level: intermediate 785 786 Notes: 787 This routine is a preferred replacement to `PetscMemcmp()` 788 789 The arrays must be of the same type 790 791 .seealso: `PetscMemcpy()`, `PetscMemcmp()`, `PetscArrayzero()`, `PetscMemzero()`, `PetscArraycpy()`, `PetscMemmove()`, `PetscStrallocpy()`, 792 `PetscArraymove()` 793 M*/ 794 #define PetscArraycmp(str1, str2, cnt, e) ((sizeof(*(str1)) == sizeof(*(str2))) ? PetscMemcmp((str1), (str2), (size_t)(cnt) * sizeof(*(str1)), (e)) : PETSC_ERR_ARG_SIZ) 795 796 /*MC 797 PetscArraymove - Copies from one array in memory to another, the arrays may overlap. Use `PetscArraycpy()` when the arrays 798 do not overlap 799 800 Synopsis: 801 #include <petscstring.h> 802 PetscErrorCode PetscArraymove(anytype *str1,const anytype *str2,size_t cnt) 803 804 Not Collective 805 806 Input Parameters: 807 + str1 - First array 808 . str2 - Second array 809 - cnt - Count of the array, not in bytes, but number of entries in the arrays 810 811 Level: intermediate 812 813 Notes: 814 This routine is a preferred replacement to `PetscMemmove()` 815 816 The arrays must be of the same type 817 818 .seealso: `PetscMemcpy()`, `PetscMemcmp()`, `PetscArrayzero()`, `PetscMemzero()`, `PetscArraycpy()`, `PetscMemmove()`, `PetscArraycmp()`, `PetscStrallocpy()` 819 M*/ 820 #define PetscArraymove(str1, str2, cnt) ((sizeof(*(str1)) == sizeof(*(str2))) ? PetscMemmove((str1), (str2), (size_t)(cnt) * sizeof(*(str1))) : PETSC_ERR_ARG_SIZ) 821 822 /*MC 823 PetscArraycpy - Copies from one array in memory to another 824 825 Synopsis: 826 #include <petscstring.h> 827 PetscErrorCode PetscArraycpy(anytype *str1,const anytype *str2,size_t cnt) 828 829 Not Collective 830 831 Input Parameters: 832 + str1 - First array (destination) 833 . str2 - Second array (source) 834 - cnt - Count of the array, not in bytes, but number of entries in the arrays 835 836 Level: intermediate 837 838 Notes: 839 This routine is a preferred replacement to `PetscMemcpy()` 840 841 The arrays must be of the same type 842 843 .seealso: `PetscMemcpy()`, `PetscMemcmp()`, `PetscArrayzero()`, `PetscMemzero()`, `PetscArraymove()`, `PetscMemmove()`, `PetscArraycmp()`, `PetscStrallocpy()` 844 M*/ 845 #define PetscArraycpy(str1, str2, cnt) ((sizeof(*(str1)) == sizeof(*(str2))) ? PetscMemcpy((str1), (str2), (size_t)(cnt) * sizeof(*(str1))) : PETSC_ERR_ARG_SIZ) 846 847 /*MC 848 PetscArrayzero - Zeros an array in memory. 849 850 Synopsis: 851 #include <petscstring.h> 852 PetscErrorCode PetscArrayzero(anytype *str1,size_t cnt) 853 854 Not Collective 855 856 Input Parameters: 857 + str1 - array 858 - cnt - Count of the array, not in bytes, but number of entries in the array 859 860 Level: intermediate 861 862 Notes: 863 This routine is a preferred replacement to `PetscMemzero()` 864 865 .seealso: `PetscMemcpy()`, `PetscMemcmp()`, `PetscMemzero()`, `PetscArraycmp()`, `PetscArraycpy()`, `PetscMemmove()`, `PetscStrallocpy()`, `PetscArraymove()` 866 M*/ 867 #define PetscArrayzero(str1, cnt) PetscMemzero((str1), (size_t)(cnt) * sizeof(*(str1))) 868 869 #endif // PETSC_STRING_H 870