diff --git a/ApplicationLibCode/Application/Tools/RiaStdStringTools.cpp b/ApplicationLibCode/Application/Tools/RiaStdStringTools.cpp index 154fa1c662..35277b0230 100644 --- a/ApplicationLibCode/Application/Tools/RiaStdStringTools.cpp +++ b/ApplicationLibCode/Application/Tools/RiaStdStringTools.cpp @@ -32,7 +32,7 @@ const std::string WHITESPACE = " \n\r\t\f\v"; //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -std::string RiaStdStringTools::leftTrimString( const std::string& s ) +std::string_view RiaStdStringTools::leftTrimString( std::string_view s ) { size_t start = s.find_first_not_of( WHITESPACE ); return ( start == std::string::npos ) ? "" : s.substr( start ); @@ -41,7 +41,7 @@ std::string RiaStdStringTools::leftTrimString( const std::string& s ) //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -std::string RiaStdStringTools::rightTrimString( const std::string& s ) +std::string_view RiaStdStringTools::rightTrimString( std::string_view s ) { size_t end = s.find_last_not_of( WHITESPACE ); return ( end == std::string::npos ) ? "" : s.substr( 0, end + 1 ); @@ -50,7 +50,7 @@ std::string RiaStdStringTools::rightTrimString( const std::string& s ) //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -std::string RiaStdStringTools::trimString( const std::string& s ) +std::string_view RiaStdStringTools::trimString( std::string_view s ) { return rightTrimString( leftTrimString( s ) ); } @@ -87,42 +87,24 @@ bool RiaStdStringTools::isNumber( const std::string& s, char decimalPoint ) //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -int16_t RiaStdStringTools::toInt16( const std::string& s ) +int16_t RiaStdStringTools::toInt16( std::string_view s ) { return (int16_t)toInt( s ); } //-------------------------------------------------------------------------------------------------- -/// +/// Convert a string to an integer. If the string is not a valid integer, the function returns -1. +/// For best performance, use toInt( const std::string_view& s, int& value ); //-------------------------------------------------------------------------------------------------- -int RiaStdStringTools::toInt( const std::string& s ) +int RiaStdStringTools::toInt( std::string_view s ) { int intValue = -1; - try - { - intValue = std::stoi( s ); - } - catch ( ... ) - { - } + toInt( s, intValue ); return intValue; } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -double RiaStdStringTools::toDouble( const std::string& s ) -{ - double doubleValue = -1.0; - - char* end; - doubleValue = std::strtod( s.data(), &end ); - - return doubleValue; -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -164,8 +146,11 @@ std::string RiaStdStringTools::formatThousandGrouping( long value ) //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -bool RiaStdStringTools::toDouble( const std::string_view& s, double& value ) +bool RiaStdStringTools::toDouble( std::string_view s, double& value ) { + s.remove_prefix( std::min( s.find_first_not_of( " " ), s.size() ) ); + + // NB! Note that we use fast_float:: here, and not std:: auto resultObject = fast_float::from_chars( s.data(), s.data() + s.size(), value ); return ( resultObject.ec == std::errc() ); @@ -174,8 +159,10 @@ bool RiaStdStringTools::toDouble( const std::string_view& s, double& value ) //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -bool RiaStdStringTools::toInt( const std::string_view& s, int& value ) +bool RiaStdStringTools::toInt( std::string_view s, int& value ) { + s.remove_prefix( std::min( s.find_first_not_of( " " ), s.size() ) ); + auto resultObject = std::from_chars( s.data(), s.data() + s.size(), value ); return ( resultObject.ec == std::errc() ); @@ -184,9 +171,9 @@ bool RiaStdStringTools::toInt( const std::string_view& s, int& value ) //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -std::string RiaStdStringTools::toUpper( const std::string& s ) +std::string RiaStdStringTools::toUpper( std::string_view s ) { - auto strCopy( s ); + std::string strCopy( s ); std::transform( strCopy.begin(), strCopy.end(), strCopy.begin(), []( unsigned char c ) { return std::toupper( c ); } ); return strCopy; diff --git a/ApplicationLibCode/Application/Tools/RiaStdStringTools.h b/ApplicationLibCode/Application/Tools/RiaStdStringTools.h index 5ef8aecc0c..b070aaf9ee 100644 --- a/ApplicationLibCode/Application/Tools/RiaStdStringTools.h +++ b/ApplicationLibCode/Application/Tools/RiaStdStringTools.h @@ -31,26 +31,25 @@ class RiaStdStringTools { public: - static std::string trimString( const std::string& s ); - static std::string rightTrimString( const std::string& s ); - static std::string leftTrimString( const std::string& s ); - static std::string removeWhitespace( const std::string& line ); + static std::string_view trimString( std::string_view s ); + static std::string_view rightTrimString( std::string_view s ); + static std::string_view leftTrimString( std::string_view s ); + static std::string removeWhitespace( const std::string& line ); static bool isNumber( const std::string& s, char decimalPoint ); - static int16_t toInt16( const std::string& s ); - static int toInt( const std::string& s ); - static double toDouble( const std::string& s ); + static int16_t toInt16( std::string_view s ); + static int toInt( std::string_view s ); static bool containsAlphabetic( const std::string& s ); static bool startsWithAlphabetic( const std::string& s ); static std::string formatThousandGrouping( long value ); // Conversion using fastest known approach - static bool toDouble( const std::string_view& s, double& value ); - static bool toInt( const std::string_view& s, int& value ); + static bool toDouble( std::string_view s, double& value ); + static bool toInt( std::string_view s, int& value ); - static std::string toUpper( const std::string& s ); + static std::string toUpper( std::string_view s ); static bool endsWith( const std::string& mainStr, const std::string& toMatch ); diff --git a/ApplicationLibCode/FileInterface/RifEclipseUserDataParserTools.cpp b/ApplicationLibCode/FileInterface/RifEclipseUserDataParserTools.cpp index 691b3fbf59..8da9eb70d0 100644 --- a/ApplicationLibCode/FileInterface/RifEclipseUserDataParserTools.cpp +++ b/ApplicationLibCode/FileInterface/RifEclipseUserDataParserTools.cpp @@ -228,7 +228,8 @@ bool RifEclipseUserDataParserTools::hasOnlyValidDoubleValues( const std::vector< } else { - double doubleVal = RiaStdStringTools::toDouble( word ); + double doubleVal = 0.0; + RiaStdStringTools::toDouble( word, doubleVal ); doubleValues->push_back( doubleVal ); } } diff --git a/ApplicationLibCode/FileInterface/RifKeywordVectorParser.cpp b/ApplicationLibCode/FileInterface/RifKeywordVectorParser.cpp index d9981721c2..53e690a0cb 100644 --- a/ApplicationLibCode/FileInterface/RifKeywordVectorParser.cpp +++ b/ApplicationLibCode/FileInterface/RifKeywordVectorParser.cpp @@ -89,9 +89,11 @@ void RifKeywordVectorParser::parseData( const QString& data ) keywordBasedVector.header = RifEclipseUserDataParserTools::headerReader( streamData, line ); if ( keywordBasedVector.header.empty() ) break; + double value = 0.0; while ( RifEclipseUserDataParserTools::isANumber( line ) ) { - keywordBasedVector.values.push_back( RiaStdStringTools::toDouble( line ) ); + RiaStdStringTools::toDouble( line, value ); + keywordBasedVector.values.push_back( value ); std::getline( streamData, line ); } diff --git a/ApplicationLibCode/FileInterface/RifOpmCommonSummary.cpp b/ApplicationLibCode/FileInterface/RifOpmCommonSummary.cpp index 448653b8d8..93d9b9cf20 100644 --- a/ApplicationLibCode/FileInterface/RifOpmCommonSummary.cpp +++ b/ApplicationLibCode/FileInterface/RifOpmCommonSummary.cpp @@ -217,7 +217,7 @@ std::string RifOpmCommonEclipseSummary::unitName( const RifEclipseSummaryAddress } } - return RiaStdStringTools::trimString( nameString ); + return std::string( RiaStdStringTools::trimString( nameString ) ); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/FileInterface/RifOpmHdf5Summary.cpp b/ApplicationLibCode/FileInterface/RifOpmHdf5Summary.cpp index 46afa8d0ad..dda481841e 100644 --- a/ApplicationLibCode/FileInterface/RifOpmHdf5Summary.cpp +++ b/ApplicationLibCode/FileInterface/RifOpmHdf5Summary.cpp @@ -125,7 +125,7 @@ std::string RifOpmHdf5Summary::unitName( const RifEclipseSummaryAddress& resultA auto keyword = it->second; auto stringFromFileReader = m_eSmry->get_unit( keyword ); - return RiaStdStringTools::trimString( stringFromFileReader ); + return std::string( RiaStdStringTools::trimString( stringFromFileReader ) ); } } diff --git a/ApplicationLibCode/GeoMech/GeoMechFileInterface/RifInpReader.cpp b/ApplicationLibCode/GeoMech/GeoMechFileInterface/RifInpReader.cpp index 27aee18007..0efb00005b 100644 --- a/ApplicationLibCode/GeoMech/GeoMechFileInterface/RifInpReader.cpp +++ b/ApplicationLibCode/GeoMech/GeoMechFileInterface/RifInpReader.cpp @@ -452,7 +452,7 @@ std::vector RifInpReader::readElementSet( std::istream& stream ) auto parts = RiaStdStringTools::splitString( line, ',' ); for ( auto part : parts ) { - std::string trimmedPart = RiaStdStringTools::trimString( part ); + auto trimmedPart = RiaStdStringTools::trimString( part ); if ( !trimmedPart.empty() ) { diff --git a/ApplicationLibCode/ProjectDataModel/Polygons/RimPolygonAppearance.cpp b/ApplicationLibCode/ProjectDataModel/Polygons/RimPolygonAppearance.cpp index ea8446151c..7dbba7429b 100644 --- a/ApplicationLibCode/ProjectDataModel/Polygons/RimPolygonAppearance.cpp +++ b/ApplicationLibCode/ProjectDataModel/Polygons/RimPolygonAppearance.cpp @@ -61,7 +61,8 @@ public: { if ( input.isEmpty() ) return State::Intermediate; - double val = RiaStdStringTools::toDouble( input.toStdString() ); + double val = 0.0; + RiaStdStringTools::toDouble( input.toStdString(), val ); if ( val > 0.001 && val <= 2.0 ) return State::Acceptable; else diff --git a/ApplicationLibCode/UnitTests/RiaStdStringTools-Test.cpp b/ApplicationLibCode/UnitTests/RiaStdStringTools-Test.cpp index c419e2476b..ff5c8d976d 100644 --- a/ApplicationLibCode/UnitTests/RiaStdStringTools-Test.cpp +++ b/ApplicationLibCode/UnitTests/RiaStdStringTools-Test.cpp @@ -257,3 +257,75 @@ TEST( RiaStdStringToolsTest, TestInvalidRangeStrings ) ASSERT_EQ( expectedValues, actualValues ); } } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +TEST( RiaStdStringToolsTest, TestToDouble ) +{ + { + std::string text = " 0.123"; + + double resultValue = 0.0; + auto isOk = RiaStdStringTools::toDouble( text, resultValue ); + EXPECT_TRUE( isOk ); + + EXPECT_DOUBLE_EQ( resultValue, 0.123 ); + } + + { + std::string text = " 0.123 2"; + + double resultValue = 0.0; + auto isOk = RiaStdStringTools::toDouble( text, resultValue ); + EXPECT_TRUE( isOk ); + + EXPECT_DOUBLE_EQ( resultValue, 0.123 ); + } + + { + std::string text = "0.123 2"; + + double resultValue = 0.0; + auto isOk = RiaStdStringTools::toDouble( text, resultValue ); + EXPECT_TRUE( isOk ); + + EXPECT_DOUBLE_EQ( resultValue, 0.123 ); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +TEST( RiaStdStringToolsTest, TestToInt ) +{ + { + std::string text = " 12"; + + int resultValue = -1; + auto isOk = RiaStdStringTools::toInt( text, resultValue ); + EXPECT_TRUE( isOk ); + + EXPECT_EQ( resultValue, 12 ); + } + + { + std::string text = " 12 "; + + int resultValue = -1; + auto isOk = RiaStdStringTools::toInt( text, resultValue ); + EXPECT_TRUE( isOk ); + + EXPECT_EQ( resultValue, 12 ); + } + + { + std::string text = "12"; + + int resultValue = -1; + auto isOk = RiaStdStringTools::toInt( text, resultValue ); + EXPECT_TRUE( isOk ); + + EXPECT_EQ( resultValue, 12 ); + } +}