Actual source code: str.c

  1: #define PETSC_DLL
  2: /*
  3:     We define the string operations here. The reason we just do not use 
  4:   the standard string routines in the PETSc code is that on some machines 
  5:   they are broken or have the wrong prototypes.

  7: */
 8:  #include petsc.h
 9:  #include petscsys.h
 10: #if defined(PETSC_HAVE_STRING_H)
 11: #include <string.h>
 12: #endif
 13: #if defined(PETSC_HAVE_STRINGS_H)
 14: #include <strings.h>
 15: #endif
 16: #include "petscfix.h"

 20: /*@C
 21:    PetscStrlen - Gets length of a string

 23:    Not Collective

 25:    Input Parameters:
 26: .  s - pointer to string

 28:    Output Parameter:
 29: .  len - length in bytes

 31:    Level: intermediate

 33:    Note:
 34:    This routine is analogous to strlen().

 36:    Null string returns a length of zero

 38:   Concepts: string length
 39:   
 40: @*/
 41: PetscErrorCode  PetscStrlen(const char s[],size_t *len)
 42: {
 44:   if (!s) {
 45:     *len = 0;
 46:   } else {
 47:     *len = strlen(s);
 48:   }
 49:   return(0);
 50: }

 54: /*@C
 55:    PetscStrallocpy - Allocates space to hold a copy of a string then copies the string

 57:    Not Collective

 59:    Input Parameters:
 60: .  s - pointer to string

 62:    Output Parameter:
 63: .  t - the copied string

 65:    Level: intermediate

 67:    Note:
 68:       Null string returns a new null string

 70:   Concepts: string copy
 71:   
 72: @*/
 73: PetscErrorCode  PetscStrallocpy(const char s[],char *t[])
 74: {
 76:   size_t         len;
 77:   char           *tmp = 0;

 80:   if (s) {
 81:     PetscStrlen(s,&len);
 82:     PetscMalloc((1+len)*sizeof(char),&tmp);
 83:     PetscStrcpy(tmp,s);
 84:   }
 85:   *t = tmp;
 86:   return(0);
 87: }

 91: /*@C
 92:    PetscStrcpy - Copies a string

 94:    Not Collective

 96:    Input Parameters:
 97: .  t - pointer to string

 99:    Output Parameter:
100: .  s - the copied string

102:    Level: intermediate

104:    Note:
105:      Null string returns a string starting with zero

107:   Concepts: string copy
108:   
109: .seealso: PetscStrncpy(), PetscStrcat(), PetscStrncat()

111: @*/
112: PetscErrorCode  PetscStrcpy(char s[],const char t[])
113: {
115:   if (t && !s) {
116:     SETERRQ(PETSC_ERR_ARG_NULL,"Trying to copy string into null pointer");
117:   }
118:   if (t) {strcpy(s,t);}
119:   else if (s) {s[0] = 0;}
120:   return(0);
121: }

125: /*@C
126:    PetscStrncpy - Copies a string up to a certain length

128:    Not Collective

130:    Input Parameters:
131: +  t - pointer to string
132: -  n - the length to copy

134:    Output Parameter:
135: .  s - the copied string

137:    Level: intermediate

139:    Note:
140:      Null string returns a string starting with zero

142:   Concepts: string copy

144: .seealso: PetscStrcpy(), PetscStrcat(), PetscStrncat()
145:   
146: @*/
147: PetscErrorCode  PetscStrncpy(char s[],const char t[],size_t n)
148: {
150:   if (t && !s) {
151:     SETERRQ(PETSC_ERR_ARG_NULL,"Trying to copy string into null pointer");
152:   }
153:   if (t) {strncpy(s,t,n);}
154:   else if (s) {s[0] = 0;}
155:   return(0);
156: }

