Reimplement subsections in Options
authorTeemu Murtola <teemu.murtola@gmail.com>
Fri, 10 Jun 2016 19:54:56 +0000 (22:54 +0300)
committerMark Abraham <mark.j.abraham@gmail.com>
Wed, 17 Aug 2016 15:31:38 +0000 (17:31 +0200)
Now the support for sections in Options provides an API similar to
other option types.  The main thing missing (both in the old and the new
implementation) is support for an "array of structs"-kind of options,
where multiple instances of the same section could create multiple
instances of some object in the code.  That should also be possible to
add following a similar public API, but the internals need quite a bit
of generalization to make that possible.  That will be done in
subsequent changes to keep the changes smaller.

Remove now-unused name and title for an Options object.

Change-Id: Ie76e31aae2de0816b4d294ff6869606d4a2bef49

29 files changed:
src/gromacs/commandline/cmdlinehelpmodule.cpp
src/gromacs/commandline/cmdlinehelpwriter.cpp
src/gromacs/commandline/cmdlinemodulemanager.cpp
src/gromacs/commandline/cmdlineoptionsmodule.cpp
src/gromacs/commandline/pargs.cpp
src/gromacs/commandline/shellcompletions.cpp
src/gromacs/commandline/tests/cmdlinehelpwriter.cpp
src/gromacs/commandline/tests/cmdlineparser.cpp
src/gromacs/options/CMakeLists.txt
src/gromacs/options/abstractoption.h
src/gromacs/options/ioptionscontainerwithsections.h [new file with mode: 0644]
src/gromacs/options/options-impl.h
src/gromacs/options/options.cpp
src/gromacs/options/options.h
src/gromacs/options/optionsassigner.cpp
src/gromacs/options/optionsassigner.h
src/gromacs/options/optionsection.h [new file with mode: 0644]
src/gromacs/options/optionsvisitor.cpp
src/gromacs/options/optionsvisitor.h
src/gromacs/options/tests/abstractoptionstorage.cpp
src/gromacs/options/tests/filenameoption.cpp
src/gromacs/options/tests/filenameoptionmanager.cpp
src/gromacs/options/tests/option.cpp
src/gromacs/options/tests/optionsassigner.cpp
src/gromacs/options/tests/timeunitmanager.cpp
src/gromacs/options/timeunitmanager.cpp
src/gromacs/selection/tests/selectionoption.cpp
src/gromacs/utility/classhelpers.h
src/testutils/testinit.cpp

index 054b5b3530ee4b2a37f7ff8b9907c7d07a9b9b17..a0b44a884d704c61a8406e79061171f6e7ed9c1a 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2012,2013,2014,2015, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016, 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.
@@ -949,7 +949,7 @@ int CommandLineHelpModule::run(int argc, char *argv[])
 
     const char *const exportFormats[] = { "rst", "completion" };
     std::string       exportFormat;
-    Options           options(NULL, NULL);
+    Options           options;
     options.addOption(StringOption("export").store(&exportFormat)
                           .enumValue(exportFormats));
     CommandLineParser(&options).parse(&argc, argv);
index 275f70fb9d4fe1363b27ef483b1b46cbd413a384..1ecd452d7e5d7933d40297aaf268805f1178d129 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2010,2011,2012,2013,2014,2015, by the GROMACS development team, led by
+ * Copyright (c) 2010,2011,2012,2013,2014,2015,2016, 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.
@@ -136,7 +136,7 @@ class OptionsFilter : public OptionsVisitor
                             IOptionsFormatter         *formatter,
                             const Options             &options);
 
-        virtual void visitSubSection(const Options &section);
+        virtual void visitSection(const OptionSectionInfo &section);
         virtual void visitOption(const OptionInfo &option);
 
     private:
@@ -153,13 +153,13 @@ void OptionsFilter::formatSelected(FilterType                 type,
 {
     formatter_  = formatter;
     filterType_ = type;
-    visitSubSection(options);
+    visitSection(options.rootSection());
 }
 
-void OptionsFilter::visitSubSection(const Options &section)
+void OptionsFilter::visitSection(const OptionSectionInfo &section)
 {
     OptionsIterator iterator(section);
-    iterator.acceptSubSections(this);
+    iterator.acceptSections(this);
     iterator.acceptOptions(this);
 }
 
index 556fd878b55a8490995c1c57cc4354b7deb1a693..1eaf5bc99f54ca7d58e61471d9c63a65c4763633 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2012,2013,2014,2015, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016, 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.
@@ -144,7 +144,7 @@ class CMainCommandLineModule : public ICommandLineModule
  */
 
 CommandLineCommonOptionsHolder::CommandLineCommonOptionsHolder()
-    : options_(NULL, NULL), bHelp_(false), bHidden_(false),
+    : bHelp_(false), bHidden_(false),
       bQuiet_(false), bVersion_(false), bCopyright_(true),
       niceLevel_(19), bNiceSet_(false), bBackup_(true), bFpexcept_(false),
       debugLevel_(0)
index ed87db95422c6780692fc6c42238c2367ba97836..b4d45d37556010611c2e8accdb319a7a28f08127 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2014,2015, by the GROMACS development team, led by
+ * Copyright (c) 2014,2015,2016, 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.
@@ -154,7 +154,7 @@ void CommandLineOptionsModule::writeHelp(const CommandLineHelpContext &context)
         moduleGuard = factory_();
         module      = moduleGuard.get();
     }
-    Options                          options(name(), shortDescription());
+    Options                          options;
     OptionsBehaviorCollection        behaviors(&options);
     CommandLineOptionsModuleSettings settings(&behaviors);
     module->initOptions(&options, &settings);
