More consistent default handling for StringOption
[alexxy/gromacs.git] / src / gromacs / options / basicoptions.h
index 8c964d3a4cefcb4c64c76c829c6adfc15759b93a..67f14e31d9414018c57e06deef57e00da2c586fe 100644 (file)
@@ -1,32 +1,36 @@
 /*
+ * 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.
  */
 /*! \file
  * \brief
@@ -35,7 +39,7 @@
  * Together with options.h, this header forms the part of the public API
  * that most classes will use to provide options.
  *
- * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \author Teemu Murtola <teemu.murtola@gmail.com>
  * \inpublicapi
  * \ingroup module_options
  */
@@ -44,6 +48,7 @@
 
 #include <string>
 
+#include "../utility/basedefinitions.h"
 #include "../utility/gmxassert.h"
 
 #include "abstractoption.h"
@@ -55,8 +60,12 @@ class BooleanOptionInfo;
 class BooleanOptionStorage;
 class IntegerOptionInfo;
 class IntegerOptionStorage;
+class Int64OptionInfo;
+class Int64OptionStorage;
 class DoubleOptionInfo;
 class DoubleOptionStorage;
+class FloatOptionInfo;
+class FloatOptionStorage;
 class StringOptionInfo;
 class StringOptionStorage;
 
@@ -89,7 +98,8 @@ class BooleanOption : public OptionTemplate<bool, BooleanOption>
 
     private:
         //! Creates a BooleanOptionStorage object.
-        virtual AbstractOptionStoragePointer createStorage() const;
+        virtual AbstractOptionStorage *createStorage(
+            const OptionManagerContainer &managers) const;
 };
 
 /*! \brief
@@ -131,7 +141,8 @@ class IntegerOption : public OptionTemplate<int, IntegerOption>
 
     private:
         //! Creates an IntegerOptionStorage object.
-        virtual AbstractOptionStoragePointer createStorage() const;
+        virtual AbstractOptionStorage *createStorage(
+            const OptionManagerContainer &managers) const;
 
         /*! \brief
          * Needed to initialize IntegerOptionStorage from this class without
@@ -140,6 +151,36 @@ class IntegerOption : public OptionTemplate<int, IntegerOption>
         friend class IntegerOptionStorage;
 };
 
+/*! \brief
+ * Specifies an option that provides 64-bit integer values.
+ *
+ * Public methods in this class do not throw.
+ *
+ * \see IntegerOption
+ *
+ * \inpublicapi
+ */
+class Int64Option : public OptionTemplate<gmx_int64_t, Int64Option>
+{
+    public:
+        //! OptionInfo subclass corresponding to this option type.
+        typedef Int64OptionInfo InfoType;
+
+        //! Initializes an option with the given name.
+        explicit Int64Option(const char *name) : MyBase(name) {}
+
+    private:
+        //! Creates an Int64OptionStorage object.
+        virtual AbstractOptionStorage *createStorage(
+            const OptionManagerContainer &managers) const;
+
+        /*! \brief
+         * Needed to initialize Int64OptionStorage from this class without
+         * otherwise unnecessary accessors.
+         */
+        friend class Int64OptionStorage;
+};
+
 /*! \brief
  * Specifies an option that provides floating-point (double) values.
  *
@@ -165,7 +206,7 @@ class DoubleOption : public OptionTemplate<double, DoubleOption>
          *
          * By itself, this option does nothing.  It marks the option as a time
          * value such that TimeUnitManager::scaleTimeOptions() can process it.
-         * In typical cases, Gromacs scales the time options just before
+         * In typical cases, \Gromacs scales the time options just before
          * Options::finish() has been called, so the option value is only
          * available after all option values have been processed.
          * All values in the program are in ps (including any default value);
@@ -176,7 +217,8 @@ class DoubleOption : public OptionTemplate<double, DoubleOption>
 
     private:
         //! Creates a DoubleOptionStorage object.
-        virtual AbstractOptionStoragePointer createStorage() const;
+        virtual AbstractOptionStorage *createStorage(
+            const OptionManagerContainer &managers) const;
 
         bool bTime_;
 
@@ -187,6 +229,45 @@ class DoubleOption : public OptionTemplate<double, DoubleOption>
         friend class DoubleOptionStorage;
 };
 
+/*! \brief
+ * Specifies an option that provides floating-point (float) values.
+ *
+ * Public methods in this class do not throw.
+ *
+ * \see DoubleOption
+ *
+ * \inpublicapi
+ */
+class FloatOption : public OptionTemplate<float, FloatOption>
+{
+    public:
+        //! OptionInfo subclass corresponding to this option type.
+        typedef FloatOptionInfo InfoType;
+
+        //! Initializes an option with the given name.
+        explicit FloatOption(const char *name) : MyBase(name), bTime_(false)
+        {
+        }
+
+        //! \copydoc IntegerOption::vector()
+        MyClass &vector() { setVector(); return me(); }
+        //! \copydoc DoubleOption::timeValue()
+        MyClass &timeValue() { bTime_ = true; return me(); }
+
+    private:
+        //! Creates a FloatOptionStorage object.
+        virtual AbstractOptionStorage *createStorage(
+            const OptionManagerContainer &managers) const;
+
+        bool bTime_;
+
+        /*! \brief
+         * Needed to initialize FloatOptionStorage from this class without
+         * otherwise unnecessary accessors.
+         */
+        friend class FloatOptionStorage;
+};
+
 /*! \brief
  * Specifies an option that provides string values.
  *
@@ -197,7 +278,7 @@ class DoubleOption : public OptionTemplate<double, DoubleOption>
    std::string  str;
    options.addOption(StringOption("str").store(&str));
    // Option that only accepts predefined values
-   const char * const  allowed[] = { "atom", "residue", "molecule", NULL };
+   const char * const  allowed[] = { "atom", "residue", "molecule" };
    std::string  str;
    int          type;
    options.addOption(StringOption("type").enumValue(allowed).store(&str)
@@ -216,16 +297,15 @@ class StringOption : public OptionTemplate<std::string, StringOption>
 
         //! Initializes an option with the given name.
         explicit StringOption(const char *name)
-            : MyBase(name), enumValues_(NULL), defaultEnumIndex_(-1),
-              enumIndexStore_(NULL)
+            : MyBase(name), enumValues_(NULL), enumValuesCount_(0),
+              defaultEnumIndex_(-1), enumIndexStore_(NULL)
         {
         }
 
         /*! \brief
          * Sets the option to only accept one of a fixed set of strings.
          *
-         * \param[in] values  Array of strings to accept, a NULL pointer
-         *      following the last string.
+         * \param[in] values  Array of strings to accept.
          *
          * Also accepts prefixes of the strings; if a prefix matches more than
          * one of the possible strings, the shortest one is used (in a tie, the
@@ -237,8 +317,35 @@ class StringOption : public OptionTemplate<std::string, StringOption>
          *
          * The strings are copied once the option is created.
          */
