UPLOAD - DOSUIT07.ZIP - COLLECT.HPP

 
Output of file : COLLECT.HPP contained in archive : DOSUIT07.ZIP

// Collections and Iterators
#ifndef COLLECT_HPP
#define COLLECT_HPP
#include
#ifdef __TURBOC__
#include
#ifndef name2
#define name2(z, y) z ## y
#endif
#ifndef name3
#define name3(z, y, x) z ## y ## x
#endif
#endif
#ifdef __ZTC__
#include
#endif

/*
This class library (like most others) provides a Collection class to
hold lists of objects. This base Collection class will hold any
object, as the implementation is a dynamic array of void pointers.
The generic class macros are used to provide type-safe Collections
of any particular kind of object, and also Stacks and Queues. A
useful variety of methods are provided, together with a copy
constructor and assignment operator, so you can assign Collections
to one another without problems.

Collection has an addition operator provided which enables a
list of objects to be created inside a call to a function or
constructor. This allows us to pass a variable number of objects
without having to use unsafe variable argument lists.

For example, if a function needs to process a variable number of void
pointers, its signature might be ...

extern process(const Collection &listOfVoidPointers);

and it might be called with ...

process(Collection()
+ (void *)new TextEdit(string, 10, "Enter me")
+ (void *)new Button("~Push me")
+ (void *)new Text("Text item")
);

I real life, most such functions take some typesafe subclass of
Collection, which can only hold pointers to objects of a specific
type. This construct is often used in constructors for user interface
objects, enabling the building of a complex structure of nested
objects in a single statement.
*/
class Collection {
public:
Collection(int hintSize = 0);
Collection(const Collection& c);
~Collection();

//~ Assignment and addition operators
Collection& operator= (const Collection& c);
Collection& operator+ (const Collection &c);
Collection& operator+ (const Collection *c) { return operator+(*c); }
Collection& operator+ (void *c) { append(c); return *this; }

//~ Maintain the list
// All the following return 0 for success
void insert(void *c); // Add item to beginning of list.
void append(void *c); // Add item to end of list.
int add(void *c, int position = -1); // Add at position (-1=end).
void appendvalist(va_list v)/*!*/;

int remove(const void *c); // Remove item from list.

//~ Access functions
int size() const // Number of elements in the list.
{ return uelements; }
void *first() const // Return first item on list.
{ return (uelements ? list[0] : 0); }
void *last() const // Return last item on list.
{ return (uelements ? list[uelements - 1] : 0); }
void *operator[](int i) const // Return an element from list.
{ return (i >= 0 && i < uelements) ? list[i] : 0; }
int elementNo(const void *e) const; // Return element no. of an item.

//~ Optimisation - expand list
void setsize(int n) // Make big enough for at least n elements.
{ if(n > nelements) expand(nelements - n); }
int expand(int n = 1); // Make the array n elements bigger.

//~ Remove items
void *get(); // Remove and return the first item on the list.
void *getlast() { return (uelements) ? list[--uelements] : 0; }
// Remove and return the last item on the list.
// Because of the way the list is implemented, this is more
// efficient than get().

int error()
{ int e = err; err = 0; return e; }
// Returns non-zero if an operation (e.g. add) failed because of
// shortage of memory.

void print(const char *s = "",const char newline = '\n') const /*!*/;
static int debug/*!*/;

protected:
void seterror(int e = 1) { err = e; }

protected:
friend class Iterator;
void **list; // Pointer to contents.
int nelements; // Number of elements in array.
int uelements; // Number of elements in use.
int err; // Error indicator.

};

/*
This class provides an iterator to step over the elements of a
Collection one at a time. The class allows traversal in either
direction, and maintains a default direction set up in the
constructor. The Iterator can even be started at a particular
element in the Collection, rather than at the beginning (or end if
traversal is backwards).
*/
class Iterator {
const Collection &list;
int i; // current element no
int b; // direction is backwards
public:
Iterator(const Collection& l,int backwards = 0);
Iterator(const Collection& l,const void *e,int backwards = 0);

//~ Move pointer about list
void start() { i = -1; }
void end() { i = -1; }
void reset() { i = -1; } // To start/end of list.
int set(const void* s); // To a particular member of list.

//~ Normal traversal of list
void *next();
void *previous();
void *operator() ();
// Access next element in default direction.
};

#define GCollection(type) name2(GCollection,type)

