Fix valid_xml_element() and valid_xml_attribute() to use XML spec.
[pwmd.git] / src / util-string.c
blobbc89eab3b11456db0ada984be2affae26fcfa7bd
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 index++;
355 xp = xmalloc (len + 1);
356 if (!xp)
358 strv_free (dst);
359 return NULL;
362 memcpy (xp, &str[lastpos], len);
363 xp[len] = 0;
365 tmp = strv_cat (dst, xp);
366 if (!tmp)
368 xfree (xp);
369 strv_free (dst);
370 return NULL;
373 dst = tmp;
374 lastpos = pos + 1;
376 if (count > 0 && index+1 == count && *(p + 1))
378 if (!strv_printf (&dst, "%s", p + 1))
380 strv_free (dst);
381 return NULL;
384 return dst;
387 dp = delim;
390 pos++;
391 continue;
394 pos++;
395 dp = delim;
398 p = str + lastpos;
399 if (!strv_printf (&dst, "%s", p))
401 strv_free (dst);
402 return NULL;
405 return dst;
408 char *
409 strv_join (char *delim, char **a)
411 char **p;
412 char *dst = NULL;
413 struct string_s *s = string_new ("");
415 if (!s)
416 return NULL;
418 for (p = a; *p; p++)
420 struct string_s *sp;
422 sp = string_append_printf (s, "%s%s", *p, delim
423 && *(p + 1) ? delim : "");
424 if (!sp)
426 string_free (s, 1);
427 return NULL;
430 s = sp;
433 dst = s->str;
434 string_free (s, 0);
435 return dst;
438 char *
439 str_down (char *str)
441 char *p;
443 for (p = str; *p; p++)
445 if (isascii (*p))
446 *p = tolower (*p);
449 return str;
452 char *
453 str_chomp (char *str)
455 int len = strlen (str);
456 char *p = str + len - 1;
458 while (len && isspace (*p))
460 *p-- = 0;
461 len--;
464 p = str;
465 while (isspace (*p))
467 p++;
468 len--;
471 memmove (str, p, len);
472 str[len] = 0;
473 return str;
476 char *
477 str_dup (const char *str)
479 char *t;
480 size_t len;
481 register size_t c;
483 len = strlen (str);
484 t = xmalloc ((len + 1) * sizeof (char));
485 if (!t)
486 return NULL;
488 for (c = 0; c < len; c++)
489 t[c] = str[c];
491 t[c] = 0;
492 return t;
495 char *
496 str_asprintf (const char *fmt, ...)
498 va_list ap;
499 char *result;
500 int len;
502 va_start (ap, fmt);
503 len = str_vasprintf (&result, fmt, ap);
504 va_end (ap);
505 return len == -1 ? NULL : result;
508 #define BUFSIZE 128
510 str_vasprintf (char **result, const char *fmt, va_list ap)
512 size_t alloc = BUFSIZE;
513 char *buf = NULL;
514 int len;
516 for (;;)
518 char *p = xrealloc (buf, alloc * sizeof (char));
519 va_list cp;
521 if (!p)
523 xfree (buf);
524 return -1;
527 buf = p;
528 va_copy (cp, ap);
529 len = vsnprintf (buf, alloc, fmt, cp);
530 va_end (cp);
532 if (len >= alloc)
534 alloc = len + 1;
535 continue;
538 break;
541 *result = buf;
542 return len;