1 /*
2 * SysDB - src/utils/strings.c
3 * Copyright (C) 2016 Sebastian 'tokkee' Harl <sh@tokkee.org>
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
17 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
19 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
28 #if HAVE_CONFIG_H
29 # include "config.h"
30 #endif
32 #include "utils/strings.h"
34 #include <assert.h>
36 #include <stdlib.h>
37 #include <string.h>
39 /*
40 * private helper functions
41 */
43 static int
44 ensure_len(char ***s, size_t *s_len, size_t len)
45 {
46 char **tmp;
48 if ((! s) || (! s_len))
49 return -1;
51 if (! len) {
52 if (*s)
53 free(*s);
54 *s = NULL;
55 *s_len = 0;
56 return 0;
57 }
59 if (*s) {
60 tmp = realloc(*s, len * sizeof(*tmp));
61 if (tmp && (len > *s_len))
62 memset(tmp + *s_len, 0, (len - *s_len) * sizeof(*tmp));
63 }
64 else
65 tmp = calloc(len, sizeof(*tmp));
67 if (! tmp)
68 return -1;
70 *s = tmp;
71 *s_len = len;
72 return 0;
73 } /* ensure_len */
75 /*
76 * public API
77 */
79 int
80 stringv_copy(char ***dst, size_t *dst_len,
81 const char * const *src, size_t src_len)
82 {
83 size_t i;
85 if (src_len && (! src))
86 return -1;
87 if (ensure_len(dst, dst_len, src_len))
88 return -1;
89 assert(dst);
91 for (i = 0; i < src_len; ++i) {
92 if ((*dst)[i])
93 free((*dst)[i]);
94 (*dst)[i] = strdup(src[i]);
95 if (! (*dst)[i])
96 return -1;
97 }
98 return 0;
99 } /* stringv_copy */
101 int
102 stringv_append(char ***s, size_t *s_len, const char *elem)
103 {
104 size_t i;
106 if ((! s_len) || ensure_len(s, s_len, *s_len + 1))
107 return -1;
108 assert(s);
110 i = *s_len - 1;
111 (*s)[i] = strdup(elem);
112 if (! (*s)[i])
113 return -1;
114 return 0;
115 } /* stringv_append */
117 int
118 stringv_append_if_missing(char ***s, size_t *s_len, const char *elem)
119 {
120 size_t i;
122 if ((! s) || (! s_len))
123 return -1;
125 for (i = 0; i < *s_len; i++)
126 if (! strcmp((*s)[i], elem))
127 return 0;
129 return stringv_append(s, s_len, elem);
130 } /* stringv_append_if_missing */
132 void
133 stringv_free(char ***s, size_t *s_len)
134 {
135 size_t i;
137 if (*s) {
138 for (i = 0; i < *s_len; ++i) {
139 if ((*s)[i])
140 free((*s)[i]);
141 (*s)[i] = NULL;
142 }
143 free(*s);
144 }
146 *s = NULL;
147 *s_len = 0;
148 } /* stringv_free */
150 /* vim: set tw=78 sw=4 ts=4 noexpandtab : */