home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Supreme Volume 6 #1
/
swsii.zip
/
swsii
/
099
/
CL181.ZIP
/
CL.CPP
next >
Wrap
C/C++ Source or Header
|
1993-04-26
|
20KB
|
1,069 lines
/*
cl.cpp -- Container Lite v 1.81
(C) Copyright 1993 John Webster Small
All rights reserved
*/
#include <string.h>
#include <fstream.h>
#include "cl.hpp"
char memberStreamDelimiter = '\n';
void cl::init(unsigned flags, unsigned maxNodes,
unsigned limit, unsigned delta)
{
curNode = first = nodes = 0U;
cmP = voidCmP0;
/*
The following relationships are maintained
during operation of a cl:
1 <= delta <= lowLimit <= limit <= maxNodes
<= CL_MAXNODES
lowThreshold = lowLimit - delta;
*/
if (maxNodes > CL_MAXNODES)
maxNodes = CL_MAXNODES;
if (limit > maxNodes)
limit = maxNodes;
if (delta > limit)
delta = limit;
if (!delta) {
delta = 1;
if (limit < delta)
limit = delta;
if (maxNodes < limit)
maxNodes = limit;
}
if ((linkS = new void *[limit]) == (void **)0)
{
this->limit = lowLimit = lowThreshold
= this->delta = this->maxNodes
= this->flags = 0U;
}
else {
this->limit = limit;
this->delta = delta;
this->maxNodes = maxNodes;
lowLimit = limit;
lowThreshold = lowLimit - delta;
this->flags = (flags | CL_SORTED);
}
}
void cl::assign(cl& b)
{
if (flags & CL_DDELETE)
allDel();
else
allRmv();
setDelta(1); setLimit(1); setMaxNodes(1);
setMaxNodes(b.MaxNodes());
setLimit(b.Limit());
setDelta(b.Delta());
resetFlags(CL_ALL_FLAGS);
setFlags(b.Flags());
setFlags(CL_DNEW | CL_DDELETE);
setCmP(b.CmP());
for (unsigned i = 0U; i < b.Nodes(); i++)
insQNew(b.atGet(i));
setCurNode(b.CurNode());
}
void cl::destruct()
{
if (flags & CL_DDELETE)
allDel();
else
allRmv();
if (linkS) {
delete linkS;
linkS = (void **)0;
}
}
int cl::put(ostream& os)
{
if (!(os << maxNodes << endm << limit << endm
<< delta << endm << nodes << endm
<< curNode << endm << flags << endm
<< cmP2ID(cmP) << endm))
return 0;
for (unsigned i = 0U; i < nodes; i++)
if (!Dput(os,atGet(i)))
return 0;
return 1;
}
int cl::get(istream& is)
{
unsigned maxNodes, limit, delta, nodes;
unsigned curNode, flags, cmPid;
if (!(is >> maxNodes >> nextm >> limit >> nextm
>> delta >> nextm >> nodes >> nextm
>> curNode >> nextm >> flags >> nextm
>> cmPid >> nextm))
return 0;
flags |= CL_DDELETE;
//reloaded nodes are dynamic!
setMaxNodes(maxNodes);
setLimit(limit);
setDelta(delta);
setFlags(flags);
setCmP(ID2cmP(cmPid));
void * D;
for (unsigned i = 0U; i < nodes; i++)
if (!insQ(D=Dget(is)))
if (D) {
Ddelete(D);
return 0;
}
setCurNode(curNode);
return 1;
}
int cl::load(const char * filename)
{
int ok = 0;
allClr();
if (filename) {
ifstream is(filename);
if (is) {
ok = get(is);
is.close();
}
}
return ok;
}
int cl::save(const char * filename)
{
int ok = 0;
if (Flags(CL_DSTORE)) {
ofstream os(filename);
if (os) {
ok = put(os);
os.close();
}
}
return ok;
}
void cl::vforEach(voidApplY B, va_list args)
{
if (!linkS || !B || !nodes)
return;
for (unsigned i = 0U; i < nodes; i++)
(*B)(linkS[(first+i)%limit],args);
}
cl::cl(void ** argv, unsigned argc,
unsigned flags)
{
init(flags,CL_MAXNODES,argc,CL_DELTA);
if (maxNodes)
if (argv)
if (argc > 0U)
while (argc--)
(void) push(argv[argc]);
else
for (argc = 0U;
insQ(argv[argc]);
argc++)
/* null stmt */;
}
void ** cl::vector(void ** argv, unsigned argc)
{
void ** V;
if ((V = argv) == (void **)0) {
if (!nodes)
return (void **)0;
if ((V = new void *[argc=nodes+1])
== (void **)0)
return (void **)0;
}
else if (argc) if (nodes > argc)
return (void **)0;
for (unsigned i = 0U; i < nodes; i++)
V[i] = atGet(i);
while (i < argc)
V[i++] = (void *)0;
return V;
}
unsigned cl::setLimit(unsigned newLimit)
{
void ** newLinkS;
unsigned i;
if (newLimit < nodes)
newLimit = nodes;
else if (newLimit > maxNodes)
newLimit = maxNodes;
if (newLimit < delta)
newLimit = delta;
if (!linkS || !newLimit || newLimit == limit)
return 0U;
if ((newLinkS = new void *[newLimit])
== (void **)0)
return 0U;
if ((i = limit - first) > nodes)
i = nodes;
if (i)
memcpy(newLinkS,&linkS[first],
sizeof(linkS[0U])*i);
/* copy wrap around */
if (i < nodes)
memcpy(&newLinkS[i],linkS,
sizeof(linkS[0U])*(nodes-i));
if (newLimit > limit)
if (newLimit - delta > limit)
lowLimit = newLimit - delta;
else
lowLimit = limit;
else
if (newLimit - delta > delta)
lowLimit = newLimit - delta;
else
lowLimit = delta;
lowThreshold = lowLimit - delta;
delete linkS;
linkS = newLinkS;
limit = newLimit;
first = 0U;
return limit;
}
unsigned cl::setDelta(unsigned newDelta)
{
return ((newDelta && newDelta <= lowLimit)?
delta = newDelta : 0U);
}
unsigned cl::setMaxNodes(unsigned newMaxNodes)
{
return ((newMaxNodes >= limit)?
(maxNodes = (newMaxNodes
> CL_MAXNODES)? CL_MAXNODES
: newMaxNodes) : 0U);
}
void * cl::atIns(unsigned n, void * D)
{
void ** newLinkS;
unsigned newLimit, i;
if (!linkS || !D)
return (void *)0;
if (nodes == limit) {
if (limit == maxNodes)
return (void *)0;
newLimit = (maxNodes - delta > limit)?
limit + delta : maxNodes;
if ((newLinkS = new void *[newLimit])
== (void **)0)
return (void *)0;
if ((i = limit - first) > nodes)
i = nodes;
if (i)
memcpy(newLinkS,&linkS[first],
sizeof(linkS[0U])*i);
/* copy wrap around */
if (i < nodes)
memcpy(&newLinkS[i],linkS,
sizeof(linkS[0U])
*(nodes-i));
/*
Compute next smaller linkS size
and threshold for shrinking.
*/
lowLimit = limit;
lowThreshold = lowLimit - delta;
/* swap new for old */
delete linkS;
linkS = newLinkS;
limit = newLimit;
first = 0U;
}
if (!Dattach(D))
return (void *)0;
if (!n) /* push */
linkS[first? --first
: (first = limit - 1)] = D;
else if (n >= nodes) /* insQ */
linkS[(first+(n=nodes))%limit] = D;
else { /* insert interior */
i = (first + n) % limit;
if (i < first || !first)
/* move rear rightward */
memmove(&linkS[i+1],&linkS[i],
sizeof(linkS[0U])
* (nodes-n));
else { /* move front leftward */
memmove(&linkS[first-1],
&linkS[first],
sizeof(linkS[0U])
*(n));
first--;
i--;
}
linkS[i] = D;
}
nodes++;
if (n <= curNode)
curNode++;
flags &= ~CL_SORTED;
return D;
}
void * cl::atInsNew(unsigned n, const void * D)
{
void * cD;
if (D && flags & CL_DNEW)
if ((cD = Dnew(D)) != (void *)0)
if (atIns(n,cD)) {
flags |= CL_DNEWED;
return cD;
}
else
Ddelete(cD);
return (void *)0;
}
void * cl::atRmv(unsigned n)
{
void ** newLinkS;
unsigned newLimit, i;
void * D;
if (!linkS || n >= nodes)
return (void *)0;
D = linkS[i=(first+n)%limit];
if (!n) { /* pop */
if (++first >= limit)
first = 0U;
}
else if (n != nodes-1) /* del interior */
if (i < first) /* move tail leftward */
memmove(&linkS[i],&linkS[i+1],
sizeof(linkS[0U])
*(nodes-n-1));
else { /* move head rightward */
memmove(&linkS[first+1],
&linkS[first],
sizeof(linkS[0U])*n);
first++;
}
if (--nodes == 0U)
flags |= CL_SORTED;
if (n < curNode)
curNode--;
else if (n == curNode)
curNode = nodes;
if (nodes < lowThreshold) {
newLimit = lowLimit;
if ((newLinkS = new void *[newLimit])
!= (void **)0) {
if ((i = limit - first)
> nodes)
i = nodes;
if (i)
memcpy(newLinkS,
&linkS[first],
sizeof(linkS[0U])*i);
/* copy wrap around */
if (i < nodes)
memcpy(&newLinkS[i],
linkS,
sizeof(linkS[0U])
*(nodes-i));
/*
Compute next smaller linkS
size and threshold for
shrinking.
*/
if (lowLimit - delta > delta)
lowLimit -= delta;
else
lowLimit = delta;
lowThreshold =
lowLimit - delta;
/* swap new for old */
delete linkS;
linkS = newLinkS;
limit = newLimit;
first = 0U;
}
}
Ddetach(D);
return D;
}
void cl::allRmv()
{
flags &= ~CL_DNEWED;
while (atRmv(0U)) /* null stmt */ ;
}
int cl::atDel(unsigned n)
{
void * D;
if (flags & CL_DDELETE)
if ((D = atRmv(n)) != (void *)0) {
Ddelete(D);
return 1;
}
return 0;
}
void * cl::atDelAsg(unsigned n, void * D)
{
void * S;
if (D && flags & CL_DASSIGN
&& flags & CL_DDELETE)
if ((S = atGet(n)) != (void *)0)
if (D != S) {
(flags &= ~CL_DREAD)
|= CL_DREAD_DEL;
if (Dassign(D,S)) {
(void) atDel(n);
return D;
}
}
return (void *)0;
}
int cl::allDel()
{
void * D;
if (flags & CL_DDELETE) {
while ((D = atRmv(0U)) != (void *)0)
Ddelete(D);
return 1;
}
return 0;
}
void cl::allClr()
{
if (flags & CL_DDELETE)
allDel();
else
allRmv();
}
void * cl::atPut(unsigned n, void * D)
{
if (linkS && D && (n < nodes)) {
void *& N = linkS[(first+n)%limit];
if (D != N) if (Dattach(D)) {
flags &= ~CL_SORTED;
Ddetach(N);
if (flags & CL_DDELETE)
Ddelete(N);
return (N=D);
}
}
return (void *)0;
}
void * cl::atPutNew(unsigned n, const void * D)
{
void * oldD, * cD;
if (!D || !(flags & CL_DNEW))
return (void *)0;
if ((oldD = atGet(n)) == (void *)0)
return (void *)0;
if (oldD == D)
return (void *)0;
if ((cD = Dnew(D)) != (void *)0)
if (atPut(n,cD)) {
flags |= CL_DNEWED;
return cD;
}
else
Ddelete(cD);
return (void *)0;
}
void * cl::atPutAsg(unsigned n, const void * D)
{
void * oldD;
if (D && flags & CL_DASSIGN)
if ((oldD = atGet(n)) != (void *)0)
if (D != oldD) {
flags &= ~(CL_DREAD
| CL_DREAD_DEL);
return Dassign(oldD,D);
}
return (void *)0;
}
void * cl::atGet(unsigned n)
{
return ((linkS && (n < nodes))?
linkS[(first+n)%limit] : (void *)0);
}
void * cl::atGetAsg(unsigned n, void * D)
{
void * N;
if (D && flags & CL_DASSIGN)
if ((N = atGet(n)) != (void *)0)
if (D != N) {
(flags &= ~CL_DREAD_DEL)
|= CL_DREAD;
return Dassign(D,N);
}
return (void *)0;
}
void * cl::atXchg(unsigned n, void * D)
{
if (linkS && D && (n < nodes))
if (Dattach(D)) {
flags &= ~CL_SORTED;
void *& N = linkS[(first+n)
%limit];
void * oldD = N;
N = D;
Ddetach(oldD);
return oldD;
}
return (void *)0;
}
unsigned cl::index(const void * D)
{
unsigned i;
if (linkS && D)
for (i = 0U; i < nodes; i++)
if (D == linkS[(first+i)
%limit])
return i;
return CL_NOTFOUND;
}
unsigned cl::CurNode()
{
return ((curNode < nodes)?
curNode : CL_NOTFOUND);
}
int cl::setCurNode(unsigned n)
{
return ((curNode = ((n > nodes)? nodes : n))
< nodes);
}
void * cl::ins(void * D)
{
if (atIns(curNode+1,D)) {
if (++curNode >= nodes)
curNode = nodes - 1;
return D;
}
return (void *)0;
}
void * cl::insNew(const void * D)
{
void * cD;
if (D && flags & CL_DNEW)
if ((cD = Dnew(D)) != (void *)0)
if (ins(cD)) {
flags |= CL_DNEWED;
return cD;
}
else
Ddelete(cD);
return (void *)0;
}
void * cl::rmv()
{
void * D;
unsigned n;
if ((D = atRmv(n=curNode)) != (void *)0)
if (n)
curNode = n - 1;
else
curNode = 0;
return D;
}
int cl::del()
{
void * D;
if (flags & CL_DDELETE)
if ((D = rmv()) != (void *)0) {
Ddelete(D);
return 1;
}
return 0;
}
void * cl::delAsg(void * D)
{
void * S;
if (D && flags & CL_DASSIGN
&& flags & CL_DDELETE)
if ((S = atGet(curNode)) != (void *)0)
if (D != S) {
(flags &= ~CL_DREAD)
|= CL_DREAD_DEL;
if (Dassign(D,S)) {
(void) del();
return D;
}
}
return (void *)0;
}
void * cl::next()
{
if (linkS) {
if (curNode >= nodes)
curNode = 0U;
else
curNode++;
if (curNode < nodes)
return linkS[(first+curNode)
%limit];
}
return (void *)0;
}
void * cl::nextAsg(void * D)
{
unsigned oldCurNode = curNode;
void * S;
if (D && flags & CL_DASSIGN)
if ((S = next()) != (void *)0) {
if (D != S) {
(flags &= ~CL_DREAD_DEL)
|= CL_DREAD;
if (Dassign(D,S))
return D;
}
curNode = oldCurNode;
}
return (void *)0;
}
void * cl::prev()
{
if (linkS) {
if (curNode) {
if (curNode > nodes)
curNode = nodes;
curNode--;
}
else
curNode = nodes;
if (curNode < nodes)
return linkS[(first+curNode)
%limit];
}
return (void *)0;
}
void * cl::prevAsg(void * D)
{
unsigned oldCurNode = curNode;
void * S;
if (D && flags & CL_DASSIGN)
if ((S = prev()) != (void *)0) {
if (D != S) {
(flags &= ~CL_DREAD_DEL)
|= CL_DREAD;
if (Dassign(D,S))
return D;
}
curNode = oldCurNode;
}
return (void *)0;
}
int cl::sort(voidCmP cmP)
{
unsigned low, mid, high;
unsigned d;
void * D;
/*
The current node is always reset to undefined
regardless of the outcome of sort.
*/
curNode = nodes;
if (!this->cmP)
this->cmP = DcmP(voidCmP0);
if (flags & CL_SORTED) {
if (this->cmP == cmP || !cmP)
return 1;
}
else if (!this->cmP && !cmP)
return 0;
if (cmP) {
this->cmP = cmP;
flags &= ~CL_SORTED;
}
if (!nodes)
return (int) (flags |= CL_SORTED);
if (!linkS)
return 0;
if (first) {
/* form contiguous block at front */
d = (first + nodes) % limit;
if (d > first)
memmove(linkS,&linkS[first],
sizeof(linkS[0U])*nodes);
else if (d < first)
memmove(&linkS[d],
&linkS[first],
sizeof(linkS[0U])
*(limit-first));
/* else array is full/contiguous */
first = 0U;
}
for (high = d = 1; d < nodes; high = ++d) {
low = 0U;
D = linkS[d];
while (low < high) {
mid = low +
((high - low) >> 1);
if ((*this->cmP)(D,
linkS[mid]) <= 0)
high = mid;
else
low = mid + 1;
}
if (high < d) {
memmove(&linkS[high+1],
&linkS[high],
sizeof(linkS[0U])
*(d-high));
linkS[high] = D;
}
}
return (int) (flags |= CL_SORTED);
}
void * cl::insSort(void * D)
{
unsigned low, mid, high;
void * ok;
/*
The current node is left undefined if
anything fails, otherwise it is set to the
newly inserted node.
*/
curNode = nodes;
if (!cmP) if ((cmP = DcmP(voidCmP0))
== voidCmP0) return (void *)0;
if (!linkS || !D || nodes >= maxNodes)
return (void *)0;
if (!(flags & CL_SORTED))
if (!sort())
return (void *)0;
low = 0U;
high = nodes;
while (low < high) {
mid = low + ((high - low) >> 1);
if ((*cmP)(D,
linkS[(first+mid)%limit]) <= 0)
high = mid;
else
low = mid + 1;
}
if ((ok = atIns(high,D)) != (void *)0)
curNode = high;
/* atIns() resets sorted to zero */
flags |= CL_SORTED;
return ok;
}
void * cl::insSortNew(const void * D)
{
void * cD;
if (D && flags & CL_DNEW)
if ((cD = Dnew(D)) != (void *)0)
if (insSort(cD)) {
flags |= CL_DNEWED;
return cD;
}
else
Ddelete(cD);
return (void *)0;
}
void * cl::insUnique(void * D)
{
if (!findFirst(D))
return insSort(D);
return (void *)0;
}
void * cl::insUniqueNew(const void * D)
{
if (!findFirst(D))
return insSortNew(D);
return (void *)0;
}
void * cl::findFirst(const void * K)
{
unsigned low, mid, high;
void * D;
/*
The current node is left undefined if
anything fails, otherwise it is set to the
newly found node.
*/
curNode = nodes;
if (!cmP) if ((cmP = DcmP(voidCmP0))
== voidCmP0) return (void *) 0;
if (!linkS || !K || !nodes)
return (void *)0;
if (flags & CL_SORTED) {
low = 0U;
high = nodes;
while (low < high) {
mid = low +
((high - low) >> 1);
if ((*cmP)(K,linkS[(first+mid)
%limit]) <= 0)
high = mid;
else
low = mid + 1;
}
if (high < nodes)
if (!(*cmP)(K,D=linkS[(first+
high)%limit])) {
curNode = high;
return D;
}
}
else { /* linear search! */
while ((D = next()) != (void *)0)
if (!(*cmP)(K,D))
return D;
}
return (void *)0;
}
void * cl::findNext(const void * K)
{
/*
For sorted cls you must first call
findFirst() to insure consistent results!
*/
void * D;
/*
The current node is left undefined if
anything fails, otherwise it is set to the
newly found node.
*/
if (!cmP)
cmP = DcmP(voidCmP0);
if (!linkS || !K || !cmP) {
curNode = nodes;
return (void *)0;
}
while ((D = next()) != (void *)0)
if (!(*cmP)(K,D))
return D;
else if (flags & CL_SORTED) {
curNode = nodes;
break; /* Look no further! */
}
return (void *)0;
}
void * cl::findLast(const void * K)
{
unsigned low, mid, high;
void * D;
/*
The current node is left undefined if
anything fails, otherwise it is set to the
newly found node.
*/
curNode = nodes;
if (!cmP) if ((cmP = DcmP(voidCmP0))
== voidCmP0) return (void *)0;
if (!linkS || !K || !nodes)
return (void *)0;
if (flags & CL_SORTED) {
low = 0U;
high = nodes;
while (low < high) {
mid = low +
((high - low) >> 1);
if ((*cmP)(K,linkS[(first+mid)
%limit]) < 0)
high = mid;
else
low = mid + 1;
}
if (high < nodes)
if (!(*cmP)(K,D=linkS[(first+
high)%limit])) {
curNode = high;
return D;
}
}
else { /* linear search! */
while ((D = prev()) != (void *)0)
if (!(*cmP)(K,D))
return D;
}
return (void *)0;
}
void * cl::findPrev(const void * K)
{
/*
For sorted cls you must first call
findLast() to insure consistent results!
*/
void * D;
/*
The current node is left undefined if
anything fails, otherwise it is set to the
newly found node.
*/
if (!cmP)
cmP = DcmP(voidCmP0);
if (!linkS || !K || !cmP) {
curNode = nodes;
return (void *)0;
}
while ((D = prev()) != (void *)0)
if (!(*cmP)(K,D))
return D;
else if (flags & CL_SORTED) {
curNode = nodes;
break; /* Look no further! */
}
return (void *)0;
}
unsigned cl::findAll(const void * K)
{
unsigned count = 0U;
/* The current node is left undefined. */
if (findFirst(K))
do {
count++;
} while (findNext(K));
return count;
}
struct GenericFnCRecord {
GenericFnC fnC;
unsigned id;
GenericFnCRecord(GenericFnC fnC, unsigned id)
{ this->fnC = fnC; this->id = id; }
~GenericFnCRecord() {}
};
typedef struct GenericFnCRecord * GenericFnCR;
#define GenericFnCR0 ((GenericFnCR)0)
int FunctionRegistry::regFnC(GenericFnC fnC,
unsigned id)
{
unsigned i;
if (!fnC && !id) // NULL's id is 0
return 1;
if ((!fnC && id) || (fnC && !id))
return 0;
for (i = 0U; i < Nodes(); i++)
if (((GenericFnCR)atGet(i))->id
== id)
break;
if (i < Nodes())
return 0;
GenericFnCR R = new GenericFnCRecord(fnC,id);
if (!R)
return 0;
else if (!insQ((void *)R)) {
delete R;
return 0;
}
return 1;
}
unsigned FunctionRegistry::fnC_2_ID(GenericFnC fnC)
{
GenericFnCR R;
unsigned i;
if (!fnC)
return 0U;
for (i = 0U; (R = (GenericFnCR) atGet(i))
!= GenericFnCR0; i++)
if (R->fnC == fnC)
return R->id;
return 0U;
}
GenericFnC FunctionRegistry::ID_2_fnC(unsigned id)
{
GenericFnCR R;
unsigned i;
if (!id)
return GenericFnC0;
for (i = 0U; (R = (GenericFnCR) atGet(i))
!= GenericFnCR0; i++)
if (R->id == id)
return R->fnC;
return GenericFnC0;
}
FunctionRegistry fnCv;