diff tango/tango/io/GrowBuffer.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/io/GrowBuffer.d	Fri Jan 11 17:57:40 2008 +0100
@@ -0,0 +1,159 @@
+/*******************************************************************************
+
+        copyright:      Copyright (c) 2004 Kris Bell. All rights reserved
+
+        license:        BSD style: $(LICENSE)
+      
+        version:        Initial release: March 2004
+        
+        author:         Kris
+
+*******************************************************************************/
+
+module tango.io.GrowBuffer;
+
+private import  tango.io.Buffer;
+
+public  import  tango.io.model.IBuffer;
+
+/*******************************************************************************
+
+        Subclass to provide support for content growth. This is handy when
+        you want to keep a buffer around as a scratchpad.
+
+*******************************************************************************/
+
+class GrowBuffer : Buffer
+{
+        private uint increment;
+
+        alias Buffer.slice  slice;
+        alias Buffer.append append; 
+
+        /***********************************************************************
+        
+                Create a GrowBuffer with the specified initial size.
+
+        ***********************************************************************/
+
+        this (uint size = 1024, uint increment = 1024)
+        {
+                super (size);
+
+                assert (increment >= 32);
+                this.increment = increment;
+        }
+
+        /***********************************************************************
+        
+                Create a GrowBuffer with the specified initial size.
+
+        ***********************************************************************/
+
+        this (IConduit conduit, uint size = 1024)
+        {
+                this (size, size);
+                setConduit (conduit);
+        }
+
+        /***********************************************************************
+        
+                Read a chunk of data from the buffer, loading from the
+                conduit as necessary. The specified number of bytes is
+                loaded into the buffer, and marked as having been read 
+                when the 'eat' parameter is set true. When 'eat' is set
+                false, the read position is not adjusted.
+
+                Returns the corresponding buffer slice when successful.
+
+        ***********************************************************************/
+
+        override void[] slice (uint size, bool eat = true)
+        {   
+                if (size > readable)
+                   {
+                   if (source is null)
+                       error (underflow);
+
+                   if (size + index > dimension)
+                       makeRoom (size);
+
+                   // populate tail of buffer with new content
+                   do {
+                      if (fill(source) is IConduit.Eof)
+                          error (eofRead);
+                      } while (size > readable);
+                   }
+
+                uint i = index;
+                if (eat)
+                    index += size;
+                return data [i .. i + size];               
+        }
+
+        /***********************************************************************
+        
+                Append an array of data to this buffer. This is often used 
+                in lieu of a Writer.
+
+        ***********************************************************************/
+
+        override IBuffer append (void *src, uint length)        
+        {               
+                if (length > writable)
+                    makeRoom (length);
+
+                copy (src, length);
+                return this;
+        }
+
+        /***********************************************************************
+
+                Try to fill the available buffer with content from the 
+                specified conduit. 
+
+                Returns the number of bytes read, or IConduit.Eof
+        
+        ***********************************************************************/
+
+        override uint fill (InputStream src)
+        {
+                if (writable <= increment/8)
+                    makeRoom (increment);
+
+                return write (&src.read);
+        } 
+
+        /***********************************************************************
+        
+                Expand and consume the conduit content, up to the maximum 
+                size indicated by the argument or until conduit.Eof
+
+                Returns the number of bytes in the buffer
+
+        ***********************************************************************/
+
+        uint fill (uint size = uint.max)
+        {   
+                while (readable < size)
+                       if (fill(source) is IConduit.Eof)
+                           break;
+                return readable;
+        }
+
+        /***********************************************************************
+
+                make some room in the buffer
+                        
+        ***********************************************************************/
+
+        private uint makeRoom (uint size)
+        {
+                if (size < increment)
+                    size = increment;
+
+                dimension += size;
+                data.length = dimension;               
+                return writable();
+        }
+}