1 #pragma once 2 3 #include <petscsys.h> 4 5 /* SUBMANSEC = Sys */ 6 7 #include <stddef.h> /* size_t */ 8 #include <string.h> /* for memcpy, memset */ 9 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[], ...); 21 22 PETSC_EXTERN PetscErrorCode PetscTokenCreate(const char[], char, PetscToken *); 23 PETSC_EXTERN PetscErrorCode PetscTokenFind(PetscToken, const char *[]); 24 PETSC_EXTERN PetscErrorCode PetscTokenDestroy(PetscToken *); 25 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 *); 30 31 PETSC_EXTERN PetscErrorCode PetscStrcat(char[], const char[]); 32 PETSC_EXTERN PetscErrorCode PetscStrcpy(char[], const char[]); 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 a string to lower case 38 39 Not Collective, No Fortran Support 40 41 Input Parameter: 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 a string to upper case 61 62 Not Collective, No Fortran Support 63 64 Input Parameter: 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 the length of a string 84 85 Not Collective, No Fortran Support 86 87 Input Parameter: 88 . s - pointer to string 89 90 Output Parameter: 91 . len - length in bytes 92 93 Level: intermediate 94 95 Note: 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 PetscStrallocpy - Allocates space to hold a copy of a string then copies the string into the new space 118 119 Not Collective, No Fortran Support 120 121 Input Parameter: 122 . s - pointer to string 123 124 Output Parameter: 125 . t - the copied string 126 127 Level: intermediate 128 129 Notes: 130 `NULL` string returns a new `NULL` string. 131 132 Use `PetscFree()` to release the data when it is no longer needed. 133 134 If `t` has previously been allocated then that memory is lost, you may need to `PetscFree()` 135 the array before calling this routine. 136 137 .seealso: `PetscStrArrayallocpy()`, `PetscStrNArrayallocpy()` 138 @*/ 139 static inline PetscErrorCode PetscStrallocpy(const char s[], char *t[]) 140 { 141 PetscFunctionBegin; 142 PetscAssertPointer_Private(t, 2); 143 *t = PETSC_NULLPTR; 144 if (s) { 145 size_t len; 146 char *tmp; 147 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 } 161 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 } 176 177 /*@C 178 PetscStrcmp - Compares two strings 179 180 Not Collective, No Fortran Support 181 182 Input Parameters: 183 + a - pointer to string first string 184 - b - pointer to second string 185 186 Output Parameter: 187 . flg - `PETSC_TRUE` if the two strings are equal 188 189 Level: intermediate 190 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 } 200 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 211 212 #ifndef 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 216 217 /*@C 218 PetscStrncpy - Copies a string up to a certain length 219 220 Not Collective 221 222 Input Parameters: 223 + t - pointer to string 224 - n - the length to copy 225 226 Output Parameter: 227 . s - the copied string 228 229 Level: intermediate 230 231 Notes: 232 `NULL` string returns a string starting with zero. 233 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. 237 238 Developer Note: 239 Should this be `PetscStrlcpy()` to reflect its behavior which is like `strlcpy()` not 240 `strncpy()`? 241 242 .seealso: `PetscStrlcat()`, `PetscStrallocpy()` 243 @*/ 244 static inline PetscErrorCode PetscStrncpy(char s[], const char t[], size_t n) 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 } 263 264 /*@C 265 PetscStrlcat - Concatenates a string onto a given string, up to a given length 266 267 Not Collective, No Fortran Support 268 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 273 274 Level: intermediate 275 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()`. 280 281 .seealso: `PetscStrncpy()` 282 @*/ 283 static inline PetscErrorCode PetscStrlcat(char s[], const char t[], size_t n) 284 { 285 size_t len; 286 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 } 301 302 #undef PETSC_SILENCE_WSTRINGOP_TRUNCATION_BEGIN 303 #undef PETSC_SILENCE_WSTRINGOP_TRUNCATION_END 304 305 /*@C 306 PetscStrncmp - Compares two strings, up to a certain length 307 308 Not Collective, No Fortran Support 309 310 Input Parameters: 311 + a - pointer to first string 312 . b - pointer to second string 313 - n - length to compare up to 314 315 Output Parameter: 316 . t - `PETSC_TRUE` if the two strings are equal, `PETSC_FALSE` otherwise 317 318 Level: intermediate 319 320 Note: 321 If `n` is `0`, `t` is set to `PETSC_FALSE`. `a` and/or `b` may be `NULL` in this case. 322 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 } 341 342 /*@C 343 PetscStrrstr - Locates last occurrence of string in another string 344 345 Not Collective, No Fortran Support 346 347 Input Parameters: 348 + a - pointer to string 349 - b - string to find 350 351 Output Parameter: 352 . tmp - location of occurrence 353 354 Level: intermediate 355 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[]) 361 { 362 const char *ltmp = PETSC_NULLPTR; 363 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 } 379 380 /*@C 381 PetscStrstr - Locates first occurrence of string in another string 382 383 Not Collective, No Fortran Support 384 385 Input Parameters: 386 + haystack - string to search 387 - needle - string to find 388 389 Output Parameter: 390 . tmp - location of `needle` within `haystack`, `NULL` if `needle` is not found 391 392 Level: intermediate 393 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[]) 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 } 411 412 /*@C 413 PetscStrgrt - If first string is greater than the second 414 415 Not Collective, No Fortran Support 416 417 Input Parameters: 418 + a - pointer to first string 419 - b - pointer to second string 420 421 Output Parameter: 422 . flg - `PETSC_TRUE` if `a` is strictly greater than `b`, `PETSC_FALSE` otherwise 423 424 Level: intermediate 425 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`. 429 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 } 451 452 /*@C 453 PetscStrchr - Locates first occurrence of a character in a string 454 455 Not Collective, No Fortran Support 456 457 Input Parameters: 458 + a - pointer to string 459 - b - character 460 461 Output Parameter: 462 . c - location of occurrence, `NULL` if not found 463 464 Level: intermediate 465 466 .seealso: `PetscStrrchr()`, `PetscTokenCreate()`, `PetscStrendswith()`, `PetscStrbeginsswith()` 467 @*/ 468 static inline PetscErrorCode PetscStrchr(const char a[], char b, char *c[]) 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 } 480 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 484 485 Not Collective, No Fortran Support 486 487 Input Parameters: 488 + a - pointer to string 489 - b - character 490 491 Output Parameter: 492 . c - one past location of `b` in `a`, or `a` if `b` was not found 493 494 Level: intermediate 495 496 .seealso: `PetscStrchr()`, `PetscTokenCreate()`, `PetscStrendswith()`, `PetscStrbeginsswith()` 497 @*/ 498 static inline PetscErrorCode PetscStrrchr(const char a[], char b, char *c[]) 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 } 512 513 /*@C 514 PetscStrendswith - Determines if a string ends with a certain string 515 516 Not Collective, No Fortran Support 517 518 Input Parameters: 519 + a - string to search 520 - b - string to end with 521 522 Output Parameter: 523 . flg - `PETSC_TRUE` if `a` ends with `b`, `PETSC_FALSE` otherwise 524 525 Level: intermediate 526 527 Note: 528 Both `a` and `b` may be `NULL` (in which case `flg` is set to `PETSC_FALSE`) bot not either. 529 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; 537 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 } 553 554 /*@C 555 PetscStrbeginswith - Determines if a string begins with a certain string 556 557 Not Collective, No Fortran Support 558 559 Input Parameters: 560 + a - string to search 561 - b - string to begin with 562 563 Output Parameter: 564 . flg - `PETSC_TRUE` if `a` begins with `b`, `PETSC_FALSE` otherwise 565 566 Level: intermediate 567 568 Notes: 569 Both `a` and `b` may be `NULL` (in which case `flg` is set to `PETSC_FALSE`) but not 570 either. 571 572 `a` and `b` may point to the same string. 573 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; 581 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 } 590 591 #undef PetscAssertPointer_Private 592 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 597 598 Not Collective, No Fortran Support 599 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 604 605 Level: intermediate 606 607 Notes: 608 `PetscArraymove()` is preferred 609 610 This routine is analogous to `memmove()`. 611 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); 629 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); 638 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 } 646 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. 651 652 Not Collective, No Fortran Support 653 654 Input Parameters: 655 + b - pointer to initial memory space 656 - n - length (in bytes) of space to copy 657 658 Output Parameter: 659 . a - pointer to copy space 660 661 Level: intermediate 662 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. 667 668 Notes: 669 Prefer `PetscArraycpy()` 670 671 This routine is analogous to `memcpy()`. 672 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; 679 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; 690 691 #if PetscDefined(PREFER_DCOPY_FOR_MEMCPY) 692 { 693 const PetscBLASInt one = 1; 694 PetscBLASInt blen; 695 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 } 707 memcpy(a, b, n); 708 PetscFunctionReturn(PETSC_SUCCESS); 709 } 710 711 /*@C 712 PetscMemzero - Zeros the specified memory. 713 714 Not Collective, No Fortran Support 715 716 Input Parameters: 717 + a - pointer to beginning memory location 718 - n - length (in bytes) of memory to initialize 719 720 Level: intermediate 721 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. 725 726 Note: 727 Prefer `PetscArrayzero()` 728 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; 740 741 if (PetscDefined(PREFER_ZERO_FOR_MEMZERO)) { 742 for (size_t i = 0; i < scalar_len; ++i) x[i] = 0; 743 } else { 744 #if PetscDefined(PREFER_FORTRAN_FOR_MEMZERO) 745 fortranzero_(&scalar_len, x); 746 #else 747 (void)scalar_len; 748 (void)x; 749 #endif 750 } 751 PetscFunctionReturn(PETSC_SUCCESS); 752 } 753 } 754 #if PetscDefined(PREFER_BZERO) 755 bzero(a, n); 756 #else 757 memset(a, 0, n); 758 #endif 759 PetscFunctionReturn(PETSC_SUCCESS); 760 } 761 762 /*MC 763 PetscArraycmp - Compares two arrays in memory. 764 765 Synopsis: 766 #include <petscstring.h> 767 PetscErrorCode PetscArraycmp(const anytype *str1, const anytype *str2, size_t cnt, PetscBool *e) 768 769 Not Collective 770 771 Input Parameters: 772 + str1 - First array 773 . str2 - Second array 774 - cnt - Count of the array, not in bytes, but number of entries in the arrays 775 776 Output Parameter: 777 . e - `PETSC_TRUE` if equal else `PETSC_FALSE`. 778 779 Level: intermediate 780 781 Notes: 782 This routine is a preferred replacement to `PetscMemcmp()` 783 784 The arrays must be of the same type 785 786 .seealso: `PetscMemcpy()`, `PetscMemcmp()`, `PetscArrayzero()`, `PetscMemzero()`, `PetscArraycpy()`, `PetscMemmove()`, `PetscStrallocpy()`, 787 `PetscArraymove()` 788 M*/ 789 #define PetscArraycmp(str1, str2, cnt, e) ((sizeof(*(str1)) == sizeof(*(str2))) ? PetscMemcmp((str1), (str2), (size_t)(cnt) * sizeof(*(str1)), (e)) : PETSC_ERR_ARG_SIZ) 790 791 /*MC 792 PetscArraymove - Copies from one array in memory to another, the arrays may overlap. Use `PetscArraycpy()` when the arrays 793 do not overlap 794 795 Synopsis: 796 #include <petscstring.h> 797 PetscErrorCode PetscArraymove(anytype *str1, const anytype *str2, size_t cnt) 798 799 Not Collective 800 801 Input Parameters: 802 + str1 - First array 803 . str2 - Second array 804 - cnt - Count of the array, not in bytes, but number of entries in the arrays 805 806 Level: intermediate 807 808 Notes: 809 This routine is a preferred replacement to `PetscMemmove()` 810 811 The arrays must be of the same type 812 813 .seealso: `PetscMemcpy()`, `PetscMemcmp()`, `PetscArrayzero()`, `PetscMemzero()`, `PetscArraycpy()`, `PetscMemmove()`, `PetscArraycmp()`, `PetscStrallocpy()` 814 M*/ 815 #define PetscArraymove(str1, str2, cnt) ((sizeof(*(str1)) == sizeof(*(str2))) ? PetscMemmove((str1), (str2), (size_t)(cnt) * sizeof(*(str1))) : PETSC_ERR_ARG_SIZ) 816 817 /*MC 818 PetscArraycpy - Copies from one array in memory to another 819 820 Synopsis: 821 #include <petscstring.h> 822 PetscErrorCode PetscArraycpy(anytype *str1, const anytype *str2, size_t cnt) 823 824 Not Collective 825 826 Input Parameters: 827 + str1 - First array (destination) 828 . str2 - Second array (source) 829 - cnt - Count of the array, not in bytes, but number of entries in the arrays 830 831 Level: intermediate 832 833 Notes: 834 This routine is a preferred replacement to `PetscMemcpy()` 835 836 The arrays must be of the same type 837 838 .seealso: `PetscMemcpy()`, `PetscMemcmp()`, `PetscArrayzero()`, `PetscMemzero()`, `PetscArraymove()`, `PetscMemmove()`, `PetscArraycmp()`, `PetscStrallocpy()` 839 M*/ 840 #define PetscArraycpy(str1, str2, cnt) ((sizeof(*(str1)) == sizeof(*(str2))) ? PetscMemcpy((str1), (str2), (size_t)(cnt) * sizeof(*(str1))) : PETSC_ERR_ARG_SIZ) 841 842 /*MC 843 PetscArrayzero - Zeros an array in memory. 844 845 Synopsis: 846 #include <petscstring.h> 847 PetscErrorCode PetscArrayzero(anytype *str1, size_t cnt) 848 849 Not Collective 850 851 Input Parameters: 852 + str1 - array 853 - cnt - Count of the array, not in bytes, but number of entries in the array 854 855 Level: intermediate 856 857 Note: 858 This routine is a preferred replacement to `PetscMemzero()` 859 860 .seealso: `PetscMemcpy()`, `PetscMemcmp()`, `PetscMemzero()`, `PetscArraycmp()`, `PetscArraycpy()`, `PetscMemmove()`, `PetscStrallocpy()`, `PetscArraymove()` 861 M*/ 862 #define PetscArrayzero(str1, cnt) PetscMemzero((str1), ((size_t)(cnt)) * sizeof(*(str1))) 863