Program Listing for File BitVectorRepr.h

Program Listing for File BitVectorRepr.h#

↰ Return to documentation for file (src/util/support/BitVectorRepr.h)

// See also, Sawyer::Container::BitVector ($ROSE/src/util/Sawyer/BitVector.h) which has a much richer API.
#ifndef BITVECTOR_DATA_REPR_H
#define BITVECTOR_DATA_REPR_H

#include <CountRefHandle.h>
#include <FunctionObject.h>
#include <DoublyLinkedList.h>
#include <map>
#include <sstream>
#include "rosedll.h"
#include <util/mlog.h>

class BitVectorReprImpl {
  unsigned* impl;
  unsigned  num;

  void operator = ( const BitVectorReprImpl& that)
  {}
 public:
  BitVectorReprImpl( unsigned size)
    {
      unsigned intsize = sizeof(unsigned);
      num = (size + intsize-1) / intsize ;
      impl = new unsigned[num];
      for (unsigned i = 0; i < num; ++i) {
        impl[i] = 0;
      }
    }
  BitVectorReprImpl( const BitVectorReprImpl& that)
    : num(that.num)
    {
      impl = new unsigned[that.num];
      for (unsigned i = 0; i < num; ++i) {
        impl[i] = that.impl[i];
      }
    }
  ~BitVectorReprImpl()
    { delete [] impl; }

  BitVectorReprImpl* Clone() const { return new BitVectorReprImpl(*this); }

  void operator |=( const BitVectorReprImpl& that)
  {
    assert(num == that.num);
    for (unsigned i = 0; i < num; ++i) {
      impl[i] |= that.impl[i];
    }
  }

  std::string toString() const
  {
    std::stringstream r;
    r <<  ":";
    for (unsigned i = 0; i < num; ++i) {
       r << impl[i];
    }
    r << ":";
    return r.str();
  }
  void operator &=( const BitVectorReprImpl& that)
  {
    assert(num == that.num);
    for (unsigned i = 0; i < num; ++i) {
      impl[i] &= that.impl[i];
    }
  }

  void complement()
    {
      for (unsigned i = 0; i < num; ++i) {
        impl[i] = ~impl[i];
      }
    }
  bool operator ==( const BitVectorReprImpl& that) const
  {
    assert(num == that.num);
    for (unsigned i = 0; i < num; ++i) {
      if (impl[i] != that.impl[i])
        return false;
    }
    return true;
  }

  bool has_member( unsigned index)  const
    {
      unsigned intsize = sizeof(unsigned);
      int i1 = index / intsize;
      int i2 = index % intsize;
      unsigned mask = 1 << i2;
      return impl[i1] & mask;
    }
  void add_member( unsigned index)
    {
      unsigned intsize = sizeof(unsigned);
      int i1 = index / intsize;
      int i2 = index % intsize;
      unsigned mask = 1 << i2;
      impl[i1] |= mask;
    }
  void delete_member( unsigned index)
    {
      unsigned intsize = sizeof(unsigned);
      int i1 = index / intsize;
      int i2 = index % intsize;
      unsigned mask = ~(1 << i2);
      impl[i1] &= mask;
    }
};

class ROSE_UTIL_API BitVectorRepr : public CountRefHandle<BitVectorReprImpl>
{
 public:
  BitVectorRepr( BitVectorReprImpl* _impl)
    : CountRefHandle <BitVectorReprImpl>(_impl) {}
  BitVectorRepr( const BitVectorReprImpl& _impl)
    : CountRefHandle <BitVectorReprImpl>(_impl) {}

  BitVectorRepr() {}
  BitVectorRepr (unsigned size)
    : CountRefHandle <BitVectorReprImpl>( new BitVectorReprImpl(size) ) {}
  BitVectorRepr( const BitVectorRepr& that)
    : CountRefHandle <BitVectorReprImpl>(that) {}
  BitVectorRepr& operator = (const BitVectorRepr& that)
  { CountRefHandle <BitVectorReprImpl>:: operator = (that); return *this; }

  bool operator ==( const BitVectorRepr& that)
  { return (ConstPtr() == that.ConstPtr()) ||
      (ConstPtr() && that.ConstPtr() && ConstRef() == that.ConstRef()); }

  bool IsNIL() const { return ConstPtr()==0; }
  bool operator !=( const BitVectorRepr& that)
  { return !operator==(that); }
  bool has_member( unsigned index)  const
    { return ConstPtr() != 0 && ConstRef().has_member(index); }
  void add_member( unsigned index)
    { UpdateRef().add_member(index); }
  void delete_member( unsigned index)
    { UpdateRef().delete_member(index); }
  void operator |= ( const BitVectorRepr& that)
  { UpdateRef() |= that.ConstRef(); }
  void operator &=( const BitVectorRepr& that)
  { UpdateRef() &= that.ConstRef(); }
  void complement()
    { UpdateRef().complement(); }
  std::string toString() const
    { return ConstRef().toString();  }
};

