summaryrefslogtreecommitdiff
path: root/structures.cpp
diff options
context:
space:
mode:
authorDaniel Wilhelm <daniel@wili.li>2014-04-18 17:11:56 +0200
committerDaniel Wilhelm <daniel@wili.li>2014-04-18 17:11:56 +0200
commit98ecf620f7de377dc8ae9ad7fbd1e3b24477e138 (patch)
treefaadc6d8822c20cd3bc6f50b2a98e6c580585949 /structures.cpp
parent3.16 (diff)
downloadFreeFileSync-98ecf620f7de377dc8ae9ad7fbd1e3b24477e138.tar.gz
FreeFileSync-98ecf620f7de377dc8ae9ad7fbd1e3b24477e138.tar.bz2
FreeFileSync-98ecf620f7de377dc8ae9ad7fbd1e3b24477e138.zip
3.17
Diffstat (limited to 'structures.cpp')
-rw-r--r--structures.cpp325
1 files changed, 203 insertions, 122 deletions
diff --git a/structures.cpp b/structures.cpp
index 6f38a0cf..f155fd84 100644
--- a/structures.cpp
+++ b/structures.cpp
@@ -6,27 +6,13 @@
//
#include "structures.h"
#include "shared/i18n.h"
-//#include <stdexcept>
+#include <iterator>
+#include <stdexcept>
-using namespace ffs3;
+using namespace zen;
-Zstring ffs3::standardExcludeFilter()
-{
-#ifdef FFS_WIN
- static Zstring exclude(wxT("\
-\\System Volume Information\\\n\
-\\RECYCLER\\\n\
-\\RECYCLED\\\n\
-\\$Recycle.Bin\\")); //exclude Recycle Bin
-#elif defined FFS_LINUX
- static Zstring exclude; //exclude nothing
-#endif
- return exclude;
-}
-
-
-wxString ffs3::getVariantName(CompareVariant var)
+wxString zen::getVariantName(CompareVariant var)
{
switch (var)
{
@@ -41,120 +27,93 @@ wxString ffs3::getVariantName(CompareVariant var)
}
-wxString ffs3::getVariantName(const SyncConfiguration& syncCfg)
+wxString zen::getVariantName(SyncConfig::Variant var)
{
- switch (getVariant(syncCfg))
+ switch (var)
{
- case SyncConfiguration::AUTOMATIC:
+ case SyncConfig::AUTOMATIC:
return _("<Automatic>");
- case SyncConfiguration::MIRROR:
+ case SyncConfig::MIRROR:
return _("Mirror ->>");
- case SyncConfiguration::UPDATE:
+ case SyncConfig::UPDATE:
return _("Update ->");
- case SyncConfiguration::CUSTOM:
+ case SyncConfig::CUSTOM:
return _("Custom");
}
return _("Error");
}
-void ffs3::setTwoWay(SyncConfiguration& syncCfg) //helper method used by <Automatic> mode fallback to overwrite old with newer files
-{
- syncCfg.automatic = false;
- syncCfg.exLeftSideOnly = SYNC_DIR_RIGHT;
- syncCfg.exRightSideOnly = SYNC_DIR_LEFT;
- syncCfg.leftNewer = SYNC_DIR_RIGHT;
- syncCfg.rightNewer = SYNC_DIR_LEFT;
- syncCfg.different = SYNC_DIR_NONE;
- syncCfg.conflict = SYNC_DIR_NONE;
-}
-
-
-SyncConfiguration::Variant ffs3::getVariant(const SyncConfiguration& syncCfg)
-{
- if (syncCfg.automatic == true)
- return SyncConfiguration::AUTOMATIC; //automatic mode
-
- if (syncCfg.exLeftSideOnly == SYNC_DIR_RIGHT &&
- syncCfg.exRightSideOnly == SYNC_DIR_RIGHT &&
- syncCfg.leftNewer == SYNC_DIR_RIGHT &&
- syncCfg.rightNewer == SYNC_DIR_RIGHT &&
- syncCfg.different == SYNC_DIR_RIGHT &&
- syncCfg.conflict == SYNC_DIR_RIGHT)
- return SyncConfiguration::MIRROR; //one way ->
-
- else if (syncCfg.exLeftSideOnly == SYNC_DIR_RIGHT &&
- syncCfg.exRightSideOnly == SYNC_DIR_NONE &&
- syncCfg.leftNewer == SYNC_DIR_RIGHT &&
- syncCfg.rightNewer == SYNC_DIR_NONE &&
- syncCfg.different == SYNC_DIR_RIGHT &&
- syncCfg.conflict == SYNC_DIR_NONE)
- return SyncConfiguration::UPDATE; //Update ->
- else
- return SyncConfiguration::CUSTOM; //other
-}
-
-
-void ffs3::setVariant(SyncConfiguration& syncCfg, const SyncConfiguration::Variant var)
+DirectionSet zen::extractDirections(const SyncConfig& cfg)
{
- switch (var)
+ DirectionSet output;
+ switch (cfg.var)
{
- case SyncConfiguration::AUTOMATIC:
- syncCfg.automatic = true;
+ case SyncConfig::AUTOMATIC:
+ throw std::logic_error("there are no predefined directions for automatic mode!");
+
+ case SyncConfig::MIRROR:
+ output.exLeftSideOnly = SYNC_DIR_RIGHT;
+ output.exRightSideOnly = SYNC_DIR_RIGHT;
+ output.leftNewer = SYNC_DIR_RIGHT;
+ output.rightNewer = SYNC_DIR_RIGHT;
+ output.different = SYNC_DIR_RIGHT;
+ output.conflict = SYNC_DIR_RIGHT;
break;
- case SyncConfiguration::MIRROR:
- syncCfg.automatic = false;
- syncCfg.exLeftSideOnly = SYNC_DIR_RIGHT;
- syncCfg.exRightSideOnly = SYNC_DIR_RIGHT;
- syncCfg.leftNewer = SYNC_DIR_RIGHT;
- syncCfg.rightNewer = SYNC_DIR_RIGHT;
- syncCfg.different = SYNC_DIR_RIGHT;
- syncCfg.conflict = SYNC_DIR_RIGHT;
- break;
- case SyncConfiguration::UPDATE:
- syncCfg.automatic = false;
- syncCfg.exLeftSideOnly = SYNC_DIR_RIGHT;
- syncCfg.exRightSideOnly = SYNC_DIR_NONE;
- syncCfg.leftNewer = SYNC_DIR_RIGHT;
- syncCfg.rightNewer = SYNC_DIR_NONE;
- syncCfg.different = SYNC_DIR_RIGHT;
- syncCfg.conflict = SYNC_DIR_NONE;
+
+ case SyncConfig::UPDATE:
+ output.exLeftSideOnly = SYNC_DIR_RIGHT;
+ output.exRightSideOnly = SYNC_DIR_NONE;
+ output.leftNewer = SYNC_DIR_RIGHT;
+ output.rightNewer = SYNC_DIR_NONE;
+ output.different = SYNC_DIR_RIGHT;
+ output.conflict = SYNC_DIR_NONE;
break;
- case SyncConfiguration::CUSTOM:
- assert(false);
+
+ case SyncConfig::CUSTOM:
+ output = cfg.custom;
break;
}
+ return output;
}
+DirectionSet zen::getTwoWaySet()
+{
+ DirectionSet output;
+ output.exLeftSideOnly = SYNC_DIR_RIGHT;
+ output.exRightSideOnly = SYNC_DIR_LEFT;
+ output.leftNewer = SYNC_DIR_RIGHT;
+ output.rightNewer = SYNC_DIR_LEFT;
+ output.different = SYNC_DIR_NONE;
+ output.conflict = SYNC_DIR_NONE;
+ return output;
+}
+
wxString MainConfiguration::getSyncVariantName()
{
- const SyncConfiguration firstSyncCfg =
- firstPair.altSyncConfig.get() ?
- firstPair.altSyncConfig->syncConfiguration :
- syncConfiguration; //fallback to main sync cfg
-
- const SyncConfiguration::Variant firstVariant = getVariant(firstSyncCfg);
+ const SyncConfig::Variant firstVariant = firstPair.altSyncConfig.get() ?
+ firstPair.altSyncConfig->syncConfiguration.var :
+ syncConfiguration.var; //fallback to main sync cfg
//test if there's a deviating variant within the additional folder pairs
for (std::vector<FolderPairEnh>::const_iterator i = additionalPairs.begin(); i != additionalPairs.end(); ++i)
{
- const SyncConfiguration::Variant thisVariant =
- i->altSyncConfig.get() ?
- getVariant(i->altSyncConfig->syncConfiguration) :
- getVariant(syncConfiguration);
+ const SyncConfig::Variant thisVariant = i->altSyncConfig.get() ?
+ i->altSyncConfig->syncConfiguration.var :
+ syncConfiguration.var;
if (thisVariant != firstVariant)
return _("Multiple...");
}
//seems to be all in sync...
- return getVariantName(firstSyncCfg);
+ return getVariantName(firstVariant);
}
-wxString ffs3::getDescription(CompareFilesResult cmpRes)
+wxString zen::getDescription(CompareFilesResult cmpRes)
{
switch (cmpRes)
{
@@ -181,7 +140,7 @@ wxString ffs3::getDescription(CompareFilesResult cmpRes)
}
-wxString ffs3::getSymbol(CompareFilesResult cmpRes)
+wxString zen::getSymbol(CompareFilesResult cmpRes)
{
switch (cmpRes)
{
@@ -207,7 +166,7 @@ wxString ffs3::getSymbol(CompareFilesResult cmpRes)
}
-wxString ffs3::getDescription(SyncOperation op)
+wxString zen::getDescription(SyncOperation op)
{
switch (op)
{
@@ -231,7 +190,7 @@ wxString ffs3::getDescription(SyncOperation op)
return _("Copy attributes only from right to left");
case SO_COPY_METADATA_TO_RIGHT:
return _("Copy attributes only from left to right");
- case SO_UNRESOLVED_CONFLICT:
+ case SO_UNRESOLVED_CONFLICT: //not used on GUI, but in .csv
return _("Conflicts/files that cannot be categorized");
};
@@ -240,7 +199,7 @@ wxString ffs3::getDescription(SyncOperation op)
}
-wxString ffs3::getSymbol(SyncOperation op)
+wxString zen::getSymbol(SyncOperation op)
{
switch (op)
{
@@ -273,7 +232,71 @@ wxString ffs3::getSymbol(SyncOperation op)
namespace
{
-bool sameFilterConfig(const std::vector<FolderPairEnh>& folderPairs)
+assert_static(std::numeric_limits<zen:: Int64>::is_specialized);
+assert_static(std::numeric_limits<zen::UInt64>::is_specialized);
+
+zen::Int64 resolve(size_t value, UnitTime unit, zen::Int64 defaultVal)
+{
+ double out = value;
+ switch (unit)
+ {
+ case UTIME_NONE:
+ return defaultVal;
+ case UTIME_SEC:
+ return zen::Int64(value);
+ case UTIME_MIN:
+ out *= 60;
+ break;
+ case UTIME_HOUR:
+ out *= 3600;
+ break;
+ case UTIME_DAY:
+ out *= 24 * 3600;
+ break;
+ }
+ return out >= to<double>(std::numeric_limits<zen::Int64>::max()) ? //prevent overflow!!!
+ std::numeric_limits<zen::Int64>::max() :
+ zen::Int64(out);
+}
+
+zen::UInt64 resolve(size_t value, UnitSize unit, zen::UInt64 defaultVal)
+{
+ double out = value;
+ switch (unit)
+ {
+ case USIZE_NONE:
+ return defaultVal;
+ case USIZE_BYTE:
+ return value;
+ case USIZE_KB:
+ out *= 1024;
+ break;
+ case USIZE_MB:
+ out *= 1024 * 1024;
+ break;
+ }
+ return out >= to<double>(std::numeric_limits<zen::UInt64>::max()) ? //prevent overflow!!!
+ std::numeric_limits<zen::UInt64>::max() :
+ zen::UInt64(out);
+}
+}
+
+void zen::resolveUnits(size_t timeSpan, UnitTime unitTimeSpan,
+ size_t sizeMin, UnitSize unitSizeMin,
+ size_t sizeMax, UnitSize unitSizeMax,
+ zen::Int64& timeSpanSec, //unit: seconds
+ zen::UInt64& sizeMinBy, //unit: bytes
+ zen::UInt64& sizeMaxBy) //unit: bytes
+{
+ timeSpanSec = resolve(timeSpan, unitTimeSpan, std::numeric_limits<zen::Int64>::max());
+ sizeMinBy = resolve(sizeMin, unitSizeMin, 0U);
+ sizeMaxBy = resolve(sizeMax, unitSizeMax, std::numeric_limits<zen::UInt64>::max());
+}
+
+
+namespace
+{
+bool sameFilter(const std::vector<FolderPairEnh>& folderPairs)
{
if (folderPairs.empty())
return true;
@@ -284,14 +307,75 @@ bool sameFilterConfig(const std::vector<FolderPairEnh>& folderPairs)
return true;
}
+
+
+bool isEmpty(const FolderPairEnh& fp)
+{
+ return fp == FolderPairEnh();
}
-ffs3::MainConfiguration ffs3::merge(const std::vector<MainConfiguration>& mainCfgs)
+FilterConfig mergeFilterConfig(const FilterConfig& global, const FilterConfig& local)
+{
+ FilterConfig out = local;
+
+ //hard filter
+
+ //pragmatism: if both global and local include filter contain data, only local filter is preserved
+ if (out.includeFilter == FilterConfig().includeFilter)
+ out.includeFilter = global.includeFilter;
+
+ out.excludeFilter.Trim(true, false);
+ out.excludeFilter = global.excludeFilter + Zstr("\n") + out.excludeFilter;
+ out.excludeFilter.Trim(true, false);
+
+ //soft filter
+ zen::Int64 locTimeSpanSec;
+ zen::UInt64 locSizeMinBy;
+ zen::UInt64 locSizeMaxBy;
+ zen::resolveUnits(out.timeSpan, out.unitTimeSpan,
+ out.sizeMin, out.unitSizeMin,
+ out.sizeMax, out.unitSizeMax,
+ locTimeSpanSec, //unit: seconds
+ locSizeMinBy, //unit: bytes
+ locSizeMaxBy); //unit: bytes
+
+ //soft filter
+ zen::Int64 gloTimeSpanSec;
+ zen::UInt64 gloSizeMinBy;
+ zen::UInt64 gloSizeMaxBy;
+ zen::resolveUnits(global.timeSpan, global.unitTimeSpan,
+ global.sizeMin, global.unitSizeMin,
+ global.sizeMax, global.unitSizeMax,
+ gloTimeSpanSec, //unit: seconds
+ gloSizeMinBy, //unit: bytes
+ gloSizeMaxBy); //unit: bytes
+
+ if (gloTimeSpanSec < locTimeSpanSec)
+ {
+ 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;
+}
+}
+
+
+zen::MainConfiguration zen::merge(const std::vector<MainConfiguration>& mainCfgs)
{
assert(!mainCfgs.empty());
if (mainCfgs.empty())
- return ffs3::MainConfiguration();
+ return zen::MainConfiguration();
if (mainCfgs.size() == 1) //mergeConfigFilesImpl relies on this!
return mainCfgs[0]; //
@@ -301,10 +385,12 @@ ffs3::MainConfiguration ffs3::merge(const std::vector<MainConfiguration>& mainCf
for (std::vector<MainConfiguration>::const_iterator i = mainCfgs.begin(); i != mainCfgs.end(); ++i)
{
std::vector<FolderPairEnh> fpTmp;
- fpTmp.push_back(i->firstPair);
- fpTmp.insert(fpTmp.end(), i->additionalPairs.begin(), i->additionalPairs.end());
- //move all configuration to item level
+ //list non-empty local configurations
+ if (!isEmpty(i->firstPair)) fpTmp.push_back(i->firstPair);
+ std::remove_copy_if(i->additionalPairs.begin(), i->additionalPairs.end(), std::back_inserter(fpTmp), &isEmpty);
+
+ //move all configuration down to item level
for (std::vector<FolderPairEnh>::iterator fp = fpTmp.begin(); fp != fpTmp.end(); ++fp)
{
if (!fp->altSyncConfig.get())
@@ -313,42 +399,37 @@ ffs3::MainConfiguration ffs3::merge(const std::vector<MainConfiguration>& mainCf
i->handleDeletion,
i->customDeletionDirectory));
- //pragmatism: if both global and local include filter contain data, only local filter is preserved
- if (fp->localFilter.includeFilter == FilterConfig().includeFilter)
- fp->localFilter.includeFilter = i->globalFilter.includeFilter;
-
- fp->localFilter.excludeFilter.Trim(true, false);
- fp->localFilter.excludeFilter = i->globalFilter.excludeFilter + Zstr("\n") + fp->localFilter.excludeFilter;
- fp->localFilter.excludeFilter.Trim(true, false);
+ fp->localFilter = mergeFilterConfig(i->globalFilter, fp->localFilter);
}
fpMerged.insert(fpMerged.end(), fpTmp.begin(), fpTmp.end());
}
+ if (fpMerged.empty())
+ return zen::MainConfiguration();
+
//optimization: remove redundant configuration
FilterConfig newGlobalFilter;
- const bool sameLocalFilter = sameFilterConfig(fpMerged);
- if (sameLocalFilter)
+ const bool equalFilters = sameFilter(fpMerged);
+ if (equalFilters)
newGlobalFilter = fpMerged[0].localFilter;
for (std::vector<FolderPairEnh>::iterator fp = fpMerged.begin(); fp != fpMerged.end(); ++fp)
{
//if local config matches output global config we don't need local one
if (fp->altSyncConfig &&
- *fp->altSyncConfig ==
- AlternateSyncConfig(mainCfgs[0].syncConfiguration,
- mainCfgs[0].handleDeletion,
- mainCfgs[0].customDeletionDirectory))
+ *fp->altSyncConfig == AlternateSyncConfig(mainCfgs[0].syncConfiguration,
+ mainCfgs[0].handleDeletion,
+ mainCfgs[0].customDeletionDirectory))
fp->altSyncConfig.reset();
- if (sameLocalFilter) //use global filter in this case
+ if (equalFilters) //use global filter in this case
fp->localFilter = FilterConfig();
}
-
//final assembly
- ffs3::MainConfiguration cfgOut = mainCfgs[0];
+ zen::MainConfiguration cfgOut = mainCfgs[0];
cfgOut.globalFilter = newGlobalFilter;
cfgOut.firstPair = fpMerged[0];
cfgOut.additionalPairs.assign(fpMerged.begin() + 1, fpMerged.end());
bgstack15