Line data Source code
1 : //* This file is part of the MOOSE framework
2 : //* https://mooseframework.inl.gov
3 : //*
4 : //* All rights reserved, see COPYRIGHT for full restrictions
5 : //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6 : //*
7 : //* Licensed under LGPL 2.1, please see LICENSE for details
8 : //* https://www.gnu.org/licenses/lgpl-2.1.html
9 :
10 : #include "MooseEnumBase.h"
11 : #include "MooseUtils.h"
12 : #include "MooseError.h"
13 : #include "Conversion.h"
14 :
15 : #include <sstream>
16 : #include <algorithm>
17 : #include <iterator>
18 : #include <limits>
19 : #include <string>
20 : #include <iostream>
21 : #include <cstdlib>
22 :
23 35980481 : MooseEnumBase::MooseEnumBase(std::string names, bool allow_out_of_range)
24 35980481 : : _allow_out_of_range(allow_out_of_range)
25 : {
26 35980481 : if (names.find(',') != std::string::npos)
27 0 : mooseError("Spaces are required to separate options, comma support has been removed.");
28 : else
29 35980481 : addEnumerationNames(names);
30 35980487 : }
31 :
32 20901203 : MooseEnumBase::MooseEnumBase(const MooseEnumBase & other_enum)
33 20901203 : : _items(other_enum._items),
34 20901203 : _deprecated_items(other_enum._deprecated_items),
35 41802406 : _allow_out_of_range(other_enum._allow_out_of_range)
36 : {
37 20901203 : }
38 :
39 : /**
40 : * Private constuctor for use by libmesh::Parameters
41 : */
42 104199312 : MooseEnumBase::MooseEnumBase() : _allow_out_of_range(false) {}
43 :
44 : void
45 3 : MooseEnumBase::deprecate(const std::string & name, const std::string & raw_name)
46 : {
47 3 : std::set<MooseEnumItem>::const_iterator deprecated = find(name);
48 3 : if (deprecated == _items.end())
49 0 : mooseError("Cannot deprecate the enum item ", name, ", is not an available value.");
50 :
51 3 : std::set<MooseEnumItem>::const_iterator replaced = find(raw_name);
52 3 : if (replaced == _items.end())
53 1 : mooseError("Cannot deprecate the enum item ",
54 : name,
55 : ", since the replaced item ",
56 : raw_name,
57 : " it is not an available value.");
58 :
59 2 : _deprecated_items.emplace(std::make_pair(*deprecated, *replaced));
60 2 : checkDeprecated();
61 2 : }
62 :
63 : void
64 35980481 : MooseEnumBase::addEnumerationNames(const std::string & names)
65 : {
66 35980481 : std::vector<std::string> elements;
67 35980481 : MooseUtils::tokenize(names, elements, 1, " ");
68 215838487 : for (const std::string & raw_name : elements)
69 179858009 : addEnumerationName(raw_name);
70 35980481 : }
71 :
72 : const MooseEnumItem &
73 179858009 : MooseEnumBase::addEnumerationName(const std::string & raw_name)
74 : {
75 : // Make sure the option is not malformed
76 179858009 : if (raw_name.find_first_of('=') == 0 || raw_name.find_last_of('=') == raw_name.length() - 1)
77 1 : mooseError("You cannot place whitespace around the '=' character in MooseEnumBase");
78 :
79 : // Split on equals sign
80 179858008 : std::vector<std::string> name_value;
81 179858008 : MooseUtils::tokenize(MooseUtils::trim(raw_name), name_value, 1, "=");
82 :
83 : // There should be one or two items in the name_value
84 179858008 : if (name_value.size() < 1 || name_value.size() > 2)
85 0 : mooseError("Invalid option supplied in MooseEnumBase: ", raw_name);
86 :
87 : // Remove un-wanted space around string
88 179858008 : name_value[0] = MooseUtils::trim(name_value[0]);
89 :
90 : // See if there is a value supplied for this option
91 : // strtol allows for proper conversions of both int and hex strings
92 : int value;
93 179858008 : if (name_value.size() == 2)
94 20380426 : value = std::strtol(name_value[1].c_str(), NULL, 0);
95 : else
96 159477582 : value = getNextValidID();
97 :
98 359716014 : return addEnumerationName(name_value[0], value);
99 179858008 : }
100 :
101 : int
102 174313302 : MooseEnumBase::getNextValidID() const
103 : {
104 174313302 : int value = -1; // Use -1 so if no values exist the first will be zero
105 1475093730 : for (const auto & item : _items)
106 1300780428 : value = std::max(value, item.id());
107 174313302 : return ++value;
108 : }
109 :
110 : const MooseEnumItem &
111 179858008 : MooseEnumBase::addEnumerationName(const std::string & name, const int & value)
112 : {
113 179858008 : return addEnumerationItem(MooseEnumItem(name, value));
114 : }
115 :
116 : const MooseEnumItem &
117 203957591 : MooseEnumBase::addEnumerationItem(const MooseEnumItem & item)
118 : {
119 203957591 : const auto & item_it = find(item);
120 203957591 : if (item_it != _items.end()) // do nothing for identical insertions
121 0 : return *item_it;
122 :
123 203957591 : if (find(item.id()) != _items.end())
124 1 : mooseError("The supplied id ",
125 : item.id(),
126 : " already exists in the enumeration, cannot not add '",
127 : item,
128 : "'.");
129 203957590 : if (find(item.name()) != _items.end())
130 1 : mooseError("The name '", item.name(), "' already exists in the enumeration.");
131 :
132 203957589 : return *_items.insert(item).first;
133 : }
134 :
135 : void
136 75287996 : MooseEnumBase::checkDeprecated(const MooseEnumItem & item) const
137 : {
138 75287996 : std::map<MooseEnumItem, MooseEnumItem>::const_iterator it = _deprecated_items.find(item);
139 75287996 : if (it != _deprecated_items.end())
140 : {
141 2 : if (it->second.name().empty())
142 0 : mooseWarning(item.name() + " is deprecated");
143 : else
144 6 : mooseWarning(item.name() + " is deprecated, consider using " + it->second.name());
145 : }
146 75287994 : }
147 :
148 : std::vector<std::string>
149 1631 : MooseEnumBase::getNames() const
150 : {
151 1631 : std::vector<std::string> out;
152 1631 : out.reserve(_items.size());
153 16941 : for (const auto & item : _items)
154 15310 : out.push_back(item.name());
155 1631 : return out;
156 0 : }
157 :
158 : std::string
159 673597 : MooseEnumBase::getRawNames() const
160 : {
161 673597 : return Moose::stringify(_items, " ");
162 : }
163 :
164 : std::vector<int>
165 2 : MooseEnumBase::getIDs() const
166 : {
167 2 : std::vector<int> out;
168 2 : out.reserve(_items.size());
169 6 : for (const auto & item : _items)
170 4 : out.push_back(item.id());
171 2 : return out;
172 0 : }
173 :
174 : void
175 280005 : MooseEnumBase::addDocumentation(const std::string & name, const std::string & doc)
176 : {
177 280005 : auto it = find(name);
178 280005 : if (it == _items.end())
179 0 : mooseError("Item '", name, "' not found in addDocumentation.");
180 280005 : _item_documentation[*it] = doc;
181 280005 : }
182 :
183 : const std::map<MooseEnumItem, std::string> &
184 615076 : MooseEnumBase::getItemDocumentation() const
185 : {
186 615076 : return _item_documentation;
187 : }
188 :
189 : std::set<MooseEnumItem>::const_iterator
190 241538769 : MooseEnumBase::find(const std::string & name) const
191 : {
192 241538769 : std::string upper = MooseUtils::toUpper(name);
193 241538769 : return std::find_if(_items.begin(),
194 : _items.end(),
195 2021442638 : [&upper](MooseEnumItem const & item) { return item.name() == upper; });
196 241538769 : }
197 :
198 : std::set<MooseEnumItem>::const_iterator
199 204218399 : MooseEnumBase::find(int id) const
200 : {
201 204218399 : return std::find_if(
202 1659487798 : _items.begin(), _items.end(), [&id](MooseEnumItem const & item) { return item.id() == id; });
203 : }
204 :
205 : std::set<MooseEnumItem>::const_iterator
206 241680989 : MooseEnumBase::find(const MooseEnumItem & other) const
207 : {
208 241680989 : const auto upper = MooseUtils::toUpper(other.name());
209 241680989 : return std::find_if(_items.begin(),
210 : _items.end(),
211 3354611188 : [&other, &upper](MooseEnumItem const & item)
212 2141805873 : { return item.id() == other.id() && item.name() == upper; });
213 241680989 : }
214 :
215 : MooseEnumBase &
216 0 : MooseEnumBase::operator+=(const std::string & name)
217 : {
218 0 : addEnumerationName(name);
219 0 : checkDeprecated();
220 0 : return *this;
221 : }
222 :
223 : MooseEnumBase &
224 0 : MooseEnumBase::operator+=(const std::initializer_list<std::string> & names)
225 : {
226 0 : for (const auto & name : names)
227 0 : *this += name;
228 0 : return *this;
229 : }
|