Remove GLib dependency.
[pwmd.git] / src / util-string.c
blob69751c73f34f5d9e18f65e473aca7fa1c57183f7
1 /*
2 Copyright (C) 2012
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 string_free(struct string_s *s, int with_data)
33 if (!s)
34 return;
36 if (with_data)
37 xfree(s->str);
39 xfree(s);
42 struct string_s *string_erase(struct string_s *s, ssize_t pos, ssize_t len)
44 if (pos > s->len)
45 return s;
47 if (len == -1) {
48 s->str[pos] = 0;
49 s->len = s->len - pos;
50 return s;
53 int n = s->len - pos;
54 n -= len;
55 memmove(&s->str[pos], &s->str[pos+len], n);
56 s->len -= len;
57 s->str[s->len] = 0;
58 return s;
61 struct string_s *string_new(const char *str)
63 struct string_s *s = xcalloc(1, sizeof(struct string_s));
65 if (str) {
66 s->str = str_dup(str);
67 if (!s->str) {
68 xfree(s);
69 return NULL;
72 s->len = strlen(s->str);
73 s->allocated = s->len + 1;
76 return s;
79 struct string_s *string_append(struct string_s *s, const char *str)
81 size_t len = strlen(str);
83 if (s->allocated < len + s->len + 1) {
84 char *p = xrealloc(s->str, (len + s->len + 1)*sizeof(char));
86 if (!p)
87 return NULL;
89 s->str = p;
90 s->allocated = s->len + len + 1;
93 memcpy(&s->str[s->len], str, len);
94 s->len += len;
95 s->str[s->len] = 0;
96 return s;
99 struct string_s *string_truncate(struct string_s *s, size_t n)
101 if (s->len < n)
102 return s;
104 s->str[n] = 0;
105 s->len = n;
106 return s;
109 struct string_s *string_prepend(struct string_s *s, const char *str)
111 size_t len = strlen(str);
113 if (s->allocated < s->len + len + 1) {
114 char *p = xrealloc(s->str, (len + s->len + 1)*sizeof(char));
116 if (!p)
117 return NULL;
119 s->str = p;
120 s->allocated = s->len + len + 1;
123 memmove(&s->str[len], s->str, s->len);
124 memcpy(s->str, str, len);
125 s->len += len;
126 s->str[s->len] = 0;
127 return s;
130 struct string_s *string_append_printf(struct string_s *s, const char *fmt, ...)
132 va_list ap;
133 char *buf = NULL;
134 size_t len;
136 va_start(ap, fmt);
137 len = str_vasprintf(&buf, fmt, ap);
138 va_end(ap);
140 if (len == -1)
141 return NULL;
143 s = string_append(s, buf);
144 xfree(buf);
145 return s;
148 struct string_s *string_insert_c(struct string_s *s, ssize_t pos, char c)
150 size_t len = s->len + 2;
152 if (pos >= s->allocated)
153 len = pos+2;
155 if (s->allocated < len) {
156 char *p = xrealloc(s->str, len*sizeof(char));
158 if (!p)
159 return NULL;
161 s->str = p;
162 s->allocated = len;
165 memmove(&s->str[pos+1], &s->str[pos], s->len - pos);
166 s->str[pos] = c;
167 s->len = pos+1 == s->allocated ? pos+1 : s->len+1;
168 s->str[s->len] = 0;
169 return s;
172 int strv_length(char **a)
174 int n = 0;
176 while (a && *a++)
177 n++;
179 return n;
182 /* 'str' must already be allocated. */
183 char **strv_cat(char **a, char *str)
185 int len = a ? strv_length(a) : 0;
186 char **dst;
188 dst = xrealloc(a, (len+2)*sizeof(char **));
189 if (!dst)
190 return NULL;
192 dst[len++] = str;
193 dst[len] = NULL;
194 return dst;
197 int strv_printf(char ***array, const char *fmt, ...)
199 char **a;
200 va_list ap;
201 char *buf;
202 int ret;
204 va_start(ap, fmt);
205 ret = str_vasprintf(&buf, fmt, ap);
206 va_end(ap);
208 if (ret == -1)
209 return 0;
211 a = strv_cat(*array, buf);
212 if (!a) {
213 xfree(buf);
214 return 0;
217 *array = a;
218 return 1;
221 void strv_free(char **a)
223 char **p;
225 for (p = a; p && *p; p++)
226 xfree(*p);
228 xfree(a);
231 char **strv_dup(char **src)
233 char **dst = NULL;
234 char **p;
236 for (p = src; p && *p; p++) {
237 char **tmp;
238 char *xp = str_dup(*p);
240 if (!xp) {
241 strv_free(dst);
242 return NULL;
245 tmp = strv_cat(dst, xp);
246 if (!tmp) {
247 xfree(xp);
248 strv_free(dst);
249 return NULL;
252 dst = tmp;
255 return dst;
258 char **strv_catv(char **dst, char **src)
260 char **p;
261 char **d = NULL;
263 if (dst && *dst) {
264 d = strv_dup(dst);
265 if (!d)
266 return NULL;
269 for (p = src; p && *p; p++) {
270 char **tmp;
271 char *xp = str_dup(*p);
273 if (!xp) {
274 strv_free(d);
275 return NULL;
278 tmp = strv_cat(d, xp);
279 if (!tmp) {
280 xfree(xp);
281 strv_free(d);
282 return NULL;
285 d = tmp;
288 return d;
291 char **str_split(const char *str, const char *delim, int count)
293 char **dst = NULL;
294 int index = 0;
295 const char *dp = delim, *p;
296 size_t dlen = strlen(delim);
297 size_t pos = 0, lastpos = 0;
299 if (!str || !*str)
300 return NULL;
302 for (p = str; *p; p++) {
303 if (*p == *dp++) {
304 if (!*dp) {
305 char **tmp;
306 char *xp;
307 size_t len = pos - lastpos - dlen + 1;
309 xp = xmalloc(len+1);
310 if (!xp) {
311 strv_free(dst);
312 return NULL;
315 memcpy(xp, &str[lastpos], len);
316 xp[len] = 0;
318 tmp = strv_cat(dst, xp);
319 if (!tmp) {
320 xfree(xp);
321 strv_free(dst);
322 return NULL;
325 dst = tmp;
326 lastpos = pos+1;
328 if (count > 0 && index == count && *(p+1)) {
329 if (!strv_printf(&dst, "%s", p+1)) {
330 strv_free(dst);
331 return NULL;
334 return dst;
337 dp = delim;
340 pos++;
341 continue;
344 pos++;
345 dp = delim;
348 p = str+lastpos;
349 if (!strv_printf(&dst, "%s", p)) {
350 strv_free(dst);
351 return NULL;
354 return dst;
357 char *strv_join(char *delim, char **a)
359 char **p;
360 char *dst = NULL;
361 struct string_s *s = string_new("");
363 if (!s)
364 return NULL;
366 for (p = a; *p; p++) {
367 struct string_s *sp;
369 sp = string_append_printf(s, "%s%s", *p, delim && *(p+1) ? delim : "");
370 if (!sp) {
371 string_free(s, 1);
372 return NULL;
375 s = sp;
378 dst = s->str;
379 string_free(s, 0);
380 return dst;
383 char *str_down(char *str)
385 char *p;
387 for (p = str; *p; p++) {
388 if (isascii(*p))
389 *p = tolower(*p);
392 return str;
395 char *str_chomp(char *str)
397 int len = strlen(str);
398 char *p = str+len-1;
400 while (len && isspace(*p)) {
401 *p-- = 0;
402 len--;
405 p = str;
406 while (isspace(*p)) {
407 p++;
408 len--;
411 memmove(str, p, len);
412 str[len] = 0;
413 return str;
416 char *str_dup(const char *str)
418 char *t;
419 size_t len;
420 register size_t c;
422 len = strlen(str);
423 t = xmalloc((len+1)*sizeof(char));
424 if (!t)
425 return NULL;
427 for (c = 0; c < len; c++)
428 t[c] = str[c];
430 t[c] = 0;
431 return t;
434 char *str_asprintf(const char *fmt, ...)
436 va_list ap;
437 char *result;
438 int len;
440 va_start(ap, fmt);
441 len = str_vasprintf(&result, fmt, ap);
442 va_end(ap);
443 return len == -1 ? NULL : result;
446 #define BUFSIZE 128
447 int str_vasprintf(char **result, const char *fmt, va_list ap)
449 size_t alloc = BUFSIZE;
450 char *buf = NULL;
451 int len;
453 for (;;) {
454 char *p = xrealloc(buf, alloc*sizeof(char));
455 va_list cp;
457 if (!p) {
458 xfree(buf);
459 return -1;
462 buf = p;
463 va_copy(cp, ap);
464 len = vsnprintf(buf, alloc, fmt, cp);
465 va_end(cp);
467 if (len >= alloc) {
468 alloc = len+1;
469 continue;
472 break;
475 *result = buf;
476 return len;