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