/* * CDE - Common Desktop Environment * * Copyright (c) 1993-2012, The Open Group. All rights reserved. * * These libraries and programs are free software; you can * redistribute them and/or modify them under the terms of the GNU * Lesser General Public License as published by the Free Software * Foundation; either version 2 of the License, or (at your option) * any later version. * * These libraries and programs are distributed in the hope that * they 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 these librararies and programs; if not, write * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth * Floor, Boston, MA 02110-1301 USA */ // $XConsortium: PathTable.cc /main/4 1996/06/11 17:07:57 cde-hal $ #include "PathTable.h" #include "Debug.h" #include "Feature.h" #include "utility/debug.h" extern SymbolTable* gElemSymTab; unsigned int letterHash(const LetterType& x) { return x; } EncodedPath::~EncodedPath() { delete [] f_array ; f_SVectors.clearAndDestroy(); delete f_copyOfS; } EncodedPath::EncodedPath(SSPath* p, unsigned int asPattern) : f_size(p -> entries()), f_patternSize(0), f_SVectors(letterHash), f_wildCard(gElemSymTab -> wildCardId()), f_unlimitedWildCard(gElemSymTab -> unlimitedWildCardId()), f_copyOfS(new BitVector(WORD_SIZE, 0)) { f_array = new LetterType[f_size]; CC_TPtrDlistIterator l_pathIter(*p); BitVector *l_bv = 0; int i = 0; while (++l_pathIter) { // // Count pattern size, excluding "*". // f_array[i] = (LetterType)((l_pathIter.key() -> symbol()).id()); if ( f_array[i] != f_unlimitedWildCard ) f_patternSize++; i++; } if ( asPattern == true ) { // // Compute the S arrays. // Examples pat = a b a c // S(a) = 1 0 1 0 // S(b) = 0 0 0 0 // S(c) = 0 0 0 1 // // pat = a ? a c // S(a) = 1 1 1 0 // S(c) = 0 1 0 1 // S(?) = 0 1 0 0 // // pat = a * a c // S(a) = 1 1 0 // S(c) = 0 0 1 // S(*) = 1 0 0 // l_pathIter.reset(); int j = patternLength()-1; LetterType l_id; // i records each PathTerm position in the list int i=0; while (++l_pathIter) { l_id = (LetterType)((l_pathIter.key() -> symbol()).id()); l_bv = f_SVectors.findValue(&l_id); if ( l_bv == 0 ) { l_bv = new BitVector(patternLength(), 0); f_SVectors.insertKeyAndValue(new LetterType(l_id), l_bv); } /////////////////////////////////////////////////// // reverse the order in the bit vector: // MSB position ==> set LSB bit in the bit vector /////////////////////////////////////////////////// if ( l_id != f_unlimitedWildCard ) { l_bv -> setBitTo(j, 1); ////////////////////////////////////////////////// // only set position when an expr is attatched // to the term ////////////////////////////////////////////////// if ( l_pathIter.key() -> pqexpr() && l_id != f_wildCard ) { /* MESSAGE(cerr, "=========="); debug(cerr, (void*)l_bv); debug(cerr, *l_bv); debug(cerr, i); debug(cerr, j); */ l_bv -> recordPositions(i, j); } j--; } else { /////////////////////////////////////////////////// // do not set bits for unlimitedWildCards that // begin or end the pattern /////////////////////////////////////////////////// if ( j < patternLength() - 1 ) l_bv -> setBitTo(j+1, 1); } i++; } /////////////////////////////////////////////////// // special treatment to the ? symbols: // OR S(?) back to each S's. /////////////////////////////////////////////////// BitVector* l_BitVectorWildCard = f_SVectors.findValue(&f_wildCard); hashTableIterator l_SVIter(f_SVectors); if ( l_BitVectorWildCard ) { while (++l_SVIter) { if ( *l_SVIter.key() != f_wildCard && *l_SVIter.key() != f_unlimitedWildCard ) { (*l_SVIter.value()) |= (*l_BitVectorWildCard); } } } /* #ifdef DEBUG l_SVIter.reset(); while (++l_SVIter) { debug(cerr, (*l_SVIter.key())); debug(cerr, (*l_SVIter.value())); } #endif */ } } unsigned int _match(LetterType* pattern, int n, LetterType* text, int m, LetterType wildCard, LetterType unlimitedWildCard ) { // A naive (brute force) string matching algorithm that handles // wild card (?) and unlimited wild card (*) symbols. unsigned int findMisMatch = false; for ( int i=0; i* elementPathNextPtr = 0; if ( elementPath ) elementPathNextPtr = new CC_TPtrDlistIterator(*elementPath); // loop over text string for ( int i=0; i positionArray() ) { //////////////////// // get a copy of S //////////////////// f_copyOfS -> setTo(*l_S); //debug(cerr, *patternPath); positionArrayIteratorT l_positionNext(*(l_S -> positionArray())); while (++ l_positionNext) { l_pr = l_positionNext.key(); //cerr << " calling patternPath -> fastGetAt(): " << (void*)patternPath << "l_pr.pathTermPos= " << l_pr.pathTermPos << endl; expr = patternPath -> fastGetAt(l_pr.pathTermPos) -> pqexpr(); /* debug(cerr, int(expr)); if ( expr ) { MESSAGE(cerr, "qualify checking is needed."); debug(cerr, *(elementPathNext -> key())); } */ if ( expr && expr->evaluate(elementPathNextPtr->key()->element()) == PQFalse ) { //MESSAGE(cerr, form("set position %d to 0", l_pr.bitPos)); f_copyOfS -> setBitTo(l_pr.bitPos, 0); } } ///////////////////////////////////////// // make l_S point at its modified copy ///////////////////////////////////////// l_S = f_copyOfS; } } else l_S = l_W; //////////////////////////////////////////////// // get unlimited wildcard's vector. //////////////////////////////////////////////// if ( l_U ) { l_I.setTo(l_R); l_I &= (*l_U); //MESSAGE(cerr, "l_I"); //debug(cerr, l_I); } //////////////////////////////////////////////// // shift the partial result vector right once //////////////////////////////////////////////// l_R.shiftRightOneBit(); //MESSAGE(cerr, "after l_R >> 1"); //debug(cerr, l_R); //////////////////////////////////////////////// // AND in this character's vector //////////////////////////////////////////////// if ( l_S ) { l_R &= (*l_S); //debug(cerr, *l_S); //MESSAGE(cerr, "after AND with l_S"); //debug(cerr, l_R); } else { /////////////////////////////////////////////// // this branch is impossible to reach. /////////////////////////////////////////////// //MESSAGE(cerr, "l_R set all bits to 0"); l_R.setAllBitsTo(0); } /////////////////////////////////////////////// // OR in unlimited wild char's vector. /////////////////////////////////////////////// if ( l_U ) { l_R |= l_I; //MESSAGE(cerr, "after OR with l_I"); //debug(cerr, l_R); } //debug(cerr, l_R); //MESSAGE(cerr, "==================="); /////////////////////////////////////////////// // Use this test to get the first matched position // if ( l_R.getBit(0) == 1 ) // return true; /////////////////////////////////////////////// } delete elementPathNextPtr; /////////////////////////////////////////////// // // the last symbol must match // /////////////////////////////////////////////// if ( l_R.getBit(0) == 1 ) return true; else return false; } basePathFeature::~basePathFeature() { delete f_path; delete f_featureSet; } PathFeature::~PathFeature() { delete f_encodedPath ; } unsigned int basePathFeature::operator==(const basePathFeature& pf) const { cerr << "Warning: basePathFeature::operator==() called\n"; return true; } unsigned int PathFeature::operator==(const PathFeature& pf) const { cerr << "Warning: PathFeature::operator==() called\n"; return true; } void pathSelector(BitVector& bv) { } unsigned int PathFeature::match(SSPath& p) { EncodedPath l_ep(&p); if ( f_path -> containSelector() == false ) return f_encodedPath -> match(l_ep, 0, 0); else return f_encodedPath -> match(l_ep, f_path, &p); } // ///////////////////////////////////////////////////////////////////////// // // class PathTable // // ///////////////////////////////////////////////////////////////////////// unsigned symHashFunc(const Symbol& s) { return s.hash(); } PathTable::PathTable() : f_lastSymIndex(0), f_lastSymIndexCount(0) { } PathTable::~PathTable() { f_pathFeatureList.clearAndDestroy(); for (unsigned int i = 0 ; i < f_lastSymIndexCount; i++) { //f_lastSymIndex[i].clearAndDestroy(); f_lastSymIndex[i] -> clear(); delete f_lastSymIndex[i]; } delete f_lastSymIndex; } LetterType PathTable::findIndex(SSPath& p) { return (LetterType) ((p.last() -> symbol()).id()); } void PathTable::initLastSymIndex() { f_lastSymIndexCount = gElemSymTab -> IdsAssigned()+1; f_lastSymIndex = new CC_TPtrDlist_PathFeature_Ptr_T[f_lastSymIndexCount]; for (unsigned int i=0; i; CC_TPtrDlistIterator l_pfIter(f_pathFeatureList); PathFeature* l_pathFeature = 0; LetterType x; while ( ++l_pfIter ) { l_pathFeature = l_pfIter.key(); x = findIndex( *(l_pathFeature->path()) ); //f_lastSymIndex[x] -> prepend(l_pathFeature); // backward order f_lastSymIndex[x] -> append(l_pathFeature); // select the matching rule // in the same order rules // appear in the // stylesheet } } FeatureSet* PathTable::getFeatureSet(SSPath& p) { if ( f_lastSymIndex == 0 ) { initLastSymIndex(); } int pids[3]; FeatureSet* fs[3]; fs[0] = getFeatureSet(findIndex(p), p, pids[0]); fs[1] = getFeatureSet(gElemSymTab -> wildCardId(), p, pids[1]); fs[2] = getFeatureSet(gElemSymTab -> unlimitedWildCardId(), p, pids[2]); int index = 0; int x = pids[0]; for ( int i=1; i<3; i++ ) { if ( pids[i] > x ) index = i; } return fs[index]; } FeatureSet* PathTable::getFeatureSet(int bucketIndex, SSPath& p, int& pathId) { CC_TPtrDlistIterator l_pathFeatureIter(*f_lastSymIndex[bucketIndex]); l_pathFeatureIter.reset(); PathFeature* l_pathFeature = 0; while ( ++l_pathFeatureIter ) { l_pathFeature = l_pathFeatureIter.key(); //debug(cerr, *(l_pathFeature->path())); //debug(cerr, *(l_pathFeature->featureSet())); if ( l_pathFeature -> match(p) ) { //MESSAGE(cerr, "match"); pathId = l_pathFeature -> id(); return l_pathFeature -> featureSet(); } } pathId = 0; return 0; } void PathTable::addPathFeatureSet(PathFeature* x) { //MESSAGE(cerr, "addPathFeatureSet():"); //debug(cerr, *(x->path())); //debug(cerr, *(x->featureSet())); if ( x -> path() -> containSelector() ) x -> path() -> fastGetIndex(); EncodedPath* l_epath = new EncodedPath(x -> path(), true); unsigned int id = f_pathFeatureList.entries()+1; x -> setEncodedPath(l_epath); x -> setID(id); f_pathFeatureList.insert(x); } ostream& operator<<(ostream& out, PathTable& pt) { CC_TPtrDlistIterator l_pfIter(pt.f_pathFeatureList); PathFeature* l_pathFeature = 0; while ( ++l_pfIter ) { l_pathFeature = l_pfIter.key(); out << *(l_pathFeature)->path() << ' ' << *(l_pathFeature->featureSet()) << endl; #ifdef DEBUG // this will cause errors if gTopOfStack is not set properly FeatureSet *set = l_pathFeature->featureSet()->evaluate(); out << *set << endl; delete set ; #endif } return out; } void PathFeatureList::appendList(PathFeatureList& list) { PathFeatureListIterator l_Iter(list); while ( ++ l_Iter ) { append(l_Iter.key()); } } PathFeatureList::~PathFeatureList() { clearAndDestroy(); }