https://mooseframework.inl.gov
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 #include "libmesh/int_range.h"
18 #include "libmesh/libmesh_common.h"
19 
20 /*
21  * This must stay a header-only utility! It is used in the capabilities python module and
22  * we do not want to link against any MOOSE libs.
23  */
24 namespace MooseUtils
25 {
29 inline std::string
30 trim(const std::string & str, const std::string & white_space = " \t\n\v\f\r")
31 {
32  const auto begin = str.find_first_not_of(white_space);
33  if (begin == std::string::npos)
34  return ""; // no content
35  const auto end = str.find_last_not_of(white_space);
36  return str.substr(begin, end - begin + 1);
37 }
38 
45 template <typename T>
46 void
47 tokenize(const std::string & str,
48  std::vector<T> & elements,
49  unsigned int min_len = 1,
50  const std::string & delims = "/")
51 {
52  elements.clear();
53 
54  std::string::size_type last_pos = str.find_first_not_of(delims, 0);
55  std::string::size_type pos = str.find_first_of(delims, std::min(last_pos + min_len, str.size()));
56 
57  while (last_pos != std::string::npos)
58  {
59  elements.push_back(str.substr(last_pos, pos - last_pos));
60  // skip delims between tokens
61  last_pos = str.find_first_not_of(delims, pos);
62  if (last_pos == std::string::npos)
63  break;
64  pos = str.find_first_of(delims, std::min(last_pos + min_len, str.size()));
65  }
66 }
67 
86 template <class T>
87 bool
88 convert(const std::string & str, T & value, const bool throw_on_failure)
89 {
90  // Special case for numeric values, also handling range checking
91  if constexpr (std::is_same_v<short int, T> || std::is_same_v<unsigned short int, T> ||
92  std::is_same_v<int, T> || std::is_same_v<unsigned int, T> ||
93  std::is_same_v<long int, T> || std::is_same_v<unsigned long int, T> ||
94  std::is_same_v<long long int, T> || std::is_same_v<unsigned long long int, T>)
95  {
96  // Try read a double and try to cast it to an int
97  long double double_val;
98  std::stringstream double_ss(str);
99  double_ss >> double_val;
100 
101  if (!double_ss.fail() && double_ss.eof())
102  {
103  // on arm64 the long double does not have sufficient precision
104  std::stringstream int_ss(str);
105  const bool use_int = !(int_ss >> value).fail() && int_ss.eof();
106 
107  // Check to see if it's an integer and thus within range of an integer
108  if (double_val == static_cast<long double>(static_cast<T>(double_val)))
109  {
110  if (!use_int)
111  value = static_cast<T>(double_val);
112  return true;
113  }
114  }
115  }
116  // Non numeric values
117  else
118  {
119  // string or derived string: direct copy
120  if constexpr (std::is_base_of_v<std::string, T>)
121  {
122  value = str;
123  return true;
124  }
125  // non-string or numeric, use stringstream >>
126  else
127  {
128  std::stringstream ss(trim(str));
129  if (!(ss >> value).fail() && ss.eof())
130  return true;
131  }
132  }
133 
134  if (throw_on_failure)
135  throw std::invalid_argument("Unable to convert '" + str + "' to type " +
136  libMesh::demangle(typeid(T).name()));
137  return false;
138 }
143 template <typename T>
144 bool
145 tokenizeAndConvert(const std::string & str,
146  std::vector<T> & tokenized_vector,
147  const std::string & delimiter = " \t\n\v\f\r")
148 {
149  std::vector<std::string> tokens;
150  MooseUtils::tokenize(str, tokens, 1, delimiter);
151  tokenized_vector.resize(tokens.size());
152  for (const auto i : libMesh::index_range(tokens))
153  if (!convert<T>(tokens[i], tokenized_vector[i], false))
154  return false;
155  return true;
156 }
157 
162 inline std::string
163 toUpper(std::string name)
164 {
165  std::transform(name.begin(), name.end(), name.begin(), ::toupper);
166  return name;
167 }
168 
173 inline std::string
174 toLower(std::string name)
175 {
176  std::transform(name.begin(), name.end(), name.begin(), ::tolower);
177  return name;
178 }
179 }
std::string name(const ElemQuality q)
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 ...
bool tokenizeAndConvert(const std::string &str, std::vector< T > &tokenized_vector, const std::string &delimiter=" \\\)
tokenizeAndConvert splits a string using delimiter and then converts to type T.
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.
std::string toUpper(std::string name)
Convert supplied string to upper case.
Real value(unsigned n, unsigned alpha, unsigned beta, Real x)
std::string trim(const std::string &str, const std::string &white_space=" \\\)
Standard scripting language trim function.
std::string toLower(std::string name)
Convert supplied string to lower case.
std::string demangle(const char *name)
charT const * delimiter
Definition: InfixIterator.h:34
auto min(const L &left, const R &right)
auto index_range(const T &sizable)