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