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