Cantera  2.5.1
stringUtils.cpp
Go to the documentation of this file.
1 /**
2  * @file stringUtils.cpp
3  * Contains definitions for string manipulation functions
4  * within Cantera.
5  */
6 
7 // This file is part of Cantera. See License.txt in the top-level directory or
8 // at https://cantera.org/license.txt for license and copyright information.
9 
10 //@{
11 #include "cantera/base/ct_defs.h"
12 
13 #ifdef _MSC_VER
14 #define SNPRINTF _snprintf
15 #else
16 #define SNPRINTF snprintf
17 #endif
18 //@}
19 
22 #include "cantera/base/ctml.h"
23 #include "cantera/base/utilities.h"
24 
25 #include <boost/algorithm/string.hpp>
26 #include <sstream>
27 #include <cstdio>
28 
29 namespace ba = boost::algorithm;
30 
31 namespace Cantera
32 {
33 
34 std::string vec2str(const vector_fp& v, const std::string& fmt,
35  const std::string& sep)
36 {
37  char buf[64];
38  std::stringstream o;
39  for (size_t i = 0; i < v.size(); i++) {
40  SNPRINTF(buf, 63, fmt.c_str(), v[i]);
41  o << buf;
42  if (i != v.size() - 1) {
43  o << sep;
44  }
45  }
46  return o.str();
47 }
48 
49 std::string stripnonprint(const std::string& s)
50 {
51  std::string ss = "";
52  for (size_t i = 0; i < s.size(); i++) {
53  if (isprint(s[i])) {
54  ss += s[i];
55  }
56  }
57  return ss;
58 }
59 
60 compositionMap parseCompString(const std::string& ss,
61  const std::vector<std::string>& names)
62 {
64  for (size_t k = 0; k < names.size(); k++) {
65  x[names[k]] = 0.0;
66  }
67 
68  size_t start = 0;
69  size_t stop = 0;
70  size_t left = 0;
71  while (stop < ss.size()) {
72  size_t colon = ss.find(':', left);
73  if (colon == npos) {
74  break;
75  }
76  size_t valstart = ss.find_first_not_of(" \t\n", colon+1);
77  stop = ss.find_first_of(", ;\n\t", valstart);
78  std::string name = ba::trim_copy(ss.substr(start, colon-start));
79  if (!names.empty() && x.find(name) == x.end()) {
80  throw CanteraError("parseCompString",
81  "unknown species '" + name + "'");
82  }
83 
84  double value;
85  try {
86  value = fpValueCheck(ss.substr(valstart, stop-valstart));
87  } catch (CanteraError&) {
88  // If we have a key containing a colon, we expect this to fail. In
89  // this case, take the current substring as part of the key and look
90  // to the right of the next colon for the corresponding value.
91  // Otherwise, this is an invalid composition string.
92  std::string testname = ss.substr(start, stop-start);
93  if (testname.find_first_of(" \n\t") != npos) {
94  // Space, tab, and newline are never allowed in names
95  throw;
96  } else if (ss.substr(valstart, stop-valstart).find(':') != npos) {
97  left = colon + 1;
98  stop = 0; // Force another iteration of this loop
99  continue;
100  } else {
101  throw;
102  }
103  }
104  if (getValue(x, name, 0.0) != 0.0) {
105  throw CanteraError("parseCompString",
106  "Duplicate key: '" + name + "'.");
107  }
108 
109  x[name] = value;
110  start = ss.find_first_not_of(", ;\n\t", stop+1);
111  left = start;
112  }
113  if (left != start) {
114  throw CanteraError("parseCompString", "Unable to parse key-value pair:"
115  "\n'{}'", ss.substr(start, stop));
116  }
117  if (stop != npos && !ba::trim_copy(ss.substr(stop)).empty()) {
118  throw CanteraError("parseCompString", "Found non-key:value data "
119  "in composition string: '" + ss.substr(stop) + "'");
120  }
121  return x;
122 }
123 
124 int intValue(const std::string& val)
125 {
126  return std::atoi(ba::trim_copy(val).c_str());
127 }
128 
129 doublereal fpValue(const std::string& val)
130 {
131  doublereal rval;
132  std::stringstream ss(val);
133  ss.imbue(std::locale("C"));
134  ss >> rval;
135  return rval;
136 }
137 
138 doublereal fpValueCheck(const std::string& val)
139 {
140  std::string str = ba::trim_copy(val);
141  if (str.empty()) {
142  throw CanteraError("fpValueCheck", "string has zero length");
143  }
144  int numDot = 0;
145  int numExp = 0;
146  char ch;
147  int istart = 0;
148  ch = str[0];
149  if (ch == '+' || ch == '-') {
150  if (str.size() == 1) {
151  throw CanteraError("fpValueCheck", "string ends in '{}'", ch);
152  }
153  istart = 1;
154  }
155  for (size_t i = istart; i < str.size(); i++) {
156  ch = str[i];
157  if (isdigit(ch)) {
158  } else if (ch == '.') {
159  numDot++;
160  if (numDot > 1) {
161  throw CanteraError("fpValueCheck",
162  "string has more than one .");
163  }
164  if (numExp > 0) {
165  throw CanteraError("fpValueCheck",
166  "string has decimal point in exponent");
167  }
168  } else if (ch == 'e' || ch == 'E' || ch == 'd' || ch == 'D') {
169  numExp++;
170  str[i] = 'E';
171  if (numExp > 1) {
172  throw CanteraError("fpValueCheck",
173  "string has more than one exp char");
174  } else if (i == str.size() - 1) {
175  throw CanteraError("fpValueCheck",
176  "string ends in '{}'", ch);
177  }
178  ch = str[i+1];
179  if (ch == '+' || ch == '-') {
180  if (i + 1 == str.size() - 1) {
181  throw CanteraError("fpValueCheck",
182  "string ends in '{}'", ch);
183  }
184  i++;
185  }
186  } else {
187  throw CanteraError("fpValueCheck",
188  "Trouble processing string, " + str);
189  }
190  }
191  return fpValue(str);
192 }
193 
194 std::string parseSpeciesName(const std::string& nameStr, std::string& phaseName)
195 {
196  std::string s = ba::trim_copy(nameStr);
197  phaseName = "";
198  size_t ibegin = s.find_first_not_of(" ;\n\t");
199  if (ibegin != std::string::npos) {
200  s = s.substr(ibegin,s.size());
201  size_t icolon = s.find(':');
202  size_t iend = s.find_first_of(" ;\n\t");
203  if (icolon != std::string::npos) {
204  phaseName = s.substr(0, icolon);
205  s = s.substr(icolon+1, s.size());
206  icolon = s.find(':');
207  if (icolon != std::string::npos) {
208  throw CanteraError("parseSpeciesName",
209  "two colons in name: '{}'", nameStr);
210  }
211  }
212  if (iend != std::string::npos) {
213  throw CanteraError("parseSpeciesName", "Species name has "
214  "\" ;/\n/\t\" in the middle of it: '{}'", nameStr);
215  }
216  }
217  return s;
218 }
219 
220 doublereal strSItoDbl(const std::string& strSI)
221 {
222  std::vector<std::string> v;
223  tokenizeString(strSI, v);
224  doublereal fp = 1.0;
225  size_t n = v.size();
226  if (n > 2 || n < 1) {
227  throw CanteraError("strSItoDbl",
228  "number of tokens is too high");
229  } else if (n == 2) {
230  fp = toSI(v[1]);
231  }
232  doublereal val = fpValueCheck(v[0]);
233  return val * fp;
234 }
235 
236 void tokenizeString(const std::string& in_val, std::vector<std::string>& v)
237 {
238  std::string val = ba::trim_copy(in_val);
239  v.clear();
240  if (val.empty()) {
241  // In this case, prefer v to be empty instead of split's behavior of
242  // returning a vector with one element that is the empty string.
243  return;
244  }
245  ba::split(v, val, ba::is_space(), ba::token_compress_on);
246 }
247 
248 size_t copyString(const std::string& source, char* dest, size_t length)
249 {
250  const char* c_src = source.c_str();
251  size_t N = std::min(length, source.length()+1);
252  size_t ret = (length >= source.length() + 1) ? 0 : source.length() + 1;
253  std::copy(c_src, c_src + N, dest);
254  if (length != 0) {
255  dest[length-1] = '\0';
256  }
257  return ret;
258 }
259 
260 std::string trimCopy(const std::string &input) {
261  return ba::trim_copy(input);
262 }
263 
264 std::string toLowerCopy(const std::string &input) {
265  return ba::to_lower_copy(input);
266 }
267 
268 bool caseInsensitiveEquals(const std::string &input, const std::string &test) {
269  return ba::iequals(input, test);
270 }
271 
272 }
Cantera::trimCopy
std::string trimCopy(const std::string &input)
Trim.
Definition: stringUtils.cpp:260
Cantera::compositionMap
std::map< std::string, double > compositionMap
Map connecting a string name with a double.
Definition: ct_defs.h:172
ct_defs.h
Cantera::vec2str
std::string vec2str(const vector_fp &v, const std::string &fmt, const std::string &sep)
Convert a vector to a string (separated by commas)
Definition: stringUtils.cpp:34
Cantera::vector_fp
std::vector< double > vector_fp
Turn on the use of stl vectors for the basic array type within cantera Vector of doubles.
Definition: ct_defs.h:180
Cantera::getValue
const U & getValue(const std::map< T, U > &m, const T &key, const U &default_val)
Const accessor for a value in a std::map.
Definition: utilities.h:528
Cantera::toSI
doublereal toSI(const std::string &unit)
Return the conversion factor to convert unit std::string 'unit' to SI units.
Definition: global.cpp:140
Cantera::tokenizeString
void tokenizeString(const std::string &in_val, std::vector< std::string > &v)
This function separates a string up into tokens according to the location of white space.
Definition: stringUtils.cpp:236
Cantera::caseInsensitiveEquals
bool caseInsensitiveEquals(const std::string &input, const std::string &test)
Case insensitive equality predicate.
Definition: stringUtils.cpp:268
utilities.h
Cantera::copyString
size_t copyString(const std::string &source, char *dest, size_t length)
Copy the contents of a std::string into a char array of a given length.
Definition: stringUtils.cpp:248
ctml.h
Cantera::parseSpeciesName
std::string parseSpeciesName(const std::string &nameStr, std::string &phaseName)
Parse a name string, separating out the phase name from the species name.
Definition: stringUtils.cpp:194
stringUtils.h
Cantera::parseCompString
compositionMap parseCompString(const std::string &ss, const std::vector< std::string > &names)
Parse a composition string into a map consisting of individual key:composition pairs.
Definition: stringUtils.cpp:60
Cantera::intValue
int intValue(const std::string &val)
Translate a string into one integer value.
Definition: stringUtils.cpp:124
fmt
Versions 6.2.0 and 6.2.1 of fmtlib do not include this define before they include windows....
Definition: fmt.h:35
Cantera::toLowerCopy
std::string toLowerCopy(const std::string &input)
Convert to lower case.
Definition: stringUtils.cpp:264
Cantera::stripnonprint
std::string stripnonprint(const std::string &s)
Strip non-printing characters wherever they are.
Definition: stringUtils.cpp:49
Cantera::CanteraError
Base class for exceptions thrown by Cantera classes.
Definition: ctexceptions.h:60
Cantera::fpValueCheck
doublereal fpValueCheck(const std::string &val)
Translate a string into one doublereal value, with error checking.
Definition: stringUtils.cpp:138
Cantera::npos
const size_t npos
index returned by functions to indicate "no position"
Definition: ct_defs.h:188
ctexceptions.h
Cantera
Namespace for the Cantera kernel.
Definition: AnyMap.cpp:263
Cantera::fpValue
doublereal fpValue(const std::string &val)
Translate a string into one doublereal value.
Definition: stringUtils.cpp:129
Cantera::strSItoDbl
doublereal strSItoDbl(const std::string &strSI)
Interpret one or two token string as a single double.
Definition: stringUtils.cpp:220