new jupp, again fixes
[alioth/jupp.git] / vs.c
1 /* $MirOS: contrib/code/jupp/vs.c,v 1.4 2012/06/08 16:55:29 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         if (pos + len > olen) {
102                 vary[pos + len] = vary[olen];
103                 sLen(vary) = pos + len;
104         }
105         if (pos > olen)
106                 vary = vsfill(vary, olen, sblank, pos - olen);
107         mmove(vary + pos, array, len * sizeof(sELEMENT));
108         return vary;
109 }
110
111 sELEMENT *vsndup(sELEMENT *vary, int pos, sELEMENT *array, int len)
112 {
113         int olen = sLEN(vary), x;
114
115         if (!vary || pos + len > sSIZ(vary))
116                 vary = vsensure(vary, pos + len);
117         if (pos + len > olen) {
118                 vary[pos + len] = vary[olen];
119                 sLen(vary) = pos + len;
120         }
121         if (pos > olen)
122                 vary = vsfill(vary, olen, sblank, pos - olen);
123         for (x = pos; x != len; ++x)
124                 vary[x] = sdup(array[x]);
125         return vary;
126 }
127
128 sELEMENT *vsdup(sELEMENT *vary)
129 {
130         return vsndup(NULL, 0, vary, sLEN(vary));
131 }
132
133 sELEMENT *_vsset(sELEMENT *vary, int pos, sELEMENT el)
134 {
135         if (!vary || pos + 1 > sSIZ(vary))
136                 vary = vsensure(vary, pos + 1);
137         if (pos > sLen(vary)) {
138                 vary = vsfill(vary, sLen(vary), sblank, pos - sLen(vary));
139                 vary[pos + 1] = vary[pos];
140                 vary[pos] = el;
141                 sLen(vary) = pos + 1;
142         } else if (pos == sLen(vary)) {
143                 vary[pos + 1] = vary[pos];
144                 vary[pos] = el;
145                 sLen(vary) = pos + 1;
146         } else {
147                 sdel(vary[pos]);
148                 vary[pos] = el;
149         }
150         return vary;
151 }
152
153 int vsbsearch(sELEMENT *ary, int len, sELEMENT el)
154 {
155         int x, y, z;
156
157         if (!ary || !len)
158                 return 0;
159         y = len;
160         x = 0;
161         z = ~0;
162         while (z != (x + y) / 2) {
163                 z = (x + y) / 2;
164                 switch (scmp(el, ary[z])) {
165                 case 1:
166                         x = z;
167                         break;
168                 case -1:
169                         y = z;
170                         break;
171                 case 0:
172                         return z;
173                 }
174         }
175         return y;
176 }
177
178 int vscmpn(sELEMENT *a, int alen, sELEMENT *b, int blen)
179 {
180         int x, l;
181         int t;
182
183         if (!a && !b)
184                 return 0;
185         if (!a)
186                 return -1;
187         if (!b)
188                 return 1;
189         if (alen > blen)
190                 l = sLen(a);
191         else
192                 l = blen;
193         for (x = 0; x != l; ++x)
194                 if ((t = scmp(a[x], b[x])) != 0)
195                         return t;
196         if (alen > blen)
197                 return 1;
198         if (alen < blen)
199                 return -1;
200         return 0;
201 }
202
203 int vscmp(sELEMENT *a, sELEMENT *b)
204 {
205         return vscmpn(sv(a), sv(b));
206 }
207
208 int vsscan(sELEMENT *a, int alen, sELEMENT *b, int blen)
209 {
210         int x;
211
212         for (x = 0; x != alen; ++x) {
213                 int z = vsbsearch(b, blen, a[x]);
214
215                 if (z < blen && !scmp(b[z], a[x]))
216                         return x;
217         }
218         return ~0;
219 }
220
221 int vsspan(sELEMENT *a, int alen, sELEMENT *b, int blen)
222 {
223         int x;
224
225         for (x = 0; x != alen; ++x) {
226                 int z = vsbsearch(b, blen, a[x]);
227
228                 if (z == blen || scmp(b[z], a[x]))
229                         break;
230         }
231         return x;
232 }