Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/weapon2/src/util/SubString.cc @ 2726

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