Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/gui/src/util/String.cc @ 1967

Last change on this file since 1967 was 1625, checked in by rgrieder, 17 years ago

merged hud branch back to trunk

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