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