/* Copyright (C) 2000-2004 Code contributed by Greg Collecutt, Joseph Hope and Paul Cochrane This file is part of xmds. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* $Id: xmdsutils.cc,v 1.14 2004/07/13 05:29:38 paultcochrane Exp $ */ /*! @file xmdsutils.cc @brief Utility classes and methods More detailed explanation... */ #include #include #include #include extern bool debugFlag; //#define DEBUG 0 // ****************************************************************************** // ****************************************************************************** // xmdsException // ****************************************************************************** // ****************************************************************************** // ****************************************************************************** xmdsException::xmdsException() : myNode(0), myErrorMessage("") { }; // ****************************************************************************** xmdsException::xmdsException( const char *const yourErrorMessage) : myNode(0), myErrorMessage(yourErrorMessage) { }; // ****************************************************************************** xmdsException::xmdsException( const Node *const yourNode, const char *const yourErrorMessage) : myNode(yourNode), myErrorMessage(yourErrorMessage) { }; // ****************************************************************************** const char* xmdsException::getError() { char s2[256]; s[0]=0; const Node* nextNode=myNode; if(nextNode != 0) { sprintf(s2,"In element '%s',\n",nextNode->nodeName()->c_str()); strcat(s,s2); nextNode=nextNode->parentNode(); } while(nextNode != 0) { sprintf(s2," which is within element '%s',\n",nextNode->nodeName()->c_str()); strcat(s,s2); nextNode=nextNode->parentNode(); } sprintf(s2,"\nthe following error occurred:\n %s\n",myErrorMessage); strcat(s,s2); return s; }; // ****************************************************************************** // ****************************************************************************** // xmdsUtility public // ****************************************************************************** // ****************************************************************************** long nxmdsUtilitys=0; //!< Number of xmds utility objects // ****************************************************************************** xmdsUtility::xmdsUtility() { if(debugFlag) { nxmdsUtilitys++; printf("xmdsUtility::xmdsUtility\n"); printf("nxmdsUtilitys=%li\n",nxmdsUtilitys); } }; // ****************************************************************************** xmdsUtility::~xmdsUtility() { if(debugFlag) { nxmdsUtilitys--; printf("xmdsUtility::~xmdsUtility\n"); printf("nxmdsUtilitys=%li\n",nxmdsUtilitys); } }; // ****************************************************************************** // ****************************************************************************** // xmdsUtility protected // ****************************************************************************** // ****************************************************************************** // ****************************************************************************** char* xmdsUtility::errorMessage() const { return myErrorMessage; }; // ****************************************************************************** void xmdsUtility::getAssignmentStrings( const Element *const inElement, const XMLString& ofName, const bool& required, const unsigned long& n2get, list& outList) { if(debugFlag) { printf("xmdsUtility::getAssignmentStrings\n"); } outList.clear(); // note that if an element is found, then the routine will throw an exception // if n2get items aren't found within, except that passing n2get=0 will escape // this behaviour const NodeList* candidateElements = inElement->getElementsByTagName(ofName,0); if(candidateElements->length()==0) { if(required) { sprintf(myErrorMessage,"Element '%s' not found",ofName.c_str()); throw xmdsException(inElement,myErrorMessage); } else { return; } } if(candidateElements->length()==1) { const Node* nextNode = candidateElements->item(0); parseXMLString(nextNode,candidateElements->item(0)->textContent(0),outList); if(n2get!=0) { // check that numbers of requested items match if(outList.size()!=n2get) { sprintf(myErrorMessage, "%li strings wanted but %li found",n2get,(long)outList.size()); throw xmdsException(nextNode,myErrorMessage); } } } else { sprintf(myErrorMessage,"Multiple Elements '%s' found",ofName.c_str()); throw xmdsException(inElement,myErrorMessage); } }; // ****************************************************************************** void xmdsUtility::getAssignmentBools( const Element *const inElement, const XMLString& ofName, const bool& required, const unsigned long& n2get, list& outList) { if(debugFlag) { printf("xmdsUtility::getAssignmentBools\n"); } // note that if an element is found, then the routine will throw an exception // if n2get items aren't found withn, except that passing n2get=0 will escape // this behaviour outList.clear(); const NodeList* candidateElements = inElement->getElementsByTagName(ofName,0); if(candidateElements->length()==0) { if(required) { sprintf(myErrorMessage,"Element '%s' not found",ofName.c_str()); throw xmdsException(inElement,myErrorMessage); } else { return; } } if(candidateElements->length()==1) { list myOutList; const Node* nextNode = candidateElements->item(0); parseXMLString(nextNode,candidateElements->item(0)->textContent(0),myOutList); for(list::const_iterator pXMLString = myOutList.begin(); pXMLString != myOutList.end(); pXMLString++) { if(*pXMLString=="yes") { outList.push_back(1); } else if(*pXMLString=="no") { outList.push_back(0); } else { throw xmdsException(nextNode,"'yes' or 'no' expected"); } } if(n2get!=0) { // check that numbers of requested items match if(outList.size()!=n2get) { sprintf(myErrorMessage,"%li 'yes'/'no' wanted but %li found",n2get,(long)outList.size()); throw xmdsException(nextNode,myErrorMessage); } } } else { sprintf(myErrorMessage,"Multiple Elements '%s' found",ofName.c_str()); throw xmdsException(inElement,myErrorMessage); } }; // ****************************************************************************** void xmdsUtility::getAssignmentULongs( const Element *const inElement, const XMLString& ofName, const bool& required, const unsigned long& n2get, list& outList) { if(debugFlag) { printf("xmdsUtility::getAssignmentLongs\n"); } // note that if an element is found, then the routine will throw an exception // if n2get items aren't found withn, except that passing n2get=0 will escape // this behaviour outList.clear(); const NodeList* candidateElements = inElement->getElementsByTagName(ofName,0); if(candidateElements->length()==0) { if(required) { sprintf(myErrorMessage,"Element '%s' not found",ofName.c_str()); throw xmdsException(inElement,myErrorMessage); } else { return; } } if(candidateElements->length()==1) { list myOutList; const Node* nextNode = candidateElements->item(0); parseXMLString(nextNode,candidateElements->item(0)->textContent(0),myOutList); for(list::const_iterator pXMLString = myOutList.begin(); pXMLString != myOutList.end(); pXMLString++) { unsigned long nextULong; if(pXMLString->asULong(nextULong)) { outList.push_back(nextULong); } else { throw xmdsException(nextNode,"invalid positive integer"); } } if(n2get!=0) { // check that numbers of requested items match if(outList.size()!=n2get) { sprintf(myErrorMessage,"%li integers wanted but %li found",n2get,(long)outList.size()); throw xmdsException(nextNode,myErrorMessage); } } } else { sprintf(myErrorMessage,"Multiple Elements '%s' found",ofName.c_str()); throw xmdsException(inElement,myErrorMessage); } }; // ****************************************************************************** void xmdsUtility::getAssignmentDoubles( const Element *const inElement, const XMLString& ofName, const bool& required, const unsigned long& n2get, list& outList) { if(debugFlag) { printf("xmdsUtility::getAssignmentDoubles\n"); } // note that if an element is found, then the routine will throw an exception // if n2get items aren't found withn, except that passing n2get=0 will escape // this behaviour outList.clear(); const NodeList* candidateElements = inElement->getElementsByTagName(ofName,0); if(candidateElements->length()==0) { if(required) { sprintf(myErrorMessage,"Element '%s' not found",ofName.c_str()); throw xmdsException(inElement,myErrorMessage); } else { return; } } if(candidateElements->length()==1) { list myOutList; const Node* nextNode = candidateElements->item(0); parseXMLString(nextNode,candidateElements->item(0)->textContent(0),myOutList); for(list::const_iterator pXMLString = myOutList.begin(); pXMLString != myOutList.end(); pXMLString++) { double nextdouble; if(pXMLString->asDouble(nextdouble)) { outList.push_back(nextdouble); } else { throw xmdsException(nextNode,"invalid floating point format"); } } if(n2get!=0) { // check that numbers of requested items match if(outList.size()!=n2get) { sprintf(myErrorMessage,"%li reals wanted but %li found",n2get,(long)outList.size()); throw xmdsException(nextNode,myErrorMessage); } } } else { sprintf(myErrorMessage,"Multiple Elements '%s' found",ofName.c_str()); throw xmdsException(inElement,myErrorMessage); } }; // ****************************************************************************** void xmdsUtility::getAssignmentDomains( const Element *const inElement, const XMLString& ofName, const bool& required, const unsigned long& n2get, list& outList) { if(debugFlag) { printf("xmdsUtility::getAssignmentDomains\n"); } // note that if an element is found, then the routine will throw an exception // if n2get items aren't found withn, except that passing n2get=0 will escape // this behaviour outList.clear(); const NodeList* candidateElements = inElement->getElementsByTagName(ofName,0); if(candidateElements->length()==0) { if(required) { sprintf(myErrorMessage,"Element '%s' not found",ofName.c_str()); throw xmdsException(inElement,myErrorMessage); } else { return; } } if(candidateElements->length()==1) { list myPairsList; const Node* nextNode = candidateElements->item(0); parseXMLString(nextNode,candidateElements->item(0)->textContent(0),myPairsList); if(n2get!=0) { // check that numbers of requested items match if(myPairsList.size() != n2get) { sprintf(myErrorMessage,"%li domain pairs wanted but %li found",n2get,(long)myPairsList.size()); throw xmdsException(nextNode,myErrorMessage); } } for(list::const_iterator pXMLString = myPairsList.begin(); pXMLString != myPairsList.end(); pXMLString++) { list myDoublesList; parseXMLString(nextNode,&*pXMLString,myDoublesList); if(myDoublesList.size() != 2) { throw xmdsException(nextNode,"bracketed pairs of reals expected"); } domainStruct nextDomain; list::const_iterator pXMLString2; pXMLString2 = myDoublesList.begin(); if(!pXMLString2->asDouble(nextDomain.begin)) { throw xmdsException(nextNode,"invalid floating point format"); } pXMLString2++; if(!pXMLString2->asDouble(nextDomain.end)) { throw xmdsException(nextNode,"invalid floating point format"); } if(nextDomain.end<=nextDomain.begin) { throw xmdsException(nextNode,"domain ends must be > begins"); } outList.push_back(nextDomain); } } else { sprintf(myErrorMessage,"Multiple Elements '%s' found",ofName.c_str()); throw xmdsException(inElement,myErrorMessage); } }; // ****************************************************************************** void xmdsUtility::getAttributeStrings( const Element *const inElement, const XMLString& ofElementName, const XMLString& ofAttrName, const bool& required, XMLString& outString) { if(debugFlag) { printf("xmdsUtility::getAttributeStrings\n"); } outString = EMPTY_STRING; const NodeList* candidateElements = inElement->getElementsByTagName(ofElementName,0); // this code is a bit weird as it was grabbed from getAssignmentStrings, and so // don't really need this next test // @todo Need to clean up this function so that required boolean means the right thing // Namely that the attribute is required, atm we're checking if the element (tag) // is required // Really not happy with how the attribute parsing code is going // this looks like it needs a bit of work to knock it into some proper shape, // what we've got here is too much of a hack on top of getAssignmentStrings and // a decent amount of thought needs to go into the implementation if(candidateElements->length()==0) { if(required) { sprintf(myErrorMessage,"Element '%s' not found",ofElementName.c_str()); throw xmdsException(inElement,myErrorMessage); } else { return; } } if(candidateElements->length()==1) { const Node* nextNode = candidateElements->item(0); const NamedNodeMap* attrNodeMap = nextNode->attributes(); if (attrNodeMap->length() > 0) { const Node* attrNode = attrNodeMap->getNamedItem(ofAttrName); if (attrNode != 0) { outString = attrNode->nodeValue()->c_str(); } // if the attribute isn't found, and it's required, barf else if ((attrNode == 0) && required) { sprintf(myErrorMessage,"Attribute '%s' not found",ofAttrName.c_str()); throw xmdsException(inElement,myErrorMessage); } else { outString = EMPTY_STRING; } } } else { sprintf(myErrorMessage,"Multiple Elements '%s' found",ofElementName.c_str()); throw xmdsException(inElement,myErrorMessage); } }; // ****************************************************************************** void xmdsUtility::getAttributeBools( const Element *const inElement, const XMLString& ofElementName, const XMLString& ofAttrName, const bool& required, bool& outBool) { if(debugFlag) { printf("xmdsUtility::getAttributeBools\n"); } outBool = false; const NodeList* candidateElements = inElement->getElementsByTagName(ofElementName,0); if (debugFlag) { printf("xmdsUtility::getAttributeBools : candidateElements->length = %ld\n",candidateElements->length()); } if(candidateElements->length()==0) { if(required) { sprintf(myErrorMessage,"Element '%s' not found",ofElementName.c_str()); throw xmdsException(inElement,myErrorMessage); } else { return; } } if(candidateElements->length()==1) { // we only want one such tag const Node* nextNode = candidateElements->item(0); // grab the tag's node const NamedNodeMap* attrNodeMap = nextNode->attributes(); // grab the attributes of the tag as a map if (debugFlag) { printf("xmdsUtility::getAttributeBools : attrNodeMap->length = %ld\n",attrNodeMap->length()); } if (attrNodeMap->length() > 0) { const Node* attrNode = attrNodeMap->getNamedItem(ofAttrName); // get the node with the name ofAttrName if (attrNode != 0) { // then compare the value with 'yes' and 'no' const string boolString = static_cast (attrNode->nodeValue()->c_str()); if (debugFlag) { printf("xmdsUtility::getAttributeBools : boolString = %s\n", boolString.c_str()); } if (boolString == "yes") { outBool = true; } else if (boolString == "no") { outBool = false; } else { throw xmdsException(nextNode, "'yes' or 'no' expected"); } } } } else { sprintf(myErrorMessage,"Multiple Elements '%s' found",ofElementName.c_str()); throw xmdsException(inElement,myErrorMessage); } if (debugFlag) { printf("xmdsUtility::getAttributeBools : outBool = %d\n",outBool); } }; // ****************************************************************************** unsigned long xmdsUtility::spaceList2ULong( const list& spaceList) const { if(debugFlag) { printf("xmdsUtility::spaceList2ULong\n"); } unsigned long space=0; unsigned long two2n=1; for(list::const_iterator pBool = spaceList.begin(); pBool != spaceList.end(); pBool++) { if(*pBool) { space += two2n; } two2n *= 2; } return space; }; // ****************************************************************************** // ****************************************************************************** // xmdsUtility private // ****************************************************************************** // ****************************************************************************** // ****************************************************************************** void xmdsUtility::parseXMLString( const Node *const inNode, const XMLString *const inString, list& outXMLStringList) { if(debugFlag) { printf("xmdsUtility::parseXMLString\n"); } outXMLStringList.clear(); if(inString->length()==0) { return; } XMLString copyInString = *inString; // begin by replacing all commas and semicolons with spaces unsigned long i=0; while(i begins; list ends; long bracketLevel=0; i=0; char lastChar=0x20; while(i::const_iterator pbegin = begins.begin(); list::const_iterator pend = ends.begin(); while(pbegin != begins.end()) { XMLString subString; copyInString.subString(subString,*pbegin,*pend); outXMLStringList.push_back(subString); pbegin++; pend++; } };