160: /*@C
161:    PetscStrcat - Concatenates a string onto a given string

163:    Not Collective

165:    Input Parameters:
166: +  s - string to be added to
167: -  t - pointer to string to be added to end

169:    Level: intermediate

171:   Concepts: string copy

173: .seealso: PetscStrcpy(), PetscStrncpy(), PetscStrncat()
174:   
175: @*/
176: PetscErrorCode  PetscStrcat(char s[],const char t[])
177: {
179:   if (!t) return(0);
180:   strcat(s,t);
181:   return(0);
182: }

186: /*@C
187:    PetscStrncat - Concatenates a string onto a given string, up to a given length

189:    Not Collective

191:    Input Parameters:
192: +  s - pointer to string to be added to end
193: .  t - string to be added to
194: .  n - maximum length to copy 

196:    Level: intermediate

198:   Concepts: string copy

200: .seealso: PetscStrcpy(), PetscStrncpy(), PetscStrcat()
201:   
202: @*/
203: PetscErrorCode  PetscStrncat(char s[],const char t[],size_t n)
204: {
206:   strncat(s,t,n);
207:   return(0);
208: }

212: /*@C
213:    PetscStrcmp - Compares two strings,

215:    Not Collective

217:    Input Parameters:
218: +  a - pointer to string first string
219: -  b - pointer to second string

221:    Output Parameter:
222: .  flg - if the two strings are equal

224:    Level: intermediate

226: .seealso: PetscStrgrt(), PetscStrncmp(), PetscStrcasecmp()

228: @*/
229: PetscErrorCode  PetscStrcmp(const char a[],const char b[],PetscTruth *flg)
230: {
231:   int c;

234:   if (!a && !b) {
235:     *flg = PETSC_TRUE;
236:   } else if (!a || !b) {
237:     *flg = PETSC_FALSE;
238:   } else {
239:     c = strcmp(a,b);
240:     if (c) *flg = PETSC_FALSE;
241:     else   *flg = PETSC_TRUE;
242:   }
243:   return(0);
244: }

248: /*@C
249:    PetscStrgrt - If first string is greater than the second

251:    Not Collective

253:    Input Parameters:
254: +  a - pointer to first string
255: -  b - pointer to second string

257:    Output Parameter:
258: .  flg - if the first string is greater

260:    Notes:
261:     Null arguments are ok, a null string is considered smaller than 
262:     all others

264:    Level: intermediate

266: .seealso: PetscStrcmp(), PetscStrncmp(), PetscStrcasecmp()

268: @*/
269: PetscErrorCode  PetscStrgrt(const char a[],const char b[],PetscTruth *t)
270: {
271:   int c;

274:   if (!a && !b) {
275:     *t = PETSC_FALSE;
276:   } else if (a && !b) {
277:     *t = PETSC_TRUE;
278:   } else if (!a && b) {
279:     *t = PETSC_FALSE;
280:   } else {
281:     c = strcmp(a,b);
282:     if (c > 0) *t = PETSC_TRUE;
283:     else       *t = PETSC_FALSE;
284:   }
285:   return(0);
286: }

290: /*@C
291:    PetscStrcasecmp - Returns true if the two strings are the same
292:      except possibly for case.

294:    Not Collective

296:    Input Parameters:
297: +  a - pointer to first string
298: -  b - pointer to second string

300:    Output Parameter:
301: .  flg - if the two strings are the same

303:    Notes:
304:     Null arguments are ok

306:    Level: intermediate

308: .seealso: PetscStrcmp(), PetscStrncmp(), PetscStrgrt()

310: @*/
311: PetscErrorCode  PetscStrcasecmp(const char a[],const char b[],PetscTruth *t)
312: {
313:   int c;

316:   if (!a && !b) c = 0;
317:   else if (!a || !b) c = 1;
318: #if defined(PETSC_HAVE_STRCASECMP)
319:   else c = strcasecmp(a,b);
320: #elif defined(PETSC_HAVE_STRICMP)
321:   else c = stricmp(a,b);
322: #else
323:   else {
324:     char *aa,*bb;
326:     PetscStrallocpy(a,&aa);
327:     PetscStrallocpy(b,&bb);
328:     PetscStrtolower(aa);
329:     PetscStrtolower(bb);
330:     PetscStrcmp(aa,bb,t);
331:     PetscStrfree(aa);
332:     PetscStrfree(bb);
333:     return(0);
334:   }
335: #endif
336:   if (!c) *t = PETSC_TRUE;
337:   else    *t = PETSC_FALSE;
338:   return(0);
339: }



