Data Structures As Objects
by Jiri Soukup 

Listing One
struct Circuit {
    Block *blocks;
    Net *nets;
};
struct Block {
    Block *next;
    Terminal *term;
    char *name;
};
struct Net {
    Net *next;
    Terminal *term;
    char *name;
};
struct Terminal {
    Block *nextOnBlock;
    Block *nextOnNet;
    Block *block;
    Net *net;
    char *name;
};
/* print all nets in the circuit */
void prtNets(Circuit *c){
    Net *np;
    for(np=nets; np; np=np->next){
        printf("%s\n",np->name);
    }
}
/* print nets connected to block bp */
void prtTerms(Block *bp){
    Terminal *tp;
    for(tp=bp->term; tp; tp=tp->next){
        printf("%s\n",tp->net->name);
    }
}
/* add Terminal to a Block */
void addTermToBlock(Terminal *tp, Block *bp){
    tp->nextOnBlock=bp->term;
    bp->term=tp;
    block=bp;
}
/* add Terminal to a Net */
void addTermToNet(Terminal *tp, Net *np){
    tp->nextOnNet=np->term;
    np->term=tp;
    tp->net=np;
}
/* create Terminal, attach it to block and net */
Terminal *createTerminal(Block *bp, Net *np, char *name){
    Terminal *tp; char *p;
    tp=(Terminal*)malloc(sizeof(Terminal));
    p=malloc(strlen(name)+1);
    if(!tp || !p)return NULL;
    addTermToBlock(tp,bp);
    addTermToNet(tp,np);
    strcpy(p,name);
    tp->name=p;
    return tp;
}


Listing Two
template<class T> Collection {
public:
    void add(T *tp);
    ...
};
template<class T> CollIterator {
public:
    CollIterator(Collection<T>& col);
    T* operator++();
    ...
};
class Circuit {
    Collection<Block> blocks;
    Collection<Net> nets;
public:
    void prtNets();
};
class Block {
    Collection<Term> termsOnBlock;
    char *name;
public:
    void prtTerms();
};
class Net {
    Collection<Term> termsOnNet;
    char *name;
};
class Terminal {
    Block *block;
    Net *net;
    char *name;
public:
    Terminal(Block *bp, Net *np, char *tName);
};
/* print all nets in the circuit */
void Circuit::prtNets(){
    Net *np;
    CollIterator<Net> it(nets);
    while(np= ++it){
        printf("%s\n",np->name);
    }
}
/* print nets connected to block bp */
void Block::prtTerms(){
    Terminal *tp;
    CollIterator<Terminal> it(termsOnNet);
    while(np= ++it){
        printf("%s\n",tp->net->name);
    }
}
/* replaces the original function createTerminal() */
Terminal:Terminal(Block *bp, Net *np, char *tName){
    name= new char[strlen(name)+1];
    if(name)strcpy(name,tName);
    bp->blocks.add(this);
    block=bp;
    np->nets.add(this);
    net=np;
    return tp;
}

Listing Three
template<class T> Collection {
    T **p;
    int sz,used;
    void growArray();
public:
    Collection(){p=NULL; sz=used=0;}
    void add(T *tp){
        if(used>=sz)growArray();
        p[used]=tp; used++;
    }
    ...
};

Listing Four
class Course {
    Collection<Student> students;
    ...
};
class Student {
    Collection<Course> courses;
    ...
};

Listing Five
void addTermToNet(Terminal *tp, Net *np){
    if(tp->nextOnNet || tp->net){
        printf("error: cannot add term=%x\n",tp);
        return;
    }
    tp->nextOnNet=np->term;
    np->term=tp;
    tp->net=np;
}
/* returns NULL when np properly destroyed */
Net *destroyNet(Net *np){
    if(next || term || name){
        printf("error: net=%x not disconnected\n",np);
    }
    else {free np; np=NULL;}
    return np;
}

Listing Six
// ---------- class library --------------------
// In Collection, Child does not know its Parent.
template<class Parent, class Child> Collection {
public:
    void add(Parent *pp, Child *cp);
    ...
};
template<class Parent, class Child> CollIterator {
public:
    CollIterator(Parent *pp);
    Child* operator++();
    ...
};
// Aggregate is a Collection, where each Child keeps a pointer to its Parent.
template<class Parent, class Child> Aggregate {
public:
    void add(Parent *pp, Child *cp);
    ...
};
template<class Parent, class Child> AggrIterator {
public:
    AggrIterator(Parent *pp);
    Child* operator++();
    ...
};
// -------- application code -------------------
class Circuit {
    If PARTICIPATE(Circuit);
public:
    void prtNets();
};
class Block {
 If PARTICIPATE(Block);
    char *name;
public:
    void prtTerms();
};
class Net {
 If PARTICIPATE(Net);
    char *name;
};
class Terminal {
 If PARTICIPATE(Terminal);
public:
    Terminal(Block *bp, Net *np, char *tName);
};
/* --------  DATA STRUCTURE SCHEMA -------- */
Collection<Circuit,Block>  blocks;
Collection<Circuit,Net>    nets;
Aggregate<Block,Terminal> termsOnBlock;
Aggregate<Net,Terminal>   termsOnNet;
/* ---------------------------------------- */
/* print all nets in the circuit */
void Circuit::prtNets(){
    Net *np;
    CollIterator<Circuit,Net> it(this);
    while(np= ++it){
        printf("%s\n",np->name);
    }
}
/* print nets connected to block bp */
void Block::prtTerms(){
    Terminal *tp;
    AggrIterator<Block,Terminal> it(this);
    while(np= ++it){
        printf("%s\n",tp->net->name);
    }
}
/* replaces the original function createTerminal() */
Terminal:Terminal(Block *bp, Net *np, char *tName){
    name= new char[strlen(name)+1];
    if(name)strcpy(name,tName);
    blocks.add(bp,this);
    nets.add(np,this);
    return tp;
}

Listing Seven
int Circuit::howBig(int numBlocks,int numNets,int numTerminals){
    return numBlocks*sizeof(Block) +
           numNets*sizeof(Net) +
           numTerminals*sizeof(Terminal);
}

Listing Eight
// input a small data set from a manually coded ascii file;
void Circuit::inputData(char *fileName);
 // generate large pseudorandom data of given size
void Circuit::randomData(int numTerms,int maxTermsOnNet,int maxTermsOnBlock);
    






5


