Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/pch/src/util/String.cc @ 3146

Last change on this file since 3146 was 3146, checked in by rgrieder, 15 years ago

Found another few unnecessary includes in util (and added two others that followed due to this change).

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