Cantera  3.1.0a1
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/utilities.h"
23 #include "cantera/base/global.h"
24 
25 #include <boost/algorithm/string.hpp>
26 #include <sstream>
27 
28 namespace ba = boost::algorithm;
29 
30 namespace Cantera
31 {
32 
33 string vec2str(const vector<double>& v, const string& fmt, const string& sep)
34 {
35  char buf[64];
36  std::stringstream o;
37  for (size_t i = 0; i < v.size(); i++) {
38  SNPRINTF(buf, 63, fmt.c_str(), v[i]);
39  o << buf;
40  if (i != v.size() - 1) {
41  o << sep;
42  }
43  }
44  return o.str();
45 }
46 
47 string stripnonprint(const string& s)
48 {
49  string ss = "";
50  for (size_t i = 0; i < s.size(); i++) {
51  if (isprint(s[i])) {
52  ss += s[i];
53  }
54  }
55  return ss;
56 }
57 
58 Composition parseCompString(const string& ss, const vector<string>& names)
59 {
60  Composition x;
61  for (size_t k = 0; k < names.size(); k++) {
62  x[names[k]] = 0.0;
63  }
64 
65  size_t start = 0;
66  size_t stop = 0;
67  size_t left = 0;
68  while (stop < ss.size()) {
69  size_t colon = ss.find(':', left);
70  if (colon == npos) {
71  break;
72  }
73  size_t valstart = ss.find_first_not_of(" \t\n", colon+1);
74  stop = ss.find_first_of(", ;\n\t", valstart);
75  string name = ba::trim_copy(ss.substr(start, colon-start));
76  if (!names.empty() && x.find(name) == x.end()) {
77  throw CanteraError("parseCompString",
78  "unknown species '" + name + "'");
79  }
80 
81  double value;
82  try {
83  value = fpValueCheck(ss.substr(valstart, stop-valstart));
84  } catch (CanteraError&) {
85  // If we have a key containing a colon, we expect this to fail. In
86  // this case, take the current substring as part of the key and look
87  // to the right of the next colon for the corresponding value.
88  // Otherwise, this is an invalid composition string.
89  string testname = ss.substr(start, stop-start);
90  if (testname.find_first_of(" \n\t") != npos) {
91  // Space, tab, and newline are never allowed in names
92  throw;
93  } else if (ss.substr(valstart, stop-valstart).find(':') != npos) {
94  left = colon + 1;
95  stop = 0; // Force another iteration of this loop
96  continue;
97  } else {
98  throw;
99  }
100  }
101  if (getValue(x, name, 0.0) != 0.0) {
102  throw CanteraError("parseCompString",
103  "Duplicate key: '" + name + "'.");
104  }
105 
106  x[name] = value;
107  start = ss.find_first_not_of(", ;\n\t", stop+1);
108  left = start;
109  }
110  if (left != start) {
111  throw CanteraError("parseCompString", "Unable to parse key-value pair:"
112  "\n'{}'", ss.substr(start, stop));
113  }
114  if (stop != npos && !ba::trim_copy(ss.substr(stop)).empty()) {
115  throw CanteraError("parseCompString", "Found non-key:value data "
116  "in composition string: '" + ss.substr(stop) + "'");
117  }
118  return x;
119 }
120 
121 double fpValue(const string& val)
122 {
123  double rval;
124  std::stringstream ss(val);
125  ss.imbue(std::locale("C"));
126  ss >> rval;
127  return rval;
128 }
129 
130 double fpValueCheck(const string& val)
131 {
132  string str = ba::trim_copy(val);
133  if (str.empty()) {
134  throw CanteraError("fpValueCheck", "string has zero length");
135  }
136  int numDot = 0;
137  int numExp = 0;
138  char ch;
139  int istart = 0;
140  ch = str[0];
141  if (ch == '+' || ch == '-') {
142  if (str.size() == 1) {
143  throw CanteraError("fpValueCheck", "string '{}' ends in '{}'", val, ch);
144  }
145  istart = 1;
146  }
147  for (size_t i = istart; i < str.size(); i++) {
148  ch = str[i];
149  if (isdigit(ch)) {
150  } else if (ch == '.') {
151  numDot++;
152  if (numDot > 1) {
153  throw CanteraError("fpValueCheck",
154  "string '{}' has more than one decimal point.", val);
155  }
156  if (numExp > 0) {
157  throw CanteraError("fpValueCheck",
158  "string '{}' has decimal point in exponent", val);
159  }
160  } else if (ch == 'e' || ch == 'E' || ch == 'd' || ch == 'D') {
161  numExp++;
162  str[i] = 'E';
163  if (numExp > 1) {
164  throw CanteraError("fpValueCheck",
165  "string '{}' has more than one exp char", val);
166  } else if (i == str.size() - 1) {
167  throw CanteraError("fpValueCheck", "string '{}' ends in '{}'", val, ch);
168  }
169  ch = str[i+1];
170  if (ch == '+' || ch == '-') {
171  if (i + 1 == str.size() - 1) {
172  throw CanteraError("fpValueCheck",
173  "string '{}' ends in '{}'", val, ch);
174  }
175  i++;
176  }
177  } else {
178  throw CanteraError("fpValueCheck", "Trouble processing string '{}'", str);
179  }
180  }
181  return fpValue(str);
182 }
183 
184 void tokenizeString(const string& in_val, vector<string>& v)
185 {
186  string val = ba::trim_copy(in_val);
187  v.clear();
188  if (val.empty()) {
189  // In this case, prefer v to be empty instead of split's behavior of
190  // returning a vector with one element that is the empty string.
191  return;
192  }
193  ba::split(v, val, ba::is_space(), ba::token_compress_on);
194 }
195 
196 void tokenizePath(const string& in_val, vector<string>& v)
197 {
198  string val = ba::trim_copy(in_val);
199  v.clear();
200  ba::split(v, val, ba::is_any_of("/\\"), ba::token_compress_on);
201 }
202 
203 size_t copyString(const string& source, char* dest, size_t length)
204 {
205  const char* c_src = source.c_str();
206  size_t N = std::min(length, source.length()+1);
207  size_t ret = (length >= source.length() + 1) ? 0 : source.length() + 1;
208  std::copy(c_src, c_src + N, dest);
209  if (length != 0) {
210  dest[length-1] = '\0';
211  }
212  return ret;
213 }
214 
215 string trimCopy(const string &input) {
216  return ba::trim_copy(input);
217 }
218 
219 string toLowerCopy(const string &input) {
220  return ba::to_lower_copy(input);
221 }
222 
223 bool caseInsensitiveEquals(const string &input, const string &test) {
224  return ba::iequals(input, test);
225 }
226 
227 }
Base class for exceptions thrown by Cantera classes.
Definition: ctexceptions.h:66
This file contains definitions of constants, types and terms that are used in internal routines and a...
Definitions for the classes that are thrown when Cantera experiences an error condition (also contain...
This file contains definitions for utility functions and text for modules, inputfiles and logging,...
size_t copyString(const string &source, char *dest, size_t length)
Copy the contents of a string into a char array of a given length.
bool caseInsensitiveEquals(const string &input, const string &test)
Case insensitive equality predicate.
string stripnonprint(const string &s)
Strip non-printing characters wherever they are.
Definition: stringUtils.cpp:47
string vec2str(const vector< double > &v, const string &fmt, const string &sep)
Convert a vector to a string (separated by commas)
Definition: stringUtils.cpp:33
double fpValue(const string &val)
Translate a string into one double value.
string trimCopy(const string &input)
Trim.
void tokenizePath(const string &in_val, vector< string > &v)
This function separates a string up into tokens according to the location of path separators.
double fpValueCheck(const string &val)
Translate a string into one double value, with error checking.
string toLowerCopy(const string &input)
Convert to lower case.
Composition parseCompString(const string &ss, const vector< string > &names)
Parse a composition string into a map consisting of individual key:composition pairs.
Definition: stringUtils.cpp:58
void tokenizeString(const string &in_val, vector< string > &v)
This function separates a string up into tokens according to the location of white space.
Namespace for the Cantera kernel.
Definition: AnyMap.cpp:564
const size_t npos
index returned by functions to indicate "no position"
Definition: ct_defs.h:180
const U & getValue(const map< T, U > &m, const T &key, const U &default_val)
Const accessor for a value in a map.
Definition: utilities.h:190
map< string, double > Composition
Map from string names to doubles.
Definition: ct_defs.h:177
Contains declarations for string manipulation functions within Cantera.
Various templated functions that carry out common vector and polynomial operations (see Templated Arr...