1/* Removes leading and/or trailing whitespaces
2   Copyright (C) 2006-2010 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
40char *
41trim2(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          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                {
77                  state = 0;
78                  continue;
79                }
80
81              if (state == 0 && !mb_isspace (mbi_cur (i)))
82                {
83                  state = 1;
84                  continue;
85                }
86
87              if (state == 1 && !mb_isspace (mbi_cur (i)))
88                {
89                  state = 1;
90                  continue;
91                }
92
93              if (state == 1 && mb_isspace (mbi_cur (i)))
94                {
95                  state = 2;
96                  r = (char *) mbi_cur_ptr (i);
97                }
98              else if (state == 2 && mb_isspace (mbi_cur (i)))
99                {
100                  state = 2;
101                }
102              else
103                {
104                  state = 1;
105                }
106            }
107
108          if (state == 2)
109            *r = '\0';
110        }
111    }
112  else
113    {
114      char *p;
115
116      /* Trim leading whitespaces. */
117      if (how != TRIM_TRAILING) {
118        for (p = d; *p && isspace ((unsigned char) *p); p++)
119          ;
120
121        memmove (d, p, strlen (p) + 1);
122      }
123
124      /* Trim trailing whitespaces. */
125      if (how != TRIM_LEADING) {
126        for (p = d + strlen (d) - 1; p >= d && isspace ((unsigned char) *p); p--)
127          *p = '\0';
128      }
129    }
130
131  return d;
132}
133
134