| Cantera 3.0.0

Loading...
Searching...
No Matches
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
20#include "cantera/base/stringUtils.h"
21#include "cantera/base/ctexceptions.h"
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}
Cantera::CanteraError
Base class for exceptions thrown by Cantera classes.
Definition ctexceptions.h:66
ct_defs.h
This file contains definitions of constants, types and terms that are used in internal routines and a...
ctexceptions.h
Definitions for the classes that are thrown when Cantera experiences an error condition (also contain...
global.h
This file contains definitions for utility functions and text for modules, inputfiles and logging,...
Cantera::copyString
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.
Definition stringUtils.cpp:203
Cantera::caseInsensitiveEquals
bool caseInsensitiveEquals(const string &input, const string &test)
Case insensitive equality predicate.
Definition stringUtils.cpp:223
Cantera::stripnonprint
string stripnonprint(const string &s)
Strip non-printing characters wherever they are.
Definition stringUtils.cpp:47
Cantera::vec2str
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
Cantera::fpValue
double fpValue(const string &val)
Translate a string into one double value.
Definition stringUtils.cpp:121
Cantera::trimCopy
string trimCopy(const string &input)
Trim.
Definition stringUtils.cpp:215
Cantera::tokenizePath
void tokenizePath(const string &in_val, vector< string > &v)
This function separates a string up into tokens according to the location of path separators.
Definition stringUtils.cpp:196
Cantera::fpValueCheck
double fpValueCheck(const string &val)
Translate a string into one double value, with error checking.
Definition stringUtils.cpp:130
Cantera::toLowerCopy
string toLowerCopy(const string &input)
Convert to lower case.
Definition stringUtils.cpp:219
Cantera::parseCompString
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
Cantera::tokenizeString
void tokenizeString(const string &in_val, vector< string > &v)
This function separates a string up into tokens according to the location of white space.
Definition stringUtils.cpp:184
Cantera
Namespace for the Cantera kernel.
Definition AnyMap.cpp:564
Cantera::npos
const size_t npos
index returned by functions to indicate "no position"
Definition ct_defs.h:195
Cantera::getValue
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
Cantera::Composition
map< string, double > Composition
Map from string names to doubles.
Definition ct_defs.h:184
stringUtils.h
Contains declarations for string manipulation functions within Cantera.
utilities.h
Various templated functions that carry out common vector and polynomial operations (see Templated Arr...