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