str.cc revision 1380
17639Sgblack@eecs.umich.edu/* 27639Sgblack@eecs.umich.edu * Copyright (c) 2001-2003 The Regents of The University of Michigan 37639Sgblack@eecs.umich.edu * All rights reserved. 47639Sgblack@eecs.umich.edu * 57639Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without 67639Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are 77639Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright 87639Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer; 97639Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright 107639Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the 117639Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution; 127639Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its 137639Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from 147639Sgblack@eecs.umich.edu * this software without specific prior written permission. 157639Sgblack@eecs.umich.edu * 167639Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 177639Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 187639Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 197639Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 207639Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 217639Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 227639Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 237639Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 247639Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 257639Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 267639Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 277639Sgblack@eecs.umich.edu */ 287639Sgblack@eecs.umich.edu 297639Sgblack@eecs.umich.edu#include <iostream> 307639Sgblack@eecs.umich.edu 317639Sgblack@eecs.umich.edu#include <string.h> 327639Sgblack@eecs.umich.edu#include <ctype.h> 337639Sgblack@eecs.umich.edu 347639Sgblack@eecs.umich.edu#include <string> 357639Sgblack@eecs.umich.edu#include <vector> 367639Sgblack@eecs.umich.edu 377639Sgblack@eecs.umich.edu#include "base/intmath.hh" 387639Sgblack@eecs.umich.edu#include "base/str.hh" 397639Sgblack@eecs.umich.edu 407639Sgblack@eecs.umich.eduusing namespace std; 417639Sgblack@eecs.umich.edu 427639Sgblack@eecs.umich.edubool 437639Sgblack@eecs.umich.edusplit_first(const string &s, string &lhs, string &rhs, char c) 447639Sgblack@eecs.umich.edu{ 457639Sgblack@eecs.umich.edu string::size_type offset = s.find(c); 467639Sgblack@eecs.umich.edu if (offset == string::npos) { 477639Sgblack@eecs.umich.edu lhs = s; 487639Sgblack@eecs.umich.edu rhs = ""; 497639Sgblack@eecs.umich.edu return false; 507639Sgblack@eecs.umich.edu } 517639Sgblack@eecs.umich.edu 527639Sgblack@eecs.umich.edu lhs = s.substr(0, offset); 537639Sgblack@eecs.umich.edu rhs = s.substr(offset + 1); 547639Sgblack@eecs.umich.edu return true; 557639Sgblack@eecs.umich.edu} 567639Sgblack@eecs.umich.edu 577639Sgblack@eecs.umich.edubool 587639Sgblack@eecs.umich.edusplit_last(const string &s, string &lhs, string &rhs, char c) 597639Sgblack@eecs.umich.edu{ 607639Sgblack@eecs.umich.edu string::size_type offset = s.rfind(c); 617639Sgblack@eecs.umich.edu if (offset == string::npos) { 627639Sgblack@eecs.umich.edu lhs = s; 637639Sgblack@eecs.umich.edu rhs = ""; 647639Sgblack@eecs.umich.edu return false; 657639Sgblack@eecs.umich.edu } 667639Sgblack@eecs.umich.edu 677639Sgblack@eecs.umich.edu lhs = s.substr(0, offset); 687639Sgblack@eecs.umich.edu rhs = s.substr(offset + 1); 697639Sgblack@eecs.umich.edu return true; 707639Sgblack@eecs.umich.edu} 717639Sgblack@eecs.umich.edu 727639Sgblack@eecs.umich.eduvoid 737639Sgblack@eecs.umich.edutokenize(vector<string>& v, const string &s, char token, bool ignore) 747639Sgblack@eecs.umich.edu{ 757639Sgblack@eecs.umich.edu string::size_type first = 0; 767639Sgblack@eecs.umich.edu string::size_type last = s.find_first_of(token); 777639Sgblack@eecs.umich.edu 787639Sgblack@eecs.umich.edu if (ignore) { 797639Sgblack@eecs.umich.edu if (last == first) { 807639Sgblack@eecs.umich.edu while (last == first) 817639Sgblack@eecs.umich.edu last = s.find_first_of(token, ++first); 827639Sgblack@eecs.umich.edu 837639Sgblack@eecs.umich.edu if (last == string::npos) { 847639Sgblack@eecs.umich.edu v.push_back(s); 857639Sgblack@eecs.umich.edu return; 867639Sgblack@eecs.umich.edu } 877639Sgblack@eecs.umich.edu } 887639Sgblack@eecs.umich.edu } 897639Sgblack@eecs.umich.edu 907639Sgblack@eecs.umich.edu while (last != string::npos) { 917639Sgblack@eecs.umich.edu v.push_back(s.substr(first, last - first)); 927639Sgblack@eecs.umich.edu 937639Sgblack@eecs.umich.edu if (ignore) { 947639Sgblack@eecs.umich.edu first = s.find_first_not_of(token, last + 1); 957639Sgblack@eecs.umich.edu 967639Sgblack@eecs.umich.edu if (first == string::npos) 977639Sgblack@eecs.umich.edu return; 987639Sgblack@eecs.umich.edu } else 997639Sgblack@eecs.umich.edu first = last + 1; 1007639Sgblack@eecs.umich.edu 1017639Sgblack@eecs.umich.edu last = s.find_first_of(token, first); 1027639Sgblack@eecs.umich.edu } 1037639Sgblack@eecs.umich.edu 1047639Sgblack@eecs.umich.edu v.push_back(s.substr(first)); 1057639Sgblack@eecs.umich.edu} 1067639Sgblack@eecs.umich.edu 1077639Sgblack@eecs.umich.edu/** 1087639Sgblack@eecs.umich.edu * @todo This function will not handle the smallest negative decimal 1097639Sgblack@eecs.umich.edu * value for a signed type 1107639Sgblack@eecs.umich.edu */ 1117639Sgblack@eecs.umich.edu 1127639Sgblack@eecs.umich.edutemplate <class T> 1137639Sgblack@eecs.umich.eduinline bool 1147639Sgblack@eecs.umich.edu__to_number(string value, T &retval) 1157639Sgblack@eecs.umich.edu{ 1167639Sgblack@eecs.umich.edu static const T maxnum = ((T)-1); 1177639Sgblack@eecs.umich.edu static const bool sign = maxnum < 0; 1187639Sgblack@eecs.umich.edu static const int bits = sizeof(T) * 8; 1197639Sgblack@eecs.umich.edu static const T hexmax = maxnum & (((T)1 << (bits - 4 - sign)) - 1); 1207639Sgblack@eecs.umich.edu static const T octmax = maxnum & (((T)1 << (bits - 3 - sign)) - 1); 1217639Sgblack@eecs.umich.edu static const T signmax = 1227639Sgblack@eecs.umich.edu (sign) ? maxnum & (((T)1 << (bits - 1)) - 1) : maxnum; 1237639Sgblack@eecs.umich.edu static const T decmax = signmax / 10; 1247639Sgblack@eecs.umich.edu 1257639Sgblack@eecs.umich.edu#if 0 1267639Sgblack@eecs.umich.edu cout << "maxnum = 0x" << hex << (unsigned long long)maxnum << "\n" 1277639Sgblack@eecs.umich.edu << "sign = 0x" << hex << (unsigned long long)sign << "\n" 1287639Sgblack@eecs.umich.edu << "hexmax = 0x" << hex << (unsigned long long)hexmax << "\n" 1297639Sgblack@eecs.umich.edu << "octmax = 0x" << hex << (unsigned long long)octmax << "\n" 1307639Sgblack@eecs.umich.edu << "signmax = 0x" << hex << (unsigned long long)signmax << "\n" 1317639Sgblack@eecs.umich.edu << "decmax = 0x" << hex << (unsigned long long)decmax << "\n"; 1327639Sgblack@eecs.umich.edu#endif 1337639Sgblack@eecs.umich.edu 1347639Sgblack@eecs.umich.edu eat_white(value); 1357639Sgblack@eecs.umich.edu 1367639Sgblack@eecs.umich.edu bool negative = false; 1377639Sgblack@eecs.umich.edu bool hex = false; 1387639Sgblack@eecs.umich.edu bool oct = false; 1397639Sgblack@eecs.umich.edu int last = value.size() - 1; 1407639Sgblack@eecs.umich.edu retval = 0; 1417639Sgblack@eecs.umich.edu int i = 0; 1427639Sgblack@eecs.umich.edu 1437639Sgblack@eecs.umich.edu char c = value[i]; 1447639Sgblack@eecs.umich.edu if (!IsDec(c)) { 1457639Sgblack@eecs.umich.edu if (c == '-' && sign) 1467639Sgblack@eecs.umich.edu negative = true; 1477639Sgblack@eecs.umich.edu else 1487639Sgblack@eecs.umich.edu return false; 1497639Sgblack@eecs.umich.edu } 1507639Sgblack@eecs.umich.edu else { 1517639Sgblack@eecs.umich.edu retval += c - '0'; 1527639Sgblack@eecs.umich.edu if (last == 0) return true; 1537639Sgblack@eecs.umich.edu } 1547639Sgblack@eecs.umich.edu 1557639Sgblack@eecs.umich.edu if (c == '0') 1567639Sgblack@eecs.umich.edu oct = true; 1577639Sgblack@eecs.umich.edu 1587639Sgblack@eecs.umich.edu c = value[++i]; 1597639Sgblack@eecs.umich.edu if (oct) { 1607639Sgblack@eecs.umich.edu if (sign && negative) 1617639Sgblack@eecs.umich.edu return false; 1627639Sgblack@eecs.umich.edu 1637639Sgblack@eecs.umich.edu if (!IsOct(c)) { 1647639Sgblack@eecs.umich.edu if (c == 'X' || c == 'x') { 1657639Sgblack@eecs.umich.edu hex = true; 1667639Sgblack@eecs.umich.edu oct = false; 1677639Sgblack@eecs.umich.edu } else 1687639Sgblack@eecs.umich.edu return false; 1697639Sgblack@eecs.umich.edu } 1707639Sgblack@eecs.umich.edu else 1717639Sgblack@eecs.umich.edu retval += c - '0'; 1727639Sgblack@eecs.umich.edu } else if (!IsDec(c)) 1737639Sgblack@eecs.umich.edu goto multiply; 1747639Sgblack@eecs.umich.edu else { 1757639Sgblack@eecs.umich.edu if (sign && negative && c == '0') 1767639Sgblack@eecs.umich.edu return false; 1777639Sgblack@eecs.umich.edu 1787639Sgblack@eecs.umich.edu retval *= 10; 1797639Sgblack@eecs.umich.edu retval += c - '0'; 1807639Sgblack@eecs.umich.edu if (last == 1) { 1817639Sgblack@eecs.umich.edu if (sign && negative) retval = -retval; 1827639Sgblack@eecs.umich.edu return true; 1837639Sgblack@eecs.umich.edu } 1847639Sgblack@eecs.umich.edu } 1857639Sgblack@eecs.umich.edu 1867639Sgblack@eecs.umich.edu if (hex) { 1877639Sgblack@eecs.umich.edu if (last == 1) 1887639Sgblack@eecs.umich.edu return false; 1897639Sgblack@eecs.umich.edu 1907639Sgblack@eecs.umich.edu for (i = 2; i <= last ; i++) { 1917639Sgblack@eecs.umich.edu c = value[i]; 1927639Sgblack@eecs.umich.edu if (!IsHex(c)) 1937639Sgblack@eecs.umich.edu return false; 1947639Sgblack@eecs.umich.edu 1957639Sgblack@eecs.umich.edu if (retval > hexmax) return false; 1967639Sgblack@eecs.umich.edu retval *= 16; 1977639Sgblack@eecs.umich.edu retval += Hex2Int(c); 1987639Sgblack@eecs.umich.edu } 1997639Sgblack@eecs.umich.edu return true; 2007639Sgblack@eecs.umich.edu } else if (oct) { 2017639Sgblack@eecs.umich.edu for (i = 2; i <= last ; i++) { 2027639Sgblack@eecs.umich.edu c = value[i]; 2037639Sgblack@eecs.umich.edu if (!IsOct(c)) 2047639Sgblack@eecs.umich.edu return false; 2057639Sgblack@eecs.umich.edu 2067639Sgblack@eecs.umich.edu if (retval > octmax) return false; 2077639Sgblack@eecs.umich.edu retval *= 8; 2087639Sgblack@eecs.umich.edu retval += (c - '0'); 2097639Sgblack@eecs.umich.edu } 2107639Sgblack@eecs.umich.edu return true; 2117639Sgblack@eecs.umich.edu } 2127639Sgblack@eecs.umich.edu 2137639Sgblack@eecs.umich.edu for (i = 2; i < last ; i++) { 2147639Sgblack@eecs.umich.edu c = value[i]; 2157639Sgblack@eecs.umich.edu if (!IsDec(c)) 2167639Sgblack@eecs.umich.edu goto multiply; 2177639Sgblack@eecs.umich.edu 2187639Sgblack@eecs.umich.edu if (retval > decmax) return false; 2197639Sgblack@eecs.umich.edu bool atmax = retval == decmax; 2207639Sgblack@eecs.umich.edu retval *= 10; 2217639Sgblack@eecs.umich.edu retval += c - '0'; 2227639Sgblack@eecs.umich.edu if (atmax && retval < decmax) return false; 2237639Sgblack@eecs.umich.edu if (sign && (retval & ((T)1 << (sizeof(T) * 8 - 1)))) 2247639Sgblack@eecs.umich.edu return false; 2257639Sgblack@eecs.umich.edu } 2267639Sgblack@eecs.umich.edu 2277639Sgblack@eecs.umich.edu c = value[last]; 2287639Sgblack@eecs.umich.edu if (IsDec(c)) { 2297639Sgblack@eecs.umich.edu 2307639Sgblack@eecs.umich.edu if (retval > decmax) return false; 2317639Sgblack@eecs.umich.edu bool atmax = retval == decmax; 2327639Sgblack@eecs.umich.edu retval *= 10; 2337639Sgblack@eecs.umich.edu retval += c - '0'; 2347639Sgblack@eecs.umich.edu if (atmax && retval < decmax) return false; 2357639Sgblack@eecs.umich.edu if (sign && negative) { 2367639Sgblack@eecs.umich.edu if ((retval & ((T)1 << (sizeof(T) * 8 - 1))) && 2377639Sgblack@eecs.umich.edu retval >= (T)-signmax) 2387639Sgblack@eecs.umich.edu return false; 2397639Sgblack@eecs.umich.edu retval = -retval; 2407639Sgblack@eecs.umich.edu } 2417639Sgblack@eecs.umich.edu else 2427639Sgblack@eecs.umich.edu if (sign && (retval & ((T)1 << ((sizeof(T) * 8) - 1)))) 2437639Sgblack@eecs.umich.edu return false; 2447639Sgblack@eecs.umich.edu return true; 2457639Sgblack@eecs.umich.edu } 2467639Sgblack@eecs.umich.edu 2477639Sgblack@eecs.umich.edu multiply: 2487639Sgblack@eecs.umich.edu signed long long mult = 1; 2497639Sgblack@eecs.umich.edu T val; 2507639Sgblack@eecs.umich.edu switch (c) { 2517639Sgblack@eecs.umich.edu case 'k': 2527639Sgblack@eecs.umich.edu case 'K': 2537639Sgblack@eecs.umich.edu if (i != last) return false; 2547639Sgblack@eecs.umich.edu mult = 1024; 2557639Sgblack@eecs.umich.edu val = signmax / mult; 2567639Sgblack@eecs.umich.edu break; 2577639Sgblack@eecs.umich.edu case 'm': 2587639Sgblack@eecs.umich.edu case 'M': 2597639Sgblack@eecs.umich.edu if (i != last) return false; 2607639Sgblack@eecs.umich.edu mult = 1024 * 1024; 2617639Sgblack@eecs.umich.edu val = signmax / mult; 2627639Sgblack@eecs.umich.edu break; 2637639Sgblack@eecs.umich.edu case 'g': 2647639Sgblack@eecs.umich.edu case 'G': 2657639Sgblack@eecs.umich.edu if (i != last) return false; 2667639Sgblack@eecs.umich.edu mult = 1024 * 1024 * 1024; 2677639Sgblack@eecs.umich.edu val = signmax / mult; 2687639Sgblack@eecs.umich.edu break; 2697639Sgblack@eecs.umich.edu case 'e': 2707639Sgblack@eecs.umich.edu case 'E': 2717639Sgblack@eecs.umich.edu if (i >= last) return false; 2727639Sgblack@eecs.umich.edu 2737639Sgblack@eecs.umich.edu mult = 0; 2747639Sgblack@eecs.umich.edu for (i++; i <= last; i++) { 2757639Sgblack@eecs.umich.edu c = value[i]; 2767639Sgblack@eecs.umich.edu if (!IsDec(c)) 2777639Sgblack@eecs.umich.edu return false; 2787639Sgblack@eecs.umich.edu 2797639Sgblack@eecs.umich.edu mult *= 10; 2807639Sgblack@eecs.umich.edu mult += c - '0'; 2817639Sgblack@eecs.umich.edu } 2827639Sgblack@eecs.umich.edu 2837639Sgblack@eecs.umich.edu for (i = 0; i < mult; i++) { 2847639Sgblack@eecs.umich.edu if (retval > signmax / 10) 2857639Sgblack@eecs.umich.edu return false; 2867639Sgblack@eecs.umich.edu retval *= 10; 2877639Sgblack@eecs.umich.edu if (sign && (retval & ((T)1 << (sizeof(T) * 8 - 1)))) 2887639Sgblack@eecs.umich.edu return false; 2897639Sgblack@eecs.umich.edu } 2907639Sgblack@eecs.umich.edu if (sign && negative) { 2917639Sgblack@eecs.umich.edu if ((retval & ((T)1 << (sizeof(T) * 8 - 1))) && 2927639Sgblack@eecs.umich.edu retval >= (T)-signmax) 2937639Sgblack@eecs.umich.edu return false; 2947639Sgblack@eecs.umich.edu retval = -retval; 2957639Sgblack@eecs.umich.edu } 2967639Sgblack@eecs.umich.edu else 2977639Sgblack@eecs.umich.edu if (sign && (retval & ((T)1 << ((sizeof(T) * 8) - 1)))) 2987639Sgblack@eecs.umich.edu return false; 2997639Sgblack@eecs.umich.edu 3007639Sgblack@eecs.umich.edu return true; 3017639Sgblack@eecs.umich.edu 3027639Sgblack@eecs.umich.edu default: 3037639Sgblack@eecs.umich.edu return false; 3047639Sgblack@eecs.umich.edu } 3057639Sgblack@eecs.umich.edu 3067639Sgblack@eecs.umich.edu if (sign && negative) 3077639Sgblack@eecs.umich.edu return false; 3087639Sgblack@eecs.umich.edu 3097639Sgblack@eecs.umich.edu if (mult > (unsigned long long)signmax) 3107639Sgblack@eecs.umich.edu return false; 3117639Sgblack@eecs.umich.edu 3127639Sgblack@eecs.umich.edu if (retval > val) 3137639Sgblack@eecs.umich.edu return false; 3147639Sgblack@eecs.umich.edu 3157639Sgblack@eecs.umich.edu retval *= mult; 3167639Sgblack@eecs.umich.edu 3177639Sgblack@eecs.umich.edu return true; 3187639Sgblack@eecs.umich.edu} 3197639Sgblack@eecs.umich.edu 3207639Sgblack@eecs.umich.edu#define STN(type) \ 3217639Sgblack@eecs.umich.edutemplate<> \ 3227639Sgblack@eecs.umich.edubool to_number<type>(const string &value, type &retval) \ 3237639Sgblack@eecs.umich.edu{ return __to_number(value, retval); } 3247639Sgblack@eecs.umich.edu 3257639Sgblack@eecs.umich.eduSTN(unsigned long long); 3267639Sgblack@eecs.umich.eduSTN(signed long long); 3277639Sgblack@eecs.umich.eduSTN(unsigned long); 3287639Sgblack@eecs.umich.eduSTN(signed long); 3297639Sgblack@eecs.umich.eduSTN(unsigned int); 3307639Sgblack@eecs.umich.eduSTN(signed int); 3317639Sgblack@eecs.umich.eduSTN(unsigned short); 3327639Sgblack@eecs.umich.eduSTN(signed short); 3337639Sgblack@eecs.umich.eduSTN(unsigned char); 3347639Sgblack@eecs.umich.eduSTN(signed char); 3357639Sgblack@eecs.umich.edu 3367639Sgblack@eecs.umich.edutemplate<> 3377639Sgblack@eecs.umich.edubool to_number<bool>(const string &value, bool &retval) 3387639Sgblack@eecs.umich.edu{ 3397639Sgblack@eecs.umich.edu string lowered = to_lower(value); 3407639Sgblack@eecs.umich.edu 3417639Sgblack@eecs.umich.edu if (value == "0") { 3427639Sgblack@eecs.umich.edu retval = false; 3437639Sgblack@eecs.umich.edu return true; 3447639Sgblack@eecs.umich.edu } 3457639Sgblack@eecs.umich.edu 3467639Sgblack@eecs.umich.edu if (value == "1"){ 3477639Sgblack@eecs.umich.edu retval = true; 3487639Sgblack@eecs.umich.edu return true; 3497639Sgblack@eecs.umich.edu } 3507639Sgblack@eecs.umich.edu 3517639Sgblack@eecs.umich.edu if (lowered == "false") { 3527639Sgblack@eecs.umich.edu retval = false; 3537639Sgblack@eecs.umich.edu return true; 3547639Sgblack@eecs.umich.edu } 3557639Sgblack@eecs.umich.edu 3567639Sgblack@eecs.umich.edu if (lowered == "true"){ 3577639Sgblack@eecs.umich.edu retval = true; 3587639Sgblack@eecs.umich.edu return true; 3597639Sgblack@eecs.umich.edu } 3607639Sgblack@eecs.umich.edu 3617639Sgblack@eecs.umich.edu if (lowered == "no") { 3627639Sgblack@eecs.umich.edu retval = false; 3637639Sgblack@eecs.umich.edu return true; 3647639Sgblack@eecs.umich.edu } 3657639Sgblack@eecs.umich.edu 3667639Sgblack@eecs.umich.edu if (lowered == "yes"){ 3677639Sgblack@eecs.umich.edu retval = true; 3687639Sgblack@eecs.umich.edu return true; 3697639Sgblack@eecs.umich.edu } 3707639Sgblack@eecs.umich.edu 3717639Sgblack@eecs.umich.edu return false; 3727639Sgblack@eecs.umich.edu} 3737639Sgblack@eecs.umich.edu