summaryrefslogtreecommitdiffabout
path: root/lib/slist.c
Unidiff
Diffstat (limited to 'lib/slist.c') (more/less context) (ignore whitespace changes)
-rw-r--r--lib/slist.c127
1 files changed, 88 insertions, 39 deletions
diff --git a/lib/slist.c b/lib/slist.c
index b110350..46e516e 100644
--- a/lib/slist.c
+++ b/lib/slist.c
@@ -28,38 +28,47 @@ struct gray_slist_bucket {
28struct gray_slist { 28struct gray_slist {
29 struct gray_slist_bucket *head, *tail; 29 struct gray_slist_bucket *head, *tail;
30 struct gray_slist_bucket *free; 30 struct gray_slist_bucket *free;
31 int ec; /* error code */
31}; 32};
32 33
33static struct gray_slist_bucket * 34static struct gray_slist_bucket *
34alloc_bucket(size_t size) 35alloc_bucket(size_t size)
35{ 36{
36 struct gray_slist_bucket *p = gray_malloc(sizeof(*p) + size); 37 struct gray_slist_bucket *p = malloc(sizeof(*p) + size);
37 p->buf = (char*)(p + 1); 38 if (p) {
38 p->level = 0; 39 p->buf = (char*)(p + 1);
39 p->size = size; 40 p->level = 0;
40 p->next = NULL; 41 p->size = size;
42 p->next = NULL;
43 }
41 return p; 44 return p;
42} 45}
43 46
44static void 47static int
45alloc_pool(gray_slist_t slist, size_t size) 48alloc_pool(gray_slist_t slist, size_t size)
46{ 49{
47 struct gray_slist_bucket *p = alloc_bucket(GRAY_SLIST_BUCKET_SIZE); 50 struct gray_slist_bucket *p = alloc_bucket(GRAY_SLIST_BUCKET_SIZE);
51 if (!p) {
52 slist->ec = errno;
53 return 1;
54 }
48 if (slist->tail) 55 if (slist->tail)
49 slist->tail->next = p; 56 slist->tail->next = p;
50 else 57 else
51 slist->head = p; 58 slist->head = p;
52 slist->tail = p; 59 slist->tail = p;
60 return 0;
53} 61}
54 62
55static size_t 63static ssize_t
56copy_chars(gray_slist_t slist, const char *str, size_t n) 64copy_chars(gray_slist_t slist, const char *str, size_t n)
57{ 65{
58 size_t rest; 66 size_t rest;
59 67
60 68 if (!slist->head || slist->tail->level == slist->tail->size) {
61 if (!slist->head || slist->tail->level == slist->tail->size) 69 if (alloc_pool(slist, GRAY_SLIST_BUCKET_SIZE))
62 alloc_pool(slist, GRAY_SLIST_BUCKET_SIZE); 70 return -1;
71 }
63 rest = slist->tail->size - slist->tail->level; 72 rest = slist->tail->size - slist->tail->level;
64 if (n > rest) 73 if (n > rest)
65 n = rest; 74 n = rest;
@@ -69,13 +78,28 @@ copy_chars(gray_slist_t slist, const char *str, size_t n)
69} 78}
70 79
71gray_slist_t 80gray_slist_t
72gray_slist_create() 81gray_slist_create(void)
73{ 82{
74 gray_slist_t slist = gray_malloc(sizeof(*slist)); 83 gray_slist_t slist = malloc(sizeof(*slist));
75 slist->head = slist->tail = slist->free = 0; 84 if (slist) {
85 slist->head = slist->tail = slist->free = 0;
86 slist->ec = 0;
87 }
76 return slist; 88 return slist;
77} 89}
78 90
91int
92gray_slist_err(gray_slist_t slist)
93{
94 return slist->ec;
95}
96
97void
98gray_slist_clerr(gray_slist_t slist)
99{
100 slist->ec = 0;
101}
102
79void 103void
80gray_slist_clear(gray_slist_t slist) 104gray_slist_clear(gray_slist_t slist)
81{ 105{
@@ -84,14 +108,15 @@ gray_slist_clear(gray_slist_t slist)
84 slist->free = slist->head; 108 slist->free = slist->head;
85 slist->head = slist->tail = NULL; 109 slist->head = slist->tail = NULL;
86 } 110 }
111 gray_slist_clerr(slist);
87 } 112 }
88 113
89 114
90void 115void
91gray_slist_free(gray_slist_t *slist) 116gray_slist_free(gray_slist_t *slist)
92{ 117{
93 struct gray_slist_bucket *p;
94 if (*slist) { 118 if (*slist) {
119 struct gray_slist_bucket *p;
95 gray_slist_clear(*slist); 120 gray_slist_clear(*slist);
96 for (p = (*slist)->free; p; ) { 121 for (p = (*slist)->free; p; ) {
97 struct gray_slist_bucket *next = p->next; 122 struct gray_slist_bucket *next = p->next;
@@ -103,21 +128,27 @@ gray_slist_free(gray_slist_t *slist)
103 *slist = NULL; 128 *slist = NULL;
104} 129}
105 130
106void 131ssize_t
107gray_slist_append(gray_slist_t slist, const char *str, size_t n) 132gray_slist_append(gray_slist_t slist, const char *str, size_t n)
108{ 133{
109 const char *ptr = str; 134 ssize_t total;
110 while (n) { 135
111 size_t s = copy_chars(slist, ptr, n); 136 if (slist->ec)
112 ptr += s; 137 return -1;
113 n -= s; 138 total = 0;
139 while (total < n) {
140 ssize_t s = copy_chars(slist, str + total, n - total);
141 if (s == -1)
142 return -1;
143 total += s;
114 } 144 }
145 return total;
115} 146}
116 147
117void 148ssize_t
118gray_slist_append_char(gray_slist_t slist, char c) 149gray_slist_append_char(gray_slist_t slist, char c)
119{ 150{
120 gray_slist_append(slist, &c, 1); 151 return gray_slist_append(slist, &c, 1);
121 } 152 }
122 153
123size_t 154size_t
@@ -130,17 +161,22 @@ gray_slist_size(gray_slist_t slist)
130 return size; 161 return size;
131} 162}
132 163
133size_t 164ssize_t
134gray_slist_coalesce(gray_slist_t slist) 165gray_slist_coalesce(gray_slist_t slist)
135{ 166{
136 size_t size; 167 size_t size;
137 168
138 if (slist->head && slist->head->next == NULL) 169 if (slist->ec)
170 return -1;
171 else if (slist->head && slist->head->next == NULL)
139 size = slist->head->level; 172 size = slist->head->level;
140 else { 173 else {
141 size = gray_slist_size(slist); 174 size = gray_slist_size(slist);
142 struct gray_slist_bucket *bucket = alloc_bucket(size); 175 struct gray_slist_bucket *bucket, *p;
143 struct gray_slist_bucket *p; 176
177 bucket = alloc_bucket(size);
178 if (!bucket)
179 return -1;
144 180
145 for (p = slist->head; p; ) { 181 for (p = slist->head; p; ) {
146 struct gray_slist_bucket *next = p->next; 182 struct gray_slist_bucket *next = p->next;
@@ -165,7 +201,10 @@ gray_slist_head(gray_slist_t slist, size_t *psize)
165void * 201void *
166gray_slist_finish(gray_slist_t slist) 202gray_slist_finish(gray_slist_t slist)
167{ 203{
168 gray_slist_coalesce(slist); 204 if (slist->ec)
205 return NULL;
206 if (gray_slist_coalesce(slist) == -1)
207 return NULL;
169 gray_slist_clear(slist); 208 gray_slist_clear(slist);
170 return slist->free->buf; 209 return slist->free->buf;
171} 210}
@@ -174,14 +213,16 @@ gray_slist_finish(gray_slist_t slist)
174#define to_num(c) \ 213#define to_num(c) \
175 (isdigit(c) ? c - '0' : (isxdigit(c) ? toupper(c) - 'A' + 10 : 255 )) 214 (isdigit(c) ? c - '0' : (isxdigit(c) ? toupper(c) - 'A' + 10 : 255 ))
176 215
177void 216int
178gray_slist_grow_backslash_num(gray_slist_t slist, char *text, char **pend, 217gray_slist_grow_backslash_num(gray_slist_t slist, char *text, char **pend,
179 int len, int base) 218 int len, int base)
180{ 219{
181 int i; 220 int i;
182 int val = 0; 221 int val = 0;
183 char *start = text; 222 char *start = text;
184 223
224 if (slist->ec)
225 return -1;
185 if (text[0] == '\\') { 226 if (text[0] == '\\') {
186 text++; 227 text++;
187 if (base == 16) 228 if (base == 16)
@@ -196,14 +237,17 @@ gray_slist_grow_backslash_num(gray_slist_t slist, char *text, char **pend,
196 } 237 }
197 238
198 if (i == 0) { 239 if (i == 0) {
199 gray_slist_append(slist, start, 1); 240 if (gray_slist_append(slist, start, 1) != 1)
241 return -1;
200 if (pend) 242 if (pend)
201 *pend = start + 1; 243 *pend = start + 1;
202 } else { 244 } else {
203 gray_slist_append_char(slist, val); 245 if (gray_slist_append_char(slist, val) != 1)
246 return -1;
204 if (pend) 247 if (pend)
205 *pend = text + i; 248 *pend = text + i;
206 } 249 }
250 return 0;
207} 251}
208 252
209int 253int
@@ -219,22 +263,27 @@ gray_decode_backslash(int c)
219 return c; 263 return c;
220} 264}
221 265
222void 266int
223gray_slist_grow_backslash(gray_slist_t slist, char *text, char **endp) 267gray_slist_grow_backslash(gray_slist_t slist, char *text, char **endp)
224{ 268{
225 if (text[1] == '\\' || (unsigned char)text[1] > 127) { 269 if (text[1] == '\\' || (unsigned char)text[1] > 127) {
226 gray_slist_append_char(slist, text[1]); 270 if (gray_slist_append_char(slist, text[1]) != 1)
271 return -1;
227 text += 2; 272 text += 2;
228 } else if (isdigit(text[1])) 273 } else if (isdigit(text[1])) {
229 gray_slist_grow_backslash_num(slist, text, &text, 3, 8); 274 if (gray_slist_grow_backslash_num(slist, text, &text, 3, 8))
230 else if (text[1] == 'x' || text[1] == 'X') 275 return -1;
231 gray_slist_grow_backslash_num(slist, text, &text, 2, 16); 276 } else if (text[1] == 'x' || text[1] == 'X') {
232 else { 277 if (gray_slist_grow_backslash_num(slist, text, &text, 2, 16))
278 return -1;
279 } else {
233 int c = gray_decode_backslash(text[1]); 280 int c = gray_decode_backslash(text[1]);
234 gray_slist_append_char(slist, c); 281 if (gray_slist_append_char(slist, c) != 1)
282 return -1;
235 text += 2; 283 text += 2;
236 } 284 }
237 285
238 *endp = text; 286 *endp = text;
287 return 0;
239} 288}
240 289

Return to:

Send suggestions and report system problems to the System administrator.