-        MyClass &enumValue(const char *const *values)
-        { enumValues_ = values; return me(); }
+        template <size_t count>
+        MyClass &enumValue(const char *const (&values)[count])
+        {
+            GMX_ASSERT(enumValues_ == NULL,
+                       "Multiple sets of enumerated values specified");
+            enumValues_      = values;
+            enumValuesCount_ = count;
+            return me();
+        }
+        /*! \brief
+         * Sets the option to only accept one of a fixed set of strings.
+         *
+         * \param[in] values  Array of strings to accept, with a NULL pointer
+         *      following the last string.
+         *
+         * Works otherwise as the array version, but accepts a pointer to
+         * an array of undetermined length.  The end of the array is indicated
+         * by a NULL pointer in the array.
+         *
+         * \see enumValue()
+         */
+        MyClass &enumValueFromNullTerminatedArray(const char *const *values)
+        {
+            GMX_ASSERT(enumValues_ == NULL,
+                       "Multiple sets of enumerated values specified");
+            enumValues_      = values;
+            enumValuesCount_ = -1;
+            return me();
+        }
         /*! \brief
          * Sets the default value using an index into the enumeration table.
          *
@@ -246,7 +353,7 @@ class StringOption : public OptionTemplate<std::string, StringOption>
          */
         MyClass &defaultEnumIndex(int index)
         {
-            GMX_RELEASE_ASSERT(index >= 0, "Invalid enumeration index");
+            GMX_ASSERT(index >= 0, "Invalid enumeration index");
             defaultEnumIndex_ = index;
             return me();
         }
@@ -257,19 +364,27 @@ class StringOption : public OptionTemplate<std::string, StringOption>
          * The index (zero-based) of the selected value in the array \p values
          * provided to enumValues() is written into \p *store after the
          * option gets its value.  If the option has not been provided,
