1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2001-2019 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials
5 // are made available under the terms of the Eclipse Public License v2.0
6 // which accompanies this distribution, and is available at
7 // http://www.eclipse.org/legal/epl-v20.html
8 // SPDX-License-Identifier: EPL-2.0
9 /****************************************************************************/
10 /// @file    StringTokenizer.cpp
11 /// @author  Daniel Krajzewicz
12 /// @author  Jakob Erdmann
13 /// @author  Michael Behrisch
14 /// @date    ?
15 /// @version $Id$
16 ///
17 // A java-style StringTokenizer for c++ (stl)
18 /****************************************************************************/
19 
20 
21 // ===========================================================================
22 // included modules
23 // ===========================================================================
24 #include <config.h>
25 
26 #include <string>
27 #include <vector>
28 #include <iostream> // !!! debug only
29 #include "UtilExceptions.h"
30 #include "StringTokenizer.h"
31 
32 
33 // ===========================================================================
34 // variable definitions
35 // ===========================================================================
36 const int StringTokenizer::NEWLINE = -256;
37 const int StringTokenizer::WHITECHARS = -257;
38 const int StringTokenizer::SPACE = 32;
39 const int StringTokenizer::TAB = 9;
40 
41 
42 // ===========================================================================
43 // method definitions
44 // ===========================================================================
StringTokenizer(std::string tosplit)45 StringTokenizer::StringTokenizer(std::string tosplit)
46     : myTosplit(tosplit), myPos(0) {
47     prepareWhitechar(tosplit);
48 }
49 
50 
StringTokenizer(std::string tosplit,std::string token,bool splitAtAllChars)51 StringTokenizer::StringTokenizer(std::string tosplit, std::string token, bool splitAtAllChars)
52     : myTosplit(tosplit), myPos(0) {
53     prepare(tosplit, token, splitAtAllChars);
54 }
55 
56 
StringTokenizer(std::string tosplit,int special)57 StringTokenizer::StringTokenizer(std::string tosplit, int special)
58     : myTosplit(tosplit), myPos(0) {
59     switch (special) {
60         case NEWLINE:
61             prepare(tosplit, "\r\n", true);
62             break;
63         case TAB:
64             prepare(tosplit, "\t", true);
65             break;
66         case WHITECHARS:
67             prepareWhitechar(tosplit);
68             break;
69         default:
70             char* buf = new char[2];
71             buf[0] = (char) special;
72             buf[1] = 0;
73             prepare(tosplit, buf, false);
74             delete[] buf;
75             break;
76     }
77 }
78 
79 
~StringTokenizer()80 StringTokenizer::~StringTokenizer() {}
81 
reinit()82 void StringTokenizer::reinit() {
83     myPos = 0;
84 }
85 
hasNext()86 bool StringTokenizer::hasNext() {
87     return myPos != (int)myStarts.size();
88 }
89 
next()90 std::string StringTokenizer::next() {
91     if (myPos >= (int)myStarts.size()) {
92         throw OutOfBoundsException();
93     }
94     if (myLengths[myPos] == 0) {
95         myPos++;
96         return "";
97     }
98     int start = myStarts[myPos];
99     int length = myLengths[myPos++];
100     return myTosplit.substr(start, length);
101 }
102 
front()103 std::string StringTokenizer::front() {
104     if (myStarts.size() == 0) {
105         throw OutOfBoundsException();
106     }
107     if (myLengths[0] == 0) {
108         return "";
109     }
110     return myTosplit.substr(myStarts[0], myLengths[0]);
111 }
112 
get(int pos) const113 std::string StringTokenizer::get(int pos) const {
114     if (pos >= (int)myStarts.size()) {
115         throw OutOfBoundsException();
116     }
117     if (myLengths[pos] == 0) {
118         return "";
119     }
120     int start = myStarts[pos];
121     int length = myLengths[pos];
122     return myTosplit.substr(start, length);
123 }
124 
125 
size() const126 int StringTokenizer::size() const {
127     return (int)myStarts.size();
128 }
129 
prepare(const std::string & tosplit,const std::string & token,bool splitAtAllChars)130 void StringTokenizer::prepare(const std::string& tosplit, const std::string& token, bool splitAtAllChars) {
131     int beg = 0;
132     int len = (int)token.length();
133     if (splitAtAllChars) {
134         len = 1;
135     }
136     while (beg < (int)tosplit.length()) {
137         std::string::size_type end;
138         if (splitAtAllChars) {
139             end = tosplit.find_first_of(token, beg);
140         } else {
141             end = tosplit.find(token, beg);
142         }
143         if (end == std::string::npos) {
144             end = tosplit.length();
145         }
146         myStarts.push_back(beg);
147         myLengths.push_back((int)end - beg);
148         beg = (int)end + len;
149         if (beg == (int)tosplit.length()) {
150             myStarts.push_back(beg - 1);
151             myLengths.push_back(0);
152         }
153     }
154 }
155 
prepareWhitechar(const std::string & tosplit)156 void StringTokenizer::prepareWhitechar(const std::string& tosplit) {
157     std::string::size_type len = tosplit.length();
158     std::string::size_type beg = 0;
159     while (beg < len && tosplit[beg] <= SPACE) {
160         beg++;
161     }
162     while (beg != std::string::npos && beg < len) {
163         std::string::size_type end = beg;
164         while (end < len && tosplit[end] > SPACE) {
165             end++;
166         }
167         myStarts.push_back((int)beg);
168         myLengths.push_back((int)end - (int)beg);
169         beg = end;
170         while (beg < len && tosplit[beg] <= SPACE) {
171             beg++;
172         }
173     }
174 }
175 
176 
177 std::vector<std::string>
getVector()178 StringTokenizer::getVector() {
179     std::vector<std::string> ret;
180     ret.reserve(size());
181     while (hasNext()) {
182         ret.push_back(next());
183     }
184     reinit();
185     return ret;
186 }
187 
188 
189 /****************************************************************************/
190