1 /* 2 We define the string operations here. The reason we just do not use 3 the standard string routines in the PETSc code is that on some machines 4 they are broken or have the wrong prototypes. 5 6 */ 7 #include <petsc/private/petscimpl.h> /*I "petscsys.h" I*/ 8 #if defined(PETSC_HAVE_STRINGS_H) 9 # include <strings.h> /* strcasecmp */ 10 #endif 11 12 /*@C 13 PetscStrToArray - Separates a string by a character (for example ' ' or '\n') and creates an array of strings 14 15 Not Collective 16 17 Input Parameters: 18 + s - pointer to string 19 - sp - separator character 20 21 Output Parameters: 22 + argc - the number of entries in the array 23 - args - an array of the entries with a null at the end 24 25 Level: intermediate 26 27 Notes: 28 this may be called before PetscInitialize() or after PetscFinalize() 29 30 Not for use in Fortran 31 32 Developer Notes: 33 Using raw malloc() and does not call error handlers since this may be used before PETSc is initialized. Used 34 to generate argc, args arguments passed to MPI_Init() 35 36 .seealso: `PetscStrToArrayDestroy()`, `PetscToken`, `PetscTokenCreate()` 37 38 @*/ 39 PetscErrorCode PetscStrToArray(const char s[], char sp, int *argc, char ***args) 40 { 41 int i,j,n,*lens,cnt = 0; 42 PetscBool flg = PETSC_FALSE; 43 44 if (!s) n = 0; 45 else n = strlen(s); 46 *argc = 0; 47 *args = NULL; 48 for (; n>0; n--) { /* remove separator chars at the end - and will empty the string if all chars are separator chars */ 49 if (s[n-1] != sp) break; 50 } 51 if (!n) return 0; 52 for (i=0; i<n; i++) { 53 if (s[i] != sp) break; 54 } 55 for (;i<n+1; i++) { 56 if ((s[i] == sp || s[i] == 0) && !flg) {flg = PETSC_TRUE; (*argc)++;} 57 else if (s[i] != sp) {flg = PETSC_FALSE;} 58 } 59 (*args) = (char**) malloc(((*argc)+1)*sizeof(char*)); if (!*args) return PETSC_ERR_MEM; 60 lens = (int*) malloc((*argc)*sizeof(int)); if (!lens) return PETSC_ERR_MEM; 61 for (i=0; i<*argc; i++) lens[i] = 0; 62 63 *argc = 0; 64 for (i=0; i<n; i++) { 65 if (s[i] != sp) break; 66 } 67 for (;i<n+1; i++) { 68 if ((s[i] == sp || s[i] == 0) && !flg) {flg = PETSC_TRUE; (*argc)++;} 69 else if (s[i] != sp) {lens[*argc]++;flg = PETSC_FALSE;} 70 } 71 72 for (i=0; i<*argc; i++) { 73 (*args)[i] = (char*) malloc((lens[i]+1)*sizeof(char)); 74 if (!(*args)[i]) { 75 free(lens); 76 for (j=0; j<i; j++) free((*args)[j]); 77 free(*args); 78 return PETSC_ERR_MEM; 79 } 80 } 81 free(lens); 82 (*args)[*argc] = NULL; 83 84 *argc = 0; 85 for (i=0; i<n; i++) { 86 if (s[i] != sp) break; 87 } 88 for (;i<n+1; i++) { 89 if ((s[i] == sp || s[i] == 0) && !flg) {flg = PETSC_TRUE; (*args)[*argc][cnt++] = 0; (*argc)++; cnt = 0;} 90 else if (s[i] != sp && s[i] != 0) {(*args)[*argc][cnt++] = s[i]; flg = PETSC_FALSE;} 91 } 92 return 0; 93 } 94 95 /*@C 96 PetscStrToArrayDestroy - Frees array created with PetscStrToArray(). 97 98 Not Collective 99 100 Output Parameters: 101 + argc - the number of arguments 102 - args - the array of arguments 103 104 Level: intermediate 105 106 Notes: 107 This may be called before PetscInitialize() or after PetscFinalize() 108 109 Not for use in Fortran 110 111 .seealso: `PetscStrToArray()` 112 113 @*/ 114 PetscErrorCode PetscStrToArrayDestroy(int argc, char **args) 115 { 116 for (int i = 0; i < argc; ++i) free(args[i]); 117 if (args) free(args); 118 return 0; 119 } 120 121 /*@C 122 PetscStrlen - Gets length of a string 123 124 Not Collective 125 126 Input Parameters: 127 . s - pointer to string 128 129 Output Parameter: 130 . len - length in bytes 131 132 Level: intermediate 133 134 Note: 135 This routine is analogous to strlen(). 136 137 Null string returns a length of zero 138 139 Not for use in Fortran 140 141 @*/ 142 PetscErrorCode PetscStrlen(const char s[], size_t *len) 143 { 144 PetscFunctionBegin; 145 *len = s ? strlen(s) : 0; 146 PetscFunctionReturn(0); 147 } 148 149 /*@C 150 PetscStrallocpy - Allocates space to hold a copy of a string then copies the string 151 152 Not Collective 153 154 Input Parameters: 155 . s - pointer to string 156 157 Output Parameter: 158 . t - the copied string 159 160 Level: intermediate 161 162 Note: 163 Null string returns a new null string 164 165 Not for use in Fortran 166 167 Warning: If t has previously been allocated then that memory is lost, you may need to PetscFree() 168 the array before calling this routine. 169 170 .seealso: `PetscStrArrayallocpy()`, `PetscStrcpy()`, `PetscStrNArrayallocpy()` 171 172 @*/ 173 PetscErrorCode PetscStrallocpy(const char s[], char *t[]) 174 { 175 char *tmp = NULL; 176 177 PetscFunctionBegin; 178 if (s) { 179 size_t len; 180 181 PetscCall(PetscStrlen(s,&len)); 182 PetscCall(PetscMalloc1(1+len,&tmp)); 183 PetscCall(PetscStrcpy(tmp,s)); 184 } 185 *t = tmp; 186 PetscFunctionReturn(0); 187 } 188 189 /*@C 190 PetscStrArrayallocpy - Allocates space to hold a copy of an array of strings then copies the strings 191 192 Not Collective 193 194 Input Parameters: 195 . s - pointer to array of strings (final string is a null) 196 197 Output Parameter: 198 . t - the copied array string 199 200 Level: intermediate 201 202 Note: 203 Not for use in Fortran 204 205 Warning: If t has previously been allocated then that memory is lost, you may need to PetscStrArrayDestroy() 206 the array before calling this routine. 207 208 .seealso: `PetscStrallocpy()`, `PetscStrArrayDestroy()`, `PetscStrNArrayallocpy()` 209 210 @*/ 211 PetscErrorCode PetscStrArrayallocpy(const char *const *list, char ***t) 212 { 213 PetscInt n = 0; 214 215 PetscFunctionBegin; 216 while (list[n++]) ; 217 PetscCall(PetscMalloc1(n+1,t)); 218 for (PetscInt i=0; i<n; i++) PetscCall(PetscStrallocpy(list[i],(*t)+i)); 219 (*t)[n] = NULL; 220 PetscFunctionReturn(0); 221 } 222 223 /*@C 224 PetscStrArrayDestroy - Frees array of strings created with PetscStrArrayallocpy(). 225 226 Not Collective 227 228 Output Parameters: 229 . list - array of strings 230 231 Level: intermediate 232 233 Notes: 234 Not for use in Fortran 235 236 .seealso: `PetscStrArrayallocpy()` 237 238 @*/ 239 PetscErrorCode PetscStrArrayDestroy(char ***list) 240 { 241 PetscInt n = 0; 242 243 PetscFunctionBegin; 244 if (!*list) PetscFunctionReturn(0); 245 while ((*list)[n]) { 246 PetscCall(PetscFree((*list)[n])); 247 ++n; 248 } 249 PetscCall(PetscFree(*list)); 250 PetscFunctionReturn(0); 251 } 252 253 /*@C 254 PetscStrNArrayallocpy - Allocates space to hold a copy of an array of strings then copies the strings 255 256 Not Collective 257 258 Input Parameters: 259 + n - the number of string entries 260 - s - pointer to array of strings 261 262 Output Parameter: 263 . t - the copied array string 264 265 Level: intermediate 266 267 Note: 268 Not for use in Fortran 269 270 .seealso: `PetscStrallocpy()`, `PetscStrArrayallocpy()`, `PetscStrNArrayDestroy()` 271 272 @*/ 273 PetscErrorCode PetscStrNArrayallocpy(PetscInt n, const char *const *list, char ***t) 274 { 275 PetscFunctionBegin; 276 PetscCall(PetscMalloc1(n,t)); 277 for (PetscInt i=0; i<n; i++) PetscCall(PetscStrallocpy(list[i],(*t)+i)); 278 PetscFunctionReturn(0); 279 } 280 281 /*@C 282 PetscStrNArrayDestroy - Frees array of strings created with PetscStrArrayallocpy(). 283 284 Not Collective 285 286 Output Parameters: 287 + n - number of string entries 288 - list - array of strings 289 290 Level: intermediate 291 292 Notes: 293 Not for use in Fortran 294 295 .seealso: `PetscStrArrayallocpy()` 296 297 @*/ 298 PetscErrorCode PetscStrNArrayDestroy(PetscInt n, char ***list) 299 { 300 PetscFunctionBegin; 301 if (!*list) PetscFunctionReturn(0); 302 for (PetscInt i=0; i<n; i++) PetscCall(PetscFree((*list)[i])); 303 PetscCall(PetscFree(*list)); 304 PetscFunctionReturn(0); 305 } 306 307 /*@C 308 PetscStrcpy - Copies a string 309 310 Not Collective 311 312 Input Parameters: 313 . t - pointer to string 314 315 Output Parameter: 316 . s - the copied string 317 318 Level: intermediate 319 320 Notes: 321 Null string returns a string starting with zero 322 323 Not for use in Fortran 324 325 It is recommended you use PetscStrncpy() instead of this routine 326 327 .seealso: `PetscStrncpy()`, `PetscStrcat()`, `PetscStrlcat()` 328 329 @*/ 330 331 PetscErrorCode PetscStrcpy(char s[], const char t[]) 332 { 333 PetscFunctionBegin; 334 if (t) { 335 PetscValidCharPointer(s,1); 336 PetscValidCharPointer(t,2); 337 strcpy(s,t); 338 } else if (s) s[0] = 0; 339 PetscFunctionReturn(0); 340 } 341 342 /*@C 343 PetscStrncpy - Copies a string up to a certain length 344 345 Not Collective 346 347 Input Parameters: 348 + t - pointer to string 349 - n - the length to copy 350 351 Output Parameter: 352 . s - the copied string 353 354 Level: intermediate 355 356 Note: 357 Null string returns a string starting with zero 358 359 If the string that is being copied is of length n or larger then the entire string is not 360 copied and the final location of s is set to NULL. This is different then the behavior of 361 strncpy() which leaves s non-terminated if there is not room for the entire string. 362 363 Developers Note: Should this be PetscStrlcpy() to reflect its behavior which is like strlcpy() not strncpy() 364 365 .seealso: `PetscStrcpy()`, `PetscStrcat()`, `PetscStrlcat()` 366 367 @*/ 368 PetscErrorCode PetscStrncpy(char s[], const char t[], size_t n) 369 { 370 PetscFunctionBegin; 371 if (s) PetscCheck(n,PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Requires an output string of length at least 1 to hold the termination character"); 372 if (t) { 373 PetscValidCharPointer(s,1); 374 if (n > 1) { 375 strncpy(s,t,n-1); 376 s[n-1] = '\0'; 377 } else { 378 s[0] = '\0'; 379 } 380 } else if (s) s[0] = 0; 381 PetscFunctionReturn(0); 382 } 383 384 /*@C 385 PetscStrcat - Concatenates a string onto a given string 386 387 Not Collective 388 389 Input Parameters: 390 + s - string to be added to 391 - t - pointer to string to be added to end 392 393 Level: intermediate 394 395 Notes: 396 Not for use in Fortran 397 398 It is recommended you use PetscStrlcat() instead of this routine 399 400 .seealso: `PetscStrcpy()`, `PetscStrncpy()`, `PetscStrlcat()` 401 402 @*/ 403 PetscErrorCode PetscStrcat(char s[], const char t[]) 404 { 405 PetscFunctionBegin; 406 if (!t) PetscFunctionReturn(0); 407 PetscValidCharPointer(s,1); 408 PetscValidCharPointer(t,2); 409 strcat(s,t); 410 PetscFunctionReturn(0); 411 } 412 413 /*@C 414 PetscStrlcat - Concatenates a string onto a given string, up to a given length 415 416 Not Collective 417 418 Input Parameters: 419 + s - pointer to string to be added to at end 420 . t - string to be added 421 - n - length of the original allocated string 422 423 Level: intermediate 424 425 Notes: 426 Not for use in Fortran 427 428 Unlike the system call strncat(), the length passed in is the length of the 429 original allocated space, not the length of the left-over space. This is 430 similar to the BSD system call strlcat(). 431 432 .seealso: `PetscStrcpy()`, `PetscStrncpy()`, `PetscStrcat()` 433 434 @*/ 435 PetscErrorCode PetscStrlcat(char s[], const char t[], size_t n) 436 { 437 size_t len; 438 439 PetscFunctionBegin; 440 if (!t) PetscFunctionReturn(0); 441 PetscValidCharPointer(s,1); 442 PetscValidCharPointer(t,2); 443 PetscCheck(n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"String buffer length must be positive"); 444 PetscCall(PetscStrlen(t,&len)); 445 strncat(s,t,n - len); 446 s[n-1] = 0; 447 PetscFunctionReturn(0); 448 } 449 450 void PetscStrcmpNoError(const char a[], const char b[], PetscBool *flg) 451 { 452 if (!a && !b) *flg = PETSC_TRUE; 453 else if (!a || !b) *flg = PETSC_FALSE; 454 else *flg = strcmp(a,b) ? PETSC_FALSE : PETSC_TRUE; 455 } 456 457 /*@C 458 PetscBasename - returns a pointer to the last entry of a / seperated directory path 459 460 Not Collective 461 462 Input Parameter: 463 . a - pointer to string 464 465 Level: intermediate 466 467 Notes: 468 Not for use in Fortran 469 470 .seealso: `PetscStrgrt()`, `PetscStrncmp()`, `PetscStrcasecmp()`, `PetscStrrchr()`,`PetscStrcmp()`,`PetscStrstr()`, 471 `PetscTokenCreate()`, `PetscStrToArray()`, `PetscStrInList()` 472 @*/ 473 const char *PetscBasename(const char a[]) 474 { 475 const char *ptr; 476 477 if (PetscStrrchr(a,'/',(char **)&ptr)) ptr = NULL; 478 return ptr; 479 } 480 481 /*@C 482 PetscStrcmp - Compares two strings, 483 484 Not Collective 485 486 Input Parameters: 487 + a - pointer to string first string 488 - b - pointer to second string 489 490 Output Parameter: 491 . flg - PETSC_TRUE if the two strings are equal 492 493 Level: intermediate 494 495 Notes: 496 Not for use in Fortran 497 498 .seealso: `PetscStrgrt()`, `PetscStrncmp()`, `PetscStrcasecmp()` 499 @*/ 500 PetscErrorCode PetscStrcmp(const char a[],const char b[],PetscBool *flg) 501 { 502 PetscFunctionBegin; 503 PetscValidBoolPointer(flg,3); 504 if (!a && !b) *flg = PETSC_TRUE; 505 else if (!a || !b) *flg = PETSC_FALSE; 506 else *flg = (PetscBool)!strcmp(a,b); 507 PetscFunctionReturn(0); 508 } 509 510 /*@C 511 PetscStrgrt - If first string is greater than the second 512 513 Not Collective 514 515 Input Parameters: 516 + a - pointer to first string 517 - b - pointer to second string 518 519 Output Parameter: 520 . flg - if the first string is greater 521 522 Notes: 523 Null arguments are ok, a null string is considered smaller than 524 all others 525 526 Not for use in Fortran 527 528 Level: intermediate 529 530 .seealso: `PetscStrcmp()`, `PetscStrncmp()`, `PetscStrcasecmp()` 531 532 @*/ 533 PetscErrorCode PetscStrgrt(const char a[], const char b[], PetscBool *t) 534 { 535 PetscFunctionBegin; 536 PetscValidBoolPointer(t,3); 537 if (!a && !b) *t = PETSC_FALSE; 538 else if (a && !b) *t = PETSC_TRUE; 539 else if (!a && b) *t = PETSC_FALSE; 540 else { 541 PetscValidCharPointer(a,1); 542 PetscValidCharPointer(b,2); 543 *t = strcmp(a,b) > 0 ? PETSC_TRUE : PETSC_FALSE; 544 } 545 PetscFunctionReturn(0); 546 } 547 548 /*@C 549 PetscStrcasecmp - Returns true if the two strings are the same 550 except possibly for case. 551 552 Not Collective 553 554 Input Parameters: 555 + a - pointer to first string 556 - b - pointer to second string 557 558 Output Parameter: 559 . flg - if the two strings are the same 560 561 Notes: 562 Null arguments are ok 563 564 Not for use in Fortran 565 566 Level: intermediate 567 568 .seealso: `PetscStrcmp()`, `PetscStrncmp()`, `PetscStrgrt()` 569 570 @*/ 571 PetscErrorCode PetscStrcasecmp(const char a[], const char b[], PetscBool *t) 572 { 573 int c; 574 575 PetscFunctionBegin; 576 PetscValidBoolPointer(t,3); 577 if (!a && !b) c = 0; 578 else if (!a || !b) c = 1; 579 #if defined(PETSC_HAVE_STRCASECMP) 580 else c = strcasecmp(a,b); 581 #elif defined(PETSC_HAVE_STRICMP) 582 else c = stricmp(a,b); 583 #else 584 else { 585 char *aa,*bb; 586 PetscCall(PetscStrallocpy(a,&aa)); 587 PetscCall(PetscStrallocpy(b,&bb)); 588 PetscCall(PetscStrtolower(aa)); 589 PetscCall(PetscStrtolower(bb)); 590 PetscCall(PetscStrcmp(aa,bb,t)); 591 PetscCall(PetscFree(aa)); 592 PetscCall(PetscFree(bb)); 593 PetscFunctionReturn(0); 594 } 595 #endif 596 *t = c ? PETSC_FALSE : PETSC_TRUE; 597 PetscFunctionReturn(0); 598 } 599 600 /*@C 601 PetscStrncmp - Compares two strings, up to a certain length 602 603 Not Collective 604 605 Input Parameters: 606 + a - pointer to first string 607 . b - pointer to second string 608 - n - length to compare up to 609 610 Output Parameter: 611 . t - if the two strings are equal 612 613 Level: intermediate 614 615 Notes: 616 Not for use in Fortran 617 618 .seealso: `PetscStrgrt()`, `PetscStrcmp()`, `PetscStrcasecmp()` 619 620 @*/ 621 PetscErrorCode PetscStrncmp(const char a[], const char b[], size_t n, PetscBool *t) 622 { 623 PetscFunctionBegin; 624 if (n) { 625 PetscValidCharPointer(a,1); 626 PetscValidCharPointer(b,2); 627 } 628 PetscValidBoolPointer(t,4); 629 *t = strncmp(a,b,n) ? PETSC_FALSE : PETSC_TRUE; 630 PetscFunctionReturn(0); 631 } 632 633 /*@C 634 PetscStrchr - Locates first occurrence of a character in a string 635 636 Not Collective 637 638 Input Parameters: 639 + a - pointer to string 640 - b - character 641 642 Output Parameter: 643 . c - location of occurrence, NULL if not found 644 645 Level: intermediate 646 647 Notes: 648 Not for use in Fortran 649 650 @*/ 651 PetscErrorCode PetscStrchr(const char a[], char b, char *c[]) 652 { 653 PetscFunctionBegin; 654 PetscValidCharPointer(a,1); 655 PetscValidPointer(c,3); 656 *c = (char*)strchr(a,b); 657 PetscFunctionReturn(0); 658 } 659 660 /*@C 661 PetscStrrchr - Locates one location past the last occurrence of a character in a string, 662 if the character is not found then returns entire string 663 664 Not Collective 665 666 Input Parameters: 667 + a - pointer to string 668 - b - character 669 670 Output Parameter: 671 . tmp - location of occurrence, a if not found 672 673 Level: intermediate 674 675 Notes: 676 Not for use in Fortran 677 678 @*/ 679 PetscErrorCode PetscStrrchr(const char a[], char b, char *tmp[]) 680 { 681 PetscFunctionBegin; 682 PetscValidCharPointer(a,1); 683 PetscValidPointer(tmp,3); 684 *tmp = (char*)strrchr(a,b); 685 if (!*tmp) *tmp = (char*)a; 686 else *tmp = *tmp + 1; 687 PetscFunctionReturn(0); 688 } 689 690 /*@C 691 PetscStrtolower - Converts string to lower case 692 693 Not Collective 694 695 Input Parameters: 696 . a - pointer to string 697 698 Level: intermediate 699 700 Notes: 701 Not for use in Fortran 702 703 @*/ 704 PetscErrorCode PetscStrtolower(char a[]) 705 { 706 PetscFunctionBegin; 707 PetscValidCharPointer(a,1); 708 while (*a) { 709 if (*a >= 'A' && *a <= 'Z') *a += 'a' - 'A'; 710 a++; 711 } 712 PetscFunctionReturn(0); 713 } 714 715 /*@C 716 PetscStrtoupper - Converts string to upper case 717 718 Not Collective 719 720 Input Parameters: 721 . a - pointer to string 722 723 Level: intermediate 724 725 Notes: 726 Not for use in Fortran 727 728 @*/ 729 PetscErrorCode PetscStrtoupper(char a[]) 730 { 731 PetscFunctionBegin; 732 PetscValidCharPointer(a,1); 733 while (*a) { 734 if (*a >= 'a' && *a <= 'z') *a += 'A' - 'a'; 735 a++; 736 } 737 PetscFunctionReturn(0); 738 } 739 740 /*@C 741 PetscStrendswith - Determines if a string ends with a certain string 742 743 Not Collective 744 745 Input Parameters: 746 + a - pointer to string 747 - b - string to endwith 748 749 Output Parameter: 750 . flg - PETSC_TRUE or PETSC_FALSE 751 752 Notes: 753 Not for use in Fortran 754 755 Level: intermediate 756 757 @*/ 758 PetscErrorCode PetscStrendswith(const char a[], const char b[], PetscBool *flg) 759 { 760 char *test; 761 762 PetscFunctionBegin; 763 PetscValidBoolPointer(flg,3); 764 *flg = PETSC_FALSE; 765 PetscCall(PetscStrrstr(a,b,&test)); 766 if (test) { 767 size_t na,nb; 768 769 PetscCall(PetscStrlen(a,&na)); 770 PetscCall(PetscStrlen(b,&nb)); 771 if (a+na-nb == test) *flg = PETSC_TRUE; 772 } 773 PetscFunctionReturn(0); 774 } 775 776 /*@C 777 PetscStrbeginswith - Determines if a string begins with a certain string 778 779 Not Collective 780 781 Input Parameters: 782 + a - pointer to string 783 - b - string to begin with 784 785 Output Parameter: 786 . flg - PETSC_TRUE or PETSC_FALSE 787 788 Notes: 789 Not for use in Fortran 790 791 Level: intermediate 792 793 .seealso: `PetscStrendswithwhich()`, `PetscStrendswith()`, `PetscStrtoupper`, `PetscStrtolower()`, `PetscStrrchr()`, `PetscStrchr()`, 794 `PetscStrncmp()`, `PetscStrlen()`, `PetscStrncmp()`, `PetscStrcmp()` 795 796 @*/ 797 PetscErrorCode PetscStrbeginswith(const char a[], const char b[], PetscBool *flg) 798 { 799 char *test; 800 801 PetscFunctionBegin; 802 PetscValidCharPointer(a,1); 803 PetscValidCharPointer(b,2); 804 PetscValidBoolPointer(flg,3); 805 *flg = PETSC_FALSE; 806 PetscCall(PetscStrrstr(a,b,&test)); 807 if (test && (test == a)) *flg = PETSC_TRUE; 808 PetscFunctionReturn(0); 809 } 810 811 /*@C 812 PetscStrendswithwhich - Determines if a string ends with one of several possible strings 813 814 Not Collective 815 816 Input Parameters: 817 + a - pointer to string 818 - bs - strings to end with (last entry must be NULL) 819 820 Output Parameter: 821 . cnt - the index of the string it ends with or the index of NULL 822 823 Notes: 824 Not for use in Fortran 825 826 Level: intermediate 827 828 @*/ 829 PetscErrorCode PetscStrendswithwhich(const char a[], const char *const *bs, PetscInt *cnt) 830 { 831 PetscFunctionBegin; 832 PetscValidPointer(bs,2); 833 PetscValidIntPointer(cnt,3); 834 *cnt = 0; 835 while (bs[*cnt]) { 836 PetscBool flg; 837 838 PetscCall(PetscStrendswith(a,bs[*cnt],&flg)); 839 if (flg) PetscFunctionReturn(0); 840 ++(*cnt); 841 } 842 PetscFunctionReturn(0); 843 } 844 845 /*@C 846 PetscStrrstr - Locates last occurrence of string in another string 847 848 Not Collective 849 850 Input Parameters: 851 + a - pointer to string 852 - b - string to find 853 854 Output Parameter: 855 . tmp - location of occurrence 856 857 Notes: 858 Not for use in Fortran 859 860 Level: intermediate 861 862 @*/ 863 PetscErrorCode PetscStrrstr(const char a[], const char b[], char *tmp[]) 864 { 865 const char *ltmp = NULL; 866 867 PetscFunctionBegin; 868 PetscValidCharPointer(a,1); 869 PetscValidCharPointer(b,2); 870 PetscValidPointer(tmp,3); 871 while (a) { 872 a = (char*)strstr(a,b); 873 if (a) ltmp = a++; 874 } 875 *tmp = (char*)ltmp; 876 PetscFunctionReturn(0); 877 } 878 879 /*@C 880 PetscStrstr - Locates first occurrence of string in another string 881 882 Not Collective 883 884 Input Parameters: 885 + haystack - string to search 886 - needle - string to find 887 888 Output Parameter: 889 . tmp - location of occurrence, is a NULL if the string is not found 890 891 Notes: 892 Not for use in Fortran 893 894 Level: intermediate 895 896 @*/ 897 PetscErrorCode PetscStrstr(const char haystack[],const char needle[],char *tmp[]) 898 { 899 PetscFunctionBegin; 900 PetscValidCharPointer(haystack,1); 901 PetscValidCharPointer(needle,2); 902 PetscValidPointer(tmp,3); 903 *tmp = (char*)strstr(haystack,needle); 904 PetscFunctionReturn(0); 905 } 906 907 struct _p_PetscToken {char token;char *array;char *current;}; 908 909 /*@C 910 PetscTokenFind - Locates next "token" in a string 911 912 Not Collective 913 914 Input Parameters: 915 . a - pointer to token 916 917 Output Parameter: 918 . result - location of occurrence, NULL if not found 919 920 Notes: 921 922 This version is different from the system version in that 923 it allows you to pass a read-only string into the function. 924 925 This version also treats all characters etc. inside a double quote " 926 as a single token. 927 928 For example if the separator character is + and the string is xxxx+y then the first fine will return a pointer to a null terminated xxxx and the 929 second will return a null terminated y 930 931 If the separator character is + and the string is xxxx then the first and only token found will be a pointer to a null terminated xxxx 932 933 Not for use in Fortran 934 935 Level: intermediate 936 937 .seealso: `PetscTokenCreate()`, `PetscTokenDestroy()` 938 @*/ 939 PetscErrorCode PetscTokenFind(PetscToken a, char *result[]) 940 { 941 char *ptr,token; 942 943 PetscFunctionBegin; 944 PetscValidPointer(a,1); 945 PetscValidPointer(result,2); 946 *result = ptr = a->current; 947 if (ptr && !*ptr) {*result = NULL; PetscFunctionReturn(0);} 948 token = a->token; 949 if (ptr && (*ptr == '"')) {token = '"';(*result)++;ptr++;} 950 while (ptr) { 951 if (*ptr == token) { 952 *ptr++ = 0; 953 while (*ptr == a->token) ptr++; 954 a->current = ptr; 955 break; 956 } 957 if (!*ptr) { 958 a->current = NULL; 959 break; 960 } 961 ptr++; 962 } 963 PetscFunctionReturn(0); 964 } 965 966 /*@C 967 PetscTokenCreate - Creates a PetscToken used to find tokens in a string 968 969 Not Collective 970 971 Input Parameters: 972 + string - the string to look in 973 - b - the separator character 974 975 Output Parameter: 976 . t- the token object 977 978 Notes: 979 980 This version is different from the system version in that 981 it allows you to pass a read-only string into the function. 982 983 Not for use in Fortran 984 985 Level: intermediate 986 987 .seealso: `PetscTokenFind()`, `PetscTokenDestroy()` 988 @*/ 989 PetscErrorCode PetscTokenCreate(const char a[], const char b, PetscToken *t) 990 { 991 PetscFunctionBegin; 992 PetscValidCharPointer(a,1); 993 PetscValidPointer(t,3); 994 PetscCall(PetscNew(t)); 995 PetscCall(PetscStrallocpy(a,&(*t)->array)); 996 997 (*t)->current = (*t)->array; 998 (*t)->token = b; 999 PetscFunctionReturn(0); 1000 } 1001 1002 /*@C 1003 PetscTokenDestroy - Destroys a PetscToken 1004 1005 Not Collective 1006 1007 Input Parameters: 1008 . a - pointer to token 1009 1010 Level: intermediate 1011 1012 Notes: 1013 Not for use in Fortran 1014 1015 .seealso: `PetscTokenCreate()`, `PetscTokenFind()` 1016 @*/ 1017 PetscErrorCode PetscTokenDestroy(PetscToken *a) 1018 { 1019 PetscFunctionBegin; 1020 if (!*a) PetscFunctionReturn(0); 1021 PetscCall(PetscFree((*a)->array)); 1022 PetscCall(PetscFree(*a)); 1023 PetscFunctionReturn(0); 1024 } 1025 1026 /*@C 1027 PetscStrInList - search string in character-delimited list 1028 1029 Not Collective 1030 1031 Input Parameters: 1032 + str - the string to look for 1033 . list - the list to search in 1034 - sep - the separator character 1035 1036 Output Parameter: 1037 . found - whether str is in list 1038 1039 Level: intermediate 1040 1041 Notes: 1042 Not for use in Fortran 1043 1044 .seealso: `PetscTokenCreate()`, `PetscTokenFind()`, `PetscStrcmp()` 1045 @*/ 1046 PetscErrorCode PetscStrInList(const char str[], const char list[], char sep, PetscBool *found) 1047 { 1048 PetscToken token; 1049 char *item; 1050 1051 PetscFunctionBegin; 1052 PetscValidBoolPointer(found,4); 1053 *found = PETSC_FALSE; 1054 PetscCall(PetscTokenCreate(list,sep,&token)); 1055 PetscCall(PetscTokenFind(token,&item)); 1056 while (item) { 1057 PetscCall(PetscStrcmp(str,item,found)); 1058 if (*found) break; 1059 PetscCall(PetscTokenFind(token,&item)); 1060 } 1061 PetscCall(PetscTokenDestroy(&token)); 1062 PetscFunctionReturn(0); 1063 } 1064 1065 /*@C 1066 PetscGetPetscDir - Gets the directory PETSc is installed in 1067 1068 Not Collective 1069 1070 Output Parameter: 1071 . dir - the directory 1072 1073 Level: developer 1074 1075 Notes: 1076 Not for use in Fortran 1077 1078 @*/ 1079 PetscErrorCode PetscGetPetscDir(const char *dir[]) 1080 { 1081 PetscFunctionBegin; 1082 PetscValidPointer(dir,1); 1083 *dir = PETSC_DIR; 1084 PetscFunctionReturn(0); 1085 } 1086 1087 /*@C 1088 PetscStrreplace - Replaces substrings in string with other substrings 1089 1090 Not Collective 1091 1092 Input Parameters: 1093 + comm - MPI_Comm of processors that are processing the string 1094 . aa - the string to look in 1095 . b - the resulting copy of a with replaced strings (b can be the same as a) 1096 - len - the length of b 1097 1098 Notes: 1099 Replaces ${PETSC_ARCH},${PETSC_DIR},${PETSC_LIB_DIR},${DISPLAY}, 1100 ${HOMEDIRECTORY},${WORKINGDIRECTORY},${USERNAME}, ${HOSTNAME} with appropriate values 1101 as well as any environmental variables. 1102 1103 PETSC_LIB_DIR uses the environmental variable if it exists. PETSC_ARCH and PETSC_DIR use what 1104 PETSc was built with and do not use environmental variables. 1105 1106 Not for use in Fortran 1107 1108 Level: intermediate 1109 1110 @*/ 1111 PetscErrorCode PetscStrreplace(MPI_Comm comm, const char aa[], char b[], size_t len) 1112 { 1113 int i = 0; 1114 size_t l,l1,l2,l3; 1115 char *work,*par,*epar,env[1024],*tfree,*a = (char*)aa; 1116 const char *s[] = {"${PETSC_ARCH}","${PETSC_DIR}","${PETSC_LIB_DIR}","${DISPLAY}","${HOMEDIRECTORY}","${WORKINGDIRECTORY}","${USERNAME}","${HOSTNAME}",NULL}; 1117 char *r[] = {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL}; 1118 PetscBool flag; 1119 static size_t DISPLAY_LENGTH = 265,USER_LENGTH = 256, HOST_LENGTH = 256; 1120 1121 PetscFunctionBegin; 1122 PetscValidCharPointer(aa,2); 1123 PetscValidCharPointer(b,3); 1124 if (aa == b) PetscCall(PetscStrallocpy(aa,(char**)&a)); 1125 PetscCall(PetscMalloc1(len,&work)); 1126 1127 /* get values for replaced variables */ 1128 PetscCall(PetscStrallocpy(PETSC_ARCH,&r[0])); 1129 PetscCall(PetscStrallocpy(PETSC_DIR,&r[1])); 1130 PetscCall(PetscStrallocpy(PETSC_LIB_DIR,&r[2])); 1131 PetscCall(PetscMalloc1(DISPLAY_LENGTH,&r[3])); 1132 PetscCall(PetscMalloc1(PETSC_MAX_PATH_LEN,&r[4])); 1133 PetscCall(PetscMalloc1(PETSC_MAX_PATH_LEN,&r[5])); 1134 PetscCall(PetscMalloc1(USER_LENGTH,&r[6])); 1135 PetscCall(PetscMalloc1(HOST_LENGTH,&r[7])); 1136 PetscCall(PetscGetDisplay(r[3],DISPLAY_LENGTH)); 1137 PetscCall(PetscGetHomeDirectory(r[4],PETSC_MAX_PATH_LEN)); 1138 PetscCall(PetscGetWorkingDirectory(r[5],PETSC_MAX_PATH_LEN)); 1139 PetscCall(PetscGetUserName(r[6],USER_LENGTH)); 1140 PetscCall(PetscGetHostName(r[7],HOST_LENGTH)); 1141 1142 /* replace that are in environment */ 1143 PetscCall(PetscOptionsGetenv(comm,"PETSC_LIB_DIR",env,sizeof(env),&flag)); 1144 if (flag) { 1145 PetscCall(PetscFree(r[2])); 1146 PetscCall(PetscStrallocpy(env,&r[2])); 1147 } 1148 1149 /* replace the requested strings */ 1150 PetscCall(PetscStrncpy(b,a,len)); 1151 while (s[i]) { 1152 PetscCall(PetscStrlen(s[i],&l)); 1153 PetscCall(PetscStrstr(b,s[i],&par)); 1154 while (par) { 1155 *par = 0; 1156 par += l; 1157 1158 PetscCall(PetscStrlen(b,&l1)); 1159 PetscCall(PetscStrlen(r[i],&l2)); 1160 PetscCall(PetscStrlen(par,&l3)); 1161 PetscCheck(l1 + l2 + l3 < len,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"b len is not long enough to hold new values"); 1162 PetscCall(PetscStrncpy(work,b,len)); 1163 PetscCall(PetscStrlcat(work,r[i],len)); 1164 PetscCall(PetscStrlcat(work,par,len)); 1165 PetscCall(PetscStrncpy(b,work,len)); 1166 PetscCall(PetscStrstr(b,s[i],&par)); 1167 } 1168 i++; 1169 } 1170 i = 0; 1171 while (r[i]) { 1172 tfree = (char*)r[i]; 1173 PetscCall(PetscFree(tfree)); 1174 i++; 1175 } 1176 1177 /* look for any other ${xxx} strings to replace from environmental variables */ 1178 PetscCall(PetscStrstr(b,"${",&par)); 1179 while (par) { 1180 *par = 0; 1181 par += 2; 1182 PetscCall(PetscStrncpy(work,b,len)); 1183 PetscCall(PetscStrstr(par,"}",&epar)); 1184 *epar = 0; 1185 epar += 1; 1186 PetscCall(PetscOptionsGetenv(comm,par,env,sizeof(env),&flag)); 1187 PetscCheck(flag,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Substitution string ${%s} not found as environmental variable",par); 1188 PetscCall(PetscStrlcat(work,env,len)); 1189 PetscCall(PetscStrlcat(work,epar,len)); 1190 PetscCall(PetscStrncpy(b,work,len)); 1191 PetscCall(PetscStrstr(b,"${",&par)); 1192 } 1193 PetscCall(PetscFree(work)); 1194 if (aa == b) PetscCall(PetscFree(a)); 1195 PetscFunctionReturn(0); 1196 } 1197 1198 /*@C 1199 PetscEListFind - searches list of strings for given string, using case insensitive matching 1200 1201 Not Collective 1202 1203 Input Parameters: 1204 + n - number of strings in 1205 . list - list of strings to search 1206 - str - string to look for, empty string "" accepts default (first entry in list) 1207 1208 Output Parameters: 1209 + value - index of matching string (if found) 1210 - found - boolean indicating whether string was found (can be NULL) 1211 1212 Notes: 1213 Not for use in Fortran 1214 1215 Level: advanced 1216 @*/ 1217 PetscErrorCode PetscEListFind(PetscInt n, const char *const *list, const char *str, PetscInt *value, PetscBool *found) 1218 { 1219 PetscFunctionBegin; 1220 if (found) { 1221 PetscValidBoolPointer(found,5); 1222 *found = PETSC_FALSE; 1223 } 1224 for (PetscInt i = 0; i < n; ++i) { 1225 PetscBool matched; 1226 1227 PetscCall(PetscStrcasecmp(str,list[i],&matched)); 1228 if (matched || !str[0]) { 1229 if (found) *found = PETSC_TRUE; 1230 *value = i; 1231 break; 1232 } 1233 } 1234 PetscFunctionReturn(0); 1235 } 1236 1237 /*@C 1238 PetscEnumFind - searches enum list of strings for given string, using case insensitive matching 1239 1240 Not Collective 1241 1242 Input Parameters: 1243 + enumlist - list of strings to search, followed by enum name, then enum prefix, then NUL 1244 - str - string to look for 1245 1246 Output Parameters: 1247 + value - index of matching string (if found) 1248 - found - boolean indicating whether string was found (can be NULL) 1249 1250 Notes: 1251 Not for use in Fortran 1252 1253 Level: advanced 1254 @*/ 1255 PetscErrorCode PetscEnumFind(const char *const *enumlist, const char *str, PetscEnum *value, PetscBool *found) 1256 { 1257 PetscInt n = 0,evalue; 1258 PetscBool efound; 1259 1260 PetscFunctionBegin; 1261 PetscValidPointer(enumlist,1); 1262 while (enumlist[n++]) PetscCheck(n <= 50,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"List argument appears to be wrong or have more than 50 entries"); 1263 PetscCheck(n >= 3,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"List argument must have at least two entries: typename and type prefix"); 1264 n -= 3; /* drop enum name, prefix, and null termination */ 1265 PetscCall(PetscEListFind(n,enumlist,str,&evalue,&efound)); 1266 if (efound) { 1267 PetscValidPointer(value,3); 1268 *value = (PetscEnum)evalue; 1269 } 1270 if (found) { 1271 PetscValidBoolPointer(found,4); 1272 *found = efound; 1273 } 1274 PetscFunctionReturn(0); 1275 } 1276