/* * e4vertex.cpp -- * * Implementation of the e4_Vertex class defined in e4graph.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" /* * This instance of e4_Vertex can be used (by assigning it to fields or * variables of type e4_Vertex) to remove remaining references to instances * that you want to discard. Especially useful for removing remaining * references in heap-allocated memory. */ e4_Vertex const invalidVertex; /* * Default constructor: */ e4_Vertex::e4_Vertex() : e4_RefCount() {} /* * Constructor which assigns a value to the the implementation pointer. */ e4_Vertex::e4_Vertex(e4_VertexImpl *ip) : e4_RefCount(ip) {} /* * Copying constructor: */ e4_Vertex::e4_Vertex(const e4_Vertex &referrer) : e4_RefCount(referrer) {} /* * Copying constructor that's given an e4_RefCount: */ e4_Vertex::e4_Vertex(const e4_RefCount &referrer) : e4_RefCount(referrer) { if ((impl != NULL) && (impl->Kind() != E4_RKVERTEX)) { (void) e4_RefCount::operator=(invalidVertex); } } /* * Assignment operator: */ e4_Vertex & e4_Vertex::operator=(const e4_Vertex &referrer) { return (e4_Vertex &) e4_RefCount::operator=(referrer); } /* * Get the value of a vertex. */ bool e4_Vertex::Get(e4_Value &v) const { e4_ValueImpl *vipp; if (impl == NULL) { return false; } if (((e4_VertexImpl *) impl)->Get(vipp) == false) { return false; } if (vipp == NULL) { return false; } v.vertexType = vipp->vertexType; switch (vipp->vertexType) { case E4_VTNODE: { e4_Node n(vipp->u.n); v.n = n; break; } case E4_VTINT: v.u.i = vipp->u.i; break; case E4_VTDOUBLE: v.u.d = vipp->u.d; break; case E4_VTSTRING: v.u.s = vipp->u.s; break; case E4_VTBINARY: v.u.b.bytes = vipp->u.b.bytes; v.u.b.nbytes = vipp->u.b.nbytes; break; default: delete vipp; return false; } delete vipp; return true; } bool e4_Vertex::Get(e4_Node &n) const { e4_NodeImpl *nipp; if (impl == NULL) { return false; } if (!((e4_VertexImpl *) impl)->Get(nipp)) { return false; } e4_Node nn(nipp); n = nn; return true; } bool e4_Vertex::Get(int &v) const { if (impl == NULL) { return false; } return ((e4_VertexImpl *) impl)->Get(v); } bool e4_Vertex::Get(double &v) const { if (impl == NULL) { return false; } return ((e4_VertexImpl *) impl)->Get(v); } bool e4_Vertex::Get(const char *&v) const { if (impl == NULL) { return false; } return ((e4_VertexImpl *) impl)->Get(v); } bool e4_Vertex::Get(const void *&v, int &nbv) const { if (impl == NULL) { return false; } return ((e4_VertexImpl *) impl)->Get(v, nbv); } /* * Set the value of a vertex. */ bool e4_Vertex::Set(int v) const { if (impl == NULL) { return false; } return ((e4_VertexImpl *) impl)->Set(v); } bool e4_Vertex::Set(double v) const { if (impl == NULL) { return false; } return ((e4_VertexImpl *) impl)->Set(v); } bool e4_Vertex::Set(const char *s) const { if (impl == NULL) { return false; } return ((e4_VertexImpl *) impl)->Set(s); } bool e4_Vertex::Set(const void *v, int nbv) const { if (impl == NULL) { return false; } return ((e4_VertexImpl *) impl)->Set(v, nbv); } bool e4_Vertex::Set(e4_Node n) const { if ((impl == NULL) || (!n.IsValid())) { return false; } return ((e4_VertexImpl *) impl)->SetToNode(n.GetRawUniqueID()); } bool e4_Vertex::Set(const e4_Value &v) const { switch (v.vertexType) { case E4_VTNODE: return Set(v.n); case E4_VTINT: return Set(v.u.i); case E4_VTDOUBLE: return Set(v.u.d); case E4_VTSTRING: return Set(v.u.s); case E4_VTBINARY: return Set(v.u.b.bytes, v.u.b.nbytes); default: return false; } } /* * Set the content of this vertex to a new node and return the new node. */ bool e4_Vertex::SetNode(e4_Node &n) const { e4_NodeImpl *nnip; if (impl == NULL) { return false; } nnip = ((e4_VertexImpl *) impl)->SetNode(); if (nnip == NULL) { return false; } e4_Node nn(nnip); /* * Decrement the refcount to offset the artificially incremented refcount * for protection during callbacks. */ nnip->DecrRefCount(); n = nn; return true; } /* * Get the rank of this vertex within the node containing it. */ int e4_Vertex::Rank() const { if (impl == NULL) { return E4_VERTEXNOTFOUND; } return ((e4_VertexImpl *) impl)->Rank(); } /* * Get the count of how many vertices up to this one in the containing * node have the same name as this one. Return -1 if the vertex is * detached. */ int e4_Vertex::CountWithName() const { if (impl == NULL) { return -1; } return ((e4_VertexImpl *) impl)->CountWithName(); } /* * Get the total count of how many vertices in the node containing * this one have the same name. Return -1 if this vertex is detached. */ int e4_Vertex::TotalCountWithName() const { if (impl == NULL) { return -1; } return ((e4_VertexImpl *) impl)->TotalCountWithName(); } /* * Get the count of vertices up to this one in the node containing this * vertex that have the same type as this vertex. If the vertex is * detached, return -1. */ int e4_Vertex::CountWithType() const { if (impl == NULL) { return -1; } return ((e4_VertexImpl *) impl)->CountWithType(); } /* * Get the total count of vertices with the same type as this one within * the node containing this vertex. Return -1 if this vertex is detached. */ int e4_Vertex::TotalCountWithType() const { if (impl == NULL) { return -1; } return ((e4_VertexImpl *) impl)->TotalCountWithType(); } /* * Detach this vertex from its containing node. */ bool e4_Vertex::Detach() const { if (impl == NULL) { return false; } return ((e4_VertexImpl *) impl)->Detach(); } /* * Is this vertex detached? */ bool e4_Vertex::IsDetached() const { if (impl == NULL) { return true; } return ((e4_VertexImpl *) impl)->IsDetached(); } /* * Get the vertex type for this vertex. */ e4_VertexType e4_Vertex::Type() const { if (impl == NULL) { return E4_VTUNKNOWN; } return ((e4_VertexImpl *) impl)->Type(); } /* * Get the name of this vertex. */ const char * e4_Vertex::Name() const { if (impl == NULL) { return NULL; } return ((e4_VertexImpl *) impl)->Name(); } /* * Rename this vertex. */ bool e4_Vertex::Rename(const char *newname) const { if (impl == NULL) { return false; } return ((e4_VertexImpl *) impl)->Rename(newname); } /* * Get a unique ID (unique within the storage) for this vertex. */ int e4_Vertex::GetRawUniqueID() const { if (impl == NULL) { return E4_VERTEXNOTFOUND; } return ((e4_VertexImpl *) impl)->GetUniqueID(); } /* * Same as above but wrap it up into an e4_VertexUniqueID. */ bool e4_Vertex::GetUniqueID(e4_VertexUniqueID &v) const { int id; e4_StorageImpl *sp; if (impl == NULL) { return false; } id = ((e4_VertexImpl *) impl)->GetUniqueID(); if (id == E4_VERTEXNOTFOUND) { return false; } sp = ((e4_VertexImpl *) impl)->GetStorage(); if (sp == NULL) { return false; } e4_VertexUniqueID vv(id, sp->HashCode()); v = vv; return true; } /* * Get the root node of the storage containing this vertex. */ bool e4_Vertex::GetRootNode(e4_Node &rn) const { e4_NodeImpl *rnip; e4_StorageImpl *ssip; if (impl == NULL) { return false; } ssip = ((e4_VertexImpl *) impl)->GetStorage(); if (ssip == NULL) { return false; } rnip = ssip->GetRootNode(); if (rnip == NULL) { return false; } e4_Node rrnn(rnip); rn = rrnn; return true; } /* * Get the storage in which this vertex occurs. */ bool e4_Vertex::GetStorage(e4_Storage &s) const { e4_StorageImpl *ssip; if (impl == NULL) { return false; } ssip = ((e4_VertexImpl *) impl)->GetStorage(); if (ssip == NULL) { return false; } e4_Storage ss(ssip); s = ss; return true; } /* * Get the node containing this vertex. */ bool e4_Vertex::GetNode(e4_Node &n) const { e4_NodeImpl *nnip; if (impl == NULL) { return false; } nnip = ((e4_VertexImpl *) impl)->GetNode(); if (nnip == NULL) { return false; } e4_Node nn(nnip); n = nn; return true; } /* * Get the next vertex after this in the node containing this vertex. */ bool e4_Vertex::Next(int num, e4_Vertex &nf) const { e4_VertexImpl *ffip; if (impl == NULL) { return false; } ffip = ((e4_VertexImpl *) impl)->Next(num); if (ffip == NULL) { return false; } e4_Vertex ff(ffip); nf = ff; return true; } /* * Get the vertex before this one in the node containing this vertex. */ bool e4_Vertex::Prev(int num, e4_Vertex &pv) const { e4_VertexImpl *ffip; if (impl == NULL) { return false; } ffip = ((e4_VertexImpl *) impl)->Prev(num); if (ffip == NULL) { return false; } e4_Vertex ff(ffip); pv = ff; return true; } /* * 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. * Otherwise offset is ignored. * * Note that only moves within the same storage are allowed. */ bool e4_Vertex::MoveVertex(const e4_Vertex &ff, e4_InsertOrder order, int offset) const { int moveVertexID; e4_Storage myStorage, hisStorage; if ((impl == NULL) || (!ff.IsValid()) || (ff.impl == impl)) { return false; } if ((!GetStorage(myStorage)) || (!ff.GetStorage(hisStorage))) { return false; } if (myStorage != hisStorage) { return false; } moveVertexID = ff.GetRawUniqueID(); switch (order) { case E4_IOFIRST: return ((e4_VertexImpl *) impl)->MoveVertex(moveVertexID, 1); case E4_IOLAST: return ((e4_VertexImpl *) impl)->MoveVertex(moveVertexID, -1); case E4_IOAT: return ((e4_VertexImpl *) impl)->MoveVertex(moveVertexID, Rank()); case E4_IOBEFORE: if (offset < 1) { return false; } return ((e4_VertexImpl *) impl)->MoveVertex(moveVertexID, Rank() + 1 - offset); case E4_IOAFTER: if (offset < 1) { return false; } return ((e4_VertexImpl *) impl)->MoveVertex(moveVertexID, Rank() + offset); default: return false; } } /* * Return the kind identifier for this instance's type. */ e4_RefKind e4_Vertex::Kind() const { return E4_RKVERTEX; } /* * Get/Set user data associated with this vertex. */ bool e4_Vertex::GetUserData(int &userData) const { if (impl == NULL) { return false; } return ((e4_VertexImpl *) impl)->GetUserData(userData); } bool e4_Vertex::SetUserData(int userData) const { if (impl == NULL) { return false; } return ((e4_VertexImpl *) impl)->SetUserData(userData); }