Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 1056 was 1056, checked in by landauf, 17 years ago

don't panic, no codechanges!
added a link to www.orxonox.net

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