diff tango/tango/util/collection/impl/Collection.d @ 132:1700239cab2e trunk

[svn r136] MAJOR UNSTABLE UPDATE!!! Initial commit after moving to Tango instead of Phobos. Lots of bugfixes... This build is not suitable for most things.
author lindquist
date Fri, 11 Jan 2008 17:57:40 +0100
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tango/tango/util/collection/impl/Collection.d	Fri Jan 11 17:57:40 2008 +0100
@@ -0,0 +1,631 @@
+/*******************************************************************************
+
+        File: Collection.d
+
+        Originally written by Doug Lea and released into the public domain. 
+        Thanks for the assistance and support of Sun Microsystems Labs, Agorics 
+        Inc, Loral, and everyone contributing, testing, and using this code.
+
+        History:
+        Date     Who                What
+        24Sep95  dl@cs.oswego.edu   Create from tango.util.collection.d  working file
+        13Oct95  dl                 Add assert
+        22Oct95  dl                 Add excludeElements, removeElements
+        28jan97  dl                 make class public; isolate version changes
+        14Dec06  kb                 Adapted for Tango usage
+        
+********************************************************************************/
+
+module tango.util.collection.impl.Collection;
+
+private import  tango.core.Exception;
+
+private import  tango.util.collection.model.View,
+                tango.util.collection.model.Iterator,
+                tango.util.collection.model.Dispenser;
+
+/*******************************************************************************
+
+        Collection serves as a convenient base class for most implementations
+        of mutable containers. It maintains a version number and element count.
+        It also provides default implementations of many collection operations. 
+
+        Authors: Doug Lea
+
+********************************************************************************/
+
+public abstract class Collection(T) : Dispenser!(T)
+{
+        alias View!(T)          ViewT;
+
+        alias bool delegate(T)  Predicate;
+
+
+        // instance variables
+
+        /***********************************************************************
+
+                version represents the current version number
+
+        ************************************************************************/
+
+        protected uint vershion;
+
+        /***********************************************************************
+
+                screener hold the supplied element screener
+
+        ************************************************************************/
+
+        protected Predicate screener;
+
+        /***********************************************************************
+
+                count holds the number of elements.
+
+        ************************************************************************/
+
+        protected uint count;
+
+        // constructors
+
+        /***********************************************************************
+
+                Initialize at version 0, an empty count, and supplied screener
+
+        ************************************************************************/
+
+        protected this (Predicate screener = null)
+        {
+                this.screener = screener;
+        }
+
+
+        /***********************************************************************
+
+        ************************************************************************/
+
+        protected final static bool isValidArg (T element)
+        {
+                static if (is (T : Object))
+                          {
+                          if (element is null)
+                              return false;
+                          }
+                return true;
+        }
+
+        // Default implementations of Collection methods
+
+        /***********************************************************************
+
+                expose collection content as an array
+
+        ************************************************************************/
+
+        public T[] toArray ()
+        {
+                auto result = new T[this.size];
+        
+                int i = 0;
+                foreach (e; this)
+                         result[i++] = e;
+
+                return result;
+        }
+
+        /***********************************************************************
+
+                Time complexity: O(1).
+                See_Also: tango.util.collection.impl.Collection.Collection.drained
+
+        ************************************************************************/
+
+        public final bool drained()
+        {
+                return count is 0;
+        }
+
+        /***********************************************************************
+
+                Time complexity: O(1).
+                Returns: the count of elements currently in the collection
+                See_Also: tango.util.collection.impl.Collection.Collection.size
+
+        ************************************************************************/
+
+        public final uint size()
+        {
+                return count;
+        }
+
+        /***********************************************************************
+
+                Checks if element is an allowed element for this collection.
+                This will not throw an exception, but any other attemp to add an
+                invalid element will do.
+
+                Time complexity: O(1) + time of screener, if present
+
+                See_Also: tango.util.collection.impl.Collection.Collection.allows
+
+        ************************************************************************/
+
+        public final bool allows (T element)
+        {
+                return isValidArg(element) &&
+                                 (screener is null || screener(element));
+        }
+
+
+        /***********************************************************************
+
+                Time complexity: O(n).
+                Default implementation. Fairly sleazy approach.
+                (Defensible only when you remember that it is just a default impl.)
+                It tries to cast to one of the known collection interface types
+                and then applies the corresponding comparison rules.
+                This suffices for all currently supported collection types,
+                but must be overridden if you define new Collection subinterfaces
+                and/or implementations.
+
+                See_Also: tango.util.collection.impl.Collection.Collection.matches
+
+        ************************************************************************/
+
+        public bool matches(ViewT other)
+        {
+/+
+                if (other is null)
+                    return false;
+                else
+                   if (other is this)
+                       return true;
+                   else
+                      if (cast(SortedKeys) this)
+                         {
+                         if (!(cast(Map) other))
+                               return false;
+                         else
+                            return sameOrderedPairs(cast(Map)this, cast(Map)other);
+                         }
+                      else
+                         if (cast(Map) this)
+                            {
+                            if (!(cast(Map) other))
+                                  return false;
+                            else
+                               return samePairs(cast(Map)(this), cast(Map)(other));
+                            }
+                         else
+                            if ((cast(Seq) this) || (cast(SortedValues) this))
+                                 return sameOrderedElements(this, other);
+                            else
+                               if (cast(Bag) this)
+                                   return sameOccurrences(this, other);
+                               else
+                                  if (cast(Set) this)
+                                      return sameInclusions(this, cast(View)(other));
+                                  else
+                                     return false;
++/
+                   return false;
+        }
+
+        // Default implementations of MutableCollection methods
+
+        /***********************************************************************
+
+                Time complexity: O(1).
+                See_Also: tango.util.collection.impl.Collection.Collection.version
+
+        ************************************************************************/
+
+        public final uint mutation()
+        {
+                return vershion;
+        }
+
+        // Object methods
+
+        /***********************************************************************
+
+                Default implementation of toString for Collections. Not
+                very pretty, but parenthesizing each element means that
+                for most kinds of elements, it's conceivable that the
+                strings could be parsed and used to build other tango.util.collection.
+
+                Not a very pretty implementation either. Casts are used
+                to get at elements/keys
+
+        ************************************************************************/
+
+        public override char[] toString()
+        {
+                char[16] tmp;
+                
+                return "<" ~ this.classinfo.name ~ ", size:" ~ itoa(tmp, size()) ~ ">";
+        }
+
+
+        /***********************************************************************
+
+        ************************************************************************/
+
+        protected final char[] itoa(char[] buf, uint i)
+        {
+                auto j = buf.length;
+                
+                do {
+                   buf[--j] = i % 10 + '0';
+                   } while (i /= 10);
+                return buf [j..$];
+        }
+        
+        // protected operations on version and count
+
+        /***********************************************************************
+
+                change the version number
+
+        ************************************************************************/
+
+        protected final void incVersion()
+        {
+                ++vershion;
+        }
+
+
+        /***********************************************************************
+
+                Increment the element count and update version
+
+        ************************************************************************/
+
+        protected final void incCount()
+        {
+                count++;
+                incVersion();
+        }
+
+        /***********************************************************************
+
+                Decrement the element count and update version
+
+        ************************************************************************/
+
+        protected final void decCount()
+        {
+                count--;
+                incVersion();
+        }
+
+
+        /***********************************************************************
+
+                add to the element count and update version if changed
+
+        ************************************************************************/
+
+        protected final void addToCount(uint c)
+        {
+                if (c !is 0)
+                   {
+                   count += c;
+                   incVersion();
+                   }
+        }
+        
+
+        /***********************************************************************
+
+                set the element count and update version if changed
+
+        ************************************************************************/
+
+        protected final void setCount(uint c)
+        {
+                if (c !is count)
+                   {
+                   count = c;
+                   incVersion();
+                   }
+        }
+
+
+        /***********************************************************************
+
+                Helper method left public since it might be useful
+
+        ************************************************************************/
+
+        public final static bool sameInclusions(ViewT s, ViewT t)
+        {
+                if (s.size !is t.size)
+                    return false;
+
+                try { // set up to return false on collection exceptions
+                    auto ts = t.elements();
+                    while (ts.more)
+                          {
+                          if (!s.contains(ts.get))
+                              return false;
+                          }
+                    return true;
+                    } catch (NoSuchElementException ex)
+                            {
+                            return false;
+                            }
+        }
+
+        /***********************************************************************
+
+                Helper method left public since it might be useful
+
+        ************************************************************************/
+
+        public final static bool sameOccurrences(ViewT s, ViewT t)
+        {
+                if (s.size !is t.size)
+                    return false;
+
+                auto ts = t.elements();
+                T last = T.init; // minor optimization -- skip two successive if same
+
+                try { // set up to return false on collection exceptions
+                    while (ts.more)
+                          {
+                          T m = ts.get;
+                          if (m !is last)
+                             {
+                             if (s.instances(m) !is t.instances(m))
+                                 return false;
+                             }
+                          last = m;
+                          }
+                    return true;
+                    } catch (NoSuchElementException ex)
+                            {
+                            return false;
+                            }
+        }
+        
+
+        /***********************************************************************
+
+                Helper method left public since it might be useful
+
+        ************************************************************************/
+
+        public final static bool sameOrderedElements(ViewT s, ViewT t)
+        {
+                if (s.size !is t.size)
+                    return false;
+
+                auto ts = t.elements();
+                auto ss = s.elements();
+
+                try { // set up to return false on collection exceptions
+                    while (ts.more)
+                          {
+                          T m = ts.get;
+                          T o = ss.get;
+                          if (m != o)
+                              return false;
+                          }
+                    return true;
+                    } catch (NoSuchElementException ex)
+                            {       
+                            return false;
+                            }
+        }
+
+        // misc common helper methods
+
+        /***********************************************************************
+
+                Principal method to throw a NoSuchElementException.
+                Besides index checks in Seqs, you can use it to check for
+                operations on empty collections via checkIndex(0)
+
+        ************************************************************************/
+
+        protected final void checkIndex(int index)
+        {
+                if (index < 0 || index >= count)
+                   {
+                   char[] msg;
+
+                   if (count is 0)
+                       msg = "Element access on empty collection";
+                   else
+                      {
+                      char[16] idx, cnt;
+                      msg = "Index " ~ itoa (idx, index) ~ " out of range for collection of size " ~ itoa (cnt, count);
+                      }
+                   throw new NoSuchElementException(msg);
+                   }
+        }
+
+        
+        /***********************************************************************
+
+                Principal method to throw a IllegalElementException
+
+        ************************************************************************/
+
+        protected final void checkElement(T element)
+        {
+                if (! allows(element))
+                   {
+                   throw new IllegalElementException("Attempt to include invalid element _in Collection");
+                   }
+        }
+
+        /***********************************************************************
+
+                See_Also: tango.util.collection.model.View.View.checkImplementation
+
+        ************************************************************************/
+
+        public void checkImplementation()
+        {
+                assert(count >= 0);
+        }
+        //public override void checkImplementation() //Doesn't compile with the override attribute
+
+        /***********************************************************************
+
+                Cause the collection to become empty. 
+
+        ************************************************************************/
+
+        abstract void clear();
+
+        /***********************************************************************
+
+                Exclude all occurrences of the indicated element from the collection. 
+                No effect if element not present.
+                Params:
+                    element = the element to exclude.
+                ---
+                !has(element) &&
+                size() == PREV(this).size() - PREV(this).instances(element) &&
+                no other element changes &&
+                Version change iff PREV(this).has(element)
+                ---
+
+        ************************************************************************/
+
+        abstract void removeAll(T element);
+
+        /***********************************************************************
+
+                Remove an instance of the indicated element from the collection. 
+                No effect if !has(element)
+                Params:
+                    element = the element to remove
+                ---
+                let occ = max(1, instances(element)) in
+                 size() == PREV(this).size() - occ &&
+                 instances(element) == PREV(this).instances(element) - occ &&
+                 no other element changes &&
+                 version change iff occ == 1
+                ---
+
+        ************************************************************************/
+
+        abstract void remove (T element);
+        
+        /***********************************************************************
+
+                Replace an occurrence of oldElement with newElement.
+                No effect if does not hold oldElement or if oldElement.equals(newElement).
+                The operation has a consistent, but slightly special interpretation
+                when applied to Sets. For Sets, because elements occur at
+                most once, if newElement is already included, replacing oldElement with
+                with newElement has the same effect as just removing oldElement.
+                ---
+                let int delta = oldElement.equals(newElement)? 0 : 
+                              max(1, PREV(this).instances(oldElement) in
+                 instances(oldElement) == PREV(this).instances(oldElement) - delta &&
+                 instances(newElement) ==  (this instanceof Set) ? 
+                        max(1, PREV(this).instances(oldElement) + delta):
+                               PREV(this).instances(oldElement) + delta) &&
+                 no other element changes &&
+                 Version change iff delta != 0
+                ---
+                Throws: IllegalElementException if has(oldElement) and !allows(newElement)
+
+        ************************************************************************/
+
+        abstract void replace (T oldElement, T newElement);
+
+        /***********************************************************************
+
+                Replace all occurrences of oldElement with newElement.
+                No effect if does not hold oldElement or if oldElement.equals(newElement).
+                The operation has a consistent, but slightly special interpretation
+                when applied to Sets. For Sets, because elements occur at
+                most once, if newElement is already included, replacing oldElement with
+                with newElement has the same effect as just removing oldElement.
+                ---
+                let int delta = oldElement.equals(newElement)? 0 : 
+                           PREV(this).instances(oldElement) in
+                 instances(oldElement) == PREV(this).instances(oldElement) - delta &&
+                 instances(newElement) ==  (this instanceof Set) ? 
+                        max(1, PREV(this).instances(oldElement) + delta):
+                               PREV(this).instances(oldElement) + delta) &&
+                 no other element changes &&
+                 Version change iff delta != 0
+                ---
+                Throws: IllegalElementException if has(oldElement) and !allows(newElement)
+
+        ************************************************************************/
+
+        abstract void replaceAll(T oldElement, T newElement);
+
+        /***********************************************************************
+
+                Exclude all occurrences of each element of the Iterator.
+                Behaviorally equivalent to
+                ---
+                while (e.more())
+                  removeAll(e.get());
+                ---
+                Param :
+                    e = the enumeration of elements to exclude.
+
+                Throws: CorruptedIteratorException is propagated if thrown
+
+                See_Also: tango.util.collection.impl.Collection.Collection.removeAll
+
+        ************************************************************************/
+
+        abstract void removeAll (Iterator!(T) e);
+
+        /***********************************************************************
+
+                 Remove an occurrence of each element of the Iterator.
+                 Behaviorally equivalent to
+
+                 ---
+                 while (e.more())
+                    remove (e.get());
+                 ---
+
+                 Param:
+                    e = the enumeration of elements to remove.
+
+                 Throws: CorruptedIteratorException is propagated if thrown
+
+        ************************************************************************/
+
+        abstract void remove (Iterator!(T) e);
+
+        /***********************************************************************
+
+                Remove and return an element.  Implementations
+                may strengthen the guarantee about the nature of this element.
+                but in general it is the most convenient or efficient element to remove.
+
+                Examples:
+                One way to transfer all elements from 
+                MutableCollection a to MutableBag b is:
+                ---
+                while (!a.empty())
+                    b.add(a.take());
+                ---
+
+                Returns:
+                    an element v such that PREV(this).has(v) 
+                    and the postconditions of removeOneOf(v) hold.
+
+                Throws: NoSuchElementException iff drained.
+
+        ************************************************************************/
+
+        abstract T take();
+}
+
+