Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/util/String.cc @ 1505

Last change on this file since 1505 was 1505, checked in by rgrieder, 12 years ago

f* svn: It doesn't even inform you if you attempt to set a non existing property. It is svn:eol-style and not eol-style when using the command by the way…

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