Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/core2/src/util/String.cc @ 1686

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

bugfix

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