blob: e1af830eecec13554d5840ca0163461a3b291a9f [file] [log] [blame]
// Copyright (C) 1999-2005 Open Source Telecom Corporation.
// Copyright (C) 2006-2010 David Sugar, Tycho Softworks.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//
// As a special exception, you may use this file as part of a free software
// library without restriction. Specifically, if other files instantiate
// templates or use macros or inline functions from this file, or you compile
// this file and link it with other files to produce an executable, this
// file does not by itself cause the resulting executable to be covered by
// the GNU General Public License. This exception does not however
// invalidate any other reasons why the executable file might be covered by
// the GNU General Public License.
//
// This exception applies only to the code released under the name GNU
// Common C++. If you copy code from other releases into a copy of GNU
// Common C++, as the General Public License permits, the exception does
// not apply to the code that you add in this way. To avoid misleading
// anyone as to the status of such modified files, you must delete
// this exception notice from them.
//
// If you write modifications of your own for GNU Common C++, it is your choice
// whether to permit this exception to apply to your modifications.
// If you do not wish that, delete this exception notice.
//
/**
* @file object.h
* @short Some object manipulation classes for smart pointers, linked lists,
* etc.
**/
#ifndef CCXX_OBJECT_H_
#define CCXX_OBJECT_H_
#ifndef CCXX_MISSING_H_
#include <cc++/missing.h>
#endif
#ifdef CCXX_NAMESPACES
namespace ost {
#endif
class __EXPORT MapObject;
class __EXPORT MapIndex;
/**
* A reference countable object. This is used in association with smart
* pointers (RefPointer).
*
* @author David Sugar <dyfet@gnutelephony.org>
* @short Object managed by smart pointer reference count.
*/
class __EXPORT RefObject
{
protected:
friend class RefPointer;
unsigned refCount;
/**
* The constructor simply initializes the count.
*/
inline RefObject()
{refCount = 0;};
/**
* The destructor is called when the reference count returns
* to zero. This is done through a virtual destructor.
*/
virtual ~RefObject();
public:
/**
* The actual object being managed can be returned by this
* method as a void and then recast to the actual type. This
* removes the need to dynamic cast from RefObject and the
* dependence on rtti this implies.
*
* @return underlying object being referenced.
*/
virtual void *getObject(void) = 0;
};
/**
* Pointer to reference counted objects. This is a non-template form
* of a reference count smart pointer, and so uses common code. This
* can be subclassed to return explicit object types.
*
* @author David Sugar <dyfet@gnutelephony.org>
* @short Pointer to reference count managed objects.
*/
class __EXPORT RefPointer
{
protected:
RefObject *ref;
/**
* Detach current object, for example, when changing pointer.
*/
void detach(void);
/**
* Patch point for mutex in derived class. This may often
* be a single static mutex shared by a managed type.
*/
virtual void enterLock(void);
/**
* Patch point for a mutex in derived class. This may often
* be a single static mutex shared by a managed type.
*/
virtual void leaveLock(void);
public:
/**
* Create an unattached pointer.
*/
inline RefPointer()
{ref = NULL;};
/**
* Create a pointer attached to a reference counted object.
*
* Object being referenced.
*/
RefPointer(RefObject *obj);
/**
* A copy constructor.
*
* Pointer being copied.
*/
RefPointer(const RefPointer &ptr);
virtual ~RefPointer();
RefPointer& operator=(const RefObject &ref);
inline void *operator*() const
{return getObject();};
inline void *operator->() const
{return getObject();};
void *getObject(void) const;
bool operator!() const;
};
/**
* Self managed single linked list object chain. This is used for
* accumulating lists by using as a base class for a derived subclass.
*
* @author David Sugar <dyfet@gnutelephony.org>
* @short Accumulating single linked list.
*/
class __EXPORT LinkedSingle
{
protected:
LinkedSingle *nextObject;
inline LinkedSingle()
{nextObject = NULL;};
virtual ~LinkedSingle();
public:
/**
* Get first linked object in list. This may be dynamically
* recast, and may refer to a master static bookmark pointer
* in a derived class. Otherwise it simply returns the current
* object. In a "free" list, this may not only return the first
* object, but also set the first to next.
*
* @return pointer to first object in list.
*/
virtual LinkedSingle *getFirst(void);
/**
* Gets the last object in the list. This normally follows the
* links to the end. This is a virtual because derived class
* may include a static member bookmark for the current end.
*
* @return pointer to last object in list.
*/
virtual LinkedSingle *getLast(void);
/**
* Get next object, for convenience. Derived class may use
* this with a dynamic cast.
*
* @return next object in list.
*/
inline LinkedSingle *getNext(void)
{return nextObject;};
/**
* Insert object into chain. This is a virtual because
* derived class may choose instead to perform an insert
* at head or tail, may manage bookmarks, and may add mutex lock.
*
* @param object being inserted.
*/
virtual void insert(LinkedSingle& obj);
LinkedSingle &operator+=(LinkedSingle &obj);
};
/**
* Self managed double linked list object chain. This is used for
* accumulating lists by using as a base class for a derived subclass.
*
* @author David Sugar <dyfet@gnutelephony.org>
* @short Accumulating double linked list.
*/
class __EXPORT LinkedDouble
{
protected:
LinkedDouble *nextObject, *prevObject;
inline LinkedDouble()
{nextObject = prevObject = NULL;};
virtual ~LinkedDouble();
virtual void enterLock(void);
virtual void leaveLock(void);
virtual LinkedDouble *firstObject();
virtual LinkedDouble *lastObject();
public:
/**
* Requested in overloaded insert() method to indicate how to insert
* data into list
*/
enum InsertMode
{
modeAtFirst, /**< insert at first position in list pointed by current object */
modeAtLast, /**< insert at last position in list pointed by current object */
modeBefore, /**< insert in list before current object */
modeAfter /**< insert in list after current object */
};
/**
* Get first linked object in list. This may be dynamically
* recast, and may refer to a master static bookmark pointer
* in a derived class. Otherwise it follows list to front.
*
* @return pointer to first object in list.
*/
virtual LinkedDouble *getFirst(void);
/**
* Gets the last object in the list. This normally follows the
* links to the end. This is a virtual because derived class
* may include a static member bookmark for the current end.
*
* @return pointer to last object in list.
*/
virtual LinkedDouble *getLast(void);
/**
* Virtual to get the insert point to use when adding new members. This
* may be current, or always head or always tail. As a virtual, this allows
* derived class to establish "policy".
*
* @return pointer to insertion point in list.
*/
virtual LinkedDouble *getInsert(void);
/**
* Get next object, for convenience. Derived class may use
* this with a dynamic cast.
*
* @return next object in list.
*/
inline LinkedDouble *getNext(void)
{return nextObject;};
/**
* Get prev object in the list.
*
* @return pointer to previous object.
*/
inline LinkedDouble *getPrev(void)
{return prevObject;};
/**
* Insert object into chain at given position, as indicated by \ref InsertMode;
* If no position is given, it defaults to \ref modeAtLast, inserting element
* at list's end.
*
* @param object being inserted.
* @param position where object is inserted.
*/
virtual void insert(LinkedDouble& obj, InsertMode position = modeAtLast);
/**
* Remove object from chain.
*/
virtual void detach(void);
LinkedDouble &operator+=(LinkedDouble &obj);
LinkedDouble &operator--();
};
/**
* A map table allows for entities to be mapped (hash index) onto it.
* Unlike with Assoc, This form of map table also allows objects to be
* removed from the table. This table also includes a mutex lock for
* thread safety. A free list is also optionally maintained for reusable
* maps.
*
* @author David Sugar <dyfet@gnutelephony.org>
* @short Table to hold hash indexed objects.
*/
class __EXPORT MapTable : public Mutex
{
protected:
friend class MapObject;
friend class MapIndex;
unsigned range;
unsigned count;
MapObject **map;
void cleanup(void);
public:
/**
* Create a map table with a specified number of slots.
*
* @param number of slots.
*/
MapTable(unsigned size);
/**
* Destroy the table, calls cleanup.
*/
virtual ~MapTable();
/**
* Get index value from id string. This function can be changed
* as needed to provide better collision avoidence for specific
* tables.
*
* @param id string
* @return index slot in table.
*/
virtual unsigned getIndex(const char *id);
/**
* Return range of this table.
*
* @return table range.
*/
inline unsigned getRange(void)
{return range;};
/**
* Return the number of object stored in this table.
*
* @return table size.
*/
inline unsigned getSize(void)
{return count;};
/**
* Lookup an object by id key. It is returned as void * for
* easy re-cast.
*
* @param key to find.
* @return pointer to found object or NULL.
*/
void *getObject(const char *id);
/**
* Map an object to our table. If it is in another table
* already, it is removed there first.
*
* @param object to map.
*/
void addObject(MapObject &obj);
/**
* Get the first element into table, it is returned as void * for
* easy re-cast.
*
* @return pointer to found object or NULL.
*/
void *getFirst();
/**
* Get the last element into table, it is returned as void * for
* easy re-cast.
*
* @return pointer to found object or NULL.
*/
void *getLast();
/**
* Get table's end, useful for cycle control; it is returned as void * for
* easy re-cast.
*
* @return pointer to found object or NULL.
*/
void *getEnd()
{ return NULL; };
/**
* Get next object from managed free list. This returns as a
* void so it can be recast into the actual type being used in
* derived MapObject's. A derived version of MapTable may well
* offer an explicit type version of this. Some derived
* MapObject's may override new to use managed list.
*
* @return next object on free list.
*/
void *getFree(void);
/**
* Add an object to the managed free list. Some MapObject's
* may override delete operator to detach and do this.
*
* @param object to add.
*/
void addFree(MapObject *obj);
/**
* An operator to map an object to the table.
*
* @return table being used.
* @param object being mapped.
*/
MapTable &operator+=(MapObject &obj);
/**
* This operator is virtual in case it must also add the object to a
* managed free list.
*
* @return current table.
* @param object entity to remove.
*/
virtual MapTable &operator-=(MapObject &obj);
};
/**
* The MapIndex allows linear access into a MapTable, that otherwise could have
* its elements being retrieved only by key.
* It can be increased, checked and dereferenced like a pointer, by means of
* suitable operators.
*
* @author Sergio Repetto <s.repetto@pentaengineering.it>
* @short Index object to access MapTable elements
*/
class __EXPORT MapIndex
{
MapObject* thisObject;
public :
/**
* Creates an empty map index (pointing to nothing).
*/
MapIndex() : thisObject(NULL)
{};
/**
* Creates a map index pointing to a specific map object
*
* @param the indexed object
*/
MapIndex(MapObject* theObject) : thisObject(theObject)
{};
/**
* Creates a copy of a given map index
*
* @param the source index object
*/
MapIndex(const MapIndex& theIndex) : thisObject(theIndex.thisObject)
{};
/**
* Dereference operator: the pointed object it is returned as void * for
* easy re-cast.
*
* @return pointer to indexed object.
*/
void* operator*() const
{ return (void*)thisObject; }
/**
* Assignment operator to avoid implicit cast.
*
* @return the object itself, as changed.
*/
MapIndex& operator=(MapObject *theObject);
/**
* Prefix increment operator, to be used in loops and such.
*
* @return the object itself, as changed.
*/
MapIndex& operator++(); // prefix
/**
* Postfix increment operator, to be used in loops and such.
*
* @return the object itself, as changed.
*/
MapIndex operator++(int) // postfix
{ return this->operator++(); }
/**
* Comparison operator, between two MapIndex's.
*
* @return the object itself, as changed.
*/
bool operator==(const MapIndex& theIndex) const
{ return thisObject == theIndex.thisObject; };
bool operator!=(const MapIndex& theIndex) const
{ return !(*this == theIndex); };
/**
* Comparison operator, between the MapIndex and a MapObject, useful to avoid
* casts for sake of clearness.
*
* @return the object itself, as changed.
*/
bool operator==(const MapObject* theObject) const
{ return thisObject == theObject; };
bool operator!=(const MapObject* theObject) const
{ return !(*this == theObject); };
};
/**
* The MapObject is a base class which can be used to make a derived
* class operate on a MapTable. Derived classes may override new and
* delete operators to use managed free list from a MapTable.
*
* @author David Sugar <dyfet@gnutelephony.org>
* @short Mappable object.
*/
class __EXPORT MapObject
{
protected:
friend class MapTable;
friend class MapIndex;
MapObject *nextObject;
const char *idObject;
MapTable *table;
public:
/**
* Remove the object from it's current table.
*/
void detach(void);
/**
* Save id, mark as not using any table.
*
* @param id string for this object.
*/
MapObject(const char *id);
};
#ifdef CCXX_NAMESPACES
}
#endif
#endif
/** EMACS **
* Local variables:
* mode: c++
* c-basic-offset: 4
* End:
*/