/* * i4node.cpp -- * * This file provides the implementation of the e4_NodeImpl class defined * in e4graphimpl.h. * * 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. */ #include "e4graphimpl.h" /* * These constants define cache key values for caching by rank: */ #define E4_CACHEIDBYRANK -1 #define E4_CACHERANKBYID -2 /* * This constructor is for internal use (by friend classes) only: */ e4_NodeImpl::e4_NodeImpl(e4_StorageImpl *s, int ni) : e4_RefCounter(), storage(s), nodeID(ni), flags(0), cachePolicy(E4_CACHEINCREMENTAL), cachedVertexIDs(NULL), cacheNonEmpty(false) {} /* * The destructor: */ e4_NodeImpl::~e4_NodeImpl() { e4_StorageImpl *lsp = storage; if (storage != NULL) { /* * Don't bother about cleanups if the storage itself is invalid. */ if (!storage->IsValid()) { return; } /* * Remove this node from the cache. */ storage->ForgetNode(nodeID); /* * Can't use the "storage" instance variable * because ForgetNode resets it to NULL. * * If this node is detached, and not the root, it became unreachable. * If GC is not deferred clean up right away. */ if (lsp->DRV_IsDetachedNodeID(nodeID) && (lsp->DRV_GetRootNodeID() != nodeID)) { lsp->RegisterUnreachableNodeID(nodeID); if ((lsp->GetState() & E4_AUTOGC) == E4_AUTOGC) { lsp->DoGC(); } else { lsp->SetNeedsGC(true); } } } /* * Clean up the cache of name+nth and rank mappings to vertex IDs. */ if (cachedVertexIDs != NULL) { e4_DeleteHashTable(cachedVertexIDs); free((char *) cachedVertexIDs); } } /* * This method is called when the reference count goes to (or below) zero. */ void e4_NodeImpl::NotReferenced() { delete this; } /* * Precache all information about this node's vertices. */ void e4_NodeImpl::PreCache() { e4_HashTable *names; e4_HashEntry *ep; int nameID, vertexID, isnew, rank, nth; union { void *v; int i; } u; if (!storage->CachingVertexIDs()) { return; } names = e4_NewHashTable(E4_ONE_WORD_KEY); for (vertexID = GetFirstVertexID(), rank = 1; vertexID != E4_VERTEXNOTFOUND; vertexID = storage->DRV_NextVertexID(vertexID), rank++) { nameID = storage->DRV_NameIDFromVertexID(vertexID); u.i = nameID; ep = E4_CREATEHASHENTRY(names, (char *) u.v, &isnew); if (isnew) { E4_SETHASHVALUE(ep, 1); nth = 1; } else { u.v = (void *) E4_GETHASHVALUE(ep); nth = 1 + u.i; E4_SETHASHVALUE(ep, u.v); } CacheVertexIDByName(nameID, nth, vertexID); CacheVertexIDByRank(rank, vertexID); CacheVertexRankByID(vertexID, rank); } e4_DeleteHashTable(names); free((char *) names); } /* * Precache all information requested by the provided mask about this * node's vertices. */ void e4_NodeImpl::PreCache(int mask) { e4_HashTable *names; e4_HashEntry *ep; int nameID, vertexID, isnew, rank, nth; union { void *v; int i; } u; if ((mask == E4_CACHEINCREMENTAL) || (!storage->CachingVertexIDs())) { return; } names = e4_NewHashTable(E4_ONE_WORD_KEY); for (vertexID = GetFirstVertexID(), rank = 1; vertexID != E4_VERTEXNOTFOUND; vertexID = storage->DRV_NextVertexID(vertexID), rank++) { nameID = storage->DRV_NameIDFromVertexID(vertexID); u.i = nameID; ep = E4_CREATEHASHENTRY(names, (char *) u.v, &isnew); if (isnew) { E4_SETHASHVALUE(ep, 1); nth = 1; } else { u.v = (void *) E4_GETHASHVALUE(ep); nth = 1 + u.i; E4_SETHASHVALUE(ep, u.v); } if ((mask & E4_AUTOCACHENAMES) == E4_AUTOCACHENAMES) { CacheVertexIDByName(nameID, nth, vertexID); } if ((mask & E4_AUTOCACHERANKS) == E4_AUTOCACHERANKS) { CacheVertexIDByRank(rank, vertexID); CacheVertexRankByID(vertexID, rank); } } e4_DeleteHashTable(names); free((char *) names); } /* * This method is called to invalidate the cache mapping name+nth and * rank to vertex IDs. */ void e4_NodeImpl::FlushCache() { if (cacheNonEmpty) { if (cachedVertexIDs != NULL) { e4_DeleteHashTable(cachedVertexIDs); free((char *) cachedVertexIDs); } cachedVertexIDs = e4_NewHashTable(E4_TWO_WORDS_KEY); } cacheNonEmpty = false; if (cachePolicy != E4_CACHEINCREMENTAL) { PreCache(); } } /* * Get a cached vertex ID by name+nth. Returns the ID or E4_VERTEXNOTFOUND. */ int e4_NodeImpl::GetCachedVertexIDByName(int nameID, int nth) const { int key[2]; e4_HashEntry *ep; union { void *v; int i; } u; if ((nth < 1) || (nameID < 0) || (cachedVertexIDs == NULL)) { return E4_VERTEXNOTFOUND; } key[0] = nth; key[1] = nameID; ep = E4_FINDHASHENTRY(cachedVertexIDs, (const char *) key); if (ep != NULL) { u.v = E4_GETHASHVALUE(ep); return u.i; } return E4_VERTEXNOTFOUND; } /* * Get a cached vertex ID by rank. Returns the ID or E4_VERTEXNOTFOUND. */ int e4_NodeImpl::GetCachedVertexIDByRank(int rank) const { int key[2]; e4_HashEntry *ep; union { void *v; int i; } u; if ((rank < 1) || (cachedVertexIDs == NULL)) { return E4_VERTEXNOTFOUND; } key[0] = rank; key[1] = E4_CACHEIDBYRANK; ep = E4_FINDHASHENTRY(cachedVertexIDs, (const char *) key); if (ep != NULL) { u.v = E4_GETHASHVALUE(ep); return u.i; } return E4_VERTEXNOTFOUND; } /* * Get a cached vertex rank by vertex ID. returns the rank * E4_VERTEXNOTFOUND. */ int e4_NodeImpl::GetCachedVertexRankByID(int vid) const { int key[2]; e4_HashEntry *ep; union { void *v; int i; } u; if ((vid < 0) || (cachedVertexIDs == NULL)) { return E4_VERTEXNOTFOUND; } key[0] = vid; key[1] = E4_CACHERANKBYID; ep = E4_FINDHASHENTRY(cachedVertexIDs, (const char *) key); if (ep != NULL) { u.v = E4_GETHASHVALUE(ep); return u.i; } return E4_VERTEXNOTFOUND; } /* * Cache a vertex ID by name + nth. */ void e4_NodeImpl::CacheVertexIDByName(int nameID, int nth, int vid) { int key[2]; e4_HashEntry *ep; int isnew; union { void *v; int i; } u; /* * Only cache if the storage allows. */ if (!storage->CachingVertexIDs()) { return; } /* * Only cache reasonable arguments. */ if ((nameID < 0) || (nth < 1) || (vid < 0)) { return; } if (cachedVertexIDs == NULL) { cachedVertexIDs = e4_NewHashTable(E4_TWO_WORDS_KEY); } key[0] = nth; key[1] = nameID; ep = E4_CREATEHASHENTRY(cachedVertexIDs, (char *) key, &isnew); if ((ep != NULL) && (isnew != 0)) { u.i = vid; E4_SETHASHVALUE(ep, u.v); } cacheNonEmpty = true; } /* * Cache a vertex ID by rank. */ void e4_NodeImpl::CacheVertexIDByRank(int rank, int vid) { int key[2]; e4_HashEntry *ep; int isnew; union { void *v; int i; } u; /* * Only cache if the storage allows. */ if (!storage->CachingVertexIDs()) { return; } /* * Only cache reasonable arguments. */ if ((rank < 1) || (vid < 0)) { return; } if (cachedVertexIDs == NULL) { cachedVertexIDs = e4_NewHashTable(E4_TWO_WORDS_KEY); } key[0] = rank; key[1] = E4_CACHEIDBYRANK; ep = E4_CREATEHASHENTRY(cachedVertexIDs, (char *) key, &isnew); if ((ep != NULL) && (isnew != 0)) { u.i = vid; E4_SETHASHVALUE(ep, u.v); } cacheNonEmpty = true; } /* * Cache a vertex rank by vertex ID. */ void e4_NodeImpl::CacheVertexRankByID(int rank, int vid) { int key[2]; e4_HashEntry *ep; int isnew; union { void *v; int i; } u; /* * Only cache if the storage allows. */ if (!storage->CachingVertexIDs()) { return; } /* * Only cache reasonable arguments. */ if ((rank < 1) || (vid < 0)) { return; } if (cachedVertexIDs == NULL) { cachedVertexIDs = e4_NewHashTable(E4_TWO_WORDS_KEY); } key[0] = vid; key[1] = E4_CACHERANKBYID; ep = E4_CREATEHASHENTRY(cachedVertexIDs, (char *) key, &isnew); if ((ep != NULL) && (isnew != 0)) { u.i = rank; E4_SETHASHVALUE(ep, u.v); } cacheNonEmpty = true; } /* * Set an existing vertex or add a vertex with a node value. */ e4_NodeImpl * e4_NodeImpl::SetNthNode(const char *nm, int nth) { int i, rank, nameID, hisNodeID; e4_NodeImpl *hisnode = NULL; e4_VertexImpl *v; if (storage == NULL) { return NULL; } if ((storage->GetPermissions() & E4_SPMODIFY) == 0) { return NULL; } nameID = storage->InternName(nm, true); i = GetCachedVertexIDByName(nameID, nth); if (i == E4_VERTEXNOTFOUND) { i = storage->DRV_VertexIDFromNthVertex(nodeID, nameID, nth, rank); if (i == E4_VERTEXNOTFOUND) { return NULL; } CacheVertexIDByName(nameID, nth, i); CacheVertexIDByRank(rank, i); CacheVertexRankByID(i, rank); } hisNodeID = storage->DRV_ReserveNodeID(); storage->MarkUnstable(); if (storage->DRV_SetVertexByIndexToNode(i, hisNodeID)) { hisnode = storage->FindOrCreateNode(hisNodeID); hisnode->IncrRefCount(); storage->RecordTimeStamp(E4_ECADDNODE | E4_ECMODVERTEX); if (storage->HasCallbacks(E4_ECADDNODE)) { storage->CauseEventInternal(E4_ECADDNODE, hisnode, NULL); } if (storage->HasCallbacks(E4_ECMODVERTEX)) { v = storage->FindReferencedVertex(i); if (v != NULL) { storage->CauseEventInternal(E4_ECMODVERTEX, v, (void *) E4_ERMVMODVALUE); } } } return hisnode; } e4_NodeImpl * e4_NodeImpl::SetNodeByRank(int rank) { int i, hisNodeID; e4_NodeImpl *hisnode = NULL; e4_VertexImpl *v; if (storage == NULL) { return NULL; } if ((storage->GetPermissions() & E4_SPMODIFY) == 0) { return NULL; } i = GetCachedVertexIDByRank(rank); if (i == E4_VERTEXNOTFOUND) { i = storage->DRV_VertexIDFromRank(nodeID, rank); if (i == E4_VERTEXNOTFOUND) { return NULL; } CacheVertexIDByRank(rank, i); CacheVertexRankByID(i, rank); } hisNodeID = storage->DRV_ReserveNodeID(); storage->MarkUnstable(); if (storage->DRV_SetVertexByIndexToNode(i, hisNodeID)) { hisnode = storage->FindOrCreateNode(hisNodeID); hisnode->IncrRefCount(); storage->RecordTimeStamp(E4_ECADDNODE | E4_ECMODVERTEX); if (storage->HasCallbacks(E4_ECADDNODE)) { storage->CauseEventInternal(E4_ECADDNODE, hisnode, NULL); } if (storage->HasCallbacks(E4_ECMODVERTEX)) { v = storage->FindReferencedVertex(i); if (v != NULL) { storage->CauseEventInternal(E4_ECMODVERTEX, v, (void *) E4_ERMVMODVALUE); } } } return hisnode; } e4_NodeImpl * e4_NodeImpl::AddNode(const char *nm, e4_InsertOrder io, int &rank) { int i, hisNodeID; e4_NodeImpl *hisnode = NULL; if (storage == NULL) { return NULL; } if ((storage->GetPermissions() & E4_SPMODIFY) == 0) { return NULL; } i = storage->DRV_AddVertex(nodeID, io, rank); if (i == E4_VERTEXNOTCREATED) { return NULL; } storage->MarkUnstable(); hisNodeID = storage->DRV_ReserveNodeID(); if (storage->DRV_SetVertex(i, storage->InternName(nm, true), E4_VTNODE, hisNodeID)) { hisnode = storage->FindOrCreateNode(hisNodeID); hisnode->IncrRefCount(); storage->RecordTimeStamp(E4_ECADDNODE | E4_ECADDVERTEX | E4_ECMODNODE); if (storage->HasCallbacks(E4_ECADDNODE)) { storage->CauseEventInternal(E4_ECADDNODE, hisnode, NULL); } if (storage->HasCallbacks(E4_ECMODNODE)) { storage->CauseEventInternal(E4_ECMODNODE, this, (void *) E4_ERMNMOVVERTEX); } CacheVertexIDByRank(rank, i); CacheVertexRankByID(i, rank); } return hisnode; } bool e4_NodeImpl::SetNthVertex(const char *nm, int nth, int value) { int i, rank, nameID; e4_VertexImpl *v; if (storage == NULL) { return false; } if ((storage->GetPermissions() & E4_SPMODIFY) == 0) { return false; } nameID = storage->InternName(nm, true); i = GetCachedVertexIDByName(nameID, nth); if (i == E4_VERTEXNOTFOUND) { i = storage->DRV_VertexIDFromNthVertex(nodeID, nameID, nth, rank); if (i == E4_VERTEXNOTFOUND) { return false; } CacheVertexIDByName(nameID, nth, i); CacheVertexIDByRank(rank, i); CacheVertexRankByID(i, rank); } if (!storage->DRV_SetVertexByIndex(i, value)) { return false; } storage->MarkUnstable(); storage->RecordTimeStamp(E4_ECMODVERTEX); if (storage->HasCallbacks(E4_ECMODVERTEX)) { v = storage->FindReferencedVertex(i); if (v != NULL) { storage->CauseEventInternal(E4_ECMODVERTEX, v, (void *) E4_ERMVMODVALUE); } } return true; } bool e4_NodeImpl::SetNthVertex(const char *nm, int nth, double value) { int i, rank, nameID; e4_VertexImpl *v; if (storage == NULL) { return false; } if ((storage->GetPermissions() & E4_SPMODIFY) == 0) { return false; } nameID = storage->InternName(nm, true); i = GetCachedVertexIDByName(nameID, nth); if (i == E4_VERTEXNOTFOUND) { i = storage->DRV_VertexIDFromNthVertex(nodeID, nameID, nth, rank); if (i == E4_VERTEXNOTFOUND) { return false; } CacheVertexIDByName(nameID, nth, i); CacheVertexIDByRank(rank, i); CacheVertexRankByID(i, rank); } if (!storage->DRV_SetVertexByIndex(i, value)) { return false; } storage->MarkUnstable(); storage->RecordTimeStamp(E4_ECMODVERTEX); if (storage->HasCallbacks(E4_ECMODVERTEX)) { v = storage->FindReferencedVertex(i); if (v != NULL) { storage->CauseEventInternal(E4_ECMODVERTEX, v, (void *) E4_ERMVMODVALUE); } } return true; } bool e4_NodeImpl::SetNthVertex(const char *nm, int nth, const char *value) { int i, rank, nameID; e4_VertexImpl *v; if (storage == NULL) { return false; } if ((storage->GetPermissions() & E4_SPMODIFY) == 0) { return false; } nameID = storage->InternName(nm, true); i = GetCachedVertexIDByName(nameID, nth); if (i == E4_VERTEXNOTFOUND) { i = storage->DRV_VertexIDFromNthVertex(nodeID, nameID, nth, rank); if (i == E4_VERTEXNOTFOUND) { return false; } CacheVertexIDByName(nameID, nth, i); CacheVertexIDByRank(rank, i); CacheVertexRankByID(i, rank); } if (!storage->DRV_SetVertexByIndex(i, value)) { return false; } storage->MarkUnstable(); storage->RecordTimeStamp(E4_ECMODVERTEX); if (storage->HasCallbacks(E4_ECMODVERTEX)) { v = storage->FindReferencedVertex(i); if (v != NULL) { storage->CauseEventInternal(E4_ECMODVERTEX, v, (void *) E4_ERMVMODVALUE); } } return true; } bool e4_NodeImpl::SetNthVertex(const char *nm, int nth, const void *bytes, int nbytes) { int i, rank, nameID; e4_VertexImpl *v; if (storage == NULL) { return false; } if ((storage->GetPermissions() & E4_SPMODIFY) == 0) { return false; } nameID = storage->InternName(nm, true); i = GetCachedVertexIDByName(nameID, nth); if (i == E4_VERTEXNOTFOUND) { i = storage->DRV_VertexIDFromNthVertex(nodeID, nameID, nth, rank); if (i == E4_VERTEXNOTFOUND) { return false; } CacheVertexIDByName(nameID, nth, i); CacheVertexIDByRank(rank, i); CacheVertexRankByID(i, rank); } if (!storage->DRV_SetVertexByIndex(i, bytes, nbytes)) { return false; } storage->MarkUnstable(); storage->RecordTimeStamp(E4_ECMODVERTEX); if (storage->HasCallbacks(E4_ECMODVERTEX)) { v = storage->FindReferencedVertex(i); if (v != NULL) { storage->CauseEventInternal(E4_ECMODVERTEX, v, (void *) E4_ERMVMODVALUE); } } return true; } bool e4_NodeImpl::SetNthVertexToNode(const char *nm, int nth, int childID) { int i, rank, nameID; e4_VertexImpl *v; e4_NodeImpl *nip; bool wasdetached; if (storage == NULL) { return false; } if ((storage->GetPermissions() & E4_SPMODIFY) == 0) { return false; } nameID = storage->InternName(nm, true); i = GetCachedVertexIDByName(nameID, nth); if (i == E4_VERTEXNOTFOUND) { i = storage->DRV_VertexIDFromNthVertex(nodeID, nameID, nth, rank); if (i == E4_VERTEXNOTFOUND) { return false; } CacheVertexIDByName(nameID, nth, i); CacheVertexIDByRank(rank, i); CacheVertexRankByID(i, rank); } wasdetached = storage->DRV_IsDetachedNodeID(childID); if (!storage->DRV_SetVertexByIndexToNode(i, childID)) { return false; } storage->MarkUnstable(); if (wasdetached) { storage->RecordTimeStamp(E4_ECMODVERTEX | E4_ECATTNODE); } else { storage->RecordTimeStamp(E4_ECMODVERTEX); } if (storage->HasCallbacks(E4_ECMODVERTEX)) { v = storage->FindReferencedVertex(i); if (v != NULL) { storage->CauseEventInternal(E4_ECMODVERTEX, v, (void *) E4_ERMVMODVALUE); } } if (wasdetached && (storage->HasCallbacks(E4_ECATTNODE))) { nip = storage->FindReferencedNode(childID); if (nip != NULL) { storage->CauseEventInternal(E4_ECATTNODE, nip, NULL); nip->ClearFlags(E4_CBDETACHDELIVERED); } } return true; } bool e4_NodeImpl::SetVertexByRank(int rank, int value) { int i; e4_VertexImpl *v; if (storage == NULL) { return false; } if ((storage->GetPermissions() & E4_SPMODIFY) == 0) { return false; } i = GetCachedVertexIDByRank(rank); if (i == E4_VERTEXNOTFOUND) { i = storage->DRV_VertexIDFromRank(nodeID, rank); if (i == E4_VERTEXNOTFOUND) { return false; } CacheVertexIDByRank(rank, i); CacheVertexRankByID(i, rank); } if (!storage->DRV_SetVertexByIndex(i, value)) { return false; } storage->MarkUnstable(); storage->RecordTimeStamp(E4_ECMODVERTEX); if (storage->HasCallbacks(E4_ECMODVERTEX)) { v = storage->FindReferencedVertex(i); if (v != NULL) { storage->CauseEventInternal(E4_ECMODVERTEX, v, (void *) E4_ERMVMODVALUE); } } return true; } bool e4_NodeImpl::SetVertexByRank(int rank, double value) { int i; e4_VertexImpl *v; if (storage == NULL) { return false; } if ((storage->GetPermissions() & E4_SPMODIFY) == 0) { return false; } i = GetCachedVertexIDByRank(rank); if (i == E4_VERTEXNOTFOUND) { i = storage->DRV_VertexIDFromRank(nodeID, rank); if (i == E4_VERTEXNOTFOUND) { return false; } CacheVertexIDByRank(rank, i); CacheVertexRankByID(i, rank); } if (!storage->DRV_SetVertexByIndex(i, value)) { return false; } storage->MarkUnstable(); storage->RecordTimeStamp(E4_ECMODVERTEX); if (storage->HasCallbacks(E4_ECMODVERTEX)) { v = storage->FindReferencedVertex(i); if (v != NULL) { storage->CauseEventInternal(E4_ECMODVERTEX, v, (void *) E4_ERMVMODVALUE); } } return true; } bool e4_NodeImpl::SetVertexByRank(int rank, const char *value) { int i; e4_VertexImpl *v; if (storage == NULL) { return false; } if ((storage->GetPermissions() & E4_SPMODIFY) == 0) { return false; } i = GetCachedVertexIDByRank(rank); if (i == E4_VERTEXNOTFOUND) { i = storage->DRV_VertexIDFromRank(nodeID, rank); if (i == E4_VERTEXNOTFOUND) { return false; } CacheVertexIDByRank(rank, i); CacheVertexRankByID(i, rank); } if (!storage->DRV_SetVertexByIndex(i, value)) { return false; } storage->MarkUnstable(); storage->RecordTimeStamp(E4_ECMODVERTEX); if (storage->HasCallbacks(E4_ECMODVERTEX)) { v = storage->FindReferencedVertex(i); if (v != NULL) { storage->CauseEventInternal(E4_ECMODVERTEX, v, (void *) E4_ERMVMODVALUE); } } return true; } bool e4_NodeImpl::SetVertexByRank(int rank, const void *bytes, int nbytes) { int i; e4_VertexImpl *v; if (storage == NULL) { return false; } if ((storage->GetPermissions() & E4_SPMODIFY) == 0) { return false; } i = GetCachedVertexIDByRank(rank); if (i == E4_VERTEXNOTFOUND) { i = storage->DRV_VertexIDFromRank(nodeID, rank); if (i == E4_VERTEXNOTFOUND) { return false; } CacheVertexIDByRank(rank, i); CacheVertexRankByID(i, rank); } if (!storage->DRV_SetVertexByIndex(i, bytes, nbytes)) { return false; } storage->MarkUnstable(); storage->RecordTimeStamp(E4_ECMODVERTEX); if (storage->HasCallbacks(E4_ECMODVERTEX)) { v = storage->FindReferencedVertex(i); if (v != NULL) { storage->CauseEventInternal(E4_ECMODVERTEX, v, (void *) E4_ERMVMODVALUE); } } return true; } bool e4_NodeImpl::SetVertexByRankToNode(int rank, int childID) { int i; e4_VertexImpl *v; if (storage == NULL) { return false; } if ((storage->GetPermissions() & E4_SPMODIFY) == 0) { return false; } i = GetCachedVertexIDByRank(rank); if (i == E4_VERTEXNOTFOUND) { i = storage->DRV_VertexIDFromRank(nodeID, rank); if (i == E4_VERTEXNOTFOUND) { return false; } CacheVertexIDByRank(rank, i); CacheVertexRankByID(i, rank); } if (!storage->DRV_SetVertexByIndexToNode(i, childID)) { return false; } storage->MarkUnstable(); storage->RecordTimeStamp(E4_ECMODVERTEX); if (storage->HasCallbacks(E4_ECMODVERTEX)) { v = storage->FindReferencedVertex(i); if (v != NULL) { storage->CauseEventInternal(E4_ECMODVERTEX, v, (void *) E4_ERMVMODVALUE); } } return true; } /* * Add a vertex to this node at a given position. */ bool e4_NodeImpl::AddVertex(const char *nm, e4_InsertOrder io, int &rank, int value) { int i, j; if (storage == NULL) { return false; } if ((storage->GetPermissions() & E4_SPMODIFY) == 0) { return false; } i = storage->DRV_AddVertex(nodeID, io, rank); if (i == E4_VERTEXNOTCREATED) { return false; } storage->MarkUnstable(); j = storage->DRV_AddInt(value); storage->DRV_SetVertex(i, storage->InternName(nm, true), E4_VTINT, j); if (io != E4_IOLAST) { FlushCache(); } CacheVertexIDByRank(rank, i); CacheVertexRankByID(i, rank); storage->RecordTimeStamp(E4_ECMODNODE | E4_ECADDVERTEX); if (storage->HasCallbacks(E4_ECMODNODE)) { storage->CauseEventInternal(E4_ECMODNODE, this, (void *) E4_ERMNADDVERTEX); } return true; } bool e4_NodeImpl::AddVertex(const char *nm, e4_InsertOrder io, int &rank, double value) { int i, j; if (storage == NULL) { return false; } if ((storage->GetPermissions() & E4_SPMODIFY) == 0) { return false; } i = storage->DRV_AddVertex(nodeID, io, rank); if (i == E4_VERTEXNOTCREATED) { return false; } storage->MarkUnstable(); j = storage->DRV_AddDouble(value); storage->DRV_SetVertex(i, storage->InternName(nm, true), E4_VTDOUBLE, j); if (io != E4_IOLAST) { FlushCache(); } CacheVertexIDByRank(rank, i); CacheVertexRankByID(i, rank); storage->RecordTimeStamp(E4_ECMODNODE | E4_ECADDVERTEX); if (storage->HasCallbacks(E4_ECMODNODE)) { storage->CauseEventInternal(E4_ECMODNODE, this, (void *) E4_ERMNADDVERTEX); } return true; } bool e4_NodeImpl::AddVertex(const char *nm, e4_InsertOrder io, int &rank, const char *value) { int i, j; if (storage == NULL) { return false; } if ((storage->GetPermissions() & E4_SPMODIFY) == 0) { return false; } i = storage->DRV_AddVertex(nodeID, io, rank); if (i == E4_VERTEXNOTCREATED) { return false; } storage->MarkUnstable(); j = storage->DRV_AddString(value); storage->DRV_SetVertex(i, storage->InternName(nm, true), E4_VTSTRING, j); if (io != E4_IOLAST) { FlushCache(); } CacheVertexIDByRank(rank, i); CacheVertexRankByID(i, rank); storage->RecordTimeStamp(E4_ECMODNODE | E4_ECADDVERTEX); if (storage->HasCallbacks(E4_ECMODNODE)) { storage->CauseEventInternal(E4_ECMODNODE, this, (void *) E4_ERMNADDVERTEX); } return true; } bool e4_NodeImpl::AddVertex(const char *nm, e4_InsertOrder io, int &rank, const void *bytes, int nbytes) { int i, j; if (storage == NULL) { return false; } if ((storage->GetPermissions() & E4_SPMODIFY) == 0) { return false; } i = storage->DRV_AddVertex(nodeID, io, rank); if (i == E4_VERTEXNOTCREATED) { return false; } storage->MarkUnstable(); j = storage->DRV_AddBinary(bytes, nbytes); storage->DRV_SetVertex(i, storage->InternName(nm, true), E4_VTBINARY, j); if (io != E4_IOLAST) { FlushCache(); } CacheVertexIDByRank(rank, i); CacheVertexRankByID(i, rank); storage->RecordTimeStamp(E4_ECMODNODE); if (storage->HasCallbacks(E4_ECMODNODE)) { storage->CauseEventInternal(E4_ECMODNODE, this, (void *) E4_ERMNADDVERTEX); } return true; } bool e4_NodeImpl::AddVertexWithNode(const char *nm, e4_InsertOrder io, int &rank, int childID) { int i; if (storage == NULL) { return false; } if ((storage->GetPermissions() & E4_SPMODIFY) == 0) { return false; } i = storage->DRV_AddVertex(nodeID, io, rank); if (i == E4_VERTEXNOTCREATED) { return false; } storage->MarkUnstable(); if (storage->DRV_SetVertex(i, storage->InternName(nm, true), E4_VTNODE, childID)) { if (io != E4_IOLAST) { FlushCache(); } CacheVertexIDByRank(rank, i); CacheVertexRankByID(i, rank); storage->RecordTimeStamp(E4_ECMODNODE | E4_ECADDVERTEX | E4_ECADDNODE); if (storage->HasCallbacks(E4_ECMODNODE)) { storage->CauseEventInternal(E4_ECMODNODE, this, (void *) E4_ERMNADDVERTEX); } return true; } return false; } /* * Add a vertex and return an e4_VertexImpl for it in one operation. */ e4_VertexImpl * e4_NodeImpl::AddVertexRef(const char *nm, e4_InsertOrder io, int &rank, int value) { int i, j; e4_VertexImpl *v; if (storage == NULL) { return NULL; } if ((storage->GetPermissions() & E4_SPMODIFY) == 0) { return false; } i = storage->DRV_AddVertex(nodeID, io, rank); if (i == E4_VERTEXNOTCREATED) { return NULL; } storage->MarkUnstable(); j = storage->DRV_AddInt(value); storage->DRV_SetVertex(i, storage->InternName(nm, true), E4_VTINT, j); if (io != E4_IOLAST) { FlushCache(); } CacheVertexIDByRank(rank, i); CacheVertexRankByID(i, rank); v = storage->GetVertex(i); v->IncrRefCount(); storage->RecordTimeStamp(E4_ECMODNODE | E4_ECADDVERTEX); if (storage->HasCallbacks(E4_ECADDVERTEX)) { storage->CauseEventInternal(E4_ECADDVERTEX, v, NULL); } if (storage->HasCallbacks(E4_ECMODNODE)) { storage->CauseEventInternal(E4_ECMODNODE, this, (void *) E4_ERMNADDVERTEX); } return v; } e4_VertexImpl * e4_NodeImpl::AddVertexRef(const char *nm, e4_InsertOrder io, int &rank, double value) { int i, j; e4_VertexImpl *v; if (storage == NULL) { return NULL; } if ((storage->GetPermissions() & E4_SPMODIFY) == 0) { return false; } i = storage->DRV_AddVertex(nodeID, io, rank); if (i == E4_VERTEXNOTCREATED) { return NULL; } storage->MarkUnstable(); j = storage->DRV_AddDouble(value); storage->DRV_SetVertex(i, storage->InternName(nm, true), E4_VTDOUBLE, j); if (io != E4_IOLAST) { FlushCache(); } CacheVertexIDByRank(rank, i); CacheVertexRankByID(i, rank); v = storage->GetVertex(i); v->IncrRefCount(); storage->RecordTimeStamp(E4_ECMODNODE | E4_ECADDVERTEX); if (storage->HasCallbacks(E4_ECADDVERTEX)) { storage->CauseEventInternal(E4_ECADDVERTEX, v, NULL); } if (storage->HasCallbacks(E4_ECMODNODE)) { storage->CauseEventInternal(E4_ECMODNODE, this, (void *) E4_ERMNADDVERTEX); } return v; } e4_VertexImpl * e4_NodeImpl::AddVertexRef(const char *nm, e4_InsertOrder io, int &rank, const char *value) { int i, j; e4_VertexImpl *v; if (storage == NULL) { return NULL; } if ((storage->GetPermissions() & E4_SPMODIFY) == 0) { return false; } i = storage->DRV_AddVertex(nodeID, io, rank); if (i == E4_VERTEXNOTCREATED) { return NULL; } storage->MarkUnstable(); j = storage->DRV_AddString(value); storage->DRV_SetVertex(i, storage->InternName(nm, true), E4_VTSTRING, j); if (io != E4_IOLAST) { FlushCache(); } CacheVertexIDByRank(rank, i); CacheVertexRankByID(i, rank); v = storage->GetVertex(i); v->IncrRefCount(); storage->RecordTimeStamp(E4_ECMODNODE | E4_ECADDVERTEX); if (storage->HasCallbacks(E4_ECADDVERTEX)) { storage->CauseEventInternal(E4_ECADDVERTEX, v, NULL); } if (storage->HasCallbacks(E4_ECMODNODE)) { storage->CauseEventInternal(E4_ECMODNODE, this, (void *) E4_ERMNADDVERTEX); } return v; } e4_VertexImpl * e4_NodeImpl::AddVertexRef(const char *nm, e4_InsertOrder io, int &rank, const void *bytes, int nbytes) { int i, j; e4_VertexImpl *v; if (storage == NULL) { return NULL; } if ((storage->GetPermissions() & E4_SPMODIFY) == 0) { return false; } i = storage->DRV_AddVertex(nodeID, io, rank); if (i == E4_VERTEXNOTCREATED) { return NULL; } storage->MarkUnstable(); j = storage->DRV_AddBinary(bytes, nbytes); storage->DRV_SetVertex(i, storage->InternName(nm, true), E4_VTBINARY, j); if (io != E4_IOLAST) { FlushCache(); } CacheVertexIDByRank(rank, i); CacheVertexRankByID(i, rank); v = storage->GetVertex(i); v->IncrRefCount(); storage->RecordTimeStamp(E4_ECMODNODE | E4_ECADDVERTEX); if (storage->HasCallbacks(E4_ECADDVERTEX)) { storage->CauseEventInternal(E4_ECADDVERTEX, v, NULL); } if (storage->HasCallbacks(E4_ECMODNODE)) { storage->CauseEventInternal(E4_ECMODNODE, this, (void *) E4_ERMNADDVERTEX); } return v; } e4_VertexImpl * e4_NodeImpl::AddVertexRefWithNode(const char *nm, e4_InsertOrder io, int &rank, int childID) { int i; e4_VertexImpl *v = NULL; if (storage == NULL) { return NULL; } if ((storage->GetPermissions() & E4_SPMODIFY) == 0) { return false; } i = storage->DRV_AddVertex(nodeID, io, rank); if (i == E4_VERTEXNOTCREATED) { return NULL; } storage->MarkUnstable(); if (storage->DRV_SetVertex(i, storage->InternName(nm, true), E4_VTNODE, childID)) { if (io != E4_IOLAST) { FlushCache(); } CacheVertexIDByRank(rank, i); CacheVertexRankByID(i, rank); v = storage->GetVertex(i); v->IncrRefCount(); storage->RecordTimeStamp(E4_ECMODNODE | E4_ECADDVERTEX); if (storage->HasCallbacks(E4_ECADDVERTEX)) { storage->CauseEventInternal(E4_ECADDVERTEX, v, NULL); } if (storage->HasCallbacks(E4_ECMODNODE)) { storage->CauseEventInternal(E4_ECMODNODE, this, (void *) E4_ERMNADDVERTEX); } } return v; } e4_VertexImpl * e4_NodeImpl::AddNodeRef(const char *nm, e4_InsertOrder io, int &rank, e4_NodeImpl *&node) { int i, hisNodeID; e4_VertexImpl *v = NULL; if (storage == NULL) { return NULL; } if ((storage->GetPermissions() & E4_SPMODIFY) == 0) { return NULL; } i = storage->DRV_AddVertex(nodeID, io, rank); if (i == E4_VERTEXNOTCREATED) { return NULL; } storage->MarkUnstable(); hisNodeID = storage->DRV_ReserveNodeID(); if (storage->DRV_SetVertex(i, storage->InternName(nm, true), E4_VTNODE, hisNodeID)) { node = storage->FindOrCreateNode(hisNodeID); if (node == NULL) { return NULL; } node->IncrRefCount(); if (io != E4_IOLAST) { FlushCache(); } CacheVertexIDByRank(rank, i); CacheVertexRankByID(i, rank); v = storage->GetVertex(i); if (v == NULL) { return NULL; } v->IncrRefCount(); storage->RecordTimeStamp(E4_ECMODNODE | E4_ECADDVERTEX | E4_ECADDNODE); if (storage->HasCallbacks(E4_ECADDNODE)) { storage->CauseEventInternal(E4_ECADDNODE, node, NULL); } if (storage->HasCallbacks(E4_ECADDVERTEX)) { storage->CauseEventInternal(E4_ECADDVERTEX, v, NULL); } if (storage->HasCallbacks(E4_ECMODNODE)) { storage->CauseEventInternal(E4_ECMODNODE, this, (void *) E4_ERMNADDVERTEX); } } return v; } /* * Get a value from a vertex: */ bool e4_NodeImpl::GetNthVertex(const char *nm, int nth, e4_ValueImpl *&v) { int i, rank, nameID; if (storage == NULL) { return false; } nameID = storage->InternName(nm, false); if (nameID == E4_NEXTNONE) { return false; } i = GetCachedVertexIDByName(nameID, nth); if (i == E4_VERTEXNOTFOUND) { i = storage->DRV_VertexIDFromNthVertex(nodeID, nameID, nth, rank); CacheVertexIDByName(nameID, nth, i); CacheVertexIDByRank(rank, i); CacheVertexRankByID(i, rank); } if ((i == E4_VERTEXNOTFOUND) || (storage->DRV_GetVertexByIndex(i, v) == false)) { return false; } return true; } bool e4_NodeImpl::GetNthVertex(const char *nm, int nth, e4_NodeImpl *&n) { int i, rank, nameID; if (storage == NULL) { return false; } nameID = storage->InternName(nm, false); if (nameID == E4_NEXTNONE) { return false; } i = GetCachedVertexIDByName(nameID, nth); if (i == E4_VERTEXNOTFOUND) { i = storage->DRV_VertexIDFromNthVertex(nodeID, nameID, nth, rank); CacheVertexIDByName(nameID, nth, i); CacheVertexIDByRank(rank, i); CacheVertexRankByID(i, rank); } if ((i == E4_VERTEXNOTFOUND) || (storage->DRV_GetVertexByIndex(i, n) == false)) { return false; } return true; } bool e4_NodeImpl::GetNthVertex(const char *nm, int nth, int &value) { int i, rank, nameID; if (storage == NULL) { return false; } nameID = storage->InternName(nm, false); if (nameID == E4_NEXTNONE) { return false; } i = GetCachedVertexIDByName(nameID, nth); if (i == E4_VERTEXNOTFOUND) { i = storage->DRV_VertexIDFromNthVertex(nodeID, nameID, nth, rank); CacheVertexIDByName(nameID, nth, i); CacheVertexIDByRank(rank, i); CacheVertexRankByID(i, rank); } if ((i == E4_VERTEXNOTFOUND) || (storage->DRV_GetVertexByIndex(i, value) == false)) { return false; } return true; } bool e4_NodeImpl::GetNthVertex(const char *nm, int nth, double &value) { int i, rank, nameID; if (storage == NULL) { return false; } nameID = storage->InternName(nm, false); if (nameID == E4_NEXTNONE) { return false; } i = GetCachedVertexIDByName(nameID, nth); if (i == E4_VERTEXNOTFOUND) { i = storage->DRV_VertexIDFromNthVertex(nodeID, nameID, nth, rank); CacheVertexIDByName(nameID, nth, i); CacheVertexIDByRank(rank, i); CacheVertexRankByID(i, rank); } if ((i == E4_VERTEXNOTFOUND) || (storage->DRV_GetVertexByIndex(i, value) == false)) { return false; } return true; } bool e4_NodeImpl::GetNthVertex(const char *nm, int nth, const char *&value) { int i, rank, nameID; if (storage == NULL) { return false; } nameID = storage->InternName(nm, false); if (nameID == E4_NEXTNONE) { return false; } i = GetCachedVertexIDByName(nameID, nth); if (i == E4_VERTEXNOTFOUND) { i = storage->DRV_VertexIDFromNthVertex(nodeID, nameID, nth, rank); CacheVertexIDByName(nameID, nth, i); CacheVertexIDByRank(rank, i); CacheVertexRankByID(i, rank); } if ((i == E4_VERTEXNOTFOUND) || (storage->DRV_GetVertexByIndex(i, value) == false)) { return false; } return true; } bool e4_NodeImpl::GetNthVertex(const char *nm, int nth, const void *&bytes, int &nbytes) { int i, rank, nameID; if (storage == NULL) { return false; } nameID = storage->InternName(nm, false); if (nameID == E4_NEXTNONE) { return false; } i = GetCachedVertexIDByName(nameID, nth); if (i == E4_VERTEXNOTFOUND) { i = storage->DRV_VertexIDFromNthVertex(nodeID, nameID, nth, rank); CacheVertexIDByName(nameID, nth, i); CacheVertexIDByRank(rank, i); CacheVertexRankByID(i, rank); } if ((i == E4_VERTEXNOTFOUND) || (storage->DRV_GetVertexByIndex(i, bytes, nbytes) == false)) { return false; } return true; } bool e4_NodeImpl::GetVertexByRank(int rank, e4_ValueImpl *&value) { int i; if (storage == NULL) { return false; } i = GetCachedVertexIDByRank(rank); if (i == E4_VERTEXNOTFOUND) { i = storage->DRV_VertexIDFromRank(nodeID, rank); CacheVertexIDByRank(rank, i); CacheVertexRankByID(i, rank); } if ((i == E4_VERTEXNOTFOUND) || (storage->DRV_GetVertexByIndex(i, value) == false)) { return false; } return true; } bool e4_NodeImpl::GetVertexByRank(int rank, e4_NodeImpl *&value) { int i; if (storage == NULL) { return false; } i = GetCachedVertexIDByRank(rank); if (i == E4_VERTEXNOTFOUND) { i = storage->DRV_VertexIDFromRank(nodeID, rank); CacheVertexIDByRank(rank, i); CacheVertexRankByID(i, rank); } if ((i == E4_VERTEXNOTFOUND) || (storage->DRV_GetVertexByIndex(i, value) == false)) { return false; } return true; } bool e4_NodeImpl::GetVertexByRank(int rank, int &value) { int i; if (storage == NULL) { return false; } i = GetCachedVertexIDByRank(rank); if (i == E4_VERTEXNOTFOUND) { i = storage->DRV_VertexIDFromRank(nodeID, rank); CacheVertexIDByRank(rank, i); CacheVertexRankByID(i, rank); } if ((i == E4_VERTEXNOTFOUND) || (storage->DRV_GetVertexByIndex(i, value) == false)) { return false; } return true; } bool e4_NodeImpl::GetVertexByRank(int rank, double &value) { int i; if (storage == NULL) { return false; } i = GetCachedVertexIDByRank(rank); if (i == E4_VERTEXNOTFOUND) { i = storage->DRV_VertexIDFromRank(nodeID, rank); CacheVertexIDByRank(rank, i); CacheVertexRankByID(i, rank); } if ((i == E4_VERTEXNOTFOUND) || (storage->DRV_GetVertexByIndex(i, value) == false)) { return false; } return true; } bool e4_NodeImpl::GetVertexByRank(int rank, const char *&value) { int i; if (storage == NULL) { return false; } i = GetCachedVertexIDByRank(rank); if (i == E4_VERTEXNOTFOUND) { i = storage->DRV_VertexIDFromRank(nodeID, rank); CacheVertexIDByRank(rank, i); CacheVertexRankByID(i, rank); } if ((i == E4_VERTEXNOTFOUND) || (storage->DRV_GetVertexByIndex(i, value) == false)) { return false; } return true; } bool e4_NodeImpl::GetVertexByRank(int rank, const void *&bytes, int &nbytes) { int i; if (storage == NULL) { return false; } i = GetCachedVertexIDByRank(rank); if (i == E4_VERTEXNOTFOUND) { i = storage->DRV_VertexIDFromRank(nodeID, rank); CacheVertexIDByRank(rank, i); CacheVertexRankByID(i, rank); } if ((i == E4_VERTEXNOTFOUND) || (storage->DRV_GetVertexByIndex(i, bytes, nbytes) == false)) { return false; } return true; } e4_VertexType e4_NodeImpl::VertexType(const char *nm, int nth) { int i, rank, nameID; if (storage == NULL) { return E4_VTUNKNOWN; } nameID = storage->InternName(nm, false); if (nameID == E4_NEXTNONE) { return E4_VTUNKNOWN; } i = GetCachedVertexIDByName(nameID, nth); if (i == E4_VERTEXNOTFOUND) { i = storage->DRV_VertexIDFromNthVertex(nodeID, nameID, nth, rank); if (i == E4_VERTEXNOTFOUND) { return E4_VTUNKNOWN; } CacheVertexIDByName(nameID, nth, i); CacheVertexIDByRank(rank, i); CacheVertexRankByID(i, rank); } return storage->DRV_VertexTypeFromVertexID(i); } e4_VertexType e4_NodeImpl::VertexTypeByRank(int rank) { int i; if (storage == NULL) { return E4_VTUNKNOWN; } i = GetCachedVertexIDByRank(rank); if (i == E4_VERTEXNOTFOUND) { i = storage->DRV_VertexIDFromRank(nodeID, rank); if (i == E4_VERTEXNOTFOUND) { return E4_VTUNKNOWN; } CacheVertexIDByRank(rank, i); CacheVertexRankByID(i, rank); } return storage->DRV_VertexTypeFromVertexID(i); } const char * e4_NodeImpl::VertexName(int rank) { int i; if (storage == NULL) { return NULL; } i = GetCachedVertexIDByRank(rank); if (i == E4_VERTEXNOTFOUND) { i = storage->DRV_VertexIDFromRank(nodeID, rank); if (i == E4_VERTEXNOTFOUND) { return NULL; } CacheVertexIDByRank(rank, i); CacheVertexRankByID(i, rank); } return storage->DRV_VertexNameFromVertexID(i); } /* * Rename a vertex identified by rank. */ bool e4_NodeImpl::RenameVertex(int rank, const char *newname) { int i; int nameID; e4_VertexImpl *v; if (storage == NULL) { return false; } if ((storage->GetPermissions() & E4_SPMODIFY) == 0) { return false; } nameID = storage->InternName(newname, true); if (nameID == E4_NEXTNONE) { return false; } i = GetCachedVertexIDByRank(rank); if (i == E4_VERTEXNOTFOUND) { i = storage->DRV_VertexIDFromRank(nodeID, rank); if (i == E4_VERTEXNOTFOUND) { return false; } } if (!storage->DRV_RenameVertexByVertexID(i, nameID)) { return false; } storage->MarkUnstable(); FlushCache(); storage->RecordTimeStamp(E4_ECMODNODE | E4_ECMODVERTEX); if (storage->HasCallbacks(E4_ECMODNODE)) { storage->CauseEventInternal(E4_ECMODNODE, this, (void *) E4_ERMNRENVERTEX); } if (storage->HasCallbacks(E4_ECMODVERTEX)) { v = storage->FindReferencedVertex(i); if (v != NULL) { storage->CauseEventInternal(E4_ECMODVERTEX, v, (void *) E4_ERMVRENAME); } } CacheVertexIDByRank(rank, i); CacheVertexRankByID(i, rank); return true; } /* * Compute the rank of the nth vertex with a given name. */ int e4_NodeImpl::VertexRank(const char *nm, int nth) { int i, nameID; int rank = E4_VERTEXNOTFOUND; if (storage == NULL) { return E4_VERTEXNOTFOUND; } nameID = storage->InternName(nm, false); if (nameID == E4_NEXTNONE) { return E4_VERTEXNOTFOUND; } i = GetCachedVertexIDByName(nameID, nth); if (i == E4_VERTEXNOTFOUND) { i = storage->DRV_VertexIDFromNthVertex(nodeID, nameID, nth, rank); if (i == E4_VERTEXNOTFOUND) { return E4_VERTEXNOTFOUND; } CacheVertexIDByName(nameID, nth, i); CacheVertexIDByRank(rank, i); CacheVertexRankByID(i, rank); } if (rank == E4_VERTEXNOTFOUND) { rank = GetCachedVertexRankByID(i); if (rank == E4_VERTEXNOTFOUND) { i = storage->DRV_VertexIDFromNthVertex(nodeID, nameID, nth, rank); if (i == E4_VERTEXNOTFOUND) { return E4_VERTEXNOTFOUND; } CacheVertexIDByName(nameID, nth, i); CacheVertexIDByRank(rank, i); CacheVertexRankByID(i, rank); } } return rank; } /* * Get the name of the ith vertex containing this node in its nth parent node. */ const char * e4_NodeImpl::GetNameInParent(int nth, int ith) const { int parentID; int vertexID; if (storage == NULL) { return NULL; } parentID = storage->DRV_GetParentNodeID(nodeID, nth); if (parentID == E4_NODENOTFOUND) { return NULL; } vertexID = storage->DRV_GetVertexIDInParent(parentID, nodeID, ith); if (vertexID == E4_VERTEXNOTFOUND) { return NULL; } return storage->DRV_VertexNameFromVertexID(vertexID); } /* * Get the name of the ith vertex containing this node in the parent node * p. */ const char * e4_NodeImpl::GetNameInParent(e4_NodeImpl *p, int ith) const { int vertexID; if ((storage == NULL) || (p->storage != storage) || (!storage->DRV_IsParentID(p->nodeID, nodeID))) { return NULL; } vertexID = storage->DRV_GetVertexIDInParent(p->nodeID, nodeID, ith); if (vertexID == E4_VERTEXNOTFOUND) { return NULL; } return storage->DRV_VertexNameFromVertexID(vertexID); } /* * Get the rank of the ith vertex containing this node in its nth parent node. */ int e4_NodeImpl::GetRankInParent(int nth, int ith) const { int parentID, rank; if (storage == NULL) { return E4_NODENOTFOUND; } parentID = storage->DRV_GetParentNodeID(nodeID, nth); if (parentID == E4_NODENOTFOUND) { return E4_NODENOTFOUND; } rank = storage->DRV_GetRankOfChildNode(parentID, nodeID, ith); if (rank == E4_VERTEXNOTFOUND) { return E4_NODENOTFOUND; } return rank; } /* * Get the rank of the ith vertex in the parent node p of this node whose * value is this node. */ int e4_NodeImpl::GetRankInParent(e4_NodeImpl *p, int ith) const { int rank; if ((storage == NULL) || (storage != p->storage) || (!storage->DRV_IsParentID(p->nodeID, nodeID))) { return E4_NODENOTFOUND; } rank = storage->DRV_GetRankOfChildNode(p->nodeID, nodeID, ith); if (rank == E4_VERTEXNOTFOUND) { return E4_NODENOTFOUND; } return rank; } /* * Detach the nth vertex with the given name in this node. */ bool e4_NodeImpl::DetachVertex(const char *nm, int nth) { int nameID, rank, i, childID, mask; e4_VertexImpl *vp; e4_NodeImpl *np; bool detachedNode = false; bool hasNodeValue = false; if (storage == NULL) { return false; } if ((storage->GetPermissions() & E4_SPMODIFY) == 0) { return false; } nameID = storage->InternName(nm, false); if (nameID == E4_NEXTNONE) { return false; } i = GetCachedVertexIDByName(nameID, nth); if (i == E4_VERTEXNOTFOUND) { i = storage->DRV_VertexIDFromNthVertex(nodeID, nameID, nth, rank); if (i == E4_VERTEXNOTFOUND) { return false; } } FlushCache(); if (storage->DRV_VertexTypeFromVertexID(i) == E4_VTNODE) { (void) storage->DRV_GetRawValue(i, childID); hasNodeValue = true; } if (!storage->DRV_DetachVertexByID(i)) { return false; } storage->MarkUnstable(); mask = E4_ECMODNODE | E4_ECDETVERTEX; if ((hasNodeValue) && (storage->DRV_IsDetachedNodeID(childID))) { mask |= E4_ECDETNODE; detachedNode = true; } storage->RecordTimeStamp(mask); if (storage->HasCallbacks(E4_ECMODNODE)) { storage->CauseEventInternal(E4_ECMODNODE, this, (void *) E4_ERMNDETVERTEX); } if (storage->HasCallbacks(E4_ECDETVERTEX)) { vp = storage->FindReferencedVertex(i); if (vp != NULL) { storage->CauseEventInternal(E4_ECDETVERTEX, vp, NULL); vp->SetFlags(E4_CBDETACHDELIVERED); } } if (detachedNode && (storage->HasCallbacks(E4_ECDETNODE))) { np = storage->FindReferencedNode(childID); if ((np != NULL) && (!np->HasFlags(E4_CBDETACHDELIVERED))) { storage->CauseEventInternal(E4_ECDETNODE, np, NULL); np->SetFlags(E4_CBDETACHDELIVERED); } } return true; } /* * Detach the vertex identified by the given rank. */ bool e4_NodeImpl::DetachVertexByRank(int rank) { int i, childID, mask; e4_VertexImpl *vp; e4_NodeImpl *np; bool detachedNode = false; bool hasNodeValue = false; if (storage == NULL) { return false; } if ((storage->GetPermissions() & E4_SPMODIFY) == 0) { return false; } i = GetCachedVertexIDByRank(rank); if (i == E4_VERTEXNOTFOUND) { i = storage->DRV_VertexIDFromRank(nodeID, rank); if (i == E4_VERTEXNOTFOUND) { return false; } } FlushCache(); if (storage->DRV_VertexTypeFromVertexID(i) == E4_VTNODE) { (void) storage->DRV_GetRawValue(i, childID); hasNodeValue = true; } if (!storage->DRV_DetachVertexByID(i)) { return false; } storage->MarkUnstable(); mask = E4_ECMODNODE | E4_ECDETVERTEX; if ((hasNodeValue) && (storage->DRV_IsDetachedNodeID(childID))) { mask |= E4_ECDETNODE; detachedNode = true; } storage->RecordTimeStamp(mask); if (storage->HasCallbacks(E4_ECMODNODE)) { storage->CauseEventInternal(E4_ECMODNODE, this, (void *) E4_ERMNDETVERTEX); } if (storage->HasCallbacks(E4_ECDETVERTEX)) { vp = storage->FindReferencedVertex(i); if ((vp != NULL) && (!vp->HasFlags(E4_CBDETACHDELIVERED))) { storage->CauseEventInternal(E4_ECDETVERTEX, vp, NULL); vp->SetFlags(E4_CBDETACHDELIVERED); } } if (detachedNode && (storage->HasCallbacks(E4_ECDETNODE))) { np = storage->FindReferencedNode(childID); if ((np != NULL) && (!np->HasFlags(E4_CBDETACHDELIVERED))) { storage->CauseEventInternal(E4_ECDETNODE, np, NULL); np->SetFlags(E4_CBDETACHDELIVERED); } } return true; } /* * Detach the first vertex whose value is the given child node. */ bool e4_NodeImpl::DetachFirstVertexWithNode(e4_NodeImpl *childImpl) { e4_VertexImpl *vp; int i; if ((storage == NULL) || (childImpl == NULL) || (childImpl->storage != storage)) { return false; } if ((storage->GetPermissions() & E4_SPMODIFY) == 0) { return false; } i = storage->DRV_GetVertexIDInParent(nodeID, childImpl->nodeID, 1); if (i == E4_VERTEXNOTFOUND) { return false; } if (!storage->DRV_DetachVertexByID(i)) { return false; } storage->MarkUnstable(); FlushCache(); storage->RecordTimeStamp(E4_ECMODNODE | E4_ECDETVERTEX); if (storage->HasCallbacks(E4_ECMODNODE)) { storage->CauseEventInternal(E4_ECMODNODE, this, (void *) E4_ERMNDETVERTEX); } if (storage->HasCallbacks(E4_ECDETVERTEX)) { vp = storage->FindReferencedVertex(i); if ((vp != NULL) && (!vp->HasFlags(E4_CBDETACHDELIVERED))) { storage->CauseEventInternal(E4_ECDETVERTEX, vp, NULL); vp->SetFlags(E4_CBDETACHDELIVERED); } } return true; } /* * Get an e4_VertexImpl for a vertex specified by rank. */ e4_VertexImpl * e4_NodeImpl::GetVertexRefByRank(int rank) { int i; if (storage == NULL) { return NULL; } i = GetCachedVertexIDByRank(rank); if (i == E4_VERTEXNOTFOUND) { i = storage->DRV_VertexIDFromRank(nodeID, rank); if (i == E4_VERTEXNOTFOUND) { return NULL; } CacheVertexIDByRank(rank, i); CacheVertexRankByID(i, rank); } return storage->GetVertex(i); } /* * Get an e4_VertexImpl from a vertex specified by name and nth. */ e4_VertexImpl * e4_NodeImpl::GetVertexRef(const char *nm, int nth) { int i, rank, nameID; if (storage == NULL) { return NULL; } nameID = storage->InternName(nm, false); if (nameID == E4_NEXTNONE) { return NULL; } i = GetCachedVertexIDByName(nameID, nth); if (i == E4_VERTEXNOTFOUND) { i = storage->DRV_VertexIDFromNthVertex(nodeID, nameID, nth, rank); if (i == E4_VERTEXNOTFOUND) { return NULL; } CacheVertexIDByName(nameID, nth, i); CacheVertexIDByRank(rank, i); CacheVertexRankByID(i, rank); } return storage->GetVertex(i); } /* * Move a vertex identified by a vertex ID into the rank given in this * node. */ bool e4_NodeImpl::MoveVertex(int vertexID, e4_InsertOrder order, int rank) { if ((storage == NULL) || ((storage->GetPermissions() & E4_SPMODIFY) == 0)) { return false; } return storage->MoveVertex(nodeID, vertexID, order, rank); } /* * How many vertices are currently in this node? */ int e4_NodeImpl::VertexCount() const { if (storage == NULL) { return 0; } return storage->DRV_VertexCountFromNodeID(nodeID); } /* * How many vertices in this node have the given name? */ int e4_NodeImpl::VertexCountWithName(const char *nm) const { int nameID; if (storage == NULL) { return 0; } nameID = storage->InternName(nm, false); if (nameID == E4_NEXTNONE) { return 0; } return storage->DRV_VertexCountWithNameIDFromNodeID(nodeID, E4_VERTEXNOTFOUND, nameID); } /* * How many vertices in this node have the given type? */ int e4_NodeImpl::VertexCountWithType(e4_VertexType tp) const { if (storage == NULL) { return 0; } return storage->DRV_VertexCountWithTypeFromNodeID(nodeID, E4_VERTEXNOTFOUND, tp); } /* * How many vertices in this node have the given value? */ int e4_NodeImpl::VertexCountWithValue(const e4_Value &v) const { if (storage == NULL) { return 0; } return storage->DRV_VertexCountWithValueFromNodeID(nodeID, E4_VERTEXNOTFOUND, v); } /* * Set a vertex to a new node: */ e4_NodeImpl * e4_NodeImpl::SetNode(const char *nm) { return SetNthNode(nm, 1); } /* * Does a vertex with the given name exist? */ bool e4_NodeImpl::Exists(const char *nm, int nth) { return (VertexRank(nm, nth) != E4_VERTEXNOTFOUND) ? true : false; } /* * Get the nth parent node: */ e4_NodeImpl * e4_NodeImpl::GetParent(int nth) const { if (storage == NULL) { return NULL; } return storage->DRV_GetParentNode(nodeID, nth); } /* * Retrieve the nth vertex in the given parent node p whose value is this node. */ e4_VertexImpl * e4_NodeImpl::GetVertexRefFromParent(e4_NodeImpl *pp, int nth) const { if ((storage == NULL) || (pp == NULL) || (pp->storage != storage)) { return NULL; } return storage->DRV_GetVertexRefFromParent(pp->nodeID, nodeID, nth); } /* * Retrieve the nth vertex in the ith parent node whose value is this node. */ e4_VertexImpl * e4_NodeImpl::GetVertexRefFromParent(int i, int nth) const { if (storage == NULL) { return NULL; } return storage->DRV_GetVertexRefFromIthParent(i, nodeID, nth); } /* * How many parents does this node have? */ int e4_NodeImpl::ParentCount() const { if (storage == NULL) { return E4_NODENOTFOUND; } return storage->DRV_ParentCount(nodeID); } /* * In how many vertices is this node the value? */ int e4_NodeImpl::OccurrenceCount() const { if (storage == NULL) { return E4_NODENOTFOUND; } return storage->DRV_OccurrenceCount(nodeID); } /* * How many vertices in this parent have this node as the value? */ int e4_NodeImpl::OccurrenceCount(int parentID) const { if (storage == NULL) { return E4_NODENOTFOUND; } return storage->DRV_OccurrenceCount(nodeID, parentID); } /* * What is the rank of the given parent in the list of parents * of this node? */ int e4_NodeImpl::ParentRank(int parentID) const { if (storage == NULL) { return E4_NODENOTFOUND; } return storage->DRV_ParentRank(nodeID, parentID); } /* * Retrieve the storage containing this node: */ e4_StorageImpl * e4_NodeImpl::GetStorage() const { return storage; } /* * Is this node the root? */ bool e4_NodeImpl::IsRoot() const { if (storage == NULL) { return false; } return (storage->GetRootNodeID() == nodeID) ? true : false; } /* * Retrieve an ID which uniquely identifies this node within its * containing storage. */ int e4_NodeImpl::GetUniqueID() const { if (storage == NULL) { return E4_NODENOTFOUND; } return nodeID; } /* * Detach this node from all vertices for which it is the value. */ bool e4_NodeImpl::Detach() { e4_NodeImpl *p; e4_VertexImpl *v; int i, l, mask; int *pids; bool hasCB; if (storage == NULL) { return false; } if ((storage->GetPermissions() & E4_SPMODIFY) == 0) { return false; } /* * Flush the cache for all referenced parents, because this is * an incompatible change. */ l = ParentCount(); if (l == 0) { return true; } for (i = 0, pids = new int[l]; i < l; i++) { pids[i] = storage->DRV_GetParentNodeID(nodeID, i+1); } if (!storage->DRV_DetachNodeByID(nodeID)) { delete[] pids; return false; } storage->MarkUnstable(); /* * Deliver callbacks: * * - Deliver a detach node callback for this node. * - Deliver detach vertex callbacks for all referenced vertices * whose value is this node that were previously attached. * - Deliver modify node callbacks for all referenced nodes that * previously used to contain vertices whose value is this node. */ mask = E4_ECDETNODE | E4_ECDETVERTEX; if (l > 0) { mask |= E4_ECMODNODE; } storage->RecordTimeStamp(mask); if (storage->HasCallbacks(E4_ECDETNODE)) { storage->CauseEventInternal(E4_ECDETNODE, this, NULL); SetFlags(E4_CBDETACHDELIVERED); } if (storage->HasCallbacks(E4_ECDETVERTEX)) { for (i = storage->DRV_GetFirstDetachedVertexIDWithNodeID(nodeID); i != E4_NEXTNONE; i = storage->DRV_GetNextDetachedVertexIDAfter(i)) { v = storage->FindReferencedVertex(i); if ((v != NULL) && (!v->HasFlags(E4_CBDETACHDELIVERED))) { storage->CauseEventInternal(E4_ECDETVERTEX, v, NULL); v->SetFlags(E4_CBDETACHDELIVERED); } } } hasCB = storage->HasCallbacks(E4_ECMODNODE); for (i = 0; i < l; i++) { p = storage->FindReferencedNode(pids[i]); if (p != NULL) { p->FlushCache(); if (hasCB) { storage->CauseEventInternal(E4_ECMODNODE, p, (void *) E4_ERMNDETVERTEX); } } } delete[] pids; return true; } /* * Is this node detached? */ bool e4_NodeImpl::IsDetached() const { if (storage == NULL) { return true; } return storage->DRV_IsDetachedNodeID(nodeID); } /* * Is this node valid? */ bool e4_NodeImpl::IsValid() const { if (storage == NULL) { return false; } return (storage->IsValid() && storage->DRV_IsLegalNodeID(nodeID)); } /* * Retrieve the ID of the first and last vertex in this node. */ int e4_NodeImpl::GetFirstVertexID() const { if (storage == NULL) { return E4_VERTEXNOTFOUND; } return storage->DRV_GetFirstVertexID(nodeID); } int e4_NodeImpl::GetLastVertexID() const { if (storage == NULL) { return E4_VERTEXNOTFOUND; } return storage->DRV_GetLastVertexID(nodeID); } /* * Retrieve the node ID for use by the containing e4_StorageImpl. */ int e4_NodeImpl::GetNodeID() const { return nodeID; } /* * Set the storage field of this node. */ void e4_NodeImpl::SetStorage(e4_StorageImpl *newstorage) { storage = newstorage; } /* * Get/Set the user data associated with this node. */ bool e4_NodeImpl::GetUserData(int &userData) const { if (storage == NULL) { return false; } return storage->DRV_GetNodeUserData(nodeID, userData); } bool e4_NodeImpl::SetUserData(int userData) { if (storage == NULL) { return false; } if ((storage->GetPermissions() & E4_SPMODIFY) == 0) { return false; } if (storage->DRV_SetNodeUserData(nodeID, userData)) { storage->MarkUnstable(); storage->RecordTimeStamp(E4_ECMODNODE); if (storage->HasCallbacks(E4_ECMODNODE)) { storage->CauseEventInternal(E4_ECMODNODE, this, (void *) E4_ERMNMODUSERDATA); } return true; } return false; } /* * Get/Set the user data of a contained vertex: */ bool e4_NodeImpl::SetVertexUserData(const char *nm, int nth, int userData) { int vertexID, nameID, rank; e4_VertexImpl *vp; if (storage == NULL) { return false; } if ((storage->GetPermissions() & E4_SPMODIFY) == 0) { return false; } nameID = storage->InternName(nm, false); if (nameID == E4_NEXTNONE) { return false; } vertexID = GetCachedVertexIDByName(nameID, nth); if (vertexID == E4_VERTEXNOTFOUND) { vertexID = storage->DRV_VertexIDFromNthVertex(nodeID, nameID, nth, rank); if (vertexID == E4_VERTEXNOTFOUND) { return false; } CacheVertexIDByName(nameID, nth, vertexID); CacheVertexIDByRank(rank, vertexID); CacheVertexRankByID(vertexID, rank); } if (storage->DRV_SetVertexUserData(vertexID, userData)) { storage->MarkUnstable(); storage->RecordTimeStamp(E4_ECMODVERTEX); if (storage->HasCallbacks(E4_ECMODVERTEX)) { vp = storage->FindReferencedVertex(vertexID); if (vp != NULL) { storage->CauseEventInternal(E4_ECMODVERTEX, vp, (void *) E4_ERMVMODUSERDATA); } } return true; } return false; } bool e4_NodeImpl::GetVertexUserData(const char *nm, int nth, int &userData) { int vertexID, nameID, rank; if (storage == NULL) { return false; } nameID = storage->InternName(nm, false); if (nameID == E4_NEXTNONE) { return false; } vertexID = GetCachedVertexIDByName(nameID, nth); if (vertexID == E4_VERTEXNOTFOUND) { vertexID = storage->DRV_VertexIDFromNthVertex(nodeID, nameID, nth, rank); if (vertexID == E4_VERTEXNOTFOUND) { return false; } CacheVertexIDByName(nameID, nth, vertexID); CacheVertexIDByRank(rank, vertexID); CacheVertexRankByID(vertexID, rank); } return storage->DRV_GetVertexUserData(vertexID, userData); } bool e4_NodeImpl::SetVertexUserDataByRank(int rank, int userData) { int vertexID; e4_VertexImpl *vp; if (storage == NULL) { return false; } if ((storage->GetPermissions() & E4_SPMODIFY) == 0) { return false; } vertexID = GetCachedVertexIDByRank(rank); if (vertexID == E4_VERTEXNOTFOUND) { vertexID = storage->DRV_VertexIDFromRank(nodeID, rank); if (vertexID == E4_VERTEXNOTFOUND) { return false; } CacheVertexIDByRank(rank, vertexID); CacheVertexRankByID(vertexID, rank); } if (storage->DRV_SetVertexUserData(vertexID, userData)) { storage->MarkUnstable(); storage->RecordTimeStamp(E4_ECMODVERTEX); if (storage->HasCallbacks(E4_ECMODVERTEX)) { vp = storage->FindReferencedVertex(vertexID); if (vp != NULL) { storage->CauseEventInternal(E4_ECMODVERTEX, vp, (void *) E4_ERMVMODUSERDATA); } } return true; } return false; } bool e4_NodeImpl::GetVertexUserDataByRank(int rank, int &userData) { int vertexID; if (storage == NULL) { return false; } vertexID = GetCachedVertexIDByRank(rank); if (vertexID == E4_VERTEXNOTFOUND) { vertexID = storage->DRV_VertexIDFromRank(nodeID, rank); if (vertexID == E4_VERTEXNOTFOUND) { return false; } CacheVertexIDByRank(rank, vertexID); CacheVertexRankByID(vertexID, rank); } return storage->DRV_GetVertexUserData(vertexID, userData); }