/*
 * e4graph.h --
 *
 *	This file contains the definition of the public interface part of the
 *	e4Graph library. It defines the following classes:
 *
 *	e4_RefCount	-- A base class used to manage lifecycle.
 *	e4_Storage	-- A representation of tree data storage.
 *	e4_Node		-- A representation of a node.
 *	e4_Vertex	-- A representation of a vertex.
 *	e4_StorageVisitor --
 *			   A visitor ranging over the currently open
 *			   storages.
 *	e4_VertexVisitor-- A visitor ranging over various selections of
 *			   vertices in a storage.
 *	e4_NodeVisitor	-- A visitor ranging over the nodes in a storage.
 *	e4_ParentVisitor
 *			-- A visitor ranging over the parent nodes of a
 *			   given node.
 *
 *	Some utility classes are also defined here:
 *
 *	e4_HashTable	-- A hash table for use with e4Graph.
 *	e4_HashEntry	-- A hash entry in a hash table.
 *	e4_HashSearch	-- A way to search through a hash table.
 *	e4_DString	-- A dynamic string facility that grows efficiently.
 *
 * Copyright (c) 2000-2003, JYL Software Inc.
 * 
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 * 
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE, EVEN IF
 * JYL SOFTWARE INC. IS MADE AWARE OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef	__E4_GRAPH_H__
#define	__E4_GRAPH_H__

/*
 * Version string (updated each release):
 */

#define E4GRAPH_VERSION		"1.0a11"

/*
 * Enumeration defining the possible release status codes:
 */

typedef enum e4_ReleaseStatus {
    E4_ALPHARELEASE = 0,
    E4_BETARELEASE = 1,
    E4_FINALRELEASE = 2,
    E4_PATCHRELEASE = 3
} e4_ReleaseStatus;

/*
 * Version numbers (updated each release):
 */

#define E4GRAPH_MAJOR		1
#define E4GRAPH_MINOR		0
#define E4GRAPH_RELEASESTATUS	E4_ALPHARELEASE
#define E4GRAPH_RELEASEITER	11

/*
 * These are the names of the built-in drivers:
 */

#define E4_METAKIT	"Metakit 2.4"

/*
 * Make export declarations work for WIN32.
 */

#ifndef e4_DLL
# if defined(_WIN32) && !defined(E4_STATIC)
#  ifdef E4_DLL
#   define e4_DLL      __declspec(dllexport)
#  else
#   define e4_DLL      __declspec(dllimport)
#  endif
# else
#  define e4_DLL
# endif
#endif

#ifndef e4_DLLSPEC
# ifdef _WIN32
#  define e4_DLLSPEC(t)   e4_DLL t
# else
#  define e4_DLLSPEC(t)   t e4_DLL
# endif
#endif

/***********************************************************************
 *
 * e4Graph public APIs proper:
 *
 ***********************************************************************
 */

/*
 * These config parameters are lifted from metakit-2.4.3/include/mk4.h.
 */

/*
 * Borland C++ and C++ Builder
 */

#if defined (__BORLANDC__)
	/*
         * Borland 5.0 supports the bool datatype
         */
    #if __BORLANDC__ >= 0x500
        #define e4_BOOL 1
    #endif
    #define E4_NO_CAST
#endif

/*
 * Metrowerks CodeWarrior
 */

#if defined (__MWERKS__)
    #if __option(bool)
        #define e4_BOOL 1
        #undef bool
        #undef true
        #undef false
    #endif
    #define E4_NO_CAST
#endif

/*
 *  Microsoft Visual C++
 */

#if defined (_MSC_VER)
	/*
         * MSVC 5.0 supports the bool datatype, MSVC 4.x has no namespaces
         */
    #if _MSC_VER >= 1100
        #define e4_BOOL 1
    #endif
    #include <malloc.h>
    #define E4_NO_CAST
#endif

/*
 * Symantec C++, Contributed by John Fletcher.
 */

#if defined(__SC__)
#ifdef _BOOL_DEFINED
#define e4_BOOL 1
#endif
#endif

/*
 * GNU C++ has a bool.
 */

#if defined (__GNUC__)
#define e4_BOOL 1
#endif

/*
 * If no bool definition is provided, define one.
 */

#if !e4_BOOL
    #define false 0
    #define true 1
    #define bool int
#endif

/*
 * Add casts for compilers that need them.
 */

#ifdef	E4_NO_CAST
#define	E4_CONST_VOID_STAR
#define E4_CONST_CHAR_STAR
#else
#define	E4_CONST_VOID_STAR	(const void *)
#define E4_CONST_CHAR_STAR	(const char *)
#endif

/*
 * Public #define values.
 */

#define E4_VERTEXNOTFOUND	-1	/* A vertex with the given name
					 * could not be found in this
					 * node. */

#define E4_VERTEXNOTCREATED	-1	/* Some kind of failure during
					 * vertex creation. */

#define E4_NODENOTCREATED	-1	/* Some kind of failure during
					 * node creation. */

#define E4_NODENOTFOUND		-2	/* A requested node could not
					 * be found. */

#define E4_RANKNOTUSED		-1	/* Constant to pass to operations
					 * that take a rank, to denote that
					 * the value is meaningless. */

#define E4_INVALIDUNIQUEID	-1	/* Constant that denotes an invalid
					 * unique ID. */

/*
 * These state bits control various behaviors of a storage at runtime.
 * They are not persistent. The various states are:
 *
 * E4_COMMITATCLOSE		If on, a commit is done before closing
 *				the storage. On by default.
 * E4_AUTOCOMMIT		If on, a commit is done periodically when
 *				changes exist in the storage. Not yet
 *				implemented. Off by default.
 * E4_OPENGC			If on, a garbage collection is performed
 *				when the storage is opened. On by default.
 * E4_GCBEFORECOMMIT		If on, a garbage collection is performed
 *				before every commit (both auto-commit and
 *				explicit commit). Off by default.
 * E4_AUTOGC			If on, a garbage collection is performed
 *				whenever an entity (node or vertex) becomes
 *				unreachable, to reclaim all unreachable
 *				space in the storage. If a large number of
 *				changes are applied to a storage, it is useful
 *				to delay garbage collection until all changes
 *				have been applied. Turning off this mode will
 *				achieve that effect. On by default.
 * E4_BIGPREALLOC		If on, space is pre-allocated in the storage
 *				in big increments. The default is to allocate
 *				storage in relatively smaller increments. This
 *				mode is intended for when a large number of
 *				entities will be created in a sequence of
 *				calls; this optimizes the amount of work
 *				that e4Graph has to do to make space for new
 *				entities as they are added to the storage.
 *				Off by default.
 * E4_COMPACTATCLOSE		If on, space is compacted when the storage
 *				is closed. This makes the storage as small
 *				as possible while preserving the logical
 *				structure of the data graph. Not yet
 *				implemented. Off by default.
 * E4_NOVERTEXCACHE		If on, this storage does not allow caching
 *				vertex IDs indexed by vertex names and rank.
 * E4_IMMEDIATEGC		If on, GC occurs immediately when an entity
 *				becomes unreachable. Off by default.
 */

#define E4_COMMITATCLOSE	(1<<0)
#define E4_AUTOCOMMIT		(1<<1)
#define E4_OPENGC		(1<<2)
#define E4_GCBEFORECOMMIT	(1<<3)
#define E4_AUTOGC		(1<<4)
#define E4_BIGPREALLOC		(1<<5)
#define E4_COMPACTATCLOSE	(1<<6)
#define E4_NOVERTEXCACHE	(1<<7)
#define E4_IMMEDIATEGC		(1<<8)

/*
 * These macros allow setting and unsetting of individual bits in the state
 * of a storage:
 */

#define SETSTATE(s, b) \
{ \
    int __oldstate__, __newstate__; \
\
    __oldstate__ = (s).GetState(); \
    __newstate__ = (__oldstate__ | (b)); \
   (void) (s).SetState(__newstate__); \
}
#define CLEARSTATE(s, b) \
{ \
    int __oldstate__, __newstate__; \
\
    __oldstate__ = (s).GetState(); \
    __newstate__ = (__oldstate__ & (~(b))); \
    (void) (s).SetState(__newstate__); \
}
#define HASSTATE(s, b)	(((s).GetState() & (b)) == (b))

/*
 * These states are on by default.
 */

#define E4_DEFAULTSTATE		(E4_COMMITATCLOSE | E4_OPENGC | E4_AUTOGC)

/*
 * These defined constants advise a node's cache management policy:
 */

#define E4_CACHEINCREMENTAL	0
#define E4_AUTOCACHENAMES	(1<<0)
#define E4_AUTOCACHERANKS	(1<<1)

/*
 * Get needed definitions from the operating system:
 */

