another update from CVS HEAD, for QA
[alioth/jupp.git] / vs.c
1 /*
2  *      Variable length 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 #include "types.h"
10
11 __RCSID("$MirOS: contrib/code/jupp/vs.c,v 1.11 2017/12/08 02:00:43 tg Exp $");
12
13 #include <stdlib.h>
14
15 #include "blocks.h"
16 #include "utils.h"
17 #include "vs.h"
18
19 sELEMENT *vsmk(int len)
20 {
21         int *new = malloc((1 + len) * sizeof(sELEMENT) + 2 * sizeof(int));
22
23         new[0] = len;
24         new[1] = 0;
25         ((sELEMENT *)(new + 2))[0] = sdup(sterm);
26         return (sELEMENT *)(new + 2);
27 }
28
29 void vsrm(sELEMENT *vary)
30 {
31         if (vary)
32                 free((int *)vary - 2);
33 }
34
35 int slen(const sELEMENT *ary)
36 {
37         if (ary) {
38                 const sELEMENT *beg = ary;
39                 while (scmp(*ary, sterm))
40                         ++ary;
41                 return ary - beg;
42         } else
43                 return 0;
44 }
45
46 sELEMENT *vsensure(sELEMENT *vary, int len)
47 {
48         if (!vary)
49                 vary = vsmk(len);
50         else if (len > sSiz(vary)) {
51                 len += (len >> 2);
52                 vary = (sELEMENT *)(2 + (int *)realloc((int *)vary - 2, (len + 1) * sizeof(sELEMENT) + 2 * sizeof(int)));
53
54                 sSiz(vary) = len;
55         }
56         return vary;
57 }
58
59 sELEMENT *vstrunc(sELEMENT *vary, int len)
60 {
61         if (!vary || len > sLEN(vary))
62                 vary = vsensure(vary, len + 16);
63         if (len < sLen(vary)) {
64                 vary[len] = vary[sLen(vary)];
65                 sLen(vary) = len;
66         } else if (len > sLen(vary)) {
67                 vary = vsfill(vary, sLen(vary), sblank, len - sLen(vary));
68         }
69         return vary;
70 }
71
72 sELEMENT *vsfill(sELEMENT *vary, int pos, sELEMENT el, int len)
73 {
74         int olen = sLEN(vary), x;
75
76         if (!vary || pos + len > sSIZ(vary))
77                 vary = vsensure(vary, pos + len);
78         if (pos + len > olen) {
79                 vary[pos + len] = vary[olen];
80                 sLen(vary) = pos + len;
81         }
82         for (x = pos; x != pos + len; ++x)
83                 vary[x] = sdup(el);
84         if (pos > olen)
85                 vary = vsfill(vary, pos, sblank, pos - olen);
86         return vary;
87 }
88
89 sELEMENT *vsncpy(sELEMENT *vary, int pos, const sELEMENT *array, int len)
90 {
91         int olen = sLEN(vary);
92
93         if (!vary || pos + len > sSIZ(vary))
94                 vary = vsensure(vary, pos + len);
95         if (pos + len > olen) {
96                 vary[pos + len] = vary[olen];
97                 sLen(vary) = pos + len;
98         }
99         if (pos > olen)
100                 vary = vsfill(vary, olen, sblank, pos - olen);
101 #ifdef TEST
102         memmove(vary + pos, array, len * sizeof(sELEMENT));
103 #else
104         mmove(vary + pos, array, len * sizeof(sELEMENT));
105 #endif
106         return vary;
107 }
108
109 sELEMENT *vsndup(sELEMENT *vary, int pos, sELEMENT *array, int len)
110 {
111         int olen = sLEN(vary), x;
112
113         if (!vary || pos + len > sSIZ(vary))
114                 vary = vsensure(vary, pos + len);
115         if (pos + len > olen) {
116                 vary[pos + len] = vary[olen];
117                 sLen(vary) = pos + len;
118         }
119         if (pos > olen)
120                 vary = vsfill(vary, olen, sblank, pos - olen);
121         for (x = pos; x != len; ++x)
122                 vary[x] = sdup(array[x]);
123         return vary;
124 }
125
126 sELEMENT *vsdup(sELEMENT *vary)
127 {
128         return vsndup(NULL, 0, vary, sLEN(vary));
129 }
130
131 sELEMENT *_vsset(sELEMENT *vary, int pos, sELEMENT el)
132 {
133         if (!vary || pos + 1 > sSIZ(vary))
134                 vary = vsensure(vary, pos + 1);
135         if (pos > sLen(vary)) {
136                 vary = vsfill(vary, sLen(vary), sblank, pos - sLen(vary));
137                 vary[pos + 1] = vary[pos];
138                 vary[pos] = el;
139                 sLen(vary) = pos + 1;
140         } else if (pos == sLen(vary)) {
141                 vary[pos + 1] = vary[pos];
142                 vary[pos] = el;
143                 sLen(vary) = pos + 1;
144         } else {
145                 sdel(vary[pos]);
146                 vary[pos] = el;
147         }
148         return vary;
149 }
150
151 int vsbsearch(const sELEMENT *ary, int len, sELEMENT el)
152 {
153         int x, y, z;
154
155         if (!ary || !len)
156                 return 0;
157         y = len;
158         x = 0;
159         z = ~0;
160         while (z != (x + y) / 2) {
161                 z = (x + y) / 2;
162                 switch (scmp(el, ary[z])) {
163                 case 1:
164                         x = z;
165                         break;
166                 case -1:
167                         y = z;
168                         break;
169                 case 0:
170                         return z;
171                 }
172         }
173         return y;
174 }
175
176 int vscmpn(sELEMENT *a, int alen, sELEMENT *b, int blen)
177 {
178         int x, l;
179         int t;
180
181         if (!a && !b)
182                 return 0;
183         if (!a)
184                 return -1;
185         if (!b)
186                 return 1;
187         if (alen > blen)
188                 l = sLen(a);
189         else
190                 l = blen;
191         for (x = 0; x != l; ++x)
192                 if ((t = scmp(a[x], b[x])) != 0)
193                         return t;
194         if (alen > blen)
195                 return 1;
196         if (alen < blen)
197                 return -1;
198         return 0;
199 }
200
201 int vscmp(sELEMENT *a, sELEMENT *b)
202 {
203         return vscmpn(sv(a), sv(b));
204 }
205
206 int vsscan(const sELEMENT *a, int alen, const sELEMENT *b, int blen)
207 {
208         int x;
209
210         for (x = 0; x != alen; ++x) {
211                 int z = vsbsearch(b, blen, a[x]);
212
213                 if (z < blen && !scmp(b[z], a[x]))
214                         return x;
215         }
216         return ~0;
217 }
218
219 int vsspan(sELEMENT *a, int alen, sELEMENT *b, int blen)
220 {
221         int x;
222
223         /* should not happen */
224         if (!b)
225                 return (0);
226
227         for (x = 0; x != alen; ++x) {
228                 int z = vsbsearch(b, blen, a[x]);
229
230                 if (z == blen || scmp(b[z], a[x]))
231                         break;
232         }
233         return x;
234 }