Merge branch 'vendor/GREP'
[dragonfly.git] / contrib / grep / lib / trim.c
1 /* Removes leading and/or trailing whitespaces
2    Copyright (C) 2006-2015 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 3 of the License, or
7    (at your option) 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.  If not, see <http://www.gnu.org/licenses/>.  */
16
17 /* Written by Davide Angelocola <davide.angelocola@gmail.com> */
18
19 #include <config.h>
20
21 /* Specification.  */
22 #include "trim.h"
23
24 #include <ctype.h>
25 #include <string.h>
26 #include <stddef.h>
27 #include <stdlib.h>
28
29 #include "mbchar.h"
30 #include "mbiter.h"
31 #include "xalloc.h"
32
33 /* Use this to suppress gcc's "...may be used before initialized" warnings. */
34 #ifdef lint
35 # define IF_LINT(Code) Code
36 #else
37 # define IF_LINT(Code) /* empty */
38 #endif
39
40 char *
41 trim2 (const char *s, int how)
42 {
43   char *d;
44
45   d = strdup (s);
46
47   if (!d)
48     xalloc_die ();
49
50   if (MB_CUR_MAX > 1)
51     {
52       mbi_iterator_t i;
53
54       /* Trim leading whitespaces. */
55       if (how != TRIM_TRAILING)
56         {
57           mbi_init (i, d, strlen (d));
58
59           for (; mbi_avail (i) && mb_isspace (mbi_cur (i)); mbi_advance (i))
60             ;
61
62           memmove (d, mbi_cur_ptr (i), strlen (mbi_cur_ptr (i)) + 1);
63         }
64
65       /* Trim trailing whitespaces. */
66       if (how != TRIM_LEADING)
67         {
68           unsigned int state = 0;
69           char *r IF_LINT (= NULL); /* used only while state = 2 */
70
71           mbi_init (i, d, strlen (d));
72
73           for (; mbi_avail (i); mbi_advance (i))
74             {
75               if (state == 0 && mb_isspace (mbi_cur (i)))
76                 continue;
77
78               if (state == 0 && !mb_isspace (mbi_cur (i)))
79                 {
80                   state = 1;
81                   continue;
82                 }
83
84               if (state == 1 && !mb_isspace (mbi_cur (i)))
85                 continue;
86
87               if (state == 1 && mb_isspace (mbi_cur (i)))
88                 {
89                   state = 2;
90                   r = (char *) mbi_cur_ptr (i);
91                 }
92               else if (state == 2 && mb_isspace (mbi_cur (i)))
93                 {
94                   /* empty */
95                 }
96               else
97                 {
98                   state = 1;
99                 }
100             }
101
102           if (state == 2)
103             *r = '\0';
104         }
105     }
106   else
107     {
108       char *p;
109
110       /* Trim leading whitespaces. */
111       if (how != TRIM_TRAILING)
112         {
113           for (p = d; *p && isspace ((unsigned char) *p); p++)
114             ;
115
116           memmove (d, p, strlen (p) + 1);
117         }
118
119       /* Trim trailing whitespaces. */
120       if (how != TRIM_LEADING)
121         {
122           for (p = d + strlen (d) - 1;
123                p >= d && isspace ((unsigned char) *p); p--)
124             *p = '\0';
125         }
126     }
127
128   return d;
129 }