#include <string.h>

/*
 * Get needed definitions from the standard C++ library.
 */

#include <stdlib.h>
#include <stdio.h>

/*
 * Forward declarations:
 */

class e4_DLL e4_RefCounter;
class e4_DLL e4_StorageImpl;
class e4_DLL e4_NodeImpl;
class e4_DLL e4_VertexImpl;

class e4_DLL e4_RefCount;
class e4_DLL e4_Storage;
class e4_DLL e4_Node;
class e4_DLL e4_Vertex;
class e4_DLL e4_StorageVisitor;
class e4_DLL e4_VertexVisitor;
class e4_DLL e4_NodeVisitor;
class e4_DLL e4_ParentVisitor;

class e4_DLL e4_Cache;

class e4_DLL e4_CommonUniqueID;
class e4_DLL e4_NodeUniqueID;
class e4_DLL e4_VertexUniqueID;

/*
 * Forward declaration of e4_Value.
 */

struct e4_Value;

/*
 * Enumerate the various kinds of reference counted entities:
 *
 * E4_RKINVALID		Illegal value.
 * E4_RKSTORAGE		This instance is a storage.
 * E4_RKNODE		This instance is a node.
 * E4_RKVERTEX		This instance is a vertex.
 */

typedef enum e4_RefKind {
    E4_RKINVALID =		-1,
    E4_RKSTORAGE =		0,
    E4_RKNODE =			2,
    E4_RKVERTEX =		3
} e4_RefKind;

/*
 * The various storage permissions:
 *
 * E4_SPMODIFY		Allows read-write access to data contained
 *			in the storage.
 * E4_SPCOMMIT		Allows commits on this storage to make modifications
 *			persistent.
 * E4_SPINITIALIZE	Allows creation of the necessary data structures in
 *			a new storage.
 * E4_SPUPDATEFORMAT	Allows update of an out of date storage format in
 *			existing storages.
 * E4_SPCOPYTO		Allows copying from other storages to this one.
 * E4_SPCOPYFROM	Allows copying from this storage to others.
 */

#define	E4_SPMODIFY		(1<<0)
#define E4_SPCOPYTO		(1<<1)
#define E4_SPCOPYFROM		(1<<2)
#define E4_SPCOMMIT		(1<<3)
#define E4_SPINITIALIZE		(1<<4)
#define E4_SPUPDATEFORMAT	(1<<5)

/*
 * This mask defines the permission bits set by default.
 */

#define E4_SPDEFAULTMASK \
	(E4_SPMODIFY | E4_SPCOPYTO | E4_SPCOPYFROM | E4_SPCOMMIT | \
	 E4_SPINITIALIZE | E4_SPUPDATEFORMAT)

/*
 * Enumerate the various vertex types:
 *
 * E4_VTUNKNOWN		Illegal value.
 * E4_VTNODE		This vertex contains a node.
 * E4_VTINT		This vertex contains a 32-bit integer.
 * E4_VTDOUBLE		This vertex contains a 64-bit floating point number.
 * E4_VTSTRING		This vertex contains a NULL-terminated string.
 * E4_VTBINARY		This vertex contains a binary unstructured value.
 */

typedef enum e4_VertexType {
    E4_VTUNKNOWN =		-1,
    E4_VTNODE =			0,
    E4_VTINT =			1,
    E4_VTDOUBLE =		2,
    E4_VTSTRING =		3,
    E4_VTBINARY =		4,
    E4_VTLASTVERTEXTYPE =	5
} e4_VertexType;

/*
 * The following enumeration describes how vertices are moved from
 * another node into this node. The argument determines how the
 * vertex is inserted into this node:
 *
 * E4_IONONE		Illegal value.
 * E4_IOAT		Insert at numeric position (zero based).
 * E4_IOFIRST		Insert as zeroth vertex.
 * E4_IOLAST		Insert as last vertex.
 * E4_IOBEFORE		Insert before another named vertex.
 * E4_IOAFTER		Insert after another named vertex.
 */

typedef enum e4_InsertOrder {
    E4_IONONE =			0,
    E4_IOAT =			1,
    E4_IOFIRST =		2,
    E4_IOLAST =			3,
    E4_IOBEFORE =		4,
    E4_IOAFTER =		5,
    E4_IOLASTINSERTORDER =	6
} e4_InsertOrder;

/*
 * The following enumeration describes the different methods of
 * operation for an e4_Visitor instance:
 *
 * E4_VMUNKNOWN		Illegal value.
 * E4_VMSTORAGE		Visit every vertex in a storage in some random order.
 * E4_VMNODE		Visit every vertex in a node in rank order.
 * E4_VMNODERANDOM	Visit every vertex in a node in some random order.
 * E4_VMPARENT		Visit vertices having a given node as their value
 *			(i.e. vertices pointing at this node).
 */

typedef enum e4_VisitMethod {
    E4_VMUNKNOWN =		0,
    E4_VMSTORAGE =		1,
    E4_VMNODE =			2,
    E4_VMNODERANDOM =		3,
    E4_VMPARENT =		4,
    E4_VMLASTMETHOD =		5
} e4_VisitMethod;

/*
 * The following enumeration describes the different choices whether to
 * visit detached entities, attached entities or both.
 */

typedef enum e4_DetachChoice {
    E4_DCDETACHED =		0,
    E4_DCATTACHED =		1,
    E4_DCBOTH     =		2
} e4_DetachChoice;

/*
 * The following bit fields define different filters to apply to exclude
 * vertices from being visited. These bit fields can be ORed together to
 * yield more complex filters.
 */

#define E4_VFNONE	0		/* Always visit.		*/
#define	E4_VFNAME	(1 << 0)	/* Visit only if name equals.	*/
#define E4_VFTYPE	(1 << 1)	/* Visit only if type equals.	*/

/*
 * This structure is used to pass a value to/from an untyped vertex
 * access function.
 */

typedef struct e4_Binary {
    int nbytes;			/* How big is the value? */
    void *bytes;		/* The value itself. */
} e4_Binary;

/*
 * A way to transmit arbitrary values:
 */

typedef struct e4_ValueImpl {
    e4_VertexType vertexType;	/* Type of the value being passed. */
    union {
        e4_NodeImpl *n;
	int i;
        double d;
        char *s;
        e4_Binary b;
    } u;
} e4_ValueImpl;

/*
 * The following enum describes the various elements of a storage, used
 * to retrieve statistics for each element usage.
 */

typedef enum e4_Space {
    E4_SPNODE = 0,
    E4_SPVERTEX = 1,
    E4_SPNAME = 2,
    E4_SPSTRING = 3,
    E4_SPINT = 4,
    E4_SPDOUBLE = 5,
    E4_SPBINARY = 6,
    E4_SPLAST = 7
} e4_Space;

/*
 * The following enum describes the different statistics collected for
 * each space. Some storage drivers may not collect all these statistics.
 */

typedef enum e4_SpaceStat {
    E4_SSUSED = 0,
    E4_SSAVAIL = 1,
    E4_SSFREED = 2,
    E4_SSALLOC = 3,
    E4_SSLAST = 4
} e4_SpaceStat;

/*
 * These constants define the kinds of predefined callbacks supported by
 * e4Graph. Other callbacks (upto value 31) can be defined by user programs.
 */

#define	E4_ECADDNODE	(1<<0)	/* A node was added to the storage. */
#define E4_ECDETNODE	(1<<1)	/* A node became detached. */
#define E4_ECATTNODE	(1<<2)	/* A node became attached. */
#define E4_ECMODNODE	(1<<3)	/* A node was modified. */
#define E4_ECADDVERTEX	(1<<4)	/* A vertex was added to the storage. */
#define	E4_ECDETVERTEX	(1<<5)	/* A vertex became detached. */
#define	E4_ECATTVERTEX	(1<<6)	/* A vertex became attached. */
#define E4_ECMODVERTEX	(1<<7)	/* A vertex was modified. */
#define	E4_ECCHANGESTG	(1<<8)	/* Storage stable status changed. */
#define E4_ECOPENSTG	(1<<9)	/* Storage was opened. */
#define E4_ECCOPYTOSTG	(1<<10)	/* Storage was copied into. */
#define E4_ECCOPYFRMSTG	(1<<11)	/* Storage was copied from. */
#define E4_ECSETSTGROOT (1<<12)	/* The storage's root node was set to some
				 * other node. */
#define E4_ECCOMMITSTG	(1<<13) /* The storage was committed. */

/*
 * This bitmask defines the events that change a storage.
 */

#define E4_ECMODSTORAGE \
    (E4_ECADDNODE | E4_ECDETNODE | E4_ECATTNODE | E4_ECMODNODE | \
     E4_ECADDVERTEX | E4_ECDETVERTEX | E4_ECATTVERTEX | E4_ECMODVERTEX | \
     E4_ECCOPYTOSTG | E4_ECSETSTGROOT)

