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