Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

added comments to all my classes in util

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