ruby: message buffer: removes some unecessary functions.
[gem5.git] / src / base / str.cc
1 /*
2 * Copyright (c) 2001-2005 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Authors: Nathan Binkert
29 */
30
31 #include <cctype>
32 #include <cstring>
33 #include <iostream>
34 #include <limits>
35 #include <string>
36 #include <vector>
37
38 #include "base/intmath.hh"
39 #include "base/str.hh"
40
41 using namespace std;
42
43 bool
44 split_first(const string &s, string &lhs, string &rhs, char c)
45 {
46 string::size_type offset = s.find(c);
47 if (offset == string::npos) {
48 lhs = s;
49 rhs = "";
50 return false;
51 }
52
53 lhs = s.substr(0, offset);
54 rhs = s.substr(offset + 1);
55 return true;
56 }
57
58 bool
59 split_last(const string &s, string &lhs, string &rhs, char c)
60 {
61 string::size_type offset = s.rfind(c);
62 if (offset == string::npos) {
63 lhs = s;
64 rhs = "";
65 return false;
66 }
67
68 lhs = s.substr(0, offset);
69 rhs = s.substr(offset + 1);
70 return true;
71 }
72
73 void
74 tokenize(vector<string>& v, const string &s, char token, bool ignore)
75 {
76 string::size_type first = 0;
77 string::size_type last = s.find_first_of(token);
78
79 if (s.empty())
80 return;
81
82 if (ignore && last == first) {
83 while (last == first)
84 last = s.find_first_of(token, ++first);
85
86 if (last == string::npos) {
87 if (first != s.size())
88 v.push_back(s.substr(first));
89 return;
90 }
91 }
92
93 while (last != string::npos) {
94 v.push_back(s.substr(first, last - first));
95
96 if (ignore) {
97 first = s.find_first_not_of(token, last + 1);
98
99 if (first == string::npos)
100 return;
101 } else
102 first = last + 1;
103
104 last = s.find_first_of(token, first);
105 }
106
107 v.push_back(s.substr(first));
108 }
109
110 /**
111 * @todo This function will not handle the smallest negative decimal
112 * value for a signed type
113 */
114
115 template <class T>
116 inline bool
117 __to_number(string value, T &retval)
118 {
119 static const T maxnum = ((T)-1);
120 static const bool sign = numeric_limits<T>::is_signed;
121 static const int bits = numeric_limits<T>::digits;
122 static const T hexmax = maxnum & (((T)1 << (bits - 4)) - 1);
123 static const T octmax = maxnum & (((T)1 << (bits - 3)) - 1);
124 static const T signmax = numeric_limits<T>::max();
125 static const T decmax = signmax / 10;
126
127 #if 0
128 cout << "maxnum = 0x" << hex << (unsigned long long)maxnum << "\n"
129 << "sign = 0x" << hex << (unsigned long long)sign << "\n"
130 << "hexmax = 0x" << hex << (unsigned long long)hexmax << "\n"
131 << "octmax = 0x" << hex << (unsigned long long)octmax << "\n"
132 << "signmax = 0x" << hex << (unsigned long long)signmax << "\n"
133 << "decmax = 0x" << hex << (unsigned long long)decmax << "\n";
134 #endif
135
136 eat_white(value);
137
138 bool negative = false;
139 bool hex = false;
140 bool oct = false;
141 int last = value.size() - 1;
142 retval = 0;
143 int i = 0;
144
145 char c = value[i];
146 if (!isDec(c)) {
147 if (c == '-' && sign)
148 negative = true;
149 else
150 return false;
151 }
152 else {
153 retval += c - '0';
154 if (last == 0) return true;
155 }
156
157 if (c == '0')
158 oct = true;
159
160 c = value[++i];
161 if (oct) {
162 if (sign && negative)
163 return false;
164
165 if (!isOct(c)) {
166 if (c == 'X' || c == 'x') {
167 hex = true;
168 oct = false;
169 } else
170 return false;
171 }
172 else
173 retval += c - '0';
174 } else if (!isDec(c))
175 goto multiply;
176 else {
177 if (sign && negative && c == '0')
178 return false;
179
180 retval *= 10;
181 retval += c - '0';
182 if (last == 1) {
183 if (sign && negative) retval = -retval;
184 return true;
185 }
186 }
187
188 if (hex) {
189 if (last == 1)
190 return false;
191
192 for (i = 2; i <= last ; i++) {
193 c = value[i];
194 if (!isHex(c))
195 return false;
196
197 if (retval > hexmax) return false;
198 retval *= 16;
199 retval += hex2Int(c);
200 }
201 return true;
202 } else if (oct) {
203 for (i = 2; i <= last ; i++) {
204 c = value[i];
205 if (!isOct(c))
206 return false;
207
208 if (retval > octmax) return false;
209 retval *= 8;
210 retval += (c - '0');
211 }
212 return true;
213 }
214
215 for (i = 2; i < last ; i++) {
216 c = value[i];
217 if (!isDec(c))
218 goto multiply;
219
220 if (retval > decmax) return false;
221 bool atmax = retval == decmax;
222 retval *= 10;
223 retval += c - '0';
224 if (atmax && retval < decmax) return false;
225 if (sign && (retval & ((T)1 << (sizeof(T) * 8 - 1))))
226 return false;
227 }
228
229 c = value[last];
230 if (isDec(c)) {
231
232 if (retval > decmax) return false;
233 bool atmax = retval == decmax;
234 retval *= 10;
235 retval += c - '0';
236 if (atmax && retval < decmax) return false;
237 if (sign && negative) {
238 if ((retval & ((T)1 << (sizeof(T) * 8 - 1))) &&
239 retval >= (T)-signmax)
240 return false;
241 retval = -retval;
242 }
243 else
244 if (sign && (retval & ((T)1 << ((sizeof(T) * 8) - 1))))
245 return false;
246 return true;
247 }
248
249 multiply:
250 signed long long mult = 1;
251 T val;
252 switch (c) {
253 case 'k':
254 case 'K':
255 if (i != last) return false;
256 mult = 1024;
257 val = signmax / mult;
258 break;
259 case 'm':
260 case 'M':
261 if (i != last) return false;
262 mult = 1024 * 1024;
263 val = signmax / mult;
264 break;
265 case 'g':
266 case 'G':
267 if (i != last) return false;
268 mult = 1024 * 1024 * 1024;
269 val = signmax / mult;
270 break;
271 case 'e':
272 case 'E':
273 if (i >= last) return false;
274
275 mult = 0;
276 for (i++; i <= last; i++) {
277 c = value[i];
278 if (!isDec(c))
279 return false;
280
281 mult *= 10;
282 mult += c - '0';
283 }
284
285 for (i = 0; i < mult; i++) {
286 if (retval > signmax / 10)
287 return false;
288 retval *= 10;
289 if (sign && (retval & ((T)1 << (sizeof(T) * 8 - 1))))
290 return false;
291 }
292 if (sign && negative) {
293 if ((retval & ((T)1 << (sizeof(T) * 8 - 1))) &&
294 retval >= (T)-signmax)
295 return false;
296 retval = -retval;
297 }
298 else
299 if (sign && (retval & ((T)1 << ((sizeof(T) * 8) - 1))))
300 return false;
301
302 return true;
303
304 default:
305 return false;
306 }
307
308 if (sign && negative)
309 return false;
310
311 if (mult > (unsigned long long)signmax)
312 return false;
313
314 if (retval > val)
315 return false;
316
317 retval *= mult;
318
319 return true;
320 }
321
322 #define STN(type) \
323 template<> \
324 bool to_number<type>(const string &value, type &retval) \
325 { return __to_number(value, retval); }
326
327 STN(unsigned long long)
328 STN(signed long long)
329 STN(unsigned long)
330 STN(signed long)
331 STN(unsigned int)
332 STN(signed int)
333 STN(unsigned short)
334 STN(signed short)
335 STN(unsigned char)
336 STN(signed char)
337 STN(char)
338
339 template<>
340 bool to_number<bool>(const string &value, bool &retval)
341 {
342 string lowered = to_lower(value);
343
344 if (value == "0") {
345 retval = false;
346 return true;
347 }
348
349 if (value == "1"){
350 retval = true;
351 return true;
352 }
353
354 if (lowered == "false") {
355 retval = false;
356 return true;
357 }
358
359 if (lowered == "true"){
360 retval = true;
361 return true;
362 }
363
364 if (lowered == "no") {
365 retval = false;
366 return true;
367 }
368
369 if (lowered == "yes"){
370 retval = true;
371 return true;
372 }
373
374 return false;
375 }