/*
A generic Collection to hold items of a particular type. See
Collection for method details. To declare a Collection class to hold
Widgets (say), all you need to do is ...

declare(GCollection,Widget);

This will create a Collection class, called GCollection(Widget).
Note that all the functions are inline, so no further implementation
is needed. Stacks and Queues are created in a similar way, but are
provided with appropriate maintenance and access methods - see
GQueue(type) and GStack(type).
*/
#define GCollectiondeclare(type)\
class GCollection(type): public Collection {\
public:\
GCollection(type)(int hintSize = 0) : Collection(hintSize) {}\
GCollection(type)(const GCollection(type)& c) : Collection(c) {} \
GCollection(type)& operator= (const GCollection(type)& c) \
{ Collection::operator=(c); return *this; } \
GCollection(type)& operator+ (const GCollection(type) &c) \
{ Collection::operator+(c); return *this; }\
GCollection(type)& operator+ (const GCollection(type) *c) \
{ Collection::operator+(c); return *this; }\
GCollection(type)& operator+ (type *c) \
{ append(c); return *this; } \
int add(type *item, int position = -1) \
{ return Collection::add((void *)item,position); }\
void insert(type *item) { Collection::insert((void *)item); }\
void append(type *item) { Collection::append((void *)item); }\
int remove(const type *item) { return Collection::remove((void *)item); }\
type *first() const { return (type *)Collection::first(); }\
type *last() const { return (type *)Collection::last(); }\
type *operator[](int i) const \
{ return (type *)Collection::operator[](i); }\
int elementNo(const type *e) const { return Collection::elementNo(e); }\
type *get() { return (type *)Collection::get(); }\
type *getlast() { return (type *)Collection::getlast(); }\
}

#define GIterator(type) name2(GIterator,type)
/*
An Iterator which iterates over a generic Collection -
GCollection(type). To declare an Iterator class for a
GCollection(Widget) (say), all you need to do is ...

declare(GIterator,Widget);

This will create an Iterator class, called GIterator(Widget). Note
that all the functions are inline, so no further implementation is
needed.
*/
#define GIteratordeclare(type)\
class GIterator(type) : public Iterator {\
public:\
GIterator(type)(const GCollection(type)& s,int bk = 0) : Iterator(s,bk) {}\
GIterator(type)(const GCollection(type)& s,const type *e,int bk = 0) \
: Iterator(s,e,bk) {}\
int set(const type *s) { return Iterator::set(s); }\
type *next() { return (type *)Iterator::next(); }\
type *previous() { return (type *)Iterator::previous(); }\
type *operator()()\
{ return (type *)Iterator::operator()(); }\
}

#define GStack(type) name2(GStack,type)

/*
A generic stack to hold items of a particular type. To declare a Stack
class to hold Widgets (say), all you need to do is ...

declare(GStack,Widget);

Note that all the functions are inline, so no further implementation
is needed.
*/
#define GStackdeclare(type)\
class GStack(type): public Collection {\
public:\
GStack(type)(int hintSize = 0) : Collection(hintSize) {}\
GStack(type)(const GStack(type)& c) : Collection(c) {} \
GStack(type)& operator= (const GStack(type)& c) \
{ Collection::operator=(c); return *this; } \
void push(type *item) { Collection::append((void *)item); }\
type *peek() const { return (type *)Collection::last(); }\
type *pop() const { return (type *)Collection::getlast(); }\
}

#define GQueue(type) name2(GQueue,type)

/*
A generic queue to hold items of a particular type. For
constructors, see Collection. To declare a Queue class to hold
Widgets (say), all you need to do is ...

declare(GQueue,Widget);

Note that all the functions are inline, so no further implementation
is needed.
*/
#define GQueuedeclare(type)\
class GQueue(type): public Collection {\
public:\
GQueue(type)(int hintSize = 0) : Collection(hintSize) {}\
GQueue(type)(const GQueue(type)& c) : Collection(c) {} \
GQueue(type)& operator= (const GQueue(type)& c) \
{ Collection::operator=(c); return *this; } \
void put(type *item) { Collection::append((void *)item); }\
type *peek() const { return (type *)Collection::first(); }\
type *last() const { return (type *)Collection::last(); }\
type *get() { return (type *)Collection::get(); }\
}

class VObject;

/*
Collection containing only VObjects. This is a separate class, so
that it can be used as the base for a further generic class -
OCollection(type).
*/
class ObjectCollection : public Collection {
int (*compfn)(const VObject *,const VObject *); // comparison function
public:
ObjectCollection(int hintSize = 0);
ObjectCollection(const ObjectCollection& c);
ObjectCollection& operator= (const ObjectCollection& c)
{ Collection::operator=(c); compfn = c.compfn; return *this; }
ObjectCollection& operator+ (const ObjectCollection &c)
{ Collection::operator+(c); return *this; }
ObjectCollection& operator+ (const ObjectCollection *c)
{ Collection::operator+(c); return *this; }
ObjectCollection& operator+ (VObject *c) { add(c); return *this; }
int add(VObject *item);
void insert(VObject *item) { Collection::insert(item); }
void append(VObject *item) { Collection::append(item); }
int remove(const VObject *item) { return Collection::remove(item); }
void deleteall(); // Delete all the VObjects in the Collection.
VObject *first() const { return (VObject *)Collection::first(); }
VObject *last() const { return (VObject *)Collection::last(); }
VObject *operator[](int i) const
{ return (VObject *)Collection::operator[](i); }
int elementNo(const VObject *e) const { return Collection::elementNo(e); }
VObject *get() { return (VObject *)Collection::get(); }
VObject *getlast() { return (VObject *)Collection::getlast(); }
void sort(int (*compare)(const VObject *,const VObject *))
// Sort the Collection, using the compare function provided.
{ compfn = compare; resort(); }
virtual int compare(const VObject *v1, const VObject *v2) const;
// Compare two elements using the current sort function.
void resort();
};

