From 75c07011b7c4d06acd7b45dabdcd60ab9d80f385 Mon Sep 17 00:00:00 2001 From: Daniel Wilhelm Date: Fri, 18 Apr 2014 17:29:28 +0200 Subject: 5.23 --- structures.cpp | 516 --------------------------------------------------------- 1 file changed, 516 deletions(-) delete mode 100644 structures.cpp (limited to 'structures.cpp') diff --git a/structures.cpp b/structures.cpp deleted file mode 100644 index e5dc08fd..00000000 --- a/structures.cpp +++ /dev/null @@ -1,516 +0,0 @@ -// ************************************************************************** -// * This file is part of the FreeFileSync project. It is distributed under * -// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * -// ************************************************************************** - -#include "structures.h" -#include -#include -#include -#include -#include - -using namespace zen; - - -std::wstring zen::getVariantName(CompareVariant var) -{ - switch (var) - { - case CMP_BY_CONTENT: - return _("File content"); - case CMP_BY_TIME_SIZE: - return _("File time and size"); - } - assert(false); - return _("Error"); -} - - -std::wstring zen::getVariantName(DirectionConfig::Variant var) -{ - switch (var) - { - case DirectionConfig::TWOWAY: - return L"<- " + _("Two way") + L" ->"; - case DirectionConfig::MIRROR: - return _("Mirror") + L" ->>"; - case DirectionConfig::UPDATE: - return _("Update") + L" ->"; - case DirectionConfig::CUSTOM: - return _("Custom"); - } - assert(false); - return _("Error"); -} - - -DirectionSet zen::extractDirections(const DirectionConfig& cfg) -{ - DirectionSet output; - switch (cfg.var) - { - case DirectionConfig::TWOWAY: - throw std::logic_error("there are no predefined directions for automatic mode!"); - - case DirectionConfig::MIRROR: - output.exLeftSideOnly = SyncDirection::RIGHT; - output.exRightSideOnly = SyncDirection::RIGHT; - output.leftNewer = SyncDirection::RIGHT; - output.rightNewer = SyncDirection::RIGHT; - output.different = SyncDirection::RIGHT; - output.conflict = SyncDirection::RIGHT; - break; - - case DirectionConfig::UPDATE: - output.exLeftSideOnly = SyncDirection::RIGHT; - output.exRightSideOnly = SyncDirection::NONE; - output.leftNewer = SyncDirection::RIGHT; - output.rightNewer = SyncDirection::NONE; - output.different = SyncDirection::RIGHT; - output.conflict = SyncDirection::NONE; - break; - - case DirectionConfig::CUSTOM: - output = cfg.custom; - break; - } - return output; -} - - -bool zen::detectMovedFilesSelectable(const DirectionConfig& cfg) -{ - if (cfg.var == DirectionConfig::TWOWAY) - return false; //moved files are always detected since we have the database file anyway - - const DirectionSet tmp = zen::extractDirections(cfg); - return (tmp.exLeftSideOnly == SyncDirection::RIGHT && - tmp.exRightSideOnly == SyncDirection::RIGHT) || - (tmp.exLeftSideOnly == SyncDirection::LEFT&& - tmp.exRightSideOnly == SyncDirection::LEFT); -} - - -bool zen::detectMovedFilesEnabled(const DirectionConfig& cfg) -{ - return detectMovedFilesSelectable(cfg) ? cfg.detectMovedFiles : cfg.var == DirectionConfig::TWOWAY; -} - - -DirectionSet zen::getTwoWayUpdateSet() -{ - DirectionSet output; - output.exLeftSideOnly = SyncDirection::RIGHT; - output.exRightSideOnly = SyncDirection::LEFT; - output.leftNewer = SyncDirection::RIGHT; - output.rightNewer = SyncDirection::LEFT; - output.different = SyncDirection::NONE; - output.conflict = SyncDirection::NONE; - return output; -} - - -std::wstring MainConfiguration::getCompVariantName() const -{ - const CompareVariant firstVariant = firstPair.altCmpConfig.get() ? - firstPair.altCmpConfig->compareVar : - cmpConfig.compareVar; //fallback to main sync cfg - - //test if there's a deviating variant within the additional folder pairs - for (const FolderPairEnh& fp : additionalPairs) - { - const CompareVariant thisVariant = fp.altCmpConfig.get() ? - fp.altCmpConfig->compareVar : - cmpConfig.compareVar; //fallback to main sync cfg - if (thisVariant != firstVariant) - return _("Multiple..."); - } - - //seems to be all in sync... - return getVariantName(firstVariant); -} - - -std::wstring MainConfiguration::getSyncVariantName() const -{ - const DirectionConfig::Variant firstVariant = firstPair.altSyncConfig.get() ? - firstPair.altSyncConfig->directionCfg.var : - syncCfg.directionCfg.var; //fallback to main sync cfg - - //test if there's a deviating variant within the additional folder pairs - for (const FolderPairEnh& fp : additionalPairs) - { - const DirectionConfig::Variant thisVariant = fp.altSyncConfig.get() ? - fp.altSyncConfig->directionCfg.var : - syncCfg.directionCfg.var; - if (thisVariant != firstVariant) - return _("Multiple..."); - } - - //seems to be all in sync... - return getVariantName(firstVariant); -} - - -std::wstring zen::getSymbol(CompareFilesResult cmpRes) -{ - switch (cmpRes) - { - case FILE_LEFT_SIDE_ONLY: - return L"only <-"; - case FILE_RIGHT_SIDE_ONLY: - return L"only ->"; - case FILE_LEFT_NEWER: - return L"newer <-"; - case FILE_RIGHT_NEWER: - return L"newer ->"; - case FILE_DIFFERENT: - return L"!="; - case FILE_EQUAL: - case FILE_DIFFERENT_METADATA: //= sub-category of equal! - return L"'=="; //added quotation mark to avoid error in Excel cell when exporting to *.cvs - case FILE_CONFLICT: - return L"conflict"; - } - assert(false); - return std::wstring(); -} - - -std::wstring zen::getSymbol(SyncOperation op) -{ - switch (op) - { - case SO_CREATE_NEW_LEFT: - return L"create <-"; - case SO_CREATE_NEW_RIGHT: - return L"create ->"; - case SO_DELETE_LEFT: - return L"delete <-"; - case SO_DELETE_RIGHT: - return L"delete ->"; - case SO_MOVE_LEFT_SOURCE: - return L"move from <-"; - case SO_MOVE_LEFT_TARGET: - return L"move to <-"; - case SO_MOVE_RIGHT_SOURCE: - return L"move from ->"; - case SO_MOVE_RIGHT_TARGET: - return L"move to ->"; - case SO_OVERWRITE_LEFT: - case SO_COPY_METADATA_TO_LEFT: - return L"update <-"; - case SO_OVERWRITE_RIGHT: - case SO_COPY_METADATA_TO_RIGHT: - return L"update ->"; - case SO_DO_NOTHING: - return L" -"; - case SO_EQUAL: - return L"'=="; //added quotation mark to avoid error in Excel cell when exporting to *.cvs - case SO_UNRESOLVED_CONFLICT: - return L"conflict"; - }; - assert(false); - return std::wstring(); -} - - -namespace -{ -assert_static(std::numeric_limits::is_specialized); -assert_static(std::numeric_limits::is_specialized); - -/* -int daysSinceBeginOfWeek(int dayOfWeek) //0-6, 0=Monday, 6=Sunday -{ - assert(0 <= dayOfWeek && dayOfWeek <= 6); -#ifdef ZEN_WIN - DWORD firstDayOfWeek = 0; - if (::GetLocaleInfo(LOCALE_USER_DEFAULT, //__in LCID Locale, - LOCALE_IFIRSTDAYOFWEEK | // first day of week specifier, 0-6, 0=Monday, 6=Sunday - LOCALE_RETURN_NUMBER, //__in LCTYPE LCType, - reinterpret_cast(&firstDayOfWeek), //__out LPTSTR lpLCData, - sizeof(firstDayOfWeek) / sizeof(TCHAR)) > 0) //__in int cchData - { - assert(firstDayOfWeek <= 6); - return (dayOfWeek + (7 - firstDayOfWeek)) % 7; - } - else //default -#endif - return dayOfWeek; //let all weeks begin with monday -} -*/ - - -Int64 resolve(size_t value, UnitTime unit, Int64 defaultVal) -{ - TimeComp locTimeStruc = zen::localTime(); - - switch (unit) - { - case UTIME_NONE: - return defaultVal; - - case UTIME_TODAY: - locTimeStruc.second = 0; //0-61 - locTimeStruc.minute = 0; //0-59 - locTimeStruc.hour = 0; //0-23 - return localToTimeT(locTimeStruc); //convert local time back to UTC - - //case UTIME_THIS_WEEK: - //{ - // localTimeFmt->tm_sec = 0; //0-61 - // localTimeFmt->tm_min = 0; //0-59 - // localTimeFmt->tm_hour = 0; //0-23 - // const time_t timeFrom = ::mktime(localTimeFmt); - - // int dayOfWeek = (localTimeFmt->tm_wday + 6) % 7; //tm_wday := days since Sunday 0-6 - // // +6 == -1 in Z_7 - - // return Int64(timeFrom) - daysSinceBeginOfWeek(dayOfWeek) * 24 * 3600; - //} - - case UTIME_THIS_MONTH: - locTimeStruc.second = 0; //0-61 - locTimeStruc.minute = 0; //0-59 - locTimeStruc.hour = 0; //0-23 - locTimeStruc.day = 1; //1-31 - return localToTimeT(locTimeStruc); - - case UTIME_THIS_YEAR: - locTimeStruc.second = 0; //0-61 - locTimeStruc.minute = 0; //0-59 - locTimeStruc.hour = 0; //0-23 - locTimeStruc.day = 1; //1-31 - locTimeStruc.month = 1; //1-12 - return localToTimeT(locTimeStruc); - - case UTIME_LAST_X_DAYS: - locTimeStruc.second = 0; //0-61 - locTimeStruc.minute = 0; //0-59 - locTimeStruc.hour = 0; //0-23 - return localToTimeT(locTimeStruc) - Int64(value) * 24 * 3600; - } - - assert(false); - return localToTimeT(locTimeStruc); -} - - -UInt64 resolve(size_t value, UnitSize unit, UInt64 defaultVal) -{ - const UInt64 maxVal =std::numeric_limits::max(); - - switch (unit) - { - case USIZE_NONE: - return defaultVal; - case USIZE_BYTE: - return value; - case USIZE_KB: - return value > maxVal / 1024U ? maxVal : //prevent overflow!!! - 1024U * value; - case USIZE_MB: - return value > maxVal / (1024 * 1024U) ? maxVal : //prevent overflow!!! - 1024 * 1024U * value; - } - assert(false); - return defaultVal; -} -} - -void zen::resolveUnits(size_t timeSpan, UnitTime unitTimeSpan, - size_t sizeMin, UnitSize unitSizeMin, - size_t sizeMax, UnitSize unitSizeMax, - zen::Int64& timeFrom, //unit: UTC time, seconds - zen::UInt64& sizeMinBy, //unit: bytes - zen::UInt64& sizeMaxBy) //unit: bytes -{ - timeFrom = resolve(timeSpan, unitTimeSpan, std::numeric_limits::min()); - sizeMinBy = resolve(sizeMin, unitSizeMin, 0U); - sizeMaxBy = resolve(sizeMax, unitSizeMax, std::numeric_limits::max()); -} - - -namespace -{ -FilterConfig mergeFilterConfig(const FilterConfig& global, const FilterConfig& local) -{ - FilterConfig out = local; - - //hard filter - if (out.includeFilter == FilterConfig().includeFilter) - out.includeFilter = global.includeFilter; - //else: if both global and local include filter contain data, only local filter is preserved - - trim(out.excludeFilter, true, false); - out.excludeFilter = global.excludeFilter + Zstr("\n") + out.excludeFilter; - trim(out.excludeFilter, true, false); - - //soft filter - Int64 loctimeFrom; - UInt64 locSizeMinBy; - UInt64 locSizeMaxBy; - resolveUnits(out.timeSpan, out.unitTimeSpan, - out.sizeMin, out.unitSizeMin, - out.sizeMax, out.unitSizeMax, - loctimeFrom, //unit: UTC time, seconds - locSizeMinBy, //unit: bytes - locSizeMaxBy); //unit: bytes - - //soft filter - Int64 glotimeFrom; - UInt64 gloSizeMinBy; - UInt64 gloSizeMaxBy; - resolveUnits(global.timeSpan, global.unitTimeSpan, - global.sizeMin, global.unitSizeMin, - global.sizeMax, global.unitSizeMax, - glotimeFrom, - gloSizeMinBy, - gloSizeMaxBy); - - if (glotimeFrom > loctimeFrom) - { - out.timeSpan = global.timeSpan; - out.unitTimeSpan = global.unitTimeSpan; - } - if (gloSizeMinBy > locSizeMinBy) - { - out.sizeMin = global.sizeMin; - out.unitSizeMin = global.unitSizeMin; - } - if (gloSizeMaxBy < locSizeMaxBy) - { - out.sizeMax = global.sizeMax; - out.unitSizeMax = global.unitSizeMax; - } - return out; -} - - -inline -bool effectivelyEmpty(const FolderPairEnh& fp) -{ - auto isEmpty = [](Zstring dirname) - { - trim(dirname); - return dirname.empty(); - }; - return isEmpty(fp.leftDirectory) && isEmpty(fp.rightDirectory); -} -} - - -MainConfiguration zen::merge(const std::vector& mainCfgs) -{ - assert(!mainCfgs.empty()); - if (mainCfgs.empty()) - return MainConfiguration(); - - if (mainCfgs.size() == 1) //mergeConfigFilesImpl relies on this! - return mainCfgs[0]; // - - //merge folder pair config - std::vector fpMerged; - for (const MainConfiguration& mainCfg : mainCfgs) - { - std::vector fpTmp; - - //skip empty folder pairs - if (!effectivelyEmpty(mainCfg.firstPair)) - fpTmp.push_back(mainCfg.firstPair); - for (const FolderPairEnh& fp : mainCfg.additionalPairs) - if (!effectivelyEmpty(fp)) - fpTmp.push_back(fp); - - //move all configuration down to item level - for (FolderPairEnh& fp : fpTmp) - { - if (!fp.altCmpConfig.get()) - fp.altCmpConfig = std::make_shared(mainCfg.cmpConfig); - - if (!fp.altSyncConfig.get()) - fp.altSyncConfig = std::make_shared(mainCfg.syncCfg); - - fp.localFilter = mergeFilterConfig(mainCfg.globalFilter, fp.localFilter); - } - fpMerged.insert(fpMerged.end(), fpTmp.begin(), fpTmp.end()); - } - - if (fpMerged.empty()) - return MainConfiguration(); - - //optimization: remove redundant configuration - - //######################################################################################################################## - //find out which comparison and synchronization setting are used most often and use them as new "header" - std::vector> cmpCfgStat; - std::vector> syncCfgStat; - for (const FolderPairEnh& fp : fpMerged) - { - //rather inefficient algorithm, but it does not require a less-than operator: - { - const CompConfig& cmpCfg = *fp.altCmpConfig; - - auto it = std::find_if(cmpCfgStat.begin(), cmpCfgStat.end(), - [&](const std::pair& entry) { return effectivelyEqual(entry.first, cmpCfg); }); - if (it == cmpCfgStat.end()) - cmpCfgStat.push_back(std::make_pair(cmpCfg, 1)); - else - ++(it->second); - } - { - const SyncConfig& syncCfg = *fp.altSyncConfig; - - auto it = std::find_if(syncCfgStat.begin(), syncCfgStat.end(), - [&](const std::pair& entry) { return effectivelyEqual(entry.first, syncCfg); }); - if (it == syncCfgStat.end()) - syncCfgStat.push_back(std::make_pair(syncCfg, 1)); - else - ++(it->second); - } - } - - //set most-used comparison and synchronization settings as new header options - const CompConfig cmpCfgHead = cmpCfgStat.empty() ? CompConfig() : - std::max_element(cmpCfgStat.begin(), cmpCfgStat.end(), - [](const std::pair& lhs, const std::pair& rhs) { return lhs.second < rhs.second; })->first; - - const SyncConfig syncCfgHead = syncCfgStat.empty() ? SyncConfig() : - std::max_element(syncCfgStat.begin(), syncCfgStat.end(), - [](const std::pair& lhs, const std::pair& rhs) { return lhs.second < rhs.second; })->first; - //######################################################################################################################## - - FilterConfig globalFilter; - const bool allFiltersEqual = std::all_of(fpMerged.begin(), fpMerged.end(), [&](const FolderPairEnh& fp) { return fp.localFilter == fpMerged[0].localFilter; }); - if (allFiltersEqual) - globalFilter = fpMerged[0].localFilter; - - //strip redundancy... - for (FolderPairEnh& fp : fpMerged) - { - //if local config matches output global config we don't need local one - if (fp.altCmpConfig && - effectivelyEqual(*fp.altCmpConfig, cmpCfgHead)) - fp.altCmpConfig.reset(); - - if (fp.altSyncConfig && - effectivelyEqual(*fp.altSyncConfig, syncCfgHead)) - fp.altSyncConfig.reset(); - - if (allFiltersEqual) //use global filter in this case - fp.localFilter = FilterConfig(); - } - - //final assembly - zen::MainConfiguration cfgOut; - cfgOut.cmpConfig = cmpCfgHead; - cfgOut.syncCfg = syncCfgHead; - cfgOut.globalFilter = globalFilter; - cfgOut.firstPair = fpMerged[0]; - cfgOut.additionalPairs.assign(fpMerged.begin() + 1, fpMerged.end()); - cfgOut.onCompletion = mainCfgs[0].onCompletion; - return cfgOut; -} -- cgit