Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

support.H

Go to the documentation of this file.
00001 #ifndef SUPPORT_H
00002 #define SUPPORT_H
00003 
00004 #include "platform.H"
00005 #include "error.H"
00006 #include "ref.H"
00007 #include "hash.H"
00008 
00009 //YYY - Using new iostream wrapper
00010 #include "std/iostream.H"
00011 
00012 #define REF_CLASS(FOO)  FOO; typedef REFptr<FOO> FOO##ptr; class FOO
00013 #define FD_REF_CLASS(FOO)  FOO; typedef REFptr<FOO> FOO##ptr
00014 #define CSTR const STR
00015 #define brcase    break; case
00016 #define brdefault break; default
00017 
00018 // Helpful debugging statement
00019 #define PRINT_VAR(v) cerr << # v << " = '" << v << "'" << endl
00020 
00021 /* ------------------ class definitions --------------------- */
00022 class STR : public REFcounter {
00023  protected:
00024    char *_s;
00025    static HASH *strpool;
00026  public:
00027    static STR *null;
00028 
00029    STR()                    { _s = 0; }
00030    STR(const char *s)       { if (!strpool) strpool = new HASH(1024); 
00031    if (!s) s = "";
00032    strpool->add(s, _s); }
00033    STR(char        s)       { char str[2]; str[0]=s; str[1] = '\0'; 
00034    if (!strpool) strpool = new HASH(1024); 
00035    strpool->add(str, _s); }
00036    STR(const STR  &s)       { _s = s._s; }
00037    STR(int         x)       { char buff[1024];sprintf(buff,"%d", x);
00038    if (!strpool) strpool = new HASH(1024);
00039    strpool->add(buff, _s); }
00040    STR(double      d)       { char buff[1024];sprintf(buff,"%g", d);
00041    if (!strpool) strpool = new HASH(1024);
00042    strpool->add(buff, _s); }
00043    ~STR()                    { /* if (strpool) strpool->del(_s); */ }
00044    size_t len()               const { return strlen(_s); }
00045    STR  &operator = (CSTR &s)       { _s = s._s; return *this;}
00046    char *operator * ()        const { return _s; }
00047    char  operator [](int   i) const { return _s[i]; }
00048    bool  operator ==(CSTR &s) const { return _s == s._s; }
00049    STR*  operator + (CSTR &s) const { char buff[1024];
00050    sprintf(buff,"%s%s",_s,s._s);
00051    return new STR(buff); }
00052    bool  contains   (CSTR &s) const { return strstr(_s, s._s) != 0; }
00053    static double load_factor() { return strpool?strpool->load_factor():0.0; }
00054    friend inline ostream &operator<<(ostream &os, CSTR *s) { return os<< s->_s;}
00055 };
00056 
00057 #define Cstr_ptr const str_ptr
00058 #define Cstr_list const str_list
00059 class str_ptr;
00060 template <class T>
00061 #if defined(sgi) || defined(WIN32) || defined(_AIX) || defined(__GNUC__) || defined(__KCC) || (defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x510)
00062 class LIST;
00063 #else
00064 class LIST<T>;
00065 #endif
00066 
00067 typedef LIST<str_ptr> str_list;
00068 class str_ptr : public REFptr<STR> {
00069  public :
00070    static Cstr_ptr null;
00071    static Cstr_ptr &null_str() { if (null.p_ == 0) ((str_ptr &) null) = (STR::null = new STR("")); return null; }
00072 
00073    str_ptr()              : REFptr<STR>(new STR("")){ }
00074    str_ptr(Cstr_ptr   &p) : REFptr<STR>(p)          { }
00075    str_ptr(STR        *s) : REFptr<STR>(s?s:null.p_){ }
00076    str_ptr(const char *s) : REFptr<STR>(new STR(s)) { }
00077    str_ptr(char        c) : REFptr<STR>(new STR(c)) { }
00078    str_ptr(int         x) : REFptr<STR>(new STR(x)) { }
00079    str_ptr(double      d) : REFptr<STR>(new STR(d)) { }
00080    size_t  len        ()            const { return   p_->len(); }
00081    char    operator [](int i)       const { return   (*p_)[i];  }
00082    bool    operator ==(Cstr_ptr &s) const { return   *s.p_ == *p_;  }
00083    bool    operator !=(Cstr_ptr &s) const { return !(*s.p_ == *p_); }
00084    bool    operator !  ()           const { return (!p_ || !**p_ || !***p_) ; }
00085    operator STR*()          const { return (!*this) ? 0 : p_; }
00086    str_ptr operator + (Cstr_ptr &s) const { return str_ptr(*p_ + *s.p_); }
00087    str_ptr to_upper   () const;
00088    str_ptr to_lower    () const;
00089    bool    contains   (Cstr_ptr &s) const {return p_->contains(*s.p_);}
00090    // Does this string contain any of the strings in str_list s?
00091    bool    contains   (Cstr_list &s) const;
00092 };
00093 
00094 #ifdef JOT_AVOID_STATIC_LOCAL_INLINE_VAR
00095 #define RET_STAT_STR(s)  return str_ptr(s)
00096 #else
00097 #define RET_STAT_STR(s)  static str_ptr st(s); return st
00098 #endif
00099 
00100 // useful string constants:
00101 #define NULL_STR str_ptr::null_str()
00102 
00103 extern "C" {
00104    typedef int (* compare_func_t) (const void *, const void *);
00105 }
00106 
00107 
00108 #define BAD_IND -1
00109 //----------------------------------------------
00110 //
00111 //  ARRAY:
00112 //      Templated array-based list. It resizes
00113 //  itself as necessary. Constructor lets you
00114 //  specify the expected size.
00115 //
00116 //----------------------------------------------
00117 #define CARRAY const ARRAY
00118 template <class T>
00119 class ARRAY {
00120  protected:
00121    T*      _array;      // pointer to the data
00122    int     _num;        // number of elements in the array
00123    int     _max;        // max elements for currently allocated array
00124    bool    _unique;     // true means elements always added uniquely
00125    bool    _do_index;   // true means element indices are stored
00126 
00127    //******** PROTECTED METHODS ********
00128 
00129    //******** ARRAY INDEXING ********
00130 
00131    //   Derived ARRAY classes may override get_index(),
00132    //   set_index() and clear_index() so that removing an
00133    //   element from the array becomes an O(1) operation.
00134    //
00135    // For derived classes that manage element indices:
00136    virtual void   set_index(const T&, int /* index */)  const {}
00137    virtual void clear_index(const T&)                   const {}
00138 
00139    //******** REFptr METHODS ********
00140 
00141    // Needed by LIST (below -- ARRAY of REFptrs):
00142    // Clear element i:
00143    virtual void clear_ele  (int /* i */)  {}
00144 
00145    // Clear elements i thru j-1:
00146    virtual void clear_range(int i, int j) {
00147       if (_do_index)
00148          for ( ; i < j; i++)
00149             clear_index(_array[i]);
00150    }
00151 
00152    //******** ADDING ********
00153 
00154    virtual void  append_ele(const T& el) {
00155       // append element
00156       if (_do_index)
00157          set_index(el, _num);
00158       if (_num < _max) {
00159          _array[_num++] = el;
00160       } else {
00161          // In case the element referenced is a current item of
00162          // the array, we copy it before reallocating:
00163          T tmp = el;
00164          realloc();
00165          _array[_num++] = tmp;
00166       }
00167    }
00168 
00169  public:
00170 
00171    //******** MANAGERS ********
00172 
00173    ARRAY(int m=0) :
00174       _array(0), _num(0), _max(max(m,0)), _unique(0), _do_index(0) {
00175       if (_max) _array = new T[_max];
00176    }
00177    ARRAY(CARRAY<T>& l) :
00178       _array(0), _num(0), _max(0), _unique(0), _do_index(0) { *this = l; }
00179 
00180    virtual ~ARRAY() { clear(); delete [] _array;}
00181 
00182    //******** ACCESSORS/CONVENIENCE ********
00183 
00184    int  num()                   const   { return _num; }
00185    bool empty()                 const   { return (_num<=0); }
00186    bool valid_index(int k)      const   { return (k>=0 && k<_num); }
00187    void set_unique()                    { _unique = 1; }
00188 
00189    T* array()                           { return _array; }
00190    T& operator[](int j)         const   { assert(_array); return _array[j]; }
00191 
00192    // Convenience: return last or first element in array.
00193    // Don't call these on an empty array. (It would be bad):
00194    T& last() const { 
00195       assert(!empty());
00196       return _array[_num-1];
00197    }
00198    T& first() const { 
00199       assert(!empty());
00200       return _array[0];
00201    }
00202 
00203    //******** ARRAY INDEXING ********
00204 
00205    // Turn on array indexing and set the index of each element
00206    void begin_index() {
00207       _do_index = true;
00208       for (int i=0; i<_num; i++)
00209          set_index(_array[i], i);
00210    }
00211 
00212    // Turn off array indexing and clear indices
00213    void end_index() {
00214       for (int i=0; i<_num; i++)
00215          clear_index(_array[i]);
00216       _do_index = false;
00217    }
00218 
00219    bool is_indexing() const { return _do_index; }
00220 
00221    //******** MEMORY MANAGEMENT ********
00222 
00223    // Clear the array (i.e. make it empty):
00224    virtual void clear() {
00225       // If doing array indexing, clear all indices:
00226       if (_do_index)
00227          end_index();
00228       // For LISTs, assign 0 to REFptrs:
00229       clear_range(0,_num);
00230       _num=0;
00231    }
00232 
00233    // Truncate the array, leaving just the first n elements:
00234    virtual void truncate(int n) {
00235       if (valid_index(n)) {
00236          clear_range(n,_num);
00237          _num = n;
00238       } else err_msg("ARRAY::truncate: Error: bad index %d/%d", n, _num);
00239    }
00240 
00241    // The following is called automatically as necessary when the
00242    // array runs out of room, or explicitly when it's known that
00243    // the array will shortly need to contain a given number of
00244    // elements. The parameter 'new_max' tells how large the array
00245    // should be -- if the array is already that large nothing
00246    // happens. Otherwise, the array is reallocated and its
00247    // elements are copied to the new array. If new_max == 0, this
00248    // is interpreted as a request that _max should be
00249    // doubled. The exception is when _max is also 0 (meaning the
00250    // array itself is null), in which case _max is set to 1 and
00251    // the array is allocated to hold a single element.
00252    virtual void realloc(int new_max=0) {
00253       // If already big enough do nothing:
00254       if (new_max && new_max <= _max)
00255          return;
00256       // Decide on the new max value:
00257       _max = (new_max == 0) ? (_max ? _max*2 : 1) : new_max;
00258       // Allocate the new array:
00259       T *tmp = new T [_max]; assert(tmp);
00260 
00261       // Copy over existing elements:
00262       for (int i=0; i<_num; i++) {
00263          tmp[i] = _array[i];
00264          clear_ele(i);
00265       }
00266       // Replace old array with new one:
00267       delete [] _array;
00268       _array = tmp;
00269    }
00270 
00271    //******** CONTAINMENT ********
00272 
00273    // Exhaustive search to find index of element.
00274    // Returns BAD_IND on failure.
00275    virtual int get_index(const T &el) const {
00276       // If _do_index is set, must over-ride this method:
00277       for (int k = _num-1; k >= 0; k--)
00278          if (_array[k] == el)
00279             return k;
00280       return BAD_IND;
00281    }
00282 
00283    bool contains(const T &el) const { return get_index(el) >= 0; }
00284 
00285    //******** ADDING ********
00286 
00287    // Add the element uniquely.
00288    // (Do nothing if it's there already):
00289    bool add_uniquely(const T& el) {
00290       if (get_index(el) < 0) {
00291          append_ele(el);
00292          return true;
00293       }
00294       return false;
00295    }
00296 
00297    // Append element to end of list:
00298    void operator += (const T& el) {
00299       if (_unique)
00300          add_uniquely(el);
00301       else
00302          append_ele(el);
00303    }
00304 
00305    // add (same as +=):
00306    void add (const T& p) { *this += p; }     
00307 
00308    // Insert element at front of list:
00309    void push(const T& p) {
00310       insert(0,1);      // Make a space in 1st slot
00311       _array[0] = p;    // Copy element in there
00312       if (_do_index)
00313          set_index(p, 0);
00314    } 
00315 
00316    // Open up a gap of uninitialized elements in the array,
00317    // starting at index 'ind', extending for 'num' elements.
00318    // Presumably these elements then get assigned directly:
00319    void insert(int ind, int num) {
00320       if (_num+num > _max) 
00321          realloc(_num+num);
00322       _num += num;
00323       for (int i=_num-1; i>=ind+num; i--) {
00324          _array[i] = _array[i-num];
00325          if (_do_index)
00326             set_index(_array[i], i);
00327       }
00328    }
00329 
00330    //******** REMOVING ********
00331 
00332    // Search for given element, remove it:
00333    bool remove(int k) {
00334       // remove element k
00335       // return 1 on success, 0 on failure:
00336       if (valid_index(k)) {
00337          // replace element k with last element and shorten list:
00338          if (_do_index) {
00339             set_index(last(), k);
00340             clear_index(_array[k]);
00341          }
00342          _array[k] = _array[--_num];
00343          clear_ele(_num);
00344          return 1;
00345       } else if (k != BAD_IND) {
00346          err_msg("ARRAY::remove: invalid index %d", k);
00347          return 0;
00348       } else return 0; // assume the call to get_index() failed
00349    }
00350 
00351    // Remove the given element:
00352    bool operator -= (const T &el)         { return remove(get_index(el)); }
00353    bool          rem(const T &p)          { return (*this -= p); }
00354 
00355    // Remove and return the last element.
00356    // Don't call this on an empty array. (It would be bad):
00357    T pop() {
00358       // delete last element in list and return it:
00359       T tmp = last();
00360       remove(_num-1);
00361       return tmp;
00362    }
00363 
00364    // Remove element k, keeping remaining elements in order.
00365    // Returns true on success.
00366    bool pull_index(int k) {
00367       if (valid_index(k)) {
00368          if (_do_index)
00369             clear_index(_array[k]);
00370          for (int i=k; i<_num-1; i++) {
00371             _array[i] = _array[i+1];
00372             if (_do_index)
00373                set_index(_array[i], i);
00374          }
00375          clear_ele(--_num);
00376          return true;
00377       }
00378       if (k != BAD_IND)
00379          err_msg("ARRAY::pull: invalid index %d", k);
00380       return 0;
00381    }
00382    // Pull the given element:
00383    bool pull_element(const T& p) { return pull_index(get_index(p)); }
00384 
00385    //******** CYCLING ********
00386 
00387    // Cyclically shift elements p steps to the right.
00388    // If p < 0 it means shift left.
00389    virtual void shift(int p) {
00390       // Can't shift the empty list
00391       if (empty())
00392          return;
00393 
00394       int n = _num;
00395 
00396       // Make sure 0 <= p < n:
00397       if (p >= n)   p %= n;
00398       else if (p<0) p = div(p,n).rem + n;
00399 
00400       assert(p >=0 && p<n);
00401 
00402       if (p == 0)
00403          return;
00404 
00405       // Copy elements to temporary array, then copy them
00406       // back shifted:
00407       ARRAY<T> tmp = *this;      
00408       for (int k=0; k<n; k++)
00409          _array[(k + p)%n] = tmp[k];
00410 
00411       // Reset element indices if needed:
00412       if (_do_index)
00413          begin_index();
00414    }
00415 
00416    // Extract a section of an array
00417    ARRAY<T> extract(int start, int n) const {
00418       if (!(valid_index(start) && valid_index(start+n-1)))
00419          return ARRAY<T>();
00420       ARRAY<T> ret(n);
00421       for (int i=0; i<n; i++)
00422          ret += _array[i+start];
00423       return ret;
00424    }
00425 
00426    //******** ARRAY OPERATORS ********
00427 
00428    // See more operators below (outside ARRAY class definition)
00429 
00430    // Array concatenation
00431    ARRAY<T>& operator+=(CARRAY<T>& b) {
00432       if(!b.empty()) {
00433          realloc(num() + b.num());
00434          for (int i=0; i<b.num(); i++)
00435             *this += b[i];
00436       }
00437       return *this;
00438    }
00439 
00440    // Array assignment
00441    ARRAY<T>& operator=(CARRAY<T>& b) {
00442       // don't do anything if rhs already is lhs
00443       if (this == &b)
00444          return *this;
00445 
00446       clear();
00447       return *this += b;
00448    }
00449 
00450    // Pull elements of given array out of this one:
00451    void operator-=(CARRAY<T> &l) {
00452       for (int i=0; i < l.num(); i++)
00453          *this -= l[i];
00454    }
00455 
00456    //******** REORDERING ********
00457    virtual void reverse() {
00458       for (int i=0, j=_num-1; i<j; ++i, --j) {
00459          swap(_array[i],_array[j]);
00460          if (_do_index) {
00461             set_index(_array[i], i);
00462             set_index(_array[j], j);
00463          }
00464       }
00465    }
00466 
00467    //******** SORTING ********
00468    virtual void sort(compare_func_t compare) {
00469       qsort(_array, _num, sizeof(T), compare);
00470 
00471       // Reset element indices if needed:
00472       if (_do_index)
00473          begin_index();
00474    }
00475 };
00476 
00477 //----------------------------------------------
00478 // ARRAY OPERATORS
00479 //
00480 // The following are convenience operators for
00481 // pairs of arrays of different types, where
00482 // elements of the 2nd array can be cast to the
00483 // type of element in the first array.
00484 //----------------------------------------------
00485 
00486 // equality
00487 template <class T, class S>
00488 inline bool
00489 operator ==(CARRAY<T>& a, CARRAY<S> &b)
00490 {
00491    if (a.num() != b.num())
00492       return 0;
00493    for (int i = 0; i < b.num(); i++) {
00494       // Use !(x == y) because == should be available and != may not be
00495       if (!(a[i] == (T)b[i]))
00496          return 0;
00497    }
00498    return 1;
00499 }
00500 
00501 // concatenation
00502 template <class T, class S>
00503 inline ARRAY<T>&
00504 operator +=(ARRAY<T>& a, CARRAY<S>& b)
00505 {
00506    if(!b.empty()) {
00507       a.realloc(a.num() + b.num());
00508       for (int i=0; i<b.num(); i++)
00509          a += (T)b[i];
00510    }
00511    return a;
00512 }
00513 
00514 // concatenation
00515 template <class T, class S>
00516 inline ARRAY<T>
00517 operator +(CARRAY<T>& a, CARRAY<S>& b)
00518 {
00519    ARRAY<T> ret = a;
00520    return ret += b;
00521 }
00522 
00523 // XXX - hack for backward compatibility -- should just remove
00524 // occurrences of ARRAYptrs:
00525 #define ARRAYptrs ARRAY
00526 
00527 //----------------------------------------------
00528 //
00529 //  LIST:
00530 //
00531 //      same as ARRAY, but assumes the templated
00532 //      type T is derived from a REFptr, and calls
00533 //      Clear() on ref pointers as needed.
00534 //
00535 //----------------------------------------------
00536 #define CLIST const LIST
00537 template <class T>
00538 class LIST : public ARRAY<T> {
00539  protected:
00540    virtual void clear_ele  (int i)          { (*this)[i].Clear(); }
00541    virtual void clear_range(int i, int j) {
00542       ARRAY<T>::clear_range(i,j);
00543       for (int k=i; k < j; k++)
00544          clear_ele(k);
00545    }
00546  public:
00547    LIST(int m=0)     : ARRAY<T>(m) {}
00548    LIST(CLIST<T>& l) : ARRAY<T>(l) {}
00549 };
00550 
00551 template<class T>
00552 ostream &
00553 operator<< (ostream &os, const ARRAY<T> &array)
00554 {
00555    os << array.num() << endl;
00556    for (int i = 0; i < array.num(); i++) {
00557       os << array[i] << endl;
00558    }
00559    os << endl;
00560    return os;
00561 }
00562 
00563 template<class T>
00564 istream &
00565 operator>> (istream &is, ARRAY<T> &array)
00566 {
00567    int num; is >> num; array.clear();
00568    for (int i = 0; i < num; i++) {
00569       T x; is >> x; array += x;
00570    }
00571    return is;
00572 }
00573 
00574 str_list tokenize(Cstr_ptr &str, char delim=' ');
00575 str_list dir_list(Cstr_ptr &directory);
00576 
00577 // None of jot's code checks if select() was interrupted by a
00578 // signal (for example, SIGALRM used by IBM's MPI
00579 // implementation).  This should probably be fixed, but for now
00580 // we have a drop in replacement that we call instead.  If jot
00581 // will be running in a signal unsafe environment then you should
00582 // call the magic voodoo "signalSafeSelect();" as one of the
00583 // first things in main() before calling any jot stuff.
00584 
00585 #ifndef WIN32
00586 extern "C" int (*SELECT)(int, fd_set *, fd_set *, fd_set *, timeval *);
00587 
00588 extern "C" int Select(int maxfds, fd_set *reads, fd_set *writes, 
00589                       fd_set *errors, struct timeval *timeout);
00590 #endif
00591 
00592 inline void
00593 signalSafeSelect(void) 
00594 {
00595 #ifndef WIN32
00596    SELECT = Select;
00597 #endif
00598 }
00599 
00600 inline void
00601 fsleep(double dur)
00602 {
00603 #ifdef WIN32
00604    Sleep(int(dur * 1e3));
00605 #else
00606    struct timeval timeout;
00607    double         sleep_time = dur * 1e6;
00608    timeout.tv_sec  = 0;
00609    // XXX - there should be a better way to avoid warnings
00610 #if defined(macosx) || defined(sgi) || defined(__CYGWIN__)
00611    timeout.tv_usec = (long) sleep_time;
00612 #else
00613 #  ifdef linux
00614    timeout.tv_usec = (time_t) sleep_time;
00615 #else
00616    timeout.tv_usec = (suseconds_t) sleep_time;
00617 #  endif
00618 #endif
00619    SELECT(FD_SETSIZE, 0, 0, 0, &timeout);
00620 #endif
00621 }
00622 
00623 #endif  // SUPPORT_H
00624 
00625 /* end of file support.H */

Generated on Mon Sep 18 11:39:33 2006 for jot by  doxygen 1.4.4