-         * and there is no default value, -1 is stored.
+         * and there is no default value, -1 is stored.  If store(),
+         * storeVector() or defaultEnumIndex() is not present, the value in
+         * \p *store is kept as a default value, otherwise it is always
+         * overwritten.
          *
          * Cannot be specified without enumValue().
+         *
+         * \todo
+         * Implement this such that it is also possible to store the value
+         * directly into a real enum type.
          */
         MyClass &storeEnumIndex(int *store)
         { enumIndexStore_ = store; return me(); }
 
     private:
         //! Creates a StringOptionStorage object.
-        virtual AbstractOptionStoragePointer createStorage() const;
-        virtual std::string createDescription() const;
+        virtual AbstractOptionStorage *createStorage(
+            const OptionManagerContainer &managers) const;
 
         const char *const      *enumValues_;
+        int                     enumValuesCount_;
         int                     defaultEnumIndex_;
         int                    *enumIndexStore_;
 
@@ -290,6 +405,12 @@ class BooleanOptionInfo : public OptionInfo
     public:
         //! Creates an option info object for the given option.
         explicit BooleanOptionInfo(BooleanOptionStorage *option);
+
+        //! Returns the default value for this option.
+        bool defaultValue() const;
+
+    private:
+        const BooleanOptionStorage &option() const;
 };
 
 /*! \brief
@@ -304,6 +425,18 @@ class IntegerOptionInfo : public OptionInfo
         explicit IntegerOptionInfo(IntegerOptionStorage *option);
 };
 
+/*! \brief
+ * Wrapper class for accessing 64-bit integer option information.
+ *
+ * \inpublicapi
+ */
+class Int64OptionInfo : public OptionInfo
+{
+    public:
+        //! Creates an option info object for the given option.
+        explicit Int64OptionInfo(Int64OptionStorage *option);
+};
+
 /*! \brief
  * Wrapper class for accessing floating-point option information.
  *
@@ -333,6 +466,28 @@ class DoubleOptionInfo : public OptionInfo
         const DoubleOptionStorage &option() const;
 };
 
+/*! \brief
+ * Wrapper class for accessing floating-point option information.
+ *
+ * \inpublicapi
+ */
+class FloatOptionInfo : public OptionInfo
+{
+    public:
+        //! Creates an option info object for the given option.
+        explicit FloatOptionInfo(FloatOptionStorage *option);
+
+        //! Whether the option specifies a time value.
+        bool isTime() const;
+
+        //! \copydoc DoubleOptionInfo::setScaleFactor()
+        void setScaleFactor(double factor);
+
+    private:
+        FloatOptionStorage &option();
+        const FloatOptionStorage &option() const;
+};
+
 /*! \brief
  * Wrapper class for accessing string option information.
  *
@@ -343,8 +498,48 @@ class StringOptionInfo : public OptionInfo
     public:
         //! Creates an option info object for the given option.
         explicit StringOptionInfo(StringOptionStorage *option);
+
+        /*! \brief
+         * Whether this option accepts an enumerated set of values.
+         *
+         * Returns true if StringOption::enumValues() was used when creating
+         * this option.
+         */
+        bool isEnumerated() const;
+        /*! \brief
+         * Returns the set of allowed values for this option.
+         *
+         * Returns an empty vector if isEnumerated() returns false.
+         */
+        const std::vector<std::string> &allowedValues() const;
+
+    private:
+        StringOptionStorage &option();
+        const StringOptionStorage &option() const;
 };
 
+/*! \typedef RealOption
+ * \brief
+ * Typedef for either DoubleOption or FloatOption, depending on precision.
+ *
+ * Generally, new would be better using DoubleOption, but this is provided for
+ * cases where the output value needs to be of type `real` for some reason.
+ */
+/*! \typedef RealOptionInfo
+ * \brief
+ * Typedef for either DoubleOptionInfo or FloatOptionInfo, depending on precision.
+ *
+ * Generally, new would be better using DoubleOption, but this is provided for
+ * cases where the output value needs to be of type `real` for some reason.
+ */
+#ifdef GMX_DOUBLE
+typedef DoubleOption     RealOption;
+typedef DoubleOptionInfo RealOptionInfo;
+#else
+typedef FloatOption      RealOption;
+typedef FloatOptionInfo  RealOptionInfo;
+#endif
+
 /*!\}*/
 
 } // namespace gmx