Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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