template <class Name, class Data>
class BitVectorReprBase
{
  struct DataEntry {
    Data data;
    Name name;
    int index;
    DataEntry( const Name& n, const Data& d, int i = 0)
      : data(d), name(n), index(i) {}
  };
  typedef DoublyLinkedListWrap<DataEntry> DataList;
  typedef std::map<Name, DoublyLinkedEntryWrap<DataEntry>* > DataMap;

  DataList datalist;
  DataMap datamap;

 public:
  typedef typename DoublyLinkedListWrap<DataEntry>::iterator iterator;
  iterator begin() const { return datalist.begin(); }
  iterator end() const { return datalist.end(); }

  BitVectorReprBase( const BitVectorReprBase<Name,Data>& that)
    {
      std::string name = "";
      for ( iterator p = that.datalist.begin(); !p.ReachEnd(); ++p) {
        DataEntry& cur = *p;
        DoublyLinkedEntryWrap<DataEntry>* e = datalist.AppendLast(cur);
        if (name != cur.name) {
           name = cur.name;
           datamap[name] = e;
        }
      }
    }
  BitVectorReprBase() {}
  unsigned size() const { return datalist.size(); }
  void add_data( const Name& n, const Data& d)
    {
      typename DataMap::iterator mp = datamap.find(n);
      if (mp == datamap.end()) {
        DoublyLinkedEntryWrap<DataEntry>* cur = datalist.AppendLast(DataEntry(n,d));
        datamap[n] = cur;
      }
      else {
        DoublyLinkedEntryWrap<DataEntry>* lp = (*mp).second;
        assert( lp->GetEntry().name == n);
        datalist.InsertAfter( DataEntry(n,d), lp);
      }
    }
  void finalize()
    {
      unsigned index = 0;
      for ( iterator p = begin(); !p.ReachEnd(); ++p, ++index) {
        DataEntry& cur = *p;
        cur.index = index;
      }
    }
  iterator find( const std::string& name) const
    {
      typename DataMap::const_iterator mp = datamap.find(name);
      if (mp == datamap.end()) {
        return end();
      }

      iterator lp( datalist, (*mp).second);
      return lp;
    }
  std::string get_name ( iterator p) const
    { return (*p).name; }
  Data get_data ( iterator p) const
    { return (*p).data; }
  int get_index( iterator p) const
    { return (*p).index; }
};

template <class Name, class Data>
class BitVectorReprGenerator
{
  BitVectorReprBase<Name, Data> base;
 public:
  BitVectorReprGenerator( const BitVectorReprBase<Name,Data>& b)
    : base(b) {}
  BitVectorRepr get_empty_set() const
    {  return BitVectorRepr(base.size()); }
  BitVectorRepr get_data_set( const Name& name) const
    {
      BitVectorRepr result(base.size());
      for (typename BitVectorReprBase<Name,Data>::iterator p
             = base.find(name);
           p != base.end() && base.get_name(p) == name; ++p) {
        int i = base.get_index( p );
        result.add_member(i);
      }
      return result;
    }

  void add_member( BitVectorRepr& repr, const Name& name, const Data& d) const
    {
      typename BitVectorReprBase<Name,Data>::iterator p = base.find(name);
      if (p == base.end()) {
           std::cerr << "Error: cannot find variable " << name << "\n";
           ROSE_ABORT();
      }
      for ( ;  p != base.end() && base.get_data(p) != d; ++p);
      if (p == base.end()) {
           std::cerr << "Error: cannot find data " << " for variable " << name << "\n";
           ROSE_ABORT();
      }
      repr.add_member( base.get_index(p));
    }

  void delete_member( BitVectorRepr& repr, const Name& name,
                      const Data& d) const
    {
      typename BitVectorReprBase<Name,Data>::iterator p = base.find(name);
      for ( ; p != base.end() && base.get_data(p) != d; ++p) ;
      assert( p != base.end());
      repr.delete_member(base.get_index(p));
    }

  void collect_member( const BitVectorRepr& repr,
                       CollectObject<Data>& collect) const
    {
      for (typename BitVectorReprBase<Name,Data>::iterator lp = base.begin();
           lp != base.end(); ++lp) {
        if (repr.has_member( base.get_index(lp)))
          collect( base.get_data(lp) );
      }
    }
  const BitVectorReprBase<Name,Data>& get_base() const { return base; }
};

#endif