str.cc revision 2665
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 <ctype.h> 32 33#include <cstring> 34#include <iostream> 35#include <string> 36#include <vector> 37 38#include "base/intmath.hh" 39#include "base/str.hh" 40 41using namespace std; 42 43bool 44split_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 58bool 59split_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 73void 74tokenize(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 115template <class T> 116inline bool 117__to_number(string value, T &retval) 118{ 119 static const T maxnum = ((T)-1); 120 static const bool sign = maxnum < 0; 121 static const int bits = sizeof(T) * 8; 122 static const T hexmax = maxnum & (((T)1 << (bits - 4 - sign)) - 1); 123 static const T octmax = maxnum & (((T)1 << (bits - 3 - sign)) - 1); 124 static const T signmax = 125 (sign) ? maxnum & (((T)1 << (bits - 1)) - 1) : maxnum; 126 static const T decmax = signmax / 10; 127 128#if 0 129 cout << "maxnum = 0x" << hex << (unsigned long long)maxnum << "\n" 130 << "sign = 0x" << hex << (unsigned long long)sign << "\n" 131 << "hexmax = 0x" << hex << (unsigned long long)hexmax << "\n" 132 << "octmax = 0x" << hex << (unsigned long long)octmax << "\n" 133 << "signmax = 0x" << hex << (unsigned long long)signmax << "\n" 134 << "decmax = 0x" << hex << (unsigned long long)decmax << "\n"; 135#endif 136 137 eat_white(value); 138 139 bool negative = false; 140 bool hex = false; 141 bool oct = false; 142 int last = value.size() - 1; 143 retval = 0; 144 int i = 0; 145 146 char c = value[i]; 147 if (!isDec(c)) { 148 if (c == '-' && sign) 149 negative = true; 150 else 151 return false; 152 } 153 else { 154 retval += c - '0'; 155 if (last == 0) return true; 156 } 157 158 if (c == '0') 159 oct = true; 160 161 c = value[++i]; 162 if (oct) { 163 if (sign && negative) 164 return false; 165 166 if (!isOct(c)) { 167 if (c == 'X' || c == 'x') { 168 hex = true; 169 oct = false; 170 } else 171 return false; 172 } 173 else 174 retval += c - '0'; 175 } else if (!isDec(c)) 176 goto multiply; 177 else { 178 if (sign && negative && c == '0') 179 return false; 180 181 retval *= 10; 182 retval += c - '0'; 183 if (last == 1) { 184 if (sign && negative) retval = -retval; 185 return true; 186 } 187 } 188 189 if (hex) { 190 if (last == 1) 191 return false; 192 193 for (i = 2; i <= last ; i++) { 194 c = value[i]; 195 if (!isHex(c)) 196 return false; 197 198 if (retval > hexmax) return false; 199 retval *= 16; 200 retval += hex2Int(c); 201 } 202 return true; 203 } else if (oct) { 204 for (i = 2; i <= last ; i++) { 205 c = value[i]; 206 if (!isOct(c)) 207 return false; 208 209 if (retval > octmax) return false; 210 retval *= 8; 211 retval += (c - '0'); 212 } 213 return true; 214 } 215 216 for (i = 2; i < last ; i++) { 217 c = value[i]; 218 if (!isDec(c)) 219 goto multiply; 220 221 if (retval > decmax) return false; 222 bool atmax = retval == decmax; 223 retval *= 10; 224 retval += c - '0'; 225 if (atmax && retval < decmax) return false; 226 if (sign && (retval & ((T)1 << (sizeof(T) * 8 - 1)))) 227 return false; 228 } 229 230 c = value[last]; 231 if (isDec(c)) { 232 233 if (retval > decmax) return false; 234 bool atmax = retval == decmax; 235 retval *= 10; 236 retval += c - '0'; 237 if (atmax && retval < decmax) return false; 238 if (sign && negative) { 239 if ((retval & ((T)1 << (sizeof(T) * 8 - 1))) && 240 retval >= (T)-signmax) 241 return false; 242 retval = -retval; 243 } 244 else 245 if (sign && (retval & ((T)1 << ((sizeof(T) * 8) - 1)))) 246 return false; 247 return true; 248 } 249 250 multiply: 251 signed long long mult = 1; 252 T val; 253 switch (c) { 254 case 'k': 255 case 'K': 256 if (i != last) return false; 257 mult = 1024; 258 val = signmax / mult; 259 break; 260 case 'm': 261 case 'M': 262 if (i != last) return false; 263 mult = 1024 * 1024; 264 val = signmax / mult; 265 break; 266 case 'g': 267 case 'G': 268 if (i != last) return false; 269 mult = 1024 * 1024 * 1024; 270 val = signmax / mult; 271 break; 272 case 'e': 273 case 'E': 274 if (i >= last) return false; 275 276 mult = 0; 277 for (i++; i <= last; i++) { 278 c = value[i]; 279 if (!isDec(c)) 280 return false; 281 282 mult *= 10; 283 mult += c - '0'; 284 } 285 286 for (i = 0; i < mult; i++) { 287 if (retval > signmax / 10) 288 return false; 289 retval *= 10; 290 if (sign && (retval & ((T)1 << (sizeof(T) * 8 - 1)))) 291 return false; 292 } 293 if (sign && negative) { 294 if ((retval & ((T)1 << (sizeof(T) * 8 - 1))) && 295 retval >= (T)-signmax) 296 return false; 297 retval = -retval; 298 } 299 else 300 if (sign && (retval & ((T)1 << ((sizeof(T) * 8) - 1)))) 301 return false; 302 303 return true; 304 305 default: 306 return false; 307 } 308 309 if (sign && negative) 310 return false; 311 312 if (mult > (unsigned long long)signmax) 313 return false; 314 315 if (retval > val) 316 return false; 317 318 retval *= mult; 319 320 return true; 321} 322 323#define STN(type) \ 324template<> \ 325bool to_number<type>(const string &value, type &retval) \ 326{ return __to_number(value, retval); } 327 328STN(unsigned long long); 329STN(signed long long); 330STN(unsigned long); 331STN(signed long); 332STN(unsigned int); 333STN(signed int); 334STN(unsigned short); 335STN(signed short); 336STN(unsigned char); 337STN(signed char); 338 339template<> 340bool 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} 376