Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/pch/src/util/SubString.cc @ 3146

Last change on this file since 3146 was 3146, checked in by rgrieder, 15 years ago

Found another few unnecessary includes in util (and added two others that followed due to this change).

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