1*6eef5f0cSAntonio Huete Jimenez /* $NetBSD: str.h,v 1.15 2021/12/15 10:57:01 rillig Exp $ */
2*6eef5f0cSAntonio Huete Jimenez
3*6eef5f0cSAntonio Huete Jimenez /*
4*6eef5f0cSAntonio Huete Jimenez Copyright (c) 2021 Roland Illig <rillig@NetBSD.org>
5*6eef5f0cSAntonio Huete Jimenez All rights reserved.
6*6eef5f0cSAntonio Huete Jimenez
7*6eef5f0cSAntonio Huete Jimenez Redistribution and use in source and binary forms, with or without
8*6eef5f0cSAntonio Huete Jimenez modification, are permitted provided that the following conditions
9*6eef5f0cSAntonio Huete Jimenez are met:
10*6eef5f0cSAntonio Huete Jimenez
11*6eef5f0cSAntonio Huete Jimenez 1. Redistributions of source code must retain the above copyright
12*6eef5f0cSAntonio Huete Jimenez notice, this list of conditions and the following disclaimer.
13*6eef5f0cSAntonio Huete Jimenez 2. Redistributions in binary form must reproduce the above copyright
14*6eef5f0cSAntonio Huete Jimenez notice, this list of conditions and the following disclaimer in the
15*6eef5f0cSAntonio Huete Jimenez documentation and/or other materials provided with the distribution.
16*6eef5f0cSAntonio Huete Jimenez
17*6eef5f0cSAntonio Huete Jimenez THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18*6eef5f0cSAntonio Huete Jimenez "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19*6eef5f0cSAntonio Huete Jimenez TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20*6eef5f0cSAntonio Huete Jimenez PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
21*6eef5f0cSAntonio Huete Jimenez BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22*6eef5f0cSAntonio Huete Jimenez CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23*6eef5f0cSAntonio Huete Jimenez SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24*6eef5f0cSAntonio Huete Jimenez INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25*6eef5f0cSAntonio Huete Jimenez CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26*6eef5f0cSAntonio Huete Jimenez ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27*6eef5f0cSAntonio Huete Jimenez POSSIBILITY OF SUCH DAMAGE.
28*6eef5f0cSAntonio Huete Jimenez */
29*6eef5f0cSAntonio Huete Jimenez
30*6eef5f0cSAntonio Huete Jimenez
31*6eef5f0cSAntonio Huete Jimenez /*
32*6eef5f0cSAntonio Huete Jimenez * Memory-efficient string handling.
33*6eef5f0cSAntonio Huete Jimenez */
34*6eef5f0cSAntonio Huete Jimenez
35*6eef5f0cSAntonio Huete Jimenez
36*6eef5f0cSAntonio Huete Jimenez /* A read-only string that may need to be freed after use. */
37*6eef5f0cSAntonio Huete Jimenez typedef struct FStr {
38*6eef5f0cSAntonio Huete Jimenez const char *str;
39*6eef5f0cSAntonio Huete Jimenez void *freeIt;
40*6eef5f0cSAntonio Huete Jimenez } FStr;
41*6eef5f0cSAntonio Huete Jimenez
42*6eef5f0cSAntonio Huete Jimenez /* A read-only range of a character array, NOT null-terminated. */
43*6eef5f0cSAntonio Huete Jimenez typedef struct Substring {
44*6eef5f0cSAntonio Huete Jimenez const char *start;
45*6eef5f0cSAntonio Huete Jimenez const char *end;
46*6eef5f0cSAntonio Huete Jimenez } Substring;
47*6eef5f0cSAntonio Huete Jimenez
48*6eef5f0cSAntonio Huete Jimenez /*
49*6eef5f0cSAntonio Huete Jimenez * Builds a string, only allocating memory if the string is different from the
50*6eef5f0cSAntonio Huete Jimenez * expected string.
51*6eef5f0cSAntonio Huete Jimenez */
52*6eef5f0cSAntonio Huete Jimenez typedef struct LazyBuf {
53*6eef5f0cSAntonio Huete Jimenez char *data;
54*6eef5f0cSAntonio Huete Jimenez size_t len;
55*6eef5f0cSAntonio Huete Jimenez size_t cap;
56*6eef5f0cSAntonio Huete Jimenez const char *expected;
57*6eef5f0cSAntonio Huete Jimenez } LazyBuf;
58*6eef5f0cSAntonio Huete Jimenez
59*6eef5f0cSAntonio Huete Jimenez /* The result of splitting a string into words. */
60*6eef5f0cSAntonio Huete Jimenez typedef struct Words {
61*6eef5f0cSAntonio Huete Jimenez char **words;
62*6eef5f0cSAntonio Huete Jimenez size_t len;
63*6eef5f0cSAntonio Huete Jimenez void *freeIt;
64*6eef5f0cSAntonio Huete Jimenez } Words;
65*6eef5f0cSAntonio Huete Jimenez
66*6eef5f0cSAntonio Huete Jimenez /* The result of splitting a string into words. */
67*6eef5f0cSAntonio Huete Jimenez typedef struct SubstringWords {
68*6eef5f0cSAntonio Huete Jimenez Substring *words;
69*6eef5f0cSAntonio Huete Jimenez size_t len;
70*6eef5f0cSAntonio Huete Jimenez void *freeIt;
71*6eef5f0cSAntonio Huete Jimenez } SubstringWords;
72*6eef5f0cSAntonio Huete Jimenez
73*6eef5f0cSAntonio Huete Jimenez
74*6eef5f0cSAntonio Huete Jimenez MAKE_INLINE FStr
FStr_Init(const char * str,void * freeIt)75*6eef5f0cSAntonio Huete Jimenez FStr_Init(const char *str, void *freeIt)
76*6eef5f0cSAntonio Huete Jimenez {
77*6eef5f0cSAntonio Huete Jimenez FStr fstr;
78*6eef5f0cSAntonio Huete Jimenez fstr.str = str;
79*6eef5f0cSAntonio Huete Jimenez fstr.freeIt = freeIt;
80*6eef5f0cSAntonio Huete Jimenez return fstr;
81*6eef5f0cSAntonio Huete Jimenez }
82*6eef5f0cSAntonio Huete Jimenez
83*6eef5f0cSAntonio Huete Jimenez /* Return a string that is the sole owner of str. */
84*6eef5f0cSAntonio Huete Jimenez MAKE_INLINE FStr
FStr_InitOwn(char * str)85*6eef5f0cSAntonio Huete Jimenez FStr_InitOwn(char *str)
86*6eef5f0cSAntonio Huete Jimenez {
87*6eef5f0cSAntonio Huete Jimenez return FStr_Init(str, str);
88*6eef5f0cSAntonio Huete Jimenez }
89*6eef5f0cSAntonio Huete Jimenez
90*6eef5f0cSAntonio Huete Jimenez /* Return a string that refers to the shared str. */
91*6eef5f0cSAntonio Huete Jimenez MAKE_INLINE FStr
FStr_InitRefer(const char * str)92*6eef5f0cSAntonio Huete Jimenez FStr_InitRefer(const char *str)
93*6eef5f0cSAntonio Huete Jimenez {
94*6eef5f0cSAntonio Huete Jimenez return FStr_Init(str, NULL);
95*6eef5f0cSAntonio Huete Jimenez }
96*6eef5f0cSAntonio Huete Jimenez
97*6eef5f0cSAntonio Huete Jimenez MAKE_INLINE void
FStr_Done(FStr * fstr)98*6eef5f0cSAntonio Huete Jimenez FStr_Done(FStr *fstr)
99*6eef5f0cSAntonio Huete Jimenez {
100*6eef5f0cSAntonio Huete Jimenez free(fstr->freeIt);
101*6eef5f0cSAntonio Huete Jimenez #ifdef CLEANUP
102*6eef5f0cSAntonio Huete Jimenez fstr->str = NULL;
103*6eef5f0cSAntonio Huete Jimenez fstr->freeIt = NULL;
104*6eef5f0cSAntonio Huete Jimenez #endif
105*6eef5f0cSAntonio Huete Jimenez }
106*6eef5f0cSAntonio Huete Jimenez
107*6eef5f0cSAntonio Huete Jimenez
108*6eef5f0cSAntonio Huete Jimenez MAKE_STATIC Substring
Substring_Init(const char * start,const char * end)109*6eef5f0cSAntonio Huete Jimenez Substring_Init(const char *start, const char *end)
110*6eef5f0cSAntonio Huete Jimenez {
111*6eef5f0cSAntonio Huete Jimenez Substring sub;
112*6eef5f0cSAntonio Huete Jimenez
113*6eef5f0cSAntonio Huete Jimenez sub.start = start;
114*6eef5f0cSAntonio Huete Jimenez sub.end = end;
115*6eef5f0cSAntonio Huete Jimenez return sub;
116*6eef5f0cSAntonio Huete Jimenez }
117*6eef5f0cSAntonio Huete Jimenez
118*6eef5f0cSAntonio Huete Jimenez MAKE_INLINE Substring
Substring_InitStr(const char * str)119*6eef5f0cSAntonio Huete Jimenez Substring_InitStr(const char *str)
120*6eef5f0cSAntonio Huete Jimenez {
121*6eef5f0cSAntonio Huete Jimenez return Substring_Init(str, str + strlen(str));
122*6eef5f0cSAntonio Huete Jimenez }
123*6eef5f0cSAntonio Huete Jimenez
124*6eef5f0cSAntonio Huete Jimenez MAKE_STATIC size_t
Substring_Length(Substring sub)125*6eef5f0cSAntonio Huete Jimenez Substring_Length(Substring sub)
126*6eef5f0cSAntonio Huete Jimenez {
127*6eef5f0cSAntonio Huete Jimenez return (size_t)(sub.end - sub.start);
128*6eef5f0cSAntonio Huete Jimenez }
129*6eef5f0cSAntonio Huete Jimenez
130*6eef5f0cSAntonio Huete Jimenez MAKE_STATIC bool
Substring_IsEmpty(Substring sub)131*6eef5f0cSAntonio Huete Jimenez Substring_IsEmpty(Substring sub)
132*6eef5f0cSAntonio Huete Jimenez {
133*6eef5f0cSAntonio Huete Jimenez return sub.start == sub.end;
134*6eef5f0cSAntonio Huete Jimenez }
135*6eef5f0cSAntonio Huete Jimenez
136*6eef5f0cSAntonio Huete Jimenez MAKE_INLINE bool
Substring_Equals(Substring sub,const char * str)137*6eef5f0cSAntonio Huete Jimenez Substring_Equals(Substring sub, const char *str)
138*6eef5f0cSAntonio Huete Jimenez {
139*6eef5f0cSAntonio Huete Jimenez size_t len = strlen(str);
140*6eef5f0cSAntonio Huete Jimenez return Substring_Length(sub) == len &&
141*6eef5f0cSAntonio Huete Jimenez memcmp(sub.start, str, len) == 0;
142*6eef5f0cSAntonio Huete Jimenez }
143*6eef5f0cSAntonio Huete Jimenez
144*6eef5f0cSAntonio Huete Jimenez MAKE_INLINE bool
Substring_Eq(Substring sub,Substring str)145*6eef5f0cSAntonio Huete Jimenez Substring_Eq(Substring sub, Substring str)
146*6eef5f0cSAntonio Huete Jimenez {
147*6eef5f0cSAntonio Huete Jimenez size_t len = Substring_Length(sub);
148*6eef5f0cSAntonio Huete Jimenez return len == Substring_Length(str) &&
149*6eef5f0cSAntonio Huete Jimenez memcmp(sub.start, str.start, len) == 0;
150*6eef5f0cSAntonio Huete Jimenez }
151*6eef5f0cSAntonio Huete Jimenez
152*6eef5f0cSAntonio Huete Jimenez MAKE_STATIC Substring
Substring_Sub(Substring sub,size_t start,size_t end)153*6eef5f0cSAntonio Huete Jimenez Substring_Sub(Substring sub, size_t start, size_t end)
154*6eef5f0cSAntonio Huete Jimenez {
155*6eef5f0cSAntonio Huete Jimenez assert(start <= Substring_Length(sub));
156*6eef5f0cSAntonio Huete Jimenez assert(end <= Substring_Length(sub));
157*6eef5f0cSAntonio Huete Jimenez return Substring_Init(sub.start + start, sub.start + end);
158*6eef5f0cSAntonio Huete Jimenez }
159*6eef5f0cSAntonio Huete Jimenez
160*6eef5f0cSAntonio Huete Jimenez MAKE_STATIC bool
Substring_HasPrefix(Substring sub,Substring prefix)161*6eef5f0cSAntonio Huete Jimenez Substring_HasPrefix(Substring sub, Substring prefix)
162*6eef5f0cSAntonio Huete Jimenez {
163*6eef5f0cSAntonio Huete Jimenez return Substring_Length(sub) >= Substring_Length(prefix) &&
164*6eef5f0cSAntonio Huete Jimenez memcmp(sub.start, prefix.start, Substring_Length(prefix)) == 0;
165*6eef5f0cSAntonio Huete Jimenez }
166*6eef5f0cSAntonio Huete Jimenez
167*6eef5f0cSAntonio Huete Jimenez MAKE_STATIC bool
Substring_HasSuffix(Substring sub,Substring suffix)168*6eef5f0cSAntonio Huete Jimenez Substring_HasSuffix(Substring sub, Substring suffix)
169*6eef5f0cSAntonio Huete Jimenez {
170*6eef5f0cSAntonio Huete Jimenez size_t suffixLen = Substring_Length(suffix);
171*6eef5f0cSAntonio Huete Jimenez return Substring_Length(sub) >= suffixLen &&
172*6eef5f0cSAntonio Huete Jimenez memcmp(sub.end - suffixLen, suffix.start, suffixLen) == 0;
173*6eef5f0cSAntonio Huete Jimenez }
174*6eef5f0cSAntonio Huete Jimenez
175*6eef5f0cSAntonio Huete Jimenez /* Returns an independent, null-terminated copy of the substring. */
176*6eef5f0cSAntonio Huete Jimenez MAKE_STATIC FStr
Substring_Str(Substring sub)177*6eef5f0cSAntonio Huete Jimenez Substring_Str(Substring sub)
178*6eef5f0cSAntonio Huete Jimenez {
179*6eef5f0cSAntonio Huete Jimenez if (Substring_IsEmpty(sub))
180*6eef5f0cSAntonio Huete Jimenez return FStr_InitRefer("");
181*6eef5f0cSAntonio Huete Jimenez return FStr_InitOwn(bmake_strsedup(sub.start, sub.end));
182*6eef5f0cSAntonio Huete Jimenez }
183*6eef5f0cSAntonio Huete Jimenez
184*6eef5f0cSAntonio Huete Jimenez MAKE_STATIC const char *
Substring_SkipFirst(Substring sub,char ch)185*6eef5f0cSAntonio Huete Jimenez Substring_SkipFirst(Substring sub, char ch)
186*6eef5f0cSAntonio Huete Jimenez {
187*6eef5f0cSAntonio Huete Jimenez const char *p;
188*6eef5f0cSAntonio Huete Jimenez
189*6eef5f0cSAntonio Huete Jimenez for (p = sub.start; p != sub.end; p++)
190*6eef5f0cSAntonio Huete Jimenez if (*p == ch)
191*6eef5f0cSAntonio Huete Jimenez return p + 1;
192*6eef5f0cSAntonio Huete Jimenez return sub.start;
193*6eef5f0cSAntonio Huete Jimenez }
194*6eef5f0cSAntonio Huete Jimenez
195*6eef5f0cSAntonio Huete Jimenez MAKE_STATIC const char *
Substring_LastIndex(Substring sub,char ch)196*6eef5f0cSAntonio Huete Jimenez Substring_LastIndex(Substring sub, char ch)
197*6eef5f0cSAntonio Huete Jimenez {
198*6eef5f0cSAntonio Huete Jimenez const char *p;
199*6eef5f0cSAntonio Huete Jimenez
200*6eef5f0cSAntonio Huete Jimenez for (p = sub.end; p != sub.start; p--)
201*6eef5f0cSAntonio Huete Jimenez if (p[-1] == ch)
202*6eef5f0cSAntonio Huete Jimenez return p - 1;
203*6eef5f0cSAntonio Huete Jimenez return NULL;
204*6eef5f0cSAntonio Huete Jimenez }
205*6eef5f0cSAntonio Huete Jimenez
206*6eef5f0cSAntonio Huete Jimenez MAKE_STATIC Substring
Substring_Dirname(Substring pathname)207*6eef5f0cSAntonio Huete Jimenez Substring_Dirname(Substring pathname)
208*6eef5f0cSAntonio Huete Jimenez {
209*6eef5f0cSAntonio Huete Jimenez const char *p;
210*6eef5f0cSAntonio Huete Jimenez
211*6eef5f0cSAntonio Huete Jimenez for (p = pathname.end; p != pathname.start; p--)
212*6eef5f0cSAntonio Huete Jimenez if (p[-1] == '/')
213*6eef5f0cSAntonio Huete Jimenez return Substring_Init(pathname.start, p - 1);
214*6eef5f0cSAntonio Huete Jimenez return Substring_InitStr(".");
215*6eef5f0cSAntonio Huete Jimenez }
216*6eef5f0cSAntonio Huete Jimenez
217*6eef5f0cSAntonio Huete Jimenez MAKE_STATIC Substring
Substring_Basename(Substring pathname)218*6eef5f0cSAntonio Huete Jimenez Substring_Basename(Substring pathname)
219*6eef5f0cSAntonio Huete Jimenez {
220*6eef5f0cSAntonio Huete Jimenez const char *p;
221*6eef5f0cSAntonio Huete Jimenez
222*6eef5f0cSAntonio Huete Jimenez for (p = pathname.end; p != pathname.start; p--)
223*6eef5f0cSAntonio Huete Jimenez if (p[-1] == '/')
224*6eef5f0cSAntonio Huete Jimenez return Substring_Init(p, pathname.end);
225*6eef5f0cSAntonio Huete Jimenez return pathname;
226*6eef5f0cSAntonio Huete Jimenez }
227*6eef5f0cSAntonio Huete Jimenez
228*6eef5f0cSAntonio Huete Jimenez
229*6eef5f0cSAntonio Huete Jimenez MAKE_STATIC void
LazyBuf_Init(LazyBuf * buf,const char * expected)230*6eef5f0cSAntonio Huete Jimenez LazyBuf_Init(LazyBuf *buf, const char *expected)
231*6eef5f0cSAntonio Huete Jimenez {
232*6eef5f0cSAntonio Huete Jimenez buf->data = NULL;
233*6eef5f0cSAntonio Huete Jimenez buf->len = 0;
234*6eef5f0cSAntonio Huete Jimenez buf->cap = 0;
235*6eef5f0cSAntonio Huete Jimenez buf->expected = expected;
236*6eef5f0cSAntonio Huete Jimenez }
237*6eef5f0cSAntonio Huete Jimenez
238*6eef5f0cSAntonio Huete Jimenez MAKE_INLINE void
LazyBuf_Done(LazyBuf * buf)239*6eef5f0cSAntonio Huete Jimenez LazyBuf_Done(LazyBuf *buf)
240*6eef5f0cSAntonio Huete Jimenez {
241*6eef5f0cSAntonio Huete Jimenez free(buf->data);
242*6eef5f0cSAntonio Huete Jimenez }
243*6eef5f0cSAntonio Huete Jimenez
244*6eef5f0cSAntonio Huete Jimenez MAKE_STATIC void
LazyBuf_Add(LazyBuf * buf,char ch)245*6eef5f0cSAntonio Huete Jimenez LazyBuf_Add(LazyBuf *buf, char ch)
246*6eef5f0cSAntonio Huete Jimenez {
247*6eef5f0cSAntonio Huete Jimenez
248*6eef5f0cSAntonio Huete Jimenez if (buf->data != NULL) {
249*6eef5f0cSAntonio Huete Jimenez if (buf->len == buf->cap) {
250*6eef5f0cSAntonio Huete Jimenez buf->cap *= 2;
251*6eef5f0cSAntonio Huete Jimenez buf->data = bmake_realloc(buf->data, buf->cap);
252*6eef5f0cSAntonio Huete Jimenez }
253*6eef5f0cSAntonio Huete Jimenez buf->data[buf->len++] = ch;
254*6eef5f0cSAntonio Huete Jimenez
255*6eef5f0cSAntonio Huete Jimenez } else if (ch == buf->expected[buf->len]) {
256*6eef5f0cSAntonio Huete Jimenez buf->len++;
257*6eef5f0cSAntonio Huete Jimenez return;
258*6eef5f0cSAntonio Huete Jimenez
259*6eef5f0cSAntonio Huete Jimenez } else {
260*6eef5f0cSAntonio Huete Jimenez buf->cap = buf->len + 16;
261*6eef5f0cSAntonio Huete Jimenez buf->data = bmake_malloc(buf->cap);
262*6eef5f0cSAntonio Huete Jimenez memcpy(buf->data, buf->expected, buf->len);
263*6eef5f0cSAntonio Huete Jimenez buf->data[buf->len++] = ch;
264*6eef5f0cSAntonio Huete Jimenez }
265*6eef5f0cSAntonio Huete Jimenez }
266*6eef5f0cSAntonio Huete Jimenez
267*6eef5f0cSAntonio Huete Jimenez MAKE_STATIC void
LazyBuf_AddStr(LazyBuf * buf,const char * str)268*6eef5f0cSAntonio Huete Jimenez LazyBuf_AddStr(LazyBuf *buf, const char *str)
269*6eef5f0cSAntonio Huete Jimenez {
270*6eef5f0cSAntonio Huete Jimenez const char *p;
271*6eef5f0cSAntonio Huete Jimenez
272*6eef5f0cSAntonio Huete Jimenez for (p = str; *p != '\0'; p++)
273*6eef5f0cSAntonio Huete Jimenez LazyBuf_Add(buf, *p);
274*6eef5f0cSAntonio Huete Jimenez }
275*6eef5f0cSAntonio Huete Jimenez
276*6eef5f0cSAntonio Huete Jimenez MAKE_STATIC void
LazyBuf_AddBytesBetween(LazyBuf * buf,const char * start,const char * end)277*6eef5f0cSAntonio Huete Jimenez LazyBuf_AddBytesBetween(LazyBuf *buf, const char *start, const char *end)
278*6eef5f0cSAntonio Huete Jimenez {
279*6eef5f0cSAntonio Huete Jimenez const char *p;
280*6eef5f0cSAntonio Huete Jimenez
281*6eef5f0cSAntonio Huete Jimenez for (p = start; p != end; p++)
282*6eef5f0cSAntonio Huete Jimenez LazyBuf_Add(buf, *p);
283*6eef5f0cSAntonio Huete Jimenez }
284*6eef5f0cSAntonio Huete Jimenez
285*6eef5f0cSAntonio Huete Jimenez MAKE_INLINE void
LazyBuf_AddSubstring(LazyBuf * buf,Substring sub)286*6eef5f0cSAntonio Huete Jimenez LazyBuf_AddSubstring(LazyBuf *buf, Substring sub)
287*6eef5f0cSAntonio Huete Jimenez {
288*6eef5f0cSAntonio Huete Jimenez LazyBuf_AddBytesBetween(buf, sub.start, sub.end);
289*6eef5f0cSAntonio Huete Jimenez }
290*6eef5f0cSAntonio Huete Jimenez
291*6eef5f0cSAntonio Huete Jimenez MAKE_STATIC Substring
LazyBuf_Get(const LazyBuf * buf)292*6eef5f0cSAntonio Huete Jimenez LazyBuf_Get(const LazyBuf *buf)
293*6eef5f0cSAntonio Huete Jimenez {
294*6eef5f0cSAntonio Huete Jimenez const char *start = buf->data != NULL ? buf->data : buf->expected;
295*6eef5f0cSAntonio Huete Jimenez return Substring_Init(start, start + buf->len);
296*6eef5f0cSAntonio Huete Jimenez }
297*6eef5f0cSAntonio Huete Jimenez
298*6eef5f0cSAntonio Huete Jimenez /*
299*6eef5f0cSAntonio Huete Jimenez * Returns the content of the buffer as a newly allocated string.
300*6eef5f0cSAntonio Huete Jimenez *
301*6eef5f0cSAntonio Huete Jimenez * See LazyBuf_Get to avoid unnecessary memory allocations.
302*6eef5f0cSAntonio Huete Jimenez */
303*6eef5f0cSAntonio Huete Jimenez MAKE_STATIC FStr
LazyBuf_DoneGet(LazyBuf * buf)304*6eef5f0cSAntonio Huete Jimenez LazyBuf_DoneGet(LazyBuf *buf)
305*6eef5f0cSAntonio Huete Jimenez {
306*6eef5f0cSAntonio Huete Jimenez if (buf->data != NULL) {
307*6eef5f0cSAntonio Huete Jimenez LazyBuf_Add(buf, '\0');
308*6eef5f0cSAntonio Huete Jimenez return FStr_InitOwn(buf->data);
309*6eef5f0cSAntonio Huete Jimenez }
310*6eef5f0cSAntonio Huete Jimenez return Substring_Str(LazyBuf_Get(buf));
311*6eef5f0cSAntonio Huete Jimenez }
312*6eef5f0cSAntonio Huete Jimenez
313*6eef5f0cSAntonio Huete Jimenez
314*6eef5f0cSAntonio Huete Jimenez Words Str_Words(const char *, bool);
315*6eef5f0cSAntonio Huete Jimenez
316*6eef5f0cSAntonio Huete Jimenez MAKE_INLINE void
Words_Free(Words w)317*6eef5f0cSAntonio Huete Jimenez Words_Free(Words w)
318*6eef5f0cSAntonio Huete Jimenez {
319*6eef5f0cSAntonio Huete Jimenez free(w.words);
320*6eef5f0cSAntonio Huete Jimenez free(w.freeIt);
321*6eef5f0cSAntonio Huete Jimenez }
322*6eef5f0cSAntonio Huete Jimenez
323*6eef5f0cSAntonio Huete Jimenez
324*6eef5f0cSAntonio Huete Jimenez SubstringWords Substring_Words(const char *, bool);
325*6eef5f0cSAntonio Huete Jimenez
326*6eef5f0cSAntonio Huete Jimenez MAKE_INLINE void
SubstringWords_Init(SubstringWords * w)327*6eef5f0cSAntonio Huete Jimenez SubstringWords_Init(SubstringWords *w)
328*6eef5f0cSAntonio Huete Jimenez {
329*6eef5f0cSAntonio Huete Jimenez w->words = NULL;
330*6eef5f0cSAntonio Huete Jimenez w->len = 0;
331*6eef5f0cSAntonio Huete Jimenez w->freeIt = NULL;
332*6eef5f0cSAntonio Huete Jimenez }
333*6eef5f0cSAntonio Huete Jimenez
334*6eef5f0cSAntonio Huete Jimenez MAKE_INLINE void
SubstringWords_Free(SubstringWords w)335*6eef5f0cSAntonio Huete Jimenez SubstringWords_Free(SubstringWords w)
336*6eef5f0cSAntonio Huete Jimenez {
337*6eef5f0cSAntonio Huete Jimenez free(w.words);
338*6eef5f0cSAntonio Huete Jimenez free(w.freeIt);
339*6eef5f0cSAntonio Huete Jimenez }
340*6eef5f0cSAntonio Huete Jimenez
341*6eef5f0cSAntonio Huete Jimenez
342*6eef5f0cSAntonio Huete Jimenez char *str_concat2(const char *, const char *);
343*6eef5f0cSAntonio Huete Jimenez char *str_concat3(const char *, const char *, const char *);
344*6eef5f0cSAntonio Huete Jimenez
345*6eef5f0cSAntonio Huete Jimenez bool Str_Match(const char *, const char *);
346*6eef5f0cSAntonio Huete Jimenez
347*6eef5f0cSAntonio Huete Jimenez void Str_Intern_Init(void);
348*6eef5f0cSAntonio Huete Jimenez void Str_Intern_End(void);
349*6eef5f0cSAntonio Huete Jimenez const char *Str_Intern(const char *);
350