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