Sort all includes in src/gromacs
[alexxy/gromacs.git] / src / gromacs / options / basicoptions.cpp
index 0f0826b3563465695fb741d60ec37c21ffa5f48f..412455560756b6325fa1fc173be892f898e05d84 100644 (file)
@@ -1,42 +1,47 @@
 /*
+ * This file is part of the GROMACS molecular simulation package.
  *
- *                This source code is part of
+ * Copyright (c) 2010,2011,2012,2013,2014, 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.
  *
- *                 G   R   O   M   A   C   S
+ * GROMACS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * of the License, or (at your option) any later version.
  *
- *          GROningen MAchine for Chemical Simulations
+ * GROMACS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
  *
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2009, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with GROMACS; if not, see
+ * http://www.gnu.org/licenses, or write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
  *
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
+ * If you want to redistribute modifications to GROMACS, please
+ * consider that scientific software is very special. Version
+ * control is crucial - bugs must be traceable. We will be happy to
+ * consider code for inclusion in the official distribution, but
+ * derived work must not be called official GROMACS. Details are found
+ * in the README & COPYING files - if they are missing, get the
+ * official version at http://www.gromacs.org.
  *
  * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- *
- * For more info, check our website at http://www.gromacs.org
+ * the research papers on the package. Check out http://www.gromacs.org.
  */
 /*! \internal \file
  * \brief
  * Implements classes in basicoptions.h and basicoptionstorage.h.
  *
- * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \author Teemu Murtola <teemu.murtola@gmail.com>
  * \ingroup module_options
  */
+#include "gmxpre.h"
+
 #include "basicoptions.h"
-#include "basicoptionstorage.h"
 
 #include <cerrno>
 #include <cstdio>
 #include <string>
 #include <vector>
 
+#include "gromacs/utility/cstringutil.h"
 #include "gromacs/utility/exceptions.h"
 #include "gromacs/utility/stringutil.h"
 
+#include "basicoptionstorage.h"
+
 namespace
 {
 
@@ -68,12 +76,12 @@ namespace
 template <typename ValueType>
 void expandVector(size_t length, std::vector<ValueType> *values)
 {
-    if (length > 0 && values->size() > 0 && values->size() != length)
+    if (length > 0 && !values->empty() && values->size() != length)
     {
         if (values->size() != 1)
         {
             GMX_THROW(gmx::InvalidInputError(gmx::formatString(
-                      "Expected 1 or %d values, got %d", length, values->size())));
+                                                     "Expected 1 or %d values, got %d", length, values->size())));
         }
         const ValueType &value = (*values)[0];
         values->resize(length, value);
@@ -119,13 +127,24 @@ BooleanOptionInfo::BooleanOptionInfo(BooleanOptionStorage *option)
 {
 }
 
+const BooleanOptionStorage &BooleanOptionInfo::option() const
+{
+    return static_cast<const BooleanOptionStorage &>(OptionInfo::option());
+}
+
+bool BooleanOptionInfo::defaultValue() const
+{
+    return option().defaultValue();
+}
+
 /********************************************************************
  * BooleanOption
  */
 
-AbstractOptionStoragePointer BooleanOption::createStorage() const
+AbstractOptionStorage *
+BooleanOption::createStorage(const OptionManagerContainer & /*managers*/) const
 {
-    return AbstractOptionStoragePointer(new BooleanOptionStorage(*this));
+    return new BooleanOptionStorage(*this);
 }
 
 
