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

DeviceConduit.d

Go to the documentation of this file.
00001 /*******************************************************************************
00002 
00003         @file DeviceConduit.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; May 2005      
00034 
00035         @author         Kris 
00036 
00037 *******************************************************************************/
00038 
00039 module mango.io.DeviceConduit;
00040 
00041 private import  mango.sys.OS,
00042                 mango.sys.System;
00043                 
00044 public  import  mango.io.Buffer,
00045                 mango.io.FileStyle;
00046 
00047 private import  mango.io.Conduit,
00048                 mango.io.Exception,
00049                 mango.io.ConduitStyle;
00050 
00051 /*******************************************************************************
00052 
00053         Bring in native Windows functions
00054 
00055 *******************************************************************************/
00056 
00057 version (Win32)
00058 {
00059         private extern (Windows) 
00060         {
00061                 HANDLE GetStdHandle (DWORD);
00062         }
00063 }
00064 
00065 
00066 /*******************************************************************************
00067 
00068         Implements a means of reading and writing a file device. Conduits
00069         are the primary means of accessing external data, and are usually 
00070         routed through a Buffer. 
00071         
00072 *******************************************************************************/
00073 
00074 class DeviceConduit : Conduit
00075 {
00076         // expose conduit.copy() methods also
00077         alias Conduit.copy  copy;
00078         alias Conduit.read  read;
00079         alias Conduit.write write;
00080 
00081         /***********************************************************************
00082         
00083                 Construct a conduit with the given style and seek abilities. 
00084                 Conduits are either seekable or non-seekable.
00085 
00086         ***********************************************************************/
00087 
00088         this (ConduitStyle style, bool seekable)
00089         {
00090                 super (style, seekable);
00091         }
00092 
00093         /***********************************************************************
00094 
00095                 Create a FileConduit on the provided FileDevice. This is 
00096                 strictly for adapting existing devices such as Stdout and
00097                 friends.
00098         
00099         ***********************************************************************/
00100 
00101         this (FileDevice device)
00102         {
00103                 // say we're not seekable
00104                 super (device, false);
00105                 
00106                 // open the file
00107                 reopen (device);
00108 
00109                 // bump lock count
00110                 acquire();
00111         }    
00112 
00113         /***********************************************************************
00114         
00115                 Callback to close the file. This is invoked from the Resource
00116                 base-class when the resource is being closed.
00117 
00118         ***********************************************************************/
00119 
00120         protected override void closure ()
00121         {       
00122                 super.closure ();
00123                 _close ();
00124         }    
00125                    
00126         /***********************************************************************
00127 
00128                 Create a Buffer of the default FileConduit size, and
00129                 associate it with this conduit
00130 
00131         ***********************************************************************/
00132 
00133         override IBuffer createBuffer()
00134         {
00135                 const int DefaultFileBufferSize = 1024 * 16; 
00136 
00137                 IBuffer buffer = new Buffer (DefaultFileBufferSize);
00138 
00139                 buffer.setConduit (this);
00140                 return buffer;
00141         } 
00142 
00143         /***********************************************************************
00144 
00145                 Return the name of this device
00146 
00147         ***********************************************************************/
00148 
00149         protected char[] getName()
00150         {
00151                 return "<device>";
00152         }
00153 
00154 
00155         /***********************************************************************
00156 
00157                 Windows-specific code
00158         
00159         ***********************************************************************/
00160 
00161         version (Win32)
00162         {
00163                 protected HANDLE handle;
00164 
00165                 /***************************************************************
00166 
00167                         Throw an IOException noting the last error
00168 
00169                 ***************************************************************/
00170 
00171                 protected void error ()
00172                 {
00173                         throw new IOException (getName() ~ ": " ~ System.error);
00174                 }
00175 
00176                 /***************************************************************
00177 
00178                         Gain access to the standard IO handles (console etc).
00179 
00180                 ***************************************************************/
00181 
00182                 protected void reopen (FileDevice device)
00183                 {
00184                         handle = cast(HANDLE) device.id;
00185                 }
00186 
00187                 /***************************************************************
00188 
00189                         Close the underlying file
00190 
00191                 ***************************************************************/
00192 
00193                 protected void _close ()
00194                 {
00195                         if (! CloseHandle (handle))
00196                               error ();
00197                 }
00198 
00199                 /***************************************************************
00200 
00201                         Read a chunk of bytes from the file into the provided
00202                         array (typically that belonging to an IBuffer)
00203 
00204                 ***************************************************************/
00205 
00206                 override int read (void[] dst)
00207                 {
00208                         DWORD read;
00209                         void *p = dst;
00210 
00211                         if (! ReadFile (handle, p, dst.length, &read, null))
00212                               error ();
00213 
00214                         if (read == 0 && dst.length > 0)
00215                             return Eof;
00216                         return read;
00217                 }
00218 
00219                 /***************************************************************
00220 
00221                         Write a chunk of bytes to the file from the provided
00222                         array (typically that belonging to an IBuffer)
00223 
00224                 ***************************************************************/
00225 
00226                 override int write (void[] src)
00227                 {
00228                         DWORD written;
00229 
00230                         if (! WriteFile (handle, src, src.length, &written, null))
00231                               error ();
00232 
00233                         return written;
00234                 }
00235         }
00236 
00237 
00238         /***********************************************************************
00239 
00240                  Unix-specific code.
00241         
00242         ***********************************************************************/
00243 
00244         version (Posix)
00245         {
00246                 protected int handle = -1;
00247 
00248                 /***************************************************************
00249 
00250                         Throw an IOException noting the last error
00251 
00252                 ***************************************************************/
00253 
00254                 protected void error ()
00255                 {
00256                         throw new IOException (getName() ~ ": " ~
00257                                                System.error);
00258                 }
00259 
00260                 /***************************************************************
00261 
00262                         Gain access to the standard IO handles (console etc).
00263 
00264                 ***************************************************************/
00265 
00266                 protected void reopen (FileDevice device)
00267                 {
00268                         handle = device.id;
00269                 }
00270 
00271                 /***************************************************************
00272 
00273                         Close the underlying file
00274 
00275                 ***************************************************************/
00276 
00277                 protected void _close ()
00278                 {
00279                         if (posix.close (handle) == -1)
00280                             error ();
00281                 }
00282 
00283                 /***************************************************************
00284 
00285                         Read a chunk of bytes from the file into the provided
00286                         array (typically that belonging to an IBuffer)
00287 
00288                 ***************************************************************/
00289 
00290                 override int read (void[] dst)
00291                 {
00292                         int read = posix.read (handle, dst, dst.length);
00293                         if (read == -1)
00294                             error ();
00295                         else
00296                            if (read == 0 && dst.length > 0)
00297                                return Eof;
00298                         return read;
00299                 }
00300 
00301                 /***************************************************************
00302 
00303                         Write a chunk of bytes to the file from the provided
00304                         array (typically that belonging to an IBuffer)
00305 
00306                 ***************************************************************/
00307 
00308                 override int write (void[] src)
00309                 {
00310                         int written = posix.write (handle, src, src.length);
00311                         if (written == -1)
00312                             error ();
00313                         return written;
00314                 }
00315         }
00316 }
00317 
00318 
00319 /*******************************************************************************
00320 
00321         Class used to wrap an existing file-oriented handle, such as Stdout
00322         and its cohorts.
00323 
00324 *******************************************************************************/
00325 
00326 class FileDevice : ConduitStyle
00327 {
00328         private uint id;
00329 
00330         this (uint id, Access access)
00331         {
00332                 super (access);
00333                 this.id = id;
00334         }
00335 }
00336 
00337 
00338 /*******************************************************************************
00339 
00340         Conduit for specifically handling the console devices. This takes
00341         care of certain implementation details on the Win32 platform.
00342         
00343 *******************************************************************************/
00344 
00345 class ConsoleConduit : DeviceConduit
00346 {
00347         // expose conduit.copy() methods also 
00348         alias DeviceConduit.copy  copy;
00349         alias DeviceConduit.read  read;
00350         alias DeviceConduit.write write;
00351 
00352         /***********************************************************************
00353 
00354                 Create a FileConduit on the provided FileDevice. This is 
00355                 strictly for adapting existing devices such as Stdout and
00356                 friends.
00357         
00358         ***********************************************************************/
00359 
00360         package this (FileDevice device)
00361         {
00362                 super (device);
00363         }    
00364 
00365         /***********************************************************************
00366 
00367                 Return the name of this device
00368 
00369         ***********************************************************************/
00370 
00371         protected char[] getName()
00372         {
00373                 return "console device";
00374         }
00375 
00376         /***********************************************************************
00377 
00378                 Windows-specific code
00379         
00380         ***********************************************************************/
00381 
00382         version(Win32)
00383         {
00384                 /***************************************************************
00385 
00386                         Gain access to the standard IO handles (console etc).
00387 
00388                 ***************************************************************/
00389 
00390                 protected override void reopen (FileDevice device)
00391                 {
00392                         static const DWORD[] id = [
00393                                                   cast(DWORD) -10, 
00394                                                   cast(DWORD) -11, 
00395                                                   cast(DWORD) -12
00396                                                   ];
00397                         static const char[][] f = [
00398                                                   "CONIN$\0", 
00399                                                   "CONOUT$\0", 
00400                                                   "CONOUT$\0"
00401                                                   ];
00402 
00403                         assert (device.id < 3);
00404                         handle = GetStdHandle (id[device.id]);
00405                         if (! handle)
00406                               handle = CreateFileA (f[device.id], 
00407                                        GENERIC_READ | GENERIC_WRITE,  
00408                                        FILE_SHARE_READ | FILE_SHARE_WRITE, 
00409                                        null, OPEN_EXISTING, 0, null);
00410                         if (! handle)
00411                               error ();
00412                 }
00413 
00414                 /***************************************************************
00415 
00416                         Write a chunk of bytes to the file from the provided
00417                         array (typically that belonging to an IBuffer)
00418 
00419                 ***************************************************************/
00420 
00421                 override int write (void[] src)
00422                 {
00423                         void* p = src.ptr;
00424                         DWORD len = src.length;
00425                         const int Max = 0x7fff;
00426 
00427                         // Win32 console has problems with content over
00428                         // 32KB in length, so handle it specifically
00429                         do {
00430                            DWORD i = len;
00431                            if (i > Max)
00432                                i = Max;
00433                            if (! WriteFile (handle, p, i, &i, null))
00434                                  error ();
00435                            len -= i;
00436                            p += i;
00437                            } while (len);
00438 
00439                         return src.length;
00440                 }
00441         }
00442 }
00443 
00444 

Generated on Mon Nov 14 10:59:37 2005 for Mango by  doxygen 1.4.0