/*
 * These constants define the range of possible values for user defined
 * event codes:
 */

#define E4_FIRSTUSERDEFINEDEVENTCODE	14
#define	E4_LASTUSERDEFINEDEVENTCODE	31

/*
 * The e4_RefCount class:
 */

class e4_DLL e4_RefCount {
protected:

    /*
     * The "impl" field contains the reference to the actual referenced
     * implementation instance.
     */

    e4_RefCounter *impl;

public:
    /*
     * Default constructor:
     */

    e4_RefCount();

    /*
     * Copying constructor:
     */

    e4_RefCount(const e4_RefCount &referrer);

    /*
     * Assignment operator:
     */

    e4_RefCount & operator=(const e4_RefCount &referrer);

    /*
     * Constructor with value assignd to implementation.
     */

    e4_RefCount(e4_RefCounter *ip);

    /*
     * Destructor:
     */

    virtual ~e4_RefCount();

    /*
     * Returns the current refcount if the impl field is valid, or
     * -1 if not.
     */

    int RefCount() const;

    /*
     * Is this instance valid?
     */

    bool IsValid() const;

    /*
     * Return an identifier for programmatic type identification for
     * this instance.
     */

    virtual e4_RefKind Kind() const;

    /*
     * Comparison operators.
     */

    bool operator==(const e4_RefCount &compared) const;
    bool operator!=(const e4_RefCount &compared) const;

    /*
     * This operation returns an integer that is guaranteed to be unique
     * while "impl" is valid. It may be different each time the underlying
     * "impl" is instantiated.
     */

    inline long GetTemporaryUID() {
	return (long) impl;
    }

    /*
     * These operations manipulate user-level data attached to each instance.
     */

    void SetTransientUserData(void *data) const;
    void *GetTransientUserData() const;
};

/*
 * This section dealing with callbacks MUST appear after the definition
 * of e4_RefCount and before the definition of e4_Storage, because it uses
 * e4_RefCount and is used by e4_Storage.
 */

/*
 * This enumeration defines the reasons for an E4_ECMODNODE event:
 */

typedef enum e4_ModNodeEventReason {
    E4_ERMNADDVERTEX = 0,		/* A vertex was added to a node. */
    E4_ERMNDETVERTEX = 1,		/* A vertex was detached frm a node. */
    E4_ERMNRENVERTEX = 2,		/* A vertex was renamed in a node. */
    E4_ERMNMOVVERTEX = 3,		/* A vertex was moved in this node. */
    E4_ERMNINSVERTEX = 4,		/* A vertex was moved into
					 * this node. */
    E4_ERMNMODUSERDATA = 5		/* The user data for the node was
					 * modified.			    */
} e4_ModNodeEventReason;

/*
 * This enumeration defines the reasons for an E4_CBMODVERTEX event:
 */

typedef enum e4_ModVertexEventReason {
    E4_ERMVMODVALUE = 0,		/* The value was modified.  */
    E4_ERMVRENAME = 1,			/* The vertex was renamed.  */
    E4_ERMVREPARENT = 2,		/* The vertex was moved.    */
    E4_ERMVDETVERTEX = 3,		/* The vertex was detached. */
    E4_ERMVMODUSERDATA = 4		/* The vertex user data was
					 * modified.		    */
} e4_ModVertexEventReason;

/*
 * Callback function typedef.
 */

typedef void (*e4_CallbackFunction)(void *clientData,
				    const e4_RefCount &r,
				    void *csdata);

/*
 * The e4_Storage class:
 */

class e4_DLL e4_Storage : public e4_RefCount {
public:

    /*
     * Static function to return version string for e4Graph.
     */

    static const char *version();

    /*
     * Numeric version numbers:
     */

    static int major_version();
    static int minor_version();
    static e4_ReleaseStatus release_status(); 
    static int release_iteration();

    /*
     * Static function to return a version string for a specific storage.
     */

    static const char *storage_version(const char *fname,
				       const char *drivername);

    /*
     * Retrieve numeric version numbers for a storage.
     */

    static bool storage_version_info(const char *fname,
				     const char *drivername,
				     int &majvp,
				     int &minvp,
				     e4_ReleaseStatus &rsp,
				     int &rip);
    
    /*
     * Default constructor:
     */

    e4_Storage();

    /*
     * Copying constructor:
     */

    e4_Storage(const e4_Storage &referrer);

    /*
     * Copying constructor thats given an e4_RefCount.
     */

    e4_Storage(const e4_RefCount &referrer);

    /*
     * Assignment operator:
     */

    e4_Storage & operator=(const e4_Storage &referrer);

    /*
     * No destructor is defined so the e4_RefCount destructor will be used.
     */

    /*
     * Constructor that chooses a concrete representation for the
     * underlying implementation.
     */

    e4_Storage(const char *name, const char *drivername);

    /*
     * Constructor that lets the user set state for the new storage
     * at construction time.
     */

    e4_Storage(const char *name, const char *drivername, int state);

    /*
     * Constructor that lets the user set state and permissions.
     */

    e4_Storage(const char *name,
	       const char *drivername,
	       int state,
	       int perms);

    /*
     * State bits manipulation.
     */

    int SetState(int statemask) const;
    int GetState() const;

    /*
     * Retrieve the storage permissions. The permissions can only
     * be set at construction time.
     */

    int GetPermissions() const;

    /*
     * Commit now.
     */

    bool Commit() const;

    /*
     * Copy the content (e4Graph related only) of this storage to another
     * storage.
     */

    bool CopyTo(e4_Storage otherStorage, bool forceCommit) const;

    /*
     * Delete the underlying physical storage.
     */

    bool Delete();

    /*
     * Get and set the root node.
     */

    bool GetRootNode(e4_Node &n) const;
    bool SetRootNode(e4_Node n) const;

    /*
     * Given a unique ID, obtain the node or vertex denoted
     * by that ID.
     */

    bool GetNodeFromID(e4_NodeUniqueID nid, e4_Node &n) const;
    bool GetVertexFromID(e4_VertexUniqueID id, e4_Vertex &v) const;

    /*
     * Is this storage stable?
     */

    bool IsStable() const;

    /*
     * Mark the storage as unstable (it needs to be committed).
     */

    void MarkUnstable() const;

    /*
     * Get the name and driver ID for this storage.
     */

    const char *GetName() const;
    const char *GetDriver() const;

    /*
     * Create detached entities within this storage:
     */

    bool CreateDetachedNode(e4_Node &n) const;
    bool CreateDetachedVertex(const char *nm, e4_Node n, e4_Vertex &v) const;
    bool CreateDetachedVertex(const char *nm, int i, e4_Vertex &v) const;
    bool CreateDetachedVertex(const char *nm, double d, e4_Vertex &v) const;
    bool CreateDetachedVertex(const char *nm, const char *s,
			      e4_Vertex &v) const;
    bool CreateDetachedVertex(const char *nm, const void *b, int nb,
			      e4_Vertex &v) const;
    bool CreateDetachedVertex(const char *nm, const e4_Value &vv, e4_Vertex &v)
	const;

    /*
     * Get a value for a statistic being collected for this storage.
     */

    bool GetStatistic(e4_Space sp, e4_SpaceStat st, int &v) const;

    /*
     * Do a GC.
     */

    void DoGC() const;

    /*
     * Is a GC needed?
     */

    bool NeedsGC() const;

    /*
     * Event management: add or delete callbacks, cause events.
     *
     * User applications cannot cause events for event codes that are
     * predefined by e4Graph. Only e4Graph itself can cause these events.
     * Attempting to do so will cause CauseEvent to return false. User
     * applications should use CauseEvent to cause events only for user
     * defined event codes.
     */

    bool DeclareCallback(int eventCode,
			 e4_CallbackFunction fn,
			 void *clientData);
    bool DeleteCallback(int eventCode,
			e4_CallbackFunction fn,
			void *clientData);
    bool CauseEvent(int eventCode, const e4_RefCount &r, void *csdata);
    bool CauseEvent(int eventCode,
		    const e4_RefCount &r,
		    void *csdata,
		    int &timestamp);

    /*
     * Timestamp mechanism: timestamps are monotonously increasing non-negative
     * integers denoting the "time" at which specific events occur. All
     * predefined events and user defined events are captured by the internals
     * of e4Graph. This mechanism records and retrieves the timestamps for the
     * occurrence of these events.
     */

    int GetTimeStamp() const;
    int GetTimeStampFor(int eventmask) const;
    bool HasOccurredSince(int timestamp, int eventmask) const;