345: /*@C
346:    PetscStrncmp - Compares two strings, up to a certain length

348:    Not Collective

350:    Input Parameters:
351: +  a - pointer to first string
352: .  b - pointer to second string
353: -  n - length to compare up to

355:    Output Parameter:
356: .  t - if the two strings are equal

358:    Level: intermediate

360: .seealso: PetscStrgrt(), PetscStrcmp(), PetscStrcasecmp()

362: @*/
363: PetscErrorCode  PetscStrncmp(const char a[],const char b[],size_t n,PetscTruth *t)
364: {
365:   int c;

368:   c = strncmp(a,b,n);
369:   if (!c) *t = PETSC_TRUE;
370:   else    *t = PETSC_FALSE;
371:   return(0);
372: }

376: /*@C
377:    PetscStrchr - Locates first occurance of a character in a string

379:    Not Collective

381:    Input Parameters:
382: +  a - pointer to string
383: -  b - character

385:    Output Parameter:
386: .  c - location of occurance, PETSC_NULL if not found

388:    Level: intermediate

390: @*/
391: PetscErrorCode  PetscStrchr(const char a[],char b,char *c[])
392: {
394:   *c = (char *)strchr(a,b);
395:   return(0);
396: }

400: /*@C
401:    PetscStrrchr - Locates one location past the last occurance of a character in a string,
402:       if the character is not found then returns entire string

404:    Not Collective

406:    Input Parameters:
407: +  a - pointer to string
408: -  b - character

410:    Output Parameter:
411: .  tmp - location of occurance, a if not found

413:    Level: intermediate

415: @*/
416: PetscErrorCode  PetscStrrchr(const char a[],char b,char *tmp[])
417: {
419:   *tmp = (char *)strrchr(a,b);
420:   if (!*tmp) *tmp = (char*)a; else *tmp = *tmp + 1;
421:   return(0);
422: }

426: /*@C
427:    PetscStrtolower - Converts string to lower case

429:    Not Collective

431:    Input Parameters:
432: .  a - pointer to string

434:    Level: intermediate

436: @*/
437: PetscErrorCode  PetscStrtolower(char a[])
438: {
440:   while (*a) {
441:     if (*a >= 'A' && *a <= 'Z') *a += 'a' - 'A';
442:     a++;
443:   }
444:   return(0);
445: }

447: struct _p_PetscToken {char token;char *array;char *current;};


452: /*@C
453:    PetscTokenFind - Locates next "token" in a string

455:    Not Collective

457:    Input Parameters:
458: .  a - pointer to token

460:    Output Parameter:
461: .  result - location of occurance, PETSC_NULL if not found

463:    Notes:

465:      This version is different from the system version in that
466:   it allows you to pass a read-only string into the function.

468:      This version also treats all characters etc. inside a double quote "
469:    as a single token.

471:    Level: intermediate

473: .seealso: PetscTokenCreate(), PetscTokenDestroy()
474: @*/
475: PetscErrorCode  PetscTokenFind(PetscToken a,char *result[])
476: {
477:   char *ptr = a->current,token;

480:   *result = a->current;
481:   if (ptr && !*ptr) {*result = 0;return(0);}
482:   token = a->token;
483:   if (ptr && (*ptr == '"')) {token = '"';(*result)++;ptr++;}
484:   while (ptr) {
485:     if (*ptr == token) {
486:       *ptr++ = 0;
487:       while (*ptr == a->token) ptr++;
488:       a->current = ptr;
489:       break;
490:     }
491:     if (!*ptr) {
492:       a->current = 0;
493:       break;
494:     }
495:     ptr++;
496:   }
497:   return(0);
498: }

