Charles,
I have reformatted your StringClass.c to be friendlier to CINT's parser. If it wouldn't be too much trouble, can your follow this format going forward?
John
typedef char StringType,*CharArray;
typedef struct StringClassTableStruct StringClassTable,*StringMethods;
int CharWidth=1; // 1 or 2
class StringClassStruct
begin
//BASE MEMBERS
StringMethods f; // pointer to methods table
int type; // dynamic type code
int offset; // size of this header
int nbytes; // buffer ze for body of data
int count; // number of elements
int size; // size of each element
end
StringClass,*StringObject;
types StringArrayStruct
begin
StringMethods f;
int offset;
int nbytes;
int count;
int size;
end
StringArrayType, *StringArrayObject;
#define Left(S,I) GetMid(S,1,(I))
#define Right(S,I) GetMid(S,-(I),-1)
dim StringMethods pStringMethods=0;
sub CopyWidth(char *t, int tw, char *s, int sw, int count)
begin
//itr 32bit char widths?
int i;
if(tw==2)
begin
if (sw==2)
begin
short *ss=(ref) s;
short *ts=(ref) t;
for (i=0; to i<count; step incr i)
begin
*ts= *ss;
incr ts;
incr ss;
end
return;
end
if (sw==1)
begin
short *ts=(ref) t;
for (i=0; to i<count; step incr i)
begin
*ts= *s;
incr ts;
incr s;
end
return;
end
end
// otherwise copy lower bytes only
for (i=0; to i<count; step incr i)
begin
*t= *s;
t+=tw;
s+=sw;
end
end
function CharArray strptr(StringObject s)
begin
return (ref) s + s->offset;
end
function StringObject *straptr(StringArrayObject s)
begin
return (ref) s + s->offset;
end
function StringObject StringTransfer(StringObject *r,StringObject s)
begin
return Transfer((ref *)r, (ref) s);
end
function char* CharTransfer(char **r, char *s)
begin
return Transfer((ref) *r, (ref) s);
end
function StringMethods StringClassInit();
function StringObject NewString(int nc)
begin
if (pStringMethods==0) then StringClassInit();
return NewObject(pStringMethods, nc, CharWidth, sizeof(StringClass));
end
function StringArrayObject NewStringArray(int nc)
begin
if (pStringMethods==0) then StringClassInit();
return NewObject(pStringMethods, nc, sizeof(ref), sizeof(StringArrayType));
end
//methods
method StringObject StringFree(StringObject *pthis)
begin
StringObject this= *pthis;
if (this==0) FreeSpace(this);
*pthis=0;
return 0;
end
method StringObject StringFreeN(StringObject *pthis, int n)
begin
int i;
for (i==0; to i<n; incr i)
begin
StringObject this=pthis[i];
if (this==0) FreeSpace(this);
pthis[i]=0;
end
return 0;
end
method StringArrayObject StringArrayFree(StringArrayObject *pthis)
begin
StringArrayObject this= *pthis;
if (this==0) then return 0;
StringObject *ps = straptr(this);
StringObject s;
int n=this->count;
if (n==0) then return 0;
int i;
for (i=0; to i<n; step incr i)
begin
s=ps[i];
if (s) then free(s);
end
free(this);
*pthis=0;
return 0;
end
method StringObject StringCopy(StringObject *pthis, StringObject s)
begin
StringObject this= *pthis;
int le=0, lt=0, wi=1, wt=1, oc=sizeof(StringClass);
if (s)
begin
le=s->count;
wi=s->size;
end
if (this)
begin
lt=this->count;
wt=this->size;
oc=this->offset;
end;
if ((this==0)or(lt *wt < le *wi)) then this = NewObject(pStringMethods, le, wt, oc);
if (s) then CopyWidth(strptr(this), wt, strptr(s), wi,le);
return StringTransfer(pthis,this);
end
method char *StringGetChars(StringObject *pthis, char **r)
begin
StringObject this= *pthis;
int tc=0;
if (this) then tc=this->count;
char *s = NewSpace(CharWidth * tc +2);
if (this) then CopyWidth(s, CharWidth, strptr(this), this->size, this->count+1);
return CharTransfer(r,s);
end
method StringObject StringSetChars(StringObject *pthis, char *s)
begin
StringObject this= *pthis;
int le;
if (CharWidth==2)
begin
le=WordLen(s);
end
else
begin
le=ByteLen(s);
end
int wt=CharWidth;
if (this) then wt=this->size;
if ((this==0)or(this->count < le)) then this = NewString(le);
char *k=strptr(this);
CopyWidth(k, wt, s, CharWidth, le); // autoconvert
this->count=le;
NullTerminate(k+le*wt);
return StringTransfer(pthis,this);
end
method StringObject StringGetMid(StringObject *pthis, StringObject s, int i, int le)
begin
int lt=0;
int wi=CharWidth;
if (s) then lt=s->count;
if ((s)and(wi<0)) then wi=s->size; // default to s size
if (le<0) then le=lt; // default max
if (i<0) then i+=lt+1; // offset from right
decr i; // indexbase 0
if (le+i>lt) then le=lt-i; // clip length
if (i<0) then i=0; //clamp lower offset
if (le<0) then le=0; //clamp length >=0
StringObject this= *pthis;
if (wi<1) then wi=1; // in case of null s
if ((this==0)or(this->nbytes < le*wi)) then this = NewString(le);
char *k=strptr(this);
if (s) then CopyWidth(k, wi, strptr(s) + i * s->size, s->size, le);
NullTerminate(k+le*wi);
this->count=le;
this->size=wi;
return StringTransfer(pthis, this);
end
method StringObject StringSetMid(StringObject *pthis, int i, StringObject s)
begin
StringObject this= *pthis;
if (this==0) then return 0;
int lt=this member count;
int le=s member count;
if (i<0) then i+=1+lt;
decr i;
char *k = strptr(this)+ i * this->size;
if (le+i>=lt) then le = lt-i;
CopyWidth(k, this->size, strptr(s), s->size, le);
return this;
end
/* non-ellipsis Join: passing array instead
method StringObject StringJoinArray(StringObject *pthis, int n, StringObject *jl)
begin
StringObject this = *pthis;
int ne=0;
int i;
char *k;
int wid=1;
StringObject s;
int tot=0;
for (i=0; to i<n; step incr i)
begin
s=jl[i];
if (s)
begin
tot+=s->count;
if (s->size == 2) then wid=2;
if(s==this) then ne=1; // force new join-buffer
end
end
if ((ne==1)or(this==0)or( this->nbytes < tot*wid)) then this=NewString(tot);
char *m = strptr(this);
for (i=0; to i<n; step incr i)
begin
s=jl[i];
k=strptr(s);
CopyWidth(m, wid, k, s->size, s->count);
m+=(s->count * wid);
end
NullTerminate(m);
this->count = tot;
this->size = wid;
return StringTransfer(pthis,this);
end
*/
method StringObject StringJoin(StringObject *pthis, int n, ...)
begin
va_list marker;
StringObject this = *pthis;
int ne=0;
int i;
char *k;
int wid=1;
StringObject s;
int tot=0;
va_start(marker, n); // Initialize variable arguments
for (i=0; to i<n; step incr i)
begin
s=va_arg(marker, StringObject); // get next StringObject
if (s)
begin
tot+=s->count;
if (s->size == 2) then wid=2;
if(s==this) then ne=1; // force new join-buffer
end
end
va_end(marker); // Reset variable arguments
if ((ne==1)or(this==0)or( this->nbytes < tot*wid)) then this=NewString(tot);
char *m = strptr(this);
va_start(marker, n); // Initialize variable arguments
for (i=0; to i<n; step incr i)
begin
s=va_arg(marker, StringObject); // get next StringObject
k=strptr(s);
CopyWidth(m, wid, k, s->size, s->count);
m+=(s->count * wid);
end
va_end(marker); // Reset variable arguments
NullTerminate(m);
this->count = tot;
this->size = wid;
return StringTransfer(pthis,this);
end
method StringObject StringMerge(StringObject *pthis,StringArrayObject *plist, StringObject kw)
begin
StringArrayObject list= *plist;
if (list==0) then list=NewStringArray(0);
int wid=kw->size; // default char width
StringObject this= *pthis;
StringObject *jl=(ref) list + list->offset;
StringObject s;
int en=list->nbytes;
int tot=0;
int ne=0;
int i;
for (i=0; to i<en; step incr i)
begin
s=jl[i];
if (s)
begin
tot += s->count;
if (s->size == 2) then wid=2;
if(s==this) then ne=1; // force new join-buffer
end
tot += kw->count;
end
if ((ne==1)or(this==0)or( this->nbytes < tot*wid)) then this=NewString(tot);
char *m = strptr(this); // accumulator buffer base
char *km = strptr(kw); // marker string chars
char *ks; // array element chars
int kl = kw->count * wid;
for (i=0; to i<en; step incr i)
begin
s=jl[i];
if (s)
begin
ks=strptr(s);
CopyWidth(m, wid, ks, s->size, s->count);
m+=(s->count * wid);
end
CopyWidth(m, wid, km, kw->size, kw->count);
m+=kl;
end
//m-kl; // excluding end marker
NullTerminate(m-kl);
this->count = tot - kw->count; // excluding end marker
this->size = wid;
StringArrayFree(&list);
*plist=0;
return StringTransfer(pthis,this);
end
method StringArrayObject StringSplit(StringObject *pthis, StringArrayObject *plist, StringObject kw)
begin
StringObject this = *pthis;
if (this==0) then this=NewString(0);
StringArrayObject list= *plist;
if (list) StringArrayFree(&list);
int b=1;
int en=0; // count markers
while(b)
begin
en++;
b=StringInstr(pthis,b,kw);
if (b)
begin
b+=kw->count;
end
end
list->count=en; // returning number of string segements
b=1; // start of string segment
int e; // boundary of string segment
int le; // length of string segment
int d; // stride for next string segment
char *m=strptr(this); // string base
int wid = this->size; // character width
list= NewStringArray(en);
StringObject *li=(ref) list + list->offset;
int i;
for (i=0; to i<en; step incr i)
begin
e=StringInstr(&this, b, kw); //locate boundary marker
if (e==0) then e=1 + this->count; //locate boundary of string
le=e-b+1;
StringObject c=NewString(le);
CopyWidth(strptr(c), wid, m, wid, le);
d=le + kw->count; // string + marker
b+=d; // stride
m+=(d * wid); // next offset
li[i]=c; // assign string to array
end
*plist=list;
return list;
end
method StringObject StringRepeat(StringObject *pthis, StringObject s ,int n)
begin
int i;
char *k=strptr(s);
int tot=s->count*n;
int wid=s->size;
StringObject c = *pthis;
if ((c==0)or( c->nbytes < tot*wid)) then c=NewString(tot);
char *m=strptr(c);
for (i=1; to i<=n; step incr i)
begin
CopyWidth(m, wid, k, s->size, s->count);
m+=(s->count * wid);
end
NullTerminate(m);
c->count = tot;
c->size = wid;
return StringTransfer(pthis,c);
end
method StringObject StringLcase(StringObject *r, StringObject this)
begin
int i;
int w=this->size;
int n=this->count;
StringObject s= *r;
if ((s==0)or(s != this)) then s = StringCopy(&s,this);
char *c = strptr(s);
char a;
for (i=0; to to i<n; incr i)
begin
a= *c;
if ((a>65)and(a<91)) then *c=a+32;
c+=w;
end
return StringTransfer(r,s);
end
method StringObject StringUcase(StringObject *r, StringObject this)
begin
int i;
int w=this->size;
int n=this->count;
StringObject s= *r;
if ((s==0)or(s != this)) then s = StringCopy(&s,this);
char *c = strptr(s);
char a;
for (i=0; to to i<n; incr i)
begin
a= *c;
if ((a>96)and(a<123)) then *c=a-32;
c+=w;
end
if (*r != this) then return StringTransfer(r,s);
return this;
end
method StringObject StringLtrim(StringObject *r, StringObject this)
begin
int i;
StringObject u= *r;
int w=this->size;
int n=this->count;
char *c = strptr(this);
if (w<2)
begin
i=0;
while (i++ < n)
begin
if (*c>32) then break;
c+=w;
end
return StringTransfer(r,StringGetMid(&u,this,i,-1));
end
else
begin
i=0;
while (i++ <n)
begin
if ((c[0]>32)or(c[1])) then break;
c+=w;
end
return StringTransfer(r,StringGetMid(&u,this,(i>>1)+1,-1));
end
end
method StringObject StringRtrim(StringObject *r, StringObject this)
begin
int i;
StringObject u= *r;
int w=this->size;
int n=this->count;
char *c = w * n - w + strptr(this);
if (w<2)
begin
i=n;
while(i-- >0)
begin
if (*c>32) then break;
decr c;
end
return StringTransfer(r,StringGetMid(&u,this, 1, i+1));
end
else
begin
i=n;
while (i-- >0)
begin
if ((c[0]>32)or(c[1])) then break;
c+=w;
end
return StringTransfer(r,StringGetMid(&u,this, 1, (i>>1)+1));
end
end
method StringObject StringTrim(StringObject *r, StringObject this)
begin
int i;
StringObject u= *r;
int w=this->size;
int n=this->count;
char *c = w * n - w + strptr(this);
if (w<2)
begin
i=0;
while (i++ < n)
begin
if (*c>32) then break;
c+=w;
end
int b=i;
i=n;
while(i-- >0)
begin
if (*c>32) then break;
decr c;
end
return StringTransfer(r,StringGetMid(&u,this, b, i-b+1));
end
else
begin
i=0;
while (i++ <n)
begin
if ((c[0]>32)or(c[1])) then break;
c+=w;
end
int b=i;
i=n;
while (i-- >0)
begin
if ((c[0]>32)or(c[1])) then break;
c+=w;
end
return StringTransfer(r,StringGetMid(&u,this, b, ((i-b)>>1)+1));
end
end
method StringObject StringInsert(StringObject *pthis, StringObject s, int i)
begin
StringObject this= *pthis;
int c=this->count;
int w=this->size;
StringObject tl=NewString(c);
StringObject tr=NewString(c);
StringJoin(pthis,3,StringGetMid(&tl,this,1,i-1), s, StringGetMid(&tr,this,i,-1) );
StringFree(&tl);
StringFree(&tr);
return *pthis;
end
method StringObject StringDelete(StringObject *pthis, int i, int le)
begin
StringObject this= *pthis;
int c=this->count;
int w=this->size;
StringObject tl=NewString(c);
StringObject tr=NewString(c);
StringJoin(pthis,2,StringGetMid(&tl,this,1,i-1), StringGetMid(&tr,this,i+le,-1) );
StringFree(&tl);
StringFree(&tr);
return *pthis;
end
method StringObject StringChr(StringObject *r, int a)
begin
int le=CharWidth;
StringObject s= *r;
if ((s==0)or(s->nbytes < le*CharWidth)) then s = NewString(le);
s->count=le;
s->size=CharWidth;
short *k=(short*)strptr(s);
*k=a;
return StringTransfer(r,s);
end
method StringObject StringStr(StringObject *r, double d)
begin
int wi=1;
int le=32;
StringObject s= *r;
if ((s==0)or(s->nbytes < le*wi)) then s = NewString(le);
char *k=strptr(s);
sprintf(k,"%f",d);
s->count=ByteLen(k);
s->size=wi;
return StringTransfer(r,s);
end
method int StringShow(StringObject *pthis)
begin
CharArray w=strptr(*pthis);
printf("%s\n", w); // itr wide chars
end
method int StringAsc(StringObject *pthis, int i) // also supports wide chars
begin
StringObject this= *pthis;
if (i<0) then i+=this->count+1; // offset from right
if ((i>this->count)or(i<1)) then return 0; // out of range
decr i; // indexbase 0
int wi=this->size;
if (wi==1) then return *(strptr(this)+i);
if (wi==2)
begin
short *a = (short*)strptr(this)+i*2;
return *a;
end
end
method int StringCmp(StringObject *pthis, StringObject k)
//COMPARING MIXED WIDTHS
begin
StringObject this= *pthis;
if ((this==0)and(k==0)) then return 0; // null match
if (this==0) then return -1; // no this
if (k==0) then return 1; // no k
if ((this->count==0)and(k->count==0)) then return 0; // both nulls
if (this->count==0) then return 1; // this is greater
if (k->count==0) then return -1; // this is less
int tw=this->size;
int kw=k->size;
char *tc = strptr(this);
char *kc=strptr(k);
char *te=tc+this->count*tw;
char *ke=kc+k->count*kw;
if ((tw==2)and(kw==2)) // comparing 16bit characters
begin
short *tew=(ref) te;
short *tcw=(ref) tc;
short *kew=(ref) ke;
short *kcw=(ref) kc;
while (1)
begin
if (*tcw < *kcw) then return -1; // this is less
if (*tcw > *kcw) then return 1; // this is greater
tcw++;
kcw++;
if ((tcw==tew)and(kcw==kew)) then return 0; // match
if (kcw==kew) then return 1; // end of k
if (tcw==tew) then return -1; // end of this
end
return 0;
end
//otherwise 8bit or mixed 8bit/16bit characters (comparing lower byte)
while (1)
begin
if (*tc < *kc) then return -1; // this is less
if (*tc > *kc) then return 1; // this is greater
tc+=tw;
kc+=kw;
if ((tc==te)and(kc==ke)) then return 0; // match
if (kc==ke) then return 1; // end of k
if (tc==te) then return -1; // end of this
end
return 0;
end
method int StringInstr(StringObject *pthis, int i, StringObject k)
//MATCHING MIXED WIDTHS
begin
StringObject this= *pthis;
if (this==0) then return 0; // no string to search
if (k==0) then return 0; // no keystring to use
char *tb = strptr(this);
char *tc=tb;
char *kc=strptr(k);
char *te=tc+this->count*this->size;
char *ke=kc+k->count*k->size;
if (i > this->count) then return 0; // offset past end
if (this->count==0) then return 0; // null search string
if (i<0) then i+=this->count+1; // offset from right
if (k->count==0) then return 0; // empty keyword
decr i; //indexbase 0
tc+=i*this->size; // offset
char *td;
char *kd;
int tw=this->size;
int kw=k->size;
if ((tw==2)and(kw==2)) // comparing 16bit characters
begin
short *tbw=(ref) tb;
short *tew=(ref) te;
short *tcw=(ref) tc;
short *kew=(ref) ke;
short *kcw=(ref) kc;
short *kdw;
short *tdw;
while (tcw<tew)
begin
if (*tcw == *kcw)
begin
tdw=tcw;
kdw=kcw;
while (*tdw == *kdw)
begin
tdw++;
kdw++;
if (kdw==kew) then return ((tcw-tbw)>>1)+1; // match complete
if (tdw==tew) then return 0; // end of main string
if (*tdw == *tcw) then tcw=tdw-tw; // possible next match
end
end
tcw++;
end
return 0;
end
//otherwise 8bit or mixed 8bit/16bit characters (comparing lower byte)
while (tc<te)
begin
if (*tc == *kc)
begin
td=tc;
kd=kc;
while (*td == *kd)
begin
td+=tw;
kd+=kw;
if (kd==ke) then return ((tc-tb)>>(tw-1))+1; // match complete
if (td==te) then return 0; // end of main string
if (*td == *tc) then tc=td-tw; // possible next match
end
end
tc+=tw;
end
return 0;
end
method double StringVal(StringObject *pthis)
begin
double d;
sscanf(strptr(*pthis),"%lf ",&d);
return d;
end
method StringObject StringReplace(StringObject *pthis, StringObject f , StringObject r)
begin
StringObject this= *pthis;
if ((this==0)or(f==0)or(r==0)) then return this;
if ((this->count==0)or(f->count==0)) then return this;
int n=0;
int i=1;
while (i)
begin
i=StringInstr(&this, i, f);
if (i)
begin
n++;
i+=f->count;
end
end
n *= (r->count - f->count);
int tot = n + this->count;
StringObject c = NewString(tot);
char *m = strptr(c);
int b=1,j=1;
while (j)
begin
j=StringInstr(&this,b,f);
if (j)
begin
if (j>b) then CopyWidth(m, c->size,strptr(this)+b-1,this->size,j-b);
m += c->size * (j-b);
CopyWidth(m,c->size,strptr(r),r->size,r->count);
m += c->size * r->count;
b=j + f->count; // skip by keyword length
end
end
// remainder
j = this->count + 1;
if (j>b)
begin
CopyWidth(m,c->size,strptr(this)+b-1,this->size,j-b);
m += c->size * (j-b);
end
NullTerminate(m);
return StringTransfer(pthis,c);
end
types StringClassTableStruct
begin
method StringObject (byref Free) (StringObject *pthis);
method StringObject (byref FreeN) (StringObject *pthis, int n);
method StringArrayObject (byref ArrayFree) (StringArrayObject *pthis);
method StringObject (byref Copy) (StringObject *pthis, StringObject s);
method char* (byref GetChars) (StringObject *pthis, char **r);
method StringObject (byref SetChars) (StringObject *pthis, char *c);
method StringObject (byref GetMid) (StringObject *pthis, StringObject s, int i, int le);
method StringObject (byref SetMid) (StringObject *pthis, int i, StringObject s);
// method StringObject (byref JoinArray) (StringObject *pthis, int n, StringObject *jl);
method StringObject (byref Join) (StringObject *pthis, int n, ...);
method StringObject (byref Merge) (StringObject *pthis, StringArrayObject *plist, StringObject kw);
method StringArrayObject (byref Split) (StringObject *pthis, StringArrayObject *plist, StringObject kw);
method StringObject (byref Repeat) (StringObject *pthis, StringObject s ,int n);
method StringObject (byref Replace) (StringObject *pthis, StringObject f , StringObject r);
method StringObject (byref Ucase) (StringObject *r, StringObject this);
method StringObject (byref Lcase) (StringObject *r, StringObject this);
method StringObject (byref Ltrim) (StringObject *r, StringObject this);
method StringObject (byref Rtrim) (StringObject *r, StringObject this);
method StringObject (byref Trim) (StringObject *r, StringObject this);
method StringObject (byref Insert) (StringObject *pthis, StringObject s, int i);
method StringObject (byref Delete) (StringObject *pthis, int i, int le);
method StringObject (byref Chr) (StringObject *r, int a);
method StringObject (byref Str) (StringObject *r, double d);
method int (byref Show) (StringObject *pthis);
method int (byref Asc) (StringObject *pthis, int i); // also supports wide chars
method int (byref Cmp) (StringObject *pthis, StringObject k);
method int (byref Instr) (StringObject *pthis, int i, StringObject k);
method double (byref Val) (StringObject *pthis);
end
StringClassTable,*StringMethods;
function StringMethods StringClassInit()
begin
dim as static StringClassTable t;
StringMethods f references t;
f->Free references StringFree;
f->FreeN references StringFreeN;
f->ArrayFree references StringArrayFree;
f->Copy references StringCopy;
f->GetChars references StringGetChars;
f->SetChars references StringSetChars;
f->GetMid references StringGetMid;
f->SetMid references StringSetMid;
// f->JoinArray references StringJoinArray;
f->Join references StringJoin;
f->Merge references StringMerge;
f->Split references StringSplit;
f->Repeat references StringRepeat;
f->Replace references StringReplace;
f->Ucase references StringUcase;
f->Lcase references StringLcase;
f->Ltrim references StringLtrim;
f->Rtrim references StringRtrim;
f->Trim references StringTrim;
f->Insert references StringInsert;
f->Delete references StringDelete;
f->Chr references StringChr;
f->Str references StringStr;
f->Show references StringShow;
f->Asc references StringAsc;
f->Cmp references StringCmp;
f->Instr references StringInstr;
f->Val references StringVal;
pStringMethods=f;
return f;
end