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

Generated on Fri May 27 18:11:55 2005 for Mango by  doxygen 1.4.0