Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/new_class_id/src/lib/util/substring.cc @ 9740

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

more convertibles, more generic

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