Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/network/src/util/SubString.cc @ 1494

Last change on this file since 1494 was 1494, checked in by rgrieder, 16 years ago
  • set the svn:eol-style property to all files so, that where ever you check out, you'll get the right line endings (had to change every file with mixed endings to windows in order to set the property)
  • Property svn:eol-style set to native
File size: 17.0 KB
RevLine 
[1494]1/* *   ORXONOX - the hottest 3D action shooter ever to exist *                    > www.orxonox.net < * * *   License notice: * *   This program is free software; you can redistribute it and/or *   modify it under the terms of the GNU General Public License *   as published by the Free Software Foundation; either version 2 *   of the License, or (at your option) any later version. * *   This program is distributed in the hope that it will be useful, *   but WITHOUT ANY WARRANTY; without even the implied warranty of *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *   GNU General Public License for more details. * *   You should have received a copy of the GNU General Public License *   along with this program; if not, write to the Free Software *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA. * *   Author: *      Christian Meyer *   Co-authors: *      Benjamin Grauer *////  splitLine//  STL string tokenizer////  Created by Clemens Wacha.//  Version 1.0//  Copyright (c) 2005 Clemens Wacha. All rights reserved.// */
[836]2#include "SubString.h"
3
4/**
5 * @brief default constructor
6 */
7SubString::SubString()
8{}
9
10
11/**
12 * @brief create a SubString from
[849]13 * @param string the String to Split
[836]14 * @param delimiter the Character at which to split string (delimiter)
15 */
16SubString::SubString(const std::string& string, char delimiter)
17{
18  this->split(string, delimiter);
19}
20
21
22/**
23 * @brief Splits a String into multiple splitters.
24 * @param string the String to split
25 * @param delimiters multiple set of characters at what to split. (delimiters)
26 * @param delimiterNeighbours neighbours of the delimiters, that will be erased only when near a delimiter.
27 * @param emptyEntries If empty entries should be allewed or removed.
28 * @param escapeChar The Escape Character that overrides splitters commends and so on...
29 * @param safemode_char within these characters splitting won't happen
30 * @param comment_char the Comment character.
31 */
32SubString::SubString(const std::string& string,
33                     const std::string& delimiters, const std::string& delimiterNeighbours, bool emptyEntries,
[1494]34                     char escapeChar, bool removeEscapeChar, char safemode_char, bool removeSafemodeChar,                     char openparenthesis_char, char closeparenthesis_char, bool removeParenthesisChars, char comment_char)
[836]35{
[1349]36  SubString::splitLine(this->strings, this->bInSafemode, string, delimiters, delimiterNeighbours, emptyEntries, escapeChar, removeEscapeChar, safemode_char, removeSafemodeChar, openparenthesis_char, closeparenthesis_char, removeParenthesisChars, comment_char);
[836]37}
38
39/**
40 * @brief creates a SubSet of a SubString.
41 * @param subString the SubString to take a set from.
42 * @param subSetBegin the beginning to the end
43 */
44SubString::SubString(const SubString& subString, unsigned int subSetBegin)
45{
[1494]46  for (unsigned int i = subSetBegin; i < subString.size(); i++)  {
47    this->strings.push_back(subString[i]);    this->bInSafemode.push_back(subString.isInSafemode(i));  }
[836]48}
49
50
51/**
52 * @brief creates a SubSet of a SubString.
53 * @param subString the SubString to take a Set from
54 * @param subSetBegin the beginning to the end
55 * @param subSetEnd the end of the SubSet (max subString.size() will be checked internaly)
56 */
57SubString::SubString(const SubString& subString, unsigned int subSetBegin, unsigned int subSetEnd)
58{
[1494]59  for (unsigned int i = subSetBegin; i < subString.size() && i < subSetEnd; i++)  {
60    this->strings.push_back(subString[i]);    this->bInSafemode.push_back(subString.isInSafemode(i));  }
[836]61}
62
63/**
64 * @brief creates a Substring from a count and values set.
65 * @param argc: the Arguments Count.
66 * @param argv: Argument Values.
67 */
68SubString::SubString(unsigned int argc, const char** argv)
69{
[1494]70  for(unsigned int i = 0; i < argc; ++i)  {
71    this->strings.push_back(std::string(argv[i]));    this->bInSafemode.push_back(false);  }
[836]72}
73
74/**
75 * @brief removes the object from memory
76 */
77SubString::~SubString()
78{ }
79
80/** @brief An empty String */
81// const std::string SubString::emptyString = "";
82/** @brief Helper that gets you a String consisting of all White Spaces */
83const std::string SubString::WhiteSpaces = " \n\t";
84/** @brief Helper that gets you a String consisting of all WhiteSpaces and the Comma */
85const std::string SubString::WhiteSpacesWithComma = " \n\t,";
86/** An Empty SubString */
87const SubString SubString::NullSubString = SubString();
88
89/**
90 * @brief stores the Value of subString in this SubString
91 * @param subString will be copied into this String.
92 * @returns this SubString.
93 */
94SubString& SubString::operator=(const SubString& subString)
95{
[1494]96  this->strings = subString.strings;  this->bInSafemode = subString.bInSafemode;
[836]97  return *this;
98}
99
100
101/**
102 * @brief comparator.
103 * @param subString the SubString to compare against this one.
104 * @returns true if the Stored Strings match
105 */
106bool SubString::operator==(const SubString& subString) const
107{
[1052]108  return ((this->strings == subString.strings) && (this->bInSafemode == subString.bInSafemode));
[836]109}
110
111/**
112 * @brief comparator.
113 * @param subString the SubString to compare against this one.
114 * @returns true if the Stored Strings match
115 */
116bool SubString::compare(const SubString& subString) const
117{
118  return (*this == subString);
119}
120
121/**
122 * @brief comparator.
123 * @param subString the SubString to compare against this one.
124 * @param length how many entries to compare. (from 0 to length)
125 * @returns true if the Stored Strings match
126 */
127bool SubString::compare(const SubString& subString, unsigned int length) const
128{
129  if (length > this->size() || length > subString.size())
130    return false;
131
132  for (unsigned int i = 0; i < length; i++)
[1052]133    if ((this->strings[i] != subString.strings[i]) || (this->bInSafemode[i] != subString.bInSafemode[i]))
[836]134      return false;
135  return true;
136}
137
138
139/**
140 * @brief append operator
141 * @param subString the String to append.
142 * @returns a SubString where this and subString are appended.
143 */
144SubString SubString::operator+(const SubString& subString) const
145{
146  return SubString(*this) += subString;
147}
148
149
150/**
151 * @brief append operator.
152 * @param subString append subString to this SubString.
153 * @returns this substring appended with subString
154 */
155SubString& SubString::operator+=(const SubString& subString)
156{
[1494]157  for (unsigned int i = 0; i < subString.size(); i++)  {
158    this->strings.push_back(subString[i]);    this->bInSafemode.push_back(subString.isInSafemode(i));  }
[836]159  return *this;
160}
161
162
163/**
164 * @brief Split the String at
165 * @param string where to split
166 * @param splitter delimiter.
167 */
168unsigned int SubString::split(const std::string& string, char splitter)
169{
[1494]170  this->strings.clear();  this->bInSafemode.clear();
[836]171  char split[2];
172  split[0] = splitter;
173  split[1] = '\0';
[1052]174  SubString::splitLine(this->strings, this->bInSafemode, string, split);
[836]175  return strings.size();
176}
177
178
179/**
180 * @brief Splits a String into multiple splitters.
181 * @param string the String to split
182 * @param delimiters multiple set of characters at what to split. (delimiters)
183 * @param delimiterNeighbours: Neighbours to the Delimiters that will be erased too.
184 * @param emptyEntries: If empty entries are added to the List of SubStrings
185 * @param escapeChar The Escape Character that overrides splitters commends and so on...
186 * @param safemode_char within these characters splitting won't happen
187 * @param comment_char the Comment character.
188 */
189unsigned int SubString::split(const std::string& string,
190                              const std::string& delimiters, const std::string& delimiterNeighbours, bool emptyEntries,
[1494]191                              char escapeChar, bool removeExcapeChar, char safemode_char, bool removeSafemodeChar,                              char openparenthesis_char, char closeparenthesis_char, bool removeParenthesisChars, char comment_char)
[836]192{
[1494]193  this->strings.clear();  this->bInSafemode.clear();
[1052]194  SubString::splitLine(this->strings, this->bInSafemode, string, delimiters, delimiterNeighbours, emptyEntries, escapeChar, removeExcapeChar, safemode_char, removeSafemodeChar, openparenthesis_char, closeparenthesis_char, removeParenthesisChars, comment_char);
[836]195  return this->strings.size();
196}
197
198
199/**
200 * @brief joins together all Strings of this Substring.
201 * @param delimiter the String between the subStrings.
202 * @returns the joined String.
203 */
204std::string SubString::join(const std::string& delimiter) const
205{
206  if (!this->strings.empty())
207  {
208    std::string retVal = this->strings[0];
209    for (unsigned int i = 1; i < this->strings.size(); i++)
210      retVal += delimiter + this->strings[i];
211    return retVal;
212  }
213  else
214  {
215    static std::string empty;
216    return empty;
217  }
218}
219
220
221/**
222 * @brief creates a SubSet of a SubString.
223 * @param subSetBegin the beginning to the end
224 * @returns the SubSet
225 *
226 * This function is added for your convenience, and does the same as
227 * SubString::SubString(const SubString& subString, unsigned int subSetBegin)
228 */
229SubString SubString::subSet(unsigned int subSetBegin) const
230{
231  return SubString(*this, subSetBegin);
232}
233
234
235/**
236 * @brief creates a SubSet of a SubString.
237 * @param subSetBegin the beginning to
238 * @param subSetEnd the end of the SubSet to select (if bigger than subString.size() it will be downset.)
239 * @returns the SubSet
240 *
241 * This function is added for your convenience, and does the same as
242 * SubString::SubString(const SubString& subString, unsigned int subSetBegin)
243 */
244SubString SubString::subSet(unsigned int subSetBegin, unsigned int subSetEnd) const
245{
246  return SubString(*this, subSetBegin, subSetEnd);
247}
248
249
250/**
251 * @brief splits line into tokens and stores them in ret.
252 * @param ret the Array, where the Splitted strings will be stored in
253 * to the beginning of the current token is stored
254 * @param line the inputLine to split
255 * @param delimiters a String of Delimiters (here the input will be splitted)
256 * @param delimiterNeighbours Naighbours to the Delimitter, that will be removed if they are to the left or the right of a Delimiter.
257 * @param emptyEntries: if empty Strings are added to the List of Strings.
258 * @param escape_char: Escape carater (escapes splitters)
[1494]259 * @param safemode_char: the beginning of the safemode is marked with this * @param removeSafemodeChar removes the safemode_char from the beginning and the ending of a token * @param openparenthesis_char the beginning of a safemode is marked with this * @param closeparenthesis_char the ending of a safemode is marked with this * @param removeParenthesisChars removes the parenthesis from the beginning and the ending of a token
[836]260 * @param comment_char: the beginning of a comment is marked with this: (until the end of a Line)
261 * @param start_state: the Initial state on how to parse the String.
[1052]262 * @return SPLIT_LINE_STATE the parser was in when returning
[836]263 *
264 * This is the Actual Splitting Algorithm from Clemens Wacha
265 * Supports delimiters, escape characters,
266 * ignores special  characters between safemode_char and between comment_char and linend '\n'.
267 */
268SubString::SPLIT_LINE_STATE
[1494]269SubString::splitLine(std::vector<std::string>& ret,                     std::vector<bool>& bInSafemode,
[836]270                     const std::string& line,
271                     const std::string& delimiters,
272                     const std::string& delimiterNeighbours,
273                     bool emptyEntries,
[1494]274                     char escape_char,                     bool removeExcapeChar,
275                     char safemode_char,                     bool removeSafemodeChar,                     char openparenthesis_char,                     char closeparenthesis_char,                     bool removeParenthesisChars,
[836]276                     char comment_char,
277                     SPLIT_LINE_STATE start_state)
278{
279  SPLIT_LINE_STATE state = start_state;
280  unsigned int i = 0;
281  unsigned int fallBackNeighbours = 0;
282
[1494]283  std::string token;  bool inSafemode = false;
[836]284
[1494]285  if(start_state != SL_NORMAL && ret.size() > 0)  {    token = ret[ret.size()-1];
286    ret.pop_back();  }  if(start_state != SL_NORMAL && bInSafemode.size() > 0)  {    inSafemode = bInSafemode[bInSafemode.size()-1];    bInSafemode.pop_back();  }
[836]287  while(i < line.size())
288  {
289    switch(state)
290    {
291      case SL_NORMAL:
292        if(line[i] == escape_char)
293        {
[1494]294          state = SL_ESCAPE;          if (!removeExcapeChar)            token += line[i];
[836]295        }
296        else if(line[i] == safemode_char)
297        {
[1494]298          state = SL_SAFEMODE;          inSafemode = true;          if (!removeSafemodeChar)            token += line[i];
299        }        else if(line[i] == openparenthesis_char)        {          state = SL_PARENTHESES;          inSafemode = true;          if (!removeParenthesisChars)            token += line[i];        }
[836]300        else if(line[i] == comment_char)
301        {
302          if (fallBackNeighbours > 0)
303            token = token.substr(0, token.size() - fallBackNeighbours);
304          /// FINISH
305          if(emptyEntries || token.size() > 0)
306          {
[1494]307            ret.push_back(token);            token.clear();            bInSafemode.push_back(inSafemode);            inSafemode = false;          }
[836]308          token += line[i];       // EAT
309          state = SL_COMMENT;
310        }
311        else if(delimiters.find(line[i]) != std::string::npos)
312        {
313          // line[i] is a delimiter
314          if (fallBackNeighbours > 0)
315            token = token.substr(0, token.size() - fallBackNeighbours);
316          /// FINISH
317          if(emptyEntries || token.size() > 0)
318          {
319            ret.push_back(token);
320            token.clear();
[1494]321            bInSafemode.push_back(inSafemode);            inSafemode = false;          }
[836]322          state = SL_NORMAL;
323        }
324        else
325        {
326          if (delimiterNeighbours.find(line[i]) != std::string::npos)
327          {
328            if (token.size() > 0)
329              ++fallBackNeighbours;
330            else
331            {
332              i++;
333              continue;
334            }
335          }
336          else
337            fallBackNeighbours = 0;
338          token += line[i];       // EAT
339        }
340        break;
[1494]341      case SL_ESCAPE:        if (!removeSafemodeChar)          token += line[i];        else        {
[1052]342          if(line[i] == 'n') token += '\n';
343          else if(line[i] == 't') token += '\t';
344          else if(line[i] == 'v') token += '\v';
345          else if(line[i] == 'b') token += '\b';
346          else if(line[i] == 'r') token += '\r';
347          else if(line[i] == 'f') token += '\f';
348          else if(line[i] == 'a') token += '\a';
349          else if(line[i] == '?') token += '\?';
[1494]350          else token += line[i];  // EAT        }
[836]351        state = SL_NORMAL;
352        break;
353      case SL_SAFEMODE:
354        if(line[i] == safemode_char)
355        {
356          state = SL_NORMAL;
[1494]357          if (!removeSafemodeChar)            token += line[i];        }
[836]358        else if(line[i] == escape_char)
359        {
360          state = SL_SAFEESCAPE;
361        }
362        else
363        {
364          token += line[i];       // EAT
365        }
[1494]366        break;      case SL_SAFEESCAPE:
[836]367        if(line[i] == 'n') token += '\n';
368        else if(line[i] == 't') token += '\t';
369        else if(line[i] == 'v') token += '\v';
370        else if(line[i] == 'b') token += '\b';
371        else if(line[i] == 'r') token += '\r';
372        else if(line[i] == 'f') token += '\f';
373        else if(line[i] == 'a') token += '\a';
374        else if(line[i] == '?') token += '\?';
375        else token += line[i];  // EAT
376        state = SL_SAFEMODE;
377        break;
[1494]378      case SL_PARENTHESES:        if(line[i] == closeparenthesis_char)        {          state = SL_NORMAL;          if (!removeParenthesisChars)            token += line[i];        }        else if(line[i] == escape_char)        {          state = SL_PARENTHESESESCAPE;        }        else        {          token += line[i];       // EAT        }        break;      case SL_PARENTHESESESCAPE:        if(line[i] == 'n') token += '\n';        else if(line[i] == 't') token += '\t';        else if(line[i] == 'v') token += '\v';        else if(line[i] == 'b') token += '\b';        else if(line[i] == 'r') token += '\r';        else if(line[i] == 'f') token += '\f';        else if(line[i] == 'a') token += '\a';        else if(line[i] == '?') token += '\?';        else token += line[i];  // EAT        state = SL_PARENTHESES;        break;
[836]379      case SL_COMMENT:
380        if(line[i] == '\n')
381        {
382          /// FINISH
383          if(token.size() > 0)
384          {
385            ret.push_back(token);
386            token.clear();
[1494]387            bInSafemode.push_back(inSafemode);            inSafemode = false;          }
[836]388          state = SL_NORMAL;
389        }
390        else
391        {
392          token += line[i];       // EAT
393        }
394        break;
395
396      default:
397        // nothing
398        break;
399    }
400    i++;
401  }
402
403  /// FINISH
404  if (fallBackNeighbours > 0)
405    token = token.substr(0, token.size() - fallBackNeighbours);
406  if(emptyEntries || token.size() > 0)
407  {
408    ret.push_back(token);
409    token.clear();
[1494]410    bInSafemode.push_back(inSafemode);    inSafemode = false;  }
[836]411  return(state);
412}
413
414
415/**
416 * @brief Some nice debug information about this SubString
417 */
418void SubString::debug() const
419{
420  printf("Substring-information::count=%d ::", this->strings.size());
421  for (unsigned int i = 0; i < this->strings.size(); i++)
422    printf("s%d='%s'::", i, this->strings[i].c_str());
423  printf("\n");
424}
Note: See TracBrowser for help on using the repository browser.