List.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 // $Id: List.h,v
00032 
00033 #ifndef LIST_H
00034 #define LIST_H
00035 
00036 #include "common/h/language.h"
00037 
00038 #include <ostream>
00039 #include <string.h>
00040 
00041 #if !defined(DO_INLINE_P)
00042 #define DO_INLINE_P
00043 #endif
00044 
00045 #if !defined(DO_INLINE_F)
00046 #define DO_INLINE_F
00047 #endif
00048 
00049 #define ListHash(ptr, size) (((unsigned int)(ptr) % (unsigned int)(size)))
00050 
00051 template <class DataType> class List;
00052 template <class DataType, class KeyType> class ListBase;
00053 template <class Type> class StringList;
00054 template <class Type> class HTable;
00055 
00056 
00057 template <class DataType, class KeyType> class _list_node {
00058  public: 
00059    friend class ListBase<DataType, KeyType>;
00060    friend class StringList<DataType>;
00061    const KeyType      key;
00062    DataType           data;
00063    _list_node<DataType, KeyType>   *next;
00064 
00065    _list_node() : next(NULL) { }
00066    _list_node(DataType &dataA, const KeyType &keyA, 
00067           _list_node<DataType, KeyType> *nextA) : key(keyA), 
00068       data(dataA), next(nextA) { }
00069    explicit _list_node(const _list_node<DataType, KeyType> &from) :
00070       key(from.key), data(from.data), next(NULL) {
00071       // key and next need to be set after constructor
00072    }
00073    _list_node<DataType, KeyType> *get_next_node() { return next; }
00074 };
00075 
00076 
00077 template <class DataType, class KeyType> class _list_iterator {
00078   typedef _list_node<DataType, KeyType> node;
00079   mutable node *cur;
00080 
00081   void move_to_next() const {
00082     cur = cur->get_next_node();
00083   }
00084 
00085  public:
00086   _list_iterator(node *cur_) :
00087      cur(cur_) {    
00088   }
00089   node *getNode() { return cur; }
00090   // returns undefined result if iterator is the ending iterator
00091   DataType &operator*() {
00092     return cur->data;
00093   }
00094   const DataType &operator*() const {
00095     return cur->data;
00096   }
00097 
00098   _list_iterator operator++(int) const {  // postfix
00099     _list_iterator result = *this;
00100     move_to_next();
00101     return result;
00102   }
00103 
00104   _list_iterator operator++() const { // prefix
00105     move_to_next();
00106     return *this;
00107   }
00108   _list_iterator operator+(unsigned n) const {
00109      _list_iterator current = *this;
00110      for(unsigned i=0; i<n; i++) {
00111     current++;
00112      }
00113      return current;
00114   }
00115   bool operator==(const _list_iterator &iter) const {
00116      return (cur == iter.cur);
00117   }
00118   bool operator!=(const _list_iterator &iter) const {
00119      return (cur != iter.cur);
00120   }
00121 };
00122 
00123 
00124 template <class DataType, class KeyType> class ListBase {
00125  public:
00126    typedef _list_iterator<DataType, KeyType> iterator;
00127    typedef const _list_iterator<DataType, KeyType> const_iterator;
00128    typedef _list_node<DataType, KeyType> node;
00129 
00130    ListBase()  { head = NULL; }
00131    ListBase(const ListBase &fromList) {
00132       node *lastCopiedNode = NULL;
00133       node *headCopiedNode = NULL;
00134       for(const node *cur = fromList.head; cur; cur=cur->next) {
00135      node *curCopiedNode = new node(*cur);  // copy constructor
00136      if(lastCopiedNode)
00137         lastCopiedNode->next = curCopiedNode;
00138      else
00139         headCopiedNode = curCopiedNode;
00140       }
00141       head = headCopiedNode;
00142    }
00143    ~ListBase() {
00144       clear();
00145    }
00146    friend std::ostream &operator<<(std::ostream &os, 
00147                const ListBase<DataType, KeyType> &data) 
00148    {
00149     TYPENAME ListBase<DataType, KeyType>::iterator curr = data.begin();
00150     TYPENAME ListBase<DataType, KeyType>::iterator endMarker = data.end();
00151    
00152     for(; curr != endMarker; ++curr) {
00153       os << *curr << std::endl;
00154     }
00155     return os;
00156    }
00157 
00158    // returns the first element
00159    DataType &front() { return *(begin()); }  
00160    const DataType &front() const { return *(begin()); }
00161    
00162    // returns the last element
00163    DataType &back() { return getLastNode()->data; }
00164 
00165    void __push_front(DataType &data, const KeyType &key);
00166    void __push_back(DataType &data, const KeyType &key);
00167    bool __addIfUniqueKey(DataType &data, const KeyType &key) {
00168       DataType temp;
00169     
00170       bool foundIt = __find_with_key(key, &temp);
00171       if (!foundIt) {
00172      __push_front(data, key);
00173      return(true);
00174       } else {
00175      return(false);
00176       }
00177    }
00178    bool __addIfUniqueVal(DataType &data, const KeyType &key) {
00179       bool foundIt = __find_with_val(data);
00180       if (!foundIt) {
00181      __push_front(data, key);
00182      return(true);
00183       } else {
00184      return(false);
00185       }
00186    }
00187    bool __find_with_key(const KeyType &key, DataType *saveVal);
00188    bool __find_with_val(const DataType &saveVal) const;
00189    bool __remove_with_key(const KeyType &key);
00190    bool __remove_with_val(const DataType &val);
00191    void clear();
00192    iterator begin() {
00193       return iterator(head);
00194    }
00195    const_iterator begin() const {
00196       return iterator(head);
00197    }
00198 
00199    iterator end() {
00200       return iterator(NULL);  // a hypothetical element after the last element
00201    }
00202    const_iterator end() const {
00203       return iterator(NULL);  // a hypothetical element after the last element
00204    }
00205 
00206    int count()  const {
00207       int c;
00208       node *curr;
00209       
00210       for (curr=head,c=0; curr; curr=curr->next) c++;
00211       return(c);
00212    }
00213    bool isEmpty() { return (head == NULL); }
00214 
00215    // inserts an item before position at pos
00216    void insert(iterator &, DataType &) {
00217       // not implemented yet
00218    }
00219    void map (void (*map_function)(const DataType item)) {
00220       const node *temp_ptr = 0;
00221       
00222       if (!map_function) return;
00223       for (temp_ptr = head; temp_ptr; temp_ptr = temp_ptr->next)
00224      map_function (temp_ptr->data);
00225    }
00226    
00227  protected:
00228    node *getLastNode();
00229 
00230    node *head;
00231 };
00232 
00233 
00234 template <class DataType> class List : public ListBase<DataType, void*> {
00235    typedef void* KeyType;
00236  public:
00237    List() : ListBase<DataType, KeyType>() { };
00238    List(const List &fromList) : ListBase<DataType, KeyType>(fromList) { }
00239    ~List() { }  // ~ListBase will be called
00240    friend std::ostream &operator<<(std::ostream &os, 
00241                   const List<DataType> &data) {
00242       return operator<<(os, static_cast<ListBase<DataType, KeyType> >(data));
00243    }
00244 
00245    void push_front(DataType &data) {
00246       __push_front(data, static_cast<KeyType>(NULL));
00247    }
00248    void push_back(DataType &data) {
00249       __push_back(data, static_cast<KeyType>(NULL));
00250    }
00251    bool addIfUniqueVal(DataType &data) {
00252       return __addIfUniqueVal(data, NULL);
00253    }
00254    bool find(const DataType &val) const {
00255       return __find_with_val(val);
00256    }
00257    bool remove(const DataType &data) {
00258       return __remove_with_val(data);
00259    }
00260 };
00261 
00262 
00263 template <class DataType, class KeyType> class ListWithKey : 
00264 public ListBase<DataType, KeyType> {
00265  public:
00266    ListWithKey() : ListBase<DataType, KeyType>() { };
00267    ListWithKey(const ListWithKey &fromList) : 
00268       ListBase<DataType, KeyType>(fromList) {}
00269    ~ListWithKey() { }  // ~ListBase will be called
00270    friend std::ostream &operator<<(std::ostream &os,
00271                   const ListWithKey<DataType, KeyType> &data)
00272    {
00273       return operator<<(os, static_cast<ListBase<DataType, KeyType> >(data));
00274    }
00275 
00276    void push_front(DataType &data, KeyType &key) {
00277       __push_front(data, key);
00278    }
00279    void push_back(DataType &data, KeyType &key) {
00280       __push_back(data, key);
00281    }
00282    bool addIfUniqueKey(DataType &data, KeyType &key) {
00283       return __addIfUniqueKey(data, key);
00284    }
00285    bool find_with_key(KeyType &key, DataType *saveVal) {
00286       return __find_with_key(key, saveVal);
00287    }
00288    bool find_with_val(const DataType &val) const {
00289       return __find_with_val(val);
00290    }
00291    bool remove_with_key(KeyType &key) {
00292       return __remove_with_key(key);
00293    }
00294    bool remove_with_val(const DataType &data) {
00295       return __remove_with_val(data);
00296    }
00297 };
00298 
00299 
00300 template <class Type> std::ostream &operator<<(std::ostream &os, 
00301                                           HTable<Type> &data);
00302 
00303 template <class Type> class HTable {
00304     public:
00305     // placing function def here makes gcc happy 
00306   // VG(06/15/02): that nonstandard hack doesn't work with gcc 3.1...
00307   // let's do this properly:
00308   // (1) the function needs to be already declared (above)
00309   // (2) add <> after name here, so only that instantiation is friended
00310   // (3) the function is defined after this class
00311   // Of course, old broken compilers don't like the standard, so we just
00312   // write something that compiles (as was the case before).
00313   // BTW, is this operator used anywhere?
00314 #if (defined(i386_unknown_nt4_0) && _MSC_VER < 1300) || defined(mips_sgi_irix6_4)
00315   friend std::ostream& operator<< (std::ostream &os, HTable<Type> &data);
00316 #else
00317   friend std::ostream& operator<< <> (std::ostream &os, HTable<Type> &data);
00318 #endif
00319 
00320     HTable(Type data) { (void) HTable(); add(data, (void *) data); }
00321     DO_INLINE_F void add(Type data, void *key);
00322     DO_INLINE_F HTable(); 
00323     bool addUnique(Type data, void *key) {
00324         Type temp;
00325 
00326         bool foundIt = find(key, &temp);
00327         if (foundIt) {
00328         return(false);
00329         } else {
00330         add(data, key);
00331         return(true);
00332         }
00333     }
00334     DO_INLINE_F Type find(void *key);
00335     DO_INLINE_F bool remove(void *key);
00336         DO_INLINE_F HTable<Type> operator =(HTable<Type> arg); 
00337         Type operator *() {
00338             return(*currList);
00339         }
00340     // postfix
00341     Type operator ++(int) {
00342       Type curr;
00343       
00344       ++currList;
00345       curr = *currList;
00346       if (curr) return(curr);
00347       for (currHid++; currHid < tableSize; currHid++) {
00348         if (table[currHid]) {
00349           currList = *table[currHid];
00350           curr = *currList;
00351           if (curr) return(curr);
00352         }
00353       }
00354       return(NULL);
00355     }
00356     // prefix
00357     Type operator ++() {
00358         Type curr;
00359 
00360         ++currList;
00361             curr = *currList;
00362             if (curr) return(curr);
00363             for (currHid++; currHid < tableSize; currHid++) {
00364                 if (table[currHid]) {
00365                     currList = *table[currHid];
00366                     curr = *currList;
00367                     if (curr) return(curr);
00368                 }
00369         }
00370         return(NULL);
00371     }
00372     int count() {
00373         int i, total;
00374 
00375         total = 0;
00376         for (i=0; i < tableSize; i++) {
00377         if (table[i]) {
00378             total += table[i]->count();
00379         }
00380         }
00381         return(total);
00382     }
00383 
00384     private:
00385     List<Type> **table;
00386     List<Type> currList;
00387     int currHid;
00388     int tableSize;
00389 };
00390 
00391 
00392 template <class Type> std::ostream &operator<<(std::ostream &os,
00393                                           HTable<Type> &data) {
00394   int i, total;
00395   
00396   total = 0;
00397   for (i=0; i < data.tableSize; i++) {
00398     if (data.table[i]) {
00399       os << *data.table[i];
00400     }
00401   }
00402   return os;
00403 }
00404 
00405 
00406 template <class Type> DO_INLINE_F HTable<Type> HTable<Type>::operator =(HTable<Type> arg) {
00407     table = arg.table;
00408     tableSize = arg.tableSize;
00409 
00410     // find the first item.
00411     currHid = -1;
00412     ++(*this);
00413     return(*this);
00414 }
00415 
00416 template <class Type> DO_INLINE_F  HTable<Type>::HTable()
00417 { 
00418     table = NULL;
00419     currHid = 0;
00420     tableSize = 0;
00421 }
00422 
00423 template <class Type> DO_INLINE_F  Type HTable<Type>::find(void *key)
00424 {
00425     int hid;
00426 
00427     if (!tableSize) return(NULL);
00428     hid = ListHash(key, tableSize);
00429     if (hid <0 || hid > tableSize) abort();
00430     if (!table[hid]) {
00431     return(NULL);
00432     } else {
00433     return(table[hid]->find(key));
00434     }
00435 }
00436 
00437 template <class Type> DO_INLINE_F  void HTable<Type>::add(Type data, void *key)
00438 {
00439     int hid;
00440 
00441     if (!tableSize) {
00442     tableSize = 97;
00443     table = (List<Type>**) calloc(tableSize, sizeof(List<Type>*));
00444     }
00445     hid = ListHash(key, tableSize);
00446     if (hid <0 || hid > tableSize) abort();
00447     if (!table[hid]) {
00448     table[hid] = new(List<Type>);
00449     }
00450     table[hid]->add(data, key);
00451 }
00452 
00453 
00454 template <class Type> DO_INLINE_F  bool HTable<Type>::remove(void *key)
00455 {
00456     int hid;
00457 
00458     hid = ListHash(key, tableSize);
00459     if (hid <0 || hid > tableSize) abort();
00460     if (table[hid]) {
00461     return(table[hid]->remove(key));
00462     }
00463     return(false);
00464 }
00465 
00466 template <class Type> class StringList: public List<Type> {
00467     public:
00468     DO_INLINE_F Type find(void *key)
00469     {
00470       // This didn't use to have StringList<Type>::, but it barfs without it, 
00471       //so... - TLM (2002/08/06)
00472       typename StringList<Type>::node *it;
00473       
00474       for (it=this->head; it; it=it->next) {
00475         if (!strcmp((char *) it->key, (char *) key)) {
00476           return(it->data);
00477         }
00478       }
00479       return((Type) 0);
00480     }
00481 };
00482 
00483 
00484 #endif /* LIST_H */
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated on 12 Jul 2013 for SymtabAPI by  doxygen 1.6.1