Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/doc/src/libraries/util/SubString.cc @ 7297

Last change on this file since 7297 was 7297, checked in by landauf, 14 years ago

fixed lots of Doxygen warnings

Note: Doxygen prints a warning if only a part of the parameters of a function are documented.

Added documentation for missing parameters (as good as I could), removed documentation of obsolete parameters and fixed names of renamed parameters.
Some parameters are tagged with "FIXME", please replace this with an appropriate documentation if you know what it does.

  • Property svn:eol-style set to native
File size: 21.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 *      Christian Meyer
24 *   Co-authors:
25 *      Benjamin Grauer
26 *
27
28//
29//  splitLine
30//  STL string tokenizer
31//
32//  Created by Clemens Wacha.
33//  Version 1.0
34//  Copyright (c) 2005 Clemens Wacha. All rights reserved.
35//
36
37 *   Extended by Fabian 'x3n' Landau by the SL_PARENTHESES mode.
38 */
39
40#include "SubString.h"
41#include <cstdio>
42
43namespace orxonox
44{
45    /**
46     * @brief default constructor
47     */
48    SubString::SubString()
49    {}
50
51
52    /**
53     * @brief create a SubString from
54     * @param string the String to Split
55     * @param delimiter the Character at which to split string (delimiter)
56     */
57    SubString::SubString(const std::string& string, char delimiter)
58    {
59        this->split(string, delimiter);
60    }
61
62
63    /**
64     * @brief Splits a string into multiple tokens.
65     * @param string The string to split
66     * @param delimiters Multiple set of characters at what to split. (delimiters)
67     * @param delimiterNeighbours Neighbours of the delimiters that will be erased as well.
68     * @param emptyEntries If empty entries are added to the list of SubStrings
69     * @param escapeChar The escape character that overrides splitters commends and so on...
70     * @param removeEscapeChar If true, the escape char is removed from the tokens
71     * @param safemode_char Within these characters splitting won't happen
72     * @param removeSafemodeChar Removes the safemode_char from the beginning and the ending of a token
73     * @param openparenthesis_char The beginning of a safemode is marked with this
74     * @param closeparenthesis_char The ending of a safemode is marked with this
75     * @param removeParenthesisChars Removes the parenthesis from the beginning and the ending of a token
76     * @param comment_char The comment character.
77     */
78    SubString::SubString(const std::string& string,
79                         const std::string& delimiters, const std::string& delimiterNeighbours, bool emptyEntries,
80                         char escapeChar, bool removeEscapeChar, char safemode_char, bool removeSafemodeChar,
81                         char openparenthesis_char, char closeparenthesis_char, bool removeParenthesisChars, char comment_char)
82    {
83        SubString::splitLine(this->strings, this->bInSafemode, string, delimiters, delimiterNeighbours, emptyEntries, escapeChar, removeEscapeChar, safemode_char, removeSafemodeChar, openparenthesis_char, closeparenthesis_char, removeParenthesisChars, comment_char);
84    }
85
86    /**
87     * @brief creates a SubSet of a SubString.
88     * @param subString the SubString to take a set from.
89     * @param subSetBegin the beginning to the end
90     */
91    SubString::SubString(const SubString& subString, unsigned int subSetBegin)
92    {
93        for (unsigned int i = subSetBegin; i < subString.size(); i++)
94        {
95            this->strings.push_back(subString[i]);
96            this->bInSafemode.push_back(subString.isInSafemode(i));
97        }
98    }
99
100
101    /**
102     * @brief creates a SubSet of a SubString.
103     * @param subString the SubString to take a Set from
104     * @param subSetBegin the beginning to the end
105     * @param subSetEnd the end of the SubSet (max subString.size() will be checked internaly)
106     */
107    SubString::SubString(const SubString& subString, unsigned int subSetBegin, unsigned int subSetEnd)
108    {
109        for (unsigned int i = subSetBegin; i < subString.size() && i < subSetEnd; i++)
110        {
111            this->strings.push_back(subString[i]);
112            this->bInSafemode.push_back(subString.isInSafemode(i));
113        }
114    }
115
116    /**
117     * @brief creates a Substring from a count and values set.
118     * @param argc: the Arguments Count.
119     * @param argv: Argument Values.
120     */
121    SubString::SubString(unsigned int argc, const char** argv)
122    {
123        for(unsigned int i = 0; i < argc; ++i)
124        {
125            this->strings.push_back(std::string(argv[i]));
126            this->bInSafemode.push_back(false);
127        }
128    }
129
130    /**
131     * @brief removes the object from memory
132     */
133    SubString::~SubString()
134    { }
135
136    /** @brief An empty String */
137    // const std::string SubString::emptyString = "";
138    /** @brief Helper that gets you a String consisting of all White Spaces */
139    const std::string SubString::WhiteSpaces = " \n\t";
140    /** @brief Helper that gets you a String consisting of all WhiteSpaces and the Comma */
141    const std::string SubString::WhiteSpacesWithComma = " \n\t,";
142    /** An Empty SubString */
143    const SubString SubString::NullSubString = SubString();
144
145    /**
146     * @brief stores the Value of subString in this SubString
147     * @param subString will be copied into this String.
148     * @returns this SubString.
149     */
150    SubString& SubString::operator=(const SubString& subString)
151    {
152        this->strings = subString.strings;
153        this->bInSafemode = subString.bInSafemode;
154        return *this;
155    }
156
157
158    /**
159     * @brief comparator.
160     * @param subString the SubString to compare against this one.
161     * @returns true if the Stored Strings match
162     */
163    bool SubString::operator==(const SubString& subString) const
164    {
165        return ((this->strings == subString.strings) && (this->bInSafemode == subString.bInSafemode));
166    }
167
168    /**
169     * @brief comparator.
170     * @param subString the SubString to compare against this one.
171     * @returns true if the Stored Strings match
172     */
173    bool SubString::compare(const SubString& subString) const
174    {
175        return (*this == subString);
176    }
177
178    /**
179     * @brief comparator.
180     * @param subString the SubString to compare against this one.
181     * @param length how many entries to compare. (from 0 to length)
182     * @returns true if the Stored Strings match
183     */
184    bool SubString::compare(const SubString& subString, unsigned int length) const
185    {
186        if (length > this->size() || length > subString.size())
187            return false;
188
189        for (unsigned int i = 0; i < length; i++)
190            if ((this->strings[i] != subString.strings[i]) || (this->bInSafemode[i] != subString.bInSafemode[i]))
191                return false;
192        return true;
193    }
194
195
196    /**
197     * @brief append operator
198     * @param subString the String to append.
199     * @returns a SubString where this and subString are appended.
200     */
201    SubString SubString::operator+(const SubString& subString) const
202    {
203        return SubString(*this) += subString;
204    }
205
206
207    /**
208     * @brief append operator.
209     * @param subString append subString to this SubString.
210     * @returns this substring appended with subString
211     */
212    SubString& SubString::operator+=(const SubString& subString)
213    {
214        for (unsigned int i = 0; i < subString.size(); i++)
215        {
216            this->strings.push_back(subString[i]);
217            this->bInSafemode.push_back(subString.isInSafemode(i));
218        }
219        return *this;
220    }
221
222
223    /**
224     * @brief Split the String at
225     * @param string where to split
226     * @param splitter delimiter.
227     */
228    unsigned int SubString::split(const std::string& string, char splitter)
229    {
230        this->strings.clear();
231        this->bInSafemode.clear();
232        char split[2];
233        split[0] = splitter;
234        split[1] = '\0';
235        SubString::splitLine(this->strings, this->bInSafemode, string, split);
236        return strings.size();
237    }
238
239
240    /**
241     * @brief Splits a string into multiple tokens.
242     * @param string The string to split
243     * @param delimiters Multiple set of characters at what to split. (delimiters)
244     * @param delimiterNeighbours: Neighbours of the delimiters that will be erased too.
245     * @param emptyEntries: If empty entries are added to the list of SubStrings
246     * @param escapeChar The escape character that overrides splitters commends and so on...
247     * @param removeEscapeChar If true, the escape char is removed from the tokens
248     * @param safemode_char Within these characters splitting won't happen
249     * @param removeSafemodeChar Removes the safemode_char from the beginning and the ending of a token
250     * @param openparenthesis_char The beginning of a safemode is marked with this
251     * @param closeparenthesis_char The ending of a safemode is marked with this
252     * @param removeParenthesisChars Removes the parenthesis from the beginning and the ending of a token
253     * @param comment_char The comment character.
254     */
255    unsigned int SubString::split(const std::string& string,
256                                  const std::string& delimiters, const std::string& delimiterNeighbours, bool emptyEntries,
257                                  char escapeChar, bool removeEscapeChar, char safemode_char, bool removeSafemodeChar,
258                                  char openparenthesis_char, char closeparenthesis_char, bool removeParenthesisChars, char comment_char)
259    {
260        this->strings.clear();
261        this->bInSafemode.clear();
262        SubString::splitLine(this->strings, this->bInSafemode, string, delimiters, delimiterNeighbours, emptyEntries, escapeChar, removeEscapeChar, safemode_char, removeSafemodeChar, openparenthesis_char, closeparenthesis_char, removeParenthesisChars, comment_char);
263        return this->strings.size();
264    }
265
266
267    /**
268     * @brief joins together all Strings of this Substring.
269     * @param delimiter the String between the subStrings.
270     * @returns the joined String.
271     */
272    std::string SubString::join(const std::string& delimiter) const
273    {
274        if (!this->strings.empty())
275        {
276            std::string retVal = this->strings[0];
277            for (unsigned int i = 1; i < this->strings.size(); i++)
278                retVal += delimiter + this->strings[i];
279            return retVal;
280        }
281        else
282            return "";
283    }
284
285
286    /**
287     * @brief creates a SubSet of a SubString.
288     * @param subSetBegin the beginning to the end
289     * @returns the SubSet
290     *
291     * This function is added for your convenience, and does the same as
292     * SubString::SubString(const SubString& subString, unsigned int subSetBegin)
293     */
294    SubString SubString::subSet(unsigned int subSetBegin) const
295    {
296        return SubString(*this, subSetBegin);
297    }
298
299
300    /**
301     * @brief creates a SubSet of a SubString.
302     * @param subSetBegin the beginning to
303     * @param subSetEnd the end of the SubSet to select (if bigger than subString.size() it will be downset.)
304     * @returns the SubSet
305     *
306     * This function is added for your convenience, and does the same as
307     * SubString::SubString(const SubString& subString, unsigned int subSetBegin)
308     */
309    SubString SubString::subSet(unsigned int subSetBegin, unsigned int subSetEnd) const
310    {
311        return SubString(*this, subSetBegin, subSetEnd);
312    }
313
314
315    /**
316     * @brief Splits a line into tokens and stores them in ret.
317     * @param ret The array, where the splitted strings will be stored in
318     * @param bInSafemode A vector wich stores for each character of the string if it is in safemode or not
319     * @param line The inputLine to split
320     * @param delimiters A string of delimiters (here the input will be splitted)
321     * @param delimiterNeighbours Neighbours of the delimiter, that will be removed if they are to the left or the right of a delimiter.
322     * @param emptyEntries If empty strings are added to the list of strings.
323     * @param escape_char Escape carater (escapes splitters)
324     * @param removeEscapeChar If true, the escape char is removed from the tokens
325     * @param safemode_char The beginning of the safemode is marked with this
326     * @param removeSafemodeChar Removes the safemode_char from the beginning and the ending of a token
327     * @param openparenthesis_char The beginning of a safemode is marked with this
328     * @param closeparenthesis_char The ending of a safemode is marked with this
329     * @param removeParenthesisChars Removes the parenthesis from the beginning and the ending of a token
330     * @param comment_char The beginning of a comment is marked with this: (until the end of a line)
331     * @param start_state The initial state on how to parse the string.
332     * @return SPLIT_LINE_STATE the parser was in when returning
333     *
334     * This is the Actual Splitting Algorithm from Clemens Wacha
335     * Supports delimiters, escape characters,
336     * ignores special  characters between safemode_char and between comment_char and linend '\n'.
337     */
338    SubString::SPLIT_LINE_STATE
339    SubString::splitLine(std::vector<std::string>& ret,
340                         std::vector<bool>& bInSafemode,
341                         const std::string& line,
342                         const std::string& delimiters,
343                         const std::string& delimiterNeighbours,
344                         bool emptyEntries,
345                         char escape_char,
346                         bool removeEscapeChar,
347                         char safemode_char,
348                         bool removeSafemodeChar,
349                         char openparenthesis_char,
350                         char closeparenthesis_char,
351                         bool removeParenthesisChars,
352                         char comment_char,
353                         SPLIT_LINE_STATE start_state)
354    {
355        SPLIT_LINE_STATE state = start_state;
356        unsigned int i = 0;
357        unsigned int fallBackNeighbours = 0;
358
359        std::string token;
360        bool inSafemode = false;
361
362        if(start_state != SL_NORMAL && ret.size() > 0)
363        {
364            token = ret[ret.size()-1];
365            ret.pop_back();
366        }
367        if(start_state != SL_NORMAL && bInSafemode.size() > 0)
368        {
369            inSafemode = bInSafemode[bInSafemode.size()-1];
370            bInSafemode.pop_back();
371        }
372
373        while(i < line.size())
374        {
375            switch(state)
376            {
377            case SL_NORMAL:
378                if(line[i] == escape_char)
379                {
380                    state = SL_ESCAPE;
381                    if (!removeEscapeChar)
382                        token += line[i];
383                }
384                else if(line[i] == safemode_char)
385                {
386                    state = SL_SAFEMODE;
387                    inSafemode = true;
388                    if (!removeSafemodeChar)
389                        token += line[i];
390                }
391                else if(line[i] == openparenthesis_char)
392                {
393                    state = SL_PARENTHESES;
394                    inSafemode = true;
395                    if (!removeParenthesisChars)
396                        token += line[i];
397                }
398                else if(line[i] == comment_char)
399                {
400                    if (fallBackNeighbours > 0)
401                        token = token.substr(0, token.size() - fallBackNeighbours);
402                    /// FINISH
403                    if(emptyEntries || token.size() > 0)
404                    {
405                        ret.push_back(token);
406                        token.clear();
407                        bInSafemode.push_back(inSafemode);
408                        inSafemode = false;
409                    }
410                    token += line[i];       // EAT
411                    state = SL_COMMENT;
412                }
413                else if(delimiters.find(line[i]) != std::string::npos)
414                {
415                    // line[i] is a delimiter
416                    if (fallBackNeighbours > 0)
417                        token = token.substr(0, token.size() - fallBackNeighbours);
418                    /// FINISH
419                    if(emptyEntries || token.size() > 0)
420                    {
421                        ret.push_back(token);
422                        token.clear();
423                        bInSafemode.push_back(inSafemode);
424                        inSafemode = false;
425                    }
426                    state = SL_NORMAL;
427                }
428                else
429                {
430                    if (delimiterNeighbours.find(line[i]) != std::string::npos)
431                    {
432                        if (token.size() > 0)
433                            ++fallBackNeighbours;
434                        else
435                        {
436                            i++;
437                            continue;
438                        }
439                    }
440                    else
441                        fallBackNeighbours = 0;
442                    token += line[i];       // EAT
443                }
444                break;
445            case SL_ESCAPE:
446                if (!removeSafemodeChar)
447                    token += line[i];
448                else
449                {
450                    if(line[i] == 'n') token += '\n';
451                    else if(line[i] == 't') token += '\t';
452                    else if(line[i] == 'v') token += '\v';
453                    else if(line[i] == 'b') token += '\b';
454                    else if(line[i] == 'r') token += '\r';
455                    else if(line[i] == 'f') token += '\f';
456                    else if(line[i] == 'a') token += '\a';
457                    else if(line[i] == '?') token += '\?';
458                    else token += line[i];  // EAT
459                }
460                state = SL_NORMAL;
461                break;
462            case SL_SAFEMODE:
463                if(line[i] == safemode_char)
464                {
465                    state = SL_NORMAL;
466                    if (!removeSafemodeChar)
467                        token += line[i];
468                }
469                else if(line[i] == escape_char)
470                {
471                    state = SL_SAFEESCAPE;
472                }
473                else
474                {
475                    token += line[i];       // EAT
476                }
477                break;
478
479            case SL_SAFEESCAPE:
480                if(line[i] == 'n') token += '\n';
481                else if(line[i] == 't') token += '\t';
482                else if(line[i] == 'v') token += '\v';
483                else if(line[i] == 'b') token += '\b';
484                else if(line[i] == 'r') token += '\r';
485                else if(line[i] == 'f') token += '\f';
486                else if(line[i] == 'a') token += '\a';
487                else if(line[i] == '?') token += '\?';
488                else token += line[i];  // EAT
489                state = SL_SAFEMODE;
490                break;
491
492            case SL_PARENTHESES:
493                if(line[i] == closeparenthesis_char)
494                {
495                    state = SL_NORMAL;
496                    if (!removeParenthesisChars)
497                        token += line[i];
498                }
499                else if(line[i] == escape_char)
500                {
501                    state = SL_PARENTHESESESCAPE;
502                }
503                else
504                {
505                    token += line[i];       // EAT
506                }
507                break;
508
509            case SL_PARENTHESESESCAPE:
510                if(line[i] == 'n') token += '\n';
511                else if(line[i] == 't') token += '\t';
512                else if(line[i] == 'v') token += '\v';
513                else if(line[i] == 'b') token += '\b';
514                else if(line[i] == 'r') token += '\r';
515                else if(line[i] == 'f') token += '\f';
516                else if(line[i] == 'a') token += '\a';
517                else if(line[i] == '?') token += '\?';
518                else token += line[i];  // EAT
519                state = SL_PARENTHESES;
520                break;
521
522            case SL_COMMENT:
523                if(line[i] == '\n')
524                {
525                    /// FINISH
526                    if(token.size() > 0)
527                    {
528                        ret.push_back(token);
529                        token.clear();
530                        bInSafemode.push_back(inSafemode);
531                        inSafemode = false;
532                    }
533                    state = SL_NORMAL;
534                }
535                else
536                {
537                    token += line[i];       // EAT
538                }
539                break;
540
541            default:
542                // nothing
543                break;
544            }
545            i++;
546        }
547
548        /// FINISH
549        if (fallBackNeighbours > 0)
550            token = token.substr(0, token.size() - fallBackNeighbours);
551        if(emptyEntries || token.size() > 0)
552        {
553            ret.push_back(token);
554            token.clear();
555            bInSafemode.push_back(inSafemode);
556            inSafemode = false;
557        }
558        return(state);
559    }
560
561
562    /**
563     * @brief Some nice debug information about this SubString
564     */
565    void SubString::debug() const
566    {
567        printf("Substring-information::count=%d ::", this->strings.size());
568        for (unsigned int i = 0; i < this->strings.size(); i++)
569            printf("s%d='%s'::", i, this->strings[i].c_str());
570        printf("\n");
571    }
572}
Note: See TracBrowser for help on using the repository browser.