More consistent default handling for StringOption
[alexxy/gromacs.git] / src / gromacs / options / basicoptions.h
index 52504ac6a9f74a15d8879e57a048b5637a7b0c1c..67f14e31d9414018c57e06deef57e00da2c586fe 100644 (file)
@@ -1,10 +1,10 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2010,2011,2012, by the GROMACS development team, led by
- * David van der Spoel, Berk Hess, Erik Lindahl, and including many
- * others, as listed in the AUTHORS file in the top-level source
- * directory and at http://www.gromacs.org.
+ * 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.
  *
  * GROMACS is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public License
@@ -48,6 +48,7 @@
 
 #include <string>
 
+#include "../utility/basedefinitions.h"
 #include "../utility/gmxassert.h"
 
 #include "abstractoption.h"
@@ -59,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;
 
@@ -93,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
@@ -135,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
@@ -144,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.
  *
@@ -169,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);
@@ -180,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_;
 
@@ -191,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.
  *
@@ -201,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)
@@ -220,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
@@ -241,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.
          *
@@ -250,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();
         }
@@ -261,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_;
 
@@ -294,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
@@ -308,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.
  *
@@ -337,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.
  *
@@ -347,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