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