    /*
     * Facility for defining new kinds of event codes. These event codes
     * are defined for *all* storages; there is no facility for defining
     * storage-specific event codes.
     *
     * Applications should not rely on the specific value returned in
     * eventcode by DefineEventCode. This value may change from one
     * invocation to the next. It is only intended to be used as an
     * identifier for calls to DeclareCallback, DeleteCallback and
     * CauseEvent, above.
     *
     * Applications cannot undefine event codes that are predefined by e4Graph.
     * Trying to do so will cause UndefineEventCode to return false.
     */

    static bool DefineEventCode(int &eventcode);
    static bool UndefineEventCode(int eventcode);
    static bool IsEventCodeDefined(int eventcode);

    /*
     * Get the kind identifier for an instance of this type:
     */

    virtual e4_RefKind Kind() const;

protected:

    /*
     * These methods are for use by classes e4_Node, e4_Vertex,
     * e4_StorageVisitor, e4_VertexVisitor, e4_NodeVisitor,
     * and e4_ParentVisitor only.
     */

    friend class e4_Node;
    friend class e4_Vertex;
    friend class e4_StorageVisitor;
    friend class e4_VertexVisitor;
    friend class e4_NodeVisitor;
    friend class e4_ParentVisitor;

    friend class e4_StorageImpl;

    /*
     * Constructor which assigns a value to the implementation field:
     */

    e4_Storage(e4_StorageImpl *ip);

    /*
     * Get the next storage after this one in an implementation dependent
     * order that visits all currently open storages.
     */

    bool FindNextStorage(e4_Storage &ss) const;

    /*
     * Get the next vertex after a vertex identified by a unique ID,
     * using a search method specified by "vm" and "vf". These are
     * defined in e4common.h.
     */

    bool FindNextVertex(int vertexID,
			e4_VisitMethod vm,
			int vf,
			int nameId,
			int nodeID,
			int parentID,
			e4_VertexType typeID,
			e4_DetachChoice dc,
			e4_Vertex &f) const;

    /*
     * Find the next node after a node identified by a unique ID.
     */

    bool FindNextNode(int nodeID, e4_DetachChoice dc, e4_Node &n) const;

    /*
     * Intern a name.
     */

    int InternName(const char *nm) const;

    /*
     * Get a node given its node ID:
     */

    e4_NodeImpl *GetNode(int nodeID) const;

    /*
     * Get the name of a vertex given the name ID.
     */

    const char *GetName(int nameID) const;

    /*
     * Get the storage implementation from this storage:
     */

    e4_StorageImpl *GetStorageImpl() const;
};

/*
 * The e4_Node class:
 */

class e4_DLL e4_Node : public e4_RefCount {
public:

    /*
     * Default constructor:
     */

    e4_Node();

    /*
     * Copying constructor:
     */

    e4_Node(const e4_Node &referrer);

    /*
     * Copying constructor that's given an e4_RefCount:
     */

    e4_Node(const e4_RefCount &referrer);

    /*
     * Assignment operator:
     */

    e4_Node & operator=(const e4_Node &referrer);

    /*
     * No destructor is defined so the e4_RefCount destructor will be used.
     */

    /*
     * How many vertices are there in this node?
     */

    int VertexCount() const;

    /*
     * How many vertices in this node have the given name, type or value?
     */

    int VertexCountWithName(const char *name) const;
    int VertexCountWithType(e4_VertexType typeID) const;
    int VertexCountWithValue(const e4_Value &v) const;

    /*
     * Operations to set data into existing vertices in this node.
     */

    bool SetNthVertex(const char *nm, int nth, int i) const;
    bool SetNthVertex(const char *nm, int nth, double f) const;
    bool SetNthVertex(const char *nm, int nth, const char *s) const;
    bool SetNthVertex(const char *nm, int nth, const void *b, int nb) const;
    bool SetNthVertex(const char *nm, int nth, e4_Node n) const;
    bool SetNthVertex(const char *nm, int nth, const e4_Value &v) const;
    bool SetNthNode(const char *nm, int nth, e4_Node &n) const;

    inline bool SetVertex(const char *nm, int i) const {
        return SetNthVertex(nm, 1, i);
    }
    inline bool SetVertex(const char *nm, double f) const {
        return SetNthVertex(nm, 1, f);
    }
    inline bool SetVertex(const char *nm, const char *s) const {
        return SetNthVertex(nm, 1, s);
    }
    inline bool SetVertex(const char *nm, const void *b, int nb) const {
        return SetNthVertex(nm, 1, b, nb);
    }
    inline bool SetVertex(const char *nm, e4_Node n) const {
	return SetNthVertex(nm, 1, n);
    }
    inline bool SetVertex(const char *nm, const e4_Value &v) const {
	return SetNthVertex(nm, 1, v);
    }
    inline bool SetNode(const char *nm, e4_Node &n) const {
        return SetNthNode(nm, 1, n);
    }

    /*
     * Set the value of an existing vertex in this node identified by rank.
     */

    bool SetVertexByRank(int rank, int i) const;
    bool SetVertexByRank(int rank, double f) const;
    bool SetVertexByRank(int rank, const char *s) const;
    bool SetVertexByRank(int rank, const void *b, int nb) const;
    bool SetVertexByRank(int rank, e4_Node n) const;
    bool SetVertexByRank(int rank, const e4_Value &v) const;
    bool SetNodeByRank(int rank, e4_Node &n) const;

    /*
     * Add a new vertex to this node according to the rank and order arguments.
     * The rank argument is in-out; on the way in, in combination with the
     * order argument, it determines where in the node the new vertex is
     * created. On the way out, it returns the rank of the newly created
     * vertex. Upon success, these operations return true. If an error occurred
     * these operations return false.
     */

    bool AddVertex(const char *nm, e4_InsertOrder order, int &rank,
		   int value) const;
    bool AddVertex(const char *nm, e4_InsertOrder order, int &rank,
		   double f) const;
    bool AddVertex(const char *nm, e4_InsertOrder order, int &rank,
		   const char *s) const;
    bool AddVertex(const char *nm, e4_InsertOrder order, int &rank,
		   const void *b, int nb) const;
    bool AddVertex(const char *nm, e4_InsertOrder order, int &rank,
		   e4_Node n) const;
    bool AddVertex(const char *nm, e4_InsertOrder order, int &rank,
		   const e4_Value &v) const;
    bool AddNode(const char *nm, e4_InsertOrder order, int &rank, 
		 e4_Node &n) const;

    /*
     * Add a new vertex and also return an e4_Vertex for the new vertex.
     * This is much more efficient than AddVertex followed by GetVertexRef.
     */

    bool AddVertexRef(const char *nm, e4_InsertOrder order, int &rank,
                     int ii, e4_Vertex &f) const;
    bool AddVertexRef(const char *nm, e4_InsertOrder order, int &rank,
                     double ff, e4_Vertex &f) const;
    bool AddVertexRef(const char *nm, e4_InsertOrder order, int &rank,
                     const char *ss, e4_Vertex &f) const;
    bool AddVertexRef(const char *nm, e4_InsertOrder order, int &rank,
                     const void *b, int nb, e4_Vertex &f) const;
    bool AddVertexRef(const char *nm, e4_InsertOrder order, int &rank,
		      e4_Node n, e4_Vertex &f) const;
    bool AddVertexRef(const char *nm, e4_InsertOrder order, int &rank,
		      const e4_Value &v, e4_Vertex &f) const;
    bool AddNodeRef(const char *nm, e4_InsertOrder order, int &rank,
                    e4_Node &n, e4_Vertex &f) const;

    /*
     * Move a given vertex to a specified position within this node.
     */

    bool MoveVertex(const e4_Vertex &f, e4_InsertOrder order, int rank);

    /*
     * Get a value out of a vertex. If the vertex is found then the output
     * parameter is set, otherwise it is not modified.
     *
     * The char * and void * returned are valid only until the next call to
     * any e4Graph API. If the caller needs to keep access to the value,
     * copy the value into memory owned by the caller.
     */
    
    bool GetNthVertex(const char *nm, int nth, e4_Value &v) const;
    bool GetNthVertex(const char *nm, int nth, e4_Node &n) const;
    bool GetNthVertex(const char *nm, int nth, int &v) const;
    bool GetNthVertex(const char *nm, int nth, double &v) const;
    bool GetNthVertex(const char *nm, int nth, const char *&v) const;
    bool GetNthVertex(const char *nm, int nth, const void *&v, int &nbv) const;

