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