Main Page   Modules   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

vbitset.hh

Go to the documentation of this file.
00001 /*
00002  *  File:       vbitset.hh
00003  *              $Id: vbitset.hh,v 1.11 2002/07/09 03:04:58 alec Exp $
00004  *
00005  *  Author:     Alec Panoviciu (alecu@email.com)
00006  *
00007  *  Comments:
00008  *
00009  *  Revision history:
00010  *
00011  *  $Log: vbitset.hh,v $
00012  *  Revision 1.11  2002/07/09 03:04:58  alec
00013  *  OWN_STRINGS bu*beep*it finally vanished
00014  *  gcc 3.1&mingw - related cleanups
00015  *
00016  *  Revision 1.10  2002/06/26 20:51:31  alec
00017  *  g++ 3.x happy
00018  *
00019  *  Revision 1.9  2002/05/27 03:04:16  alec
00020  *  doc update
00021  *
00022  *  Revision 1.8  2002/05/22 01:44:16  alec
00023  *  length update bugfix
00024  *
00025  *  Revision 1.7  2002/05/16 21:22:35  alec
00026  *  in-depth coppy operator added (oops :)
00027  *  destructor
00028  *
00029  *  Revision 1.6  2002/05/01 16:32:14  alec
00030  *  dfa ok. huh !
00031  *
00032  *  Revision 1.5  2002/05/01 09:18:26  alec
00033  *  - vBitset fixes
00034  *  - FOLLOWPOS written (not tested yet)
00035  *
00036  *  Revision 1.4  2002/04/30 16:24:38  alec
00037  *  tested the scanner ptree & vBitVector implementation -> ok
00038  *
00039  *  Revision 1.3  2002/04/30 09:22:32  alec
00040  *  bitset fixes
00041  *
00042  *  Revision 1.2  2002/04/29 17:55:41  alec
00043  *  regexps almost done
00044  *
00045  *  Revision 1.1  2002/04/29 09:40:01  alec
00046  *  *** empty log message ***
00047  *
00048  */
00049 
00050 
00051 /* 
00052   Copyright (C) 2002 Alexandru Panoviciu (alecu@email.com)
00053 
00054   This program is free software; you can redistribute it and/or modify
00055   it under the terms of the GNU General Public License as published by
00056   the Free Software Foundation; either version 2 of the License, or
00057   (at your option) any later version.
00058 
00059   This program is distributed in the hope that it will be useful,
00060   but WITHOUT ANY WARRANTY; without even the implied warranty of
00061   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00062   GNU General Public License for more details.
00063 
00064   You should have received a copy of the GNU General Public License
00065   along with this program; if not, write to the Free Software
00066   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00067 
00068  */
00069 
00070 #ifndef __VBITSET_HH__
00071 #define __VBITSET_HH__
00072 
00073 #include <memory>
00074 using namespace std;
00075 
00076 #include "debug.h"
00077 
00078 extern unsigned char vBitset_bit_count[];
00079 
00080 #ifdef DEBUG
00081   extern unsigned long vBitset_usecnt;
00082 #endif
00083 
00099 template<class W, class A = allocator<W> > class vBitset_base
00100 {
00101   /* NOTE: the implementation assumes at various points (mostly logic and
00102      relational operators implementations) that, if more storage is allocated
00103      than it is required for the actual length of the bitset, the extra bits are
00104      0. If this condition is false, the operators' behaviour is undefined (for
00105      instance, == will most certainly return the wrong results. This is ok for
00106      now, as a bit set can only grow but however, if a shrink operation will be
00107      implemented, it should take care to clean those remaining bits.
00108   */
00109 public:
00110 
00116   typedef W WordType;
00117 
00118   typedef A AllocatorType;
00119 
00123   typedef WordType *Mptr;
00124 
00128   typedef WordType &Mref;
00129 
00133   typedef size_t  SizeType;
00134 
00138   static const SizeType WORDBITS = sizeof(WordType) * 8;
00139 
00140   static const SizeType WORDBYTES = sizeof(WordType);
00141 
00142   static SizeType whichWord (SizeType bits)
00143   {
00144     return bits / WORDBITS;
00145   }
00146 
00147   static SizeType whichBit (SizeType bits)
00148   {
00149     return bits % WORDBITS;
00150   }
00151 
00152   static WordType maskBit (SizeType bits)
00153   {
00154     return static_cast<WordType>(1) << whichBit(bits);
00155   }
00156   
00161   class reference
00162   {
00163     friend class vBitset_base;
00164     
00165   public:
00166 
00167     reference (const vBitset_base &set_, SizeType bit_) :
00168       wp(set_.getWord(bit_)), mask(maskBit(bit_))
00169     {}
00170 
00171     reference (const reference &o) :
00172       wp(o.wp), mask(o.mask)
00173     {}
00174 
00175     reference () : wp(0), mask(0)
00176     {}
00177 
00178     ~reference ()
00179     {}
00180 
00181     reference& operator = (const reference &o)
00182     {
00183       wp = o.wp;
00184       mask = o.mask;
00185       return *this;
00186     }
00187 
00192     bool set (bool b = 1) const
00193     {
00194       check();
00195       if (b) *wp |= mask; else *wp &= ~mask;
00196       return b;
00197     }
00198 
00202     bool get () const
00203     {
00204       return *wp & mask;
00205     }
00206 
00212     bool eq (const reference &o)
00213     {
00214       return (wp == o.wp) && (mask == o.mask);
00215     }
00216 
00217     bool neq (const reference &o)
00218     {
00219       return !eq(o);
00220     }
00221 
00222     bool lt (const reference &o)
00223     {
00224       return (wp < o.wp) || ((wp == o.wp) && (mask < o.mask));
00225     }
00226 
00227     bool le (const reference &o)
00228     {
00229       return lt(o) || eq(o);
00230     }
00231 
00232     bool gt (const reference &o)
00233     {
00234       return !le(o);
00235     }
00236 
00237     bool ge (const reference &o)
00238     {
00239       return !lt(o);
00240     }
00241 
00242     /* @} */
00243 
00247     reference& next ()
00248     {
00249       if (mask == (static_cast<WordType>(1) << (WORDBITS - 1))) {
00250         mask = (WordType) 1;
00251         ++wp;
00252       } else {
00253         mask <<= 1;
00254       }
00255       return *this;
00256     }
00257 
00261     reference& prev ()
00262     {
00263       if (mask == static_cast<WordType>(1)) {
00264         mask = static_cast<WordType>(1) << (WORDBITS - 1);
00265         --wp;
00266       } else {
00267         mask >>= 1;
00268       }
00269       return this;
00270     }
00271 
00276     void check() const
00277     {
00278       /* yeahhhh SURE ! */
00279     }
00280 
00281   protected:
00282 
00287     void move (const vBitset_base &set_, SizeType bit_)
00288     {
00289       wp = set_.getWord(bit_);
00290       mask = maskBit(bit_);
00291     }
00292 
00293     
00294   private:
00295     Mptr wp;
00296     WordType mask;
00297   };
00298 
00304   vBitset_base (SizeType len_ = 1) :
00305     len(len_ ? len_ : 1)
00306   {
00307     SizeType cap = whichWord(len) + 1;
00308     data = M_alloc.allocate(cap);
00309     endOfData = data + cap;
00310     for (Mptr q = data; q < endOfData; *q++ = 0);
00311     updateLimits();
00312 #ifdef DEBUG
00313     vBitset_usecnt++;
00314 #endif
00315   }
00316 
00317   vBitset_base (const vBitset_base &o)
00318   {
00319     len = o.len;
00320     data = M_alloc.allocate(o.capacity());
00321     endOfData = data + o.capacity();
00322     for(Mptr p = data, q = o.data; p < endOfData; *p++ = *q++);
00323     updateLimits();
00324 #ifdef DEBUG
00325     vBitset_usecnt++;
00326 #endif
00327   }
00328 
00329 
00330   vBitset_base& operator = (const vBitset_base &o)
00331   {
00332     if (this == &o) return *this;
00333     M_alloc.deallocate(data, capacity());
00334     len = o.len;
00335     data = M_alloc.allocate(o.capacity());
00336     endOfData = data + o.capacity();
00337     for(Mptr p = data, q = o.data; p < endOfData; *p++ = *q++);
00338     updateLimits();
00339   }
00340 
00341   ~vBitset_base ()
00342   {
00343     M_alloc.deallocate(data, capacity());
00344   }
00345 
00346 
00351   reference operator [] (SizeType n)
00352   {
00353     return reference(*this, n);
00354   }
00355 
00356   reference begin ()
00357   {
00358     return _begin;
00359   }
00360 
00361   reference end ()
00362   {
00363     return _end;
00364   }
00365 
00370   void resize (SizeType n)
00371   {
00372     grow(n);
00373   }
00374 
00378   SizeType size () const
00379   {
00380     return len;
00381   }
00382 
00386   SizeType length () const
00387   {
00388     return size();
00389   }
00390 
00395   SizeType capacity () const
00396   {
00397     return endOfData - data;
00398   }
00399 
00403   bool all0 () const
00404   {
00405     return count1() == 0;
00406   }
00407 
00411   bool all1 () const
00412   {
00413     return !all0();
00414   }
00415 
00419   SizeType count1 () const
00420   {
00421     SizeType res = 0;
00422     
00423     for (unsigned char* p = (unsigned char *) data;
00424          p < (unsigned char *)endOfData; p++)
00425     {
00426       res += vBitset_bit_count[*p];
00427     }
00428 
00429     return res;
00430   }
00431 
00435   SizeType count0 () const
00436   {
00437     return length() - count1();
00438   }
00439 
00443   void flip ()
00444   {
00445     for (Mptr q = data; q < endOfData; q++) *q = ~*q;
00446   }
00447 
00448   void doOr (const vBitset_base &o)
00449   {
00450     Mptr p = data, q = o.data;
00451     if (capacity() < o.capacity()) {
00452       while (p < endOfData) *p++ |= *q++;
00453       grow_fill(o.length(), q); // 0 | q[i] == q[i]
00454     } else {
00455       while (q < o.endOfData) *p++ |= *q++; // 0 | p[i] == p[i]
00456       if (o.len > len) { // capacity == o.capacity, but o.len > len
00457         len = o.len;
00458         updateLimits();
00459       }
00460     }
00461   }
00462   
00463   vBitset_base& operator |= (const vBitset_base &o)
00464   {
00465     doOr(o);
00466     return *this;
00467   }
00468 
00469   void doAnd (const vBitset_base &o)
00470   {
00471     Mptr p = data, q = o.data;
00472     if (capacity() < o.capacity()) {
00473       while (p < endOfData) *p++ &= *q++;
00474       grow(o.length()); // 0 & q[i] == 0
00475     } else {
00476       while (q < o.endOfData) *p++ &= *q++;
00477       while (p < endOfData) *p++ = 0; // 0 & p[i] == 0
00478       if (o.len > len) { // capacity == o.capacity, but o.len is actually > len
00479         len = o.len;
00480         updateLimits();
00481       }
00482     }
00483   }
00484   
00485   vBitset_base& operator &= (const vBitset_base &o)
00486   {
00487     doAnd(o);
00488     return *this;
00489   }
00490 
00497   bool operator == (const vBitset_base &o) const
00498   {
00499     if (this == &o) return true;
00500 
00501     if (o.capacity() > capacity()) return o == *this;
00502 
00503     // pre: capacity() >= o.capacity()
00504     Mptr p = data, q = o.data;
00505     while (q < o.endOfData) if (*p++ != *q++) return false;
00506     while (p < endOfData) if (*p++ != static_cast<WordType>(0)) return false;
00507     return true;
00508   }
00509 
00510   bool operator != (const vBitset_base &o) const
00511   {
00512     return ! (*this== o);
00513   }
00514 
00515   void clear ()
00516   {
00517     for (Mptr p = data; p < endOfData; *p++ = static_cast<WordType>(0));
00518     len = 1;
00519     updateLimits();
00520   }
00521   
00522 protected:
00523 
00527   Mptr getWord (SizeType n) const
00528   {
00529     return data + whichWord(n);
00530   }
00531 
00536   void grow (SizeType n)
00537   {
00538     SizeType newCap = whichWord(n) + 1;
00539     if (capacity() < newCap)
00540     {
00541       Mptr q = data, pS = M_alloc.allocate(newCap), pE = pS;
00542     
00543       while (q < endOfData) *pE++ = *q++;
00544       while (pE < pS + newCap) *pE++ = static_cast<WordType>(0);
00545     
00546       M_alloc.deallocate(data, capacity());
00547     
00548       data = pS;
00549       endOfData = pE;
00550     }
00551     len = n;
00552     updateLimits();
00553   }
00554 
00559   void grow_fill (SizeType n, Mptr d)
00560   {
00561     SizeType newCap = whichWord(n) + 1;
00562     if (capacity() < newCap)
00563     {
00564       Mptr q = data, pS = M_alloc.allocate(newCap), pE = pS;
00565       
00566       while (q < endOfData) *pE++ = *q++;
00567       while (pE < pS + newCap) *pE++ = *d++;
00568       
00569       M_alloc.deallocate(data, capacity());
00570       
00571       data = pS;
00572       endOfData = pE;
00573     }
00574     len = n;
00575     updateLimits();
00576   }
00577 
00581   void updateLimits ()
00582   {
00583     _begin.move(*this, 0);
00584     _end.move(*this, len);
00585   }
00586   
00587 private:
00588 
00592   Mptr data;
00593 
00597   Mptr endOfData;
00598 
00602   SizeType len;
00603 
00607   reference _begin;
00608 
00612   reference _end;
00613   
00614   static AllocatorType M_alloc;
00615 };
00616 
00617 
00618 typedef vBitset_base<unsigned long> vBitset;
00619 
00620 template<class W, class A>
00621 vBitset_base<W, A> operator | (const vBitset_base<W, A> &a,
00622                                const vBitset_base<W, A> &b)
00623 {
00624   vBitset_base<W, A> res(a);
00625   res |= b;
00626   return res;
00627 }
00628 
00629 template<class W, class A>
00630 vBitset_base<W, A> operator & (const vBitset_base<W, A> &a,
00631                                const vBitset_base<W, A> &b)
00632 {
00633   vBitset_base<W, A> res(a);
00634   res &= b;
00635   return res;
00636 }
00637 
00638 template<class W, class A>
00639 vBitset_base<W, A> operator ^ (const vBitset_base<W, A> &a,
00640                                const vBitset_base<W, A> &b)
00641 {
00642   vBitset_base<W, A> res(a);
00643   res ^= b;
00644   return res;
00645 }
00646 
00647 template<class W, class A>
00648 vBitset_base<W, A> operator << (const vBitset_base<W, A> &a,
00649                                 typename vBitset_base<W, A>::SizeType n)
00650 {
00651   vBitset_base<W, A> res(a);
00652   res <<= n;
00653   return res;
00654 }
00655 
00656 template<class W, class A>
00657 vBitset_base<W, A> operator >> (const vBitset_base<W, A> &a,
00658                                 typename vBitset_base<W, A>::SizeType n)
00659 {
00660   vBitset_base<W, A> res(a);
00661   res >>= n;
00662   return res;
00663 }
00664 
00665 #endif /* #ifndef __VBITSET_HH__ */

Generated at Tue Jul 9 21:05:46 2002 for CppCC by doxygen1.2.8.1 written by Dimitri van Heesch, © 1997-2001