    inline bool GetVertex(const char *nm, e4_Value &v) const {
        return GetNthVertex(nm, 1, v);
    }
    inline bool GetVertex(const char *nm, e4_Node &v) const {
        return GetNthVertex(nm, 1, v);
    }
    inline bool GetVertex(const char *nm, int &v) const {
        return GetNthVertex(nm, 1, v);
    }
    inline bool GetVertex(const char *nm, double &v) const {
        return GetNthVertex(nm, 1, v);
    }
    inline bool GetVertex(const char *nm, const char *&s) const {
        return GetNthVertex(nm, 1, s);
    }
    inline bool GetVertex(const char *nm, const void *&v, int &nbv) const {
        return GetNthVertex(nm, 1, v, nbv);
    }

    /*
     * Get the value of a vertex identified by rank, in this node.
     */

    bool GetVertexByRank(int rank, e4_Value &v) const;
    bool GetVertexByRank(int rank, e4_Node &n) const;
    bool GetVertexByRank(int rank, int &v) const;
    bool GetVertexByRank(int rank, double &v) const;
    bool GetVertexByRank(int rank, const char *&s) const;
    bool GetVertexByRank(int rank, const void *&v, int &nbv) const;

    /*
     * Detach a vertex.
     */

    bool DetachVertex(const char *nm, int nth) const;
    inline bool DetachVertex(const char *nm) const {
	return DetachVertex(nm, 1);
    }
    bool DetachVertexByRank(int rank) const;

    /*
     * Detach the first vertex whose value is a given child node.
     */

    bool DetachFirstVertexWithNode(e4_Node child) const;

    /*
     * Get an e4_Vertex for a vertex identified by name or rank.
     */

    bool GetVertexRef(const char *nm, int nth, e4_Vertex &f) const;
    inline bool GetVertexRef(const char *nm, e4_Vertex &f) const {
        return GetVertexRef(nm, 1, f);
    }
    bool GetVertexRefByRank(int rank, e4_Vertex &f) const;

    /*
     * Get the type of the value stored in a specific vertex.
     */

    e4_VertexType VertexType(const char *nm, int nth) const;
    inline e4_VertexType VertexType(const char *nm) const {
        return VertexType(nm, 1);
    }
    e4_VertexType VertexTypeByRank(int rank) const;

    /*
     * Get the name of a vertex.
     */

    const char *VertexName(int rank) const;

    /*
     * Rename a vertex.
     */

    bool RenameVertex(int rank, const char *newName) const;

    /*
     * Get the rank of a vertex.
     */

    int VertexRank(const char *nm, int nth) const;
    inline int VertexRank(const char *nm) const{
        return VertexRank(nm, 1);
    }

    /*
     * Does a named vertex exist?
     */

    bool Exists(const char *nm, int nth) const;
    inline bool Exists(const char *nm) const{
        return Exists(nm, 1);
    }

    /*
     * Get a parent node of a node.
     */

    bool GetParent(int nth, e4_Node &p) const;
    inline bool GetParent(e4_Node &p) const {
	return GetParent(1, p);
    }

    /*
     * Retrieve the nth vertex in the given parent node p whose value
     * is this node.
     */

    bool GetVertexRefFromParent(e4_Node p, int nth, e4_Vertex &v) const;

    /*
     * Retrieve the nth vertex in the ith parent whose value is this node.
     */

    bool GetVertexRefFromParent(int i, int nth, e4_Vertex &v) const;

    /*
     * How many parents does this node have?
     */

    int ParentCount() const;

    /*
     * How many vertices contain this node as the value?
     */

    int OccurrenceCount() const;

    /*
     * How many times does this node occur as a child in the given node?
     */

    int OccurrenceCount(e4_Node p) const;

    /*
     * What is the rank of this parent for this node?
     */

    int ParentRank(e4_Node p) const;

    /*
     * A node is the root if it would be the node returned by
     * s.GetRootNode() on its storage.
     */

    bool IsRoot() const;

    /*
     * Get the root node of the storage containing this node.
     */

    bool GetRootNode(e4_Node &rn) const;
    
    /*
     * Get the rank of the ith vertex containing this node in its nth parent 
     * and the name of the ith vertex containing this node in its nth parent.
     * There are also versions that take the e4_Node for the parent instead
     * of its parent rank.
     */

    int GetRankInParent(e4_Node p, int ith) const;
    int GetRankInParent(int nth, int ith) const;
    inline int GetRankInParent(int nth) const {
	return GetRankInParent(nth, 1);
    }
    inline int GetRankInParent() const {
	return GetRankInParent(1);
    }

    const char *GetNameInParent(e4_Node p, int ith) const;
    const char *GetNameInParent(int nth, int ith) const;
    inline const char *GetNameInParent(int nth) const {
	return GetNameInParent(nth, 1);
    }
    inline const char *GetNameInParent() const {
	return GetNameInParent(1);
    }

    /*
     * Get the storage containing this node.
     */

    bool GetStorage(e4_Storage &s) const;

    /*
     * Get a unique ID (unique within the storage containing this node) for
     * the node.
     */

    bool GetUniqueID(e4_NodeUniqueID &n) const;
    
    /*
     * Detach this node by detaching all vertices for which this node is
     * the value.
     */

    bool Detach() const;

    /*
     * Is this node detached?
     */

    bool IsDetached() const;

    /*
     * Return the kind identifier for an instance of this type:
     */

    virtual e4_RefKind Kind() const;

    /*
     * Get/Set user data associated with this node.
     */

    bool GetUserData(int &userData) const;
    bool SetUserData(int userData) const;

    /*
     * Get/Set user data for a contained vertex.
     */

    bool GetVertexUserData(const char *name, int &userData) const;
    bool GetVertexUserData(const char *name, int nth, int &userData) const;
    bool SetVertexUserData(const char *name, int userData) const;
    bool SetVertexUserData(const char *name, int nth, int userData) const;

    bool GetVertexUserDataByRank(int rank, int &userData) const;
    bool SetVertexUserDataByRank(int rank, int userData) const;

    /*
     * Get/Set advisory cache management policy flags:
     */

    int SetAdvisoryCachingPolicy(bool set, int mask) const;
    int GetAdvisoryCachingPolicy() const;

    /*
     * Pre-cache the vertex IDs for all vertices in this node.
     */

    void PreCache() const;

protected:

    /*
     * These operations are for use by class e4_Storage, e4_Vertex,, e4_Cache,
     * e4_VertexVisitor, e4_StorageVisitor, e4_NodeVisitor,
     * and e4_ParentVisitor only:
     */

    friend class e4_Storage;
    friend class e4_Vertex;
    friend class e4_StorageVisitor;
    friend class e4_VertexVisitor;
    friend class e4_NodeVisitor;
    friend class e4_ParentVisitor;

    friend class e4_StorageImpl;

    /*
     * Constructor which assigns a value to the implementation field:
     */

    e4_Node(e4_NodeImpl *ip);

    /*
     * Get the unique ID for this node in a raw (unwrapped) form.
     */

    int GetRawUniqueID() const;
};

/*
 * The e4_Vertex class:
 */

class e4_DLL e4_Vertex : public e4_RefCount {
public:
    /*
     * Default constructor:
     */

    e4_Vertex();

    /*
     * Copying constructor:
     */

    e4_Vertex(const e4_Vertex &referrer);

    /*
     * Copying constructor that's given an e4_RefCount:
     */

    e4_Vertex(const e4_RefCount &referrer);

    /*
     * Assignment operator:
     */

    e4_Vertex & operator=(const e4_Vertex &referrer);

    /*
     * No destructor is defined so the e4_RefCount destructor will be used.
     */

    /*
     * Get the value stored in this vertex.
     */

    bool Get(e4_Value &v) const;
    bool Get(e4_Node &n) const;
    bool Get(int &v) const;
    bool Get(double &v) const;
    bool Get(const char *&s) const;
    bool Get(const void *&b, int &nb) const;

    /*
     * Set the content of this vertex (and its type) to the value supplied.
     */

    bool Set(int v) const;
    bool Set(double v) const;
    bool Set(const char *v) const;
    bool Set(const void *b, int nb) const;
    bool Set(e4_Node n) const;
    bool Set(const e4_Value &v) const;

    /*
     * Set the content of this vertex to a new node and return the new node.
     */

    bool SetNode(e4_Node &n) const;

    /*
     * Get the rank of this vertex in the node in which it appears.
     */

    int Rank() const;

    /*
     * Get the count of how many vertices up to this one in the containing
     * node have the same name. If this vertex is detached, return -1.
     */

    int CountWithName() const;

    /*
     * Get the total count of how many vertices in the node containing
     * this one have the same name. If this vertex is detached, return -1.
     */

    int TotalCountWithName() const;

    /*
     * Get the count of how many vertices up to this one in the containing
     * node have the same type. If this vertex is detached, return -1.
     */

    int CountWithType() const;

    /*
     * Get the total count of how many vertices in the node containing
     * this one have the same type. If this vertex is detached, return -1.
     */

