Main Page | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members | Related Pages

MappedBuffer.d

Go to the documentation of this file.
00001 /*******************************************************************************
00002 
00003         @file MappedBuffer.d
00004 
00005         Copyright (c) 2004 Kris Bell
00006         
00007         This software is provided 'as-is', without any express or implied
00008         warranty. In no event will the authors be held liable for damages
00009         of any kind arising from the use of this software.
00010         
00011         Permission is hereby granted to anyone to use this software for any 
00012         purpose, including commercial applications, and to alter it and/or 
00013         redistribute it freely, subject to the following restrictions:
00014         
00015         1. The origin of this software must not be misrepresented; you must 
00016            not claim that you wrote the original software. If you use this 
00017            software in a product, an acknowledgment within documentation of 
00018            said product would be appreciated but is not required.
00019 
00020         2. Altered source versions must be plainly marked as such, and must 
00021            not be misrepresented as being the original software.
00022 
00023         3. This notice may not be removed or altered from any distribution
00024            of the source.
00025 
00026         4. Derivative works are permitted, but they must carry this notice
00027            in full and credit the original source.
00028 
00029 
00030                         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00031 
00032       
00033         @version        Initial version; March 2004
00034 
00035         @author         Kris
00036 
00037 
00038 *******************************************************************************/
00039 
00040 module mango.io.MappedBuffer;
00041 
00042 private import  mango.sys.OS;
00043 
00044 private import  mango.io.Buffer,
00045                 mango.io.Exception;
00046 
00047 public  import  mango.io.FileConduit;
00048 
00049 /*******************************************************************************
00050 
00051         Win32 declarations
00052 
00053 *******************************************************************************/
00054 
00055 version (Win32)
00056         {
00057         private extern (Windows) 
00058                 {
00059                 BOOL   UnmapViewOfFile    (LPCVOID);
00060                 BOOL   FlushViewOfFile    (LPCVOID, DWORD);
00061                 LPVOID MapViewOfFile      (HANDLE, DWORD, DWORD, DWORD, DWORD);
00062                 HANDLE CreateFileMappingA (HANDLE, LPSECURITY_ATTRIBUTES, DWORD, DWORD, DWORD, LPCTSTR);
00063                 }
00064         }
00065 
00066 
00067 /*******************************************************************************
00068 
00069         Subclass to treat the buffer as a seekable entity, where all 
00070         capacity is available for reading and/or writing. To achieve 
00071         this we must effectively disable the 'limit' watermark, and 
00072         locate write operations around 'position' instead. 
00073 
00074 *******************************************************************************/
00075 
00076 class MappedBuffer : Buffer
00077 {
00078         private FileConduit     host;                   // the hosting file
00079 
00080         version (Win32)
00081         {
00082                 private void*   base;                   // array pointer
00083                 private HANDLE  mmFile;                 // mapped file
00084 
00085                 /***************************************************************
00086 
00087                         Construct a MappedBuffer upon the given FileConduit. 
00088                         One should set the file size using seek() & truncate() 
00089                         to setup the available working space.
00090 
00091                 ***************************************************************/
00092 
00093                 this (FileConduit host)
00094                 {
00095                         super (0);
00096 
00097                         this.host = host;
00098 
00099                         // can only do 32bit mapping on 32bit platform
00100                         long size = host.length;
00101                         ConduitStyle.Bits style = host.getStyle;
00102 
00103                         DWORD flags = PAGE_READWRITE;
00104                         if (! (style.access & ConduitStyle.Access.Read))
00105                                flags = PAGE_READONLY;
00106 
00107                         mmFile = CreateFileMappingA (host.getHandle(), null, flags, 0, 0, null);
00108                         if (mmFile is null)
00109                             host.error ();
00110 
00111                         flags = FILE_MAP_WRITE;
00112                         if (! (style.access & ConduitStyle.Access.Read))
00113                               flags = FILE_MAP_READ;
00114 
00115                         base = MapViewOfFile (mmFile, flags, 0, 0, 0);
00116                         if (base is null)
00117                             host.error ();
00118 
00119                         void[] mem = base[0..size];
00120                         setValidContent (mem);
00121                 }
00122 
00123                 /***************************************************************
00124 
00125                         Close this mapped buffer
00126 
00127                 ***************************************************************/
00128 
00129                 void close ()
00130                 {
00131                         if (base)
00132                             UnmapViewOfFile (base);
00133 
00134                         if (mmFile)
00135                             CloseHandle (mmFile);       
00136 
00137                         mmFile = null;
00138                         base = null;
00139                 }
00140 
00141                 /***************************************************************
00142 
00143                         Flush dirty content out to the drive. This
00144                         fails with error 33 if the file content is
00145                         virgin. Opening a file for ReadWriteExists
00146                         followed by a flush() will cause this.
00147 
00148                 ***************************************************************/
00149 
00150                 void flush ()
00151                 {
00152                         // flush all dirty pages
00153                         if (! FlushViewOfFile (base, 0))
00154                               host.error ();
00155                 }
00156         }
00157 
00158         /***********************************************************************
00159                 
00160         ***********************************************************************/
00161 
00162         version (Posix)
00163         {
00164                 // not yet supported
00165                 private this (){};
00166 
00167                 void close () {}
00168 
00169                 void flush () {};
00170         }
00171 
00172         /***********************************************************************
00173                 
00174                 Ensure this is closed when GC'd
00175 
00176         ***********************************************************************/
00177         
00178         ~this ()
00179         {
00180                 close ();        
00181         }
00182 
00183         /***********************************************************************
00184                 
00185                 Set the read/write position
00186 
00187         ***********************************************************************/
00188 
00189         void setPosition (uint position)
00190         {
00191                 this.position = position;
00192         }
00193 
00194         /***********************************************************************
00195         
00196                 Seek to the specified position within the buffer, and return
00197                 the byte offset of the new location (relative to zero).
00198 
00199         ***********************************************************************/
00200 
00201         uint seek (uint offset, ISeekable.SeekAnchor anchor)
00202         {
00203                 uint pos = capacity;
00204 
00205                 if (anchor == ISeekable.SeekAnchor.Begin)
00206                     pos = offset;
00207                 else
00208                    if (anchor == ISeekable.SeekAnchor.End)
00209                        pos -= offset;
00210                    else
00211                       pos = position + offset;
00212 
00213                 return position = pos;
00214         }
00215 
00216         /***********************************************************************
00217         
00218                 Return count of writable bytes available in buffer. This is 
00219                 calculated simply as capacity() - limit()
00220 
00221         ***********************************************************************/
00222 
00223         override uint writable ()
00224         {
00225                 return capacity - position;
00226         }               
00227 
00228         /***********************************************************************
00229         
00230                 Bulk copy of data from 'src'. Position is adjusted by 'size'
00231                 bytes.
00232 
00233         ***********************************************************************/
00234 
00235         override protected void copy (void *src, uint size)
00236         {
00237                 data[position..position+size] = src[0..size];
00238                 position += size;
00239         }
00240 
00241         /***********************************************************************
00242 
00243                 Exposes the raw data buffer at the current write position, 
00244                 The delegate is provided with a void[] representing space
00245                 available within the buffer at the current write position.
00246 
00247                 The delegate should return the appropriate number of bytes 
00248                 if it writes valid content, or IConduit.Eof on error.
00249 
00250                 Returns whatever the delegate returns.
00251 
00252         ***********************************************************************/
00253 
00254         override uint write (uint delegate (void[]) dg)
00255         {
00256                 int count = dg (data [position..capacity]);
00257 
00258                 if (count != IConduit.Eof) 
00259                    {
00260                    position += count;
00261                    assert (position <= capacity);
00262                    }
00263                 return count;
00264         }               
00265 
00266         /***********************************************************************
00267 
00268                 Prohibit compress() from doing anything at all.
00269 
00270         ***********************************************************************/
00271 
00272         override IBuffer compress ()
00273         {
00274                 return this;
00275         }               
00276 
00277         /***********************************************************************
00278 
00279                 Prohibit clear() from doing anything at all.
00280 
00281         ***********************************************************************/
00282 
00283         override IBuffer clear ()
00284         {
00285                 return this;
00286         }               
00287 
00288         /***********************************************************************
00289         
00290                 Prohibit the setting of another IConduit
00291 
00292         ***********************************************************************/
00293 
00294         override void setConduit (IConduit conduit)
00295         {
00296                 throw new IOException ("cannot setConduit on memory-mapped buffer");
00297         }
00298 }

Generated on Sat Dec 24 17:28:33 2005 for Mango by  doxygen 1.4.0