/* * e4xmlnvg.cpp -- * * This file contains the implementation of the e4_XMLNodeVertexGenerator * class defined in e4xml.h. * * Authors: Jacob Levy and Jean-Claude Wippler. * jyl@best.com jcw@equi4.com * * Copyright: JYL Software, Inc., (c) 2000-2003. * * 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 "e4xml.h" /* *************************************************************************** * * * Implementation of e4_XMLNodeVertexCreator class: * * * *************************************************************************** */ /* * Default constructor: */ e4_XMLNodeVertexCreator::e4_XMLNodeVertexCreator() : parser(NULL) { nodesSeen = NULL; } /* * Constructor taking parser as argument: */ e4_XMLNodeVertexCreator::e4_XMLNodeVertexCreator(e4_XMLParser *p) : parser(p) { nodesSeen = e4_NewHashTable(E4_ONE_WORD_KEY); } /* * Destructor, declared virtual for derived classes. */ e4_XMLNodeVertexCreator::~e4_XMLNodeVertexCreator() { if (nodesSeen != NULL) { e4_DeleteHashTable(nodesSeen); } } /* * This operation stores a unique ID for the new node in the nodesSeen * hash table so that subsequent back references to it can be made. */ void e4_XMLNodeVertexCreator::HashNode(e4_Node nn, int id) const { e4_NodeUniqueID nuid; e4_HashEntry *ePtr; int isnew, i; ePtr = E4_CREATEHASHENTRY(nodesSeen, (char *) id, &isnew); (void) nn.GetUniqueID(nuid); i = nuid.GetUniqueID(); E4_SETHASHVALUE(ePtr, i); } /* * This operation adds a back reference to a node that was already * parsed. */ bool e4_XMLNodeVertexCreator::AddNodeBackRef(e4_Node &n, const char *nm, const char *nid, int ud) { int index, rank, id; e4_HashEntry *ePtr; e4_Node bn; e4_Vertex v; e4_Storage ss; index = atoi(nid); ePtr = E4_FINDHASHENTRY(nodesSeen, (char *) index); if (ePtr == NULL) { parser->FlagError("Invalid node back reference!"); return false; } e4_NodeUniqueID nuid; id = (int) E4_GETHASHVALUE(ePtr); (void) parser->GetStorage(ss); nuid.SetUniqueID(id,ss); if ((!ss.GetNodeFromID(nuid, bn)) || (!bn.IsValid())) { parser->FlagError("Invalid node back reference!"); return false; } if (!AddVertexRef(n, nm, E4_IOLAST, rank, bn, v) || !v.IsValid()) { parser->FlagError("Invalid node back reference!"); return false; } v.SetUserData(ud); /* * Finished making the new vertex, fire the completion event. */ (void) parser->CauseVertexCompletionEvent(v, NULL); return true; } /* * Add a vertex that will be set to a new node. */ bool e4_XMLNodeVertexCreator::AddNodeRef(e4_Node &n, const char* name, e4_InsertOrder io, int &rank, e4_Node &nn, e4_Vertex &v, int nud, int vud) { bool res = n.AddNodeRef(name, io, rank, nn, v); if (res) { nn.SetUserData(nud); v.SetUserData(vud); } return res; } /* * This operation adds a new style vertex to the current node. */ bool e4_XMLNodeVertexCreator::AddVertex(e4_Node &n, const char *vname, const char *vtype, int ud) { int rank; e4_Vertex v; /* * Initially (error condition) we set the saved vertex to an invalid one. */ GetParser()->SetSavedVertex(invalidVertex); /* * If its a string or binary vertex, add a vertex with a dummy value. * We also save the vertex inside the associated parser so that the * close vertex operation can set the actual data. */ if (strcmp(vtype, "string") == 0) { if (!AddVertexRef(n, vname, E4_IOLAST, rank, "abcd", v)) { parser->FlagError("Can't add string vertex"); return false; } v.SetUserData(ud); GetParser()->SetSavedVertex(v); return true; } if (strcmp(vtype, "binary") == 0) { if (!AddVertexRef(n, vname, E4_IOLAST, rank, "abcd", 4, v)) { parser->FlagError("Can't add binary vertex"); return false; } v.SetUserData(ud); GetParser()->SetSavedVertex(v); return true; } /* * Only vertices of type "string" or "binary" have new style * input. If it's something else, punt. */ return false; } /* * This operation adds a new vertex to the current node. */ bool e4_XMLNodeVertexCreator::AddVertex(e4_Node &n, const char *vname, const char *vtype, const char *vval, int ud) { int rank; int iv; double fv; byte *bytes; int len; e4_Vertex v; /* * Indicate that there is no saved vertex. */ GetParser()->SetSavedVertex(invalidVertex); if (strcmp(vtype, "int") == 0) { iv = atoi(vval); if (!AddVertexRef(n, vname, E4_IOLAST, rank, iv, v)) { parser->FlagError("Can't add int vertex"); return false; } v.SetUserData(ud); /* * Finished adding the new vertex, fire the completion event. */ parser->CauseVertexCompletionEvent(v, NULL); return true; } if (strcmp(vtype, "double") == 0) { fv = (double) atof(vval); if (!AddVertexRef(n, vname, E4_IOLAST, rank, fv, v)) { parser->FlagError("Can't add double vertex"); return false; } v.SetUserData(ud); /* * Finished adding the new vertex, fire the completion event. */ parser->CauseVertexCompletionEvent(v, NULL); return true; } if (strcmp(vtype, "string") == 0) { if (!AddVertexRef(n, vname, E4_IOLAST, rank, vval, v)) { parser->FlagError("Can't add string vertex"); return false; } v.SetUserData(ud); return true; } if (strcmp(vtype, "binary") == 0) { bytes = base64_decode(vval, &len); if (bytes == NULL) { parser->FlagError("Can't parse binary value"); return false; } if (!AddVertexRef(n, vname, E4_IOLAST, rank, bytes, len, v)) { parser->FlagError("Can't add binary vertex"); return false; } v.SetUserData(ud); /* * Finished adding the new vertex, fire the completion event. */ parser->CauseVertexCompletionEvent(v, NULL); return true; } parser->FlagError("Can't add vertex -- illegal type"); return false; } /* * Add a vertex of type int to the specified storage */ bool e4_XMLNodeVertexCreator::AddVertexRef(e4_Node &n, const char* name, e4_InsertOrder io, int &rank, int i, e4_Vertex &v) { return n.AddVertexRef(name, io, rank, i, v); } /* * Add a vertex of type double to the specified storage */ bool e4_XMLNodeVertexCreator::AddVertexRef(e4_Node &n, const char* name, e4_InsertOrder io, int &rank, double d, e4_Vertex &v) { return n.AddVertexRef(name, io, rank, d, v); } /* * Add a vertex of type string. */ bool e4_XMLNodeVertexCreator::AddVertexRef(e4_Node &n, const char* name, e4_InsertOrder io, int &rank, const char *s, e4_Vertex &v) { return n.AddVertexRef(name, io, rank, s, v); } /* * Add a vertex of type binary. */ bool e4_XMLNodeVertexCreator::AddVertexRef(e4_Node &n, const char* name, e4_InsertOrder io, int &rank, const void* bytes, int nbytes, e4_Vertex &v) { return n.AddVertexRef(name, io, rank, bytes, nbytes, v); } /* * Add a vertex with a value of the node specified. */ bool e4_XMLNodeVertexCreator::AddVertexRef(e4_Node &n, const char* name, e4_InsertOrder io, int &rank, e4_Node vn, e4_Vertex &v) { return n.AddVertexRef(name, io, rank, vn, v); }