/*
This class provides an Iterator to step over the elements of an
ObjectCollection one at a time. For details, see Iterator.
*/
class ObjectIterator : public Iterator {
public:
ObjectIterator(const ObjectCollection& s,int bk = 0);
ObjectIterator(const ObjectCollection& s,const VObject *e,int bk = 0);
int set(const VObject *s) { return Iterator::set(s); }
VObject *next() { return (VObject *)Iterator::next(); }
VObject *previous() { return (VObject *)Iterator::previous(); }
VObject *operator()()
{ return (VObject *)Iterator::operator()(); }
};

#define OCollection(type) name2(OCollection,type)

/*
A generic ObjectCollection to hold items of a particular type. See
ObjectCollection for method details. Note that the sort method will
now require a function which takes two pointers to items of your
type, rather than VObjects. To declare an ObjectCollection class to
hold Widgets (say), all you need to do is ...

declare(OCollection,Widget);

in your header (.hpp) file. This will provide the definition of an
ObjectCollection class, called OCollection(Widget), including all
the inline functions. Then, in your .cpp file, do ...

implement(OCollection,Widget)

(Note lack of semicolon), which will implement the non- inline
functions.
*/
#define OCollectiondeclare(type)\
class OCollection(type): public ObjectCollection {\
int (*compfn)(const type *,const type *);\
public:\
OCollection(type)(int hintSize = 0);\
OCollection(type)(const OCollection(type)& c);\
OCollection(type)& operator= (const OCollection(type)& c) \
{ ObjectCollection::operator=(c); compfn = c.compfn; return *this; } \
OCollection(type)& operator+ (const OCollection(type) &c) \
{ ObjectCollection::operator+(c); return *this; } \
OCollection(type)& operator+ (const OCollection(type) *c) \
{ ObjectCollection::operator+(c); return *this; } \
OCollection(type)& operator+ (type *c) { add(c); return *this; }\
int add(type *item) { return ObjectCollection::add(item); }\
void insert(type *item) { ObjectCollection::insert(item); }\
void append(type *item) { ObjectCollection::append(item); }\
int remove(const type *item) { return ObjectCollection::remove(item); }\
type *first() const { return (type *)ObjectCollection::first(); }\
type *last() const { return (type *)ObjectCollection::last(); }\
type *operator[](int i) const \
{ return (type *)ObjectCollection::operator[](i); }\
int elementNo(const type *e) const { return ObjectCollection::elementNo(e); }\
type *get() { return (type *)ObjectCollection::get(); }\
type *getlast() { return (type *)ObjectCollection::getlast(); }\
void sort(int (*compare)(const type *,const type *))\
{ compfn = compare; resort(); }\
virtual int compare(const VObject *v1, const VObject *v2) const;\
}

#define OCollectionimplement(type)\
OCollection(type)::OCollection(type)(int hintSize)\
: ObjectCollection(hintSize), compfn(0) {}\
OCollection(type)::OCollection(type)(const OCollection(type)& c)\
: ObjectCollection(c), compfn(0) {} \
int OCollection(type)::compare(const VObject *v1, const VObject *v2) const\
{\
return compfn ? compfn((type *)v1,(type *)v2) : 0;\
}

#define OIterator(type) name2(OIterator,type)

/*
An ObjectIterator which iterates over a generic ObjectCollection -
OCollection(type). To declare an ObjectIterator class for a
OCollection(Widget) (say), all you need to do is ...

declare(OIterator,Widget);

This will create an ObjectIterator class, called OIterator(Widget).
Note that all the functions are inline, so no further implementation
is needed.
*/
#define OIteratordeclare(type)\
class OIterator(type) : public ObjectIterator {\
public:\
OIterator(type)(const OCollection(type)& s,int bk = 0) : ObjectIterator(s,bk) {}\
OIterator(type)(const OCollection(type)& s,const type *e,int bk = 0) \
: ObjectIterator(s,e,bk) {}\
int set(const type *s) { return ObjectIterator::set(s); }\
type *next() { return (type *)ObjectIterator::next(); }\
type *previous() { return (type *)ObjectIterator::previous(); }\
type *operator()()\
{ return (type *)ObjectIterator::operator()(); }\
}

#endif