/*ident "@(#)Set:incl/set.h 3.1" */ /****************************************************************************** * * C++ Standard Components, Release 3.0. * * Copyright (c) 1991, 1992 AT&T and Unix System Laboratories, Inc. * Copyright (c) 1988, 1989, 1990 AT&T. All Rights Reserved. * * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T and Unix System * Laboratories, Inc. The copyright notice above does not evidence * any actual or intended publication of such source code. * ******************************************************************************/ #ifndef SETH #define SETH // The following include is required so that the instantiation // files that include set.h will get what they need from Set.h #include class ostream; // The 32 bits of a Set_or_Bag_hashval are broken into // 8 4-bit groups. Each 4-bit group indexes // into a Internal_node of 16 Internal_items. static const int SET_NODE_SIZE_ATTLC = 16; static const int SET_POSITIONS_ATTLC = 8; static const int SET_MASK_BITS_ATTLC = 0XF; static const int SET_INITIAL_SHIFT_ATTLC = 0; static const int SET_SHIFT_INCR_ATTLC = 4; extern int SET_LT_ATTLC( Set_or_Bag_hashval a, Set_or_Bag_hashval b ); struct Space_info_ATTLC { int max_level; // max depth of tree long node_count; // total nodes long leaf_count; // total leaves long overhead; // size of data structure int leaves[SET_POSITIONS_ATTLC]; // leaves at each level int occupancy[SET_POSITIONS_ATTLC]; // non-null items at each level }; // Index to non-parametric classes: class Set_bucket_non_param_ATTLC; class Internal_item_ATTLC; class Internal_node_ATTLC; class Position_ATTLC; // The following ATTLC class declarations are // needed to disambiguate the copy-avoidance // constructors: class Set_select_ATTLC; class Set_reject_ATTLC; class Set_map_ATTLC; class Set_union_ATTLC; class Set_inter_ATTLC; class Set_diff_ATTLC; class Set_xor_ATTLC; extern Pool* internal_node_pool_ptr_ATTLC; struct Set_bucket_non_param_ATTLC { Set_or_Bag_hashval hashval; }; struct Internal_item_ATTLC { // An Internal_item is a single "slot" in an // Internal_node. It may contain: // // o An Internal_node* // o A Set_bucket_non_param_ATTLC* // o NULL // // Set_bucket_non_param_ATTLC* and Internal_node* pointers // can't be byte-aligned, so the low order bit is free to // be used as the union discriminant. // // o When the low-order bit is 1, the item // is a Set_bucket_non_param_ATTLC* // // o When the low order bit is 0, the item // is a Internal_node* or NULL. union { void* ext_leaf; Internal_node_ATTLC* nodep; long this_is_leaf; }; inline int is_leaf_or_null() const; inline int is_node() const; inline int is_leaf() const; inline int is_null() const; inline Internal_node_ATTLC* next_node() const; inline void* external_leaf() const; inline void make_leaf(void*); inline void make_node(Internal_node_ATTLC*); inline void make_null(); void show(int) const; void space(int,Space_info_ATTLC&) const; }; struct Internal_node_ATTLC { // A Internal_node has SET_NODE_SIZE_ATTLC Internal_items // plus a count of how many of these are in use. // Each Internal_item is directly indexed // by a lg(SET_NODE_SIZE_ATTLC) chunk. static void initialize(); Internal_item_ATTLC item[SET_NODE_SIZE_ATTLC]; int busy_count; Internal_node_ATTLC(); inline ~Internal_node_ATTLC(); void* operator new(size_t); inline void operator delete(void*); void show(int) const; void space(int,Space_info_ATTLC&) const; }; struct Position_ATTLC { // A Position caches the result of the most // recent search, down to the level of the // Bucket: // // o curr_value is the Set_or_Bag_hashval that we // searched for // // o curr_pos is a stack of pointers to // Internal_items which remembers a // path of Internal_items through the // index: // // o curr_pos[0] points to the Internal_item // selected by the first 4 bit chunk // // o curr_pos[1] points to the Internal_item // selected by the second 4 bit chunk // // o curr_pos[curr_depth] points to the // Internal_item which points to // a Bucket_ATTLC(T) // // If set mutation occurs, a Position is // canceled by setting its curr_depth to -1; // curr_value can be used subsequently to rebuild // the cur_pos stack so that iteration can resume // Internal_item_ATTLC* curr_pos[SET_POSITIONS_ATTLC]; int curr_depth; Set_or_Bag_hashval curr_value; inline Position_ATTLC(); void show() const; }; // Internal_item inlines int Internal_item_ATTLC::is_leaf_or_null() const { return this_is_leaf & 01; } int Internal_item_ATTLC::is_node() const { return !is_leaf_or_null() && nodep; } int Internal_item_ATTLC::is_leaf() const { return is_leaf_or_null() && ((long)ext_leaf & ~(long)01); } int Internal_item_ATTLC::is_null() const { return !nodep; } Internal_node_ATTLC* Internal_item_ATTLC::next_node() const { #ifdef DEBUG_ATTLC assert(is_node()); #endif return nodep; } void* Internal_item_ATTLC::external_leaf() const { #ifdef DEBUG_ATTLC assert(is_leaf()); #endif return (void*)((long)ext_leaf & ~(long)01); } void Internal_item_ATTLC::make_leaf(void* p) { #ifdef DEBUG_ATTLC assert(((long)p & 01) == 0); #endif ext_leaf = (void*)((long)p | 01); } void Internal_item_ATTLC::make_node(Internal_node_ATTLC* cp) { #ifdef DEBUG_ATTLC assert(((long)cp & 01) == 0); #endif nodep = cp; } void Internal_item_ATTLC::make_null() { nodep = 0; } // Internal_node inlines void Internal_node_ATTLC::operator delete(void* p) { internal_node_pool_ptr_ATTLC->free(p); } Internal_node_ATTLC::~Internal_node_ATTLC() { } // Position inlines Position_ATTLC::Position_ATTLC() : curr_depth(-1), curr_value(0) // curr_value probably not needed { } #ifdef __GNUG__ #pragma interface #endif template class Bucket_ATTLC; template class Bucketiter_ATTLC; // The following classes are for public consumption: template class Setiter; template class Set; // Each leaf item in the tree-structured index // points to a pair of values: // // o 'hashval' is the hash key // o 'collision_list' is a list of values which // hash to hashval // // Note that ALIGN values in the original version // become Bucket_ATTLC* values in this version. // template struct Bucket_ATTLC : public Set_bucket_non_param_ATTLC { List collision_list; void show() const; }; template class Bucketiter_ATTLC { friend class Set; protected: Set* my_set; Bucketiter_ATTLC* next_it; Position_ATTLC pos; public: Bucketiter_ATTLC(const Set&); Bucketiter_ATTLC(const Bucketiter_ATTLC&); ~Bucketiter_ATTLC(); const Bucket_ATTLC* first(); const Bucket_ATTLC* next(); void clobber() { pos.curr_depth = -1; } Bucketiter_ATTLC& operator=(const Bucketiter_ATTLC&); }; // This class must be modified to use // Bucketiter_ATTLC(*this).first() and next(). template class Setiter : public Bucketiter_ATTLC { private: int inited; // new Listiter* itp; public: const Set* the_set() const { // new return my_set; } Setiter(const Set& s) : Bucketiter_ATTLC(s), inited(0), itp(0) {} Setiter(const Setiter& si) : Bucketiter_ATTLC(*(si.the_set())), inited(0), itp(0) {} ~Setiter() { if (itp) delete itp; } const T* first(); // undocumented - TBD_make private const T* next(); // subsumes first, next int next(const T*& t) { // new t = next(); return t!=0; } void reset() { // new semantics inited=0; } Setiter& operator=(const Setiter& si) { return (Setiter&)((Bucketiter_ATTLC&)*this = (const Bucketiter_ATTLC&)si); } }; template class Set { friend class Bucketiter_ATTLC; friend class Setiter; private: int sze; Internal_item_ATTLC contents; Bucketiter_ATTLC* iter_head; // was Setiter Position_ATTLC pos; // was Position // The following are only used on empty sets void make_setlogic(const Set&, const Set&, int); Set(const Set&, const Set&, Set_union_ATTLC*); Set(const Set&, const Set&, Set_inter_ATTLC*); Set(const Set&, const Set&, Set_diff_ATTLC*); Set(const Set&, const Set&, Set_xor_ATTLC*); void warn_iterators() const; public: // Constructors Set() : sze(0), iter_head(0) { pos.curr_depth = -1; contents.make_null(); } Set(const T&); Set(const T&, const T&); Set(const T&, const T&, const T&); Set(const T&, const T&, const T&, const T&); Set(const Set&); ~Set(); // Size unsigned int size() const { return (unsigned)sze; } unsigned int size_unique() const { return (unsigned)sze; } operator const void*() const { return (size()? (this): (0)); } // Assignment Set& operator=(const Set&); // Relations int operator==(const Set& b) const { return containment(b, 0); } int operator!=(const Set& s) const { return !(*this == s); } int operator<=(const Set& b) const { return containment(b, 1); } int operator<(const Set& b) const { return containment(b, 2); } int operator>=(const Set& s) const { return s <= *this; } int operator>(const Set& s) const { return s < *this; } private: int containment(const Set&, int) const; public: // Membership const T* contains(const T&) const; unsigned int count(const T& t) const { return contains(t)?1:0; } // Insert and Remove elements const T* insert(const T&, int=1); unsigned remove(const T&, int=1); unsigned remove_all(const T& t) { return remove(t); } unsigned remove_all(); // Select an arbitrary element const T* select() const; // Set algebra Set operator|(const Set& s) const { return Set(*this,s,(Set_union_ATTLC*)0); } Set operator-(const Set& s) const { return Set(*this, s,(Set_diff_ATTLC*)0); } Set operator&(const Set& s) const { return Set(*this,s,(Set_inter_ATTLC*)0); } Set operator^(const Set& s) const { return Set(*this,s,(Set_xor_ATTLC*)0); } Set& operator|=(const Set&); Set& operator-=(const Set&); Set& operator&=(const Set&); Set& operator^=(const Set&); // Performance tuning void histogram(Map&) const; // Debugging, performance tuning void check() const; void show() const; Space_info_ATTLC space() const; // Hash function static Set_or_Bag_hashval hash(const T&); // user specializes if needed ostream& print(ostream&) const; }; template ostream& operator<<(ostream&, const Set&); template Set_or_Bag_hashval Set::hash(const T&) { return 0; } // Debugging code - don't want to require including // Developer can uncomment for debugging #if 0 template void Bucket_ATTLC::show() const { cout << " hashval=" << hashval << "\n"; cout << " collision_list="; Listiter it(collision_list); int first=1; cout << "<"; while(!it.at_end()) { if ( first ) first=0; else cout << ","; cout << it.next(); } cout << ">\n"; } template static void showiter(Listiter* itp) { T e; if ( itp ) { if ( itp->peek_prev(e) ) cout << e; else cout << "*"; if ( itp->peek_next(e) ) cout << e; else cout << "*"; cout << ">\n"; } else cout << "0"; } template void Set::show() const { cout << "sze = " << sze << "\n"; cout << "pos =\n"; pos.show(); cerr << "contents =\n"; contents.show(0); } template Space_info_ATTLC Set::space() const { // contents is level 0; the first node is level 1, etc. Space_info_ATTLC result; result.max_level = -1; result.node_count = 0; result.leaf_count = 0; if( !contents.is_null() ) { int i; for ( i=0 ; i ostream& operator<<(ostream& os, const Set& s) { os << "{"; Setiter it(s); const T* tp; int first=1; while( tp = it.next() ) { if ( first ) first=0; else os << ","; os << *tp; } os << "}"; return os; } #if (defined(__edg_att_40) || defined(__GNUG__)) && !defined(__IMPLICIT_INCLUDE) #include #endif #endif