From 5185470d773f8a211fd29eda765c11069e66a102 Mon Sep 17 00:00:00 2001 From: aliceconcordel Date: Mon, 31 Oct 2016 17:17:19 +0100 Subject: [PATCH 1/2] replaced std::atof by ParsingUtils::parse_float and ParsingUtils::parse_double to avoid dependency on locale this fixes #53 --- src/config/ConfigurationReader.cpp | 61 ++++++++++--------- src/config/EvolverConfiguration.cpp | 16 ++--- .../representation/RobotRepresentation.cpp | 8 ++- src/utils/ParsingUtils.h | 59 ++++++++++++++++++ 4 files changed, 104 insertions(+), 40 deletions(-) create mode 100644 src/utils/ParsingUtils.h diff --git a/src/config/ConfigurationReader.cpp b/src/config/ConfigurationReader.cpp index 4d3be7e..6bedcd8 100644 --- a/src/config/ConfigurationReader.cpp +++ b/src/config/ConfigurationReader.cpp @@ -45,6 +45,7 @@ #include "config/LightSourcesConfig.h" #include "utils/RobogenUtils.h" +#include "utils/ParsingUtils.h" #define DEFAULT_LIGHT_SOURCE_HEIGHT (0.1) #define DEFAULT_OBSTACLE_DENSITY (0.) @@ -451,10 +452,10 @@ boost::shared_ptr ConfigurationReader::parseConfigurationFile( std::vector gravityOpts; boost::split(gravityOpts, gravityString, boost::is_any_of(",")); if (gravityOpts.size() == 1) { - gravity[2] = std::atof(gravityOpts[0].c_str()); + gravity[2] = parse_float(gravityOpts[0]); } else if (gravityOpts.size() == 3) { for(unsigned int i=0; i<3; ++i) { - gravity[i] = std::atof(gravityOpts[i].c_str()); + gravity[i] = parse_float(gravityOpts[i]); } } else { std::cerr << "'gravity' must either be a single value for " << @@ -551,37 +552,37 @@ boost::shared_ptr ConfigurationReader::parseObstaclesFile( zRotation, rotationAngle; if(boost::regex_match(line.c_str(), match, fullObstacleRegex)){ - x = std::atof(match[1].str().c_str()); - y = std::atof(match[2].str().c_str()); - z = std::atof(match[3].str().c_str()); - xSize = std::atof(match[4].str().c_str()); - ySize = std::atof(match[5].str().c_str()); - zSize = std::atof(match[6].str().c_str()); - density = std::atof(match[7].str().c_str()); - xRotation = std::atof(match[8].str().c_str()); - yRotation = std::atof(match[9].str().c_str()); - zRotation = std::atof(match[10].str().c_str()); - rotationAngle = std::atof(match[11].str().c_str()); + x = parse_float(match[1].str()); + y = parse_float(match[2].str()); + z = parse_float(match[3].str()); + xSize = parse_float(match[4].str()); + ySize = parse_float(match[5].str()); + zSize = parse_float(match[6].str()); + density = parse_float(match[7].str()); + xRotation = parse_float(match[8].str()); + yRotation = parse_float(match[9].str()); + zRotation = parse_float(match[10].str()); + rotationAngle = parse_float(match[11].str()); } else { xRotation = yRotation = zRotation = rotationAngle = 0.0; if (boost::regex_match(line.c_str(), match, oldObstacleRegex)){ - x = std::atof(match[1].str().c_str()); - y = std::atof(match[2].str().c_str()); - xSize = std::atof(match[3].str().c_str()); - ySize = std::atof(match[4].str().c_str()); - zSize = std::atof(match[5].str().c_str()); - density = std::atof(match[6].str().c_str()); + x = parse_float(match[1].str()); + y = parse_float(match[2].str()); + xSize = parse_float(match[3].str()); + ySize = parse_float(match[4].str()); + zSize = parse_float(match[5].str()); + density = parse_float(match[6].str()); z = zSize/2; } else if(boost::regex_match(line.c_str(), match, noRotationObstacleRegex)){ - x = std::atof(match[1].str().c_str()); - y = std::atof(match[2].str().c_str()); - z = std::atof(match[3].str().c_str()); - xSize = std::atof(match[4].str().c_str()); - ySize = std::atof(match[5].str().c_str()); - zSize = std::atof(match[6].str().c_str()); - density = std::atof(match[7].str().c_str()); + x = parse_float(match[1].str()); + y = parse_float(match[2].str()); + z = parse_float(match[3].str()); + xSize = parse_float(match[4].str()); + ySize = parse_float(match[5].str()); + zSize = parse_float(match[6].str()); + density = parse_float(match[7].str()); } else { std::cerr << "Error parsing line " << lineNum << " of obstacles file: '" << fileName << "'" @@ -626,7 +627,7 @@ boost::shared_ptr ConfigurationReader::parseLightSourcesFile boost::cmatch match; float x, y, z, intensity; if(boost::regex_match(line.c_str(), match, fullRegex)){ - intensity = std::atof(match[4].str().c_str()); + intensity = parse_float(match[4].str()); } else { intensity = 1.0; if(!boost::regex_match(line.c_str(), match, noIntensityRegex)){ @@ -638,9 +639,9 @@ boost::shared_ptr ConfigurationReader::parseLightSourcesFile return boost::shared_ptr(); } } - x = std::atof(match[1].str().c_str()); - y = std::atof(match[2].str().c_str()); - z = std::atof(match[3].str().c_str()); + x = parse_float(match[1].str()); + y = parse_float(match[2].str()); + z = parse_float(match[3].str()); coordinates.push_back(osg::Vec3(x, y, z)); intensities.push_back(intensity); diff --git a/src/config/EvolverConfiguration.cpp b/src/config/EvolverConfiguration.cpp index a8278e0..08b7180 100644 --- a/src/config/EvolverConfiguration.cpp +++ b/src/config/EvolverConfiguration.cpp @@ -34,6 +34,8 @@ #include #include "config/EvolverConfiguration.h" +#include "utils/ParsingUtils.h" + #include "PartList.h" namespace robogen { @@ -59,8 +61,8 @@ bool parseBounds(std::string value, double &min, double &max) { "\" does not match pattern :" << std::endl; return false; } - min = std::atof(match[1].first); - max = std::atof(match[2].first); + min = parse_double(match[1].str()); + max = parse_double(match[2].str()); if (min > max) { std::cerr << "supplied min " << min << " is greater than supplied max " << max << std::endl; @@ -331,11 +333,11 @@ bool EvolverConfiguration::init(std::string configFileName) { return false; } if(vm.count("brainSigma") > 0){ - brainWeightSigma = atof(vm["brainSigma"].as().c_str()); + brainWeightSigma = parse_double(vm["brainSigma"].as()); brainBiasSigma = brainWeightSigma; } else if(vm.count("weightSigma") > 0 && vm.count("biasSigma") > 0) { - brainWeightSigma = atof(vm["weightSigma"].as().c_str()); - brainBiasSigma = atof(vm["biasSigma"].as().c_str()); + brainWeightSigma = parse_double(vm["weightSigma"].as()); + brainBiasSigma = parse_double(vm["biasSigma"].as()); } else { std::cerr << "Must supply either brainSigma or (weightSigma and biasSigma)" << " ( and sigmas for other brain params)" << std::endl; @@ -385,8 +387,8 @@ bool EvolverConfiguration::init(std::string configFileName) { "\" does not match pattern :" << std::endl; return false; } - minNumInitialParts = std::atof(match[1].first); - maxNumInitialParts = std::atof(match[2].first); + minNumInitialParts = parse_float(match[1].str()); + maxNumInitialParts = parse_float(match[2].str()); } diff --git a/src/evolution/representation/RobotRepresentation.cpp b/src/evolution/representation/RobotRepresentation.cpp index 5ae15e1..7dc7c92 100644 --- a/src/evolution/representation/RobotRepresentation.cpp +++ b/src/evolution/representation/RobotRepresentation.cpp @@ -46,6 +46,8 @@ #include "PartList.h" #include "utils/json2pb/json2pb.h" #include "utils/RobogenUtils.h" +#include "utils/ParsingUtils.h" + #include "brain/NeuralNetwork.h" #define VERIFY_ON_LOAD_TXT @@ -211,7 +213,7 @@ bool robotTextFileReadWeightLine(std::ifstream &file, std::string &from, fromIoId = std::atoi(match[2].first); to.assign(match[3]); toIoId = std::atoi(match[4].first); - value = std::atof(match[5].first); + value = parse_double(match[5].str()); return true; } else { // additional info if poor formatting, i.e. line not empty @@ -300,7 +302,7 @@ bool robotTextFileReadParamsLine(std::ifstream &file, std::string &node, std::vector strs; boost::split(strs, paramsString, boost::is_any_of(" ")); for (unsigned int i=0; i. + * + * @(#) $Id$ + */ +#ifndef PARSING_UTILS_H_ +#define PARSING_UTILS_H_ + +#include + + +namespace robogen +{ + static inline float parse_float(const std::string& str) + { + + float f = 0.0f; + std::istringstream istr(str); + + istr >> f; + + return f; + } + + + static inline double parse_double(const std::string& str) + { + + double d = 0.0f; + std::istringstream istr(str); + + istr >> d; + + return d; + } +} +#endif /* PARSING_UTILS_H_ */ \ No newline at end of file From f900850cb85f116a7a6e6f5b382ce384b1e0aca0 Mon Sep 17 00:00:00 2001 From: aliceconcordel Date: Mon, 31 Oct 2016 18:18:43 +0100 Subject: [PATCH 2/2] ParseUtils:: added support for NAN and INF numbers. Completed documentation for these functions. --- src/utils/ParsingUtils.h | 42 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/src/utils/ParsingUtils.h b/src/utils/ParsingUtils.h index fb5d579..aced3cb 100644 --- a/src/utils/ParsingUtils.h +++ b/src/utils/ParsingUtils.h @@ -33,26 +33,64 @@ namespace robogen { + /** + * Parse the string to get the numeric value. + * Supports NAN, INF, E and e (exponential). + * @param str input string + * @return parsed float; if failed, returns 0.0f + */ static inline float parse_float(const std::string& str) { float f = 0.0f; std::istringstream istr(str); + istr >> f; + if(istr.fail()) + { + // check for NAN, nan or NaN + if (!str.compare(0, 3, "NAN") || !str.compare(0, 3, "nan") || !str.compare(0, 3, "NaN")) + { + f = NAN; + } + else if (!str.compare(0, 3, "INF") || !str.compare(0, 3, "inf") || !str.compare(0, 3, "Inf")) + { + f = std::numeric_limits::infinity(); + } + } + return f; } - + /** + * Parse the string to get the numeric value. + * Supports NAN, INF, E and e (exponential). + * @param str input string + * @return parsed double; if failed, returns 0.0 + */ static inline double parse_double(const std::string& str) { - double d = 0.0f; + double d = 0.0; std::istringstream istr(str); istr >> d; + if(istr.fail()) + { + // check for NAN, nan or NaN + if (!str.compare(0, 3, "NAN") || !str.compare(0, 3, "nan") || !str.compare(0, 3, "NaN")) + { + d = NAN; + } + else if (!str.compare(0, 3, "INF") || !str.compare(0, 3, "inf") || !str.compare(0, 3, "Inf")) + { + d = std::numeric_limits::infinity(); + } + } + return d; } }