openat: don’t close (-1)
[gnulib.git] / lib / trim.c
blob77cf19b2d3bb067669298bb15d04e4f817d45a77
1 /* Removes leading and/or trailing whitespaces
2 Copyright (C) 2006-2024 Free Software Foundation, Inc.
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.
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.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <https://www.gnu.org/licenses/>. */
17 /* Written by Davide Angelocola <davide.angelocola@gmail.com> */
19 #include <config.h>
21 /* Specification. */
22 #include "trim.h"
24 #include <ctype.h>
25 #include <string.h>
26 #include <stddef.h>
27 #include <stdlib.h>
29 #if GNULIB_MCEL_PREFER
30 # include "mcel.h"
31 #else
32 # include "mbchar.h"
33 # include "mbuiterf.h"
34 #endif
35 #include "xalloc.h"
37 char *
38 trim2 (const char *s, int how)
40 const char *start = s;
41 const char *end;
43 if (MB_CUR_MAX > 1)
45 #if GNULIB_MCEL_PREFER
46 /* Skip leading whitespace. */
47 if (how != TRIM_TRAILING)
48 for (mcel_t g; *start; start += g.len)
50 g = mcel_scanz (start);
51 if (!c32isspace (g.ch))
52 break;
55 /* Find start of any trailing whitespace. */
56 if (how != TRIM_LEADING)
57 for (const char *p = end = start; *p; )
59 mcel_t g = mcel_scanz (p);
60 p += g.len;
61 if (!c32isspace (g.ch))
62 end = p;
64 #else
65 mbuif_state_t state;
66 mbuif_init (state);
68 /* Skip leading whitespace. */
69 if (how != TRIM_TRAILING)
70 while (mbuif_avail (state, start))
72 mbchar_t cur = mbuif_next (state, start);
73 if (!mb_isspace (cur))
74 break;
75 start += mb_len (cur);
78 /* Find start of any trailing whitespace. */
79 if (how != TRIM_LEADING)
80 for (const char *p = end = start; mbuif_avail (state, p); )
82 mbchar_t cur = mbuif_next (state, p);
83 p += mb_len (cur);
84 if (!mb_isspace (cur))
85 end = p;
87 #endif
89 else
91 /* Skip leading whitespace. */
92 if (how != TRIM_TRAILING)
93 while (isspace ((unsigned char) *start))
94 start++;
96 /* Find start of any trailing whitespace. */
97 if (how != TRIM_LEADING)
98 for (const char *p = end = start; *p; )
99 if (!isspace ((unsigned char) *p++))
100 end = p;
103 /* Create trimmed copy. */
104 size_t dlen = how == TRIM_LEADING ? strlen (start) : end - start;
105 char *d = malloc (dlen + 1);
106 if (!d)
107 xalloc_die ();
108 char *d_end = mempcpy (d, start, dlen);
109 *d_end = '\0';
111 return d;