Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/trunk/src/lib/util/substring.cc @ 10767

Last change on this file since 10767 was 9869, checked in by bensch, 18 years ago

orxonox/trunk: merged the new_class_id branche back to the trunk.
merged with command:
svn merge https://svn.orxonox.net/orxonox/branches/new_class_id trunk -r9683:HEAD
no conflicts… puh..

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