str.cc revision 1762
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 29#include <iostream> 30 31#include <string.h> 32#include <ctype.h> 33 34#include <string> 35#include <vector> 36 37#include "base/intmath.hh" 38#include "base/str.hh" 39 40using namespace std; 41 42bool 43split_first(const string &s, string &lhs, string &rhs, char c) 44{ 45 string::size_type offset = s.find(c); 46 if (offset == string::npos) { 47 lhs = s; 48 rhs = ""; 49 return false; 50 } 51 52 lhs = s.substr(0, offset); 53 rhs = s.substr(offset + 1); 54 return true; 55} 56 57bool 58split_last(const string &s, string &lhs, string &rhs, char c) 59{ 60 string::size_type offset = s.rfind(c); 61 if (offset == string::npos) { 62 lhs = s; 63 rhs = ""; 64 return false; 65 } 66 67 lhs = s.substr(0, offset); 68 rhs = s.substr(offset + 1); 69 return true; 70} 71 72void 73tokenize(vector<string>& v, const string &s, char token, bool ignore) 74{ 75 string::size_type first = 0; 76 string::size_type last = s.find_first_of(token); 77 78 if (ignore) { 79 if (last == first) { 80 while (last == first) 81 last = s.find_first_of(token, ++first); 82 83 if (last == string::npos) { 84 v.push_back(s); 85 return; 86 } 87 } 88 } 89 90 while (last != string::npos) { 91 v.push_back(s.substr(first, last - first)); 92 93 if (ignore) { 94 first = s.find_first_not_of(token, last + 1); 95 96 if (first == string::npos) 97 return; 98 } else 99 first = last + 1; 100 101 last = s.find_first_of(token, first); 102 } 103 104 v.push_back(s.substr(first)); 105} 106 107/** 108 * @todo This function will not handle the smallest negative decimal 109 * value for a signed type 110 */ 111 112template <class T> 113inline bool 114__to_number(string value, T &retval) 115{ 116 static const T maxnum = ((T)-1); 117 static const bool sign = maxnum < 0; 118 static const int bits = sizeof(T) * 8; 119 static const T hexmax = maxnum & (((T)1 << (bits - 4 - sign)) - 1); 120 static const T octmax = maxnum & (((T)1 << (bits - 3 - sign)) - 1); 121 static const T signmax = 122 (sign) ? maxnum & (((T)1 << (bits - 1)) - 1) : maxnum; 123 static const T decmax = signmax / 10; 124 125#if 0 126 cout << "maxnum = 0x" << hex << (unsigned long long)maxnum << "\n" 127 << "sign = 0x" << hex << (unsigned long long)sign << "\n" 128 << "hexmax = 0x" << hex << (unsigned long long)hexmax << "\n" 129 << "octmax = 0x" << hex << (unsigned long long)octmax << "\n" 130 << "signmax = 0x" << hex << (unsigned long long)signmax << "\n" 131 << "decmax = 0x" << hex << (unsigned long long)decmax << "\n"; 132#endif 133 134 eat_white(value); 135 136 bool negative = false; 137 bool hex = false; 138 bool oct = false; 139 int last = value.size() - 1; 140 retval = 0; 141 int i = 0; 142 143 char c = value[i]; 144 if (!IsDec(c)) { 145 if (c == '-' && sign) 146 negative = true; 147 else 148 return false; 149 } 150 else { 151 retval += c - '0'; 152 if (last == 0) return true; 153 } 154 155 if (c == '0') 156 oct = true; 157 158 c = value[++i]; 159 if (oct) { 160 if (sign && negative) 161 return false; 162 163 if (!IsOct(c)) { 164 if (c == 'X' || c == 'x') { 165 hex = true; 166 oct = false; 167 } else 168 return false; 169 } 170 else 171 retval += c - '0'; 172 } else if (!IsDec(c)) 173 goto multiply; 174 else { 175 if (sign && negative && c == '0') 176 return false; 177 178 retval *= 10; 179 retval += c - '0'; 180 if (last == 1) { 181 if (sign && negative) retval = -retval; 182 return true; 183 } 184 } 185 186 if (hex) { 187 if (last == 1) 188 return false; 189 190 for (i = 2; i <= last ; i++) { 191 c = value[i]; 192 if (!IsHex(c)) 193 return false; 194 195 if (retval > hexmax) return false; 196 retval *= 16; 197 retval += Hex2Int(c); 198 } 199 return true; 200 } else if (oct) { 201 for (i = 2; i <= last ; i++) { 202 c = value[i]; 203 if (!IsOct(c)) 204 return false; 205 206 if (retval > octmax) return false; 207 retval *= 8; 208 retval += (c - '0'); 209 } 210 return true; 211 } 212 213 for (i = 2; i < last ; i++) { 214 c = value[i]; 215 if (!IsDec(c)) 216 goto multiply; 217 218 if (retval > decmax) return false; 219 bool atmax = retval == decmax; 220 retval *= 10; 221 retval += c - '0'; 222 if (atmax && retval < decmax) return false; 223 if (sign && (retval & ((T)1 << (sizeof(T) * 8 - 1)))) 224 return false; 225 } 226 227 c = value[last]; 228 if (IsDec(c)) { 229 230 if (retval > decmax) return false; 231 bool atmax = retval == decmax; 232 retval *= 10; 233 retval += c - '0'; 234 if (atmax && retval < decmax) return false; 235 if (sign && negative) { 236 if ((retval & ((T)1 << (sizeof(T) * 8 - 1))) && 237 retval >= (T)-signmax) 238 return false; 239 retval = -retval; 240 } 241 else 242 if (sign && (retval & ((T)1 << ((sizeof(T) * 8) - 1)))) 243 return false; 244 return true; 245 } 246 247 multiply: 248 signed long long mult = 1; 249 T val; 250 switch (c) { 251 case 'k': 252 case 'K': 253 if (i != last) return false; 254 mult = 1024; 255 val = signmax / mult; 256 break; 257 case 'm': 258 case 'M': 259 if (i != last) return false; 260 mult = 1024 * 1024; 261 val = signmax / mult; 262 break; 263 case 'g': 264 case 'G': 265 if (i != last) return false; 266 mult = 1024 * 1024 * 1024; 267 val = signmax / mult; 268 break; 269 case 'e': 270 case 'E': 271 if (i >= last) return false; 272 273 mult = 0; 274 for (i++; i <= last; i++) { 275 c = value[i]; 276 if (!IsDec(c)) 277 return false; 278 279 mult *= 10; 280 mult += c - '0'; 281 } 282 283 for (i = 0; i < mult; i++) { 284 if (retval > signmax / 10) 285 return false; 286 retval *= 10; 287 if (sign && (retval & ((T)1 << (sizeof(T) * 8 - 1)))) 288 return false; 289 } 290 if (sign && negative) { 291 if ((retval & ((T)1 << (sizeof(T) * 8 - 1))) && 292 retval >= (T)-signmax) 293 return false; 294 retval = -retval; 295 } 296 else 297 if (sign && (retval & ((T)1 << ((sizeof(T) * 8) - 1)))) 298 return false; 299 300 return true; 301 302 default: 303 return false; 304 } 305 306 if (sign && negative) 307 return false; 308 309 if (mult > (unsigned long long)signmax) 310 return false; 311 312 if (retval > val) 313 return false; 314 315 retval *= mult; 316 317 return true; 318} 319 320#define STN(type) \ 321template<> \ 322bool to_number<type>(const string &value, type &retval) \ 323{ return __to_number(value, retval); } 324 325STN(unsigned long long); 326STN(signed long long); 327STN(unsigned long); 328STN(signed long); 329STN(unsigned int); 330STN(signed int); 331STN(unsigned short); 332STN(signed short); 333STN(unsigned char); 334STN(signed char); 335 336template<> 337bool to_number<bool>(const string &value, bool &retval) 338{ 339 string lowered = to_lower(value); 340 341 if (value == "0") { 342 retval = false; 343 return true; 344 } 345 346 if (value == "1"){ 347 retval = true; 348 return true; 349 } 350 351 if (lowered == "false") { 352 retval = false; 353 return true; 354 } 355 356 if (lowered == "true"){ 357 retval = true; 358 return true; 359 } 360 361 if (lowered == "no") { 362 retval = false; 363 return true; 364 } 365 366 if (lowered == "yes"){ 367 retval = true; 368 return true; 369 } 370 371 return false; 372} 373