@@ -141,9 +160,9 @@ std::string IntegerOptionStorage::formatSingleValue(const int &value) const
 void IntegerOptionStorage::convertValue(const std::string &value)
 {
     const char *ptr = value.c_str();
-    char *endptr;
+    char       *endptr;
     errno = 0;
-    long int ival = std::strtol(ptr, &endptr, 10);
+    long int    ival = std::strtol(ptr, &endptr, 10);
     if (errno == ERANGE
         || ival < std::numeric_limits<int>::min()
         || ival > std::numeric_limits<int>::max())
@@ -180,9 +199,58 @@ IntegerOptionInfo::IntegerOptionInfo(IntegerOptionStorage *option)
  * IntegerOption
  */
 
-AbstractOptionStoragePointer IntegerOption::createStorage() const
+AbstractOptionStorage *
+IntegerOption::createStorage(const OptionManagerContainer & /*managers*/) const
+{
+    return new IntegerOptionStorage(*this);
+}
+
+
+/********************************************************************
+ * Int64OptionStorage
+ */
+
+std::string Int64OptionStorage::formatSingleValue(const gmx_int64_t &value) const
+{
+    return formatString("%" GMX_PRId64, value);
+}
+
+void Int64OptionStorage::convertValue(const std::string &value)
+{
+    const char       *ptr = value.c_str();
+    char             *endptr;
+    errno = 0;
+    const gmx_int64_t ival = str_to_int64_t(ptr, &endptr);
+    if (errno == ERANGE)
+    {
+        GMX_THROW(InvalidInputError("Invalid value: '" + value
+                                    + "'; it causes an integer overflow"));
+    }
+    if (*ptr == '\0' || *endptr != '\0')
+    {
+        GMX_THROW(InvalidInputError("Invalid value: '" + value
+                                    + "'; expected an integer"));
+    }
+    addValue(ival);
+}
+
+/********************************************************************
+ * Int64OptionInfo
+ */
+
+Int64OptionInfo::Int64OptionInfo(Int64OptionStorage *option)
+    : OptionInfo(option)
+{
+}
+
+/********************************************************************
+ * Int64Option
+ */
+
+AbstractOptionStorage *
+Int64Option::createStorage(const OptionManagerContainer & /*managers*/) const
 {
-    return AbstractOptionStoragePointer(new IntegerOptionStorage(*this));
+    return new Int64OptionStorage(*this);
 }
 
 
@@ -195,9 +263,9 @@ DoubleOptionStorage::DoubleOptionStorage(const DoubleOption &settings)
 {
 }
 
-const char *DoubleOptionStorage::typeString() const
+std::string DoubleOptionStorage::typeString() const
 {
-    return isVector() ? "vector" : (isTime() ? "time" : "double");
+    return isVector() ? "vector" : (isTime() ? "time" : "real");
 }
 
 std::string DoubleOptionStorage::formatSingleValue(const double &value) const
@@ -208,9 +276,9 @@ std::string DoubleOptionStorage::formatSingleValue(const double &value) const
 void DoubleOptionStorage::convertValue(const std::string &value)
 {
     const char *ptr = value.c_str();
-    char *endptr;
+    char       *endptr;
     errno = 0;
-    double dval = std::strtod(ptr, &endptr);
+    double      dval = std::strtod(ptr, &endptr);
     if (errno == ERANGE)
     {
         GMX_THROW(InvalidInputError("Invalid value: '" + value
@@ -232,16 +300,12 @@ void DoubleOptionStorage::processSetValues(ValueList *values)
     }
 }
 
-void DoubleOptionStorage::processAll()
-{
-}
-
 void DoubleOptionStorage::setScaleFactor(double factor)
 {
     GMX_RELEASE_ASSERT(factor > 0.0, "Invalid scaling factor");
     if (!hasFlag(efOption_HasDefaultValue))
     {
-        double scale = factor / factor_;
+        double              scale = factor / factor_;
         ValueList::iterator i;
         for (i = values().begin(); i != values().end(); ++i)
         {
@@ -285,9 +349,114 @@ void DoubleOptionInfo::setScaleFactor(double factor)
  * DoubleOption
  */
 
-AbstractOptionStoragePointer DoubleOption::createStorage() const
+AbstractOptionStorage *
+DoubleOption::createStorage(const OptionManagerContainer & /*managers*/) const
+{
+    return new DoubleOptionStorage(*this);
+}
+
+
+/********************************************************************
+ * FloatOptionStorage
+ */
+
+FloatOptionStorage::FloatOptionStorage(const FloatOption &settings)
+    : MyBase(settings), info_(this), bTime_(settings.bTime_), factor_(1.0)
+{
+}
+
+std::string FloatOptionStorage::typeString() const
+{
+    return isVector() ? "vector" : (isTime() ? "time" : "real");
+}
+
+std::string FloatOptionStorage::formatSingleValue(const float &value) const
+{
+    return formatString("%g", value / factor_);
+}
+
+void FloatOptionStorage::convertValue(const std::string &value)
+{
+    const char *ptr = value.c_str();
+    char       *endptr;
+    errno = 0;
+    double      dval = std::strtod(ptr, &endptr);
+    if (errno == ERANGE
+        || dval * factor_ < -std::numeric_limits<float>::max()
+        || dval * factor_ >  std::numeric_limits<float>::max())
+    {
+        GMX_THROW(InvalidInputError("Invalid value: '" + value
+                                    + "'; it causes an overflow/underflow"));
+    }
+    if (*ptr == '\0' || *endptr != '\0')
+    {
+        GMX_THROW(InvalidInputError("Invalid value: '" + value
+                                    + "'; expected a number"));
+    }
+    addValue(dval * factor_);
+}
+
+void FloatOptionStorage::processSetValues(ValueList *values)
+{
+    if (isVector())
+    {
+        expandVector(maxValueCount(), values);
+    }
+}
+
+void FloatOptionStorage::setScaleFactor(double factor)
+{
+    GMX_RELEASE_ASSERT(factor > 0.0, "Invalid scaling factor");
+    if (!hasFlag(efOption_HasDefaultValue))
+    {
+        double              scale = factor / factor_;
+        ValueList::iterator i;
+        for (i = values().begin(); i != values().end(); ++i)
+        {
+            (*i) *= scale;
+        }
+        refreshValues();
+    }
+    factor_ = factor;
+}
+
+/********************************************************************
+ * FloatOptionInfo
+ */
+
+FloatOptionInfo::FloatOptionInfo(FloatOptionStorage *option)
+    : OptionInfo(option)
+{
+}
+
+FloatOptionStorage &FloatOptionInfo::option()
+{
+    return static_cast<FloatOptionStorage &>(OptionInfo::option());
+}
+
+const FloatOptionStorage &FloatOptionInfo::option() const
+{
+    return static_cast<const FloatOptionStorage &>(OptionInfo::option());
+}
+
+bool FloatOptionInfo::isTime() const
+{
+    return option().isTime();
+}
+
+void FloatOptionInfo::setScaleFactor(double factor)
+{
+    option().setScaleFactor(factor);
+}
+
+/********************************************************************
+ * FloatOption
+ */
+
+AbstractOptionStorage *
+FloatOption::createStorage(const OptionManagerContainer & /*managers*/) const
 {
-    return AbstractOptionStoragePointer(new DoubleOptionStorage(*this));
+    return new FloatOptionStorage(*this);
 }
 
 
@@ -314,9 +483,22 @@ StringOptionStorage::StringOptionStorage(const StringOption &settings)
     {
         enumIndexStore_ = settings.enumIndexStore_;
         const std::string *defaultValue = settings.defaultValue();
-        int match = -1;
-        for (int i = 0; settings.enumValues_[i] != NULL; ++i)
+        int                match        = -1;
+        int                count        = settings.enumValuesCount_;
+        if (count < 0)
+        {
+            count = 0;
+            while (settings.enumValues_[count] != NULL)
+            {
+                ++count;
+            }
+        }
+        for (int i = 0; i < count; ++i)
         {
+            if (settings.enumValues_[i] == NULL)
+            {
+                GMX_THROW(APIError("Enumeration value cannot be NULL"));
+            }
             if (defaultValue != NULL && settings.enumValues_[i] == *defaultValue)
             {
                 match = i;
@@ -341,11 +523,6 @@ StringOptionStorage::StringOptionStorage(const StringOption &settings)
                 GMX_THROW(APIError("Conflicting default values"));
             }
         }
-        // If there is no default value, match is still -1.
-        if (enumIndexStore_ != NULL)
-        {
-            *enumIndexStore_ = match;
-        }
     }
     if (settings.defaultEnumIndex_ >= 0)
     {
@@ -353,6 +530,31 @@ StringOptionStorage::StringOptionStorage(const StringOption &settings)
         addValue(allowed_[settings.defaultEnumIndex_]);
         commitValues();
     }
+    // Somewhat subtly, this does not update the stored enum index if the
+    // caller has not provided store() or storeVector(), because values()
+    // will be empty in such a case.  This leads to (desired) behavior of
+    // preserving the existing value in the enum index store variable in such
+    // cases.
+    refreshEnumIndexStore();
+}
+
+std::string StringOptionStorage::formatExtraDescription() const
+{
+    std::string result;
+    if (!allowed_.empty())
+    {
+        result.append(": ");
+        ValueList::const_iterator i;
+        for (i = allowed_.begin(); i != allowed_.end(); ++i)
+        {
+            if (i != allowed_.begin())
+            {
+                result.append(", ");
+            }
+            result.append(*i);
+        }
+    }
+    return result;
 }
 
 std::string StringOptionStorage::formatSingleValue(const std::string &value) const
@@ -392,15 +594,27 @@ void StringOptionStorage::convertValue(const std::string &value)
 void StringOptionStorage::refreshValues()
 {
     MyBase::refreshValues();
+    refreshEnumIndexStore();
+}
+
+void StringOptionStorage::refreshEnumIndexStore()
+{
     if (enumIndexStore_ != NULL)
     {
         for (size_t i = 0; i < values().size(); ++i)
         {
-            ValueList::const_iterator match =
-                std::find(allowed_.begin(), allowed_.end(), values()[i]);
-            GMX_ASSERT(match != allowed_.end(),
-                       "Enum value not found (internal error)");
-            enumIndexStore_[i] = static_cast<int>(match - allowed_.begin());
+            if (values()[i].empty())
+            {
+                enumIndexStore_[i] = -1;
+            }
+            else
+            {
+                ValueList::const_iterator match =
+                    std::find(allowed_.begin(), allowed_.end(), values()[i]);
+                GMX_ASSERT(match != allowed_.end(),
+                           "Enum value not found (internal error)");
+                enumIndexStore_[i] = static_cast<int>(match - allowed_.begin());
+            }
         }
     }
 }
@@ -414,32 +628,34 @@ StringOptionInfo::StringOptionInfo(StringOptionStorage *option)
 {
 }
 
-/********************************************************************
- * StringOption
- */
+StringOptionStorage &StringOptionInfo::option()
+{
+    return static_cast<StringOptionStorage &>(OptionInfo::option());
+}
 
-AbstractOptionStoragePointer StringOption::createStorage() const
+const StringOptionStorage &StringOptionInfo::option() const
 {
-    return AbstractOptionStoragePointer(new StringOptionStorage(*this));
+    return static_cast<const StringOptionStorage &>(OptionInfo::option());
 }
 
-std::string StringOption::createDescription() const
+bool StringOptionInfo::isEnumerated() const
 {
-    std::string value(MyBase::createDescription());
+    return !allowedValues().empty();
+}
 
-    if (enumValues_ != NULL)
-    {
-        value.append(": ");
-        for (int i = 0; enumValues_[i] != NULL; ++i)
-        {
-            value.append(enumValues_[i]);
-            if (enumValues_[i + 1] != NULL)
-            {
-                value.append(enumValues_[i + 2] != NULL ? ", " : ", or ");
-            }
-        }
-    }
-    return value;
+const std::vector<std::string> &StringOptionInfo::allowedValues() const
+{
+    return option().allowedValues();
+}
+
+/********************************************************************
+ * StringOption
+ */
+
+AbstractOptionStorage *
+StringOption::createStorage(const OptionManagerContainer & /*managers*/) const
+{
+    return new StringOptionStorage(*this);
 }
 
 } // namespace gmx