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

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