Recreate doc/pwmd.html after 'make distclean'.
[pwmd.git] / src / util-string.c
blob9eed0953a871879e52ebc474e0d1a649845d4526
1 /*
2 Copyright (C) 2012, 2013
3 Ben Kibbey <bjk@luxsci.net>
5 This file is part of pwmd.
7 Pwmd is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 2 of the License, or
10 (at your option) any later version.
12 Pwmd is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with Pwmd. If not, see <http://www.gnu.org/licenses/>.
20 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
24 #include <stdio.h>
25 #include <string.h>
26 #include <ctype.h>
28 #include "util-string.h"
29 #include "mem.h"
31 void
32 string_free (struct string_s *s, int with_data)
34 if (!s)
35 return;
37 if (with_data)
38 xfree (s->str);
40 xfree (s);
43 struct string_s *
44 string_erase (struct string_s *s, ssize_t pos, ssize_t len)
46 if (pos > s->len)
47 return s;
49 if (len == -1)
51 s->str[pos] = 0;
52 s->len = s->len - pos;
53 return s;
56 int n = s->len - pos;
57 n -= len;
58 memmove (&s->str[pos], &s->str[pos + len], n);
59 s->len -= len;
60 s->str[s->len] = 0;
61 return s;
64 /* Be careful about allocations since other string_ functions may
65 * realloc the 'str' pointer. */
66 struct string_s *
67 string_new_content (char *str)
69 struct string_s *s = xcalloc (1, sizeof (struct string_s));
71 s->str = str;
72 s->len = strlen (s->str);
73 s->allocated = s->len + 1;
74 return s;
77 struct string_s *
78 string_new (const char *str)
80 struct string_s *s = xcalloc (1, sizeof (struct string_s));
82 if (str)
84 s->str = str_dup (str);
85 if (!s->str)
87 xfree (s);
88 return NULL;
91 s->len = strlen (s->str);
92 s->allocated = s->len + 1;
95 return s;
98 struct string_s *
99 string_append (struct string_s *s, const char *str)
101 size_t len = strlen (str);
103 if (s->allocated < len + s->len + 1)
105 char *p = xrealloc (s->str, (len + s->len + 1) * sizeof (char));
107 if (!p)
108 return NULL;
110 s->str = p;
111 s->allocated = s->len + len + 1;
114 memcpy (&s->str[s->len], str, len);
115 s->len += len;
116 s->str[s->len] = 0;
117 return s;
120 struct string_s *
121 string_truncate (struct string_s *s, size_t n)
123 if (s->len < n)
124 return s;
126 s->str[n] = 0;
127 s->len = n;
128 return s;
131 struct string_s *
132 string_prepend (struct string_s *s, const char *str)
134 size_t len = strlen (str);
136 if (s->allocated < s->len + len + 1)
138 char *p = xrealloc (s->str, (len + s->len + 1) * sizeof (char));
140 if (!p)
141 return NULL;
143 s->str = p;
144 s->allocated = s->len + len + 1;
147 memmove (&s->str[len], s->str, s->len);
148 memcpy (s->str, str, len);
149 s->len += len;
150 s->str[s->len] = 0;
151 return s;
154 struct string_s *
155 string_append_printf (struct string_s *s, const char *fmt, ...)
157 va_list ap;
158 char *buf = NULL;
159 size_t len;
161 va_start (ap, fmt);
162 len = str_vasprintf (&buf, fmt, ap);
163 va_end (ap);
165 if (len == -1)
166 return NULL;
168 s = string_append (s, buf);
169 xfree (buf);
170 return s;
173 struct string_s *
174 string_insert_c (struct string_s *s, ssize_t pos, char c)
176 size_t len = s->len + 2;
178 if (pos >= s->allocated)
179 len = pos + 2;
181 if (s->allocated < len)
183 char *p = xrealloc (s->str, len * sizeof (char));
185 if (!p)
186 return NULL;
188 s->str = p;
189 s->allocated = len;
192 memmove (&s->str[pos + 1], &s->str[pos], s->len - pos);
193 s->str[pos] = c;
194 s->len = pos + 1 == s->allocated ? pos + 1 : s->len + 1;
195 s->str[s->len] = 0;
196 return s;
200 strv_length (char **a)
202 int n = 0;
204 while (a && *a++)
205 n++;
207 return n;
210 /* 'str' must already be allocated. */
211 char **
212 strv_cat (char **a, char *str)
214 int len = a ? strv_length (a) : 0;
215 char **dst;
217 dst = xrealloc (a, (len + 2) * sizeof (char **));
218 if (!dst)
219 return NULL;
221 dst[len++] = str;
222 dst[len] = NULL;
223 return dst;
227 strv_printf (char ***array, const char *fmt, ...)
229 char **a;
230 va_list ap;
231 char *buf;
232 int ret;
234 va_start (ap, fmt);
235 ret = str_vasprintf (&buf, fmt, ap);
236 va_end (ap);
238 if (ret == -1)
239 return 0;
241 a = strv_cat (*array, buf);
242 if (!a)
244 xfree (buf);
245 return 0;
248 *array = a;
249 return 1;
252 void
253 strv_free (char **a)
255 char **p;
257 for (p = a; p && *p; p++)
258 xfree (*p);
260 xfree (a);
263 char **
264 strv_dup (char **src)
266 char **dst = NULL;
267 char **p;
269 for (p = src; p && *p; p++)
271 char **tmp;
272 char *xp = str_dup (*p);
274 if (!xp)
276 strv_free (dst);
277 return NULL;
280 tmp = strv_cat (dst, xp);
281 if (!tmp)
283 xfree (xp);
284 strv_free (dst);
285 return NULL;
288 dst = tmp;
291 return dst;
294 char **
295 strv_catv (char **dst, char **src)
297 char **p;
298 char **d = NULL;
300 if (dst && *dst)
302 d = strv_dup (dst);
303 if (!d)
304 return NULL;
307 for (p = src; p && *p; p++)
309 char **tmp;
310 char *xp = str_dup (*p);
312 if (!xp)
314 strv_free (d);
315 return NULL;
318 tmp = strv_cat (d, xp);
319 if (!tmp)
321 xfree (xp);
322 strv_free (d);
323 return NULL;
326 d = tmp;
329 return d;
332 char **
333 str_split (const char *str, const char *delim, int count)
335 char **dst = NULL;
336 int index = 0;
337 const char *dp = delim, *p;
338 size_t dlen = strlen (delim);
339 size_t pos = 0, lastpos = 0;
341 if (!str || !*str)
342 return NULL;
344 for (p = str; *p; p++)
346 if (*p == *dp++)
348 if (!*dp)
350 char **tmp;
351 char *xp;
352 size_t len = pos - lastpos - dlen + 1;
354 xp = xmalloc (len + 1);
355 if (!xp)
357 strv_free (dst);
358 return NULL;
361 memcpy (xp, &str[lastpos], len);
362 xp[len] = 0;
364 tmp = strv_cat (dst, xp);
365 if (!tmp)
367 xfree (xp);
368 strv_free (dst);
369 return NULL;
372 dst = tmp;
373 lastpos = pos + 1;
375 if (count > 0 && index == count && *(p + 1))
377 if (!strv_printf (&dst, "%s", p + 1))
379 strv_free (dst);
380 return NULL;
383 return dst;
386 dp = delim;
389 pos++;
390 continue;
393 pos++;
394 dp = delim;
397 p = str + lastpos;
398 if (!strv_printf (&dst, "%s", p))
400 strv_free (dst);
401 return NULL;
404 return dst;
407 char *
408 strv_join (char *delim, char **a)
410 char **p;
411 char *dst = NULL;
412 struct string_s *s = string_new ("");
414 if (!s)
415 return NULL;
417 for (p = a; *p; p++)
419 struct string_s *sp;
421 sp = string_append_printf (s, "%s%s", *p, delim
422 && *(p + 1) ? delim : "");
423 if (!sp)
425 string_free (s, 1);
426 return NULL;
429 s = sp;
432 dst = s->str;
433 string_free (s, 0);
434 return dst;
437 char *
438 str_down (char *str)
440 char *p;
442 for (p = str; *p; p++)
444 if (isascii (*p))
445 *p = tolower (*p);
448 return str;
451 char *
452 str_chomp (char *str)
454 int len = strlen (str);
455 char *p = str + len - 1;
457 while (len && isspace (*p))
459 *p-- = 0;
460 len--;
463 p = str;
464 while (isspace (*p))
466 p++;
467 len--;
470 memmove (str, p, len);
471 str[len] = 0;
472 return str;
475 char *
476 str_dup (const char *str)
478 char *t;
479 size_t len;
480 register size_t c;
482 len = strlen (str);
483 t = xmalloc ((len + 1) * sizeof (char));
484 if (!t)
485 return NULL;
487 for (c = 0; c < len; c++)
488 t[c] = str[c];
490 t[c] = 0;
491 return t;
494 char *
495 str_asprintf (const char *fmt, ...)
497 va_list ap;
498 char *result;
499 int len;
501 va_start (ap, fmt);
502 len = str_vasprintf (&result, fmt, ap);
503 va_end (ap);
504 return len == -1 ? NULL : result;
507 #define BUFSIZE 128
509 str_vasprintf (char **result, const char *fmt, va_list ap)
511 size_t alloc = BUFSIZE;
512 char *buf = NULL;
513 int len;
515 for (;;)
517 char *p = xrealloc (buf, alloc * sizeof (char));
518 va_list cp;
520 if (!p)
522 xfree (buf);
523 return -1;
526 buf = p;
527 va_copy (cp, ap);
528 len = vsnprintf (buf, alloc, fmt, cp);
529 va_end (cp);
531 if (len >= alloc)
533 alloc = len + 1;
534 continue;
537 break;
540 *result = buf;
541 return len;