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 48507510 : MooseEnumBase::MooseEnumBase(std::string names, bool allow_out_of_range)
24 48507510 : : _allow_out_of_range(allow_out_of_range)
25 : {
26 48507510 : if (names.find(',') != std::string::npos)
27 0 : mooseError("Spaces are required to separate options, comma support has been removed.");
28 : else
29 48507510 : addEnumerationNames(names);
30 48507522 : }
31 :
32 22104422 : MooseEnumBase::MooseEnumBase(const MooseEnumBase & other_enum)
33 22104422 : : _items(other_enum._items),
34 22104422 : _deprecated_items(other_enum._deprecated_items),
35 44208844 : _allow_out_of_range(other_enum._allow_out_of_range)
36 : {
37 22104422 : }
38 :
39 : /**
40 : * Private constuctor for use by libmesh::Parameters
41 : */
42 132614442 : MooseEnumBase::MooseEnumBase() : _allow_out_of_range(false) {}
43 :
44 : void
45 6 : MooseEnumBase::deprecate(const std::string & name, const std::string & raw_name)
46 : {
47 6 : std::set<MooseEnumItem>::const_iterator deprecated = find(name);
48 6 : if (deprecated == _items.end())
49 0 : mooseError("Cannot deprecate the enum item ", name, ", is not an available value.");
50 :
51 6 : std::set<MooseEnumItem>::const_iterator replaced = find(raw_name);
52 6 : if (replaced == _items.end())
53 2 : 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 4 : _deprecated_items.emplace(std::make_pair(*deprecated, *replaced));
60 4 : checkDeprecated();
61 4 : }
62 :
63 : void
64 48507510 : MooseEnumBase::addEnumerationNames(const std::string & names)
65 : {
66 48507510 : std::vector<std::string> elements;
67 48507510 : MooseUtils::tokenize(names, elements, 1, " ");
68 262625108 : for (const std::string & raw_name : elements)
69 214117604 : addEnumerationName(raw_name);
70 48507510 : }
71 :
72 : const MooseEnumItem &
73 214402539 : MooseEnumBase::addEnumerationName(const std::string & raw_name)
74 : {
75 : // Make sure the option is not malformed
76 214402539 : if (raw_name.find_first_of('=') == 0 || raw_name.find_last_of('=') == raw_name.length() - 1)
77 2 : mooseError("You cannot place whitespace around the '=' character in MooseEnumBase");
78 :
79 : // Split on equals sign
80 214402537 : std::vector<std::string> name_value;
81 643207611 : MooseUtils::tokenize(MooseUtils::trim(raw_name), name_value, 1, "=");
82 :
83 : // There should be one or two items in the name_value
84 214402537 : 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 214402537 : 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 214402537 : if (name_value.size() == 2)
94 21272822 : value = std::strtol(name_value[1].c_str(), NULL, 0);
95 : else
96 193129715 : value = getNextValidID();
97 :
98 428805070 : return addEnumerationName(name_value[0], value);
99 214402537 : }
100 :
101 : int
102 209414799 : MooseEnumBase::getNextValidID() const
103 : {
104 209414799 : int value = -1; // Use -1 so if no values exist the first will be zero
105 1636927867 : for (const auto & item : _items)
106 1427513068 : value = std::max(value, item.id());
107 209414799 : return ++value;
108 : }
109 :
110 : const MooseEnumItem &
111 214402537 : MooseEnumBase::addEnumerationName(const std::string & name, const int & value)
112 : {
113 214402537 : return addEnumerationItem(MooseEnumItem(name, value));
114 : }
115 :
116 : const MooseEnumItem &
117 248562235 : MooseEnumBase::addEnumerationItem(const MooseEnumItem & item)
118 : {
119 248562235 : const auto & item_it = find(item);
120 248562235 : if (item_it != _items.end()) // do nothing for identical insertions
121 528897 : return *item_it;
122 :
123 248033338 : if (find(item.id()) != _items.end())
124 2 : mooseError("The supplied id ",
125 : item.id(),
126 : " already exists in the enumeration, cannot not add '",
127 : item,
128 : "'.");
129 248033336 : if (find(item.name()) != _items.end())
130 2 : mooseError("The name '", item.name(), "' already exists in the enumeration.");
131 :
132 248033334 : return *_items.insert(item).first;
133 : }
134 :
135 : void
136 90418830 : MooseEnumBase::checkDeprecated(const MooseEnumItem & item) const
137 : {
138 90418830 : std::map<MooseEnumItem, MooseEnumItem>::const_iterator it = _deprecated_items.find(item);
139 90418830 : if (it != _deprecated_items.end())
140 : {
141 4 : if (it->second.name().empty())
142 0 : mooseWarning(item.name() + " is deprecated");
143 : else
144 12 : mooseWarning(item.name() + " is deprecated, consider using " + it->second.name());
145 : }
146 90418826 : }
147 :
148 : std::vector<std::string>
149 1782 : MooseEnumBase::getNames() const
150 : {
151 1782 : std::vector<std::string> out;
152 1782 : out.reserve(_items.size());
153 18494 : for (const auto & item : _items)
154 16712 : out.push_back(item.name());
155 1782 : return out;
156 0 : }
157 :
158 : std::string
159 988452 : MooseEnumBase::getRawNames() const
160 : {
161 3953808 : return Moose::stringify(_items, " ");
162 : }
163 :
164 : std::vector<int>
165 4 : MooseEnumBase::getIDs() const
166 : {
167 4 : std::vector<int> out;
168 4 : out.reserve(_items.size());
169 12 : for (const auto & item : _items)
170 8 : out.push_back(item.id());
171 4 : return out;
172 0 : }
173 :
174 : void
175 869256 : MooseEnumBase::addDocumentation(const std::string & name, const std::string & doc)
176 : {
177 869256 : auto it = find(name);
178 869256 : if (it == _items.end())
179 0 : mooseError("Item '", name, "' not found in addDocumentation.");
180 869256 : _item_documentation[*it] = doc;
181 869256 : }
182 :
183 : const std::map<MooseEnumItem, std::string> &
184 927852 : MooseEnumBase::getItemDocumentation() const
185 : {
186 927852 : return _item_documentation;
187 : }
188 :
189 : std::set<MooseEnumItem>::const_iterator
190 299512574 : MooseEnumBase::find(const std::string & name) const
191 : {
192 299512574 : std::string upper = MooseUtils::toUpper(name);
193 299512574 : return std::find_if(_items.begin(),
194 : _items.end(),
195 2399939439 : [&upper](MooseEnumItem const & item) { return item.name() == upper; });
196 299512574 : }
197 :
198 : std::set<MooseEnumItem>::const_iterator
199 248296583 : MooseEnumBase::find(int id) const
200 : {
201 248296583 : return std::find_if(
202 1945482993 : _items.begin(), _items.end(), [&id](MooseEnumItem const & item) { return item.id() == id; });
203 : }
204 :
205 : std::set<MooseEnumItem>::const_iterator
206 288723444 : MooseEnumBase::find(const MooseEnumItem & other) const
207 : {
208 288723444 : const auto upper = MooseUtils::toUpper(other.name());
209 288723444 : return std::find_if(_items.begin(),
210 : _items.end(),
211 1921888719 : [&other, &upper](MooseEnumItem const & item)
212 2499335607 : { return item.id() == other.id() && item.name() == upper; });
213 288723444 : }
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 : }
|