502: /*@C
503:    PetscTokenCreate - Creates a PetscToken used to find tokens in a string

505:    Not Collective

507:    Input Parameters:
508: +  string - the string to look in
509: -  token - the character to look for

511:    Output Parameter:
512: .  a - pointer to token

514:    Notes:

516:      This version is different from the system version in that
517:   it allows you to pass a read-only string into the function.

519:    Level: intermediate

521: .seealso: PetscTokenFind(), PetscTokenDestroy()
522: @*/
523: PetscErrorCode  PetscTokenCreate(const char a[],const char b,PetscToken *t)
524: {

528:   PetscNew(struct _p_PetscToken,t);
529:   PetscStrallocpy(a,&(*t)->array);
530:   (*t)->current = (*t)->array;
531:   (*t)->token   = b;
532:   return(0);
533: }

537: /*@C
538:    PetscTokenDestroy - Destroys a PetscToken

540:    Not Collective

542:    Input Parameters:
543: .  a - pointer to token

545:    Level: intermediate

547: .seealso: PetscTokenCreate(), PetscTokenFind()
548: @*/
549: PetscErrorCode  PetscTokenDestroy(PetscToken a)
550: {

554:   PetscFree(a->array);
555:   PetscFree(a);
556:   return(0);
557: }

561: /*@C
562:    PetscStrrstr - Locates last occurance of string in another string

564:    Not Collective

566:    Input Parameters:
567: +  a - pointer to string
568: -  b - string to find

570:    Output Parameter:
571: .  tmp - location of occurance

573:    Level: intermediate

575: @*/
576: PetscErrorCode  PetscStrrstr(const char a[],const char b[],char *tmp[])
577: {
578:   const char *stmp = a, *ltmp = 0;

581:   while (stmp) {
582:     stmp = (char *)strstr(stmp,b);
583:     if (stmp) {ltmp = stmp;stmp++;}
584:   }
585:   *tmp = (char *)ltmp;
586:   return(0);
587: }

591: /*@C
592:    PetscStrstr - Locates first occurance of string in another string

594:    Not Collective

596:    Input Parameters:
597: +  a - pointer to string
598: -  b - string to find

600:    Output Parameter:
601: .  tmp - location of occurance

603:    Level: intermediate

605: @*/
606: PetscErrorCode  PetscStrstr(const char a[],const char b[],char *tmp[])
607: {
609:   *tmp = (char *)strstr(a,b);
610:   return(0);
611: }

615: /*@C
616:    PetscGetPetscDir - Gets the directory PETSc is installed in

618:    Not Collective

620:    Output Parameter:
621: .  dir - the directory

623:    Level: developer

625: @*/
626: PetscErrorCode  PetscGetPetscDir(const char *dir[])
627: {
629:   *dir = PETSC_DIR;
630:   return(0);
631: }

