123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605 |
- /*
- * 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 libraries 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<PathTerm> 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<LetterType, BitVector> 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<n; i++ ) { // over the "text" string
- for ( int j=0; j<m; j++ ) { // over the pattern
- if ( pattern[j] == wildCard ) {
- continue;
- } else
- if ( pattern[j] == unlimitedWildCard ) {
- for (;;) {
- j++;
- if ( j == m )
- return true;
- if ( pattern[j] != unlimitedWildCard )
- break;
- }
- for ( int x=i+1; x<n; x++ ) {
- if ( text[x] == pattern[j] )
- if (
- _match(
- &pattern[j], m-j,
- &text[x], n-x,
- wildCard, unlimitedWildCard
- ) == true
- )
- return true;
-
- }
- } else {
- if ( pattern[j] != text[i] ) {
- findMisMatch = true;
- break;
- }
- }
- }
- if ( findMisMatch == false )
- return true;
- }
- return false;
- }
- unsigned int
- EncodedPath::match(EncodedPath& text, SSPath* patternPath, SSPath* elementPath)
- {
- ////////////////////////////////////////////////
- // text: the encoded string for the element path
- // elementPath: the element path
- //
- // this: the encoded string for the pattern string
- // patternPath: the pattern path
- ////////////////////////////////////////////////
- ////////////////////////////////////////////////
- // the unlimited wildcard vector
- ////////////////////////////////////////////////
- BitVector* l_U = f_SVectors.findValue(&f_unlimitedWildCard);
- if ( l_U && patternLength() == 0 )
- return true;
- ////////////////////////////////////////////////
- // the wildcard vector
- ////////////////////////////////////////////////
- BitVector* l_W = f_SVectors.findValue(&f_wildCard);
- // the S vector of each Letter, including that for '?'
- BitVector* l_S = 0;
- // the accumulated result vector
- BitVector l_R(patternLength(), 0);
- // placeholder for '*''s contribution
- BitVector l_I(patternLength(), 0);
- // hole position record of each path term in the pattern path
- posRecord l_pr;
- // expr pointer of each path term in the pattern path
- PQExpr* expr = 0;
- CC_TPtrDlistIterator<PathTerm>* elementPathNextPtr = 0;
- if ( elementPath )
- elementPathNextPtr = new CC_TPtrDlistIterator<PathTerm>(*elementPath);
- // loop over text string
- for ( int i=0; i<text.length(); i++) {
- if ( elementPath )
- ++(*elementPathNextPtr);
- //MESSAGE(cerr, "===================");
- //debug(cerr, text.f_array[i]);
- ////////////////////////////////////////////////
- // get this character's vector, including '?'s
- ////////////////////////////////////////////////
- l_S = f_SVectors.findValue(&text.f_array[i]);
-
- if ( l_S ) {
- //debug(cerr, (void*)l_S);
- //debug(cerr, *l_S);
- //MESSAGE(cerr, "checking qualifies");
- //////////////////////
- // check qualifies.
- //////////////////////
- if ( patternPath && l_S -> 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<f_lastSymIndexCount; i++)
- f_lastSymIndex[i] = new CC_TPtrDlist<PathFeature>;
-
- CC_TPtrDlistIterator<PathFeature> 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<PathFeature> 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<PathFeature> 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();
- }
|