    int TotalCountWithType() const;

    /*
     * Detach this vertex from its containing node.
     */

    bool Detach() const;

    /*
     * Is this vertex detached?
     */

    bool IsDetached() const;

    /*
     * Return the type of the vertex.
     */

    e4_VertexType Type() const;

    /*
     * Return the name of the vertex.
     */

    const char *Name() const;

    /*
     * Rename this vertex.
     */

    bool Rename(const char *newname) const;

    /*
     * Get a unique (within the storage containing it) ID for this vertex.
     */

    bool GetUniqueID(e4_VertexUniqueID &v) const;

    /*
     * Get the root node of the storage containing this vertex.
     */

    bool GetRootNode(e4_Node &rn) const;

    /*
     * Get the storage in which this vertex appears.
     */

    bool GetStorage(e4_Storage &ss) const;

    /*
     * Get the node in which this vertex appears.
     */

    bool GetNode(e4_Node &nn) const;

    /*
     * Move the given vertex into the node containing this vertex at
     * the indicated insertOrder and offset. If insertOrder is either
     * E4_IOBEFORE, offset is subtracted from the rank of this vertex
     * plus one to get the rank at which the given vertex is inserted.
     * If insertOrder is E4_IOAFTER, offset is added to the rank of
     * this vertex to get the rank at which the given vertex is inserted.
     * In these cases, offset must be equal or greater than one.
     * Otherwise offset is ignored.
     */

    bool MoveVertex(const e4_Vertex &ff, e4_InsertOrder order, int offset)
	const;

    /*
     * Retrieve the next vertex after this one in the node
     * containing this vertex.
     */

    bool Next(int num, e4_Vertex &ff) const;

    /*
     * Retrieve the previous vertex before this one in the node
     * containing this vertex.
     */

    bool Prev(int num, e4_Vertex &ff) const;

    /*
     * Return the kind identifier for an instance of this type:
     */

    virtual e4_RefKind Kind() const;

    /*
     * Get/Set user data associated with this vertex.
     */

    bool GetUserData(int &userData) const;
    bool SetUserData(int userData) const;

protected:

    /*
     * These operations are for use by class e4_Node, e4_Storage, e4_Cache,
     * e4_VertexVisitor, e4_StorageVisitor, e4_NodeVisitor ,
     * and e4_ParentVisitor only only:
     */

    friend class e4_Node;
    friend class e4_Storage;
    friend class e4_StorageVisitor;
    friend class e4_VertexVisitor;
    friend class e4_NodeVisitor;
    friend class e4_ParentVisitor;

    friend class e4_StorageImpl;
    
    /*
     * Constructor which assigns a value to the implementation field:
     */

    e4_Vertex(e4_VertexImpl *ip);

    /*
     * Get the unique ID for this vertex in a raw (unwrapped) form.
     */

    int GetRawUniqueID() const;
};

/*
 * Class e4_StorageVisitor
 */

class e4_DLL e4_StorageVisitor {
private:

    /*
     * The storage being visited now.
     */

    e4_Storage s;

    /*
     * Is this visitor done visiting all the storages?
     */

    bool done;

public:

    /*
     * Default constructor:
     */

    e4_StorageVisitor();

    /*
     * Copying constructor:
     */

    e4_StorageVisitor(const e4_StorageVisitor &referrer);

    /*
     * Assignment operator:
     */

    e4_StorageVisitor & operator=(const e4_StorageVisitor &referrer);

    /*
     * Comparison operators:
     */

    bool operator==(const e4_StorageVisitor &compared) const;
    bool operator!=(const e4_StorageVisitor &compared) const;

    /*
     * Destructor:
     */

    virtual ~e4_StorageVisitor();

    /*
     * Is this visitor done visiting all the storages?
     */

    bool IsDone();

    /*
     * Get the current storage being visited:
     */

    bool CurrentStorage(e4_Storage &ss);

    /*
     * Get the current storage being visited and advance the
     * visitor to the next storage.
     */

    bool CurrentStorageAndAdvance(e4_Storage &ss);

    /*
     * Get the next storage:
     */

    bool NextStorage(e4_Storage &ss);

    /*
     * Advance to the next storage but do not retrieve it:
     */

    bool Advance();

    /*
     * Is this instance valid?
     */

    bool IsValid();
};

/*
 * Class e4_VertexVisitor:
 */

class e4_DLL e4_VertexVisitor {
private:

    /*
     * The storage used by this visitor.
     */

    e4_Storage s;

    /*
     * The last vertex returned by the visitor.
     */

    e4_Vertex f;

    /*
     * Is this visitor done visiting all vertices in its itinerary?
     */

    bool done;

    /*
     * Is this visitor visiting detached vertices, attached vertices, or both?
     */

    e4_DetachChoice detachchoice;

    /*
     * The ID of the node whose vertices we will visit.
     */

    int nodeID;

    /*
     * The ID of the parent node whose vertices we will visit.
     */

    int parentID;

    /*
     * Only vertices with this nameID will be visited.
     */

    int nameID;

    /*
     * Only vertices with this type will be visited.
     */

    e4_VertexType typeID;

    /*
     * The method by which vertices are visited.
     */

    e4_VisitMethod vm;

    /*
     * Vertices to be visited are chosen by this visit filter.
     */

    int vf;

public:

    /*
     * Default constructor:
     */

    e4_VertexVisitor();

    /*
     * Copying constructor:
     */

    e4_VertexVisitor(const e4_VertexVisitor &referrer);

    /*
     * Assignment operator:
     */

    e4_VertexVisitor & operator=(const e4_VertexVisitor &referrer);

    /*
     * Comparison operators:
     */

    bool operator==(const e4_VertexVisitor &compared) const;
    bool operator!=(const e4_VertexVisitor &compared) const;

    /*
     * Constructors which initialize the visitor from a node.
     */

    e4_VertexVisitor(const e4_Node &n);
    e4_VertexVisitor(const e4_Node &n, const char *nm, e4_VertexType ft);
    e4_VertexVisitor(const e4_Node &child,
		     const e4_Node &parent,
		     e4_DetachChoice dc);
    e4_VertexVisitor(const e4_Node &child,
		     const e4_Node &parent,
		     e4_DetachChoice dc,
		     const char *nm);

    /*
     * Constructors which initialize the visitor from a vertex.
     */

    e4_VertexVisitor(const e4_Vertex &ff);
    e4_VertexVisitor(const e4_Vertex &ff,
		     bool useVertexName, 
		     bool useVertexType);
    e4_VertexVisitor(const e4_Vertex &ff,
		     bool useVertexName, 
		     bool useVertexType,
		     e4_VisitMethod vmvm);

    /*
     * Constructors that initialize the visitor from a storage.
     */

    e4_VertexVisitor(const e4_Storage &s);
    e4_VertexVisitor(const e4_Storage &s, e4_DetachChoice dc);
    e4_VertexVisitor(const e4_Storage &s, const char *nm, e4_VertexType ft);
    e4_VertexVisitor(const e4_Storage &s,
		     e4_DetachChoice dc,
		     const char *nm,
		     e4_VertexType vt);

    /*
     * Destructor:
     */

    virtual ~e4_VertexVisitor();

    /*
     * Is this visitor done visiting all the vertices in its itinerary?
     */

    bool IsDone();

    /*
     * Get the next vertex from the visitor.
     */

    bool NextVertex(e4_Vertex &ff);

    /*
     * Advance to the next vertex but do not retrieve it:
     */

    bool Advance();

    /*
     * Get the current vertex.
     */

    bool CurrentVertex(e4_Vertex &ff);

    /*
     * Retrieve the current vertex and advance to the next one.
     */

    bool CurrentVertexAndAdvance(e4_Vertex &ff);

    /*
     * Reset the visitor to visit vertices that have a given node
     * as their value.
     */

    bool SetParentVertex(const e4_Node &child,
			 const e4_Node &parent,
			 e4_DetachChoice dc,
			 const char *nm);

    /*
     * Reset the visitor to a given vertex.
     */

    bool SetVertex(const e4_Vertex &ff);
    bool SetVertex(const e4_Vertex &ff,
		   bool useVertexName, 
		   bool useVertexType);
    bool SetVertex(const e4_Vertex &ff,
		   bool useVertexName, 
		   bool useVertexType,
		   e4_VisitMethod vmvm);

    /*
     * Reset the visitor to start at the first vertex of the given node.
     */

    bool SetNode(const e4_Node &nn);
    bool SetNode(const e4_Node &nn, const char *nm, e4_VertexType ft);

    /*
     * Reset the visitor to visit all vertices in a storage.
     */

