Back to index

nux  3.0.0
NFileManagerGeneric.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright 2010 Inalogic® Inc.
00003  *
00004  * This program is free software: you can redistribute it and/or modify it
00005  * under the terms of the GNU Lesser General Public License, as
00006  * published by the  Free Software Foundation; either version 2.1 or 3.0
00007  * of the License.
00008  *
00009  * This program is distributed in the hope that it will be useful, but
00010  * WITHOUT ANY WARRANTY; without even the implied warranties of
00011  * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
00012  * PURPOSE.  See the applicable version of the GNU Lesser General Public
00013  * License for more details.
00014  *
00015  * You should have received a copy of both the GNU Lesser General Public
00016  * License along with this program. If not, see <http://www.gnu.org/licenses/>
00017  *
00018  * Authored by: Jay Taoko <jaytaoko@inalogic.com>
00019  *
00020  */
00021 
00022 
00023 #include "NuxCore.h"
00024 #include "Math/MathUtility.h"
00025 
00026 namespace nux
00027 {
00028 
00029 #define COPYBLOCKSIZE       32768
00030 
00031 
00032   int NFileManagerGeneric::Copy (const TCHAR *InDestFile, const TCHAR *InSrcFile, bool OverWriteExisting, bool OverWriteReadOnly, NFileTransferMonitor *Monitor)
00033   {
00034     // Direct file copier.
00035     if (Monitor && !Monitor->Progress (0.0) )
00036     {
00037       return COPY_CANCELED;
00038     }
00039 
00040     int           Result           = COPY_OK;
00041     NString SrcFile         = InSrcFile;
00042     NString DestFile = InDestFile;
00043 
00044     NSerializer *Src = CreateFileReader (SrcFile.GetTCharPtr() );
00045 
00046     if (!Src)
00047     {
00048       Result = COPY_READFAIL;
00049     }
00050     else
00051     {
00052       unsigned int Size = Src->GetFileSize();
00053       NSerializer *Dest = CreateFileWriter (DestFile.GetTCharPtr(), (OverWriteExisting ? 0 : FILEWRITE_NOREPLACEEXISTING) | (OverWriteReadOnly ? FILEWRITE_EVENIFREADONLY : 0) );
00054 
00055       if (!Dest)
00056       {
00057         Result = COPY_WRITEFAIL;
00058       }
00059       else
00060       {
00061         unsigned int Percent = 0, NewPercent = 0;
00062         BYTE Buffer[COPYBLOCKSIZE];
00063 
00064         for (unsigned int Total = 0; Total < Size; Total += sizeof (Buffer) )
00065         {
00066           unsigned int Count = Min<unsigned int> (Size - Total, (unsigned int) sizeof (Buffer) );
00067           Src->Serialize (Buffer, Count);
00068 
00069           if (Src->IsError() )
00070           {
00071             Result = COPY_READFAIL;
00072             break;
00073           }
00074 
00075           Dest->Serialize (Buffer, Count);
00076 
00077           if (Dest->IsError() )
00078           {
00079             Result = COPY_WRITEFAIL;
00080             break;
00081           }
00082 
00083           NewPercent = Total * 100 / Size;
00084 
00085           if (Monitor && Percent != NewPercent && !Monitor->Progress ( (float) NewPercent / 100.f) )
00086           {
00087             Result = COPY_CANCELED;
00088             break;
00089           }
00090 
00091           Percent = NewPercent;
00092         }
00093 
00094         if (Result == COPY_OK)
00095         {
00096           if (!Dest->Close() )
00097           {
00098             Result = COPY_WRITEFAIL;
00099           }
00100         }
00101 
00102         delete Dest;
00103 
00104         if (Result != COPY_OK)
00105         {
00106           Delete (DestFile.GetTCharPtr() );
00107         }
00108       }
00109 
00110       if (Result == COPY_OK)
00111       {
00112         if (!Src->Close() )
00113         {
00114           Result = COPY_READFAIL;
00115         }
00116       }
00117 
00118       delete Src;
00119     }
00120 
00121     if (Monitor && Result == COPY_OK && !Monitor->Progress (1.0) )
00122     {
00123       Result = COPY_CANCELED;
00124     }
00125 
00126     return Result;
00127   }
00128 
00129   bool NFileManagerGeneric::IsDrive (const TCHAR *Path)
00130   {
00131     // Does Path refer to a drive letter or UNC path?
00132     // A UNC is a naming convention that permits you to use a network resource,
00133     // such as a network server, without formally connecting to the network resource
00134     // with a mapped drive. A UNC path uses the following syntax:
00135     //      \<Server><Share>
00136     // The share is a drive: D:\Folder of ServerA = "\\ServerA\D\Folder"
00137 
00138     if (Stricmp (Path, TEXT ("") ) == 0)
00139       return 1;
00140     else if ( (ToUpperCase (Path[0]) != ToLowerCase (Path[0]) ) && (Path[1] == TEXT (':') ) && (Path[2] == 0) ) // look for "a:", "c:", "d:" ...
00141       return 1;
00142     else if (Stricmp (Path, TEXT ("\\") ) == 0) // look for "\"
00143       return 1;
00144     else if (Stricmp (Path, TEXT ("\\\\") ) == 0) // look for "\\"
00145       return 1;
00146     else if (Path[0] == TEXT ('\\') && Path[1] == TEXT ('\\') && !Strchr (Path + 2, TEXT ('\\') ) ) // look for "\\Server"
00147       return 1;
00148     else if (Path[0] == TEXT ('\\') && Path[1] == TEXT ('\\') && Strchr (Path + 2, TEXT ('\\') ) && !Strchr (Strchr (Path + 2, TEXT ('\\') ) + 1, TEXT ('\\') ) )
00149       // look for "\\Server\share"
00150       return 1;
00151     else
00152       return 0;
00153   }
00154 
00155   bool NFileManagerGeneric::MakeDirectory (const TCHAR *Path, bool CreateCompletePath)
00156   {
00157     // Support code for making a directory tree.
00158     nuxAssert (CreateCompletePath);
00159     unsigned int SlashCount = 0, CreateCount = 0;
00160 
00161     for (TCHAR Full[256] = TEXT (""), *Ptr = Full; ; *Ptr++ = *Path++)
00162     {
00163       if ( (*Path == NUX_BACKSLASH_CHAR) || (*Path == NUX_SLASH_CHAR) || (*Path == 0) )
00164       {
00165         if ( (SlashCount++ > 0) && !IsDrive (Full) )
00166         {
00167           *Ptr = 0;
00168 
00169           if (MakeDirectory (Full, 0) != NUX_OK)
00170             return 0;
00171 
00172           CreateCount++;
00173         }
00174       }
00175 
00176       if (*Path == 0)
00177         break;
00178     }
00179 
00180     return CreateCount != 0;
00181   }
00182 
00183   bool NFileManagerGeneric::DeleteDirectory (const TCHAR *Path, bool DeleteContentFirst)
00184   {
00185     nuxAssert (DeleteContentFirst);
00186     nuxAssert (Path != NULL);
00187 
00188     size_t PathLength = StringLength (Path);
00189 
00190     if (PathLength == 0)
00191       return false;
00192 
00193     NString WildcardPath = NString (Path);
00194 
00195     if ( (WildcardPath[PathLength - 1] != NUX_BACKSLASH_CHAR) && (WildcardPath[PathLength - 1] != NUX_SLASH_CHAR) )
00196       WildcardPath += NUX_BACKSLASH_CHAR;
00197 
00198     WildcardPath += TEXT ("*");
00199 
00200     std::vector<NString> List;
00201     FindFiles (List, *WildcardPath, 1, 0);
00202 
00203     for (unsigned int i = 0; i < List.size(); i++)
00204     {
00205       if (!Delete (* (NString (Path) + NUX_BACKSLASH_CHAR + List[i]), 1) )
00206         return 0;
00207     }
00208 
00209     List.clear();
00210     FindFiles (List, *WildcardPath, 0, 1);
00211 
00212     for (unsigned int i = 0; i < List.size(); i++)
00213     {
00214       if (!DeleteDirectory (* (NString (Path) + NUX_BACKSLASH_CHAR + List[i]), true) )
00215         return 0;
00216     }
00217 
00218     List.clear();
00219     return DeleteDirectory (Path, false);
00220   }
00221 
00222   bool NFileManagerGeneric::Move (const TCHAR *Dest, const TCHAR *Src, bool OverWriteExisting, bool OverWriteReadOnly, NFileTransferMonitor *Monitor)
00223   {
00224     // Move file manually.
00225     if (Copy (Dest, Src, OverWriteExisting, OverWriteReadOnly, NULL) != COPY_OK)
00226       return 0;
00227 
00228     Delete (Src, 1);
00229     return 1;
00230   }
00231 
00232 
00233   int NFileManagerGeneric::CreateUniqueFileName (const TCHAR *Filename, const TCHAR *Extension, NString &OutputFilename, unsigned int BaseIndex)
00234   {
00235     nuxAssert (Filename);
00236     nuxAssert (Extension);
00237 
00238     NString FullPath (Filename);
00239     const size_t IndexMarker = FullPath.Length();                     // Marks location of the four-digit index.
00240     FullPath += TEXT ("0000.");
00241     FullPath += Extension;
00242 
00243     // Iterate over indices, searching for a file that doesn't exist.
00244     for (DWORD i = BaseIndex + 1 ; i < 10000 ; ++i)
00245     {
00246       FullPath[IndexMarker  ] = i / 1000     + TEXT ('0');
00247       FullPath[IndexMarker+1] = (i / 100) % 10 + TEXT ('0');
00248       FullPath[IndexMarker+2] = (i / 10)  % 10 + TEXT ('0');
00249       FullPath[IndexMarker+3] =   i     % 10 + TEXT ('0');
00250 
00251       if (GFileManager.FileSize (FullPath.GetTCharPtr() ) == -1)
00252       {
00253         // The file doesn't exist; output success.
00254         OutputFilename = FullPath;
00255         return static_cast<int> (i);
00256       }
00257     }
00258 
00259     // Can't find an empty filename slot with index in (StartVal, 9999].
00260     return -1;
00261   }
00262 
00263 }
00264