Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 7462 was 7398, checked in by bensch, 19 years ago

orxonox/trunk: SubString more functionality

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