diff options
author | Daniel Wilhelm <daniel@wili.li> | 2014-04-18 16:55:48 +0200 |
---|---|---|
committer | Daniel Wilhelm <daniel@wili.li> | 2014-04-18 16:55:48 +0200 |
commit | daea231de0ae28fc8343f29f09d0457cc0591461 (patch) | |
tree | a1d572442d2c903e40741a859ad47c8b0d740969 /algorithm.cpp | |
parent | 1.13 (diff) | |
download | FreeFileSync-daea231de0ae28fc8343f29f09d0457cc0591461.tar.gz FreeFileSync-daea231de0ae28fc8343f29f09d0457cc0591461.tar.bz2 FreeFileSync-daea231de0ae28fc8343f29f09d0457cc0591461.zip |
1.14
Diffstat (limited to 'algorithm.cpp')
-rw-r--r-- | algorithm.cpp | 227 |
1 files changed, 146 insertions, 81 deletions
diff --git a/algorithm.cpp b/algorithm.cpp index 4ea1a82d..e608a93b 100644 --- a/algorithm.cpp +++ b/algorithm.cpp @@ -6,7 +6,7 @@ #include "library/resources.h" #ifdef FFS_WIN -#include <windows.h> +#include <wx/msw/wrapwin.h> //includes "windows.h" #endif //FFS_WIN using namespace FreeFileSync; @@ -95,22 +95,23 @@ wxString FreeFileSync::formatFilesizeToShortString(const double filesize) } -wxString FreeFileSync::getFormattedDirectoryName(const wxString& dirname) +Zstring FreeFileSync::getFormattedDirectoryName(const Zstring& dirname) { //Formatting is needed since functions in FreeFileSync.cpp expect the directory to end with '\' to be able to split the relative names. //Also improves usability. - wxString dirnameTmp = dirname; + wxString dirnameTmp = dirname.c_str(); dirnameTmp.Trim(true); //remove whitespace characters from right dirnameTmp.Trim(false); //remove whitespace characters from left if (dirnameTmp.IsEmpty()) //an empty string is interpreted as "\"; this is not desired - return wxEmptyString; + return Zstring(); //let wxWidgets do the directory formatting, e.g. replace '/' with '\' for Windows wxFileName directory = wxFileName::DirName(dirnameTmp); wxString result = directory.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR); - return result; + //return Zstring(result.c_str()); + return Zstring(result); } @@ -138,7 +139,7 @@ void FreeFileSync::swapGrids(FileCompareResult& grid) } -void FreeFileSync::adjustModificationTimes(const wxString& parentDirectory, const int timeInSeconds, ErrorHandler* errorHandler) throw(AbortThisProcess) +void FreeFileSync::adjustModificationTimes(const Zstring& parentDirectory, const int timeInSeconds, ErrorHandler* errorHandler) throw(AbortThisProcess) { #ifndef __WXDEBUG__ wxLogNull noWxLogs; //prevent wxWidgets logging @@ -147,8 +148,8 @@ void FreeFileSync::adjustModificationTimes(const wxString& parentDirectory, cons if (timeInSeconds == 0) return; - wxArrayString fileList; - wxArrayString dirList; + vector<Zstring> fileList; + vector<Zstring> dirList; while (true) //should be executed in own scope so that directory access does not disturb deletion { @@ -160,7 +161,7 @@ void FreeFileSync::adjustModificationTimes(const wxString& parentDirectory, cons catch (const FileError& e) { ErrorHandler::Response rv = errorHandler->reportError(e.show()); - if (rv == ErrorHandler::CONTINUE_NEXT) + if (rv == ErrorHandler::IGNORE_ERROR) break; else if (rv == ErrorHandler::RETRY) ; //continue with loop @@ -171,27 +172,27 @@ void FreeFileSync::adjustModificationTimes(const wxString& parentDirectory, cons //this part is only a bit slower than direct Windows API-access! wxDateTime modTime; - for (unsigned int j = 0; j < fileList.GetCount(); ++j) + for (unsigned int j = 0; j < fileList.size(); ++j) { while (true) //own scope for directory access to not disturb file access! { try { - wxFileName file(fileList[j]); + wxFileName file(fileList[j].c_str()); if (!file.GetTimes(NULL, &modTime, NULL)) //get modification time - throw FileError(wxString(_("Error changing modification time: ")) + wxT("\"") + fileList[j] + wxT("\"")); + throw FileError(wxString(_("Error changing modification time:")) + wxT(" \"") + fileList[j].c_str() + wxT("\"")); modTime.Add(wxTimeSpan(0, 0, timeInSeconds, 0)); if (!file.SetTimes(NULL, &modTime, NULL)) //get modification time - throw FileError(wxString(_("Error changing modification time: ")) + wxT("\"") + fileList[j] + wxT("\"")); + throw FileError(wxString(_("Error changing modification time:")) + wxT(" \"") + fileList[j].c_str() + wxT("\"")); break; } catch (const FileError& error) { ErrorHandler::Response rv = errorHandler->reportError(error.show()); - if (rv == ErrorHandler::CONTINUE_NEXT) + if (rv == ErrorHandler::IGNORE_ERROR) break; else if (rv == ErrorHandler::RETRY) ; //continue with loop @@ -203,18 +204,18 @@ void FreeFileSync::adjustModificationTimes(const wxString& parentDirectory, cons } -void compoundStringToTable(const wxString& compoundInput, const wxChar* delimiter, vector<wxString>& output) +void compoundStringToTable(const Zstring& compoundInput, const defaultChar* delimiter, vector<Zstring>& output) { output.clear(); - wxString input(compoundInput); + Zstring input(compoundInput); //make sure input ends with delimiter - no problem with empty strings here if (!input.EndsWith(delimiter)) - input+= delimiter; + input += delimiter; unsigned int indexStart = 0; unsigned int indexEnd = 0; - while ((indexEnd = input.find(delimiter, indexStart )) != string::npos) + while ((indexEnd = input.find(delimiter, indexStart)) != Zstring::npos) { if (indexStart != indexEnd) //do not add empty strings { @@ -232,53 +233,23 @@ void compoundStringToTable(const wxString& compoundInput, const wxChar* delimite inline -void formatFilterString(wxString& filter) -{ -#ifdef FFS_WIN - //Windows does NOT distinguish between upper/lower-case - filter.MakeLower(); -#elif defined FFS_LINUX - //Linux DOES distinguish between upper/lower-case -//nothing to do here -#else - adapt; -#endif -} - - -inline -void formatFilenameString(wxString& filename) -{ -#ifdef FFS_WIN - //Windows does NOT distinguish between upper/lower-case - filename.MakeLower(); -#elif defined FFS_LINUX - //Linux DOES distinguish between upper/lower-case -//nothing to do here -#else - adapt; -#endif -} - - -inline -void mergeVectors(vector<wxString>& changing, const vector<wxString>& input) +void mergeVectors(vector<Zstring>& changing, const vector<Zstring>& input) { - for (vector<wxString>::const_iterator i = input.begin(); i != input.end(); ++i) + for (vector<Zstring>::const_iterator i = input.begin(); i != input.end(); ++i) changing.push_back(*i); } -vector<wxString> FreeFileSync::compoundStringToFilter(const wxString& filterString) +vector<Zstring> compoundStringToFilter(const Zstring& filterString) { //delimiters may be ';' or '\n' - vector<wxString> filterList; - vector<wxString> filterPreProcessing; + vector<Zstring> filterList; + vector<Zstring> filterPreProcessing; compoundStringToTable(filterString, wxT(";"), filterPreProcessing); - for (vector<wxString>::const_iterator i = filterPreProcessing.begin(); i != filterPreProcessing.end(); ++i) + for (vector<Zstring>::const_iterator i = filterPreProcessing.begin(); i != filterPreProcessing.end(); ++i) { - vector<wxString> newEntries; + vector<Zstring> newEntries; compoundStringToTable(*i, wxT("\n"), newEntries); mergeVectors(filterList, newEntries); } @@ -287,19 +258,34 @@ vector<wxString> FreeFileSync::compoundStringToFilter(const wxString& filterStri } +inline +void formatFilterString(Zstring& filter) +{ +#ifdef FFS_WIN + //Windows does NOT distinguish between upper/lower-case + filter.MakeLower(); +#elif defined FFS_LINUX + //Linux DOES distinguish between upper/lower-case +//nothing to do here +#else + adapt; +#endif +} + + void FreeFileSync::filterCurrentGridData(FileCompareResult& currentGridData, const wxString& includeFilter, const wxString& excludeFilter) { //no need for regular expressions! In tests wxRegex was by factor of 10 slower than wxString::Matches()!! //load filter into vectors of strings //delimiters may be ';' or '\n' - vector<wxString> includeList = FreeFileSync::compoundStringToFilter(includeFilter); - vector<wxString> excludeList = FreeFileSync::compoundStringToFilter(excludeFilter); + vector<Zstring> includeList = compoundStringToFilter(includeFilter); + vector<Zstring> excludeList = compoundStringToFilter(excludeFilter); //format entries - for (vector<wxString>::iterator i = includeList.begin(); i != includeList.end(); ++i) + for (vector<Zstring>::iterator i = includeList.begin(); i != includeList.end(); ++i) formatFilterString(*i); - for (vector<wxString>::iterator i = excludeList.begin(); i != excludeList.end(); ++i) + for (vector<Zstring>::iterator i = excludeList.begin(); i != excludeList.end(); ++i) formatFilterString(*i); //############################################################## @@ -307,17 +293,17 @@ void FreeFileSync::filterCurrentGridData(FileCompareResult& currentGridData, con //filter currentGridData for (FileCompareResult::iterator i = currentGridData.begin(); i != currentGridData.end(); ++i) { - wxString filenameLeft = i->fileDescrLeft.fullName; - wxString filenameRight = i->fileDescrRight.fullName; + Zstring filenameLeft = i->fileDescrLeft.fullName; + Zstring filenameRight = i->fileDescrRight.fullName; - formatFilenameString(filenameLeft); - formatFilenameString(filenameRight); + formatFilterString(filenameLeft); + formatFilterString(filenameRight); //process include filters if (i->fileDescrLeft.objType != FileDescrLine::TYPE_NOTHING) { bool includedLeft = false; - for (vector<wxString>::const_iterator j = includeList.begin(); j != includeList.end(); ++j) + for (vector<Zstring>::const_iterator j = includeList.begin(); j != includeList.end(); ++j) if (filenameLeft.Matches(*j)) { includedLeft = true; @@ -334,7 +320,7 @@ void FreeFileSync::filterCurrentGridData(FileCompareResult& currentGridData, con if (i->fileDescrRight.objType != FileDescrLine::TYPE_NOTHING) { bool includedRight = false; - for (vector<wxString>::const_iterator j = includeList.begin(); j != includeList.end(); ++j) + for (vector<Zstring>::const_iterator j = includeList.begin(); j != includeList.end(); ++j) if (filenameRight.Matches(*j)) { includedRight = true; @@ -352,7 +338,7 @@ void FreeFileSync::filterCurrentGridData(FileCompareResult& currentGridData, con if (i->fileDescrLeft.objType != FileDescrLine::TYPE_NOTHING) { bool excluded = false; - for (vector<wxString>::const_iterator j = excludeList.begin(); j != excludeList.end(); ++j) + for (vector<Zstring>::const_iterator j = excludeList.begin(); j != excludeList.end(); ++j) if (filenameLeft.Matches(*j)) { excluded = true; @@ -369,7 +355,7 @@ void FreeFileSync::filterCurrentGridData(FileCompareResult& currentGridData, con if (i->fileDescrRight.objType != FileDescrLine::TYPE_NOTHING) { bool excluded = false; - for (vector<wxString>::const_iterator j = excludeList.begin(); j != excludeList.end(); ++j) + for (vector<Zstring>::const_iterator j = excludeList.begin(); j != excludeList.end(); ++j) if (filenameRight.Matches(*j)) { excluded = true; @@ -399,7 +385,7 @@ void FreeFileSync::removeFilterOnCurrentGridData(FileCompareResult& currentGridD //add(!) all files and subfolder gridlines that are dependent from the directory void FreeFileSync::addSubElements(set<int>& subElements, const FileCompareResult& grid, const FileCompareLine& relevantRow) { - wxString relevantDirectory; + Zstring relevantDirectory; if (relevantRow.fileDescrLeft.objType == FileDescrLine::TYPE_DIRECTORY) relevantDirectory = relevantRow.fileDescrLeft.relativeName + GlobalResources::FILE_NAME_SEPARATOR; //FILE_NAME_SEPARATOR needed to exclude subfile/dirs only @@ -480,7 +466,7 @@ void FreeFileSync::deleteOnGridAndHD(FileCompareResult& grid, const set<int>& ro //if (updateClass) -> is mandatory ErrorHandler::Response rv = errorHandler->reportError(error.show()); - if (rv == ErrorHandler::CONTINUE_NEXT) + if (rv == ErrorHandler::IGNORE_ERROR) break; else if (rv == ErrorHandler::RETRY) @@ -493,7 +479,7 @@ void FreeFileSync::deleteOnGridAndHD(FileCompareResult& grid, const set<int>& ro } -bool FreeFileSync::sameFileTime(const wxULongLong& a, const wxULongLong& b) +bool FreeFileSync::sameFileTime(const time_t a, const time_t b) { if (a < b) return b - a <= FILE_TIME_PRECISION; @@ -501,6 +487,94 @@ bool FreeFileSync::sameFileTime(const wxULongLong& a, const wxULongLong& b) return a - b <= FILE_TIME_PRECISION; } + +inline +void writeTwoDigitNumber(unsigned int number, wxChar*& position) +{ + assert (number < 100); + + *position = '0' + number / 10; + position[1] = '0' + number % 10; + + position += 2; +} + + +inline +void writeFourDigitNumber(unsigned int number, wxChar*& position) +{ + assert (number < 10000); + + *position = '0' + number / 1000; + number %= 1000; + position[1] = '0' + number / 100; + number %= 100; + position[2] = '0' + number / 10; + number %= 10; + position[3] = '0' + number; + + position += 4; +} + + +wxString FreeFileSync::utcTimeToLocalString(const time_t utcTime) +{ +#ifdef FFS_WIN + + //convert ansi C time to FILETIME + wxULongLong fileTimeLong(utcTime); + fileTimeLong += wxULongLong(2, 3054539008UL); //timeshift between ansi C time and FILETIME in seconds == 11644473600s + fileTimeLong *= 10000000; + + FILETIME lastWriteTimeUtc; + lastWriteTimeUtc.dwLowDateTime = fileTimeLong.GetLo(); + lastWriteTimeUtc.dwHighDateTime = fileTimeLong.GetHi(); + + FILETIME localFileTime; + if (FileTimeToLocalFileTime( //convert to local time + &lastWriteTimeUtc, //pointer to UTC file time to convert + &localFileTime //pointer to converted file time + ) == 0) + throw RuntimeException(wxString(_("Conversion error:")) + wxT(" FILETIME -> local FILETIME")); + + SYSTEMTIME time; + if (FileTimeToSystemTime( + &localFileTime, //pointer to file time to convert + &time //pointer to structure to receive system time + ) == 0) + throw RuntimeException(wxString(_("Conversion error:")) + wxT(" FILETIME -> SYSTEMTIME")); + + //assemble time string (performance optimized) + wxChar formattedTime[21]; + wxChar* p = formattedTime; + + writeFourDigitNumber(time.wYear, p); + *(p++) = wxChar('-'); + writeTwoDigitNumber(time.wMonth, p); + *(p++) = wxChar('-'); + writeTwoDigitNumber(time.wDay, p); + *(p++) = wxChar(' '); + *(p++) = wxChar(' '); + writeTwoDigitNumber(time.wHour, p); + *(p++) = wxChar(':'); + writeTwoDigitNumber(time.wMinute, p); + *(p++) = wxChar(':'); + writeTwoDigitNumber(time.wSecond, p); + *p = 0; + + return wxString(formattedTime); + +#elif defined FFS_LINUX + tm* timeinfo; + timeinfo = localtime(&utcTime); //convert to local time + char buffer[50]; + strftime(buffer, 50, "%Y-%m-%d %H:%M:%S", timeinfo); + + return wxString(buffer); +#endif +} + + inline wxString getDriveName(const wxString& directoryName) { @@ -612,17 +686,8 @@ void FreeFileSync::checkForDSTChange(const FileCompareResult& gridData, if ( leftFile.objType == FileDescrLine::TYPE_FILE && rightFile.objType == FileDescrLine::TYPE_FILE && leftFile.fileSize == rightFile.fileSize && - -#ifdef FFS_WIN - //Windows does NOT distinguish between upper/lower-case - leftFile.directory.CmpNoCase(i->leftDirectory) == 0 && - rightFile.directory.CmpNoCase(i->rightDirectory) == 0 -#elif defined FFS_LINUX - //Linux DOES distinguish between upper/lower-case - leftFile.directory.Cmp(i->leftDirectory) == 0 && - rightFile.directory.Cmp(i->rightDirectory) == 0 -#endif - ) + leftFile.directory.CmpNoCase(i->leftDirectory.c_str()) == 0 && //Windows does NOT distinguish between upper/lower-case + rightFile.directory.CmpNoCase(i->rightDirectory.c_str()) == 0) // { ++filesTotal; |