/MirOS/dist/jupp/joe-3.1jupp30.tgz
[alioth/jupp.git] / vs.c
1 /* $MirOS: contrib/code/jupp/vs.c,v 1.9 2017/01/10 19:16:28 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 <stdlib.h>
13
14 #include "blocks.h"
15 #include "utils.h"
16 #include "vs.h"
17
18 sELEMENT *vsmk(int len)
19 {
20         int *new = (int *) joe_malloc((1 + len) * sizeof(sELEMENT) + 2 * sizeof(int));
21
22         new[0] = len;
23         new[1] = 0;
24         ((sELEMENT *)(new + 2))[0] = sdup(sterm);
25         return (sELEMENT *)(new + 2);
26 }
27
28 void vsrm(sELEMENT *vary)
29 {
30         if (vary)
31                 joe_free((int *) vary - 2);
32 }
33
34 int slen(const sELEMENT *ary)
35 {
36         if (ary) {
37                 const sELEMENT *beg = ary;
38                 while (scmp(*ary, sterm))
39                         ++ary;
40                 return ary - beg;
41         } else
42                 return 0;
43 }
44
45 sELEMENT *vsensure(sELEMENT *vary, int len)
46 {
47         if (!vary)
48                 vary = vsmk(len);
49         else if (len > sSiz(vary)) {
50                 len += (len >> 2);
51                 vary = (sELEMENT *)(2 + (int *) joe_realloc((int *) vary - 2, (len + 1) * sizeof(sELEMENT) + 2 * sizeof(int)));
52
53                 sSiz(vary) = len;
54         }
55         return vary;
56 }
57
58 sELEMENT *vstrunc(sELEMENT *vary, int len)
59 {
60         if (!vary || len > sLEN(vary))
61                 vary = vsensure(vary, len + 16);
62         if (len < sLen(vary)) {
63                 vary[len] = vary[sLen(vary)];
64                 sLen(vary) = len;
65         } else if (len > sLen(vary)) {
66                 vary = vsfill(vary, sLen(vary), sblank, len - sLen(vary));
67         }
68         return vary;
69 }
70
71 sELEMENT *vsfill(sELEMENT *vary, int pos, sELEMENT el, int len)
72 {
73         int olen = sLEN(vary), x;
74
75         if (!vary || pos + len > sSIZ(vary))
76                 vary = vsensure(vary, pos + len);
77         if (pos + len > olen) {
78                 vary[pos + len] = vary[olen];
79                 sLen(vary) = pos + len;
80         }
81         for (x = pos; x != pos + len; ++x)
82                 vary[x] = sdup(el);
83         if (pos > olen)
84                 vary = vsfill(vary, pos, sblank, pos - olen);
85         return vary;
86 }
87
88 sELEMENT *vsncpy(sELEMENT *vary, int pos, const sELEMENT *array, int len)
89 {
90         int olen = sLEN(vary);
91
92         if (!vary || pos + len > sSIZ(vary))
93                 vary = vsensure(vary, pos + len);
94         mkssert(vary != NULL);
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 }