/* * t4graphrep -- * * This include file provides definitions for the internal representation * of T4Graph objects. * * Authors: Jacob Levy and Jean-Claude Wippler. * jyl@best.com jcw@equi4.com * * 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 __T4GRAPHREP_H__ #define __T4GRAPHREP_H__ /* * First include the public interface: */ #include "t4graph.h" /* * Include the GenObject public interface: */ #include "genobject.h" /* * HACK to get the code to compile cleanly with both Tcl 8.3 and Tcl 8.4 and * later. */ #ifndef CONST84 #define CONST84 #endif /* * These pointers are for public access to the GenObj type definitions for * each Tcl_Obj object type provided by TGraph: */ extern struct GO_Extension *vertexExt; extern struct GO_Extension *nodeExt; /* * The key for use of our private interpreter associated data. */ #define T4_ASSOCKEY "tgraph::openstorages" /* * Enumeration of the different T4Graph internal representations: */ typedef enum T4Kinds { T4GRAPH_ILLEGAL = -1, T4GRAPH_STORAGE = 0, T4GRAPH_NODE = 1, T4GRAPH_VERTEX = 2 } T4Kinds; /* * This record contains information pertaining to one callback declaration. */ typedef struct T4CallbackRecord { T4Storage *storage; /* The storage on which the callback occurs. */ Tcl_Interp *interp; /* The interp in which the callback occurs. */ int kind; /* The kind of callback this record is for. */ } T4CallbackRecord; /* * Enumeration to allow selection of an object kind (for Get and Callback * operations). */ typedef enum T4ObjectKindSelector { T4_OKNODE = 0, T4_OKVERTEX = 1, T4_OKSTORAGE = 2 } T4ObjectKindSelector; /* * Enumerations for managing the callback facility on a T4Storage object. */ typedef enum T4CallbackEventSelector { T4_CBESADD = 0, T4_CBESDET = 1, T4_CBESATT = 2, T4_CBESMOD = 3, T4_CBESCHG = 4 } T4CallbackEventSelector; typedef enum T4CallbackActionSelector { T4_CBASADD = 0, T4_CBASDEL = 1, T4_CBASGET = 2, T4_CBASSET = 3, T4_CBASKND = 4, T4_CBASCNT = 5, T4_CBASHAS = 6 } T4CallbackActionSelector; /* * Flags marking a T4Vertex. */ #define T4_VERTEXEXPORTED (1 << 0) #define T4_VERTEXUSED (1 << 1) /* * How many vertices can be cached between subsequent sweeps of the cache? */ #define T4_SWEEP_INTERVAL 256 /* * This structure contains the per-interpreter data for a storage object: */ typedef struct T4StoragePerInterp { /* * doubly-linked chain of records. */ struct T4StoragePerInterp *next; struct T4StoragePerInterp *prev; /* * Link back to the T4Storage that contains this structure: */ T4Storage *storage; /* * The interpreter in which this set of information is valid. */ Tcl_Interp *interp; /* * These hash tables contain the internal representations of * all objects in this storage that have been exported to Tcl. */ Tcl_HashTable *exportedNodes; Tcl_HashTable *exportedVertices; /* * Hash table for callbacks. */ Tcl_HashTable *callbacks; /* * Hash tables for storing information associated with vertices. */ Tcl_HashTable *storedProcs; Tcl_HashTable *storedValues; /* * Counters for how many callbacks there are for each kind of event. * When a counter is zero, the C++ level callback is cancelled. */ int cbaddnode; int cbaddvertex; int cbdetnode; int cbdetvertex; int cbattnode; int cbattvertex; int cbmodnode; int cbmodvertex; int cbchgstorage; /* * Callback tokens to be used when the callback is deleted. */ T4CallbackRecord *cbAddNodeRecord; T4CallbackRecord *cbDetNodeRecord; T4CallbackRecord *cbAttNodeRecord; T4CallbackRecord *cbAddVertexRecord; T4CallbackRecord *cbDetVertexRecord; T4CallbackRecord *cbAttVertexRecord; T4CallbackRecord *cbChgStorageRecord; } T4StoragePerInterp; /* * This class serves as the common base class for all T4Graph internal * representations, so its possible to pass any of them throuh a * common procedure argument. */ class e4_TGRAPHDLL T4InternalRep { private: /* * The Tcl_Obj * that represents this T4InternalRep in Tcl: */ Tcl_Obj *tclPtr; /* * The name assigned to this T4Graph object in Tcl and its length. */ char *nm; int nmlen; public: /* * Default constructor: */ T4InternalRep(); /* * Return a T4Kinds identifier for the type of this * T4Graph object. */ virtual T4Kinds KindIdentifier() const; /* * Returns a string representing the kind identifier. */ virtual const char *KindString() const; /* * Return the name by which this object is known in Tcl. */ char *GetName(); /* * Return the length of the name by which this object is known in Tcl. */ int GetNameLen(); /* * Set/get the Tcl object associated with this internal representation. */ Tcl_Obj *GetTclObject(); void SetTclObject(Tcl_Obj *obj); }; /* * This class is the internal representation of a storage object: */ class e4_TGRAPHDLL T4Storage : public T4InternalRep { private: /* * The actual storage object. */ e4_Storage s; /* * Chain of records, one per interp, for holding interpreter specific * information. */ T4StoragePerInterp *spip; /* * The name of the file and driver for this storage. */ char *fname; char *drivername; /* * Visitor methods: */ int VisitNodes(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); int VisitVertices(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); /* * Helper methods for callback registration mgmt: */ int CBAddCallback(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); int CBDelCallback(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); int CBGetCallback(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); int CBSetCallback(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); int CBKindCallback(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); int CBCountCallback(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); int CBHasCallback(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); /* * Helper methods for configure operation: */ int SetStorageOptions(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); int GetStorageOptions(Tcl_Interp *interp); int GetStorageOption(Tcl_Interp *interp, Tcl_Obj *opt); /* * Clean up in-core state associated with this storage. */ int InternalClose(Tcl_Interp *interp, bool selfdestruct); /* * Get the interpreter-specific data for this storage in the given * interpreter. */ T4StoragePerInterp *GetStoragePerInterp(Tcl_Interp *interp); public: /* * Constructor: */ T4Storage(e4_Storage ss, char *fn, char *dn); /* * Destructor: */ virtual ~T4Storage(); /* * This method returns the kind of internal representation that * is implemented by this class. */ virtual inline T4Kinds KindIdentifier() const { return T4GRAPH_STORAGE; } /* * This method returns the string representing the kind identifier. */ virtual const char *KindString() const { return "T4Storage"; } /* * The following methods implement Tcl sub-commands: */ int Close(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); int Commit(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); int Configure(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); int IsStable(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); int MarkUnstable(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); int CopyTo(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); int Delete(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); int DoGC(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); int Root(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); int IsValid(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); int Name(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); int NeedsGC(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); int Node(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); int Vertex(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); int Foreach(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); int Statistic(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); int Callback(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); int Get(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); int Share(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); /* * These operations return internal representations of T4Graph * objects identified by index or name. The object must already have * been created. */ T4Node *GetNodeById(Tcl_Interp *interp, e4_NodeUniqueID nuid); T4Vertex *GetVertexById(Tcl_Interp *interp, e4_VertexUniqueID vuid); /* * These operations create a new entry in the respective hash * table when an object is exported to Tcl. */ void StoreNode(Tcl_Interp *interp, T4Node *n, int id); void StoreVertex(Tcl_Interp *interp, T4Vertex *f, int id); /* * These operations remove an internal representation from the * respective hash table when the object is no longer being * exported to Tcl. */ void RemoveNode(Tcl_Interp *interp, e4_NodeUniqueID nuid); void RemoveVertex(Tcl_Interp *interp, e4_VertexUniqueID vuid); /* * This operation removes all registered callbacks for this storage. */ void RemoveAllCallbacks(T4StoragePerInterp *spp); /* * This operation externalizes the e4Graph storage object. */ void ExternalizeStorage(e4_Storage &ss); /* * These methods get called when a callback event occurs. */ void AddNodeCallback(Tcl_Interp *interp, e4_Node n); void AddVertexCallback(Tcl_Interp *interp, e4_Vertex v); void DetNodeCallback(Tcl_Interp *interp, e4_Node n); void DetVertexCallback(Tcl_Interp *interp, e4_Vertex v); void AttNodeCallback(Tcl_Interp *interp, e4_Node n); void AttVertexCallback(Tcl_Interp *interp, e4_Vertex v); void ChangeStorageCallback(Tcl_Interp *interp); /* * Special callbacks for node modification and vertex modification. * These callbacks are always installed, even when the Tcl program * does not have any callbacks of these kinds registered. These * methods do some housekeeping and then call the Tcl scritps registered * as callbacks, thereby ensuring that the housekeeping is always done * before any Tcl scripts are run. */ void ModNodeCallback(T4StoragePerInterp *spp, e4_Node n, e4_ModNodeEventReason cbr); void ModVertexCallback(T4StoragePerInterp *spp, e4_Vertex v, e4_ModVertexEventReason cbr); /* * Register and unregister this storage with an interpreter. */ void RegisterStoragePerInterp(Tcl_Interp *interp); void UnregisterStoragePerInterp(Tcl_Interp *interp); /* * Manage state for a vertex exported to Tcl. */ void ClearVertexStoredState(Tcl_Interp *interp, e4_Vertex v) const; void SetVertexStoredObject(Tcl_Interp *interp, e4_Vertex v, Tcl_Obj *obj) const; void SetVertexStoredCmdInfo(Tcl_Interp *interp, e4_Vertex v, T4CmdInfo *cmdInfo) const; Tcl_Obj *GetVertexStoredObject(Tcl_Interp *interp, e4_Vertex v) const; T4CmdInfo *GetVertexStoredCmdInfo(Tcl_Interp *interp, e4_Vertex v) const; }; /* * This class is the internal representation of a node object. */ class e4_TGRAPHDLL T4Node : public T4InternalRep { private: /* * The actual node object. */ e4_Node n; /* * The T4Storage instance of the storage containing this vertex: */ T4Storage *s; /* * Obtain an e4_Vertex for a vertex being modified. */ int GetVertexRef(Tcl_Interp *interp, char *vn, bool createifnotfound, e4_Vertex &v); /* * Set the value of an e4_Vertex to the given type using the supplied * value as the source of the converted type. */ int SetAs(Tcl_Interp *interp, e4_Vertex v, Tcl_Obj *val, int rt); /* * Obtain a T4Vertex given a vertex name. */ T4Vertex *ObtainVertex(Tcl_Interp *interp, char *vn, bool *crp); /* * Private visitor functions: */ int VisitVertices(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); int VisitParents(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); public: /* * Constructor: */ T4Node(e4_Node nn, T4Storage *ss); /* * Destructor */ virtual ~T4Node(); /* * Cleanup done before destruction: */ void CleanupInternal(Tcl_Interp *interp); /* * This method returns the kind of internal representation that * is implemented by this class. */ virtual inline T4Kinds KindIdentifier() const { return T4GRAPH_NODE; } /* * This method returns a string representing the kind identifier. */ virtual const char *KindString() const { return "T4Node"; } /* * Retrieve the T4Storage instance for the storage containing * this vertex: */ inline T4Storage *GetStorage() const { return s; } /* * The following methods implement Tcl sub-commands. */ int VertexCount(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); int Set(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); int Add(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); int Get(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); int SetNode(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); int AddNode(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); int GetVertex(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); int MoveVertex(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); int DetachVertex(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); int VertexType(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); int VertexRank(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); int VertexName(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); int RenameVertex(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); int Exists(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); int Parent(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); int ParentCount(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); int OccurrenceCount(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); int ParentRank(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); int Root(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); int IsRoot(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); int RankInParent(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); int NameInParent(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); int Detach(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); int Dispose(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); int IsValid(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); int IsDetached(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); int Method(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); int Call(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); int Foreach(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); int Id(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); int UserData(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); int DetachFirstVertexWithNode(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); int PreCache(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); /* * This operation externalizes the e4Graph node object. */ void ExternalizeNode(e4_Node &nn); /* * This IsValid operation is only intended for use by the invoker * as a quick check whether the internal representation was lost. */ bool IsValid() const; }; /* * This class is the internal representation of a vertex object. */ class e4_TGRAPHDLL T4Vertex : public T4InternalRep { private: /* * The actual vertex object. */ e4_Vertex f; /* * The T4Storage instance of the storage containing this vertex: */ T4Storage *s; public: /* * Constructor: */ T4Vertex(e4_Vertex ff, T4Storage *ss); /* * Destructor: */ virtual ~T4Vertex(); /* * Cleanup done before destruction: */ void CleanupInternal(Tcl_Interp *interp); /* * This method returns the kind of internal representation that * is implemented by this class. */ virtual inline T4Kinds KindIdentifier() const { return T4GRAPH_VERTEX; } /* * This method returns a string representing the kind identifier. */ virtual const char *KindString() const { return "T4Vertex"; } /* * Retrieve the T4Storage instance for the storage containing * this vertex: */ inline T4Storage *GetStorage() const { return s; } /* * The following operation is the same as Set() except that it * converts the given value to a requested type. */ int SetAs(Tcl_Interp *interp, Tcl_Obj *val, int reqtype); /* * The following methods implement Tcl sub-commands. */ int Get(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); int Set(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); int SetNode(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); int Rank(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); int Detach(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); int Dispose(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); int IsValid(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); int IsDetached(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); int Type(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); int Name(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); int Rename(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); int Root(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); int Node(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); int Move(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); int Next(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); int Prev(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); int Call(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); int Id(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); int UserData(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); /* * This operation externalizes the e4Graph vertex object. */ void ExternalizeVertex(e4_Vertex &ff); /* * This operation is only intended to be used by the invoker for a * quick check whether the internal representation was lost. */ bool IsValid() const; }; #endif /* __T4GRAPHREP_H__ */