Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/buildsystem/src/util/String.cc @ 2252

Last change on this file since 2252 was 2244, checked in by rgrieder, 16 years ago

Applied long created patch that removes plugins.cfg and puts the content into orxonox.ini
This also allows to specify the media path for each 'distribution' individually because orxonox.ini has been added to the default files.

  • Property svn:eol-style set to native
File size: 15.6 KB
Line 
1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *                    > www.orxonox.net <
4 *
5 *
6 *   License notice:
7 *
8 *   This program is free software; you can redistribute it and/or
9 *   modify it under the terms of the GNU General Public License
10 *   as published by the Free Software Foundation; either version 2
11 *   of the License, or (at your option) any later version.
12 *
13 *   This program is distributed in the hope that it will be useful,
14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *   GNU General Public License for more details.
17 *
18 *   You should have received a copy of the GNU General Public License
19 *   along with this program; if not, write to the Free Software
20 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 *
22 *   Author:
23 *      Fabian 'x3n' Landau
24 *   Co-authors:
25 *      Benjamin Grauer
26 *
27 */
28
29/**
30    @file String.cc
31    @brief Implementation of several string manipulation functions.
32*/
33
34#include "String.h"
35
36#include <cctype>
37#include <iostream>
38
39/**
40    @brief Blank string as variable so you can use const std::string& even if you have to return "".
41*/
42std::string blankString = "";
43
44/**
45    @brief Removes all whitespaces from a string.
46    @param str The string to strip
47*/
48void strip(std::string* str)
49{
50    unsigned int pos;
51    while ((pos = (*str).find(" ")) < (*str).length())
52        (*str).erase(pos, 1);
53    while ((pos = (*str).find("\t")) < (*str).length())
54        (*str).erase(pos, 1);
55    while ((pos = (*str).find("\n")) < (*str).length())
56        (*str).erase(pos, 1);
57}
58
59/**
60    @brief Returns a copy of a string without whitespaces.
61    @param str The string to strip
62    @return The stripped line
63*/
64std::string getStripped(const std::string& str)
65{
66    std::string output = std::string(str);
67    strip(&output);
68    return output;
69}
70
71/**
72    @brief Returns a copy of a string without trailing whitespaces.
73    @param str The string
74    @return The modified copy
75*/
76std::string removeTrailingWhitespaces(const std::string& str)
77{
78    unsigned int pos1 = 0;
79    int pos2 = str.size() - 1;
80    for (; pos1 < str.size() && (str[pos1] == ' ' || str[pos1] == '\t' || str[pos1] == '\n'); pos1++);
81    for (; pos2 > 0          && (str[pos2] == ' ' || str[pos2] == '\t' || str[pos2] == '\n'); pos2--);
82    return str.substr(pos1, pos2 - pos1 + 1);
83}
84
85/**
86    @brief Returns the position of the next quote in the string, starting with start.
87    @param str The string
88    @param start The startposition
89    @return The position of the next quote (std::string::npos if there is no next quote)
90*/
91unsigned int getNextQuote(const std::string& str, unsigned int start)
92{
93    unsigned int quote = start - 1;
94
95    while ((quote = str.find('\"', quote + 1)) != std::string::npos)
96    {
97        unsigned int backslash = quote;
98        unsigned int numbackslashes = 0;
99        for (; backslash > 0; backslash--, numbackslashes++)
100            if (str[backslash - 1] != '\\')
101                break;
102
103        if (numbackslashes % 2 == 0)
104            break;
105    }
106
107    return quote;
108}
109
110/**
111    @brief Returns true if pos is between two quotes.
112    @param str The string
113    @param pos The position to check
114    @return True if pos is between two quotes
115*/
116bool isBetweenQuotes(const std::string& str, unsigned int pos)
117{
118    if (pos == std::string::npos)
119        return false;
120
121    unsigned int quotecount = 0;
122    unsigned int quote = (unsigned int)-1;
123    while ((quote = getNextQuote(str, quote + 1)) < pos)
124    {
125        if (quote == pos)
126            return false;
127        quotecount++;
128    }
129
130    if (quote == std::string::npos)
131        return false;
132
133    return ((quotecount % 2) == 1);
134}
135
136/**
137    @brief Returns true if the string contains something like '..."between quotes"...'.
138    @param The string
139    @return True if there is something between quotes
140*/
141bool hasStringBetweenQuotes(const std::string& str)
142{
143    unsigned int pos1 = getNextQuote(str, 0);
144    unsigned int pos2 = getNextQuote(str, pos1 + 1);
145    return (pos1 != std::string::npos && pos2 != std::string::npos && pos2 > pos1 + 1);
146}
147
148/**
149    @brief If the string contains something like '..."between quotes"...' then 'between quotes' gets returned (without quotes).
150    @param The string
151    @param The string between the quotes
152*/
153std::string getStringBetweenQuotes(const std::string& str)
154{
155    unsigned int pos1 = getNextQuote(str, 0);
156    unsigned int pos2 = getNextQuote(str, pos1 + 1);
157    if (pos1 != std::string::npos && pos2 != std::string::npos)
158        return str.substr(pos1, pos2 - pos1 + 1);
159    else
160        return "";
161}
162
163/**
164    @brief Removes enclosing quotes if available (including whitespaces at the outside of the quotes).
165    @brief str The string to strip
166    @return The string with removed quotes
167*/
168std::string stripEnclosingQuotes(const std::string& str)
169{
170    unsigned int start = std::string::npos;
171    unsigned int end = 0;
172
173    for (unsigned int pos = 0; (pos < str.size()) && (pos < std::string::npos); pos++)
174    {
175        if (str[pos] == '"')
176        {
177            start = pos;
178            break;
179        }
180
181        if ((str[pos] != ' ') && (str[pos] != '\t') && (str[pos] != '\n'))
182            return str;
183    }
184
185    for (unsigned int pos = str.size() - 1; pos < std::string::npos; pos--)
186    {
187        if (str[pos] == '"')
188        {
189            end = pos;
190            break;
191        }
192
193        if ((str[pos] != ' ') && (str[pos] != '\t') && (str[pos] != '\n'))
194            return str;
195    }
196
197    if ((start != std::string::npos) && (end != 0))
198        return str.substr(start + 1, end - start - 1);
199    else
200        return str;
201}
202
203/**
204    @brief Removes enclosing {braces} (braces must be exactly on the beginning and the end of the string).
205    @param str The string to strip
206    @return The striped string
207*/
208std::string stripEnclosingBraces(const std::string& str)
209{
210    std::string output = str;
211
212    while (output.size() >= 2 && output[0] == '{' && output[output.size() - 1] == '}')
213        output = output.substr(1, output.size() - 2);
214
215    return output;
216}
217
218/**
219    @brief Determines if a string is a comment (starts with a comment-symbol).
220    @param str The string to check
221    @return True = it's a comment
222
223    A comment is defined by a leading '#', '%', ';' or '//'.
224*/
225bool isComment(const std::string& str)
226{
227    // Strip the line, whitespaces are disturbing
228    std::string teststring = getStripped(str);
229
230    // There are four possible comment-symbols:
231    //  1) #comment in script-language style
232    //  2) %comment in matlab style
233    //  3) ;comment in unreal tournament config-file style
234    //  4) //comment in code style
235    if (teststring.size() >= 2)
236    {
237        if (teststring[0] == '#' || teststring[0] == '%' || teststring[0] == ';' || (teststring[0] == '/' && teststring[1] == '/'))
238            return true;
239    }
240    else if (teststring.size() == 1)
241    {
242        if (teststring[0] == '#' || teststring[0] == '%' || teststring[0] == ';')
243            return true;
244    }
245
246    return false;
247}
248
249/**
250    @brief Determines if a string is empty (contains only whitespaces).
251    @param str The string to check
252    @return True = it's empty
253*/
254bool isEmpty(const std::string& str)
255{
256    std::string temp = getStripped(str);
257    return ((temp == "") || (temp.size() == 0));
258}
259
260/**
261    @brief Determines if a string contains only numbers and maximal one '.'.
262    @param str The string to check
263    @return True = it's a number
264*/
265bool isNumeric(const std::string& str)
266{
267    bool foundPoint = false;
268
269    for (std::string::const_iterator it = str.begin(); it != str.end(); ++it)
270    {
271        if (((*it) < '0' || (*it) > '9'))
272        {
273            if ((*it) != '.' && !foundPoint)
274                foundPoint = true;
275            else
276                return false;
277        }
278    }
279
280    return true;
281}
282
283/**
284    @brief Adds backslashes to the given string which makes special chars visible. Existing slashes will be doubled.
285    @param str The string to manipulate
286    @return The string with added slashes
287*/
288std::string addSlashes(const std::string& str)
289{
290    std::string output = str;
291
292    for (unsigned int pos = 0; (pos = output.find('\\', pos)) < std::string::npos; pos += 2) { output.replace(pos, 1, "\\\\"); }
293    for (unsigned int pos = 0; (pos = output.find('\n', pos)) < std::string::npos; pos += 2) { output.replace(pos, 1, "\\n"); }
294    for (unsigned int pos = 0; (pos = output.find('\t', pos)) < std::string::npos; pos += 2) { output.replace(pos, 1, "\\t"); }
295    for (unsigned int pos = 0; (pos = output.find('\v', pos)) < std::string::npos; pos += 2) { output.replace(pos, 1, "\\v"); }
296    for (unsigned int pos = 0; (pos = output.find('\b', pos)) < std::string::npos; pos += 2) { output.replace(pos, 1, "\\b"); }
297    for (unsigned int pos = 0; (pos = output.find('\r', pos)) < std::string::npos; pos += 2) { output.replace(pos, 1, "\\r"); }
298    for (unsigned int pos = 0; (pos = output.find('\f', pos)) < std::string::npos; pos += 2) { output.replace(pos, 1, "\\f"); }
299    for (unsigned int pos = 0; (pos = output.find('\a', pos)) < std::string::npos; pos += 2) { output.replace(pos, 1, "\\a"); }
300    for (unsigned int pos = 0; (pos = output.find('"', pos)) < std::string::npos; pos += 2) { output.replace(pos, 1, "\\\""); }
301    for (unsigned int pos = 0; (pos = output.find('\0', pos)) < std::string::npos; pos += 2) { output.replace(pos, 1, "\\0"); }
302
303    return output;
304}
305
306/**
307    @brief Removes backslashes from the given string. Double backslashes are interpreted as one backslash.
308    @param str The string to manipulate
309    @return The string with removed slashes
310*/
311std::string removeSlashes(const std::string& str)
312{
313    if (str.size() <= 1)
314        return str;
315
316    std::string output = "";
317    for (unsigned int pos = 0; pos < str.size() - 1; )
318    {
319        if (str[pos] == '\\')
320        {
321            if (str[pos + 1] == '\\') { output += '\\'; pos += 2; continue; }
322            else if (str[pos + 1] == 'n') { output += '\n'; pos += 2; continue; }
323            else if (str[pos + 1] == 't') { output += '\t'; pos += 2; continue; }
324            else if (str[pos + 1] == 'v') { output += '\v'; pos += 2; continue; }
325            else if (str[pos + 1] == 'b') { output += '\b'; pos += 2; continue; }
326            else if (str[pos + 1] == 'r') { output += '\r'; pos += 2; continue; }
327            else if (str[pos + 1] == 'f') { output += '\f'; pos += 2; continue; }
328            else if (str[pos + 1] == 'a') { output += '\a'; pos += 2; continue; }
329            else if (str[pos + 1] == '"') { output += '"'; pos += 2; continue; }
330            else if (str[pos + 1] == '0') { output += '\0'; pos += 2; continue; }
331        }
332        output += str[pos];
333        pos++;
334        if (pos == str.size() - 1)
335            output += str[pos];
336    }
337
338    return output;
339}
340
341/**
342    @brief Replaces each char between A and Z with its lowercase equivalent.
343    @param str The string to convert
344*/
345void lowercase(std::string* str)
346{
347    for (unsigned int i = 0; i < str->size(); ++i)
348    {
349        (*str)[i] = (char)tolower((*str)[i]);
350    }
351}
352
353/**
354    @brief Returns a copy of the given string without uppercase chars.
355    @param str The string
356    @return The copy
357*/
358std::string getLowercase(const std::string& str)
359{
360    std::string output = std::string(str);
361    lowercase(&output);
362    return output;
363}
364
365/**
366    @brief Replaces each char between a and z with its uppercase equivalent.
367    @param str The string to convert
368*/
369void uppercase(std::string* str)
370{
371    for (unsigned int i = 0; i < str->size(); ++i)
372    {
373        (*str)[i] = (char)toupper((*str)[i]);
374    }
375}
376
377/**
378    @brief Returns a copy of the given string without lowercase chars.
379    @param str The string
380    @return The copy
381*/
382std::string getUppercase(const std::string& str)
383{
384    std::string output = std::string(str);
385    uppercase(&output);
386    return output;
387}
388
389/**
390    @brief Compares two strings ignoring different casing.
391    @param s1 First string
392    @param s2 Second string
393*/
394int nocaseCmp(const std::string& s1, const std::string& s2)
395{
396    std::string::const_iterator it1=s1.begin();
397    std::string::const_iterator it2=s2.begin();
398
399    //stop when either string's end has been reached
400    while ( (it1!=s1.end()) && (it2!=s2.end()) )
401    {
402        if(::toupper(*it1) != ::toupper(*it2)) //letters differ?
403            // return -1 to indicate smaller than, 1 otherwise
404            return (::toupper(*it1)  < ::toupper(*it2)) ? -1 : 1;
405        //proceed to the next character in each string
406        ++it1;
407        ++it2;
408    }
409    size_t size1=s1.size(), size2=s2.size();// cache lengths
410    //return -1,0 or 1 according to strings' lengths
411    if (size1==size2)
412        return 0;
413    return (size1<size2) ? -1 : 1;
414}
415
416
417/**
418    @brief Compares the first 'len' chars of two strings ignoring different casing.
419    @param s1 First string
420    @param s2 Second string
421    @param len Maximal number of chars to compare
422*/
423int nocaseCmp(const std::string& s1, const std::string& s2, unsigned int len)
424{
425    if (len == 0)
426        return 0;
427    std::string::const_iterator it1=s1.begin();
428    std::string::const_iterator it2=s2.begin();
429
430    //stop when either string's end has been reached
431    while ( (it1!=s1.end()) && (it2!=s2.end()) && len-- > 0)
432    {
433        if(::toupper(*it1) != ::toupper(*it2)) //letters differ?
434            // return -1 to indicate smaller than, 1 otherwise
435            return (::toupper(*it1)  < ::toupper(*it2)) ? -1 : 1;
436        //proceed to the next character in each string
437        ++it1;
438        ++it2;
439    }
440    return 0;
441}
442
443/**
444    @brief Returns true if the string contains a comment, introduced by #, %, ; or //.
445    @param str The string
446    @return True if the string contains a comment
447*/
448bool hasComment(const std::string& str)
449{
450    return (getCommentPosition(str) != std::string::npos);
451}
452
453/**
454    @brief If the string contains a comment, the comment gets returned (including the comment symbol), an empty string otherwise.
455    @param str The string
456    @return The comment
457*/
458std::string getComment(const std::string& str)
459{
460    return str.substr(getCommentPosition(str));
461}
462
463/**
464    @brief If the string contains a comment, the position of the comment-symbol gets returned, std::string::npos otherwise.
465    @param str The string
466    @return The position
467*/
468unsigned int getCommentPosition(const std::string& str)
469{
470    return getNextCommentPosition(str, 0);
471}
472
473/**
474    @brief Returns the position of the next comment-symbol, starting with start.
475    @param str The string
476    @param start The startposition
477    @return The position
478*/
479unsigned int getNextCommentPosition(const std::string& str, unsigned int start)
480{
481    for (unsigned int i = start; i < str.size(); i++)
482        if (isComment(str.substr(i)))
483            return i;
484
485    return std::string::npos;
486}
487
488/**
489    @brief Converts a path string to windows with "\" instead of "/".
490    @param str String pointer to be manipulated
491*/
492void convertToWindowsPath(std::string* str)
493{
494    std::string& path = *str;
495    // replace all occurences of "/" with "\"
496    for (unsigned int i = 0; i < path.length(); ++i)
497    {
498        if (path[i] == '/')
499            path[i] = '\\';
500    }
501    // add an extra '\\' at the end to make it a complete path
502    if (path != "" && path[path.length() - 1] != '\\')
503        path.append("\\");
504}
505
506/**
507    @brief Converts a path string to unix with "/" instead of "\".
508    @param str String pointer to be manipulated
509*/
510void convertToUnixPath(std::string* str)
511{
512    std::string& path = *str;
513    // replace all occurences of "\" with "/"
514    for (unsigned int i = 0; i < path.length(); ++i)
515    {
516        if (path[i] == '\\')
517            path[i] = '/';
518    }
519    // add an extra '\\' at the end to make it a complete path
520    if (path != "" && path[path.length() - 1] != '/')
521        path.append("/");
522}
Note: See TracBrowser for help on using the repository browser.