Reimplement the KEEPALIVE status message.
[pwmd.git] / src / util-string.c
blob0a2489a9410f9a0250a2acc0e782eb04857576c1
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 struct string_s *
65 string_new (const char *str)
67 struct string_s *s = xcalloc (1, sizeof (struct string_s));
69 if (str)
71 s->str = str_dup (str);
72 if (!s->str)
74 xfree (s);
75 return NULL;
78 s->len = strlen (s->str);
79 s->allocated = s->len + 1;
82 return s;
85 struct string_s *
86 string_append (struct string_s *s, const char *str)
88 size_t len = strlen (str);
90 if (s->allocated < len + s->len + 1)
92 char *p = xrealloc (s->str, (len + s->len + 1) * sizeof (char));
94 if (!p)
95 return NULL;
97 s->str = p;
98 s->allocated = s->len + len + 1;
101 memcpy (&s->str[s->len], str, len);
102 s->len += len;
103 s->str[s->len] = 0;
104 return s;
107 struct string_s *
108 string_truncate (struct string_s *s, size_t n)
110 if (s->len < n)
111 return s;
113 s->str[n] = 0;
114 s->len = n;
115 return s;
118 struct string_s *
119 string_prepend (struct string_s *s, const char *str)
121 size_t len = strlen (str);
123 if (s->allocated < s->len + len + 1)
125 char *p = xrealloc (s->str, (len + s->len + 1) * sizeof (char));
127 if (!p)
128 return NULL;
130 s->str = p;
131 s->allocated = s->len + len + 1;
134 memmove (&s->str[len], s->str, s->len);
135 memcpy (s->str, str, len);
136 s->len += len;
137 s->str[s->len] = 0;
138 return s;
141 struct string_s *
142 string_append_printf (struct string_s *s, const char *fmt, ...)
144 va_list ap;
145 char *buf = NULL;
146 size_t len;
148 va_start (ap, fmt);
149 len = str_vasprintf (&buf, fmt, ap);
150 va_end (ap);
152 if (len == -1)
153 return NULL;
155 s = string_append (s, buf);
156 xfree (buf);
157 return s;
160 struct string_s *
161 string_insert_c (struct string_s *s, ssize_t pos, char c)
163 size_t len = s->len + 2;
165 if (pos >= s->allocated)
166 len = pos + 2;
168 if (s->allocated < len)
170 char *p = xrealloc (s->str, len * sizeof (char));
172 if (!p)
173 return NULL;
175 s->str = p;
176 s->allocated = len;
179 memmove (&s->str[pos + 1], &s->str[pos], s->len - pos);
180 s->str[pos] = c;
181 s->len = pos + 1 == s->allocated ? pos + 1 : s->len + 1;
182 s->str[s->len] = 0;
183 return s;
187 strv_length (char **a)
189 int n = 0;
191 while (a && *a++)
192 n++;
194 return n;
197 /* 'str' must already be allocated. */
198 char **
199 strv_cat (char **a, char *str)
201 int len = a ? strv_length (a) : 0;
202 char **dst;
204 dst = xrealloc (a, (len + 2) * sizeof (char **));
205 if (!dst)
206 return NULL;
208 dst[len++] = str;
209 dst[len] = NULL;
210 return dst;
214 strv_printf (char ***array, const char *fmt, ...)
216 char **a;
217 va_list ap;
218 char *buf;
219 int ret;
221 va_start (ap, fmt);
222 ret = str_vasprintf (&buf, fmt, ap);
223 va_end (ap);
225 if (ret == -1)
226 return 0;
228 a = strv_cat (*array, buf);
229 if (!a)
231 xfree (buf);
232 return 0;
235 *array = a;
236 return 1;
239 void
240 strv_free (char **a)
242 char **p;
244 for (p = a; p && *p; p++)
245 xfree (*p);
247 xfree (a);
250 char **
251 strv_dup (char **src)
253 char **dst = NULL;
254 char **p;
256 for (p = src; p && *p; p++)
258 char **tmp;
259 char *xp = str_dup (*p);
261 if (!xp)
263 strv_free (dst);
264 return NULL;
267 tmp = strv_cat (dst, xp);
268 if (!tmp)
270 xfree (xp);
271 strv_free (dst);
272 return NULL;
275 dst = tmp;
278 return dst;
281 char **
282 strv_catv (char **dst, char **src)
284 char **p;
285 char **d = NULL;
287 if (dst && *dst)
289 d = strv_dup (dst);
290 if (!d)
291 return NULL;
294 for (p = src; p && *p; p++)
296 char **tmp;
297 char *xp = str_dup (*p);
299 if (!xp)
301 strv_free (d);
302 return NULL;
305 tmp = strv_cat (d, xp);
306 if (!tmp)
308 xfree (xp);
309 strv_free (d);
310 return NULL;
313 d = tmp;
316 return d;
319 char **
320 str_split (const char *str, const char *delim, int count)
322 char **dst = NULL;
323 int index = 0;
324 const char *dp = delim, *p;
325 size_t dlen = strlen (delim);
326 size_t pos = 0, lastpos = 0;
328 if (!str || !*str)
329 return NULL;
331 for (p = str; *p; p++)
333 if (*p == *dp++)
335 if (!*dp)
337 char **tmp;
338 char *xp;
339 size_t len = pos - lastpos - dlen + 1;
341 xp = xmalloc (len + 1);
342 if (!xp)
344 strv_free (dst);
345 return NULL;
348 memcpy (xp, &str[lastpos], len);
349 xp[len] = 0;
351 tmp = strv_cat (dst, xp);
352 if (!tmp)
354 xfree (xp);
355 strv_free (dst);
356 return NULL;
359 dst = tmp;
360 lastpos = pos + 1;
362 if (count > 0 && index == count && *(p + 1))
364 if (!strv_printf (&dst, "%s", p + 1))
366 strv_free (dst);
367 return NULL;
370 return dst;
373 dp = delim;
376 pos++;
377 continue;
380 pos++;
381 dp = delim;
384 p = str + lastpos;
385 if (!strv_printf (&dst, "%s", p))
387 strv_free (dst);
388 return NULL;
391 return dst;
394 char *
395 strv_join (char *delim, char **a)
397 char **p;
398 char *dst = NULL;
399 struct string_s *s = string_new ("");
401 if (!s)
402 return NULL;
404 for (p = a; *p; p++)
406 struct string_s *sp;
408 sp = string_append_printf (s, "%s%s", *p, delim
409 && *(p + 1) ? delim : "");
410 if (!sp)
412 string_free (s, 1);
413 return NULL;
416 s = sp;
419 dst = s->str;
420 string_free (s, 0);
421 return dst;
424 char *
425 str_down (char *str)
427 char *p;
429 for (p = str; *p; p++)
431 if (isascii (*p))
432 *p = tolower (*p);
435 return str;
438 char *
439 str_chomp (char *str)
441 int len = strlen (str);
442 char *p = str + len - 1;
444 while (len && isspace (*p))
446 *p-- = 0;
447 len--;
450 p = str;
451 while (isspace (*p))
453 p++;
454 len--;
457 memmove (str, p, len);
458 str[len] = 0;
459 return str;
462 char *
463 str_dup (const char *str)
465 char *t;
466 size_t len;
467 register size_t c;
469 len = strlen (str);
470 t = xmalloc ((len + 1) * sizeof (char));
471 if (!t)
472 return NULL;
474 for (c = 0; c < len; c++)
475 t[c] = str[c];
477 t[c] = 0;
478 return t;
481 char *
482 str_asprintf (const char *fmt, ...)
484 va_list ap;
485 char *result;
486 int len;
488 va_start (ap, fmt);
489 len = str_vasprintf (&result, fmt, ap);
490 va_end (ap);
491 return len == -1 ? NULL : result;
494 #define BUFSIZE 128
496 str_vasprintf (char **result, const char *fmt, va_list ap)
498 size_t alloc = BUFSIZE;
499 char *buf = NULL;
500 int len;
502 for (;;)
504 char *p = xrealloc (buf, alloc * sizeof (char));
505 va_list cp;
507 if (!p)
509 xfree (buf);
510 return -1;
513 buf = p;
514 va_copy (cp, ap);
515 len = vsnprintf (buf, alloc, fmt, cp);
516 va_end (cp);
518 if (len >= alloc)
520 alloc = len + 1;
521 continue;
524 break;
527 *result = buf;
528 return len;