COSC_4P82_Assignment_1/lib/beagle-3.0.3/PACC/XML/Finder.cpp

294 lines
8.6 KiB
C++
Raw Normal View History

2024-02-13 21:21:51 -05:00
/*
* Portable Agile C++ Classes (PACC)
* Copyright (C) 2001-2003 by Marc Parizeau
* http://manitou.gel.ulaval.ca/~parizeau/PACC
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Contact:
* Laboratoire de Vision et Systemes Numeriques
* Departement de genie electrique et de genie informatique
* Universite Laval, Quebec, Canada, G1K 7P4
* http://vision.gel.ulaval.ca
*
*/
/*!
* \file PACC/XML/Finder.cpp
* \brief Class methods for the %XML tag finder.
* \author Marc Parizeau, Laboratoire de vision et systèmes numériques, Université Laval
* $Revision: 1.6.2.1 $
* $Date: 2007/09/10 18:24:10 $
*/
#include "XML/Finder.hpp"
#include <sstream>
#include <stdexcept>
using namespace std;
using namespace PACC;
/*!
Only regular markup is considered in this search. Here is an usage example for finding the first instance of tag "MyTag" in document \c lDocument:
\code
Document lDocument;
...
Finder lFinder(lDocument.getFirstDataTag());
// find the first instance
Iterator lTag = lFinder.find("//Mytag");
if(lTag)
{
// process this instance of markup "Mytag"
...
}
\endcode
After processing a found tag, the search may be continued using method Finder::findNext.
*/
XML::Iterator XML::Finder::find(const string& inPath)
{
// reset the path steps
mSteps.clear();
// parse the search path
istringstream lStream(inPath);
Tokenizer lTokenizer(lStream);
lTokenizer.setDelimiters("", "/");
string lToken;
while(lTokenizer.getNextToken(lToken)) {
// next token should be '/'
if(lToken[0] != '/') {
// unless path is relative; then make it absolute!
if(mSteps.empty()) {
mSteps.push_back("*");
mSteps.push_back(lToken);
continue;
} else throw runtime_error(string("Finder::find() invalid search path: ")+inPath);
}
char lNextChar = lTokenizer.peekNextChar();
if(lNextChar == -1) break;
// process '//' special case
if(lNextChar == '/') {
// but ignore '///'
if(mSteps.empty() || mSteps.back() != "") mSteps.push_back("");
} else if(lTokenizer.getNextToken(lToken)) mSteps.push_back(lToken);
else break;
}
// search for the path
search(mNode, 0);
// pop first match from queue
Iterator lPos;
if(!mMatches.empty()) {
lPos = mMatches.front();
mMatches.pop();
}
// return first match or null iterator
return lPos;
}
/*!
The search proceeds from the point where the last markup was found. Here is an example where we search for all instances of markup "Mytag" in document \c lDocument:
\code
Document lDocument;
...
Finder lFinder(lDocument.getFirstDataTag());
// find all instances of tag
for(Iterator lTag = lFinder.find("//Mytag"); lTag; lTag = lFinder.findNext())
{
// process each instance
...
}
\endcode
*/
XML::Iterator XML::Finder::findNext(void)
{
Iterator lPos;
// pop next match from the queue
if(!mMatches.empty()) {
lPos = mMatches.front();
mMatches.pop();
}
// return next match or null iterator
return lPos;
}
//! Search for step \c inStep starting at position \c inPos.
void XML::Finder::search(XML::Iterator inPos, unsigned int inStep) {
// stop recursion?
if(!inPos || inStep >= mSteps.size()) return;
// process current step
if(mSteps[inStep] == "..") {
// move up to parent
if(inPos != mNode) {
if(inStep+1 < mSteps.size()) {
if(mSteps[inStep+1] == "..") search(inPos->getParent(), inStep+1);
else {
for(Iterator lPos = inPos->getParent()->getFirstChild(); lPos; ++lPos)
search(lPos, inStep+1);
}
} else mMatches.push(inPos->getParent());
}
} else if(mSteps[inStep] == "") {
// walk tree in level order
queue<Iterator> lSearchQueue;
lSearchQueue.push(inPos);
while(!lSearchQueue.empty()) {
// get next node
Iterator lPos = lSearchQueue.front();
lSearchQueue.pop();
// push all its children onto the search queue
for(Iterator lChild = lPos->getFirstChild(); lChild; ++lChild) lSearchQueue.push(lChild);
// if not last step, search recursively
if(inStep+1 < mSteps.size()) search(lPos, inStep+1);
else mMatches.push(lPos);
}
} else {
if(mSteps[inStep] == "*" || inPos->getValue() == mSteps[inStep]) {
// found a match
if(inStep+1 < mSteps.size()) {
if(mSteps[inStep+1] == "..") search(inPos, inStep+1);
else {
for(Iterator lPos = inPos->getFirstChild(); lPos; ++lPos)
search(lPos, inStep+1);
}
} else mMatches.push(inPos);
}
}
}
/*!
Only regular markup is considered in this search. Here is an usage example for finding the first instance of tag "MyTag" in document \c lDocument:
\code
Document lDocument;
...
ConstFinder lFinder(lDocument.getFirstDataTag());
// find the first instance
ConstIterator lTag = lFinder.find("//Mytag");
if(lTag)
{
// process this instance of markup "Mytag"
...
}
\endcode
After processing a found tag, the search may be continued using method Finder::findNext.
*/
XML::ConstIterator XML::ConstFinder::find(const string& inPath)
{
// reset the path steps
mSteps.clear();
// parse the search path
istringstream lStream(inPath);
Tokenizer lTokenizer(lStream);
lTokenizer.setDelimiters("", "/");
string lToken;
while(lTokenizer.getNextToken(lToken)) {
// next token should be '/'
if(lToken[0] != '/') {
// unless path is relative; then make it absolute!
if(mSteps.empty()) {
mSteps.push_back("*");
mSteps.push_back(lToken);
continue;
} else throw runtime_error(string("ConstFinder::find() invalid search path: ")+inPath);
}
char lNextChar = lTokenizer.peekNextChar();
if(lNextChar == -1) break;
// process '//' special case
if(lNextChar == '/') {
// but ignore '///'
if(mSteps.empty() || mSteps.back() != "") mSteps.push_back("");
} else if(lTokenizer.getNextToken(lToken)) mSteps.push_back(lToken);
else break;
}
// search for the path
search(mNode, 0);
// pop first match from queue
ConstIterator lPos;
if(!mMatches.empty()) {
lPos = mMatches.front();
mMatches.pop();
}
// return first match or null iterator
return lPos;
}
/*!
The search proceeds from the point where the last markup was found. Here is an example where we search for all instances of markup "Mytag" in document \c lDocument:
\code
Document lDocument;
...
ConstFinder lFinder(lDocument.getFirstDataTag());
// find all instances of tag
for(ConstIterator lTag = lDocument.find("//Mytag"); lTag; lTag = lDocument.findNext())
{
// process each instance
...
}
\endcode
*/
XML::ConstIterator XML::ConstFinder::findNext(void)
{
ConstIterator lPos;
// pop next match from queue
if(!mMatches.empty()) {
lPos = mMatches.front();
mMatches.pop();
}
// return next match or null iterator
return lPos;
}
//! Search for step \c inStep starting at position \c inPos.
void XML::ConstFinder::search(XML::ConstIterator inPos, unsigned int inStep) {
// stop recursion?
if(!inPos || inStep >= mSteps.size()) return;
// process current step
if(mSteps[inStep] == "..") {
// move up to parent
if(inPos != mNode) {
if(inStep+1 < mSteps.size()) {
if(mSteps[inStep+1] == "..") search(inPos->getParent(), inStep+1);
else {
for(ConstIterator lPos = inPos->getParent()->getFirstChild(); lPos; ++lPos)
search(lPos, inStep+1);
}
} else mMatches.push(inPos->getParent());
}
} else if(mSteps[inStep] == "") {
// walk tree in level order
queue<ConstIterator> lSearchQueue;
lSearchQueue.push(inPos);
while(!lSearchQueue.empty()) {
// get next node
ConstIterator lPos = lSearchQueue.front();
lSearchQueue.pop();
// push all its children onto the search queue
for(ConstIterator lChild = lPos->getFirstChild(); lChild; ++lChild) lSearchQueue.push(lChild);
// if not last step, search recursively
if(inStep+1 < mSteps.size()) search(lPos, inStep+1);
else mMatches.push(lPos);
}
} else {
if(mSteps[inStep] == "*" || inPos->getValue() == mSteps[inStep]) {
// found a match
if(inStep+1 < mSteps.size()) {
if(mSteps[inStep+1] == "..") search(inPos, inStep+1);
else {
for(ConstIterator lPos = inPos->getFirstChild(); lPos; ++lPos)
search(lPos, inStep+1);
}
} else mMatches.push(inPos);
}
}
}