Cantera  2.3.0
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 http://www.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 fp2str(const double x, const std::string& fmt)
35 {
36  warn_deprecated("fp2str", "Unused. To be removed after Cantera 2.3. "
37  "Use fmt::format instead.");
38  char buf[64];
39  int n = SNPRINTF(buf, 63, fmt.c_str(), x);
40  if (n > 0) {
41  buf[63] = '\0';
42  return std::string(buf);
43  }
44  return std::string(" ");
45 }
46 
47 std::string int2str(const int n, const std::string& fmt)
48 {
49  warn_deprecated("int2str", "Unused. To be removed after Cantera 2.3. "
50  "Use fmt::format instead.");
51  char buf[30];
52  int m = SNPRINTF(buf, 30, fmt.c_str(), n);
53  if (m > 0) {
54  buf[29] = '\0';
55  return std::string(buf);
56  }
57  return std::string(" ");
58 }
59 
60 std::string int2str(const size_t n)
61 {
62  warn_deprecated("int2str", "Unused. To be removed after Cantera 2.3. "
63  "Use fmt::format instead.");
64  std::stringstream ss;
65  ss << n;
66  return ss.str();
67 }
68 
69 std::string vec2str(const vector_fp& v, const std::string& fmt,
70  const std::string& sep)
71 {
72  char buf[64];
73  std::stringstream o;
74  for (size_t i = 0; i < v.size(); i++) {
75  SNPRINTF(buf, 63, fmt.c_str(), v[i]);
76  o << buf;
77  if (i != v.size() - 1) {
78  o << sep;
79  }
80  }
81  return o.str();
82 }
83 
84 
85 std::string lowercase(const std::string& s)
86 {
87  warn_deprecated("lowercase", "Use boost::algorithm::to_lower_copy instead. "
88  "To be removed after Cantera 2.3.");
89  std::string lc(s);
90  for (size_t i = 0; i < s.size(); i++) {
91  lc[i] = (char) tolower(s[i]);
92  }
93  return lc;
94 }
95 
96 std::string stripws(const std::string& s)
97 {
98  warn_deprecated("stripws", "Use boost::algorithm::trim_copy instead. "
99  "To be removed after Cantera 2.3.");
100  return ba::trim_copy(s);
101 }
102 
103 std::string stripnonprint(const std::string& s)
104 {
105  std::string ss = "";
106  for (size_t i = 0; i < s.size(); i++) {
107  if (isprint(s[i])) {
108  ss += s[i];
109  }
110  }
111  return ss;
112 }
113 
114 compositionMap parseCompString(const std::string& ss,
115  const std::vector<std::string>& names)
116 {
117  compositionMap x;
118  for (size_t k = 0; k < names.size(); k++) {
119  x[names[k]] = 0.0;
120  }
121 
122  size_t start = 0;
123  size_t stop = 0;
124  size_t left = 0;
125  while (stop < ss.size()) {
126  size_t colon = ss.find(':', left);
127  if (colon == npos) {
128  break;
129  }
130  size_t valstart = ss.find_first_not_of(" \t\n", colon+1);
131  stop = ss.find_first_of(", ;\n\t", valstart);
132  std::string name = ba::trim_copy(ss.substr(start, colon-start));
133  if (!names.empty() && x.find(name) == x.end()) {
134  throw CanteraError("parseCompString",
135  "unknown species '" + name + "'");
136  }
137  if (getValue(x, name, 0.0) != 0.0) {
138  throw CanteraError("parseCompString",
139  "Duplicate key: '" + name + "'.");
140  }
141 
142  double value;
143  try {
144  value = fpValueCheck(ss.substr(valstart, stop-colon-1));
145  } catch (CanteraError& err) {
146  // If we have a key containing a colon, we expect this to fail. In
147  // this case, take the current substring as part of the key and look
148  // to the right of the next colon for the corresponding value.
149  // Otherwise, this is an invalid composition string.
150  std::string testname = ss.substr(start, stop-colon-1);
151  if (testname.find_first_of(" \n\t") != npos) {
152  // Space, tab, and newline are never allowed in names
153  throw;
154  } else if (ss.substr(valstart, stop-colon-1).find(':') != npos) {
155  left = colon + 1;
156  stop = 0; // Force another iteration of this loop
157  continue;
158  } else {
159  throw;
160  }
161  }
162  x[name] = value;
163  start = ss.find_first_not_of(", ;\n\t", stop+1);
164  left = start;
165  }
166  if (left != start) {
167  throw CanteraError("parseCompString", "Unable to parse key-value pair:"
168  "\n'{}'", ss.substr(start, stop));
169  }
170  if (stop != npos && !ba::trim_copy(ss.substr(stop)).empty()) {
171  throw CanteraError("parseCompString", "Found non-key:value data "
172  "in composition string: '" + ss.substr(stop) + "'");
173  }
174  return x;
175 }
176 
177 int intValue(const std::string& val)
178 {
179  return std::atoi(ba::trim_copy(val).c_str());
180 }
181 
182 doublereal fpValue(const std::string& val)
183 {
184  doublereal rval;
185  std::stringstream ss(val);
186  ss.imbue(std::locale("C"));
187  ss >> rval;
188  return rval;
189 }
190 
191 doublereal fpValueCheck(const std::string& val)
192 {
193  std::string str = ba::trim_copy(val);
194  if (str.empty()) {
195  throw CanteraError("fpValueCheck", "string has zero length");
196  }
197  int numDot = 0;
198  int numExp = 0;
199  char ch;
200  int istart = 0;
201  ch = str[0];
202  if (ch == '+' || ch == '-') {
203  istart = 1;
204  }
205  for (size_t i = istart; i < str.size(); i++) {
206  ch = str[i];
207  if (isdigit(ch)) {
208  } else if (ch == '.') {
209  numDot++;
210  if (numDot > 1) {
211  throw CanteraError("fpValueCheck",
212  "string has more than one .");
213  }
214  if (numExp > 0) {
215  throw CanteraError("fpValueCheck",
216  "string has decimal point in exponent");
217  }
218  } else if (ch == 'e' || ch == 'E' || ch == 'd' || ch == 'D') {
219  numExp++;
220  str[i] = 'E';
221  if (numExp > 1) {
222  throw CanteraError("fpValueCheck",
223  "string has more than one exp char");
224  }
225  ch = str[i+1];
226  if (ch == '+' || ch == '-') {
227  i++;
228  }
229  } else {
230  throw CanteraError("fpValueCheck",
231  "Trouble processing string, " + str);
232  }
233  }
234  return fpValue(str);
235 }
236 
237 std::string wrapString(const std::string& s, const int len)
238 {
239  warn_deprecated("wrapString", "Unused. To be removed after Cantera 2.3.");
240  int count=0;
241  std::string r;
242  for (size_t n = 0; n < s.size(); n++) {
243  if (s[n] == '\n') {
244  count = 0;
245  } else {
246  count++;
247  }
248  if (count > len && s[n] == ' ') {
249  r += "\n ";
250  count = 0;
251  }
252  r += s[n];
253  }
254  return r;
255 }
256 
257 std::string parseSpeciesName(const std::string& nameStr, std::string& phaseName)
258 {
259  std::string s = ba::trim_copy(nameStr);
260  phaseName = "";
261  size_t ibegin = s.find_first_not_of(" ;\n\t");
262  if (ibegin != std::string::npos) {
263  s = s.substr(ibegin,s.size());
264  size_t icolon = s.find(':');
265  size_t iend = s.find_first_of(" ;\n\t");
266  if (icolon != std::string::npos) {
267  phaseName = s.substr(0, icolon);
268  s = s.substr(icolon+1, s.size());
269  icolon = s.find(':');
270  if (icolon != std::string::npos) {
271  throw CanteraError("parseSpeciesName()", "two colons in name: " + nameStr);
272  }
273  }
274  if (iend != std::string::npos) {
275  throw CanteraError("parseSpeciesName()",
276  "Species name has \" ;/\n/\t\" in the middle of it: " + nameStr);
277  }
278  }
279  return s;
280 }
281 
282 doublereal strSItoDbl(const std::string& strSI)
283 {
284  std::vector<std::string> v;
285  tokenizeString(strSI, v);
286  doublereal fp = 1.0;
287  size_t n = v.size();
288  if (n > 2 || n < 1) {
289  throw CanteraError("strSItoDbl",
290  "number of tokens is too high");
291  } else if (n == 2) {
292  fp = toSI(v[1]);
293  }
294  doublereal val = fpValueCheck(v[0]);
295  return val * fp;
296 }
297 
298 void tokenizeString(const std::string& in_val, std::vector<std::string>& v)
299 {
300  std::string val = ba::trim_copy(in_val);
301  v.clear();
302  if (val.empty()) {
303  // In this case, prefer v to be empty instead of split's behavior of
304  // returning a vector with one element that is the empty string.
305  return;
306  }
307  ba::split(v, val, ba::is_space(), ba::token_compress_on);
308 }
309 
310 size_t copyString(const std::string& source, char* dest, size_t length)
311 {
312  const char* c_src = source.c_str();
313  size_t N = std::min(length, source.length()+1);
314  size_t ret = (length >= source.length() + 1) ? 0 : source.length() + 1;
315  std::copy(c_src, c_src + N, dest);
316  if (length != 0) {
317  dest[length-1] = '\0';
318  }
319  return ret;
320 }
321 
322 }
std::map< std::string, doublereal > compositionMap
Map connecting a string name with a double.
Definition: ct_defs.h:149
doublereal fpValue(const std::string &val)
Translate a string into one doublereal value.
std::string int2str(const int n, const std::string &fmt)
Convert an int to a string using a format converter.
Definition: stringUtils.cpp:47
CTML ("Cantera Markup Language") is the variant of XML that Cantera uses to store data...
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:69
Various templated functions that carry out common vector operations (see Templated Utility Functions)...
doublereal toSI(const std::string &unit)
Return the conversion factor to convert unit std::string &#39;unit&#39; to SI units.
Definition: global.cpp:160
const size_t npos
index returned by functions to indicate "no position"
Definition: ct_defs.h:165
This file contains definitions of terms that are used in internal routines and are unlikely to need m...
void warn_deprecated(const std::string &method, const std::string &extra)
Print a warning indicating that method is deprecated.
Definition: global.cpp:54
std::string lowercase(const std::string &s)
Cast a copy of a string to lower case.
Definition: stringUtils.cpp:85
std::string stripws(const std::string &s)
Strip the leading and trailing white space from a string.
Definition: stringUtils.cpp:96
std::string fp2str(const double x, const std::string &fmt)
Convert a double into a c++ string.
Definition: stringUtils.cpp:34
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...
Base class for exceptions thrown by Cantera classes.
Definition: ctexceptions.h:65
const U & getValue(const std::map< T, U > &m, const T &key)
Const accessor for a value in a std::map.
Definition: utilities.h:537
std::string parseSpeciesName(const std::string &nameStr, std::string &phaseName)
Parse a name string, separating out the phase name from the species name.
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.
std::string wrapString(const std::string &s, const int len)
Line wrap a string via a copy operation.
int intValue(const std::string &val)
Translate a string into one integer value.
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.
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:157
Contains declarations for string manipulation functions within Cantera.
Namespace for the Cantera kernel.
Definition: application.cpp:29
doublereal strSItoDbl(const std::string &strSI)
Interpret one or two token string as a single double.
std::string stripnonprint(const std::string &s)
Strip non-printing characters wherever they are.
doublereal fpValueCheck(const std::string &val)
Translate a string into one doublereal value, with error checking.
Definitions for the classes that are thrown when Cantera experiences an error condition (also contain...