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, "&", "&");
433 0 : s = ReplaceAll(s, "\"", """);
434 0 : s = ReplaceAll(s, "\'", "'");
435 0 : s = ReplaceAll(s, "<", "<");
436 0 : s = ReplaceAll(s, ">", ">");
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 :
|