+// This may look like C code, but it is really -*- C++ -*-
+/*
+Copyright (C) 1988 Free Software Foundation
+ written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of GNU CC.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY. No author or distributor
+accepts responsibility to anyone for the consequences of using it
+or for whether it serves any particular purpose or works at all,
+unless he says so in writing. Refer to the GNU CC General Public
+License for full details.
+
+Everyone is granted permission to copy, modify and redistribute
+GNU CC, but only under the conditions described in the
+GNU CC General Public License. A copy of this license is
+supposed to have been given to you along with GNU CC so you
+can know your rights and responsibilities. It should be in a
+file named COPYING. Among other things, the copyright notice
+and this notice must be preserved on all copies.
+*/
+
+#ifndef _BitString_h
+#ifdef __GNUG__
+#pragma once
+#pragma interface
+#endif
+
+#define _BitString_h 1
+
+#include <stream.h>
+#include <values.h>
+
+#define BITSTRBITS BITS(short)
+
+struct BitStrRep
+{
+ unsigned int len; // length in bits
+ unsigned short sz; // allocated slots
+ unsigned short s[1]; // bits start here
+};
+
+extern BitStrRep* BStr_alloc(BitStrRep*, const unsigned short*, int, int,int);
+extern BitStrRep* BStr_resize(BitStrRep*, int);
+extern BitStrRep* BStr_copy(BitStrRep*, const BitStrRep*);
+extern BitStrRep* cmpl(const BitStrRep*, BitStrRep*);
+extern BitStrRep* and(const BitStrRep*, const BitStrRep*, BitStrRep*);
+extern BitStrRep* or(const BitStrRep*, const BitStrRep*, BitStrRep*);
+extern BitStrRep* xor(const BitStrRep*, const BitStrRep*, BitStrRep*);
+extern BitStrRep* diff(const BitStrRep*, const BitStrRep*, BitStrRep*);
+extern BitStrRep* cat(const BitStrRep*, const BitStrRep*, BitStrRep*);
+extern BitStrRep* cat(const BitStrRep*, unsigned int, BitStrRep*);
+extern BitStrRep* lshift(const BitStrRep*, int, BitStrRep*);
+
+
+class BitString;
+class BitPattern;
+
+class BitStrBit
+{
+protected:
+ BitString& src;
+ unsigned int pos;
+
+ public:
+ BitStrBit(BitString& v, int p);
+ BitStrBit(const BitStrBit& b);
+ ~BitStrBit();
+ operator unsigned int() const;
+ int operator = (unsigned int b);
+ int operator == (unsigned int b) const ;
+ int operator != (unsigned int b) const ;
+};
+
+class BitSubString
+{
+ friend class BitString;
+ friend class BitPattern;
+
+protected:
+
+ BitString& S;
+ int pos;
+ int len;
+
+ BitSubString(BitString& x, int p, int l);
+ BitSubString(const BitSubString& x);
+public:
+ ~BitSubString();
+
+ void operator = (const BitString&);
+ void operator = (const BitSubString&);
+
+ int length() const;
+ int empty() const;
+
+ int OK() const;
+};
+
+class BitString
+{
+ friend class BitSubString;
+ friend class BitPattern;
+protected:
+ BitStrRep* rep;
+
+ int search(int, int, const unsigned short*, int, int) const;
+ int match(int, int, int, const unsigned short*,int,int) const;
+ BitSubString _substr(int first, int l);
+
+public:
+
+// constructors
+ BitString();
+ BitString(const BitString&);
+ BitString(const BitSubString& y);
+
+ ~BitString();
+
+ void operator = (unsigned int bit);
+ void operator = (const BitString& y);
+ void operator = (const BitSubString& y);
+
+// equality & subset tests
+
+ friend int operator == (const BitString&, const BitString&);
+ friend int operator != (const BitString&, const BitString&);
+ friend int operator < (const BitString&, const BitString&);
+ friend int operator <= (const BitString&, const BitString&);
+ friend int operator > (const BitString&, const BitString&);
+ friend int operator >= (const BitString&, const BitString&);
+
+// procedural versions of operators
+
+
+ friend void and(const BitString&, const BitString&, BitString&);
+ friend void or(const BitString&, const BitString&, BitString&);
+ friend void xor(const BitString&, const BitString&, BitString&);
+ friend void diff(const BitString&, const BitString&, BitString&);
+ friend void cat(const BitString&, const BitString&, BitString&);
+ friend void cat(const BitString&, unsigned int, BitString&);
+ friend void lshift(const BitString&, int, BitString&);
+ friend void rshift(const BitString&, int, BitString&);
+
+ friend void complement(const BitString&, BitString&);
+
+ friend int lcompare(const BitString&, const BitString&);
+
+// assignment-based operators
+// (constuctive versions decalred inline below
+
+ void operator |= (const BitString&);
+ void operator &= (const BitString&);
+ void operator -= (const BitString&);
+ void operator ^= (const BitString&);
+ void operator += (const BitString&);
+ void operator += (unsigned int b);
+ void operator <<=(int s);
+ void operator >>=(int s);
+
+ void complement();
+
+// individual bit manipulation
+
+ void set(int pos);
+ void set(int from, int to);
+ void set();
+
+ void clear(int pos);
+ void clear(int from, int to);
+ void clear();
+
+ void invert(int pos);
+ void invert(int from, int to);
+
+ int test(int pos) const;
+ int test(int from, int to) const;
+
+ void assign(int p, unsigned int bit);
+
+// indexing
+
+ BitStrBit operator [] (int pos);
+
+// iterators
+
+ int first(unsigned int bit = 1) const;
+ int last(unsigned int b = 1) const;
+
+ int next(int pos, unsigned int b = 1) const;
+ int previous(int pos, unsigned int b = 1) const;
+
+// searching & matching
+
+ int index(unsigned int bit, int startpos = 0) const ;
+ int index(const BitString&, int startpos = 0) const;
+ int index(const BitSubString&, int startpos = 0) const;
+ int index(const BitPattern&, int startpos = 0) const;
+
+ int contains(const BitString&) const;
+ int contains(const BitSubString&) const;
+ int contains(const BitPattern&) const;
+
+ int contains(const BitString&, int pos) const;
+ int contains(const BitSubString&, int pos) const;
+ int contains(const BitPattern&, int pos) const;
+
+ int matches(const BitString&, int pos = 0) const;
+ int matches(const BitSubString&, int pos = 0) const;
+ int matches(const BitPattern&, int pos = 0) const;
+
+// BitSubString extraction
+
+ BitSubString at(int pos, int len);
+ BitSubString at(const BitString&, int startpos = 0);
+ BitSubString at(const BitSubString&, int startpos = 0);
+ BitSubString at(const BitPattern&, int startpos = 0);
+
+ BitSubString before(int pos);
+ BitSubString before(const BitString&, int startpos = 0);
+ BitSubString before(const BitSubString&, int startpos = 0);
+ BitSubString before(const BitPattern&, int startpos = 0);
+
+ BitSubString after(int pos);
+ BitSubString after(const BitString&, int startpos = 0);
+ BitSubString after(const BitSubString&, int startpos = 0);
+ BitSubString after(const BitPattern&, int startpos = 0);
+
+// other friends & utilities
+
+ friend BitString common_prefix(const BitString&, const BitString&,
+ int pos = 0);
+ friend BitString common_suffix(const BitString&, const BitString&,
+ int pos = -1);
+ friend BitString reverse(const BitString&);
+
+ void right_trim(unsigned int bit);
+ void left_trim(unsigned int bit);
+
+// status
+
+ int empty() const ;
+ int count(unsigned int bit = 1) const;
+ int length() const;
+
+// convertors & IO
+
+ friend BitString atoBitString(const char* s, char f='0', char t='1');
+ friend const char* BitStringtoa(const BitString&, char f='0', char t='1');
+
+ friend BitString shorttoBitString(unsigned short);
+ friend BitString longtoBitString(unsigned long);
+
+ friend ostream& operator << (ostream& s, const BitString&);
+
+// misc
+
+ volatile void error(const char* msg) const;
+
+// indirect friends
+
+ friend const char* BitPatterntoa(const BitPattern& p,
+ char f='0',char t='1',char x='X');
+ friend BitPattern atoBitPattern(const char* s,
+ char f='0',char t='1',char x='X');
+
+ int OK() const;
+};
+
+
+class BitPattern
+{
+public:
+ BitString pattern;
+ BitString mask;
+
+ BitPattern();
+ BitPattern(const BitPattern&);
+ BitPattern(const BitString& p, const BitString& m);
+
+ ~BitPattern();
+
+ friend const char* BitPatterntoa(const BitPattern&, char f, char t, char x);
+ friend BitPattern atoBitPattern(const char* s, char f,char t, char x);
+ friend ostream& operator << (ostream& s, const BitPattern&);
+
+ int search(const unsigned short*, int, int) const;
+ int match(const unsigned short* xs, int, int, int) const;
+
+ int OK() const;
+};
+
+BitString operator & (const BitString& x, const BitString& y);
+BitString operator | (const BitString& x, const BitString& y);
+BitString operator ^ (const BitString& x, const BitString& y);
+BitString operator << (const BitString& x, int y);
+BitString operator >> (const BitString& x, int y);
+BitString operator - (const BitString& x, const BitString& y);
+BitString operator + (const BitString& x, const BitString& y);
+BitString operator + (const BitString& x, unsigned int y);
+BitString operator ~ (const BitString& x);
+int operator != (const BitString& x, const BitString& y);
+int operator>(const BitString& x, const BitString& y);
+int operator>=(const BitString& x, const BitString& y);
+
+extern BitStrRep _nilBitStrRep;
+extern BitString _nil_BitString;
+
+// primitive bit extraction
+
+// These must be inlined regardless of optimization.
+
+inline int BitStr_index(int l) { return (unsigned)(l) / BITSTRBITS; }
+
+inline int BitStr_pos(int l) { return l & (BITSTRBITS - 1); }
+
+#if defined(__OPTIMIZE__) || defined(USE_LIBGXX_INLINES)
+
+// constructors & assignment
+
+inline BitString::BitString() :rep(&_nilBitStrRep) {}
+
+inline BitString::BitString(const BitString& x) :rep(BStr_copy(0, x.rep)) {}
+
+inline BitString::BitString(const BitSubString& y)
+ :rep (BStr_alloc(0, y.S.rep->s, y.pos, y.pos+y.len, y.len)) {}
+
+inline BitString::~BitString()
+{
+ if (rep != &_nilBitStrRep) delete rep;
+}
+
+#if defined(__GNUG__) && !defined(NO_NRV)
+
+inline BitString shorttoBitString(unsigned short w) return r
+{
+ r.rep = BStr_alloc(0, &w, 0, BITSTRBITS, BITSTRBITS);
+}
+
+inline BitString longtoBitString(unsigned long w) return r
+{
+ unsigned short u[2];
+ u[0] = w & ((unsigned short)(~(0)));
+ u[1] = w >> BITSTRBITS;
+ r.rep = BStr_alloc(0, &u[0], 0, 2*BITSTRBITS, 2*BITSTRBITS);
+}
+
+#else
+
+inline BitString shorttoBitString(unsigned short w)
+{
+ BitString r; r.rep = BStr_alloc(0, &w, 0, BITSTRBITS, BITSTRBITS); return r;
+}
+
+inline BitString longtoBitString(unsigned long w)
+{
+ BitString r;
+ unsigned short u[2];
+ u[0] = w & ((unsigned short)(~(0)));
+ u[1] = w >> BITSTRBITS;
+ r.rep = BStr_alloc(0, &u[0], 0, 2*BITSTRBITS, 2*BITSTRBITS);
+ return r;
+}
+
+#endif
+
+inline void BitString::operator = (const BitString& y)
+{
+ rep = BStr_copy(rep, y.rep);
+}
+
+inline void BitString::operator = (unsigned int b)
+{
+ unsigned short bit = b;
+ rep = BStr_alloc(rep, &bit, 0, 1, 1);
+}
+
+inline void BitString::operator=(const BitSubString& y)
+{
+ rep = BStr_alloc(rep, y.S.rep->s, y.pos, y.pos+y.len, y.len);
+}
+
+inline BitSubString::BitSubString(const BitSubString& x)
+ :S(x.S), pos(x.pos), len(x.len) {}
+
+inline BitSubString::BitSubString(BitString& x, int p, int l)
+ : S(x), pos(p), len(l) {}
+
+inline BitSubString::~BitSubString() {}
+
+inline BitPattern::BitPattern(const BitString& p, const BitString& m)
+ :pattern(p), mask(m) {}
+
+inline BitPattern::BitPattern(const BitPattern& b)
+ :pattern(b.pattern), mask(b.mask) {}
+
+inline BitPattern::BitPattern() {}
+inline BitPattern::~BitPattern() {}
+
+
+// procedural versions of operators
+
+inline void and(const BitString& x, const BitString& y, BitString& r)
+{
+ r.rep = and(x.rep, y.rep, r.rep);
+}
+
+inline void or(const BitString& x, const BitString& y, BitString& r)
+{
+ r.rep = or(x.rep, y.rep, r.rep);
+}
+
+inline void xor(const BitString& x, const BitString& y, BitString& r)
+{
+ r.rep = xor(x.rep, y.rep, r.rep);
+}
+
+inline void diff(const BitString& x, const BitString& y, BitString& r)
+{
+ r.rep = diff(x.rep, y.rep, r.rep);
+}
+
+inline void cat(const BitString& x, const BitString& y, BitString& r)
+{
+ r.rep = cat(x.rep, y.rep, r.rep);
+}
+
+inline void cat(const BitString& x, unsigned int y, BitString& r)
+{
+ r.rep = cat(x.rep, y, r.rep);
+}
+
+inline void rshift(const BitString& x, int y, BitString& r)
+{
+ r.rep = lshift(x.rep, -y, r.rep);
+}
+
+inline void lshift(const BitString& x, int y, BitString& r)
+{
+ r.rep = lshift(x.rep, y, r.rep);
+}
+
+inline void complement(const BitString& x, BitString& r)
+{
+ r.rep = cmpl(x.rep, r.rep);
+}
+
+// operators
+
+
+inline void BitString::operator &= (const BitString& y)
+{
+ and(*this, y, *this);
+}
+
+
+inline void BitString::operator |= (const BitString& y)
+{
+ or(*this, y, *this);
+}
+
+inline void BitString::operator ^= (const BitString& y)
+{
+ xor(*this, y, *this);
+}
+
+inline void BitString::operator <<= (int y)
+{
+ lshift(*this, y, *this);
+}
+
+inline void BitString::operator >>= (int y)
+{
+ rshift(*this, y, *this);
+}
+
+inline void BitString::operator -= (const BitString& y)
+{
+ diff(*this, y, *this);
+}
+
+inline void BitString::operator += (const BitString& y)
+{
+ cat(*this, y, *this);
+}
+
+inline void BitString::operator += (unsigned int y)
+{
+ cat(*this, y, *this);
+}
+
+inline void BitString::complement()
+{
+ ::complement(*this, *this);
+}
+
+#if defined(__GNUG__) && !defined(NO_NRV)
+
+inline BitString operator & (const BitString& x, const BitString& y) return r
+{
+ and(x, y, r);
+}
+
+inline BitString operator | (const BitString& x, const BitString& y) return r
+{
+ or(x, y, r);
+}
+
+inline BitString operator ^ (const BitString& x, const BitString& y) return r
+{
+ xor(x, y, r);
+}
+
+inline BitString operator << (const BitString& x, int y) return r
+{
+ lshift(x, y, r);
+}
+
+inline BitString operator >> (const BitString& x, int y) return r
+{
+ rshift(x, y, r);
+}
+
+inline BitString operator - (const BitString& x, const BitString& y) return r
+{
+ diff(x, y, r);
+}
+
+inline BitString operator + (const BitString& x, const BitString& y) return r
+{
+ cat(x, y, r);
+}
+
+inline BitString operator + (const BitString& x, unsigned int y) return r
+{
+ cat(x, y, r);
+}
+
+inline BitString operator ~ (const BitString& x) return r
+{
+ complement(x, r);
+}
+
+#else /* NO_NRV */
+
+inline BitString operator & (const BitString& x, const BitString& y)
+{
+ BitString r; and(x, y, r); return r;
+}
+
+inline BitString operator | (const BitString& x, const BitString& y)
+{
+ BitString r; or(x, y, r); return r;
+}
+
+inline BitString operator ^ (const BitString& x, const BitString& y)
+{
+ BitString r; xor(x, y, r); return r;
+}
+
+inline BitString operator << (const BitString& x, int y)
+{
+ BitString r; lshift(x, y, r); return r;
+}
+
+inline BitString operator >> (const BitString& x, int y)
+{
+ BitString r; rshift(x, y, r); return r;
+}
+
+inline BitString operator - (const BitString& x, const BitString& y)
+{
+ BitString r; diff(x, y, r); return r;
+}
+
+inline BitString operator + (const BitString& x, const BitString& y)
+{
+ BitString r; cat(x, y, r); return r;
+}
+
+inline BitString operator + (const BitString& x, unsigned int y)
+{
+ BitString r; cat(x, y, r); return r;
+}
+
+inline BitString operator ~ (const BitString& x)
+{
+ BitString r; complement(x, r); return r;
+}
+
+#endif
+
+// status, matching
+
+inline int BitString::length() const
+{
+ return rep->len;
+}
+
+inline int BitString::empty() const
+{
+ return rep->len == 0;
+}
+
+inline int BitString::index(const BitString& y, int startpos) const
+{
+ return search(startpos, rep->len, y.rep->s, 0, y.rep->len);
+}
+
+inline int BitString::index(const BitSubString& y, int startpos) const
+{
+ return search(startpos, rep->len, y.S.rep->s, y.pos, y.pos+y.len);
+}
+
+inline int BitString::contains(const BitString& y) const
+{
+ return search(0, rep->len, y.rep->s, 0, y.rep->len) >= 0;
+}
+
+inline int BitString::contains(const BitSubString& y) const
+{
+ return search(0, rep->len, y.S.rep->s, y.pos, y.pos+y.len) >= 0;
+}
+
+inline int BitString::contains(const BitString& y, int p) const
+{
+ return match(p, rep->len, 0, y.rep->s, 0, y.rep->len);
+}
+
+inline int BitString::matches(const BitString& y, int p) const
+{
+ return match(p, rep->len, 1, y.rep->s, 0, y.rep->len);
+}
+
+inline int BitString::contains(const BitSubString& y, int p) const
+{
+ return match(p, rep->len, 0, y.S.rep->s, y.pos, y.pos+y.len);
+}
+
+inline int BitString::matches(const BitSubString& y, int p) const
+{
+ return match(p, rep->len, 1, y.S.rep->s, y.pos, y.pos+y.len);
+}
+
+inline int BitString::contains(const BitPattern& r) const
+{
+ return r.search(rep->s, 0, rep->len) >= 0;
+}
+
+inline int BitString::contains(const BitPattern& r, int p) const
+{
+ return r.match(rep->s, p, rep->len, 0);
+}
+
+inline int BitString::matches(const BitPattern& r, int p) const
+{
+ return r.match(rep->s, p, rep->len, 1);
+}
+
+inline int BitString::index(const BitPattern& r, int startpos) const
+{
+ return r.search(rep->s, startpos, rep->len);
+}
+
+inline int BitSubString::length() const
+{
+ return len;
+}
+
+inline int BitSubString::empty() const
+{
+ return len == 0;
+}
+
+inline int operator != (const BitString& x, const BitString& y)
+{
+ return !(x == y);
+}
+
+inline int operator>(const BitString& x, const BitString& y)
+{
+ return y < x;
+}
+
+inline int operator>=(const BitString& x, const BitString& y)
+{
+ return y <= x;
+}
+
+inline int BitString::first(unsigned int b) const
+{
+ return next(-1, b);
+}
+
+inline int BitString::last(unsigned int b) const
+{
+ return previous(rep->len, b);
+}
+
+inline int BitString::index(unsigned int bit, int startpos) const
+{
+ if (startpos >= 0)
+ return next(startpos - 1, bit);
+ else
+ return previous(rep->len + startpos + 1, bit);
+}
+
+inline void BitString::right_trim(unsigned int b)
+{
+ int nb = (b == 0)? 1 : 0;
+ rep = BStr_resize(rep, previous(rep->len, nb) + 1);
+}
+
+inline void BitString::left_trim(unsigned int b)
+{
+ int nb = (b == 0)? 1 : 0;
+ int p = next(-1, nb);
+ rep = BStr_alloc(rep, rep->s, p, rep->len, rep->len - p);
+}
+
+inline int BitString::test(int i) const
+{
+ return ((unsigned)(i) >= rep->len)? 0 :
+ ((rep->s[BitStr_index(i)] & (1 << (BitStr_pos(i)))) != 0);
+}
+
+
+// subscripting
+
+inline BitStrBit::BitStrBit(const BitStrBit& b) :src(b.src), pos(b.pos) {}
+
+inline BitStrBit::BitStrBit(BitString& v, int p) :src(v), pos(p) {}
+
+inline BitStrBit::~BitStrBit() {}
+
+inline BitStrBit::operator unsigned int() const
+{
+ return src.test(pos);
+}
+
+inline int BitStrBit::operator = (unsigned int b)
+{
+ src.assign(pos, b); return b;
+}
+
+inline int BitStrBit::operator == (unsigned int b) const
+{
+ return src.test(pos) == b;
+}
+
+inline int BitStrBit::operator != (unsigned int b) const
+{
+ return src.test(pos) != b;
+}
+
+inline BitStrBit BitString::operator [] (int i)
+{
+ if ((unsigned)(i) >= rep->len) error("illegal bit index");
+ return BitStrBit(*this, i);
+}
+
+inline BitSubString BitString::_substr(int first, int l)
+{
+ if (first < 0 || l <= 0 || (unsigned)(first + l) > rep->len)
+ return BitSubString(_nil_BitString, 0, 0) ;
+ else
+ return BitSubString(*this, first, l);
+}
+
+#endif
+
+#endif