Enable clang tidy/warnings for tests
[alexxy/gromacs.git] / src / testutils / refdata-impl.h
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 2015,2016,2017,2018, by the GROMACS development team, led by
5  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
6  * and including many others, as listed in the AUTHORS file in the
7  * top-level source directory and at http://www.gromacs.org.
8  *
9  * GROMACS is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public License
11  * as published by the Free Software Foundation; either version 2.1
12  * of the License, or (at your option) any later version.
13  *
14  * GROMACS is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with GROMACS; if not, see
21  * http://www.gnu.org/licenses, or write to the Free Software Foundation,
22  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
23  *
24  * If you want to redistribute modifications to GROMACS, please
25  * consider that scientific software is very special. Version
26  * control is crucial - bugs must be traceable. We will be happy to
27  * consider code for inclusion in the official distribution, but
28  * derived work must not be called official GROMACS. Details are found
29  * in the README & COPYING files - if they are missing, get the
30  * official version at http://www.gromacs.org.
31  *
32  * To help us fund GROMACS development, we humbly ask that you cite
33  * the research papers on the package. Check out http://www.gromacs.org.
34  */
35 /*! \internal \file
36  * \brief
37  * Declares internal data structures for the reference data framework.
38  *
39  * \author Teemu Murtola <teemu.murtola@gmail.com>
40  * \ingroup module_testutils
41  */
42 #ifndef GMX_TESTUTILS_REFDATA_IMPL_H
43 #define GMX_TESTUTILS_REFDATA_IMPL_H
44
45 #include <list>
46 #include <memory>
47 #include <string>
48
49 #include "gromacs/compat/make_unique.h"
50 #include "gromacs/utility/gmxassert.h"
51
52 namespace gmx
53 {
54 namespace test
55 {
56
57 class ReferenceDataEntry
58 {
59     public:
60         typedef std::unique_ptr<ReferenceDataEntry> EntryPointer;
61         typedef std::list<EntryPointer> ChildList;
62         typedef ChildList::const_iterator ChildIterator;
63
64         static EntryPointer createRoot()
65         {
66             return gmx::compat::make_unique<ReferenceDataEntry>("", "");
67         }
68
69         ReferenceDataEntry(const char *type, const char *id)
70             : type_(type), id_(id != nullptr ? id : ""), isTextBlock_(false),
71               hasBeenChecked_(false), correspondingOutputEntry_(nullptr)
72         {
73         }
74
75         const std::string &type() const { return type_; }
76         const std::string &id() const { return id_; }
77         bool isCompound() const { return !children_.empty(); }
78         bool isTextBlock() const { return isTextBlock_; }
79         const std::string &value() const { return value_; }
80         const ChildList &children() const { return children_; }
81         ReferenceDataEntry *correspondingOutputEntry() const
82         {
83             return correspondingOutputEntry_;
84         }
85
86         bool idMatches(const char *id) const
87         {
88             return (id == nullptr && id_.empty()) || (id != nullptr && id_ == id);
89         }
90
91         ChildIterator findChild(const char *id, const ChildIterator &prev) const
92         {
93             if (children_.empty())
94             {
95                 return children_.end();
96             }
97             ChildIterator  child          = prev;
98             bool           wrappingSearch = true;
99             if (child != children_.end())
100             {
101                 if (id == nullptr && (*child)->id().empty())
102                 {
103                     wrappingSearch = false;
104                     ++child;
105                     if (child == children_.end())
106                     {
107                         return children_.end();
108                     }
109                 }
110             }
111             else
112             {
113                 child          = children_.begin();
114                 wrappingSearch = false;
115             }
116             do
117             {
118                 if ((*child)->idMatches(id))
119                 {
120                     return child;
121                 }
122                 ++child;
123                 if (wrappingSearch && child == children_.end())
124                 {
125                     child = children_.begin();
126                 }
127             }
128             while (child != children_.end() && child != prev);
129             return children_.end();
130         }
131         bool isValidChild(const ChildIterator &prev) const
132         {
133             return prev != children_.end();
134         }
135
136         bool hasBeenChecked() const { return hasBeenChecked_; }
137         void setChecked() { hasBeenChecked_ = true; }
138
139         void setCheckedIncludingChildren()
140         {
141             setChecked();
142             for (const auto &child : children_)
143             {
144                 child->setCheckedIncludingChildren();
145             }
146         }
147
148         EntryPointer cloneToOutputEntry()
149         {
150             EntryPointer entry(new ReferenceDataEntry(type_.c_str(), id_.c_str()));
151             setCorrespondingOutputEntry(entry.get());
152             entry->setValue(value());
153             entry->isTextBlock_ = isTextBlock_;
154             return entry;
155         }
156
157         void setValue(const std::string &value)
158         {
159             GMX_RELEASE_ASSERT(!isCompound(),
160                                "Cannot have a value for a compound entry");
161             value_ = value;
162         }
163         void setTextBlockValue(const std::string &value)
164         {
165             GMX_RELEASE_ASSERT(!isCompound(),
166                                "Cannot have a value for a compound entry");
167             value_       = value;
168             isTextBlock_ = true;
169         }
170         void makeCompound(const char *type)
171         {
172             type_.assign(type);
173             value_.clear();
174             isTextBlock_ = false;
175         }
176         void setCorrespondingOutputEntry(ReferenceDataEntry *entry)
177         {
178             GMX_RELEASE_ASSERT(correspondingOutputEntry_ == nullptr,
179                                "Output entry already exists");
180             correspondingOutputEntry_ = entry;
181         }
182         ChildIterator addChild(EntryPointer child)
183         {
184             GMX_RELEASE_ASSERT(isCompound() || value_.empty(),
185                                "Cannot make an entry with a value to a compound");
186             return children_.insert(children_.end(), move(child));
187         }
188
189     private:
190         std::string         type_;
191         std::string         id_;
192         std::string         value_;
193         bool                isTextBlock_;
194         ChildList           children_;
195         bool                hasBeenChecked_;
196         ReferenceDataEntry *correspondingOutputEntry_;
197 };
198
199 } // namespace test
200 } // namespace gmx
201
202 #endif