/*
* Variable length strings
* Copyright
* (C) 1992 Joseph H. Allen
*
* This file is part of JOE (Joe's Own Editor)
*/
#include "types.h"
int sicmp(char a, char b)
{
if (a >= 'A' && a <= 'Z')
a = (char)(a + 'a' - 'A');
if (b >= 'A' && b <= 'Z')
b = (char)(b + 'a' - 'A');
return scmp(a, b);
}
sELEMENT *vsmk(ptrdiff_t len)
{
ptrdiff_t *news = (ptrdiff_t *)joe_malloc((1 + len) * SIZEOF(sELEMENT) + 2 * SIZEOF(ptrdiff_t));
news[0] = len;
news[1] = 0;
((sELEMENT *)(news + 2))[0] = sdup(sterm);
return (sELEMENT *)(news + 2);
}
void vsrm(sELEMENT *vary)
{
if (vary)
joe_free((ptrdiff_t *) vary - 2);
}
ptrdiff_t slen(const sELEMENT *ary)
{
if (ary) {
const sELEMENT *beg = ary;
while (scmp(*ary, sterm))
++ary;
return ary - beg;
} else
return 0;
}
sELEMENT *vsensure(sELEMENT *vary, ptrdiff_t len)
{
if (!vary)
vary = vsmk(len);
else if (len > sSiz(vary)) {
len += (len >> 2);
vary = (sELEMENT *)(2 + (ptrdiff_t *) joe_realloc((ptrdiff_t *) vary - 2, (len + 1) * SIZEOF(sELEMENT) + 2 * SIZEOF(ptrdiff_t)));
sSiz(vary) = len;
}
return vary;
}
sELEMENT *vstrunc(sELEMENT *vary, ptrdiff_t len)
{
if (!vary || len > sLEN(vary))
vary = vsensure(vary, len + 16);
if (len < sLen(vary)) {
vary[len] = vary[sLen(vary)];
sLen(vary) = len;
} else if (len > sLen(vary)) {
vary = vsfill(vary, sLen(vary), sblank, len - sLen(vary));
}
return vary;
}
sELEMENT *vsfill(sELEMENT *vary, ptrdiff_t pos, sELEMENT el, ptrdiff_t len)
{
ptrdiff_t olen = sLEN(vary), x;
if (!vary || pos + len > sSIZ(vary))
vary = vsensure(vary, pos + len);
if (pos + len > olen) {
vary[pos + len] = vary[olen];
sLen(vary) = pos + len;
}
for (x = pos; x != pos + len; ++x)
vary[x] = sdup(el);
if (pos > olen)
vary = vsfill(vary, pos, sblank, pos - olen);
return vary;
}
sELEMENT *vsncpy(sELEMENT *vary, ptrdiff_t pos, const sELEMENT *array, ptrdiff_t len)
{
ptrdiff_t olen = sLEN(vary);
if (!vary || pos + len > sSIZ(vary))
vary = vsensure(vary, pos + len);
if (pos + len > olen) {
vary[pos + len] = vary[olen];
sLen(vary) = pos + len;
}
if (pos > olen)
vary = vsfill(vary, olen, sblank, pos - olen);
mmove(vary + pos, array, len * SIZEOF(sELEMENT));
return vary;
}
sELEMENT *vsndup(sELEMENT *vary, ptrdiff_t pos, sELEMENT *array, ptrdiff_t len)
{
ptrdiff_t olen = sLEN(vary), x;
if (!vary || pos + len > sSIZ(vary))
vary = vsensure(vary, pos + len);
if (pos + len > olen) {
vary[pos + len] = vary[olen];
sLen(vary) = pos + len;
}
if (pos > olen)
vary = vsfill(vary, olen, sblank, pos - olen);
for (x = pos; x != len; ++x)
vary[x] = sdup(array[x]);
return vary;
}
sELEMENT *vsdup(sELEMENT *vary)
{
return vsndup(NULL, 0, vary, sLEN(vary));
}
sELEMENT *_vsset(sELEMENT *vary, ptrdiff_t pos, sELEMENT el)
{
if (!vary || pos + 1 > sSIZ(vary))
vary = vsensure(vary, pos + 1);
if (pos > sLen(vary)) {
vary = vsfill(vary, sLen(vary), sblank, pos - sLen(vary));
vary[pos + 1] = vary[pos];
vary[pos] = el;
sLen(vary) = pos + 1;
} else if (pos == sLen(vary)) {
vary[pos + 1] = vary[pos];
vary[pos] = el;
sLen(vary) = pos + 1;
} else {
sdel(vary[pos]);
vary[pos] = el;
}
return vary;
}
#ifdef junk
sELEMENT *vsins(sELEMENT *vary, ptrdiff_t pos, ptrdiff_t n)
{
if (!vary || sLEN(vary) + n > sSIZ(vary))
vary = vsensure(vary, sLEN(vary) + n);
if (pos >= sLen(vary))
vary = vstrunc(vary, pos + n);
else {
mmove(vary + pos + n, vary + pos, sLen(vary) - (pos + n) + 1);
sLen(vary) += n;
}
return vary;
}
sELEMENT *vsdel(sELEMENT *vary, ptrdiff_t pos, ptrdiff_t n)
{
if (pos >= sLEN(vary))
return vary;
if (pos + n >= sLen(vary))
return vstrunc(vary, pos);
mmove(vary + pos, vary + pos + n, sLen(vary) - (pos + n) + 1);
sLen(vary) -= n;
return vary;
}
int _scmp(sELEMENT a, sELEMENT b)
{
return scmp(a, b);
}
sELEMENT *vssort(sELEMENT *ary, ptrdiff_t len)
{
if (!ary || !len)
return ary;
qsort(ary, len, SIZEOF(sELEMENT), _scmp);
return ary;
}
#endif
ptrdiff_t vsbsearch(const sELEMENT *ary, ptrdiff_t len, sELEMENT el)
{
ptrdiff_t x, y, z;
if (!ary || !len)
return 0;
y = len;
x = 0;
z = ~0;
while (z != (x + y) / 2) {
z = (x + y) / 2;
switch (scmp(el, ary[z])) {
case 1:
x = z;
break;
case -1:
y = z;
break;
case 0:
return z;
}
}
return y;
}
#ifdef junk
ptrdiff_t vsfirst(sELEMENT *ary, ptrdiff_t len, sELEMENT el)
{
ptrdiff_t x;
if (!ary || !len)
return ~0;
for (x = 0; x != len; ++x)
if (!scmp(ary[x], el))
return x;
return ~0;
}
ptrdiff_t vslast(sELEMENT *ary, ptrdiff_t len, sELEMENT el)
{
ptrdiff_t x = len;
if (!ary || !len)
return ~0;
do {
--x;
if (!scmp(ary[x], el))
return x;
} while (x);
return ~0;
}
#endif
int vscmpn(sELEMENT *a, ptrdiff_t myalen, sELEMENT *b, ptrdiff_t blen)
{
ptrdiff_t x, l;
int t;
if (!a && !b)
return 0;
if (!a)
return -1;
if (!b)
return 1;
if (myalen > blen)
l = sLen(a);
else
l = blen;
for (x = 0; x != l; ++x)
if ((t = scmp(a[x], b[x])) != 0)
return t;
if (myalen > blen)
return 1;
if (myalen < blen)
return -1;
return 0;
}
int vscmp(sELEMENT *a, sELEMENT *b)
{
return vscmpn(sv(a), sv(b));
}
#ifdef junk
int vsicmpn(sELEMENT *a, ptrdiff_t myalen, sELEMENT *b, ptrdiff_t blen)
{
ptrdiff_t x, l;
int t;
if (!a && !b)
return 0;
if (!a)
return -1;
if (!b)
return 1;
if (myalen > blen)
l = sLen(a);
else
l = blen;
for (x = 0; x != l; ++x)
if (t = sicmp(a[x], b[x]))
return t;
if (myalen > blen)
return 1;
if (myalen < blen)
return -1;
return 0;
}
ptrdiff_t vss(sELEMENT *a, ptrdiff_t myalen, sELEMENT *b, ptrdiff_t blen)
{
ptrdiff_t x;
if (!a && !b)
return 0;
if (!a || !b)
return ~0;
if (myalen < blen)
return ~0;
if (!blen)
return 0;
for (x = 0; x != myalen - blen; ++x)
if (!vscmpn(a, blen, b, blen))
return x;
return ~0;
}
#endif
ptrdiff_t vsscan(const sELEMENT *a, ptrdiff_t myalen, const sELEMENT *b, ptrdiff_t blen)
{
ptrdiff_t x;
for (x = 0; x != myalen; ++x) {
ptrdiff_t z = vsbsearch(b, blen, a[x]);
if (z < blen && !scmp(b[z], a[x]))
return x;
}
return ~0;
}
ptrdiff_t vsspan(const sELEMENT *a, ptrdiff_t myalen, const sELEMENT *b, ptrdiff_t blen)
{
ptrdiff_t x;
for (x = 0; x != myalen; ++x) {
ptrdiff_t z = vsbsearch(b, blen, a[x]);
if (z == blen || scmp(b[z], a[x]))
break;
}
return x;
}
#ifdef junk
sELEMENT *vsread(sELEMENT d, ptrdiff_t p, int (*getC)(), void *ptr)
{
int c;
if (!d)
d = vsmk(10);
c = getC(ptr);
if (c == NO_MORE_DATA) {
vsrm(d);
return NULL;
} else if (c == '\n')
return d;
else {
d = vsset(d, p, c);
p++;
}
while (c = getC(ptr), c != NO_MORE_DATA && c != '\n') {
d = vsset(d, p, c);
p++;
}
return d;
}
sELEMENT *vwords(sELEMENT *s, sELEMENT **a, ptrdiff_t len, sELEMENT t)
{
ptrdiff_t x;
if (!s)
s = vsmk(32);
else
s = vstrunc(s, 0);
for (x = 0; x != len; ++x) {
s = vsncpy(s, sLEN(s), sz(a[x]));
if (a[1])
s = vsadd(s, t);
}
return s;
}
#endif