// 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) based on code by Marc Shapiro (shapiro@sor.inria.fr) This file is part of the GNU C++ Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef _MPlex_h #ifdef __GNUG__ #pragma interface #endif #define _MPlex_h 1 #include ".Plex.h" // Number of bits per long, used in MChunk bit map operations #define _MAP_BITS 32 class MChunk : public IChunk { protected: unsigned long* map; // bitmap of slots int unused; // number of unused internal slots void mark(int); // bitmap operations void free(int); int valid(int) const; public: MChunk(* d, // ptr to array of elements int base_idx, // initial indices int low_idx, // & initially clear map int fence_idx, int top_idx); ~MChunk(); // virtuals int first_index() const; int last_index() const; int succ(int idx) const; int pred(int idx) const; * first_pointer() const; * last_pointer() const; * succ(*) const; * pred(*) const; int empty() const; int full() const; int valid_index(int i) const; int valid_pointer(const * p) const; * grow_high (); * grow_low (); void shrink_high (); void shrink_low (); void clear(int); void cleardown(int); int OK() const; // extensions int unused_indices() const; // how many free slot in low..fence? int unused_index() const; // return index of free slot int del(int i); // delete data indexed by i // return true if was present int undel(int idx); // un-delete data indexed by i // return true if already present void reset_low(); // reset low = lowest valid index; void reset_high(); // same for high }; class MPlex: public Plex { MChunk* ch; // cached chunk int unused; // # of free slots between low & fence void make_initial_chunks(int up = 1); void cache(int idx) const; void cache(const * p) const; int dopred(int) const; int dosucc(int) const; void set_cache(const MChunk* t) const; // logically, // not physically const public: MPlex(); // set low = 0; // fence = 0; // csize = default MPlex(int ch_size); // low = 0; // fence = 0; // csize = ch_size MPlex(int lo, // low = lo; int ch_size); // fence=lo // csize = ch_size MPlex(int lo, // low = lo int hi, // fence = hi+1 const initval,// fill with initval, int ch_size = 0); // csize= ch_size // or fence-lo if 0 MPlex(const MPlex&); void operator= (const MPlex&); // virtuals & high_element (); & low_element (); const & high_element () const; const & low_element () const; Pix first() const; Pix last() const ; void prev(Pix& ptr) const; void next(Pix& ptr) const; int owns(Pix p) const; & operator () (Pix p); const & operator () (Pix p) const; int low() const; int high() const; int valid(int idx) const; void prev(int& idx) const; void next(int& x) const; & operator [] (int index); const & operator [] (int index) const; int Pix_to_index(Pix p) const; Pix index_to_Pix(int idx) const; int can_add_high() const; int can_add_low() const; int full() const; int add_high(const elem); int del_high (); int add_low (const elem); int del_low (); void clear(); int OK () const; // extensions int count() const; // # valid elements int available() const; // # deleted elements int unused_index()const; // return index of a deleted elem Pix unused_Pix() const; // return Pix of a deleted elem int del_index(int idx); // logically delete at idx; // return true if was present int del_Pix(Pix p); // delete at p void undel_index(int idx); // undelete at idx; void undel_Pix(Pix p); // undelete at p; void adjust_bounds(); // reset lo, hi to lowest & // highest valid indices int add(const elem); // add anywhere }; inline MChunk:: ~MChunk() { delete map; } inline void MChunk::mark(int idx) { unsigned int i = idx - base; map[i / _MAP_BITS] |= 1 << (i & (_MAP_BITS - 1)); } inline void MChunk::free(int idx) { unsigned int i = idx - base; map[i / _MAP_BITS] &= ~(1 << (i & (_MAP_BITS - 1))); } inline int MChunk::valid(int idx) const { unsigned int i = idx - base; return map[i / _MAP_BITS] & (1 << (i & (_MAP_BITS - 1))); } inline int MChunk:: valid_index(int i) const { return i >= low && i < fence && valid(i); } inline int MChunk:: valid_pointer(const * p) const { int i = ((int)p - (int)data) / sizeof(); return i >= 0 && i < (fence - base) && (map[(unsigned)i / _MAP_BITS] & (1 << (i & (_MAP_BITS - 1)))); } inline int MChunk::empty() const { return fence - low - unused == 0; } inline int MChunk::full() const { return unused + (top - fence) + (low - base) == 0; } inline int MChunk::succ(int idx) const { int i = (idx < low)? low : idx + 1; while (i < fence && !valid(i)) ++i; return i; } inline int MChunk::pred(int idx) const { int i = (idx > fence)? (fence - 1) : idx - 1; while (i >= low && !valid(i)) --i; return i; } inline int MChunk::unused_indices() const { return unused; } inline * MChunk:: grow_high () { if (!can_grow_high()) full_error(); mark(fence); return &(data[fence++ - base]); } inline * MChunk:: grow_low () { if (!can_grow_low()) full_error(); mark(--low); return &(data[low - base]); } inline void MChunk::reset_low() { while (low < fence && !valid(low)) { --unused; ++low; } } inline void MChunk::reset_high() { while (fence > low && !valid(fence - 1)) { --unused; --fence; } } inline int MPlex::full () const { return 0; } inline int MPlex::can_add_high() const { return 1; } inline int MPlex::can_add_low() const { return 1; } inline int MPlex::available() const { return unused; } inline int MPlex::count() const { return fnc - lo - unused; } inline void MPlex::set_cache(const MChunk* t) const { ((MPlex*)(this))->ch = (MChunk*)t; } inline & MPlex:: operator [] (int idx) { if (!ch->MChunk::valid_index(idx)) cache(idx); return * (ch->pointer_to(idx)); } inline const & MPlex:: operator [] (int idx) const { if (!ch->MChunk::valid_index(idx)) cache(idx); return * ((const *)(ch->pointer_to(idx))); } inline int MPlex::Pix_to_index(Pix p) const { if (!ch->MChunk::valid_pointer((*)p)) cache((*)p); return ch->index_of((*)p); } inline int MPlex::high() const { return (((const MChunk*)tl())->MChunk::valid_index(fnc-1)) ? fnc-1 : dopred(fnc-1); } inline int MPlex::low() const { return (((const MChunk*)hd)->MChunk::valid_index(lo))? lo : dosucc(lo); } inline & MPlex::low_element () { return (*this)[low()]; } inline const & MPlex::low_element () const { return (*this)[low()]; } inline & MPlex::high_element () { return (*this)[high()]; } inline const & MPlex::high_element () const { return (*this)[high()]; } inline Pix MPlex::index_to_Pix(int idx) const { if (!ch->MChunk::valid_index(idx)) cache(idx); return Pix(ch->pointer_to(idx)); } inline void MPlex::next(int& idx) const { idx = (ch->MChunk::valid_index(idx+1))? idx+1 : dosucc(idx); } inline void MPlex::prev(int& idx) const { idx = (ch->MChunk::valid_index(idx-1))? idx-1 : dopred(idx); } inline Pix MPlex::first() const { return index_to_Pix(low()); } inline Pix MPlex::last() const { return index_to_Pix(high()); } inline void MPlex::undel_Pix(Pix p) { undel_index(Pix_to_index(p)); } inline int MPlex::del_Pix(Pix p) { return del_index(Pix_to_index(p)); } inline & MPlex:: operator () (Pix p) { return *((*)p); } inline const & MPlex:: operator () (Pix p) const { return *((const *)p); } #endif