Fixed locale-dependent processing of XML files
Floating point values are read using a std::stringstream imbued with the "C" locale to avoid problems with using std::atof when the user's locale uses a character other than "." as the decimal separator. Patch provided by Phillip Berndt. Fixes Issue 153.
This commit is contained in:
parent
00a4e04ce0
commit
7b7d3ac0d4
9 changed files with 50 additions and 40 deletions
|
|
@ -633,7 +633,7 @@ void getFloats(const Cantera::XML_Node& node, std::map<std::string, double>& v,
|
|||
std::string typ, title, units, vmin, vmax;
|
||||
for (int i = 0; i < n; i++) {
|
||||
const XML_Node& fi = *(f[i]);
|
||||
x = atof(fi().c_str());
|
||||
x = fpValue(fi());
|
||||
x0 = Undef;
|
||||
x1 = Undef;
|
||||
typ = fi["type"];
|
||||
|
|
@ -642,14 +642,14 @@ void getFloats(const Cantera::XML_Node& node, std::map<std::string, double>& v,
|
|||
vmin = fi["min"];
|
||||
vmax = fi["max"];
|
||||
if (vmin != "") {
|
||||
x0 = atof(vmin.c_str());
|
||||
x0 = fpValue(vmin);
|
||||
if (x < x0 - Tiny) {
|
||||
writelog("\nWarning: value "+fi()+" is below lower limit of "
|
||||
+vmin+".\n");
|
||||
}
|
||||
}
|
||||
if (fi["max"] != "") {
|
||||
x1 = atof(vmax.c_str());
|
||||
x1 = fpValue(vmax);
|
||||
if (x > x1 + Tiny) {
|
||||
writelog("\nWarning: value "+fi()+" is above upper limit of "
|
||||
+vmax+".\n");
|
||||
|
|
@ -744,21 +744,21 @@ doublereal getFloatCurrent(const Cantera::XML_Node& node,
|
|||
{
|
||||
doublereal x, x0, x1, fctr = 1.0;
|
||||
string units, vmin, vmax;
|
||||
x = atof(node().c_str());
|
||||
x = fpValue(node());
|
||||
x0 = Undef;
|
||||
x1 = Undef;
|
||||
units = node["units"];
|
||||
vmin = node["min"];
|
||||
vmax = node["max"];
|
||||
if (vmin != "") {
|
||||
x0 = atof(vmin.c_str());
|
||||
x0 = fpValue(vmin);
|
||||
if (x < x0 - Tiny) {
|
||||
writelog("\nWarning: value "+node()+" is below lower limit of "
|
||||
+vmin+".\n");
|
||||
}
|
||||
}
|
||||
if (node["max"] != "") {
|
||||
x1 = atof(vmax.c_str());
|
||||
x1 = fpValue(vmax);
|
||||
if (x > x1 + Tiny) {
|
||||
writelog("\nWarning: value "+node()+" is above upper limit of "
|
||||
+vmax+".\n");
|
||||
|
|
@ -1076,10 +1076,10 @@ size_t getFloatArray(const Cantera::XML_Node& node, std::vector<doublereal> & v,
|
|||
}
|
||||
|
||||
if ((*readNode)["min"] != "") {
|
||||
vmin = atofCheck((*readNode)["min"].c_str());
|
||||
vmin = fpValueCheck((*readNode)["min"]);
|
||||
}
|
||||
if ((*readNode)["max"] != "") {
|
||||
vmax = atofCheck((*readNode)["max"].c_str());
|
||||
vmax = fpValueCheck((*readNode)["max"]);
|
||||
}
|
||||
|
||||
doublereal vv;
|
||||
|
|
@ -1089,7 +1089,7 @@ size_t getFloatArray(const Cantera::XML_Node& node, std::vector<doublereal> & v,
|
|||
if (icom != string::npos) {
|
||||
numstr = val.substr(0,icom);
|
||||
val = val.substr(icom+1,val.size());
|
||||
dtmp = atofCheck(numstr.c_str());
|
||||
dtmp = fpValueCheck(numstr);
|
||||
v.push_back(dtmp);
|
||||
} else {
|
||||
/*
|
||||
|
|
@ -1101,7 +1101,7 @@ size_t getFloatArray(const Cantera::XML_Node& node, std::vector<doublereal> & v,
|
|||
* possibility in for backwards compatibility.
|
||||
*/
|
||||
if (!val.empty()) {
|
||||
dtmp = atofCheck(val.c_str());
|
||||
dtmp = fpValueCheck(val);
|
||||
v.push_back(dtmp);
|
||||
}
|
||||
break;
|
||||
|
|
@ -1152,10 +1152,10 @@ int getNamedFloatArray(const Cantera::XML_Node& parentNode, const std::string&
|
|||
}
|
||||
|
||||
if ((*readNode)["min"] != "") {
|
||||
vmin = atofCheck((*readNode)["min"].c_str());
|
||||
vmin = fpValueCheck((*readNode)["min"]);
|
||||
}
|
||||
if ((*readNode)["max"] != "") {
|
||||
vmax = atofCheck((*readNode)["max"].c_str());
|
||||
vmax = fpValueCheck((*readNode)["max"]);
|
||||
}
|
||||
|
||||
int expectedSize = 0;
|
||||
|
|
@ -1176,7 +1176,7 @@ int getNamedFloatArray(const Cantera::XML_Node& parentNode, const std::string&
|
|||
if (icom != string::npos) {
|
||||
numstr = val.substr(0,icom);
|
||||
val = val.substr(icom+1,val.size());
|
||||
dtmp = atofCheck(numstr.c_str());
|
||||
dtmp = fpValueCheck(numstr);
|
||||
v.push_back(dtmp);
|
||||
} else {
|
||||
/*
|
||||
|
|
@ -1189,7 +1189,7 @@ int getNamedFloatArray(const Cantera::XML_Node& parentNode, const std::string&
|
|||
*/
|
||||
int nlen = strlen(val.c_str());
|
||||
if (nlen > 0) {
|
||||
dtmp = atofCheck(val.c_str());
|
||||
dtmp = fpValueCheck(val);
|
||||
v.push_back(dtmp);
|
||||
}
|
||||
break;
|
||||
|
|
@ -1425,7 +1425,7 @@ void getMatrixValues(const Cantera::XML_Node& node,
|
|||
throw CanteraError("getMatrixValues","Col not matched by string: "
|
||||
+ key2);
|
||||
}
|
||||
double dval = atofCheck(val.c_str());
|
||||
double dval = fpValueCheck(val);
|
||||
dval *= funit;
|
||||
/*
|
||||
* Finally, insert the value;
|
||||
|
|
|
|||
|
|
@ -214,7 +214,7 @@ compositionMap parseCompString(const std::string& ss,
|
|||
throw CanteraError("parseCompString",
|
||||
"unknown species " + name);
|
||||
}
|
||||
x[name] = atof(num.c_str());
|
||||
x[name] = fpValue(num);
|
||||
} else {
|
||||
s = "";
|
||||
}
|
||||
|
|
@ -306,7 +306,11 @@ int intValue(const std::string& val)
|
|||
//================================================================================================
|
||||
doublereal fpValue(const std::string& val)
|
||||
{
|
||||
return std::atof(stripws(val).c_str());
|
||||
doublereal rval;
|
||||
std::stringstream ss(val);
|
||||
ss.imbue(std::locale("C"));
|
||||
ss >> rval;
|
||||
return rval;
|
||||
}
|
||||
//================================================================================================
|
||||
doublereal fpValueCheck(const std::string& val)
|
||||
|
|
@ -453,12 +457,12 @@ int stripLTWScstring(char str[])
|
|||
//================================================================================================
|
||||
// Translate a char string into a single double
|
||||
/*
|
||||
* atofCheck is a wrapper around the C stdlib routine atof().
|
||||
* It does quite a bit more error checking than atof() or
|
||||
* atofCheck is a wrapper around the C++ stdlib stringstream double parser.
|
||||
* It does quite a bit more error checking than atofCheck() or
|
||||
* strtod(), and is quite a bit more restrictive.
|
||||
*
|
||||
* First it interprets both E, e, d, and D as exponents.
|
||||
* atof() only interprets e or E as an exponent character.
|
||||
* stringstreams only interpret e or E as an exponent character.
|
||||
*
|
||||
* It only accepts a string as well formed if it consists as a
|
||||
* single token. Multiple words will produce an error message
|
||||
|
|
@ -470,6 +474,9 @@ int stripLTWScstring(char str[])
|
|||
*
|
||||
* It does not accept hexadecimal numbers.
|
||||
*
|
||||
* It does always use the C locale, regardless of any locale
|
||||
* settings.
|
||||
*
|
||||
* @param dptr pointer to the input c string
|
||||
* @return Returns the double
|
||||
*
|
||||
|
|
@ -523,7 +530,10 @@ doublereal atofCheck(const char* const dptr)
|
|||
"Trouble processing string, " + hh);
|
||||
}
|
||||
}
|
||||
doublereal rval = atof(eptr);
|
||||
doublereal rval;
|
||||
std::stringstream ss(eptr);
|
||||
ss.imbue(std::locale("C"));
|
||||
ss >> rval;
|
||||
free(eptr);
|
||||
return rval;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -661,7 +661,7 @@ std::string XML_Node::operator()() const
|
|||
*/
|
||||
doublereal XML_Node::fp_value() const
|
||||
{
|
||||
return atofCheck(m_value.c_str());
|
||||
return fpValueCheck(m_value);
|
||||
}
|
||||
|
||||
// Return the value of an XML node as a single int
|
||||
|
|
|
|||
|
|
@ -236,7 +236,7 @@ bool getReagents(const XML_Node& rxn, Kinetics& kin, int rp,
|
|||
* specified species.
|
||||
*/
|
||||
spnum.push_back(isp);
|
||||
stch = atof(val[n].c_str());
|
||||
stch = fpValue(val[n]);
|
||||
stoich.push_back(stch);
|
||||
ord = doublereal(stch);
|
||||
order.push_back(ord);
|
||||
|
|
|
|||
|
|
@ -392,7 +392,7 @@ addElement(const std::string& symbol, doublereal weight)
|
|||
void Elements::
|
||||
addElement(const XML_Node& e)
|
||||
{
|
||||
doublereal weight = atof(e["atomicWt"].c_str());
|
||||
doublereal weight = fpValue(e["atomicWt"]);
|
||||
string symbol = e["name"];
|
||||
addElement(symbol, weight);
|
||||
}
|
||||
|
|
@ -467,7 +467,7 @@ addUniqueElement(const XML_Node& e)
|
|||
{
|
||||
doublereal weight = 0.0;
|
||||
if (e.hasAttrib("atomicWt")) {
|
||||
weight = atof(stripws(e["atomicWt"]).c_str());
|
||||
weight = fpValue(stripws(e["atomicWt"]));
|
||||
}
|
||||
int anum = 0;
|
||||
if (e.hasAttrib("atomicNumber")) {
|
||||
|
|
@ -478,7 +478,7 @@ addUniqueElement(const XML_Node& e)
|
|||
if (e.hasChild("entropy298")) {
|
||||
XML_Node& e298Node = e.child("entropy298");
|
||||
if (e298Node.hasAttrib("value")) {
|
||||
entropy298 = atofCheck(stripws(e298Node["value"]).c_str());
|
||||
entropy298 = fpValueCheck(stripws(e298Node["value"]));
|
||||
}
|
||||
}
|
||||
if (weight != 0.0) {
|
||||
|
|
|
|||
|
|
@ -243,12 +243,12 @@ void HMWSoln::readXMLBinarySalt(XML_Node& BinSalt)
|
|||
|
||||
if (nodeName == "alpha1") {
|
||||
stemp = xmlChild.value();
|
||||
m_Alpha1MX_ij[counter] = atofCheck(stemp.c_str());
|
||||
m_Alpha1MX_ij[counter] = fpValueCheck(stemp);
|
||||
}
|
||||
|
||||
if (nodeName == "alpha2") {
|
||||
stemp = xmlChild.value();
|
||||
m_Alpha2MX_ij[counter] = atofCheck(stemp.c_str());
|
||||
m_Alpha2MX_ij[counter] = fpValueCheck(stemp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -475,7 +475,7 @@ void HMWSoln::readXMLPsiCommonCation(XML_Node& BinSalt)
|
|||
if (nodeName == "theta") {
|
||||
stemp = xmlChild.value();
|
||||
double old = m_Theta_ij[counter];
|
||||
m_Theta_ij[counter] = atofCheck(stemp.c_str());
|
||||
m_Theta_ij[counter] = fpValueCheck(stemp);
|
||||
if (old != 0.0) {
|
||||
if (old != m_Theta_ij[counter]) {
|
||||
throw CanteraError("HMWSoln::readXMLPsiCommonCation",
|
||||
|
|
@ -614,7 +614,7 @@ void HMWSoln::readXMLPsiCommonAnion(XML_Node& BinSalt)
|
|||
if (nodeName == "theta") {
|
||||
stemp = xmlChild.value();
|
||||
double old = m_Theta_ij[counter];
|
||||
m_Theta_ij[counter] = atofCheck(stemp.c_str());
|
||||
m_Theta_ij[counter] = fpValueCheck(stemp);
|
||||
if (old != 0.0) {
|
||||
if (old != m_Theta_ij[counter]) {
|
||||
throw CanteraError("HMWSoln::readXMLPsiCommonAnion",
|
||||
|
|
@ -1116,7 +1116,7 @@ void HMWSoln::constructPhaseXML(XML_Node& phaseNode, std::string id)
|
|||
stemp = scNode.attrib("TempReference");
|
||||
formString = lowercase(stemp);
|
||||
if (formString != "") {
|
||||
m_TempPitzerRef = atofCheck(formString.c_str());
|
||||
m_TempPitzerRef = fpValueCheck(formString);
|
||||
} else {
|
||||
m_TempPitzerRef = 273.15 + 25;
|
||||
}
|
||||
|
|
@ -1230,7 +1230,7 @@ initThermoXML(XML_Node& phaseNode, const std::string& id_)
|
|||
stemp = scNode.attrib("TempReference");
|
||||
formString = lowercase(stemp);
|
||||
if (formString != "") {
|
||||
m_TempPitzerRef = atofCheck(formString.c_str());
|
||||
m_TempPitzerRef = fpValueCheck(formString);
|
||||
} else {
|
||||
m_TempPitzerRef = 273.15 + 25;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -632,12 +632,12 @@ void PDSS_HKFT::constructPDSSXML(VPStandardStateTP* tp, size_t spindex,
|
|||
|
||||
std::string minTstring = (*hh)["Tmin"];
|
||||
if (minTstring != "") {
|
||||
m_minTemp = atofCheck(minTstring.c_str());
|
||||
m_minTemp = fpValueCheck(minTstring);
|
||||
}
|
||||
|
||||
std::string maxTstring = (*hh)["Tmax"];
|
||||
if (maxTstring != "") {
|
||||
m_maxTemp = atofCheck(maxTstring.c_str());
|
||||
m_maxTemp = fpValueCheck(maxTstring);
|
||||
}
|
||||
|
||||
if (hh->hasChild("DG0_f_Pr_Tr")) {
|
||||
|
|
|
|||
|
|
@ -665,7 +665,7 @@ void Phase::addElement(const std::string& symbol, doublereal weight)
|
|||
|
||||
void Phase::addElement(const XML_Node& e)
|
||||
{
|
||||
doublereal weight = atof(e["atomicWt"].c_str());
|
||||
doublereal weight = fpValue(e["atomicWt"]);
|
||||
string symbol = e["name"];
|
||||
addElement(symbol, weight);
|
||||
}
|
||||
|
|
@ -721,7 +721,7 @@ void Phase::addUniqueElement(const XML_Node& e)
|
|||
{
|
||||
doublereal weight = 0.0;
|
||||
if (e.hasAttrib("atomicWt")) {
|
||||
weight = atof(stripws(e["atomicWt"]).c_str());
|
||||
weight = fpValue(stripws(e["atomicWt"]));
|
||||
}
|
||||
int anum = 0;
|
||||
if (e.hasAttrib("atomicNumber")) {
|
||||
|
|
@ -732,7 +732,7 @@ void Phase::addUniqueElement(const XML_Node& e)
|
|||
if (e.hasChild("entropy298")) {
|
||||
XML_Node& e298Node = e.child("entropy298");
|
||||
if (e298Node.hasAttrib("value")) {
|
||||
entropy298 = atofCheck(stripws(e298Node["value"]).c_str());
|
||||
entropy298 = fpValueCheck(stripws(e298Node["value"]));
|
||||
}
|
||||
}
|
||||
if (weight != 0.0) {
|
||||
|
|
|
|||
|
|
@ -667,9 +667,9 @@ void PecosTransport::read_blottner_transport_table()
|
|||
|
||||
// this is the right species index
|
||||
if (sss.compare(ss1) == 0) {
|
||||
a[k] = atof(ss2.c_str());
|
||||
b[k] = atof(ss3.c_str());
|
||||
c[k] = atof(ss4.c_str());
|
||||
a[k] = fpValue(ss2);
|
||||
b[k] = fpValue(ss3);
|
||||
c[k] = fpValue(ss4);
|
||||
|
||||
// index
|
||||
i++;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue