New 'trim' module, from Davide Angelocola <davide.angelocola@tiscali.it>.
[gnulib.git] / lib / trim.c
1 /* Removes leading and/or trailing whitespaces
2    Copyright (C) 2006 Free Software Foundation, Inc.
3
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; either version 2, or (at your option)
7    any later version.
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program; see the file COPYING.
16    If not, write to the Free Software Foundation,
17    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
18
19 /* Written by Davide Angelocola <davide.angelocola@gmail.com> */
20
21 #ifdef HAVE_CONFIG_H
22 # include <config.h>
23 #endif
24
25 #if HAVE_MBRTOWC 
26 # include <stddef.h>
27 # include "mbchar.h"
28 # include "mbiter.h"
29 # include "mbuiter.h"           /* FIXME: for MB_CUR_MAX */
30 #else
31 # include <ctype.h>
32 #endif
33
34 #include "xalloc.h"
35 #include "trim.h"
36
37 char *
38 trim2(const char *s, int how)
39 {
40   char *d;
41     
42   d = strdup(s);
43
44   if (!d)
45     xalloc_die();
46   
47 #if HAVE_MBRTOWC
48   if (MB_CUR_MAX > 1)
49     {
50       mbi_iterator_t i;
51       
52       /* Trim leading whitespaces. */
53       if (how != TRIM_TRAILING) 
54         {
55           mbi_init (i, d, strlen (d));
56       
57           for (; mbi_avail (i) && mb_isspace (mbi_cur (i)); mbi_advance (i))
58             ;
59           
60           memmove (d, mbi_cur_ptr (i), strlen (mbi_cur_ptr (i)) + 1);
61         }
62   
63       /* Trim trailing whitespaces. */
64       if (how != TRIM_LEADING) 
65         {
66           int state = 0;
67           char *r;
68           
69           mbi_init (i, d, strlen (d));
70
71           for (; mbi_avail (i); mbi_advance (i)) 
72             {
73               if (state == 0 && mb_isspace (mbi_cur (i))) 
74                 {
75                   state = 0;
76                   continue;
77                 }
78               
79               if (state == 0 && !mb_isspace (mbi_cur (i)))
80                 {
81                   state = 1;
82                   continue;
83                 }
84               
85               if (state == 1 && !mb_isspace (mbi_cur (i)))
86                 {
87                   state = 1;
88                   continue;
89                 }
90               
91               if (state == 1 && mb_isspace (mbi_cur (i))) 
92                 {
93                   state = 2;
94                   r = (char *) mbi_cur_ptr (i);
95                 }
96               else if (state == 2 && mb_isspace (mbi_cur (i))) 
97                 {
98                   state = 2;
99                 } 
100               else 
101                 {
102                   state = 1;
103                 }
104             }
105           
106           if (state == 2) 
107             *r = '\0';
108         }
109     }
110   else
111 #endif /* HAVE_MBRTOWC */
112     {
113       char *p;
114       
115       /* Trim leading whitespaces. */
116       if (how != TRIM_TRAILING) {
117         for (p = d; *p && isspace (*p); p++)
118           ;                     
119
120         memmove (d, p, strlen (p) + 1);
121       }
122
123       /* Trim trailing whitespaces. */
124       if (how != TRIM_LEADING) {
125         for (p = d + strlen (d) - 1; p >= d && isspace (*p); p--)
126           *p = '\0';
127       }
128     }
129   
130   return d;
131 }
132