Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/network/src/util/String.cc @ 1446

Last change on this file since 1446 was 1446, checked in by landauf, 16 years ago

merged console branch into network branch

after several heavy troubles it compiles, but there is still a bug I couldn't fix: orxonox crashes as soon as one presses a key after opening the console… maybe someone else sees the problem?

File size: 14.1 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 = 0;
111    while ((quote = getNextQuote(str, quote)) < 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.