    bool SetStorage(const e4_Storage &ss);
    bool SetStorage(const e4_Storage &ss, e4_DetachChoice dc);
    bool SetStorage(const e4_Storage &ss,
		    const char *nm,
		    e4_VertexType ft);
    bool SetStorage(const e4_Storage &ss,
		    const char *nm,
		    e4_VertexType ft,
		    e4_DetachChoice dc);

    /*
     * Is this instance valid?
     */

    bool IsValid();

    /*
     * Query methods:
     */

    inline e4_VisitMethod VisitMethod() const {return vm;}
    inline int VisitFilter() const {return vf;}
    inline bool StorageVisited(e4_Storage &ss) const {
	if (s.IsValid()) {
	    ss = s;
	    return true;
	}
	return false;
    }
    inline bool VertexVisited(e4_Vertex &ff) const {
	if (s.IsValid() && f.IsValid()) {
	    ff = f;
	    return true;
	}
	return false;
    }
    inline e4_VertexType TypeFilter() const {return typeID;}
    const char *NameFilter() const;
    bool NodeVisited(e4_Node &n) const;
};

/*
 * class e4_NodeVisitor:
 */

class e4_DLL e4_NodeVisitor {
private:
    /*
     * The storage used by this visitor.
     */

    e4_Storage s;

    /*
     * The last node returned by the visitor.
     */

    e4_Node n;

    /*
     * Is this visitor done visiting all the nodes in this storage?
     */

    bool done;

    /*
     * Is this visitor visiting detached nodes, attached nodes or both?
     * (false)?
     */

    e4_DetachChoice detachchoice;

public:

    /*
     * Default constructor:
     */

    e4_NodeVisitor();

    /*
     * Copying constructor:
     */

    e4_NodeVisitor(const e4_NodeVisitor &referrer);

    /*
     * Assignment operator:
     */

    e4_NodeVisitor & operator=(const e4_NodeVisitor &referrer);

    /*
     * Comparison operators:
     */

    bool operator==(const e4_NodeVisitor &compared) const;
    bool operator!=(const e4_NodeVisitor &compared) const;

    /*
     * Constructors that initialize the visitor from a storage, node,
     * or vertex.
     */

    e4_NodeVisitor(const e4_Storage &ss);
    e4_NodeVisitor(const e4_Storage &ss, e4_DetachChoice dc);
    e4_NodeVisitor(const e4_Node &nn);
    e4_NodeVisitor(const e4_Vertex &ff);

    /*
     * Destructor:
     */

    virtual ~e4_NodeVisitor();

    /*
     * Is this visitor done visiting all the nodes in this storage?
     */

    bool IsDone();

    /*
     * Get the next node from this visitor:
     */

    bool NextNode(e4_Node &nn);

    /*
     * Advance to the next node but do not retrieve it:
     */

    bool Advance();

    /*
     * Get the current node.
     */

    bool CurrentNode(e4_Node &nn);

    /*
     * Get the current node and advance the visitor to the next node.
     */

    bool CurrentNodeAndAdvance(e4_Node &nn);

    /*
     * Reset the visitor from a given storage, node, or vertex.
     */

    bool SetStorage(const e4_Storage &ss);
    bool SetStorage(const e4_Storage &ss, e4_DetachChoice dc);
    bool SetNode(const e4_Node &nn);
    bool SetVertex(const e4_Vertex &ff);

    /*
     * Is this visitor valid?
     */

    bool IsValid();
};

/*
 * class e4_ParentVisitor:
 */

class e4_DLL e4_ParentVisitor {
private:
    /*
     * The storage used by this visitor.
     */

    e4_Storage s;

    /*
     * The last node returned by the visitor.
     */

    e4_Node p;

    /*
     * The node whose parents are being visited.
     */

    e4_Node n;

    /*
     * The current parent count:
     */

    int curParent;

    /*
     * Is this visitor done visiting all the nodes in this storage?
     */

    bool done;

public:

    /*
     * Default constructor:
     */

    e4_ParentVisitor();

    /*
     * Copying constructor:
     */

    e4_ParentVisitor(const e4_ParentVisitor &referrer);

    /*
     * Assignment operator:
     */

    e4_ParentVisitor & operator=(const e4_ParentVisitor &referrer);

    /*
     * Comparison operators:
     */

    bool operator==(const e4_ParentVisitor &compared) const;
    bool operator!=(const e4_ParentVisitor &compared) const;

    /*
     * Constructors that initialize the visitor from a node.
     */

    e4_ParentVisitor(const e4_Node &nn);

    /*
     * Destructor:
     */

    virtual ~e4_ParentVisitor();

    /*
     * Is this visitor done visiting all the parents of the given node?
     */

    bool IsDone();

    /*
     * Get the next parent node from this visitor:
     */

    bool NextParent(e4_Node &pp);

    /*
     * Advance to the next parent but do not retrieve it:
     */

    bool Advance();

    /*
     * Get the current parent.
     */

    bool CurrentParent(e4_Node &pp);

    /*
     * Get the current parent and advance the visitor to the next node.
     */

    bool CurrentParentAndAdvance(e4_Node &pp);

    /*
     * Reset the visitor from a given node.
     */

    bool SetNode(const e4_Node &nn);

    /*
     * Is this visitor valid?
     */

    bool IsValid();
};

/*
 * A way to transmit arbitrary values:
 */

typedef struct e4_Value {
    e4_VertexType vertexType;	/* Type of the value being passed. */
    e4_Node n;
    union {
	int i;
        double d;
        char *s;
        e4_Binary b;
    } u;
} e4_Value;

/*
 * Global constant instances of e4_RefCount, e4_Storage, e4_Node
 * and e4_Vertex that are guaranteed to be invalid. You can assign these
 * to a variable of the appropriate type to ensure that the reference
 * previously stored in that variable is discarded. Especially useful for
 * removing remaining references in heap-allocated structures.
 */

extern e4_DLL const e4_RefCount	invalidRefCount;
extern e4_DLL const e4_Storage	invalidStorage;
extern e4_DLL const e4_Node	invalidNode;
extern e4_DLL const e4_Vertex	invalidVertex;

/*
 * The parts common to all wrappers:
 */

class e4_DLL e4_CommonUniqueID {
private:
    /*
     * The wrapped ID and SP values:
     */

    int ID;
    int SP;

public:
    /*
     * Default constructor:
     */

    e4_CommonUniqueID();

    /*
     * Copying constructor:
     */

    e4_CommonUniqueID(const e4_CommonUniqueID &referrer);

    /*
     * Constructor that assigns a unique ID to the wrapper:
     */

    e4_CommonUniqueID(int uid, int sp);

    /*
     * Assignment operator:
     */

    e4_CommonUniqueID & operator=(const e4_CommonUniqueID &referrer);

    /*
     * Destructor:
     */

    virtual ~e4_CommonUniqueID();

    /*
     * Get and assign the ID, SP fields.
     */

    inline int GetID() const {return ID;}
    inline void SetID(int id) {ID = id;}

    inline int GetSP() const {return SP;}
    inline void SetSP(int sp) {SP = sp;}

    /*
     * Comparison operators:
     */

    bool operator==(const e4_CommonUniqueID &compared) const;
    bool operator!=(const e4_CommonUniqueID &compared) const;

    /*
     * Is this unique ID wrapper assigned a value?
     */

    inline bool IsAssigned() const 
    {
	return ((ID == E4_INVALIDUNIQUEID) || (SP == 0))? false : true;
    }
};

/*
 * Wrapper for unique ID derived from an e4_Node.
 */

class e4_DLL e4_NodeUniqueID : public e4_CommonUniqueID {
public:
    /*
     * Default constructor:
     */

    e4_NodeUniqueID();

    /*
     * Copying constructor:
     */

    e4_NodeUniqueID(const e4_NodeUniqueID &referrer);

    /*
     * Constructor that assigns a value.
     */

    e4_NodeUniqueID(int nid, int sp);

    /*
     * Assignment operator:
     */

    e4_NodeUniqueID & operator=(const e4_NodeUniqueID &referrer);

    /*
     * Comparison operators:
     */

    bool operator==(const e4_NodeUniqueID &compared) const;
    bool operator!=(const e4_NodeUniqueID &compared) const;

    /*
     * Extract the value.
     */

    inline operator int() const {return GetID();}

    /*
     * Extract the value.
     */

    inline int GetUniqueID() const {return GetID();}

    /*
     * Set the value.
     */

    inline void SetUniqueID(int nid, e4_Storage s) {
	if (!s.IsValid()) {
	    return;
	}
	SetID(nid);
	SetSP(s.GetTemporaryUID());
    }
};

/*
 * Wrapper for unique ID derived from an e4_Vertex.
 */

class e4_DLL e4_VertexUniqueID : public e4_CommonUniqueID {
public:
    /*
     * Default constructor:
     */

