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