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