add a CVS snapshot, to thoroughly test on the Debian side
[alioth/jupp.git] / va.c
1 /* $MirOS: contrib/code/jupp/va.c,v 1.3 2012/06/08 16:55:29 tg Exp $ */
2 /*
3  *      Variable length array of strings
4  *      Copyright
5  *              (C) 1992 Joseph H. Allen
6  *
7  *      This file is part of JOE (Joe's Own Editor)
8  */
9 #include "config.h"
10
11 #ifdef HAVE_STDLIB_H
12 #include <stdlib.h>
13 #endif
14
15 #include "utils.h"
16 #include "va.h"
17
18 aELEMENT *vamk(int len)
19 {
20         int *new = (int *) joe_malloc((1 + len) * sizeof(aELEMENT) + 2 * sizeof(int));
21
22         new[0] = len;
23         new[1] = 0;
24         ((aELEMENT *)(new + 2))[0] = aterm;
25         return (aELEMENT *)(new + 2);
26 }
27
28 void varm(aELEMENT *vary)
29 {
30         if (vary) {
31                 vazap(vary, 0, aLen(vary));
32                 joe_free((int *) vary - 2);
33         }
34 }
35
36 int alen(aELEMENT *ary)
37 {
38         if (ary) {
39                 aELEMENT *beg = ary;
40                 while (acmp(*ary, aterm))
41                         ++ary;
42                 return ary - beg;
43         } else
44                 return 0;
45 }
46
47 aELEMENT *vaensure(aELEMENT *vary, int len)
48 {
49         if (!vary)
50                 vary = vamk(len);
51         else if (len > aSiz(vary)) {
52                 len += (len >> 2);
53                 vary = (aELEMENT *)(2 + (int *) joe_realloc((int *) vary - 2, (len + 1) * sizeof(aELEMENT) + 2 * sizeof(int)));
54
55                 aSiz(vary) = len;
56         }
57         return vary;
58 }
59
60 aELEMENT *vazap(aELEMENT *vary, int pos, int n)
61 {
62         if (vary) {
63                 int x;
64
65                 if (pos < aLen(vary)) {
66                         if (pos + n <= aLen(vary)) {
67                                 for (x = pos; x != pos + n; ++x)
68                                         adel(vary[x]);
69                         } else {
70                                 for (x = pos; x != aLen(vary); ++x)
71                                         adel(vary[x]);
72                         }
73                 }
74         }
75         return vary;
76 }
77
78 aELEMENT *vatrunc(aELEMENT *vary, int len)
79 {
80         if (!vary || len > aLEN(vary))
81                 vary = vaensure(vary, len);
82         if (len < aLen(vary)) {
83                 vary = vazap(vary, len, aLen(vary) - len);
84                 vary[len] = vary[aLen(vary)];
85                 aLen(vary) = len;
86         } else if (len > aLen(vary)) {
87                 vary = vafill(vary, aLen(vary), ablank, len - aLen(vary));
88         }
89         return vary;
90 }
91
92 aELEMENT *vafill(aELEMENT *vary, int pos, aELEMENT el, int len)
93 {
94         int olen = aLEN(vary), x;
95
96         if (!vary || pos + len > aSIZ(vary))
97                 vary = vaensure(vary, pos + len);
98         if (pos + len > olen) {
99                 vary[pos + len] = vary[olen];
100                 aLen(vary) = pos + len;
101         }
102         for (x = pos; x != pos + len; ++x)
103                 vary[x] = adup(el);
104         if (pos > olen)
105                 vary = vafill(vary, pos, ablank, pos - olen);
106         return vary;
107 }
108
109 aELEMENT *vandup(aELEMENT *vary, int pos, aELEMENT *array, int len)
110 {
111         int olen = aLEN(vary), x;
112
113         if (!vary || pos + len > aSIZ(vary))
114                 vary = vaensure(vary, pos + len);
115         if (pos + len > olen) {
116                 vary[pos + len] = vary[olen];
117                 aLen(vary) = pos + len;
118         }
119         if (pos > olen)
120                 vary = vafill(vary, olen, ablank, pos - olen);
121         for (x = 0; x != len; ++x)
122                 vary[x + pos] = adup(array[x]);
123         return vary;
124 }
125
126 aELEMENT *vadup(aELEMENT *vary)
127 {
128         return vandup(NULL, 0, vary, aLEN(vary));
129 }
130
131 aELEMENT *_vaset(aELEMENT *vary, int pos, aELEMENT el)
132 {
133         if (!vary || pos + 1 > aSIZ(vary))
134                 vary = vaensure(vary, pos + 1);
135         if (pos > aLen(vary)) {
136                 vary = vafill(vary, aLen(vary), ablank, pos - aLen(vary));
137                 vary[pos + 1] = vary[pos];
138                 vary[pos] = el;
139                 aLen(vary) = pos + 1;
140         } else if (pos == aLen(vary)) {
141                 vary[pos + 1] = vary[pos];
142                 vary[pos] = el;
143                 aLen(vary) = pos + 1;
144         } else {
145                 adel(vary[pos]);
146                 vary[pos] = el;
147         }
148         return vary;
149 }
150
151 static int _acmp(aELEMENT *a, aELEMENT *b)
152 {
153         return acmp(*a, *b);
154 }
155
156 aELEMENT *vasort(aELEMENT *ary, int len)
157 {
158         if (!ary || !len)
159                 return ary;
160         qsort(ary, len, sizeof(aELEMENT), (int (*)(const void *, const void *))_acmp);
161         return ary;
162 }
163
164 aELEMENT *vawords(aELEMENT *a, unsigned char *s, int len, unsigned char *sep, int seplen)
165 {
166         int x;
167
168         if (!a)
169                 a = vamk(10);
170         else
171                 a = vatrunc(a, 0);
172       loop:
173         x = vsspan(s, len, sep, seplen);
174         s += x;
175         len -= x;
176         if (len) {
177                 x = vsscan(s, len, sep, seplen);
178                 if (x != ~0) {
179                         a = vaadd(a, vsncpy(vsmk(x), 0, s, x));
180                         s += x;
181                         len -= x;
182                         if (len)
183                                 goto loop;
184                 } else
185                         a = vaadd(a, vsncpy(vsmk(len), 0, s, len));
186         }
187         return a;
188 }