    e4_VertexUniqueID();

    /*
     * Copying constructor:
     */

    e4_VertexUniqueID(const e4_VertexUniqueID &referrer);

    /*
     * Constructor that assigns a value.
     */

    e4_VertexUniqueID(int vid, int sp);

    /*
     * Assignment operator:
     */

    e4_VertexUniqueID & operator=(const e4_VertexUniqueID &referrer);

    /*
     * Comparison operators:
     */

    bool operator==(const e4_VertexUniqueID &compared) const;
    bool operator!=(const e4_VertexUniqueID &compared) const;

    /*
     * Extract the value.
     */

    inline operator int() const {return GetID();}

    /*
     * Extract the value.
     */

    inline int GetUniqueID() const {return GetID();}

    /*
     * Set the value.
     */

    inline void SetUniqueID(int nid, e4_Storage s) {
	if (!s.IsValid()) {
	    return;
	}
	SetID(nid);
	SetSP(s.GetTemporaryUID());
    }
};

/***********************************************************************
 *
 * Dynamic string API:
 *
 ***********************************************************************
 */

/*
 * How big is the static space for dynamic strings?
 */

#define	E4_DSTRING_STATIC_SIZE		200

/*
 * The DString class:
 */

class e4_DLL e4_DString {
private:

    /*
     * The string itself.
     */

    char *buf;

    /*
     * The static space.
     */

    char staticSpace[E4_DSTRING_STATIC_SIZE + 1];

    /*
     * How much space is available?
     */

    int spaceAvailable;

    /*
     * And how long is the current value of the string?
     */

    int length;

public:

    /*
     * Constructor:
     */

    e4_DString();

    /*
     * Destructor:
     */

    virtual ~e4_DString();

    /*
     * Append a string to this DString.
     */

    void Append(const char *str, int slen);

    /*
     * Get the current value of the string.
     */

    char *Get() const;

    /*
     * Get a copy of the current value of the string.
     */

    char *GetCopy() const;

    /*
     * Get the length of the string.
     */

    int Length() const;

    /*
     * Set the length of the string.
     */

    int SetLength(int newlength);

    /*
     * Reset the instance to its original state (empty contents,
     * static buffer).
     */

    void Reset();    
};

/***********************************************************************
 *
 * Hash table API:
 *
 ***********************************************************************
 */

/*
 * Forward declaration of E4_HashTable.  Needed by some C++ compilers
 * to prevent errors when the forward reference to E4_HashTable is
 * encountered in the E4_HashEntry structure.
 */

struct e4_HashTable;

/*
 * Structure definition for an entry in a hash table.
 */

typedef struct e4_HashEntry {
    struct e4_HashEntry *nextPtr;	/* Pointer to next entry in this
					 * hash bucket, or NULL for end of
					 * chain. */
    struct e4_HashTable *tablePtr;	/* Ptr to table containing entry. */
    struct e4_HashEntry **bucketPtr;	/* Pointer to bucket that points to
					 * first entry in this entry's chain:
					 * used for deleting the entry. */
    void *clientData;			/* Application stores something here
					 * with e4_SetHashValue. */
    union {				/* Key has one of these forms: */
	char *oneWordValue;		/* One-word value for key. */
	int words[1];			/* Multiple integer words for key.
					 * The actual size will be as large
					 * as necessary for this table's
					 * keys. */
	char string[4];			/* String for key.  The actual size
					 * will be as large as needed to hold
					 * the key. */
    } key;				/* MUST BE LAST FIELD IN RECORD!! */
} e4_HashEntry;

/*
 * Structure definition for a hash table.  Must be in e4.h so clients
 * can allocate space for these structures, but clients should never
 * access any fields in this structure.
 */

#define E4_SMALL_HASH_TABLE 4
typedef struct e4_HashTable {
    e4_HashEntry **buckets;		/* Pointer to bucket array.  Each
					 * element points to first entry in
					 * bucket's hash chain, or NULL. */
    e4_HashEntry *staticBuckets[E4_SMALL_HASH_TABLE];
					/* Bucket array used for small tables
					 * (to avoid mallocs and frees). */
    int numBuckets;			/* Total number of buckets allocated
					 * at **bucketPtr. */
    int numEntries;			/* Total number of entries present
					 * in table. */
    int rebuildSize;			/* Enlarge table when numEntries gets
					 * to be this large. */
    int downShift;			/* Shift count used in hashing
					 * function.  Designed to use high-
					 * order bits of randomized keys. */
    int mask;				/* Mask value used in hashing
					 * function. */
    int keyType;			/* Type of keys used in this table. 
					 * It's either E4_STRING_KEY,
					 * E4_ONE_WORD_KEY, or an integer
					 * giving the number of ints that
                                         * is the size of the key.
					 */
    e4_HashEntry *(*findProc) (struct e4_HashTable *tablePtr,
			       const char *key);
    e4_HashEntry *(*createProc) (struct e4_HashTable *tablePtr,
				 const char *key, int *newPtr);
} e4_HashTable;

/*
 * Structure definition for information used to keep track of searches
 * through hash tables:
 */

typedef struct e4_HashSearch {
    e4_HashTable *tablePtr;		/* Table being searched. */
    int nextIndex;			/* Index of next bucket to be
					 * enumerated after present one. */
    e4_HashEntry *nextEntryPtr;	/* Next entry to be enumerated in the
					 * the current bucket. */
} e4_HashSearch;

/*
 * Acceptable key types for hash tables:
 */

#define E4_STRING_KEY		0
#define E4_ONE_WORD_KEY		1
#define E4_TWO_WORDS_KEY	2

/*
 * Macros for clients to use to access fields of hash entries:
 */

#define E4_GETHASHVALUE(h) ((h)->clientData)
#define E4_SETHASHVALUE(h, value) ((h)->clientData = (void *) (value))
#define E4_GETHASHKEY(tablePtr, h) \
    ((char *) (((tablePtr)->keyType == E4_ONE_WORD_KEY) \
	       ? (h)->key.oneWordValue \
	       : (h)->key.string))

/*
 * Macros to use for clients to use to invoke find and create procedures
 * for hash tables:
 */

#define E4_FINDHASHENTRY(tablePtr, key) \
	(*((tablePtr)->findProc))(tablePtr, key)
#define E4_CREATEHASHENTRY(tablePtr, key, newPtr) \
	(*((tablePtr)->createProc))(tablePtr, key, newPtr)

/*
 * Function entry points:
 */

extern e4_DLL void		e4_DeleteHashEntry (e4_HashEntry *entryPtr);
extern e4_DLL void		e4_DeleteHashTable (e4_HashTable *tablePtr);
extern e4_DLL e4_HashEntry *	e4_FirstHashEntry (e4_HashTable *tablePtr,
						   e4_HashSearch *searchPtr);
extern e4_DLL e4_HashEntry *	e4_NextHashEntry (e4_HashSearch *searchPtr);
extern e4_DLL e4_HashTable *	e4_NewHashTable (int keyType);

#ifdef	NOTDEF
/*
 * The generic cache facility:
 *
 * This facility allows user applications to associate a sizeof(void *) value
 * with each e4_Storage, e4_Node and e4_Vertex. It provides operations for
 * storing, retrieving and deleting the association.
 */

class e4_DLL e4_Cache {
private:
    /*
     * These hash tables contain the data associated with instances of
     * e4_Graph entities.
     */

    e4_HashTable *tblStorages;
    e4_HashTable *tblNodes;
    e4_HashTable *tblVertices;

public:

    /*
     * Constructor:
     */

    e4_Cache();

    /*
     * Destructor:
     */

    ~e4_Cache();

    /*
     * Operations to create, retrieve and delete associations:
     */

    void Put(e4_Storage s, void *cd);
    void Put(e4_Node n, void *cd);
    void Put(e4_Vertex v, void *cd);

    void *Get(e4_Storage s);
    void *Get(e4_Node n);
    void *Get(e4_Vertex v);

    void Del(e4_Storage s);
    void Del(e4_Node n);
    void Del(e4_Vertex v);

    /*
     * Delete all associations for entities that are contained within the
     * given storage.
     */

    void DelAll(e4_Storage s);

    /*
     * Prune all entries for which the passed-in predicate returns
     * non-zero.
     */

    void PruneStorages(int (*fn)(void *));
    void PruneNodes(int (*fn)(void *));
    void PruneVertices(int (*fn)(void *));

    /*
     * Operations to retrieve the caches for each data type.
     */

    e4_HashTable *GetStorageCache();
    e4_HashTable *GetNodeCache();
    e4_HashTable *GetVertexCache();
};
#endif

#endif	/* __E4_GRAPH_H__ */
