Merge branch release-5-1
[alexxy/gromacs.git] / src / gromacs / options / filenameoptionmanager.cpp
index 834ec2cc78e2ce250448aac5ddb8cd02a21da05c..1a627cd85c6d7f550f915cd71458928357855854 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2014, by the GROMACS development team, led by
+ * Copyright (c) 2014,2015, by the GROMACS development team, led by
  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
  * and including many others, as listed in the AUTHORS file in the
  * top-level source directory and at http://www.gromacs.org.
@@ -53,7 +53,7 @@
 #include "gromacs/options/options.h"
 #include "gromacs/utility/arrayref.h"
 #include "gromacs/utility/exceptions.h"
-#include "gromacs/utility/file.h"
+#include "gromacs/utility/fileredirector.h"
 #include "gromacs/utility/path.h"
 #include "gromacs/utility/stringutil.h"
 
@@ -79,15 +79,16 @@ const char *const c_compressedExtensions[] =
  * The first match is returned.
  * Returns an empty string if no existing file is found.
  */
-std::string findExistingExtension(const std::string        &prefix,
-                                  const FileNameOptionInfo &option)
+std::string findExistingExtension(const std::string                  &prefix,
+                                  const FileNameOptionInfo           &option,
+                                  const IFileInputRedirector         *redirector)
 {
     ConstArrayRef<int>                 types = option.fileTypes();
     ConstArrayRef<int>::const_iterator i;
     for (i = types.begin(); i != types.end(); ++i)
     {
         std::string testFilename(prefix + ftp2ext_with_dot(*i));
-        if (File::exists(testFilename))
+        if (redirector->fileExists(testFilename))
         {
             return testFilename;
         }
@@ -109,12 +110,18 @@ std::string findExistingExtension(const std::string        &prefix,
 class FileNameOptionManager::Impl
 {
     public:
-        Impl() : bInputCheckingDisabled_(false) {}
+        Impl()
+            : redirector_(&defaultFileInputRedirector()),
+              bInputCheckingDisabled_(false)
+        {
+        }
 
+        //! Redirector for file existence checks.
+        const IFileInputRedirector         *redirector_;
         //! Global default file name, if set.
-        std::string     defaultFileName_;
+        std::string                         defaultFileName_;
         //! Whether input option processing has been disabled.
-        bool            bInputCheckingDisabled_;
+        bool                                bInputCheckingDisabled_;
 };
 
 /********************************************************************
@@ -130,6 +137,12 @@ FileNameOptionManager::~FileNameOptionManager()
 {
 }
 
+void FileNameOptionManager::setInputRedirector(
+        const IFileInputRedirector *redirector)
+{
+    impl_->redirector_ = redirector;
+}
+
 void FileNameOptionManager::disableInputOptionChecking(bool bDisable)
 {
     impl_->bInputCheckingDisabled_ = bDisable;
@@ -146,13 +159,16 @@ void FileNameOptionManager::addDefaultFileNameOption(
 std::string FileNameOptionManager::completeFileName(
         const std::string &value, const FileNameOptionInfo &option)
 {
-    const bool bInput = option.isInputFile() || option.isInputOutputFile();
+    const bool bAllowMissing = option.allowMissing();
+    const bool bInput
+        = option.isInputFile() || option.isInputOutputFile();
     // Currently, directory options are simple, and don't need any
     // special processing.
     // TODO: Consider splitting them into a separate DirectoryOption.
     if (option.isDirectoryOption())
     {
-        if (!impl_->bInputCheckingDisabled_ && bInput && !Directory::exists(value))
+        if (!impl_->bInputCheckingDisabled_ && bInput && !bAllowMissing
+            && !Directory::exists(value))
         {
             std::string message
                 = formatString("Directory '%s' does not exist or is not accessible.",
@@ -166,7 +182,7 @@ std::string FileNameOptionManager::completeFileName(
     const int fileType = fn2ftp(value.c_str());
     if (bInput && !impl_->bInputCheckingDisabled_)
     {
-        if (fileType == efNR && File::exists(value))
+        if (fileType == efNR && impl_->redirector_->fileExists(value))
         {
             ConstArrayRef<const char *>                 compressedExtensions(c_compressedExtensions);
             ConstArrayRef<const char *>::const_iterator ext;
@@ -193,12 +209,17 @@ std::string FileNameOptionManager::completeFileName(
         }
         else if (fileType == efNR)
         {
-            std::string processedValue = findExistingExtension(value, option);
+            const std::string processedValue
+                = findExistingExtension(value, option, impl_->redirector_);
             if (!processedValue.empty())
             {
                 return processedValue;
             }
-            if (option.isLibraryFile())
+            if (bAllowMissing)
+            {
+                return value + option.defaultExtension();
+            }
+            else if (option.isLibraryFile())
             {
                 // TODO: Treat also library files here.
                 return value + option.defaultExtension();
@@ -218,7 +239,7 @@ std::string FileNameOptionManager::completeFileName(
             {
                 // TODO: Treat also library files.
             }
-            else if (!File::exists(value))
+            else if (!bAllowMissing && !impl_->redirector_->fileExists(value))
             {
                 std::string message
                     = formatString("File '%s' does not exist or is not accessible.",
@@ -247,21 +268,26 @@ std::string FileNameOptionManager::completeFileName(
 std::string FileNameOptionManager::completeDefaultFileName(
         const std::string &prefix, const FileNameOptionInfo &option)
 {
-    if (option.isDirectoryOption() || impl_->bInputCheckingDisabled_)
+    if (option.isDirectoryOption())
     {
         return std::string();
     }
     const bool        bInput = option.isInputFile() || option.isInputOutputFile();
     const std::string realPrefix
         = !impl_->defaultFileName_.empty() ? impl_->defaultFileName_ : prefix;
-    if (bInput)
+    if (bInput && !impl_->bInputCheckingDisabled_)
     {
-        std::string completedName = findExistingExtension(realPrefix, option);
+        const std::string completedName
+            = findExistingExtension(realPrefix, option, impl_->redirector_);
         if (!completedName.empty())
         {
             return completedName;
         }
-        if (option.isLibraryFile())
+        if (option.allowMissing())
+        {
+            return realPrefix + option.defaultExtension();
+        }
+        else if (option.isLibraryFile())
         {
             // TODO: Treat also library files here.
             return realPrefix + option.defaultExtension();