Update copyright statements and change license to LGPL
[alexxy/gromacs.git] / src / gmxlib / string2.c
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
5  * Copyright (c) 2001-2004, The GROMACS development team,
6  * check out http://www.gromacs.org for more information.
7  * Copyright (c) 2012, by the GROMACS development team, led by
8  * David van der Spoel, Berk Hess, Erik Lindahl, and including many
9  * others, as listed in the AUTHORS file in the top-level source
10  * directory and at http://www.gromacs.org.
11  *
12  * GROMACS is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU Lesser General Public License
14  * as published by the Free Software Foundation; either version 2.1
15  * of the License, or (at your option) any later version.
16  *
17  * GROMACS is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20  * Lesser General Public License for more details.
21  *
22  * You should have received a copy of the GNU Lesser General Public
23  * License along with GROMACS; if not, see
24  * http://www.gnu.org/licenses, or write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
26  *
27  * If you want to redistribute modifications to GROMACS, please
28  * consider that scientific software is very special. Version
29  * control is crucial - bugs must be traceable. We will be happy to
30  * consider code for inclusion in the official distribution, but
31  * derived work must not be called official GROMACS. Details are found
32  * in the README & COPYING files - if they are missing, get the
33  * official version at http://www.gromacs.org.
34  *
35  * To help us fund GROMACS development, we humbly ask that you cite
36  * the research papers on the package. Check out http://www.gromacs.org.
37  */
38 /* This file is completely threadsafe - keep it that way! */
39 #ifdef HAVE_CONFIG_H
40 #include <config.h>
41 #endif
42 #include "visibility.h"
43 #include "gmx_header_config.h"
44
45 #ifdef GMX_CRAY_XT3
46 #undef HAVE_PWD_H
47 #endif
48
49 #include <stdio.h>
50 #include <ctype.h>
51 #include <stdlib.h>
52 #include <errno.h>
53 #include <sys/types.h>
54 #include <time.h>
55
56 #ifdef HAVE_SYS_TIME_H
57 #include <sys/time.h>
58 #endif
59
60
61 #ifdef HAVE_PWD_H
62 #include <pwd.h>
63 #endif
64 #include <time.h>
65 #include <assert.h>
66
67 #include "typedefs.h"
68 #include "smalloc.h"
69 #include "gmx_fatal.h"
70 #include "macros.h"
71 #include "string2.h"
72 #include "futil.h"
73
74 int continuing(char *s)
75 /* strip trailing spaces and if s ends with a CONTINUE remove that too.
76  * returns TRUE if s ends with a CONTINUE, FALSE otherwise.
77  */
78 {
79   int sl;
80   assert(s);
81
82   rtrim(s);
83   sl = strlen(s);
84   if ((sl > 0) && (s[sl-1] == CONTINUE)) {
85     s[sl-1] = 0;
86     return TRUE;
87   }
88   else
89     return FALSE;
90 }
91
92
93
94 char *fgets2(char *line, int n, FILE *stream)
95 /* This routine reads a string from stream of max length n
96  * and zero terminated, without newlines
97  * line should be long enough (>= n)
98  */
99 {
100   char *c;
101   if (fgets(line,n,stream) == NULL) {
102     return NULL;
103   }
104   if ((c=strchr(line,'\n')) != NULL) {
105     *c = '\0';
106   } else {
107     /* A line not ending in a newline can only occur at the end of a file,
108      * or because of n being too small.
109      * Since both cases occur very infrequently, we can check for EOF.
110      */
111     if (!gmx_eof(stream)) {
112       gmx_fatal(FARGS,"An input file contains a line longer than %d characters, while the buffer passed to fgets2 has size %d. The line starts with: '%20.20s'",n,n,line);
113     }
114   }
115   if ((c=strchr(line,'\r')) != NULL) {
116     *c = '\0';
117   }
118
119   return line;
120 }
121
122 void strip_comment (char *line)
123 {
124   char *c;
125
126   if (!line)
127     return;
128
129   /* search for a comment mark and replace it by a zero */
130   if ((c = strchr(line,COMMENTSIGN)) != NULL) 
131     (*c) = 0;
132 }
133
134 void upstring (char *str)
135 {
136   int i;
137
138   for (i=0; (i < (int)strlen(str)); i++) 
139     str[i] = toupper(str[i]);
140 }
141
142 void ltrim (char *str)
143 {
144   char *tr;
145   int i,c;
146
147   if (NULL == str)
148     return;
149
150   c = 0;
151   while (('\0' != str[c]) && isspace(str[c]))
152     c++;
153   if (c > 0) 
154     {
155       for(i=c; ('\0' != str[i]); i++)
156         str[i-c] = str[i];
157       str[i-c] = '\0';
158     }
159 }
160
161 void rtrim (char *str)
162 {
163   int nul;
164
165   if (NULL == str)
166     return;
167
168   nul = strlen(str)-1;
169   while ((nul > 0) && ((str[nul] == ' ') || (str[nul] == '\t')) ) {
170     str[nul] = '\0';
171     nul--;
172   }
173 }
174
175 void trim (char *str)
176 {
177   ltrim (str);
178   rtrim (str);
179 }
180
181 GMX_LIBGMX_EXPORT
182 char *
183 gmx_ctime_r(const time_t *clock,char *buf, int n)
184 {
185     char tmpbuf[STRLEN];
186   
187 #ifdef GMX_NATIVE_WINDOWS
188     /* Windows */
189     ctime_s( tmpbuf, STRLEN, clock );
190 #elif (defined(__sun))
191     /*Solaris*/
192     ctime_r(clock, tmpbuf, n);
193 #else
194     ctime_r(clock,tmpbuf);
195 #endif
196     strncpy(buf,tmpbuf,n-1);
197     buf[n-1]='\0';
198     
199     return buf;
200 }
201           
202 void nice_header (FILE *out,const char *fn)
203 {
204   const char *unk = "onbekend";
205   time_t clock;
206   const char *user=unk;
207   int    gh;
208   uid_t  uid;
209   char   buf[256]="";
210   char   timebuf[STRLEN];
211 #ifdef HAVE_PWD_H
212   struct passwd *pw;
213 #endif
214
215   /* Print a nice header above the file */
216   time(&clock);
217   fprintf (out,"%c\n",COMMENTSIGN);
218   fprintf (out,"%c\tFile '%s' was generated\n",COMMENTSIGN,fn ? fn : unk);
219   
220 #ifdef HAVE_PWD_H
221   uid = getuid();
222   pw  = getpwuid(uid);
223   gh  = gethostname(buf,255);
224   user= pw->pw_name;
225 #else
226   uid = 0;
227   gh  = -1;
228 #endif
229   
230   gmx_ctime_r(&clock,timebuf,STRLEN);
231   fprintf (out,"%c\tBy user: %s (%d)\n",COMMENTSIGN,
232            user ? user : unk,(int) uid);
233   fprintf(out,"%c\tOn host: %s\n",COMMENTSIGN,(gh == 0) ? buf : unk);
234
235   fprintf (out,"%c\tAt date: %s",COMMENTSIGN,timebuf);
236   fprintf (out,"%c\n",COMMENTSIGN);
237 }
238
239
240 int gmx_strcasecmp_min(const char *str1, const char *str2)
241 {
242     char ch1,ch2;
243
244     do
245     {
246         do
247         {
248             ch1=toupper(*(str1++));
249         }
250         while ((ch1=='-') || (ch1=='_'));
251         do
252         {
253             ch2=toupper(*(str2++));
254         }
255         while ((ch2=='-') || (ch2=='_'));
256
257         if (ch1!=ch2) return (ch1-ch2);
258     }
259     while (ch1);
260     return 0;
261 }
262
263 int gmx_strncasecmp_min(const char *str1, const char *str2, int n)
264 {
265     char ch1,ch2;
266     char *stri1, *stri2;
267
268     stri1=(char *)str1;
269     stri2=(char *)str2;
270     do
271     {
272         do
273         {
274             ch1=toupper(*(str1++));
275         }
276         while ((ch1=='-') || (ch1=='_'));
277         do
278         {
279             ch2=toupper(*(str2++));
280         }
281         while ((ch2=='-') || (ch2=='_'));
282
283         if (ch1!=ch2) return (ch1-ch2);
284     }
285     while (ch1 && (str1-stri1<n) && (str2-stri2<n));
286   return 0; 
287 }
288
289 int gmx_strcasecmp(const char *str1, const char *str2)
290 {
291   char ch1,ch2;
292   
293   do
294     {
295       ch1=toupper(*(str1++));
296       ch2=toupper(*(str2++));
297       if (ch1!=ch2) return (ch1-ch2);
298     }
299   while (ch1);
300   return 0; 
301 }
302
303 int gmx_strncasecmp(const char *str1, const char *str2, int n)
304 {
305   char ch1,ch2;
306  
307   if(n==0) 
308     return 0;
309
310   do
311     {
312       ch1=toupper(*(str1++));
313       ch2=toupper(*(str2++));
314       if (ch1!=ch2) return (ch1-ch2);
315       n--;
316     }
317   while (ch1 && n);
318   return 0; 
319 }
320
321 char *gmx_strdup(const char *src)
322 {
323   char *dest;
324
325   snew(dest,strlen(src)+1);
326   strcpy(dest,src);
327   
328   return dest;
329 }
330
331 char *
332 gmx_strndup(const char *src, int n)
333 {
334     int   len;
335     char *dest;
336
337     len = strlen(src);
338     if (len > n) 
339     {
340         len = n;
341     }
342     snew(dest, len+1);
343     strncpy(dest, src, len);
344     dest[len] = 0;
345     return dest;
346 }
347
348 /* Magic hash init number for Dan J. Bernsteins algorithm.
349  * Do NOT use any other value unless you really know what you are doing.
350  */
351 const unsigned int
352 gmx_string_hash_init = 5381;
353
354
355 unsigned int
356 gmx_string_hash_func(const char *s, unsigned int hash_init)
357 {
358     int c;
359
360     while ((c = toupper(*s++)) != '\0')
361     {
362         if(isalnum(c)) hash_init = ((hash_init << 5) + hash_init) ^ c; /* (hash * 33) xor c */
363     }
364     return hash_init;
365 }
366
367 /*!
368  * \param[in] pattern  Pattern to match against.
369  * \param[in] str      String to match.
370  * \returns   0 on match, GMX_NO_WCMATCH if there is no match.
371  *
372  * Matches \p str against \p pattern, which may contain * and ? wildcards.
373  * All other characters are matched literally.
374  * Currently, it is not possible to match literal * or ?.
375  */
376 int
377 gmx_wcmatch(const char *pattern, const char *str)
378 {
379     while (*pattern)
380     {
381         if (*pattern == '*')
382         {
383             /* Skip multiple wildcards in a sequence */
384             while (*pattern == '*' || *pattern == '?')
385             {
386                 ++pattern;
387                 /* For ?, we need to check that there are characters left
388                  * in str. */
389                 if (*pattern == '?')
390                 {
391                     if (*str == 0)
392                     {
393                         return GMX_NO_WCMATCH;
394                     }
395                     else
396                     {
397                         ++str;
398                     }
399                 }
400             }
401             /* If the pattern ends after the star, we have a match */
402             if (*pattern == 0)
403             {
404                 return 0;
405             }
406             /* Match the rest against each possible suffix of str */
407             while (*str)
408             {
409                 /* Only do the recursive call if the first character
410                  * matches. We don't have to worry about wildcards here,
411                  * since we have processed them above. */
412                 if (*pattern == *str)
413                 {
414                     int rc;
415                     /* Match the suffix, and return if a match or an error */
416                     rc = gmx_wcmatch(pattern, str);
417                     if (rc != GMX_NO_WCMATCH)
418                     {
419                         return rc;
420                     }
421                 }
422                 ++str;
423             }
424             /* If no suffix of str matches, we don't have a match */
425             return GMX_NO_WCMATCH;
426         }
427         else if ((*pattern == '?' && *str != 0) || *pattern == *str)
428         {
429             ++str;
430         }
431         else
432         {
433             return GMX_NO_WCMATCH;
434         }
435         ++pattern;
436     }
437     /* When the pattern runs out, we have a match if the string has ended. */
438     return (*str == 0) ? 0 : GMX_NO_WCMATCH;
439 }
440
441 char *wrap_lines(const char *buf,int line_width, int indent,gmx_bool bIndentFirst)
442 {
443   char *b2;
444   int i,i0,i2,j,b2len,lspace=0,l2space=0;
445   gmx_bool bFirst,bFitsOnLine;
446
447   /* characters are copied from buf to b2 with possible spaces changed
448    * into newlines and extra space added for indentation.
449    * i indexes buf (source buffer) and i2 indexes b2 (destination buffer)
450    * i0 points to the beginning of the current line (in buf, source)
451    * lspace and l2space point to the last space on the current line
452    * bFirst is set to prevent indentation of first line
453    * bFitsOnLine says if the first space occurred before line_width, if 
454    * that is not the case, we have a word longer than line_width which 
455    * will also not fit on the next line, so we might as well keep it on 
456    * the current line (where it also won't fit, but looks better)
457    */
458   
459   b2=NULL;
460   b2len=strlen(buf)+1+indent;
461   snew(b2,b2len);
462   i0=i2=0;
463   if (bIndentFirst)
464     for(i2=0; (i2<indent); i2++)
465       b2[i2] = ' ';
466   bFirst=TRUE;
467   do {
468     l2space = -1;
469     /* find the last space before end of line */
470     for(i=i0; ((i-i0 < line_width) || (l2space==-1)) && (buf[i]); i++) {
471       b2[i2++] = buf[i];
472       /* remember the position of a space */
473       if (buf[i] == ' ') {
474         lspace = i;
475         l2space = i2-1;
476       }
477       /* if we have a newline before the line is full, reset counters */
478       if (buf[i]=='\n' && buf[i+1]) { 
479         i0=i+1;
480         b2len+=indent;
481         srenew(b2, b2len);
482         /* add indentation after the newline */
483         for(j=0; (j<indent); j++)
484           b2[i2++]=' ';
485       }
486     }
487     /* If we are at the last newline, copy it */
488     if (buf[i]=='\n' && !buf[i+1]) {
489       b2[i2++] = buf[i++];
490     }
491     /* if we're not at the end of the string */
492     if (buf[i]) {
493       /* check if one word does not fit on the line */
494       bFitsOnLine = (i-i0 <= line_width);
495       /* reset line counters to just after the space */
496       i0 = lspace+1;
497       i2 = l2space+1;
498       /* if the words fit on the line, and we're beyond the indentation part */
499       if ( (bFitsOnLine) && (l2space >= indent) ) {
500         /* start a new line */
501         b2[l2space] = '\n';
502         /* and add indentation */
503         if (indent) {
504           if (bFirst) {
505             line_width-=indent;
506             bFirst=FALSE;
507           }
508           b2len+=indent;
509           srenew(b2, b2len);
510           for(j=0; (j<indent); j++)
511             b2[i2++]=' ';
512           /* no extra spaces after indent; */
513           while(buf[i0]==' ')
514             i0++;
515         }
516       }
517     }
518   } while (buf[i]);
519   b2[i2] = '\0';
520   
521   return b2;
522 }
523
524 char **split(char sep,char *str)
525 {
526   char **ptr = NULL;
527   int  n,nn,nptr = 0;
528   
529   if (str == NULL)
530     return NULL;
531   nn = strlen(str);
532   for(n=0; (n<nn); n++)
533     if (str[n] == sep)
534       nptr++;
535   snew(ptr,nptr+2);
536   nptr = 0;
537   while (*str != '\0') {
538     while ((*str != '\0') && (*str == sep))
539       str++;
540     if (*str != '\0') {
541       snew(ptr[nptr],1+strlen(str));
542       n = 0;
543       while ((*str != '\0') && (*str != sep)) {
544         ptr[nptr][n] = *str;
545         str++;
546         n++;
547       }
548       ptr[nptr][n] = '\0';
549       nptr++;
550     }
551   }
552   ptr[nptr] = NULL;
553   
554   return ptr;
555 }
556
557
558 gmx_large_int_t
559 str_to_large_int_t(const char *str, char **endptr)
560 {
561         int         sign = 1;
562         gmx_large_int_t  val  = 0;
563         char        ch;
564         const char  *p;
565         
566         p = str;
567         if(p==NULL)
568         {
569                 *endptr=NULL;
570                 return 0;
571         }
572         
573         /* Strip off initial white space */
574         while(isspace(*p))
575         {
576                 p++;
577         }
578         /* Conform to ISO C99 - return original pointer if string does not contain a number */
579         if(*str=='\0')
580         {
581                 *endptr=(char *)str;
582         }
583         
584         if(*p=='-')
585         {
586                 p++;
587                 sign *= -1;
588         }
589         
590         while( ((ch=*p) != '\0') && isdigit(ch) )
591         {
592                 /* Important to add sign here, so we dont overflow in final multiplication */
593                 ch = (ch-'0')*sign; 
594                 val = val*10 + ch;
595                 if(ch != val%10) 
596                 {
597                         /* Some sort of overflow has occured, set endptr to original string */
598                         *endptr=(char *)str;
599                         errno = ERANGE;
600                         return(0);
601                 }
602                 p++;
603         }
604         
605         *endptr=(char *)p;
606         
607         return val;
608 }
609
610 char *gmx_strsep(char **stringp, const char *delim)
611 {
612     char *ret;
613     int len=strlen(delim);
614     int i,j=0;
615     int found=0;
616
617     if (! *stringp)
618         return NULL;
619     ret=*stringp;
620     do
621     {
622         if ( (*stringp)[j] == '\0')
623         {
624             found=1;
625             *stringp=NULL;
626             break;
627         }
628         for (i=0;i<len;i++)
629         {
630             if ( (*stringp)[j]==delim[i])
631             {
632                 (*stringp)[j]='\0';
633                 *stringp=*stringp+j+1;
634                 found=1;
635                 break;
636             }
637         }
638         j++;
639     } while (!found);
640
641     return ret;
642 }
643