Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

merged core2 back to trunk
there might be some errors, wasn't able to test it yet due to some strange g++ and linker behaviour.

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.