///////////////////////////////////////////////////////////////////////////////// // // Copyright (C) 2017 Statoil ASA // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY // WARRANTY; without even the implied warranty of MERCHANTABILITY or // FITNESS FOR A PARTICULAR PURPOSE. // // See the GNU General Public License at // for more details. // ///////////////////////////////////////////////////////////////////////////////// #include "RiaStdStringTools.h" //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- std::string RiaStdStringTools::trimString( const std::string& s ) { auto sCopy = s.substr( 0, s.find_last_not_of( ' ' ) + 1 ); sCopy = sCopy.substr( sCopy.find_first_not_of( ' ' ) ); return sCopy; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- bool RiaStdStringTools::isNumber( const std::string& s, char decimalPoint ) { if ( s.empty() ) return false; if ( findCharMatchCount( s, decimalPoint ) > 1 ) return false; if ( findCharMatchCount( s, '-' ) > 1 ) return false; if ( findCharMatchCount( s, 'e' ) > 1 ) return false; if ( findCharMatchCount( s, 'E' ) > 1 ) return false; std::string matchChars( "0123456789eE-+" ); matchChars.append( 1, decimalPoint ); auto it = s.find_first_not_of( matchChars ); return ( it == std::string::npos ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- int16_t RiaStdStringTools::toInt16( const std::string& s ) { return (int16_t)toInt( s ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- int RiaStdStringTools::toInt( const std::string& s ) { int intValue = -1; try { intValue = std::stoi( s ); } catch ( ... ) { } return intValue; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- double RiaStdStringTools::toDouble( const std::string& s ) { double doubleValue = -1.0; char* end; doubleValue = std::strtod( s.data(), &end ); return doubleValue; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- bool RiaStdStringTools::containsAlphabetic( const std::string& s ) { return std::find_if( s.begin(), s.end(), []( char c ) { return isalpha( c ); } ) != s.end(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- bool RiaStdStringTools::startsWithAlphabetic( const std::string& s ) { if ( s.empty() ) return false; return isalpha( s[0] ) != 0; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- bool RiaStdStringTools::endsWith( const std::string& mainStr, const std::string& toMatch ) { if ( mainStr.size() >= toMatch.size() && mainStr.compare( mainStr.size() - toMatch.size(), toMatch.size(), toMatch ) == 0 ) return true; else return false; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- std::vector RiaStdStringTools::splitStringBySpace( const std::string& s ) { std::vector words; splitByDelimiter( s, words ); return words; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- size_t RiaStdStringTools::findCharMatchCount( const std::string& s, char c ) { size_t count = 0; size_t pos = 0; while ( ( pos = s.find_first_of( c, pos + 1 ) ) != std::string::npos ) { count++; } return count; } //-------------------------------------------------------------------------------------------------- /// Function to find Levenshtein Distance between two strings (x and y). /// Adapted from pseudocode from wikipedia: https://en.wikipedia.org/wiki/Levenshtein_distance /// Implementation is the Wagner-Fischer variant: https://en.wikipedia.org/wiki/Wagner-Fischer_algorithm /// /// Return value is higher when strings are more "different", and zero when strings are equal. //-------------------------------------------------------------------------------------------------- int RiaStdStringTools::computeEditDistance( const std::string& x, const std::string& y ) { // for all i and j, T[i,j] will hold the Levenshtein distance between // the first i characters of x and the first j characters of y int m = static_cast( x.length() ); int n = static_cast( y.length() ); std::vector> T( m + 1, std::vector( n + 1, 0 ) ); // source prefixes can be transformed into empty string by // dropping all characters for ( int i = 1; i <= m; i++ ) T[i][0] = i; // target prefixes can be reached from empty source prefix // by inserting every character for ( int j = 1; j <= n; j++ ) T[0][j] = j; // fill the lookup table in bottom-up manner for ( int i = 1; i <= m; i++ ) { for ( int j = 1; j <= n; j++ ) { int substitutionCost; if ( x[i - 1] == y[j - 1] ) substitutionCost = 0; else substitutionCost = 1; int deletion = T[i - 1][j] + 1; int insertion = T[i][j - 1] + 1; int replacement = T[i - 1][j - 1] + substitutionCost; T[i][j] = std::min( std::min( deletion, insertion ), replacement ); } } // The distance between the two full strings as the last value computed. return T[m][n]; }