LCOV - code coverage report
Current view: top level - ugbase/common/util - string_util.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 3.2 % 217 7
Test Date: 2025-09-21 23:31:46 Functions: 8.3 % 36 3

            Line data    Source code
       1              : /*
       2              :  * Copyright (c) 2010-2015:  G-CSC, Goethe University Frankfurt
       3              :  * Author: Andreas Vogel
       4              :  * 
       5              :  * This file is part of UG4.
       6              :  * 
       7              :  * UG4 is free software: you can redistribute it and/or modify it under the
       8              :  * terms of the GNU Lesser General Public License version 3 (as published by the
       9              :  * Free Software Foundation) with the following additional attribution
      10              :  * requirements (according to LGPL/GPL v3 §7):
      11              :  * 
      12              :  * (1) The following notice must be displayed in the Appropriate Legal Notices
      13              :  * of covered and combined works: "Based on UG4 (www.ug4.org/license)".
      14              :  * 
      15              :  * (2) The following notice must be displayed at a prominent place in the
      16              :  * terminal output of covered works: "Based on UG4 (www.ug4.org/license)".
      17              :  * 
      18              :  * (3) The following bibliography is recommended for citation and must be
      19              :  * preserved in all covered files:
      20              :  * "Reiter, S., Vogel, A., Heppner, I., Rupp, M., and Wittum, G. A massively
      21              :  *   parallel geometric multigrid solver on hierarchically distributed grids.
      22              :  *   Computing and visualization in science 16, 4 (2013), 151-164"
      23              :  * "Vogel, A., Reiter, S., Rupp, M., Nägel, A., and Wittum, G. UG4 -- a novel
      24              :  *   flexible software system for simulating pde based models on high performance
      25              :  *   computers. Computing and visualization in science 16, 4 (2013), 165-179"
      26              :  * 
      27              :  * This program is distributed in the hope that it will be useful,
      28              :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      29              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
      30              :  * GNU Lesser General Public License for more details.
      31              :  */
      32              : 
      33              : #include "string_util.h"
      34              : #include <algorithm>
      35              : #include <string>
      36              : #include <cstring>
      37              : #include <sstream>
      38              : #include <iostream>
      39              : #include <iomanip>
      40              : #include <cctype>
      41              : #include <fstream>
      42              : #include "common/common.h"
      43              : #include "common/assert.h"
      44              : #include "common/profiler/profiler.h"
      45              : 
      46              : namespace ug{
      47              : 
      48              : using namespace std;
      49              : 
      50            0 : void RemoveWhitespaceFromString(std::string& str)
      51              : {
      52            0 :         str.erase(std::remove_if(str.begin(), str.end(), ::isspace), str.end());
      53            0 : }
      54              : 
      55              : 
      56            0 : void TokenizeString(const string& str, vector<string>& vToken, const char delimiter)
      57              : {
      58              :         vToken.clear();
      59            0 :         stringstream tokenstream;
      60              :         tokenstream << str;
      61              :         string token;
      62              : 
      63            0 :         while ( getline (tokenstream, token, delimiter ) ){
      64            0 :                 if(!token.empty())
      65            0 :                         vToken.push_back(token);
      66              :         }
      67            0 : }
      68              : 
      69            0 : vector<string> TokenizeString(const string& str, const char delimiter)
      70              : {
      71              :         vector<string> vToken;
      72            0 :         TokenizeString(str, vToken, delimiter);
      73            0 :         return vToken;
      74            0 : }
      75              : 
      76            0 : vector<string> TokenizeString(const char* str, const char delimiter)
      77              : {
      78              :         vector<string> vToken;
      79            0 :         TokenizeString(string(str), vToken, delimiter);
      80            0 :         return vToken;
      81            0 : }
      82              : 
      83            0 : void TokenizeTrimString(const string& str, vector<string>& vToken, const char delimiter)
      84              : {
      85              :         vToken.clear();
      86            0 :         stringstream tokenstream;
      87              :         tokenstream << str;
      88              :         string token;
      89              : 
      90            0 :         while ( getline (tokenstream, token, delimiter ) ){
      91            0 :                 token = TrimString(token);
      92            0 :                 if(!token.empty())
      93            0 :                         vToken.push_back(token);
      94              :         }
      95            0 : }
      96              : 
      97            0 : vector<string> TokenizeTrimString(const string& str, const char delimiter)
      98              : {
      99              :         vector<string> vToken;
     100              :         TokenizeTrimString(str, vToken, delimiter);
     101            0 :         return vToken;
     102            0 : }
     103              : 
     104        29467 : string TrimString(const string& str)
     105              : {
     106              :         const size_t start = str.find_first_not_of(" \t");
     107              :         const size_t end = str.find_last_not_of(" \t");
     108        29467 :         if(start == string::npos || end == string::npos) return "";
     109        23459 :         return str.substr(start, end - start + 1);
     110              : }
     111              : 
     112            0 : string SnipString(const string& str, size_t totalSize,
     113              :                   size_t replaceLast, const char replace)
     114              : {
     115            0 :         if(str.size() <= totalSize) return str;
     116              : 
     117            0 :         string s = str.substr(0, totalSize);
     118            0 :         int r = totalSize - replaceLast;
     119            0 :         if(r <= 0) return s;
     120            0 :         s.replace(r, replaceLast, replaceLast, replace);
     121            0 :         return s;
     122              : }
     123              : 
     124            0 : string SnipStringFront(const string& str, size_t totalSize,
     125              :                        size_t replaceFirst, const char replace)
     126              : {
     127            0 :         if(str.size() <= totalSize) return str;
     128              : 
     129            0 :         string s = str.substr(str.size()-totalSize, str.size());
     130            0 :         int r = totalSize - replaceFirst;
     131            0 :         if(r <= 0) return s;
     132            0 :         s.replace(0, replaceFirst, replaceFirst, replace);
     133            0 :         return s;
     134              : }
     135              : 
     136            0 : int NumberOfDigits(int nsigned)
     137              : {
     138            0 :         int n = abs(nsigned);
     139              : //      a 0 has 1 digit
     140            0 :         if (n == 0) return 1;
     141              : 
     142              : //      divide by 10 until
     143              :     int cnt = 0;
     144            0 :     while (n > 0)
     145              :     {
     146            0 :         ++cnt;
     147            0 :         n /= 10;
     148              :     }
     149              : 
     150              : //      return number of digits
     151              :     return cnt;
     152              : }
     153              : 
     154            0 : void AppendCounterToString( string& str, string indicator, int counter, 
     155              :                             int maxCounter )
     156              : {
     157              : //      check correct usage
     158              :         if(maxCounter >= 0)
     159              :                 UG_ASSERT(counter <= maxCounter, "Wrong usage of function");
     160              : 
     161              : //      get number of digits needed for counter field (default is 4)
     162              :         int numDigits = 4;
     163            0 :         if(maxCounter >= 0) numDigits = NumberOfDigits(maxCounter);
     164              : 
     165              : //      create stringstream
     166            0 :         stringstream ss;
     167              : 
     168              : //      print stringstream
     169            0 :         ss << indicator << setfill ('0') << setw (numDigits) << counter;
     170              : 
     171              : //      append to string
     172            0 :         str.append(ss.str());
     173            0 : }
     174              : 
     175            0 : string AppendSpacesToString(string& str, int totalLength)
     176              : {
     177            0 :         int numSpaces = max((int)(totalLength-str.length()), 0);
     178            0 :         for(int i = 0; i < numSpaces; ++i) str.append(" ");
     179              : 
     180            0 :         return str;
     181              : }
     182              : 
     183            0 : string::size_type GetDirectorySeperatorPos(const string &str)
     184              : {
     185              :         string::size_type pos1 = str.rfind("/");
     186              :         string::size_type pos2 = str.rfind("\\");
     187            0 :         if(pos1 != string::npos)
     188              :         {
     189            0 :                 if(pos2 != string::npos && pos2 > pos1) return pos2;
     190            0 :                 else return pos1;
     191              :         }
     192              :         else return pos2;
     193              : }
     194              : 
     195            0 : string FilenameWithoutPath(const string &str)
     196              : {
     197            0 :         string::size_type pos = GetDirectorySeperatorPos(str);
     198            0 :         if( pos != string::npos ) return str.substr( pos+1 );
     199              :         else return str;
     200              : }
     201              : 
     202            0 : string PathFromFilename(const string &str)
     203              : {
     204            0 :         string::size_type pos = GetDirectorySeperatorPos(str);
     205            0 :         if( pos != string::npos ) return str.substr(0, pos+1 );
     206            0 :         else return ".";
     207              : }
     208              : 
     209            0 : string FilenameWithoutExtension(string str)
     210              : {
     211            0 :         str = FilenameWithoutPath(str);
     212              :         string::size_type pos = str.rfind(".");
     213            0 :         if( pos != string::npos ) return str.substr(0, pos );
     214            0 :         else return str;
     215              : }
     216              : 
     217            0 : string FilenameAndPathWithoutExtension(string str)
     218              : {
     219              :         string::size_type pos = str.rfind(".");
     220            0 :         if( pos != string::npos ) return str.substr(0, pos );
     221            0 :         else return str;
     222              : }
     223              : 
     224            0 : string GetFilenameExtension(const string &str)
     225              : {
     226              :         string::size_type pos = str.rfind(".");
     227            0 :         if( pos != string::npos ) return str.substr(pos+1);
     228            0 :         else return "";
     229              : }
     230              : 
     231            0 : string ReplaceAll( string target, const string& oldstr, const string& newstr ) {
     232              :         // no substitution necessary
     233            0 :         if (oldstr == newstr) {
     234            0 :                 return target;
     235              :         }
     236              : 
     237            0 :         for (size_t x = target.find(oldstr); x != string::npos; x = target.find(oldstr, x + newstr.size())) {
     238            0 :                 target.erase(x, oldstr.length());
     239              :                 target.insert(x, newstr);
     240              :         }
     241              : 
     242            0 :         return target;
     243              : }
     244              : 
     245        30553 : bool StartsWith(const string& str, const string& begin) {
     246        30553 :         return str.find(begin) == 0;
     247              : }
     248              : 
     249         7638 : bool Contains(const string& str, const string& search) {
     250         7638 :         return str.find(search) != string::npos;
     251              : }
     252              : 
     253              : //sreiter - Implementation is copied from some book or website. Can't remember...
     254            0 : template <> size_t hash_key(const string& key)
     255              : {
     256              : 
     257              :         unsigned long hash = 5381;
     258              :         const char* str = key.c_str();
     259              :         int c;
     260              : 
     261            0 :         while((c = *str)){
     262            0 :                 hash = hash * 33 + c;
     263            0 :                 ++str;
     264              :         }
     265              : 
     266            0 :         return hash;
     267              : }
     268              : 
     269            0 : string ToLower(string str) {
     270              :     transform(str.begin(), str.end(), str.begin(), ::tolower);
     271            0 :     return str;
     272              : }
     273              : 
     274            0 : string ToUpper(string str) {
     275              :     transform(str.begin(), str.end(), str.begin(), ::toupper);
     276            0 :     return str;
     277              : }
     278              : 
     279            0 : vector<string> FindDuplicates(const vector<string>& vec) {
     280              :                 
     281              :         vector<string> result;
     282              :         
     283              :         // search for duplicates
     284            0 :         for (size_t i = 0; i < vec.size();i++) {
     285              :                 
     286              :                 bool duplicateExists = false;
     287              :                 
     288            0 :                 for (size_t j = 0; j < vec.size();j++) {
     289            0 :                         if (vec[i]==vec[j] && i!=j) {
     290              :                                 duplicateExists = true;
     291              :                                 break;
     292              :                         }
     293              :                 }
     294              :                 
     295              :                 // if not already added, add entry to result vec
     296              :                 bool duplicateAddedToResult =
     297            0 :                         find(result.begin(), result.end(), vec[i])!=result.end();
     298              :                 
     299            0 :                 if (duplicateExists && !duplicateAddedToResult) {
     300            0 :                         result.push_back(vec[i]);
     301              :                 }
     302              :         }
     303              :         
     304            0 :         return result;  
     305            0 : }
     306              : 
     307              : 
     308              : const unsigned int cost_del = 1;
     309              : const unsigned int cost_ins = 1;
     310              : const unsigned int cost_sub = 1;
     311            0 : size_t LevenshteinDistance( const string& s1, const string& s2 )
     312              : {
     313              :   size_t n1 = s1.length();
     314              :   size_t n2 = s2.length();
     315              : 
     316            0 :   size_t* p = new size_t[ n2+1 ];
     317            0 :   size_t* q = new size_t[ n2+1 ];
     318              :   size_t* r;
     319              : 
     320            0 :   p[ 0 ] = 0;
     321            0 :   for( size_t j = 1; j <= n2; ++j )
     322            0 :     p[ j ] = p[ j-1 ] + cost_ins;
     323              : 
     324            0 :   for( size_t i = 1; i <= n1; ++i )
     325              :     {
     326            0 :       q[ 0 ] = p[ 0 ] + cost_del;
     327            0 :       for( size_t j = 1; j <= n2; ++j )
     328              :         {
     329            0 :           size_t d_del = p[ j   ] + cost_del;
     330            0 :           size_t d_ins = q[ j-1 ] + cost_ins;
     331            0 :           size_t d_sub = p[ j-1 ] + ( s1[i-1] == s2[j-1] ? 0 : cost_sub );
     332            0 :           q[ j ] = min( min( d_del, d_ins ), d_sub );
     333              :       }
     334              :       r = p;
     335              :       p = q;
     336              :       q = r;
     337              :     }
     338              : 
     339            0 :   size_t tmp = p[ n2 ];
     340            0 :   delete[] p;
     341            0 :   delete[] q;
     342              : 
     343            0 :   return tmp;
     344              : }
     345              : 
     346            0 : string repeat(char c, int nr)
     347              : {
     348            0 :         if(nr > 0)
     349            0 :                 return string(nr, c);
     350              :         else
     351            0 :                 return string("");
     352              : }
     353              : 
     354            0 : bool IsLonger(const string &a, const string &b)
     355              : {
     356            0 :         return b.size() > a.size();
     357              : }
     358              : 
     359            0 : string GetFileLines(const char *filename, size_t fromline, size_t toline, bool includeLineNumbers)
     360              : {
     361              :         PROFILE_FUNC(); // since this is an i/o function
     362            0 :         if(filename[0] == '@') filename++;
     363              :         char buf[512];
     364            0 :         fstream file(filename, std::ios::in);
     365            0 :         if(file.is_open() == false) return string("");
     366            0 :         for(size_t i=0; i<fromline && !file.eof(); i++)
     367            0 :                 file.getline(buf, 512);
     368            0 :         stringstream ss;
     369            0 :         if(includeLineNumbers)
     370            0 :                 ss << fromline << "\t";
     371            0 :         ss << buf;
     372            0 :         for(; fromline < toline && !file.eof(); fromline++)
     373              :         {
     374            0 :                 file.getline(buf, 512);
     375            0 :                 ss << "\n";
     376            0 :                 if(includeLineNumbers)
     377            0 :                         ss << fromline+1 << "\t";
     378            0 :                 ss << buf;
     379              :         }
     380              :         return ss.str();
     381            0 : }
     382              : 
     383            0 : string GetFileLine(const char *filename, size_t line)
     384              : {
     385            0 :         return GetFileLines(filename, line, line, false);
     386              : }
     387              : 
     388            0 : bool WildcardMatch(const char *str, const char *pattern)
     389              : {
     390            0 :         int strLen = strlen(str);
     391            0 :         int patternLen = strlen(pattern);
     392              :         int j=0;
     393            0 :         for(int i=0; i<patternLen; i++)
     394              :         {
     395            0 :                 if(j >= strLen)
     396            0 :                         return pattern[i] == '*';
     397            0 :                 switch(pattern[i])
     398              :                 {
     399            0 :                 case '*':
     400            0 :                         if(i == patternLen-1) return true;
     401              :                         else
     402              :                         {
     403            0 :                                 char nextSign = pattern[i+1];
     404              :                                 UG_ASSERT(nextSign != '*', "** is not a valid pattern");
     405              :                                 while(1)
     406              :                                 {
     407            0 :                                         for(;j<strLen; j++)
     408            0 :                                                 if(str[j] == nextSign)
     409              :                                                         break;
     410            0 :                                         if(j == strLen) return false;
     411            0 :                                         if(WildcardMatch(str+j, pattern+i+1)) return true;
     412            0 :                                         j++;
     413              :                                 }
     414              :                         }
     415              :                         break;
     416              : 
     417            0 :                 case '?':
     418            0 :                         j++;
     419            0 :                         break;
     420              : 
     421            0 :                 default:
     422            0 :                         if(pattern[i] != str[j]) return false;
     423            0 :                         j++;
     424            0 :                         break;
     425              :                 }
     426              :         }
     427              :         return true;
     428              : }
     429              : 
     430            0 : string XMLStringEscape(string s)
     431              : {
     432            0 :         s = ReplaceAll(s, "&", "&amp;");
     433            0 :         s = ReplaceAll(s, "\"", "&quot;");
     434            0 :         s = ReplaceAll(s, "\'", "&apos;");
     435            0 :         s = ReplaceAll(s, "<", "&lt;");
     436            0 :         s = ReplaceAll(s, ">", "&gt;");
     437            0 :         return s;
     438              : }
     439              : 
     440              : static const char shiftCharacters[] = "|#[+";
     441              : static const size_t shiftCharactersLength = sizeof(shiftCharacters)/sizeof(shiftCharacters[0]);
     442              : 
     443            0 : bool IsShiftChar(char c)
     444              : {
     445            0 :         for(size_t i=0; i<shiftCharactersLength; i++)
     446            0 :                 if(c==shiftCharacters[i]) return true;
     447              :         return false;
     448              : }
     449            0 : char ConfigShiftRotation(char c)
     450              : {
     451            0 :         for(size_t i=0; i<shiftCharactersLength; i++)
     452            0 :                 if(c==shiftCharacters[i])
     453            0 :                         return shiftCharacters[(i+1) % (shiftCharactersLength-1)];
     454              :         return c;
     455              : }
     456              : 
     457            0 : string ConfigShift(string s)
     458              : {
     459            0 :         if(s.find("\n") == string::npos)
     460            0 :                 return s;
     461              : 
     462            0 :         stringstream ss;
     463            0 :         ss << "\n";
     464              :         bool bNewLine = true;
     465            0 :         for(size_t k=0; k<s.length(); k++)
     466              :         {
     467            0 :                 if(s[k] == '\n')
     468              :                 {
     469            0 :                         if(k == s.length()-1) return ss.str();
     470              :                         bNewLine=true;
     471              :                 }
     472            0 :                 else if(bNewLine)
     473              :                 {
     474              :                         bNewLine = false;
     475            0 :                         ss << " | ";
     476            0 :                         while(k+2 < s.length() && s[k] == ' ' && IsShiftChar(s[k+1]) && s[k+2] == ' ')
     477              :                         {
     478            0 :                                 ss << " " << ConfigShiftRotation(s[k+1]) << " ";
     479            0 :                                 k+=3;
     480              :                         }
     481              : 
     482              :                 }
     483            0 :                 ss << s[k];
     484              :         }
     485              :         return ss.str();
     486            0 : }
     487              : 
     488              : 
     489            0 : string GetBytesSizeString(size_t s, int length)
     490              : {
     491            0 :         stringstream ss;
     492            0 :         if(length!=0)
     493            0 :                 ss << setw(length-3);
     494            0 :         if(s > 1024*1024*1024)
     495            0 :                 ss << s/(1024*1024*1024.0) << " Gb";
     496            0 :         else if(s > 1024*1024)
     497            0 :                 ss << s/(1024*1024.0) << " Mb";
     498            0 :         else if(s > 1024)
     499            0 :                         ss << s/(1024.0) << " kb";
     500            0 :         else if(length == 0)
     501            0 :                 ss << s << " b";
     502              :         else
     503            0 :                 ss << s << " b ";
     504            0 :         return ss.str();
     505            0 : }
     506              : 
     507              : }
     508              : 
        

Generated by: LCOV version 2.0-1