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 42struct 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 */ 54const char ** 55list_array(const struct list *l) 56{ 57 58 return l->array; 59} 60 61/* 62 * return array count 63 */ 64size_t 65list_count(const struct list *l) 66{ 67 68 return l->arrayused; 69} 70 71/* 72 * allocate a new list header 73 */ 74struct list * 75list_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 */ 94void 95list_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 */ 106void 107list_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 */ 118void 119list_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 */ 135void 136list_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 */ 168void 169list_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 */ 179void 180list_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