1 //
2 //   lst.c
3 //
4 //   Oliver Fromme  <olli@fromme.com>
5 //   @(#)$Id: lst.c,v 1.6 1998/12/04 09:04:42 olli Exp $
6 //
7 
8 static const char cvsid[]
9     = "@(#)$Id: lst.c,v 1.6 1998/12/04 09:04:42 olli Exp $";
10 
11 #include <string.h>
12 #include <stdlib.h>
13 
14 #include "lst.h"
15 #include "utils.h"
16 
17 //
18 //   The following functions work on simple, unordered lists.
19 //
20 
21 void
simple_list_init(simple_list * l)22 simple_list_init (simple_list *l)
23 {
24 	l->count = 0;
25 	l->list = NULL;
26 }
27 
28 void
simple_list_add(simple_list * l,void * new,int size)29 simple_list_add (simple_list *l, void *new, int size)
30 {
31 	if (!(l->list = realloc(l->list, (l->count + 1) * sizeof(*l->list))))
32 		out_of_memory();
33 	if (new && size) {
34 		l->list[l->count] = tmalloc(size);
35 		memcpy (l->list[l->count++], new, size);
36 	}
37 	else
38 		l->list[l->count++] = NULL;
39 }
40 
41 int
simple_list_count(simple_list * l)42 simple_list_count (simple_list *l)
43 {
44 	return l->count;
45 }
46 
47 //
48 //   Traverse a simple list.
49 //
50 //   If the job function returns a non-zero value, the
51 //   traversal is aborted, and the function returns with
52 //   that value.  If all job functions return zero, the
53 //   return value is also zero.
54 //
55 //   If TRAVERSE_IGNORERESULT is set in the flags, the
56 //   return values of the job functions are ignored, and
57 //   the return value is always zero.
58 //
59 
60 int
simple_list_traverse(simple_list * l,jobfunc * job,void * jobdata,unsigned flags)61 simple_list_traverse (simple_list *l, jobfunc *job, void *jobdata,
62     unsigned flags)
63 {
64 	int i, result;
65 
66 	if (!l)
67 		return 0;
68 	if (flags & TRAVERSE_IGNORERESULT) {
69 		for (i = 0; i < l->count; i++)
70 			if (l->list[i])
71 				job (l->list[i], jobdata);
72 	}
73 	else
74 		for (i = 0; i < l->count; i++)
75 			if (l->list[i])
76 				if ((result = job(l->list[i], jobdata)))
77 					return result;
78 	return 0;
79 }
80 
81 void
simple_list_done(simple_list * l)82 simple_list_done (simple_list *l)
83 {
84 	int i;
85 
86 	for (i = 0; i < l->count; i++)
87 		if (l->list[i])
88 			free (l->list[i]);
89 	free (l->list);
90 	l->count = 0;
91 	l->list = NULL;
92 }
93 
94 //
95 //   The following functions work on CSV strings
96 //   (CSV = comma-separated values).
97 //
98 //   csv_count() returns the number of values in a CSV string.
99 //               Note that values can also be empty, i.e.
100 //               csv_count("x,,y,") == 4 && csv_count("") == 1.
101 //
102 //   csv_value() returns a zero-terminated copy of the n'th
103 //               value in a CSV string, starting with n = 0.
104 //               Returns NULL if n >= csv_count().
105 //               Note that it's the responsibility of the
106 //               calling function to free() the copy of the
107 //               value.
108 //
109 //   csv_traverse() calls the given job function for each value
110 //                  of the given CSV string.
111 //
112 //   NB:  We're not using strtok() because of several
113 //   disadvantages, and we're not using strsep() either
114 //   because it's not portable enough.
115 //
116 
117 int
csv_count(char * csv)118 csv_count (char *csv)
119 {
120 	int i;
121 
122 	i = 1;
123 	while (*csv)
124 		if (*csv++ == ',')
125 			i++;
126 	return i;
127 }
128 
129 char *
csv_value(char * csv,int n)130 csv_value (char *csv, int n)
131 {
132 	char *v;
133 
134 	if (n) {
135 		while (*csv)
136 			if (*csv++ == ',')
137 				if (!--n)
138 					break;
139 		if (n)
140 			return NULL;
141 	}
142 	if (!(v = strndup(csv, strcspn(csv, ","))))
143 		out_of_memory();
144 	return justify(v);
145 }
146 
147 int
csv_traverse(char * csv,jobfunc * job,void * jobdata,unsigned flags)148 csv_traverse (char *csv, jobfunc *job, void *jobdata, unsigned flags)
149 {
150 	char *v;
151 	int len, result;
152 
153 	for (;;) {
154 		len = strcspn(csv, ",");
155 		if (!(v = strndup(csv, len)))
156 			out_of_memory();
157 		result = job(justify(v), jobdata);
158 		free (v);
159 		if (!result && !(flags & TRAVERSE_IGNORERESULT))
160 			return FALSE;
161 		if (!*(csv += len))
162 			break;
163 		csv++;
164 	}
165 	return TRUE;
166 }
167 
168 //--
169