1 /* Id */
2 /* $NetBSD: list.c,v 1.1.1.1 2016/02/09 20:29:12 plunky Exp $ */
3
4 /*-
5 * Copyright (c) 2014 Iain Hibbert.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 */
25
26 #include <stdarg.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29
30 #include "driver.h"
31
32 /*
33 * A list is an opaque collection of strings. We can add strings, another
34 * list or an array of strings to the list. We can get a pointer to the
35 * array of strings in the list and the number of strings in it, and we
36 * can free the entire list when we are done.
37 */
38
39 #define COUNT 64 /* element count increments */
40 #define BLOCK 4096 /* buffer size increments */
41
42 struct list {
43 const char ** array;
44 size_t arraylen;
45 size_t arrayused;
46 void * buf;
47 size_t buflen;
48 size_t bufused;
49 };
50
51 /*
52 * return array pointer
53 */
54 const char **
list_array(const struct list * l)55 list_array(const struct list *l)
56 {
57
58 return l->array;
59 }
60
61 /*
62 * return array count
63 */
64 size_t
list_count(const struct list * l)65 list_count(const struct list *l)
66 {
67
68 return l->arrayused;
69 }
70
71 /*
72 * allocate a new list header
73 */
74 struct list *
list_alloc(void)75 list_alloc(void)
76 {
77 struct list *l;
78
79 l = xmalloc(sizeof(struct list));
80 l->array = xmalloc(COUNT * sizeof(char *));
81 l->array[0] = NULL;
82 l->arraylen = COUNT;
83 l->arrayused = 0;
84 l->buf = NULL;
85 l->buflen = 0;
86 l->bufused = 0;
87
88 return l;
89 }
90
91 /*
92 * release a list header and associated storage
93 */
94 void
list_free(struct list * l)95 list_free(struct list *l)
96 {
97
98 free(l->array);
99 free(l->buf);
100 free(l);
101 }
102
103 /*
104 * print out a list
105 */
106 void
list_print(const struct list * l)107 list_print(const struct list *l)
108 {
109 size_t i;
110
111 for (i = 0; i < l->arrayused; i++)
112 fprintf(stderr, "%s%s\n", (i == 0 ? "" : " "), l->array[i]);
113 }
114
115 /*
116 * add const string to list
117 */
118 void
list_add_nocopy(struct list * l,const char * str)119 list_add_nocopy(struct list *l, const char *str)
120 {
121
122 l->array[l->arrayused++] = str;
123
124 if (l->arrayused == l->arraylen) {
125 l->arraylen += COUNT;
126 l->array = xrealloc(l->array, l->arraylen * sizeof(char *));
127 }
128
129 l->array[l->arrayused] = NULL;
130 }
131
132 /*
133 * add formatted string to list, storing in list buffer
134 */
135 void
list_add(struct list * l,const char * str,...)136 list_add(struct list *l, const char *str, ...)
137 {
138 va_list ap;
139 void *p;
140 size_t s;
141 int n;
142
143 for (;;) {
144 p = l->buf + l->bufused;
145 s = l->buflen - l->bufused;
146
147 va_start(ap, str);
148 n = vsnprintf(p, s, str, ap);
149 va_end(ap);
150
151 if (n < 0)
152 error("vsnprintf");
153
154 if ((unsigned int)n < s)
155 break;
156
157 l->buflen += BLOCK;
158 l->buf = xrealloc(l->buf, l->buflen);
159 }
160
161 list_add_nocopy(l, p);
162 l->bufused += n;
163 }
164
165 /*
166 * add a NULL terminated array of const data to list
167 */
168 void
list_add_array(struct list * l,const char ** a)169 list_add_array(struct list *l, const char **a)
170 {
171
172 while (*a)
173 list_add_nocopy(l, *a++);
174 }
175
176 /*
177 * add another list to list (with copy)
178 */
179 void
list_add_list(struct list * l1,const struct list * l2)180 list_add_list(struct list *l1, const struct list *l2)
181 {
182 size_t i;
183
184 for (i = 0; i < l2->arrayused; i++)
185 list_add(l1, l2->array[i]);
186 }
187