NodeIterator.h

Go to the documentation of this file.
00001 /*
00002  * See the dyninst/COPYRIGHT file for copyright information.
00003  * 
00004  * We provide the Paradyn Tools (below described as "Paradyn")
00005  * on an AS IS basis, and do not warrant its validity or performance.
00006  * We reserve the right to update, modify, or discontinue this
00007  * software at any time.  We shall have no obligation to supply such
00008  * updates or modifications or any other form of support to you.
00009  * 
00010  * By your use of Paradyn, you understand and agree that we (or any
00011  * other person or entity with proprietary rights in Paradyn) are
00012  * under no obligation to provide either maintenance services,
00013  * update services, notices of latent defects, or correction of
00014  * defects for Paradyn.
00015  * 
00016  * This library is free software; you can redistribute it and/or
00017  * modify it under the terms of the GNU Lesser General Public
00018  * License as published by the Free Software Foundation; either
00019  * version 2.1 of the License, or (at your option) any later version.
00020  * 
00021  * This library is distributed in the hope that it will be useful,
00022  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00023  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00024  * Lesser General Public License for more details.
00025  * 
00026  * You should have received a copy of the GNU Lesser General Public
00027  * License along with this library; if not, write to the Free Software
00028  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00029  */
00030 
00031 // Implementations of Node iterators
00032 
00033 #if !defined(NODE_ITERATOR_H)
00034 #define NODE_ITERATOR_H
00035 
00036 #include "Node.h"
00037 #include "Edge.h"
00038 
00039 namespace Dyninst {
00040 
00041 // This is a pure virtual interface class
00042 class NodeIteratorImpl {
00043     friend class NodeIterator;
00044     
00045  public:
00046     virtual void inc() = 0;
00047     virtual void dec() = 0;
00048     virtual Node::Ptr get() = 0;
00049     virtual bool equals(NodeIteratorImpl *) = 0;
00050     virtual NodeIteratorImpl *copy() = 0;
00051 
00052     virtual ~NodeIteratorImpl() {};
00053 };
00054 
00055 // Types of node iteration: over a set of nodes
00056 class NodeIteratorSet : public NodeIteratorImpl {
00057  public:
00058     virtual void inc() { ++internal_; }
00059     virtual void dec() { --internal_; }
00060     virtual Node::Ptr get() { return *internal_; }
00061     virtual bool equals(NodeIteratorImpl *rhs) {
00062         NodeIteratorSet *tmp = dynamic_cast<NodeIteratorSet *>(rhs);
00063         if (tmp == NULL) return false;
00064         return internal_ == tmp->internal_;
00065     }
00066 
00067     virtual NodeIteratorImpl *copy() {
00068         return new NodeIteratorSet(internal_);
00069     }
00070 
00071     virtual ~NodeIteratorSet() {
00072         // Nothing to do
00073     }
00074     
00075     NodeIteratorSet(const std::set<Node::Ptr>::iterator iter) : internal_(iter) {};
00076 
00077  private:
00078     std::set<Node::Ptr>::iterator internal_;
00079 };
00080 
00081 class NodeFromEdgeSet : public NodeIteratorImpl {
00082  public:
00083     typedef enum {
00084         target,
00085         source,
00086         unset } iterType;
00087 
00088     virtual void inc() { ++internal_; }
00089     virtual void dec() { --internal_; }
00090     virtual Node::Ptr get() { 
00091         switch(type_) {
00092         case target:
00093             return (*internal_)->target();
00094         case source:
00095             return (*internal_)->source();
00096         default:
00097             return Node::Ptr();
00098         }
00099     }
00100     virtual bool equals(NodeIteratorImpl *rhs) {
00101         NodeFromEdgeSet *tmp = dynamic_cast<NodeFromEdgeSet *>(rhs);
00102         if (tmp == NULL) return false;
00103 
00104         return ((internal_ == tmp->internal_)  &&
00105                 (type_ == tmp->type_));
00106     }
00107     virtual NodeIteratorImpl *copy () {
00108         NodeIteratorImpl *tmp = new NodeFromEdgeSet(internal_, type_);
00109         return tmp;
00110     }
00111 
00112     virtual ~NodeFromEdgeSet() {};
00113 
00114     NodeFromEdgeSet(const std::set<Edge::Ptr>::iterator iter,
00115                    iterType type) : internal_(iter), type_(type) {};
00116 
00117  private:
00118     std::set<Edge::Ptr>::iterator internal_;
00119     iterType type_;
00120 };
00121 
00122 class NodeSearchIterator : public NodeIteratorImpl{
00123     friend class NodeIterator;
00124  public:
00125     // Share implementation, as DFS/BFS are very similar
00126     typedef enum {
00127         depth,
00128         breadth} Type;
00129     typedef enum {
00130         in,
00131         out} Direction;
00132 
00133     // This iterator linearizes access to a tree/graph structure.
00134     // Since we operate over a graph there may be cycles. This
00135     // is handled by keeping a visited set; once a node is encountered
00136     // it is placed in the visited set. 
00137     //
00138     // The iterator is defined to be "end" if the following is true:
00139     // 1) The current pointer is NULL;
00140     // The iterator is one step from "end" (that is, iter->inc == end) if the 
00141     // following is true:
00142     // 2) Current is non-NULL and every element in the worklist has been visited. 
00143     // Due to 2) above, we _must_ describe the worklist and visited sets in terms
00144     // of nodes, rather than iterators; given an iterator we cannot determine 
00145     // (without deep inspection) whether it contains an unvisited node. Deep inspection
00146     // really obviates the point, here. 
00147 
00148     // TODO: reverse iteration. 
00149 
00150     virtual void inc() {
00151         // If current is NULL, we're done
00152         if (!current) return;
00153 
00154         Node::Ptr next;
00155         // Iterate over the worklist and see if any element there
00156         // has not been visited.
00157         while (next == NULL && (!worklist.empty())) {
00158             next = popWorklist();
00159         }
00160         // If the worklist is empty, then set to end and
00161         // return
00162         if (worklist.empty()) {
00163             setToEnd();
00164             return;
00165         }
00166         assert(next != NULL);
00167 
00168         current = next;
00169         
00170         updateVisited(current);
00171         NodeIterator begin, end;
00172         getNext(begin, end);
00173         updateWorklist(begin, end);
00174     }
00175     virtual void dec() {
00176         // Unsupported
00177         assert(0); return;
00178     }
00179     virtual Node::Ptr get() { return current; }
00180     // Equality
00181     // 1) End == end, even if the internal data is not the same
00182     // 2) Otherwise, identical iterators are equal.
00183     virtual bool equals(NodeIteratorImpl *rhs) {
00184         NodeSearchIterator *tmp = dynamic_cast<NodeSearchIterator *>(rhs);
00185         if (!tmp) return false;
00186 
00187         if (end() && tmp->end()) return true;
00188         return ((current == tmp->current) &&
00189                 (type == tmp->type) &&
00190                 (direction == tmp->direction) &&
00191                 (worklist == tmp->worklist) &&
00192                 (visited == tmp->visited));
00193     }
00194 
00195     virtual NodeIteratorImpl *copy() {
00196         return new NodeSearchIterator(current, direction, type, worklist, visited);
00197     }
00198 
00199     NodeSearchIterator() : direction(in), type(depth) {};
00200     NodeSearchIterator(Node::Ptr cur, Direction d, Type t) : current(cur), direction(d), type(t) {
00201         updateVisited(current);
00202         NodeIterator begin, end;
00203         getNext(begin,end);
00204         updateWorklist(begin,end);
00205     };
00206     NodeSearchIterator(Node::Ptr cur, Direction d, Type t, std::deque<Node::Ptr> wl, std::set<Node::Ptr> v) :
00207         current(cur), direction(d), type(t), worklist(wl), visited(v) {};
00208 
00209     NodeSearchIterator(NodeIterator &rangeBegin, NodeIterator &rangeEnd, Direction d, Type t) :
00210         direction(d), type(t) {
00211         updateWorklist(rangeBegin, rangeEnd);
00212 
00213         if (worklist.empty()) return;
00214         current = popWorklist();
00215         updateVisited(current);
00216         NodeIterator begin, end;
00217         getNext(begin, end);
00218         updateWorklist(begin, end);
00219     }
00220 
00221     virtual ~NodeSearchIterator() {};
00222 
00223  private:
00224 
00225     bool end() {
00226         if (current == NULL) return true;
00227         return false;
00228     }
00229 
00230     void updateVisited(Node::Ptr &current) {
00231         assert(current);
00232         visited.insert(current);
00233     }
00234 
00235     // This is where the direction and type of iterator come in.
00236     // Direction: select whether we access the in set or out set of nodes.
00237     // Type: DFS: push to the front of the worklist; BFS: push to the back.
00238     void getNext(NodeIterator &begin, NodeIterator &end) {
00239         assert(current);
00240         switch (direction) {
00241         case in:
00242             current->ins(begin, end);
00243             break;
00244         case out:
00245             current->outs(begin, end);
00246             break;
00247         default:
00248             assert(0);
00249         }
00250     }
00251     void updateWorklist(NodeIterator &begin, NodeIterator &end) {
00252         for (; begin != end; begin++) {
00253             if (visited.find(*begin) == visited.end()) {
00254                 switch (type) {
00255                 case depth:
00256                     worklist.push_front(*begin);
00257                     break;
00258                 case breadth:
00259                     worklist.push_back(*begin);
00260                     break;
00261                 default:
00262                     assert(0);
00263                 }
00264             }
00265         }
00266     }
00267 
00268     Node::Ptr popWorklist() {
00269         if (worklist.empty()) return Node::Ptr();
00270         Node::Ptr tmp = worklist.front();
00271         worklist.pop_front();
00272         return tmp;
00273     }
00274 
00275     void setToEnd() {
00276         current = Node::Ptr();
00277         worklist.clear();
00278         visited.clear();
00279     }
00280 
00281     Node::Ptr current;
00282     Direction direction;
00283     Type type;
00284     std::deque<Node::Ptr> worklist;
00285     std::set<Node::Ptr> visited;
00286 };
00287 
00288 // And given a set to hold internally until the iterator goes away
00289 class NodeIteratorPredicateObj : public NodeIteratorImpl {
00290  public:
00291     virtual void inc() { 
00292         if (cur == end) return;
00293         cur = next;
00294         setNext();
00295     }
00296     virtual void dec() {  return; }
00297     virtual Node::Ptr get() { return *cur; }
00298     virtual bool equals(NodeIteratorImpl *rhs) {
00299         NodeIteratorPredicateObj *tmp = dynamic_cast<NodeIteratorPredicateObj *>(rhs);
00300         if (tmp == NULL) return false;
00301         return ((pred == tmp->pred) &&
00302                 (cur == tmp->cur) &&
00303                 (next == tmp->next) &&
00304                 (end == tmp->end));
00305     }
00306 
00307     virtual NodeIteratorImpl *copy() {
00308         return new NodeIteratorPredicateObj(pred, cur, next, end);
00309     }
00310 
00311     virtual ~NodeIteratorPredicateObj() {
00312         // Nothing to do
00313     }
00314     
00315     NodeIteratorPredicateObj(Graph::NodePredicate::Ptr p,
00316                     NodeIterator &c,
00317                     NodeIterator &n,
00318                     NodeIterator &e) :
00319         pred(p),
00320         cur(c), next(n), end(e) {};
00321     NodeIteratorPredicateObj(Graph::NodePredicate::Ptr p,
00322                              NodeIterator &b,
00323                              NodeIterator &e) :
00324         pred(p), cur(b), next(b), end(e) {
00325         setNext();
00326         // next is now a matching node. If the start wasn't,
00327         // then we need to increment...
00328         if ((cur != end) && !pred->predicate(*cur)) {
00329             inc();
00330         }
00331     }
00332     void setNext() {
00333         // Set next to the, well, next match
00334         if (next == end) return;
00335         do {
00336             ++next; 
00337         } while (next != end && !(pred->predicate(*next)));
00338     }
00339 
00340  private:
00341     Graph::NodePredicate::Ptr pred;
00342     // We're not allowing reverse iteration over this, since we really
00343     // don't want to suffer copy overhead. 
00344     NodeIterator cur, next, end;
00345 };
00346 
00347 // And given a set to hold internally until the iterator goes away
00348 class NodeIteratorPredicateFunc : public NodeIteratorImpl {
00349  public:
00350     virtual void inc() { 
00351         if (cur == end) return;
00352         cur = next;
00353         setNext();
00354     }
00355     virtual void dec() {  return; }
00356     virtual Node::Ptr get() { return *cur; }
00357     virtual bool equals(NodeIteratorImpl *rhs) {
00358         NodeIteratorPredicateFunc *tmp = dynamic_cast<NodeIteratorPredicateFunc *>(rhs);
00359         if (tmp == NULL) return false;
00360         return ((pred == tmp->pred) &&
00361                 (user_arg == tmp->user_arg) &&
00362                 (cur == tmp->cur) &&
00363                 (next == tmp->next) &&
00364                 (end == tmp->end));
00365     }
00366 
00367     virtual NodeIteratorImpl *copy() {
00368         return new NodeIteratorPredicateFunc(pred, user_arg, cur, next, end);
00369     }
00370 
00371     virtual ~NodeIteratorPredicateFunc() {
00372         // Nothing to do
00373     }
00374     
00375     NodeIteratorPredicateFunc(Graph::NodePredicateFunc p,
00376                               void *u, 
00377                               NodeIterator &c,
00378                               NodeIterator &n,
00379                               NodeIterator &e) :
00380         pred(p),
00381         user_arg(u),
00382         cur(c), next(n), end(e) {};
00383     NodeIteratorPredicateFunc(Graph::NodePredicateFunc p,
00384                               void *u,
00385                               NodeIterator &b,
00386                               NodeIterator &e) :
00387         pred(p), user_arg(u), cur(b), next(b), end(e) {
00388         setNext();
00389         // next is now a matching node. If the start wasn't,
00390         // then we need to increment...
00391         if ((cur != end) && !pred(*cur, user_arg)) {
00392             inc();
00393         }
00394     }
00395     void setNext() {
00396         // Set next to the, well, next match
00397         if (next == end) return;
00398         ++next;
00399         do {
00400             ++next; 
00401         } while (next != end && !(pred(*next, user_arg)));
00402     }
00403 
00404  private:
00405     Graph::NodePredicateFunc pred;
00406     void *user_arg;
00407     // We're not allowing reverse iteration over this, since we really
00408     // don't want to suffer copy overhead. 
00409     NodeIterator begin, cur, next, end;
00410 };
00411 
00412 }
00413 
00414 #endif
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated on 12 Jul 2013 for SymtabAPI by  doxygen 1.6.1