https://mooseframework.inl.gov
Loading...
Searching...
No Matches
MooseStringUtils.h
Go to the documentation of this file.
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#pragma once
11
12#include <algorithm>
13#include <sstream>
14#include <string>
15#include <vector>
16
17// The capabilities library (capabilities target in moose.mk) uses this
18// utility for parsing. We don't want to include libmesh libraries in
19// this library as the test harness uses it. However, in the convert
20// method (heavily used by the parser), we really want to take advantage
21// of libMesh::demangle() for useful error messages. So this lets us
22// still use pretty demangling when used by MOOSE but not by the
23// capabilities library (which is probably ok...)
24#ifndef MOOSESTRINGUTILS_NO_LIBMESH
25#include "libmesh/libmesh_common.h"
26#endif
27
28/*
29 * This must stay a header-only utility! It is used in the capabilities python module and
30 * we do not want to link against any MOOSE libs.
31 */
32namespace MooseUtils
33{
37inline std::string
38trim(const std::string & str, const std::string & white_space = " \t\n\v\f\r")
39{
40 const auto begin = str.find_first_not_of(white_space);
41 if (begin == std::string::npos)
42 return ""; // no content
43 const auto end = str.find_last_not_of(white_space);
44 return str.substr(begin, end - begin + 1);
45}
46
53template <typename T>
54void
55tokenize(const std::string & str,
56 std::vector<T> & elements,
57 unsigned int min_len = 1,
58 const std::string & delims = "/")
59{
60 elements.clear();
61
62 std::string::size_type last_pos = str.find_first_not_of(delims, 0);
63 std::string::size_type pos = str.find_first_of(delims, std::min(last_pos + min_len, str.size()));
64
65 while (last_pos != std::string::npos)
66 {
67 elements.push_back(str.substr(last_pos, pos - last_pos));
68 // skip delims between tokens
69 last_pos = str.find_first_not_of(delims, pos);
70 if (last_pos == std::string::npos)
71 break;
72 pos = str.find_first_of(delims, std::min(last_pos + min_len, str.size()));
73 }
74}
75
94template <class T>
95bool
96convert(const std::string & str, T & value, const bool throw_on_failure)
97{
98 // Special case for numeric values, also handling range checking
99 if constexpr (std::is_same_v<short int, T> || std::is_same_v<unsigned short int, T> ||
100 std::is_same_v<int, T> || std::is_same_v<unsigned int, T> ||
101 std::is_same_v<long int, T> || std::is_same_v<unsigned long int, T> ||
102 std::is_same_v<long long int, T> || std::is_same_v<unsigned long long int, T>)
103 {
104 // Try read a double and try to cast it to an int
105 long double double_val;
106 std::stringstream double_ss(str);
107 double_ss >> double_val;
108
109 if (!double_ss.fail() && double_ss.eof())
110 {
111 // on arm64 the long double does not have sufficient precision
112 std::stringstream int_ss(str);
113 const bool use_int = !(int_ss >> value).fail() && int_ss.eof();
114
115 // Check to see if it's an integer and thus within range of an integer
116 if (double_val == static_cast<long double>(static_cast<T>(double_val)))
117 {
118 if (!use_int)
119 value = static_cast<T>(double_val);
120 return true;
121 }
122 }
123 }
124 // Non numeric values
125 else
126 {
127 // string or derived string: direct copy
128 if constexpr (std::is_base_of_v<std::string, T>)
129 {
130 value = str;
131 return true;
132 }
133 // non-string or numeric, use stringstream >>
134 else
135 {
136 std::stringstream ss(trim(str));
137 if (!(ss >> value).fail() && ss.eof())
138 return true;
139 }
140 }
141
142 if (throw_on_failure)
143 {
144 std::string error = "Unable to convert '" + str + "' to type ";
145#ifdef MOOSESTRINGUTILS_NO_LIBMESH
146 error += typeid(T).name();
147#else
148 error += libMesh::demangle(typeid(T).name());
149#endif
150 throw std::invalid_argument(error);
151 }
152
153 return false;
154}
155
160template <typename T>
161bool
162tokenizeAndConvert(const std::string & str,
163 std::vector<T> & tokenized_vector,
164 const std::string & delimiter = " \t\n\v\f\r")
165{
166 std::vector<std::string> tokens;
167 MooseUtils::tokenize(str, tokens, 1, delimiter);
168 tokenized_vector.resize(tokens.size());
169 for (std::size_t i = 0; i < tokens.size(); ++i)
170 if (!convert<T>(tokens[i], tokenized_vector[i], false))
171 return false;
172 return true;
173}
174
179inline std::string
180toUpper(std::string name)
181{
182 std::transform(name.begin(), name.end(), name.begin(), ::toupper);
183 return name;
184}
185
190inline std::string
191toLower(std::string name)
192{
193 std::transform(name.begin(), name.end(), name.begin(), ::tolower);
194 return name;
195}
196
200inline std::string
201stringJoin(const std::vector<std::string> & values, const std::string & separator = " ")
202{
203 std::string combined;
204 for (const auto & value : values)
205 combined += value + separator;
206 if (values.size())
207 combined = combined.substr(0, combined.size() - separator.size());
208 return combined;
209}
210}
std::array< Real, 2 > values
Definition MortarUtils.C:52
bool convert(const std::string &str, T &value, const bool throw_on_failure)
Takes the string representation of a value and converts it to the value.
bool tokenizeAndConvert(const std::string &str, std::vector< T > &tokenized_vector, const std::string &delimiter=" \t\n\v\f\r")
tokenizeAndConvert splits a string using delimiter and then converts to type T.
std::string toUpper(std::string name)
Convert supplied string to upper case.
std::string toLower(std::string name)
Convert supplied string to lower case.
void tokenize(const std::string &str, std::vector< T > &elements, unsigned int min_len=1, const std::string &delims="/")
This function will split the passed in string on a set of delimiters appending the substrings to the ...
std::string trim(const std::string &str, const std::string &white_space=" \t\n\v\f\r")
Standard scripting language trim function.
std::string stringJoin(const std::vector< std::string > &values, const std::string &separator=" ")
Concatenates value into a single string separated by separator.
std::string demangle(const char *name)