Home | History | Annotate | Line # | Download | only in driver
      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 **
     55 list_array(const struct list *l)
     56 {
     57 
     58 	return l->array;
     59 }
     60 
     61 /*
     62  * return array count
     63  */
     64 size_t
     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 *
     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
     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
    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
    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
    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
    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
    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