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

FileProxy.d

Go to the documentation of this file.
00001 /*******************************************************************************
00002 
00003         @file FileProxy.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                         Brad Anderson
00037                         teqdruid
00038                         Anders (Darwin support)
00039                         Chris Sauls (Win95 file support)
00040 
00041 *******************************************************************************/
00042 
00043 module mango.io.FileProxy;
00044 
00045 private import  mango.sys.System;
00046 
00047 private import  mango.io.Utf,
00048                 mango.io.FilePath,
00049                 mango.io.FileStyle,
00050                 mango.io.Exception;
00051 
00052 private import  mango.io.model.IWriter;
00053  
00054 
00055 version (Win32)
00056         {
00057         private import std.c.windows.windows;
00058 
00059         version (Win32SansUnicode)
00060                 {
00061                 private extern (C) int strlen (char *s);
00062                 private alias WIN32_FIND_DATA FIND_DATA;
00063                 }
00064              else
00065                 {
00066                 private extern (C) int wcslen (wchar *s);
00067                 private alias WIN32_FIND_DATAW FIND_DATA;
00068                 }
00069         }
00070 
00071 
00072 version (Posix)
00073         {
00074         private extern (C) int strlen (char *s);
00075 
00076         version (darwin)
00077                 {
00078                 // missing from std.c.darwin.darwin in GDC 0.9 :
00079 
00080                 alias long off_t;
00081 
00082                 extern (C)
00083                        {
00084                        struct  dirent
00085                                {
00086                                int      d_ino;
00087                                off_t    d_off;
00088                                ushort   d_reclen;
00089                                ubyte    d_type;
00090                                char[256] d_name;
00091                                }
00092 
00093                        struct DIR
00094                              {
00095                              // Managed by OS.
00096                              }
00097 
00098                        DIR* opendir(char* name);
00099                        int closedir(DIR* dir);
00100                        dirent* readdir(DIR* dir);
00101                        void rewinddir(DIR* dir);
00102                        off_t telldir(DIR* dir);
00103                        void seekdir(DIR* dir, off_t offset);
00104                        }
00105                 }
00106         }
00107 
00108 
00109 /*******************************************************************************
00110 
00111         Models a generic file. Use this to manipulate files and directories
00112         in conjunction with FilePath, FileSystem and FileConduit. Doxygen
00113         has a hard time with D version() statements, so part of this class
00114         is documented in FileProxy::VersionWin32 instead.
00115 
00116         Compile with -version=Win32SansUnicode to enable Win95 & Win32s file
00117         support.
00118         
00119 *******************************************************************************/
00120 
00121 class FileProxy : IWritable
00122 {
00123         private FilePath path;
00124 
00125         /***********************************************************************
00126         
00127                 Construct a FileProxy from the provided FilePath
00128 
00129         ***********************************************************************/
00130                                   
00131         this (FilePath path)
00132         {
00133                 this.path = path;
00134         }
00135 
00136         /***********************************************************************
00137         
00138                 Construct a FileProxy from a text string
00139 
00140         ***********************************************************************/
00141 
00142         this (char[] path)
00143         {
00144                 this (new FilePath (path));
00145         }
00146 
00147         /***********************************************************************
00148         
00149                 Return the FilePath associated with this FileProxy
00150 
00151         ***********************************************************************/
00152 
00153         FilePath getPath ()
00154         {
00155                 return path;
00156         }               
00157 
00158         /***********************************************************************
00159         
00160                 Return the name of the associated path
00161 
00162         ***********************************************************************/
00163 
00164         char[] toString ()
00165         {
00166                 return path.toString();
00167         }               
00168 
00169         /***********************************************************************
00170         
00171                 Does this path currently exist?
00172 
00173         ***********************************************************************/
00174 
00175         bool isExisting ()               
00176         {
00177                 try {
00178                     getSize();
00179                     return true;
00180                     } catch (IOException){}
00181                 return false;
00182         }            
00183 
00184         /***********************************************************************
00185         
00186                 List the files contained within the associated path:
00187 
00188                 @code
00189                 FileProxy proxy = new FileProxy (".");
00190 
00191                 foreach (FilePath path; proxy.toList())
00192                          Stdout.put(path).cr();
00193                 @endcode
00194 
00195         ***********************************************************************/
00196 
00197         FilePath[] toList ()
00198         {
00199                 bool accept (FilePath fp) {return true;}
00200 
00201                 return toList (&accept);
00202         }              
00203 
00204         /***********************************************************************
00205         
00206                 Write this FileProxy to the given IWriter. We just emit 
00207                 the filepath, since that's what we represent.
00208 
00209         ***********************************************************************/
00210 
00211         void write (IWriter emit)
00212         {
00213                 emit (path);
00214         }
00215 
00216         /***********************************************************************
00217 
00218         ***********************************************************************/
00219 
00220         version (Win32)
00221         {
00222                 private import std.c.windows.windows;
00223 
00224                 /***************************************************************
00225 
00226                         Throw an exception using the last known error
00227 
00228                 ***************************************************************/
00229 
00230                 private void exception ()
00231                 {
00232                         throw new IOException (path.toString ~ ": " ~ System.error);
00233                 }
00234 
00235                 /***************************************************************
00236 
00237                         Get info about this path
00238 
00239                 ***************************************************************/
00240 
00241                 private uint getInfo (void delegate (FIND_DATA info) dg)
00242                 {
00243                         FIND_DATA info;
00244 
00245                         version (Win32SansUnicode)
00246                                  HANDLE h = FindFirstFileA (path.toUtf8, &info);
00247                              else
00248                                 HANDLE h = FindFirstFileW (path.toUtf16, &info);
00249 
00250                         if (h == INVALID_HANDLE_VALUE)
00251                             exception ();
00252 
00253                         if (dg)
00254                             dg (info);
00255                         FindClose (h);
00256 
00257                         return info.dwFileAttributes;
00258                 }
00259 
00260                 /***************************************************************
00261                         
00262                         Return the file length (in bytes)
00263 
00264                 ***************************************************************/
00265 
00266                 long getSize ()
00267                 {
00268                         long _size;
00269 
00270                         void size (FIND_DATA info)
00271                         {
00272                                 _size = (cast(ulong) info.nFileSizeHigh << 32) + 
00273                                                      info.nFileSizeLow;
00274                         }
00275 
00276                         getInfo (&size);
00277                         return _size;
00278                 }
00279 
00280                 /***************************************************************
00281 
00282                         Is this file writable?
00283 
00284                 ***************************************************************/
00285 
00286                 bool isWritable ()               
00287                 {
00288                         return (getInfo(null) & FILE_ATTRIBUTE_READONLY) == 0;
00289                 }            
00290 
00291                 /***************************************************************
00292 
00293                         Is this file really a directory?
00294 
00295                 ***************************************************************/
00296 
00297                 bool isDirectory ()               
00298                 {
00299                         return (getInfo(null) & FILE_ATTRIBUTE_DIRECTORY) != 0;
00300                 }            
00301 
00302                 /***************************************************************
00303 
00304                         Return the time when the file was last modified
00305 
00306                 ***************************************************************/
00307 
00308                 long getModifiedTime ()
00309                 {
00310                         long _time;
00311 
00312                         void time (FIND_DATA info)
00313                         {
00314                                 _time = (cast(ulong) info.ftLastWriteTime.dwHighDateTime << 32) + 
00315                                                      info.ftLastWriteTime.dwLowDateTime;
00316                         }
00317 
00318                         getInfo (&time);
00319                         return _time;
00320                 }               
00321 
00322                 /***************************************************************
00323 
00324                         Remove the file/directory from the file-system
00325 
00326                 ***************************************************************/
00327 
00328                 void remove ()
00329                 {
00330                         if (isDirectory ())
00331                            {
00332                            version (Win32SansUnicode)
00333                                    {
00334                                    if (! RemoveDirectoryA (path.toUtf8))
00335                                          exception();
00336                                    }
00337                                 else
00338                                    {
00339                                    if (! RemoveDirectoryW (path.toUtf16))
00340                                          exception();
00341                                    }
00342                            }
00343                         else
00344                            version (Win32SansUnicode)
00345                                    {
00346                                    if (! DeleteFileA (path.toUtf8))
00347                                          exception();
00348                                    }
00349                                 else
00350                                    {
00351                                    if (! DeleteFileW (path.toUtf16))
00352                                          exception();
00353                                    }
00354                 }           
00355 
00356                 /***************************************************************
00357 
00358                         Create a new file 
00359 
00360                 ***************************************************************/
00361 
00362                 FileProxy createFile ()
00363                 {
00364                         HANDLE h;
00365 
00366                         version (Win32SansUnicode)
00367                                  h = CreateFileA (path.toUtf8, GENERIC_WRITE, 
00368                                                   0, null, CREATE_ALWAYS, 
00369                                                   FILE_ATTRIBUTE_NORMAL, null);
00370                              else
00371                                 h = CreateFileW (path.toUtf16, GENERIC_WRITE, 
00372                                                  0, null, CREATE_ALWAYS, 
00373                                                  FILE_ATTRIBUTE_NORMAL, null);
00374 
00375                         if (h == INVALID_HANDLE_VALUE)
00376                             exception ();
00377 
00378                         if (! CloseHandle (h))
00379                               exception ();
00380 
00381                         return this;
00382                 }
00383 
00384                 /***************************************************************
00385 
00386                         Create a new directory
00387 
00388                 ***************************************************************/
00389 
00390                 FileProxy createDirectory ()
00391                 {
00392                         version (Win32SansUnicode)
00393                                 {
00394                                 if (! CreateDirectoryA (path.toUtf8, null))
00395                                       exception();
00396                                 }
00397                              else
00398                                 {
00399                                 if (! CreateDirectoryW (path.toUtf16, null))
00400                                       exception();
00401                                 }
00402                         return this;
00403                 }
00404 
00405                 /***************************************************************
00406                         
00407                         List the set of children within this directory. See
00408                         toList() above.
00409 
00410                 ***************************************************************/
00411 
00412                 FilePath[] toList (bool delegate(FilePath fp) filter)
00413                 {
00414                         int                     i;
00415                         wchar[]                 c;
00416                         HANDLE                  h;
00417                         FilePath                fp;
00418                         FilePath[]              list;
00419                         FIND_DATA               fileinfo;
00420 
00421                         int next()
00422                         {
00423                                 version (Win32SansUnicode)
00424                                          return FindNextFileA (h, &fileinfo);
00425                                      else
00426                                          return FindNextFileW (h, &fileinfo);
00427                         }
00428                         
00429                         list = new FilePath[50];
00430 
00431                         version (Win32SansUnicode)
00432                                 h = FindFirstFileA (path.toUtf8 ~ "\\*\0", &fileinfo);
00433                              else
00434                                 h = FindFirstFileW (path.toUtf16 ~ cast(wchar[]) "\\*\0", &fileinfo);
00435 
00436                         if (h != INVALID_HANDLE_VALUE)
00437                             try {
00438                                 do {
00439                                    // make a copy of the file name for listing
00440                                    version (Win32SansUnicode)
00441                                            {
00442                                            int len = strlen (fileinfo.cFileName);
00443                                            fp = new FilePath (fileinfo.cFileName [0 .. len]);
00444                                            }
00445                                         else
00446                                            {
00447                                            int len = wcslen (fileinfo.cFileName);
00448                                            fp = new FilePath (Utf.toUtf8(fileinfo.cFileName [0 .. len]));                                           
00449                                            }
00450 
00451                                    if (i >= list.length)
00452                                       list.length = list.length * 2;
00453 
00454                                    if (filter (fp))
00455                                       {
00456                                       list[i] = fp;
00457                                       ++i;
00458                                       }
00459                                    } while (next);
00460                                 } finally {
00461                                           FindClose (h);
00462                                           }
00463                         list.length = i;
00464                         return list;
00465                 }
00466         }
00467 
00468         /***********************************************************************
00469 
00470         ***********************************************************************/
00471 
00472         version (Posix)
00473         {
00474                 private import std.c.stdio;
00475 
00476                 version (linux) 
00477                         {
00478                         private import std.c.linux.linux;
00479                         alias std.c.linux.linux posix;
00480                         }
00481                 version (darwin)
00482                         {
00483                         private import std.c.darwin.darwin;
00484                         alias std.c.darwin.darwin posix;
00485                         }
00486 
00487                 /***************************************************************
00488 
00489                         Throw an exception using the last known error
00490 
00491                 ***************************************************************/
00492 
00493                 private void exception ()
00494                 {
00495                         throw new IOException (path.toString ~ ": " ~ System.error);
00496                 }
00497 
00498                 /***************************************************************
00499 
00500                         Get info about this path
00501 
00502                 ***************************************************************/
00503 
00504                 private uint getInfo (void delegate (struct_stat info) dg)
00505                 {
00506                         struct_stat stats;
00507 
00508                         if (posix.stat (path.toUtf8, &stats))
00509                             exception();
00510 
00511                         if (dg)
00512                             dg (stats);
00513 
00514                         return stats.st_mode;
00515                 }               
00516 
00517                 /***************************************************************
00518 
00519                         Return the file length (in bytes)
00520 
00521                 ***************************************************************/
00522 
00523                 long getSize ()
00524                 {
00525                         long _size;
00526 
00527                         void size (struct_stat info)
00528                         {
00529                                 _size = cast(ulong) info.st_size;    // 32 bits only
00530                         }
00531 
00532                         getInfo (&size);
00533                         return _size;
00534                 }
00535 
00536                 /***************************************************************
00537 
00538                         Is this file writable?
00539 
00540                 ***************************************************************/
00541 
00542                 bool isWritable ()               
00543                 {
00544                         return (getInfo(null) & O_RDONLY) == 0;
00545                 }            
00546 
00547                 /***************************************************************
00548 
00549                         Is this file really a directory?
00550 
00551                 ***************************************************************/
00552 
00553                 bool isDirectory ()               
00554                 {
00555                         return (getInfo(null) & S_IFDIR) != 0;
00556                 }            
00557 
00558                 /***************************************************************
00559 
00560                         Return the time when the file was last modified
00561 
00562                 ***************************************************************/
00563 
00564                 long getModifiedTime ()
00565                 {
00566                         long _time;
00567 
00568                         void time (struct_stat info)
00569                         {
00570                                _time = cast(ulong) info.st_mtime; // seconds since 1/1/1970
00571                         }
00572 
00573                         getInfo (&time);
00574                         return _time;
00575                 }               
00576 
00577                 /***************************************************************
00578 
00579                         Remove the file/directory from the file-system
00580 
00581                 ***************************************************************/
00582 
00583                 void remove ()
00584                 {
00585                         if (isDirectory())
00586                            {
00587                            if (posix.rmdir (path.toUtf8))
00588                                exception ();
00589                            }
00590                         else           
00591                            if (std.c.stdio.remove (path.toUtf8) == -1)
00592                                exception ();
00593                 }              
00594 
00595                 /***************************************************************
00596 
00597                         Create a new file 
00598 
00599                 ***************************************************************/
00600 
00601                 FileProxy createFile ()
00602                 {
00603                         int fd;
00604 
00605                         fd = posix.open (path.toUtf8, O_CREAT | O_WRONLY | O_TRUNC, 0660);
00606                         if (fd == -1)
00607                             exception();
00608 
00609                         if (posix.close(fd) == -1)
00610                             exception();
00611 
00612                         return this;
00613                 }              
00614 
00615                 /***************************************************************
00616 
00617                         Create a new directory
00618 
00619                 ***************************************************************/
00620 
00621                 FileProxy createDirectory ()
00622                 {
00623                         if (posix.mkdir (path.toUtf8, 0777))
00624                             exception();
00625 
00626                         return this;
00627                 }
00628 
00629                 /***************************************************************
00630                 
00631                         List the set of children within this directory. See
00632                         toList() above.
00633 
00634                 ***************************************************************/
00635 
00636                 FilePath[] toList (bool delegate(FilePath fp) filter)
00637                 {
00638                         int             i;
00639                         DIR*            dir;
00640                         dirent*         entry;
00641                         FilePath[]      list;
00642 
00643                         dir = opendir (path.toUtf8);
00644                         if (! dir) 
00645                               exception();
00646 
00647                         list = new FilePath [50];
00648                         while ((entry = readdir(dir)) != null)
00649                               {
00650                               int len = strlen (entry.d_name);
00651 
00652                               // make a copy of the file name for listing
00653                               FilePath fp = new FilePath (entry.d_name[0 ..len].dup);
00654 
00655                               if (i >= list.length)
00656                                   list.length = list.length * 2;
00657 
00658                               if (filter (fp))
00659                                  {
00660                                  list[i] = fp;
00661                                  ++i;
00662                                  }
00663                               }  
00664 
00665                         list.length = i;
00666                         closedir (dir);
00667                         return list;
00668                 }
00669 
00670         }
00671 }
00672 

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