635: /*@C
636:    PetscStrreplace - Replaces substrings in string with other substrings

638:    Not Collective

640:    Input Parameters:
641: +   comm - MPI_Comm of processors that are processing the string
642: .   aa - the string to look in
643: .   b - the resulting copy of a with replaced strings (b can be the same as a)
644: -   len - the length of b

646:    Notes:
647:       Replaces   ${PETSC_ARCH},${PETSC_DIR},${PETSC_LIB_DIR},${DISPLAY},
648:       ${HOMEDIRECTORY},${WORKINGDIRECTORY},${USERNAME} with appropriate values
649:       as well as any environmental variables.
650:    
651:    Level: intermediate

653: @*/
654: PetscErrorCode  PetscStrreplace(MPI_Comm comm,const char aa[],char b[],size_t len)
655: {
657:   int            i = 0;
658:   size_t         l,l1,l2,l3;
659:   char           *work,*par,*epar,env[1024],*tfree,*a = (char*)aa;
660:   const char     *s[] = {"${PETSC_ARCH}","${PETSC_DIR}","${PETSC_LIB_DIR}","${DISPLAY}","${HOMEDIRECTORY}","${WORKINGDIRECTORY}","${USERNAME}",0};
661:   const char     *r[] = {0,0,0,0,0,0,0,0};
662:   PetscTruth     flag;

665:   if (!a || !b) SETERRQ(PETSC_ERR_ARG_NULL,"a and b strings must be nonnull");
666:   if (aa == b) {
667:     PetscStrallocpy(aa,(char **)&a);
668:   }
669:   PetscMalloc(len*sizeof(char*),&work);

671:   /* get values for replaced variables */
672:   PetscStrallocpy(PETSC_ARCH,(char**)&r[0]);
673:   PetscStrallocpy(PETSC_DIR,(char**)&r[1]);
674:   PetscStrallocpy(PETSC_LIB_DIR,(char**)&r[2]);
675:   PetscMalloc(256*sizeof(char),&r[3]);
676:   PetscMalloc(PETSC_MAX_PATH_LEN*sizeof(char),&r[4]);
677:   PetscMalloc(PETSC_MAX_PATH_LEN*sizeof(char),&r[5]);
678:   PetscMalloc(256*sizeof(char),&r[6]);
679:   PetscGetDisplay((char*)r[3],256);
680:   PetscGetHomeDirectory((char*)r[4],PETSC_MAX_PATH_LEN);
681:   PetscGetWorkingDirectory((char*)r[5],PETSC_MAX_PATH_LEN);
682:   PetscGetUserName((char*)r[6],256);

684:   /* replace that are in environment */
685:   PetscOptionsGetenv(comm,"PETSC_LIB_DIR",env,1024,&flag);
686:   if (flag) {
687:     PetscStrallocpy(env,(char**)&r[2]);
688:   }

690:   /* replace the requested strings */
691:   PetscStrncpy(b,a,len);
692:   while (s[i]) {
693:     PetscStrlen(s[i],&l);
694:     PetscStrstr(b,s[i],&par);
695:     while (par) {
696:       *par  =  0;
697:       par  += l;

699:       PetscStrlen(b,&l1);
700:       PetscStrlen(r[i],&l2);
701:       PetscStrlen(par,&l3);
702:       if (l1 + l2 + l3 >= len) {
703:         SETERRQ(PETSC_ERR_ARG_SIZ,"b len is not long enough to hold new values");
704:       }
705:       PetscStrcpy(work,b);
706:       PetscStrcat(work,r[i]);
707:       PetscStrcat(work,par);
708:       PetscStrncpy(b,work,len);
709:       PetscStrstr(b,s[i],&par);
710:     }
711:     i++;
712:   }
713:   i = 0;
714:   while (r[i]) {
715:     tfree = (char*)r[i];
716:     PetscFree(tfree);
717:     i++;
718:   }

720:   /* look for any other ${xxx} strings to replace from environmental variables */
721:   PetscStrstr(b,"${",&par);
722:   while (par) {
723:     *par = 0;
724:     par += 2;
725:     PetscStrcpy(work,b);
726:     PetscStrstr(par,"}",&epar);
727:     *epar = 0;
728:     epar += 1;
729:     PetscOptionsGetenv(comm,par,env,256,&flag);
730:     if (!flag) {
731:       SETERRQ1(PETSC_ERR_ARG_WRONG,"Substitution string ${%s} not found as environmental variable",par);
732:     }
733:     PetscStrcat(work,env);
734:     PetscStrcat(work,epar);
735:     PetscStrcpy(b,work);
736:     PetscStrstr(b,"${",&par);
737:   }
738:   PetscFree(work);
739:   if (aa == b) {
740:     PetscFree(a);
741:   }
742:   return(0);
743: }

745: /*MC
746:    PetscStrfree - Frees a string (if it is not null)

748:    Not Collective

750:    Synopsis:
751:    PetscErrorCode PetscStrfree(char *s)

753:    Input Parameter:
754: .  s - pointer to string

756:    Level: intermediate

758:   Concepts: string free
759:   
760: .seealso: PetscStrncpy(), PetscStrcat(), PetscStrncat(), PetscStrallocpy()

762: M*/