@@ -166,7 +166,7 @@ void CommandLineOptionsModule::writeHelp(const CommandLineHelpContext &context)
 void CommandLineOptionsModule::parseOptions(int argc, char *argv[])
 {
     FileNameOptionManager fileoptManager;
-    Options               options(name_, description_);
+    Options               options;
 
     options.addManager(&fileoptManager);
 
index 8fd3da8f470efc9d4d7b8f477524192962d26afb..edb4a056569ec8e2280c5c348051dd9166d48429 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
  * Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016, 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.
@@ -494,7 +494,7 @@ gmx_bool parse_common_args(int *argc, char *argv[], unsigned long Flags,
         bool                            bView         = false;
         int                             xvgFormat     = 0;
         gmx::OptionsAdapter             adapter(*argc, argv);
-        gmx::Options                    options(NULL, NULL);
+        gmx::Options                    options;
         gmx::OptionsBehaviorCollection  behaviors(&options);
         gmx::FileNameOptionManager      fileOptManager;
 
index be1cd70d97fcfa30844436087c35ef19e4c2cf11..88d64ab8c627d2060d5abbedaabc4e905ff21177 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
  * Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016, 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.
@@ -56,6 +56,7 @@
 #include "gromacs/fileio/filetypes.h"
 #include "gromacs/options/basicoptions.h"
 #include "gromacs/options/filenameoption.h"
+#include "gromacs/options/options.h"
 #include "gromacs/options/optionsvisitor.h"
 #include "gromacs/utility/arrayref.h"
 #include "gromacs/utility/exceptions.h"
@@ -74,10 +75,10 @@ class OptionsListWriter : public OptionsVisitor
     public:
         const std::string &optionList() const { return optionList_; }
 
-        virtual void visitSubSection(const Options &section)
+        virtual void visitSection(const OptionSectionInfo &section)
         {
             OptionsIterator iterator(section);
-            iterator.acceptSubSections(this);
+            iterator.acceptSections(this);
             iterator.acceptOptions(this);
         }
         virtual void visitOption(const OptionInfo &option)
@@ -109,10 +110,10 @@ class OptionCompletionWriter : public OptionsVisitor
     public:
         explicit OptionCompletionWriter(TextWriter *out) : out_(*out) {}
 
-        virtual void visitSubSection(const Options &section)
+        virtual void visitSection(const OptionSectionInfo &section)
         {
             OptionsIterator iterator(section);
-            iterator.acceptSubSections(this);
+            iterator.acceptSections(this);
             iterator.acceptOptions(this);
         }
         virtual void visitOption(const OptionInfo &option);
@@ -237,12 +238,12 @@ void ShellCompletionWriter::writeModuleCompletions(
     out.writeLine("COMPREPLY=()");
 
     OptionsListWriter listWriter;
-    listWriter.visitSubSection(options);
+    listWriter.visitSection(options.rootSection());
     out.writeLine(formatString("if (( $COMP_CWORD <= 1 )) || [[ $c == -* ]]; then COMPREPLY=( $(compgen -S ' '  -W $'%s' -- $c)); return 0; fi", listWriter.optionList().c_str()));
 
     out.writeLine("case \"$p\" in");
     OptionCompletionWriter optionWriter(&out);
-    optionWriter.visitSubSection(options);
+    optionWriter.visitSection(options.rootSection());
     out.writeLine("esac }");
 }
 
@@ -261,7 +262,7 @@ void ShellCompletionWriter::writeWrapperCompletions(
     impl_->file_->writeLine("if (( i == COMP_CWORD )); then");
     impl_->file_->writeLine("c=${COMP_WORDS[COMP_CWORD]}");
     OptionsListWriter lister;
-    lister.visitSubSection(options);
+    lister.visitSection(options.rootSection());
     std::string       completions(lister.optionList());
     for (ModuleNameList::const_iterator i = modules.begin();
          i != modules.end(); ++i)
index ae34edf40f6dcae859d0dabda4cce221c2498558..b55b840f034002c3527ceaf8d16072098d073bf1 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2012,2013,2014,2015, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016, 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.
@@ -101,7 +101,7 @@ TEST_F(CommandLineHelpWriterTest, HandlesOptionTypes)
 {
     using namespace gmx;
 
-    Options options("test", "Short Description");
+    Options options;
     options.addOption(BooleanOption("bool").description("Boolean option")
                           .defaultValue(true));
     options.addOption(BooleanOption("hidden").description("Hidden option")
@@ -166,7 +166,7 @@ TEST_F(CommandLineHelpWriterTest, HandlesDefaultValuesFromVariables)
 {
     using namespace gmx;
 
-    Options options("test", "Short Description");
+    Options options;
 
     bool    bValue = true;
     options.addOption(BooleanOption("bool").description("Boolean option")
@@ -204,7 +204,7 @@ TEST_F(CommandLineHelpWriterTest, HandlesLongFileOptions)
     using gmx::eftGenericData;
     using gmx::eftTrajectory;
 
-    gmx::Options options(NULL, NULL);
+    gmx::Options options;
     options.addOption(FileNameOption("f")
                           .description("File name option with a long value")
                           .filetype(eftTrajectory).inputFile().required()
@@ -240,7 +240,7 @@ TEST_F(CommandLineHelpWriterTest, HandlesLongOptions)
     using gmx::DoubleOption;
     using gmx::StringOption;
 
-    gmx::Options options(NULL, NULL);
+    gmx::Options options;
     options.addOption(BooleanOption("longboolean")
                           .description("Boolean option with a long name")
                           .defaultValue(true));
@@ -270,7 +270,7 @@ TEST_F(CommandLineHelpWriterTest, HandlesSelectionOptions)
     using gmx::SelectionFileOption;
     using gmx::SelectionOption;
 
-    gmx::Options                options(NULL, NULL);
+    gmx::Options                options;
     gmx::SelectionCollection    selections;
     gmx::SelectionOptionManager manager(&selections);
     options.addManager(&manager);
@@ -298,7 +298,7 @@ TEST_F(CommandLineHelpWriterTest, HandlesOptionGroups)
 {
     using gmx::IntegerOption;
 
-    gmx::Options            options(NULL, NULL);
+    gmx::Options            options;
     gmx::IOptionsContainer &group1 = options.addGroup();
     gmx::IOptionsContainer &group2 = options.addGroup();
     group2.addOption(IntegerOption("sub2").description("Option in group 2"));
@@ -321,7 +321,7 @@ TEST_F(CommandLineHelpWriterTest, HandlesHelpText)
     };
     using gmx::IntegerOption;
 
-    gmx::Options options(NULL, NULL);
+    gmx::Options options;
     options.addOption(IntegerOption("int").description("Integer option")
                           .defaultValue(2));
 
index 719e69d34f71917e67a1c1a2198387b44eee4e99..d9f973d0117eeace823313c28981a5d8f23a0a51 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2010,2011,2012,2013,2014, by the GROMACS development team, led by
+ * Copyright (c) 2010,2011,2012,2013,2014,2016, 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.
@@ -76,8 +76,7 @@ class CommandLineParserTest : public ::testing::Test
 };
 
 CommandLineParserTest::CommandLineParserTest()
-    : options_(NULL, NULL), parser_(&options_),
-      flag_(false), ivalue1p_(0), ivalue12_(0)
+    : parser_(&options_), flag_(false), ivalue1p_(0), ivalue12_(0)
 {
     using gmx::BooleanOption;
     using gmx::IntegerOption;
index 62d006445c347feef7dba88995e2ca6ceabe13e2..71c36c82f8c60efbe4c089f76bf6697630f4e50d 100644 (file)
@@ -1,7 +1,7 @@
 #
 # This file is part of the GROMACS molecular simulation package.
 #
-# Copyright (c) 2010,2012,2013,2014,2015, by the GROMACS development team, led by
+# Copyright (c) 2010,2012,2013,2014,2015,2016, 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.
@@ -42,9 +42,11 @@ gmx_install_headers(
     filenameoptionmanager.h
     ioptionsbehavior.h
     ioptionscontainer.h
+    ioptionscontainerwithsections.h
     optionfiletype.h
     optionflags.h
     options.h
+    optionsection.h
     timeunitmanager.h
     )
 
index ff8a2596865374f82d1ba577d3ca34e934f16c09..fc1723cea59d86f884d7ad0e317209ac5c117d1b 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2010,2011,2012,2013,2014,2015, by the GROMACS development team, led by
+ * Copyright (c) 2010,2011,2012,2013,2014,2015,2016, 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.
@@ -69,7 +69,7 @@ class OptionManagerContainer;
 
 namespace internal
 {
-class OptionsImpl;
+class OptionSectionImpl;
 }
 
 /*! \brief
@@ -198,7 +198,7 @@ class AbstractOption
          */
         friend class AbstractOptionStorage;
         //! Needed to be able to call createStorage().
-        friend class internal::OptionsImpl;
+        friend class internal::OptionSectionImpl;
 };
 
 /*! \brief
diff --git a/src/gromacs/options/ioptionscontainerwithsections.h b/src/gromacs/options/ioptionscontainerwithsections.h
new file mode 100644 (file)
index 0000000..93f7791
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * This file is part of the GROMACS molecular simulation package.
+ *
+ * Copyright (c) 2016, 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
+ * as published by the Free Software Foundation; either version 2.1
+ * of the License, or (at your option) any later version.
+ *
+ * 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.
+ *
+ * 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 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 research papers on the package. Check out http://www.gromacs.org.
+ */
+/*! \file
+ * \brief
+ * Declares gmx::IOptionsContainerWithSections.
+ *
+ * \author Teemu Murtola <teemu.murtola@gmail.com>
+ * \inpublicapi
+ * \ingroup module_options
+ */
+#ifndef GMX_OPTIONS_IOPTIONSCONTAINERWITHSECTIONS_H
+#define GMX_OPTIONS_IOPTIONSCONTAINERWITHSECTIONS_H
+
+#include "gromacs/options/ioptionscontainer.h"
+
+namespace gmx
+{
+
+class OptionSection;
+class OptionSectionInfo;
+
+/*! \brief
+ * Interface for adding input options with sections.
+ *
+ * This interface extends IOptionsContainer with an additional addSection()
+ * method that supports creating a hierarchy of sections for the options.
+ *
+ * Header optionsection.h provides OptionSection.
+ *
+ * \inpublicapi
+ * \ingroup module_options
+ */
+class IOptionsContainerWithSections : public IOptionsContainer
+{
+    public:
+        /*! \brief
+         * Adds a section to this collection.
+         *
+         * \param[in] section Section to add.
+         */
+        virtual IOptionsContainerWithSections &addSection(const OptionSection &section) = 0;
+
+    protected:
+        // Disallow deletion through the interface.
+        // (no need for the virtual, but some compilers warn otherwise)
+        virtual ~IOptionsContainerWithSections();
+};
+
+} // namespace
+
+#endif
index e17a77617a77ddc015e2d07e7d54a8e6ca8287c6..064cafc54ec1d1f6e145dc9d264dea0e9fe045cb 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2010,2011,2012,2013,2014,2015, by the GROMACS development team, led by
+ * Copyright (c) 2010,2011,2012,2013,2014,2015,2016, 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.
 #include <vector>
 
 #include "gromacs/options/abstractoption.h"
+#include "gromacs/options/abstractoptionstorage.h"
+#include "gromacs/options/ioptionscontainer.h"
+#include "gromacs/options/ioptionscontainerwithsections.h"
 #include "gromacs/options/optionmanagercontainer.h"
 #include "gromacs/options/options.h"
+#include "gromacs/options/optionsection.h"
 
 namespace gmx
 {
 
-class AbstractOptionStorage;
+class ExceptionInitializer;
 
 namespace internal
 {
 
 /*! \internal
  * \brief
- * Private implementation class for Options.
+ * Internal implementation class for storing an option section.
  *
- * Note that in addition to Options, the OptionsAssigner and OptionsIterator
- * classes also directly access this class.
+ * All options are stored within a section: the top-level contents of an
+ * Options object are handled within an unnamed, "root" section.
  *
  * \ingroup module_options
  */
-class OptionsImpl
+class OptionSectionImpl : public IOptionsContainerWithSections
 {
     public:
         /*! \internal \brief
@@ -86,35 +90,52 @@ class OptionsImpl
                 typedef std::list<Group> SubgroupList;
 
                 //! Creates a group within the given Options.
-                explicit Group(OptionsImpl *parent) : parent_(parent) {}
+                explicit Group(OptionSectionImpl *parent) : parent_(parent) {}
 
                 // From IOptionsContainer
                 virtual IOptionsContainer &addGroup();
                 virtual OptionInfo *addOption(const AbstractOption &settings);
 
                 //! Containing options object.
-                OptionsImpl  *parent_;
+                OptionSectionImpl  *parent_;
                 /*! \brief
                  * List of options, in insertion order.
                  *
                  * Pointers in this container point to the objects managed by
                  * Impl::optionsMap_.
                  */
-                OptionList    options_;
+                OptionList          options_;
                 //! List of groups, in insertion order.
-                SubgroupList  subgroups_;
+                SubgroupList        subgroups_;
         };
 
         //! Smart pointer for managing an AbstractOptionStorage object.
         typedef std::unique_ptr<AbstractOptionStorage>
             AbstractOptionStoragePointer;
-        //! Convenience type for list of sections.
-        typedef std::vector<Options *> SubSectionList;
         //! Convenience typedef for a map that contains all the options.
         typedef std::map<std::string, AbstractOptionStoragePointer> OptionMap;
+        //! Smart pointer for managing subsections.
+        typedef std::unique_ptr<OptionSectionImpl> SectionPointer;
+        //! Convenience typedef for a container for subsections.
+        typedef std::vector<SectionPointer> SectionList;
+
+        //! Creates storage for a new section.
+        OptionSectionImpl(const OptionManagerContainer &managers, const char *name)
+            : managers_(managers), info_(this), name_(name), rootGroup_(this)
+        {
+        }
+
+        // From IOptionsContainerWithSections
+        virtual IOptionsContainerWithSections &addSection(const OptionSection &section);
 
-        //! Sets the name and title.
-        OptionsImpl(const char *name, const char *title);
+        // From IOptionsContainer
+        virtual IOptionsContainer &addGroup();
+        virtual OptionInfo *addOption(const AbstractOption &settings);
+
+        //! Returns section info object for this section.
+        OptionSectionInfo       &info() { return info_; }
+        //! Returns section info object for this section.
+        const OptionSectionInfo &info() const { return info_; }
 
         /*! \brief
          * Finds a subsection by name.
@@ -124,7 +145,7 @@ class OptionsImpl
          *
          * Does not throw.
          */
-        Options *findSubSection(const char *name) const;
+        OptionSectionImpl *findSection(const char *name) const;
         /*! \brief
          * Finds an option by name.
          *
@@ -142,32 +163,50 @@ class OptionsImpl
          * Does not throw.
          */
         void startSource();
-
-        //! Name for the Options object.
-        std::string             name_;
         /*! \brief
-         * Option managers set for this collection.
-         *
-         * This is non-empty only for the top-level Options object.
+         * Calls AbstractOptionStorage::finish() for all options, including
+         * subsections.
          */
-        OptionManagerContainer  managers_;
+        void finish(ExceptionInitializer *errors);
+
+        //! Reference to the option managers in the parent Options object.
+        const OptionManagerContainer  &managers_;
+        //! Info object for this object.
+        OptionSectionInfo              info_;
+        //! Name of this section (empty and unused for the root section).
+        std::string                    name_;
         /*! \brief
          * Group that contains all options (and subgroups).
          *
          * This is used to store the insertion order of options.
          */
-        Group                   rootGroup_;
+        Group                          rootGroup_;
         //! Map from option names to options; owns the option storage objects.
-        OptionMap               optionMap_;
-        /*! \brief
-         * List of subsections, in insertion order.
-         *
-         * This container contains only references to external objects; memory
-         * management is performed elsewhere.
-         */
-        SubSectionList          subSections_;
-        //! Options object that contains this object as a subsection, or NULL.
-        Options                *parent_;
+        OptionMap                      optionMap_;
+        //! List of subsections, in insertion order.
+        SectionList                    subsections_;
+
+        GMX_DISALLOW_COPY_AND_ASSIGN(OptionSectionImpl);
+};
+
+/*! \internal
+ * \brief
+ * Private implementation class for Options.
+ *
+ * Note that in addition to Options, the OptionsAssigner class also directly
+ * accesses this class.
+ *
+ * \ingroup module_options
+ */
+class OptionsImpl
+{
+    public:
+        OptionsImpl();
+
+        //! Option managers set for this collection.
+        OptionManagerContainer  managers_;
+        //! Root section for this collection.
+        OptionSectionImpl       rootSection_;
 };
 
 } // namespace internal
index 2a6e5f2ba5e0bcacb7cb6e16cddd5adf4031821d..3240dce28ca2111c3301f405ff70444ac75fdbca 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2010,2011,2012,2014,2015, by the GROMACS development team, led by
+ * Copyright (c) 2010,2011,2012,2014,2015,2016, 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.
@@ -47,6 +47,7 @@
 
 #include "gromacs/options/abstractoption.h"
 #include "gromacs/options/abstractoptionstorage.h"
+#include "gromacs/options/optionsection.h"
 #include "gromacs/utility/arrayref.h"
 #include "gromacs/utility/exceptions.h"
 #include "gromacs/utility/gmxassert.h"
@@ -73,6 +74,14 @@ IOptionsContainer::~IOptionsContainer()
 {
 }
 
+/********************************************************************
+ * IOptionsContainerWithSections
+ */
+
+IOptionsContainerWithSections::~IOptionsContainerWithSections()
+{
+}
+
 /********************************************************************
  * OptionsImpl
  */
@@ -80,76 +89,118 @@ IOptionsContainer::~IOptionsContainer()
 namespace internal
 {
 
-OptionsImpl::OptionsImpl(const char *name, const char * /*title*/)
-    : name_(name != NULL ? name : ""), rootGroup_(this),
-      parent_(NULL)
+OptionsImpl::OptionsImpl()
+    : rootSection_(managers_, "")
+{
+}
+
+/********************************************************************
+ * OptionSectionImpl
+ */
+
+IOptionsContainerWithSections &OptionSectionImpl::addSection(const OptionSection &section)
+{
+    const char *name = section.name_;
+    // Make sure that there are no duplicate sections.
+    GMX_RELEASE_ASSERT(findSection(name) == NULL, "Duplicate subsection name");
+    subsections_.push_back(SectionPointer(new OptionSectionImpl(managers_, name)));
+    return *subsections_.back();
+}
+
+IOptionsContainer &OptionSectionImpl::addGroup()
 {
+    return rootGroup_.addGroup();
 }
 
-Options *OptionsImpl::findSubSection(const char *name) const
+OptionInfo *OptionSectionImpl::addOption(const AbstractOption &settings)
 {
-    SubSectionList::const_iterator i;
-    for (i = subSections_.begin(); i != subSections_.end(); ++i)
+    return rootGroup_.addOption(settings);
+}
+
+OptionSectionImpl *OptionSectionImpl::findSection(const char *name) const
+{
+    for (const auto &section : subsections_)
     {
-        if ((*i)->name() == name)
+        if (section->name_ == name)
         {
-            return *i;
+            return section.get();
         }
     }
-    return NULL;
+    return nullptr;
 }
 
-AbstractOptionStorage *OptionsImpl::findOption(const char *name) const
+AbstractOptionStorage *OptionSectionImpl::findOption(const char *name) const
 {
     OptionMap::const_iterator i = optionMap_.find(name);
     if (i == optionMap_.end())
     {
-        return NULL;
+        return nullptr;
     }
     return i->second.get();
 }
 
-void OptionsImpl::startSource()
+void OptionSectionImpl::startSource()
 {
-    OptionMap::const_iterator i;
-    for (i = optionMap_.begin(); i != optionMap_.end(); ++i)
+    for (const auto &entry : optionMap_)
     {
-        AbstractOptionStorage &option = *i->second;
-        option.startSource();
+        entry.second->startSource();
     }
-    SubSectionList::const_iterator j;
-    for (j = subSections_.begin(); j != subSections_.end(); ++j)
+    for (const auto &section : subsections_)
     {
-        Options &section = **j;
-        section.impl_->startSource();
+        section->startSource();
+    }
+}
+
+void OptionSectionImpl::finish(ExceptionInitializer *errors)
+{
+    for (const auto &entry : optionMap_)
+    {
+        AbstractOptionStorage &option = *entry.second;
+        try
+        {
+            option.finish();
+        }
+        catch (UserInputError &ex)
+        {
+            ex.prependContext("In option " + option.name());
+            errors->addCurrentExceptionAsNested();
+        }
+    }
+    for (const auto &section : subsections_)
+    {
+        try
+        {
+            section->finish(errors);
+        }
+        catch (const UserInputError &)
+        {
+            errors->addCurrentExceptionAsNested();
+        }
     }
 }
 
 /********************************************************************
- * OptionsImpl::Group
+ * OptionSectionImpl::Group
  */
 
-IOptionsContainer &OptionsImpl::Group::addGroup()
+IOptionsContainer &OptionSectionImpl::Group::addGroup()
 {
     subgroups_.push_back(Group(parent_));
     return subgroups_.back();
 }
 
-OptionInfo *OptionsImpl::Group::addOption(const AbstractOption &settings)
+OptionInfo *OptionSectionImpl::Group::addOption(const AbstractOption &settings)
 {
-    OptionsImpl *root = parent_;
-    while (root->parent_ != NULL)
-    {
-        root = root->parent_->impl_.get();
-    }
-    AbstractOptionStoragePointer         option(settings.createStorage(root->managers_));
+    OptionSectionImpl::AbstractOptionStoragePointer
+         option(settings.createStorage(parent_->managers_));
     options_.reserve(options_.size() + 1);
-    std::pair<OptionMap::iterator, bool> insertionResult =
+    auto insertionResult =
         parent_->optionMap_.insert(std::make_pair(option->name(),
                                                   std::move(option)));
     if (!insertionResult.second)
     {
-        GMX_THROW(APIError("Duplicate option: " + option->name()));
+        const std::string &name = insertionResult.first->second->name();
+        GMX_THROW(APIError("Duplicate option: " + name));
     }
     AbstractOptionStorage &insertedOption = *insertionResult.first->second;
     options_.push_back(&insertedOption);
@@ -164,8 +215,8 @@ using internal::OptionsImpl;
  * Options
  */
 
-Options::Options(const char *name, const char *title)
-    : impl_(new OptionsImpl(name, title))
+Options::Options()
+    : impl_(new OptionsImpl)
 {
 }
 
@@ -173,85 +224,49 @@ Options::~Options()
 {
 }
 
-const std::string &Options::name() const
-{
-    return impl_->name_;
-}
-
 
 void Options::addManager(IOptionManager *manager)
 {
-    GMX_RELEASE_ASSERT(impl_->parent_ == NULL,
-                       "Can only add a manager in a top-level Options object");
     // This ensures that all options see the same set of managers.
-    GMX_RELEASE_ASSERT(impl_->optionMap_.empty(),
+    GMX_RELEASE_ASSERT(impl_->rootSection_.optionMap_.empty(),
                        "Can only add a manager before options");
     // This check could be relaxed if we instead checked that the subsections
     // do not have options.
-    GMX_RELEASE_ASSERT(impl_->subSections_.empty(),
+    GMX_RELEASE_ASSERT(impl_->rootSection_.subsections_.empty(),
                        "Can only add a manager before subsections");
     impl_->managers_.add(manager);
 }
 
-void Options::addSubSection(Options *section)
+IOptionsContainerWithSections &Options::addSection(const OptionSection &section)
 {
-    // This is required, because managers are used from the root Options
-    // object, so they are only seen after the subsection has been added.
-    GMX_RELEASE_ASSERT(section->impl_->optionMap_.empty(),
-                       "Can only add a subsection before it has any options");
-    GMX_RELEASE_ASSERT(section->impl_->managers_.empty(),
-                       "Can only have managers in a top-level Options object");
-    // Make sure that section is not already inserted somewhere.
-    GMX_RELEASE_ASSERT(section->impl_->parent_ == NULL,
-                       "Cannot add as subsection twice");
-    // Make sure that there are no duplicate sections.
-    GMX_RELEASE_ASSERT(impl_->findSubSection(section->name().c_str()) == NULL,
-                       "Duplicate subsection name");
-    impl_->subSections_.push_back(section);
-    section->impl_->parent_ = this;
+    return impl_->rootSection_.addSection(section);
 }
 
 IOptionsContainer &Options::addGroup()
 {
-    return impl_->rootGroup_.addGroup();
+    return impl_->rootSection_.addGroup();
 }
 
 OptionInfo *Options::addOption(const AbstractOption &settings)
 {
-    return impl_->rootGroup_.addOption(settings);
+    return impl_->rootSection_.addOption(settings);
+}
+
+OptionSectionInfo &Options::rootSection()
+{
+    return impl_->rootSection_.info();
+}
+
+const OptionSectionInfo &Options::rootSection() const
+{
+    return impl_->rootSection_.info();
 }
 
 void Options::finish()
 {
     // TODO: Consider how to customize these error messages based on context.
-    ExceptionInitializer                    errors("Invalid input values");
-    OptionsImpl::OptionMap::const_iterator  i;
-    for (i = impl_->optionMap_.begin(); i != impl_->optionMap_.end(); ++i)
-    {
-        AbstractOptionStorage &option = *i->second;
-        try
-        {
-            option.finish();
-        }
-        catch (UserInputError &ex)
-        {
-            ex.prependContext("In option " + option.name());
-            errors.addCurrentExceptionAsNested();
-        }
-    }
-    OptionsImpl::SubSectionList::const_iterator j;
-    for (j = impl_->subSections_.begin(); j != impl_->subSections_.end(); ++j)
-    {
-        Options &section = **j;
-        try
-        {
-            section.finish();
-        }
-        catch (const UserInputError &)
-        {
-            errors.addCurrentExceptionAsNested();
-        }
-    }
+    ExceptionInitializer  errors("Invalid input values");
+    impl_->rootSection_.finish(&errors);
     if (errors.hasNestedExceptions())
     {
         // TODO: This exception type may not always be appropriate.
index 944606db1ba7ab1bfd451b0b1d5c511ed5b8c307..40944859fce593c955a12af3b59a97c28b438bb5 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2010,2011,2012,2014,2015, by the GROMACS development team, led by
+ * Copyright (c) 2010,2011,2012,2014,2015,2016, 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.
 
 #include <string>
 
-#include "gromacs/options/ioptionscontainer.h"
+#include "gromacs/options/ioptionscontainerwithsections.h"
 #include "gromacs/utility/classhelpers.h"
 
 namespace gmx
 {
 
 class AbstractOption;
+class OptionSection;
+class OptionSectionInfo;
 class OptionsAssigner;
-class OptionsIterator;
 
 namespace internal
 {
@@ -88,7 +89,7 @@ class IOptionManager
  * Collection of options.
  *
  * See \ref module_options for an overview of how the options work.
- * The IOptionsContainer interface documents how to add options.
+ * The IOptionsContainerWithSections interface documents how to add options.
  *
  * In order to keep the public interface of this class simple, functionality
  * to assign values to options is provided by a separate OptionsAssigner class.
@@ -98,23 +99,13 @@ class IOptionManager
  * \inpublicapi
  * \ingroup module_options
  */
-class Options : public IOptionsContainer
+class Options : public IOptionsContainerWithSections
 {
     public:
-        /*! \brief
-         * Initializes the name and title of an option collection.
-         *
-         * \param[in] name  Single-word name.
-         * \param[in] title Descriptive title.
-         *
-         * Copies the input strings.
-         */
-        Options(const char *name, const char *title);
+        //! Initializes an empty options root container.
+        Options();
         ~Options();
 
-        //! Returns the short name of the option collection.
-        const std::string &name() const;
-
         /*! \brief
          * Adds an option manager.
          *
@@ -133,36 +124,23 @@ class Options : public IOptionsContainer
          * The Options object (and its contained options) only stores a
          * reference to the object.
          *
-         * This method cannot be called after adding options or subsections.
+         * This method cannot be called after adding options or sections.
          */
         void addManager(IOptionManager *manager);
 
-        /*! \brief
-         * Adds an option collection as a subsection of this collection.
-         *
-         * \param[in] section Subsection to add.
-         *
-         * The name() field of \p section is used as the name of the
-         * subsection.  If an attempt is made to add two different subsections
-         * with the same name, this function asserts.
-         *
-         * \p section should not have any options added at the point this
-         * method is called.
-         *
-         * Only a pointer to the provided object is stored.  The caller is
-         * responsible that the object exists for the lifetime of the
-         * collection.
-         * It is not possible to add the same Options object as a subsection to
-         * several different Options.
-         * If an attempt is made, the function asserts.
-         */
-        void addSubSection(Options *section);
+        // From IOptionsContainerWithSections
+        virtual IOptionsContainerWithSections &addSection(const OptionSection &section);
 
         // From IOptionsContainer
         virtual IOptionsContainer &addGroup();
         virtual OptionInfo *addOption(const AbstractOption &settings);
         using IOptionsContainer::addOption;
 
+        //! Returns a handle to the root section.
+        OptionSectionInfo       &rootSection();
+        //! Returns a handle to the root section.
+        const OptionSectionInfo &rootSection() const;
+
         /*! \brief
          * Notifies the collection that all option values are assigned.
          *
@@ -182,14 +160,8 @@ class Options : public IOptionsContainer
     private:
         PrivateImplPointer<internal::OptionsImpl> impl_;
 
-        //! Needed for the implementation to access subsections.
-        friend class internal::OptionsImpl;
         //! Needed to be able to extend the interface of this object.
         friend class OptionsAssigner;
-        //! Needed to be able to extend the interface of this object.
-        friend class OptionsIterator;
-        //! Needed to be able to extend the interface of this object.
-        friend class OptionsModifyingIterator;
 };
 
 } // namespace gmx
index 2842655c54f438b38559d32d2989383ec69d1b39..3d6ea85c79d37ba2adee2ab13709f516b74bb5d0 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2010,2011,2012,2013,2014,2015, by the GROMACS development team, led by
+ * Copyright (c) 2010,2011,2012,2013,2014,2015,2016, 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.
@@ -67,13 +67,16 @@ namespace gmx
 class OptionsAssigner::Impl
 {
     public:
+        //! Shorthand for the internal type used to represent a section.
+        typedef internal::OptionSectionImpl Section;
+
         //! Sets the option object to assign to.
         explicit Impl(Options *options);
 
         //! Returns true if a subsection has been set.
-        bool inSubSection() const { return sectionStack_.size() > 1; }
+        bool inSection() const { return sectionStack_.size() > 1; }
         //! Returns the Options object for the current section.
-        Options &currentSection() const { return *sectionStack_.back(); }
+        Section &currentSection() const { return *sectionStack_.back(); }
         /*! \brief
          * Finds an option by the given name.
          *
@@ -95,7 +98,7 @@ class OptionsAssigner::Impl
          *
          * The first element always points to \a options_.
          */
-        std::vector<Options *>  sectionStack_;
+        std::vector<Section *>  sectionStack_;
         //! Current option being assigned to, or NULL if none.
         AbstractOptionStorage  *currentOption_;
         /*! \brief
@@ -113,7 +116,7 @@ OptionsAssigner::Impl::Impl(Options *options)
     : options_(*options), bAcceptBooleanNoPrefix_(false),
       currentOption_(NULL), currentValueCount_(0), reverseBoolean_(false)
 {
-    sectionStack_.push_back(&options_);
+    sectionStack_.push_back(&options_.impl_->rootSection_);
 }
 
 AbstractOptionStorage *
@@ -121,13 +124,13 @@ OptionsAssigner::Impl::findOption(const char *name)
 {
     GMX_RELEASE_ASSERT(currentOption_ == NULL,
                        "Cannot search for another option while processing one");
-    const Options         &section = currentSection();
-    AbstractOptionStorage *option  = section.impl_->findOption(name);
+    const Section         &section = currentSection();
+    AbstractOptionStorage *option  = section.findOption(name);
     if (option == NULL && bAcceptBooleanNoPrefix_)
     {
         if (name[0] == 'n' && name[1] == 'o')
         {
-            option = section.impl_->findOption(name + 2);
+            option = section.findOption(name + 2);
             if (option != NULL && option->isBoolean())
             {
                 reverseBoolean_ = true;
@@ -161,12 +164,12 @@ void OptionsAssigner::setAcceptBooleanNoPrefix(bool bEnabled)
 
 void OptionsAssigner::start()
 {
-    impl_->options_.impl_->startSource();
+    impl_->options_.impl_->rootSection_.startSource();
 }
 
-void OptionsAssigner::startSubSection(const char *name)
+void OptionsAssigner::startSection(const char *name)
 {
-    Options *section = impl_->currentSection().impl_->findSubSection(name);
+    Impl::Section *section = impl_->currentSection().findSection(name);
     if (section == NULL)
     {
         GMX_THROW(InvalidInputError("Unknown subsection"));
@@ -231,17 +234,17 @@ void OptionsAssigner::finishOption()
     }
 }
 
-void OptionsAssigner::finishSubSection()
+void OptionsAssigner::finishSection()
 {
     // Should only be called if we are in a subsection.
-    GMX_RELEASE_ASSERT(impl_->inSubSection(), "startSubSection() not called");
+    GMX_RELEASE_ASSERT(impl_->inSection(), "startSection() not called");
     impl_->sectionStack_.pop_back();
 }
 
 void OptionsAssigner::finish()
 {
     GMX_RELEASE_ASSERT(impl_->currentOption_ == NULL, "finishOption() not called");
-    GMX_RELEASE_ASSERT(!impl_->inSubSection(), "finishSubSection() not called");
+    GMX_RELEASE_ASSERT(!impl_->inSection(), "finishSection() not called");
 }
 
 } // namespace gmx
index 35bb70dce9225e3e5b71146ef832a3df43086011..d965f85d3c64ee886fe3ec2e3fd20273051d8597 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2010,2011,2012,2013,2014,2015, by the GROMACS development team, led by
+ * Copyright (c) 2010,2011,2012,2013,2014,2015,2016, 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.
@@ -70,11 +70,11 @@ class Options;
    assigner.startOption("opt1");
    assigner.appendValue("3");
    assigner.finishOption();
-   assigner.startSubSection("section");
+   assigner.startSection("section");
    assigner.startOption("opt2"); // Now in the subsection
    assigner.appendValue("yes");
    assigner.finishOption();
-   assigner.finishSubSection()
+   assigner.finishSection()
    assigner.startOption("opt3"); // Again in the main options
    assigner.appendValue("2");
    assigner.finishOption();
@@ -124,7 +124,7 @@ class OptionsAssigner
          *
          * Strong exception safety guarantee.
          */
-        void startSubSection(const char *name);
+        void startSection(const char *name);
         /*! \brief
          * Starts assigning values for an option.
          *
@@ -186,7 +186,7 @@ class OptionsAssigner
          *
          * Does not throw.
          */
-        void finishSubSection();
+        void finishSection();
         /*! \brief
          * Finish assigning options through the object.
          *
diff --git a/src/gromacs/options/optionsection.h b/src/gromacs/options/optionsection.h
new file mode 100644 (file)
index 0000000..6f708ec
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * This file is part of the GROMACS molecular simulation package.
+ *
+ * Copyright (c) 2016, 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
+ * as published by the Free Software Foundation; either version 2.1
+ * of the License, or (at your option) any later version.
+ *
+ * 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.
+ *
+ * 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 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 research papers on the package. Check out http://www.gromacs.org.
+ */
+/*! \file
+ * \brief
+ * Declares gmx::OptionSection and gmx::OptionSectionInfo.
+ *
+ * \author Teemu Murtola <teemu.murtola@gmail.com>
+ * \inpublicapi
+ * \ingroup module_options
+ */
+#ifndef GMX_OPTIONS_OPTIONSECTION_H
+#define GMX_OPTIONS_OPTIONSECTION_H
+
+#include "gromacs/utility/classhelpers.h"
+
+namespace gmx
+{
+
+namespace internal
+{
+class OptionSectionImpl;
+}
+
+class OptionSection
+{
+    public:
+        explicit OptionSection(const char *name) : name_(name) {}
+
+    private:
+        const char *name_;
+
+        friend class internal::OptionSectionImpl;
+};
+
+class OptionSectionInfo
+{
+    public:
+        //! Wraps a given section storage object.
+        explicit OptionSectionInfo(internal::OptionSectionImpl *section)
+            : section_(*section)
+        {
+        }
+
+        //! Returns the wrapped section storage object.
+        internal::OptionSectionImpl       &section() { return section_; }
+        //! Returns the wrapped section storage object.
+        const internal::OptionSectionImpl &section() const { return section_; }
+
+    private:
+        internal::OptionSectionImpl &section_;
+
+        GMX_DISALLOW_COPY_AND_ASSIGN(OptionSectionInfo);
+};
+
+} // namespace gmx
+
+#endif
index c9584dee9eceb29528793f81022848cd94cd2e2c..07397c888638019dde71300a9ae36326c9706dbb 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2010,2012,2014,2015, by the GROMACS development team, led by
+ * Copyright (c) 2010,2012,2014,2015,2016, 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.
@@ -45,6 +45,7 @@
 
 #include "gromacs/options/abstractoptionstorage.h"
 #include "gromacs/options/options.h"
+#include "gromacs/options/optionsection.h"
 
 #include "options-impl.h"
 
@@ -69,17 +70,15 @@ void visitOption(OptionsModifyingVisitor *visitor, OptionInfo &optionInfo)
 
 //! Helper function to recursively visit all options in a group.
 template <class VisitorType>
-void acceptOptionsGroup(const OptionsImpl::Group &group, VisitorType *visitor)
+void acceptOptionsGroup(const internal::OptionSectionImpl::Group &group, VisitorType *visitor)
 {
-    OptionsImpl::Group::OptionList::const_iterator option;
-    for (option = group.options_.begin(); option != group.options_.end(); ++option)
+    for (const auto &option : group.options_)
     {
-        visitOption(visitor, (*option)->optionInfo());
+        visitOption(visitor, option->optionInfo());
     }
-    OptionsImpl::Group::SubgroupList::const_iterator subgroup;
-    for (subgroup = group.subgroups_.begin(); subgroup != group.subgroups_.end(); ++subgroup)
+    for (const auto &subgroup : group.subgroups_)
     {
-        acceptOptionsGroup(*subgroup, visitor);
+        acceptOptionsGroup(subgroup, visitor);
     }
 }
 
@@ -90,24 +89,26 @@ void acceptOptionsGroup(const OptionsImpl::Group &group, VisitorType *visitor)
  */
 
 OptionsIterator::OptionsIterator(const Options &options)
-    : options_(options)
+    : section_(options.rootSection().section())
 {
 }
 
-void OptionsIterator::acceptSubSections(OptionsVisitor *visitor) const
+OptionsIterator::OptionsIterator(const OptionSectionInfo &section)
+    : section_(section.section())
 {
-    const OptionsImpl::SubSectionList          &subSectionList =
-        options_.impl_->subSections_;
-    OptionsImpl::SubSectionList::const_iterator i;
-    for (i = subSectionList.begin(); i != subSectionList.end(); ++i)
+}
+
+void OptionsIterator::acceptSections(OptionsVisitor *visitor) const
+{
+    for (const auto &section : section_.subsections_)
     {
-        visitor->visitSubSection(*(*i));
+        visitor->visitSection(section->info());
     }
 }
 
 void OptionsIterator::acceptOptions(OptionsVisitor *visitor) const
 {
-    acceptOptionsGroup(options_.impl_->rootGroup_, visitor);
+    acceptOptionsGroup(section_.rootGroup_, visitor);
 }
 
 /********************************************************************
@@ -115,24 +116,26 @@ void OptionsIterator::acceptOptions(OptionsVisitor *visitor) const
  */
 
 OptionsModifyingIterator::OptionsModifyingIterator(Options *options)
-    : options_(*options)
+    : section_(options->rootSection().section())
+{
+}
+
+OptionsModifyingIterator::OptionsModifyingIterator(OptionSectionInfo *section)
+    : section_(section->section())
 {
 }
 
-void OptionsModifyingIterator::acceptSubSections(OptionsModifyingVisitor *visitor) const
+void OptionsModifyingIterator::acceptSections(OptionsModifyingVisitor *visitor) const
 {
-    const OptionsImpl::SubSectionList          &subSectionList =
-        options_.impl_->subSections_;
-    OptionsImpl::SubSectionList::const_iterator i;
-    for (i = subSectionList.begin(); i != subSectionList.end(); ++i)
+    for (auto &section : section_.subsections_)
     {
-        visitor->visitSubSection(*i);
+        visitor->visitSection(&section->info());
     }
 }
 
 void OptionsModifyingIterator::acceptOptions(OptionsModifyingVisitor *visitor) const
 {
-    acceptOptionsGroup(options_.impl_->rootGroup_, visitor);
+    acceptOptionsGroup(section_.rootGroup_, visitor);
 }
 
 } // namespace gmx
index 44e265a2f78dd4e3ffd1127d5306085a248e9fdf..6502f836b7524d7e1b49a90dac12cad34ee6d1a4 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2010,2011,2012,2014, by the GROMACS development team, led by
+ * Copyright (c) 2010,2011,2012,2014,2016, 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.
@@ -54,6 +54,12 @@ namespace gmx
 {
 
 class Options;
+class OptionSectionInfo;
+
+namespace internal
+{
+class OptionSectionImpl;
+}
 
 /*! \libinternal \brief
  * Pure interface for visiting options in a Options object.
@@ -68,13 +74,9 @@ class OptionsVisitor
     public:
         virtual ~OptionsVisitor() {}
 
-        /*! \brief
-         * Called for each subsection in Options.
-         */
-        virtual void visitSubSection(const Options &section) = 0;
-        /*! \brief
-         * Called for each option in Options.
-         */
+        //! Called for each section.
+        virtual void visitSection(const OptionSectionInfo &section) = 0;
+        //! Called for each option.
         virtual void visitOption(const OptionInfo &option) = 0;
 };
 
@@ -93,7 +95,7 @@ class OptionsTypeVisitor : public OptionsVisitor
     public:
         virtual ~OptionsTypeVisitor() {}
 
-        virtual void visitSubSection(const Options &section) = 0;
+        virtual void visitSection(const OptionSectionInfo &section) = 0;
         /*! \brief
          * Called for each option of type \p InfoType.
          */
@@ -113,7 +115,7 @@ class OptionsTypeVisitor : public OptionsVisitor
 /*! \libinternal \brief
  * Decorator class for visiting options in a Options object.
  *
- * This class provides an interface for looping through subsections and
+ * This class provides an interface for looping through sections and
  * options in a Options object.
  *
  * Typical use (loop over all options, iteratively descending into
@@ -122,10 +124,10 @@ class OptionsTypeVisitor : public OptionsVisitor
    class Visitor : public gmx::OptionsVisitor
    {
        public:
-           void visitSubSection(const Options &section)
+           void visitSection(const Options &section)
            {
                OptionsIterator iterator(section);
-               iterator.acceptSubSections(this);
+               iterator.acceptSections(this);
                iterator.acceptOptions(this);
            }
 
@@ -135,7 +137,7 @@ class OptionsTypeVisitor : public OptionsVisitor
            }
    }
 
-   Visitor().visitSubSection(options);
+   Visitor().visitSection(options);
  * \endcode
  *
  * \inlibraryapi
@@ -146,21 +148,22 @@ class OptionsIterator
     public:
         /*! \brief
          * Creates an object for visiting options in a Options object.
+         *
+         * The created iterator iterates over the "root" section in the Options
+         * object.
          */
         explicit OptionsIterator(const Options &options);
+        //! Creates an object for visiting options in an options section.
+        explicit OptionsIterator(const OptionSectionInfo &section);
 
-        /*! \brief
-         * Visits each subsection in the wrapped Options object.
-         */
-        void acceptSubSections(OptionsVisitor *visitor) const;
-        /*! \brief
-         * Visits each option in the wrapped Options object.
-         */
+        //! Visits each section in the wrapped section.
+        void acceptSections(OptionsVisitor *visitor) const;
+        //! Visits each option in the wrapped section.
         void acceptOptions(OptionsVisitor *visitor) const;
 
     private:
-        //! The wrapped Options object.
-        const Options          &options_;
+        //! The wrapped section object.
+        const internal::OptionSectionImpl &section_;
 
         GMX_DISALLOW_COPY_AND_ASSIGN(OptionsIterator);
 };
@@ -179,13 +182,9 @@ class OptionsModifyingVisitor
     public:
         virtual ~OptionsModifyingVisitor() {}
 
-        /*! \brief
-         * Called for each subsection in Options.
-         */
-        virtual void visitSubSection(Options *section) = 0;
-        /*! \brief
-         * Called for each option in Options.
-         */
+        //! Called for each section.
+        virtual void visitSection(OptionSectionInfo *section) = 0;
+        //! Called for each option.
         virtual void visitOption(OptionInfo *option) = 0;
 };
 
@@ -205,7 +204,7 @@ class OptionsModifyingTypeVisitor : public OptionsModifyingVisitor
     public:
         virtual ~OptionsModifyingTypeVisitor() {}
 
-        virtual void visitSubSection(Options *section) = 0;
+        virtual void visitSection(OptionSectionInfo *section) = 0;
         /*! \brief
          * Called for each option of type \p InfoType.
          */
@@ -238,21 +237,22 @@ class OptionsModifyingIterator
     public:
         /*! \brief
          * Creates an object for visiting options in a Options object.
+         *
+         * The created iterator iterates over the "root" section in the Options
+         * object.
          */
         explicit OptionsModifyingIterator(Options *options);
+        //! Creates an object for visiting options in an options section.
+        explicit OptionsModifyingIterator(OptionSectionInfo *section);
 
-        /*! \brief
-         * Visits each subsection in the wrapped Options object.
-         */
-        void acceptSubSections(OptionsModifyingVisitor *visitor) const;
-        /*! \brief
-         * Visits each option in the wrapped Options object.
-         */
+        //! Visits each section in the wrapped section.
+        void acceptSections(OptionsModifyingVisitor *visitor) const;
+        //! Visits each option in the wrapped section.
         void acceptOptions(OptionsModifyingVisitor *visitor) const;
 
     private:
-        //! The wrapped Options object.
-        Options                &options_;
+        //! The wrapped section object.
+        internal::OptionSectionImpl &section_;
 
         GMX_DISALLOW_COPY_AND_ASSIGN(OptionsModifyingIterator);
 };
index 1682129575a0eec6f53c8cd1fd2ef746797d64d5..7b22c94463b02ad57ce9851423aa9f71ff72c61b 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2010,2011,2012,2013,2014, by the GROMACS development team, led by
+ * Copyright (c) 2010,2011,2012,2013,2014,2016, 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.
@@ -186,7 +186,7 @@ MockOptionStorage &MockOptionInfo::option()
  */
 TEST(AbstractOptionStorageTest, HandlesSetInFinish)
 {
-    gmx::Options                options(NULL, NULL);
+    gmx::Options                options;
     std::vector<std::string>    values;
     MockOptionInfo             *info = options.addOption(
                 MockOption("name").required().storeVector(&values));
@@ -216,7 +216,7 @@ TEST(AbstractOptionStorageTest, HandlesSetInFinish)
  */
 TEST(AbstractOptionStorageTest, HandlesValueRemoval)
 {
-    gmx::Options                options(NULL, NULL);
+    gmx::Options                options;
     std::vector<std::string>    values;
     MockOptionInfo             *info = options.addOption(
                 MockOption("name").storeVector(&values).multiValue());
@@ -255,7 +255,7 @@ TEST(AbstractOptionStorageTest, HandlesValueRemoval)
  */
 TEST(AbstractOptionStorageTest, HandlesValueAddition)
 {
-    gmx::Options                options(NULL, NULL);
+    gmx::Options                options;
     std::vector<std::string>    values;
     MockOptionInfo             *info = options.addOption(
                 MockOption("name").storeVector(&values).multiValue());
@@ -295,7 +295,7 @@ TEST(AbstractOptionStorageTest, HandlesValueAddition)
  */
 TEST(AbstractOptionStorageTest, HandlesTooManyValueAddition)
 {
-    gmx::Options                options(NULL, NULL);
+    gmx::Options                options;
     std::vector<std::string>    values;
     MockOptionInfo             *info = options.addOption(
                 MockOption("name").storeVector(&values).valueCount(2));
@@ -331,7 +331,7 @@ TEST(AbstractOptionStorageTest, HandlesTooManyValueAddition)
  */
 TEST(AbstractOptionStorageTest, AllowsEmptyValues)
 {
-    gmx::Options                options(NULL, NULL);
+    gmx::Options                options;
     std::vector<std::string>    values;
     MockOptionInfo             *info = options.addOption(
                 MockOption("name").storeVector(&values).valueCount(0));
index 5ae358f3cbb3044d3d1a702599ffa5bb3ab3a37b..2d3cde55f528c945ba9e2f3041192148e04eaa13 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2012,2013,2014,2015, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016, 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.
@@ -59,7 +59,7 @@ using gmx::FileNameOption;
 
 TEST(FileNameOptionTest, HandlesRequiredDefaultValueWithoutExtension)
 {
-    gmx::Options           options(NULL, NULL);
+    gmx::Options           options;
     std::string            value;
     ASSERT_NO_THROW_GMX(options.addOption(
                                 FileNameOption("f").store(&value).required()
@@ -77,7 +77,7 @@ TEST(FileNameOptionTest, HandlesRequiredDefaultValueWithoutExtension)
 
 TEST(FileNameOptionTest, HandlesRequiredOptionWithoutValue)
 {
-    gmx::Options           options(NULL, NULL);
+    gmx::Options           options;
     std::string            value;
     ASSERT_NO_THROW_GMX(options.addOption(
                                 FileNameOption("f").store(&value).required()
@@ -97,7 +97,7 @@ TEST(FileNameOptionTest, HandlesRequiredOptionWithoutValue)
 
 TEST(FileNameOptionTest, HandlesOptionalUnsetOption)
 {
-    gmx::Options           options(NULL, NULL);
+    gmx::Options           options;
     std::string            value;
     ASSERT_NO_THROW_GMX(options.addOption(
                                 FileNameOption("f").store(&value)
@@ -115,7 +115,7 @@ TEST(FileNameOptionTest, HandlesOptionalUnsetOption)
 
 TEST(FileNameOptionTest, HandlesOptionalDefaultValueWithoutExtension)
 {
-    gmx::Options           options(NULL, NULL);
+    gmx::Options           options;
     std::string            value;
     ASSERT_NO_THROW_GMX(options.addOption(
                                 FileNameOption("f").store(&value)
@@ -135,7 +135,7 @@ TEST(FileNameOptionTest, HandlesOptionalDefaultValueWithoutExtension)
 
 TEST(FileNameOptionTest, HandlesRequiredCustomDefaultExtension)
 {
-    gmx::Options           options(NULL, NULL);
+    gmx::Options           options;
     std::string            value;
     ASSERT_NO_THROW_GMX(options.addOption(
                                 FileNameOption("f").store(&value).required()
@@ -154,7 +154,7 @@ TEST(FileNameOptionTest, HandlesRequiredCustomDefaultExtension)
 
 TEST(FileNameOptionTest, HandlesOptionalCustomDefaultExtension)
 {
-    gmx::Options           options(NULL, NULL);
+    gmx::Options           options;
     std::string            value;
     ASSERT_NO_THROW_GMX(options.addOption(
                                 FileNameOption("f").store(&value)
@@ -175,7 +175,7 @@ TEST(FileNameOptionTest, HandlesOptionalCustomDefaultExtension)
 
 TEST(FileNameOptionTest, GivesErrorOnUnknownFileSuffix)
 {
-    gmx::Options           options(NULL, NULL);
+    gmx::Options           options;
     std::string            value;
     ASSERT_NO_THROW_GMX(options.addOption(
                                 FileNameOption("f").store(&value)
@@ -195,7 +195,7 @@ TEST(FileNameOptionTest, GivesErrorOnUnknownFileSuffix)
 
 TEST(FileNameOptionTest, GivesErrorOnInvalidFileSuffix)
 {
-    gmx::Options           options(NULL, NULL);
+    gmx::Options           options;
     std::string            value;
     ASSERT_NO_THROW_GMX(options.addOption(
                                 FileNameOption("f").store(&value)
index 6992689febcd245d5730cb8b3ad2e0cc31e6fa15..9a67461c05ebf87065b4c9fbd8bec1fe28ac50b4 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2014,2015, by the GROMACS development team, led by
+ * Copyright (c) 2014,2015,2016, 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.
@@ -63,7 +63,6 @@ class FileNameOptionManagerTest : public ::testing::Test
 {
     public:
         FileNameOptionManagerTest()
-            : options_(NULL, NULL)
         {
             manager_.setInputRedirector(&redirector_);
             options_.addManager(&manager_);
index 5d6cf976b66e85be1c1eb2cbc8969b402a1b4a76..c9d85b2b9bb223d5c7a9c60117e5c0119559bfa4 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2010,2011,2012,2013,2014,2015, by the GROMACS development team, led by
+ * Copyright (c) 2010,2011,2012,2013,2014,2015,2016, 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.
@@ -60,7 +60,7 @@ namespace
 
 TEST(OptionsTest, FailsOnNonsafeStorage)
 {
-    gmx::Options options(NULL, NULL);
+    gmx::Options options;
     int          value = -1;
     using gmx::IntegerOption;
     ASSERT_THROW_GMX(options.addOption(IntegerOption("name").store(&value)
index b9dd8eb5f8f77a7581388e1ad97bb74d29fd0c33..a12201f92d3b993c3fbf375d6a718840fff023f2 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2010,2011,2012,2013,2014,2015, by the GROMACS development team, led by
+ * Copyright (c) 2010,2011,2012,2013,2014,2015,2016, 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.
@@ -56,6 +56,7 @@
 
 #include "gromacs/options/basicoptions.h"
 #include "gromacs/options/options.h"
+#include "gromacs/options/optionsection.h"
 #include "gromacs/utility/exceptions.h"
 #include "gromacs/utility/stringutil.h"
 
@@ -70,7 +71,7 @@ namespace
 
 TEST(OptionsAssignerTest, HandlesMissingRequiredParameter)
 {
-    gmx::Options options(NULL, NULL);
+    gmx::Options options;
     int          value = 0;
     using gmx::IntegerOption;
     ASSERT_NO_THROW(options.addOption(
@@ -81,7 +82,7 @@ TEST(OptionsAssignerTest, HandlesMissingRequiredParameter)
 
 TEST(OptionsAssignerTest, HandlesRequiredParameterWithDefaultValue)
 {
-    gmx::Options options(NULL, NULL);
+    gmx::Options options;
     int          value = 0;
     using gmx::IntegerOption;
     ASSERT_NO_THROW(options.addOption(
@@ -94,7 +95,7 @@ TEST(OptionsAssignerTest, HandlesRequiredParameterWithDefaultValue)
 
 TEST(OptionsAssignerTest, HandlesInvalidMultipleParameter)
 {
-    gmx::Options     options(NULL, NULL);
+    gmx::Options     options;
     std::vector<int> values;
     bool             bIsSet = false;
     using gmx::IntegerOption;
@@ -119,7 +120,7 @@ TEST(OptionsAssignerTest, HandlesInvalidMultipleParameter)
 
 TEST(OptionsAssignerTest, HandlesMultipleParameter)
 {
-    gmx::Options     options(NULL, NULL);
+    gmx::Options     options;
     std::vector<int> values;
     bool             bIsSet = false;
     using gmx::IntegerOption;
@@ -147,7 +148,7 @@ TEST(OptionsAssignerTest, HandlesMultipleParameter)
 
 TEST(OptionsAssignerTest, HandlesMissingValue)
 {
-    gmx::Options options(NULL, NULL);
+    gmx::Options options;
     int          value1 = 0, value2 = 0;
     using gmx::IntegerOption;
     ASSERT_NO_THROW(options.addOption(IntegerOption("p").store(&value1)));
@@ -168,7 +169,7 @@ TEST(OptionsAssignerTest, HandlesMissingValue)
 
 TEST(OptionsAssignerTest, HandlesExtraValue)
 {
-    gmx::Options options(NULL, NULL);
+    gmx::Options options;
     int          value1 = 0;
     using gmx::IntegerOption;
     ASSERT_NO_THROW(options.addOption(IntegerOption("p").store(&value1)));
@@ -187,7 +188,7 @@ TEST(OptionsAssignerTest, HandlesExtraValue)
 
 TEST(OptionsAssignerTest, HandlesGroups)
 {
-    gmx::Options            options(NULL, NULL);
+    gmx::Options            options;
     gmx::IOptionsContainer &group1 = options.addGroup();
     gmx::IOptionsContainer &group2 = options.addGroup();
     int                     value  = 3;
@@ -217,36 +218,35 @@ TEST(OptionsAssignerTest, HandlesGroups)
     EXPECT_EQ(6, value2);
 }
 
-TEST(OptionsAssignerTest, HandlesSubSections)
+TEST(OptionsAssignerTest, HandlesSections)
 {
-    gmx::Options options(NULL, NULL);
-    gmx::Options sub1("section1", NULL);
-    gmx::Options sub2("section2", NULL);
+    using gmx::OptionSection;
+    gmx::Options options;
+    auto        &sub1   = options.addSection(OptionSection("section1"));
+    auto        &sub2   = options.addSection(OptionSection("section2"));
     int          value  = 3;
     int          value1 = 1;
     int          value2 = 2;
     using gmx::IntegerOption;
-    ASSERT_NO_THROW(options.addSubSection(&sub1));
-    ASSERT_NO_THROW(options.addSubSection(&sub2));
-    ASSERT_NO_THROW(options.addOption(IntegerOption("p").store(&value)));
-    ASSERT_NO_THROW(sub1.addOption(IntegerOption("p").store(&value1)));
-    ASSERT_NO_THROW(sub2.addOption(IntegerOption("p").store(&value2)));
+    ASSERT_NO_THROW_GMX(options.addOption(IntegerOption("p").store(&value)));
+    ASSERT_NO_THROW_GMX(sub1.addOption(IntegerOption("p").store(&value1)));
+    ASSERT_NO_THROW_GMX(sub2.addOption(IntegerOption("p").store(&value2)));
 
     gmx::OptionsAssigner assigner(&options);
     EXPECT_NO_THROW(assigner.start());
-    ASSERT_NO_THROW(assigner.startSubSection("section1"));
+    ASSERT_NO_THROW(assigner.startSection("section1"));
     ASSERT_NO_THROW(assigner.startOption("p"));
     EXPECT_NO_THROW(assigner.appendValue("5"));
     EXPECT_NO_THROW(assigner.finishOption());
-    EXPECT_NO_THROW(assigner.finishSubSection());
+    EXPECT_NO_THROW(assigner.finishSection());
     ASSERT_NO_THROW(assigner.startOption("p"));
     EXPECT_NO_THROW(assigner.appendValue("4"));
     EXPECT_NO_THROW(assigner.finishOption());
-    ASSERT_NO_THROW(assigner.startSubSection("section2"));
+    ASSERT_NO_THROW(assigner.startSection("section2"));
     ASSERT_NO_THROW(assigner.startOption("p"));
     EXPECT_NO_THROW(assigner.appendValue("6"));
     EXPECT_NO_THROW(assigner.finishOption());
-    EXPECT_NO_THROW(assigner.finishSubSection());
+    EXPECT_NO_THROW(assigner.finishSection());
     EXPECT_NO_THROW(assigner.finish());
     EXPECT_NO_THROW(options.finish());
 
@@ -257,7 +257,7 @@ TEST(OptionsAssignerTest, HandlesSubSections)
 
 TEST(OptionsAssignerTest, HandlesMultipleSources)
 {
-    gmx::Options options(NULL, NULL);
+    gmx::Options options;
     int          value = -1;
     using gmx::IntegerOption;
     ASSERT_NO_THROW(options.addOption(IntegerOption("p").store(&value)));
@@ -290,7 +290,7 @@ TEST(OptionsAssignerTest, HandlesMultipleSources)
 
 TEST(OptionsAssignerBooleanTest, StoresYesValue)
 {
-    gmx::Options options(NULL, NULL);
+    gmx::Options options;
     bool         value = false;
     using gmx::BooleanOption;
     ASSERT_NO_THROW(options.addOption(BooleanOption("p").store(&value)));
@@ -308,7 +308,7 @@ TEST(OptionsAssignerBooleanTest, StoresYesValue)
 
 TEST(OptionsAssignerBooleanTest, SetsBooleanWithoutExplicitValue)
 {
-    gmx::Options options(NULL, NULL);
+    gmx::Options options;
     bool         value = false;
     using gmx::BooleanOption;
     ASSERT_NO_THROW(options.addOption(BooleanOption("p").store(&value)));
@@ -325,7 +325,7 @@ TEST(OptionsAssignerBooleanTest, SetsBooleanWithoutExplicitValue)
 
 TEST(OptionsAssignerBooleanTest, ClearsBooleanWithPrefixNo)
 {
-    gmx::Options options(NULL, NULL);
+    gmx::Options options;
     bool         value = true;
     using gmx::BooleanOption;
     ASSERT_NO_THROW(options.addOption(BooleanOption("p").store(&value)));
@@ -343,7 +343,7 @@ TEST(OptionsAssignerBooleanTest, ClearsBooleanWithPrefixNo)
 
 TEST(OptionsAssignerBooleanTest, HandlesBooleanWithPrefixAndValue)
 {
-    gmx::Options options(NULL, NULL);
+    gmx::Options options;
     bool         value = false;
     using gmx::BooleanOption;
     ASSERT_NO_THROW(options.addOption(BooleanOption("p").store(&value)));
@@ -374,7 +374,7 @@ TEST(OptionsAssignerBooleanTest, HandlesBooleanWithPrefixAndValue)
 
 TEST(OptionsAssignerIntegerTest, StoresSingleValue)
 {
-    gmx::Options options(NULL, NULL);
+    gmx::Options options;
     int          value = 1;
     using gmx::IntegerOption;
     ASSERT_NO_THROW(options.addOption(IntegerOption("p").store(&value)));
@@ -392,7 +392,7 @@ TEST(OptionsAssignerIntegerTest, StoresSingleValue)
 
 TEST(OptionsAssignerIntegerTest, HandlesEmptyValue)
 {
-    gmx::Options options(NULL, NULL);
+    gmx::Options options;
     int          value = 1;
     using gmx::IntegerOption;
     ASSERT_NO_THROW(options.addOption(IntegerOption("p").store(&value)));
@@ -410,7 +410,7 @@ TEST(OptionsAssignerIntegerTest, HandlesEmptyValue)
 
 TEST(OptionsAssignerIntegerTest, HandlesInvalidValue)
 {
-    gmx::Options options(NULL, NULL);
+    gmx::Options options;
     int          value = 1;
     using gmx::IntegerOption;
     ASSERT_NO_THROW(options.addOption(IntegerOption("p").store(&value)));
@@ -428,7 +428,7 @@ TEST(OptionsAssignerIntegerTest, HandlesInvalidValue)
 
 TEST(OptionsAssignerIntegerTest, HandlesOverflow)
 {
-    gmx::Options options(NULL, NULL);
+    gmx::Options options;
     int          value = 1;
     using gmx::IntegerOption;
     ASSERT_NO_THROW(options.addOption(IntegerOption("p").store(&value)));
@@ -448,7 +448,7 @@ TEST(OptionsAssignerIntegerTest, HandlesOverflow)
 
 TEST(OptionsAssignerIntegerTest, StoresDefaultValue)
 {
-    gmx::Options options(NULL, NULL);
+    gmx::Options options;
     int          value = -1;
     using gmx::IntegerOption;
     ASSERT_NO_THROW(options.addOption(
@@ -465,7 +465,7 @@ TEST(OptionsAssignerIntegerTest, StoresDefaultValue)
 
 TEST(OptionsAssignerIntegerTest, StoresDefaultValueIfSet)
 {
-    gmx::Options options(NULL, NULL);
+    gmx::Options options;
     int          value = -1;
     using gmx::IntegerOption;
     ASSERT_NO_THROW(options.addOption(
@@ -484,7 +484,7 @@ TEST(OptionsAssignerIntegerTest, StoresDefaultValueIfSet)
 
 TEST(OptionsAssignerIntegerTest, HandlesDefaultValueIfSetWhenNotSet)
 {
-    gmx::Options options(NULL, NULL);
+    gmx::Options options;
     int          value = -1;
     using gmx::IntegerOption;
     ASSERT_NO_THROW(options.addOption(
@@ -501,7 +501,7 @@ TEST(OptionsAssignerIntegerTest, HandlesDefaultValueIfSetWhenNotSet)
 
 TEST(OptionsAssignerIntegerTest, HandlesBothDefaultValues)
 {
-    gmx::Options options(NULL, NULL);
+    gmx::Options options;
     int          value = -1;
     using gmx::IntegerOption;
     ASSERT_NO_THROW(options.addOption(
@@ -521,7 +521,7 @@ TEST(OptionsAssignerIntegerTest, HandlesBothDefaultValues)
 
 TEST(OptionsAssignerIntegerTest, StoresToVector)
 {
-    gmx::Options          options(NULL, NULL);
+    gmx::Options          options;
     std::vector<int>      values;
     using gmx::IntegerOption;
     ASSERT_NO_THROW(options.addOption(
@@ -545,7 +545,7 @@ TEST(OptionsAssignerIntegerTest, StoresToVector)
 
 TEST(OptionsAssignerIntegerTest, HandlesVectors)
 {
-    gmx::Options options(NULL, NULL);
+    gmx::Options options;
     int          vec[3] = {0, 0, 0};
     using gmx::IntegerOption;
     ASSERT_NO_THROW(options.addOption(IntegerOption("p").store(vec).vector()));
@@ -567,7 +567,7 @@ TEST(OptionsAssignerIntegerTest, HandlesVectors)
 
 TEST(OptionsAssignerIntegerTest, HandlesVectorFromSingleValue)
 {
-    gmx::Options options(NULL, NULL);
+    gmx::Options options;
     int          vec[3] = {0, 0, 0};
     using gmx::IntegerOption;
     ASSERT_NO_THROW(options.addOption(IntegerOption("p").store(vec).vector()));
@@ -587,7 +587,7 @@ TEST(OptionsAssignerIntegerTest, HandlesVectorFromSingleValue)
 
 TEST(OptionsAssignerIntegerTest, HandlesVectorsWithDefaultValue)
 {
-    gmx::Options options(NULL, NULL);
+    gmx::Options options;
     int          vec[3] = {3, 2, 1};
     using gmx::IntegerOption;
     ASSERT_NO_THROW(options.addOption(IntegerOption("p").store(vec).vector()));
@@ -601,7 +601,7 @@ TEST(OptionsAssignerIntegerTest, HandlesVectorsWithDefaultValue)
 
 TEST(OptionsAssignerIntegerTest, HandlesVectorsWithDefaultValueWithInvalidAssignment)
 {
-    gmx::Options     options(NULL, NULL);
+    gmx::Options     options;
     int              vec[3] = {3, 2, 1};
     std::vector<int> vec2(vec, vec+3);
     using gmx::IntegerOption;
@@ -633,7 +633,7 @@ TEST(OptionsAssignerIntegerTest, HandlesVectorsWithDefaultValueWithInvalidAssign
 
 TEST(OptionsAssignerDoubleTest, StoresSingleValue)
 {
-    gmx::Options options(NULL, NULL);
+    gmx::Options options;
     double       value = 0.0;
     using gmx::DoubleOption;
     ASSERT_NO_THROW(options.addOption(DoubleOption("p").store(&value)));
@@ -651,7 +651,7 @@ TEST(OptionsAssignerDoubleTest, StoresSingleValue)
 
 TEST(OptionsAssignerDoubleTest, HandlesEmptyValue)
 {
-    gmx::Options options(NULL, NULL);
+    gmx::Options options;
     double       value = 1.0;
     using gmx::DoubleOption;
     ASSERT_NO_THROW(options.addOption(DoubleOption("p").store(&value)));
@@ -677,7 +677,7 @@ const char *const c_allowed[] = { "none", "test", "value" };
 
 TEST(OptionsAssignerStringTest, StoresSingleValue)
 {
-    gmx::Options           options(NULL, NULL);
+    gmx::Options           options;
     std::string            value;
     using gmx::StringOption;
     ASSERT_NO_THROW(options.addOption(StringOption("p").store(&value)));
@@ -695,7 +695,7 @@ TEST(OptionsAssignerStringTest, StoresSingleValue)
 
 TEST(OptionsAssignerStringTest, HandlesEnumValue)
 {
-    gmx::Options           options(NULL, NULL);
+    gmx::Options           options;
     std::string            value;
     using gmx::StringOption;
     ASSERT_NO_THROW(options.addOption(
@@ -715,7 +715,7 @@ TEST(OptionsAssignerStringTest, HandlesEnumValue)
 
 TEST(OptionsAssignerStringTest, HandlesEnumValueFromNullTerminatedArray)
 {
-    gmx::Options           options(NULL, NULL);
+    gmx::Options           options;
     std::string            value;
     const char * const     allowed[] = { "none", "test", "value", NULL };
     using gmx::StringOption;
@@ -736,7 +736,7 @@ TEST(OptionsAssignerStringTest, HandlesEnumValueFromNullTerminatedArray)
 
 TEST(OptionsAssignerStringTest, HandlesIncorrectEnumValue)
 {
-    gmx::Options           options(NULL, NULL);
+    gmx::Options           options;
     std::string            value;
     using gmx::StringOption;
     ASSERT_NO_THROW(options.addOption(
@@ -751,7 +751,7 @@ TEST(OptionsAssignerStringTest, HandlesIncorrectEnumValue)
 
 TEST(OptionsAssignerStringTest, CompletesEnumValue)
 {
-    gmx::Options           options(NULL, NULL);
+    gmx::Options           options;
     std::string            value;
     using gmx::StringOption;
     ASSERT_NO_THROW(options.addOption(
@@ -771,7 +771,7 @@ TEST(OptionsAssignerStringTest, CompletesEnumValue)
 
 TEST(OptionsAssignerStringTest, HandlesEnumWithNoValue)
 {
-    gmx::Options           options(NULL, NULL);
+    gmx::Options           options;
     std::string            value;
     using gmx::StringOption;
     ASSERT_NO_THROW(options.addOption(
@@ -786,7 +786,7 @@ TEST(OptionsAssignerStringTest, HandlesEnumWithNoValue)
 
 TEST(OptionsAssignerStringTest, HandlesEnumDefaultValue)
 {
-    gmx::Options           options(NULL, NULL);
+    gmx::Options           options;
     std::string            value;
     using gmx::StringOption;
     ASSERT_NO_THROW(options.addOption(
@@ -804,7 +804,7 @@ TEST(OptionsAssignerStringTest, HandlesEnumDefaultValue)
 
 TEST(OptionsAssignerStringTest, HandlesEnumDefaultValueFromVariable)
 {
-    gmx::Options           options(NULL, NULL);
+    gmx::Options           options;
     std::string            value("test");
     using gmx::StringOption;
     ASSERT_NO_THROW(options.addOption(
@@ -822,7 +822,7 @@ TEST(OptionsAssignerStringTest, HandlesEnumDefaultValueFromVariable)
 
 TEST(OptionsAssignerStringTest, HandlesEnumDefaultValueFromVector)
 {
-    gmx::Options             options(NULL, NULL);
+    gmx::Options             options;
     std::vector<std::string> value;
     value.push_back("test");
     value.push_back("value");
@@ -860,7 +860,7 @@ enum TestEnum
 
 TEST(OptionsAssignerEnumTest, StoresSingleValue)
 {
-    gmx::Options           options(NULL, NULL);
+    gmx::Options           options;
     TestEnum               value     = etestNone;
     using gmx::EnumOption;
     ASSERT_NO_THROW(options.addOption(
@@ -881,7 +881,7 @@ TEST(OptionsAssignerEnumTest, StoresSingleValue)
 
 TEST(OptionsAssignerEnumTest, StoresVectorValues)
 {
-    gmx::Options           options(NULL, NULL);
+    gmx::Options           options;
     std::vector<TestEnum>  values;
     using gmx::EnumOption;
     ASSERT_NO_THROW(options.addOption(
@@ -905,7 +905,7 @@ TEST(OptionsAssignerEnumTest, StoresVectorValues)
 
 TEST(OptionsAssignerEnumTest, HandlesInitialValueOutOfRange)
 {
-    gmx::Options           options(NULL, NULL);
+    gmx::Options           options;
     TestEnum               value     = etestNR;
     using gmx::EnumOption;
     ASSERT_NO_THROW(options.addOption(
@@ -923,7 +923,7 @@ TEST(OptionsAssignerEnumTest, HandlesInitialValueOutOfRange)
 
 TEST(OptionsAssignerEnumTest, HandlesEnumDefaultValue)
 {
-    gmx::Options           options(NULL, NULL);
+    gmx::Options           options;
     TestEnum               value     = etestNone;
     using gmx::EnumOption;
     ASSERT_NO_THROW(options.addOption(
@@ -941,7 +941,7 @@ TEST(OptionsAssignerEnumTest, HandlesEnumDefaultValue)
 
 TEST(OptionsAssignerEnumTest, HandlesEnumDefaultValueFromVariable)
 {
-    gmx::Options           options(NULL, NULL);
+    gmx::Options           options;
     TestEnum               value     = etestTest;
     using gmx::EnumOption;
     ASSERT_NO_THROW(options.addOption(
@@ -959,7 +959,7 @@ TEST(OptionsAssignerEnumTest, HandlesEnumDefaultValueFromVariable)
 
 TEST(OptionsAssignerEnumTest, HandlesEnumDefaultValueFromVector)
 {
-    gmx::Options             options(NULL, NULL);
+    gmx::Options             options;
     std::vector<TestEnum>    value;
     value.push_back(etestNone);
     value.push_back(etestTest);
index a66206b2e7e11b47566cadac06e327be5fe3fbb1..044f81ee7fc80f33aed12ce937f1f747cafb01f9 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2012,2013,2014,2015, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016, 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.
@@ -72,7 +72,7 @@ TEST(TimeUnitBehaviorTest, ScalesAssignedOptionValue)
 {
     gmx::TimeUnitBehavior  behavior;
 
-    gmx::Options           options(NULL, NULL);
+    gmx::Options           options;
     double                 value = 0.0;
     using gmx::DoubleOption;
     ASSERT_NO_THROW_GMX(options.addOption(DoubleOption("p").store(&value).timeValue()));
@@ -108,7 +108,7 @@ TEST(TimeUnitBehaviorTest, DoesNotScaleDefaultValues)
 {
     gmx::TimeUnitBehavior behavior;
 
-    gmx::Options          options(NULL, NULL);
+    gmx::Options          options;
     double                value = 1.5, value2 = 0.0;
     using gmx::DoubleOption;
     ASSERT_NO_THROW_GMX(options.addOption(DoubleOption("p").store(&value).timeValue()));
@@ -133,7 +133,7 @@ TEST(TimeUnitBehaviorTest, ScalesUserInputWithMultipleSources)
 {
     gmx::TimeUnitBehavior behavior;
 
-    gmx::Options          options(NULL, NULL);
+    gmx::Options          options;
     double                value = 0.0;
     using gmx::DoubleOption;
     ASSERT_NO_THROW_GMX(options.addOption(DoubleOption("p").store(&value).timeValue()));
@@ -159,7 +159,7 @@ TEST(TimeUnitBehaviorTest, TimeUnitOptionWorks)
 {
     gmx::TimeUnitBehavior behavior;
 
-    gmx::Options          options(NULL, NULL);
+    gmx::Options          options;
     double                value = 0.0;
     using gmx::DoubleOption;
     ASSERT_NO_THROW_GMX(options.addOption(DoubleOption("p").store(&value).timeValue()));
index 73f8fc329b081311b76b770a174fb6dbee5ce157..8136f80681eabfcdd88fda6916b7e4071f96b654 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2012,2013,2014,2015, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016, 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.
@@ -190,10 +190,10 @@ class TimeOptionScaler : public OptionsModifyingTypeVisitor<FloatingPointOptionI
         //! Initializes a scaler with the given factor.
         explicit TimeOptionScaler(double factor) : factor_(factor) {}
 
-        void visitSubSection(Options *section)
+        void visitSection(OptionSectionInfo *section)
         {
             OptionsModifyingIterator iterator(section);
-            iterator.acceptSubSections(this);
+            iterator.acceptSections(this);
             iterator.acceptOptions(this);
         }
 
@@ -214,8 +214,8 @@ class TimeOptionScaler : public OptionsModifyingTypeVisitor<FloatingPointOptionI
 void TimeUnitBehavior::optionsFinishing(Options *options)
 {
     double factor = TimeUnitManager(timeUnit()).timeScaleFactor();
-    TimeOptionScaler<DoubleOptionInfo>(factor).visitSubSection(options);
-    TimeOptionScaler<FloatOptionInfo>(factor).visitSubSection(options);
+    TimeOptionScaler<DoubleOptionInfo>(factor).visitSection(&options->rootSection());
+    TimeOptionScaler<FloatOptionInfo>(factor).visitSection(&options->rootSection());
     if (timeUnitStore_ != NULL)
     {
         *timeUnitStore_ = static_cast<TimeUnit>(timeUnit_);
index 8cd96fab1315ffa10d73d01ebe0fdb7cf82133fb..d6d6e7053fc6b5ba966b7f0daabdbc0907e34896 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2010,2011,2012,2013,2014,2015, by the GROMACS development team, led by
+ * Copyright (c) 2010,2011,2012,2013,2014,2015,2016, 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.
@@ -83,7 +83,7 @@ class SelectionOptionTestBase : public ::testing::Test
 };
 
 SelectionOptionTestBase::SelectionOptionTestBase()
-    : manager_(&sc_), options_(NULL, NULL)
+    : manager_(&sc_)
 {
     options_.addManager(&manager_);
     sc_.setReferencePosType("atom");
index 6dceffc528b3832a1e67c714e8438d52caf5438d..3714313fe6cd5dea3dc9172ea09df8c7fc4d531c 100644 (file)
@@ -52,6 +52,7 @@
 namespace gmx
 {
 
+#ifdef DOXYGEN
 /*! \brief
  * Macro to declare a class non-copyable and non-assignable.
  *
@@ -59,9 +60,12 @@ namespace gmx
  *
  * \ingroup module_utility
  */
+#define GMX_DISALLOW_COPY_AND_ASSIGN(ClassName)
+#else
 #define GMX_DISALLOW_COPY_AND_ASSIGN(ClassName) \
     ClassName &operator=(const ClassName &) = delete;   \
     ClassName(const ClassName &)            = delete
+#endif
 /*! \brief
  * Macro to declare a class non-assignable.
  *
index 83e877d7be942f26d0397b5fe72b7b8aae6173f2..4c2411b7e83681f84995b6a60b1ad40fbdf57b63 100644 (file)
@@ -198,7 +198,7 @@ void initTestUtils(const char *dataPath, const char *tempPath, bool usesMpi,
         }
         bool        bHelp = false;
         std::string sourceRoot;
-        Options     options(NULL, NULL);
+        Options     options;
         // TODO: A single option that accepts multiple names would be nicer.
         // Also, we recognize -help, but GTest doesn't, which leads to a bit
         // unintuitive behavior.