Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/proxy/src/lib/util/substring.cc @ 9313

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

orxonox/proxy: new substring functions

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