str.cc revision 1793
18706Sandreas.hansson@arm.com/*
28706Sandreas.hansson@arm.com * Copyright (c) 2001-2005 The Regents of The University of Michigan
38706Sandreas.hansson@arm.com * All rights reserved.
48706Sandreas.hansson@arm.com *
58706Sandreas.hansson@arm.com * Redistribution and use in source and binary forms, with or without
68706Sandreas.hansson@arm.com * modification, are permitted provided that the following conditions are
78706Sandreas.hansson@arm.com * met: redistributions of source code must retain the above copyright
88706Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer;
98706Sandreas.hansson@arm.com * redistributions in binary form must reproduce the above copyright
108706Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer in the
118706Sandreas.hansson@arm.com * documentation and/or other materials provided with the distribution;
128706Sandreas.hansson@arm.com * neither the name of the copyright holders nor the names of its
136892SBrad.Beckmann@amd.com * contributors may be used to endorse or promote products derived from
146892SBrad.Beckmann@amd.com * this software without specific prior written permission.
156892SBrad.Beckmann@amd.com *
166892SBrad.Beckmann@amd.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
176892SBrad.Beckmann@amd.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
186892SBrad.Beckmann@amd.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
196892SBrad.Beckmann@amd.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
206892SBrad.Beckmann@amd.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
216892SBrad.Beckmann@amd.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
226892SBrad.Beckmann@amd.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
236892SBrad.Beckmann@amd.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
246892SBrad.Beckmann@amd.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
256892SBrad.Beckmann@amd.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
266892SBrad.Beckmann@amd.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
276892SBrad.Beckmann@amd.com */
286892SBrad.Beckmann@amd.com
296892SBrad.Beckmann@amd.com#include <ctype.h>
306892SBrad.Beckmann@amd.com
316892SBrad.Beckmann@amd.com#include <cstring>
326892SBrad.Beckmann@amd.com#include <iostream>
336892SBrad.Beckmann@amd.com#include <string>
346892SBrad.Beckmann@amd.com#include <vector>
356892SBrad.Beckmann@amd.com
366892SBrad.Beckmann@amd.com#include "base/intmath.hh"
376892SBrad.Beckmann@amd.com#include "base/str.hh"
386892SBrad.Beckmann@amd.com
396892SBrad.Beckmann@amd.comusing namespace std;
406892SBrad.Beckmann@amd.com
416892SBrad.Beckmann@amd.combool
427563SBrad.Beckmann@amd.comsplit_first(const string &s, string &lhs, string &rhs, char c)
436892SBrad.Beckmann@amd.com{
446892SBrad.Beckmann@amd.com    string::size_type offset = s.find(c);
456892SBrad.Beckmann@amd.com    if (offset == string::npos) {
466892SBrad.Beckmann@amd.com        lhs = s;
477538SBrad.Beckmann@amd.com        rhs = "";
488939SBrad.Beckmann@amd.com        return false;
498939SBrad.Beckmann@amd.com    }
508939SBrad.Beckmann@amd.com
519791Sakash.bagdia@arm.com    lhs = s.substr(0, offset);
529791Sakash.bagdia@arm.com    rhs = s.substr(offset + 1);
539791Sakash.bagdia@arm.com    return true;
549791Sakash.bagdia@arm.com}
559841Snilay@cs.wisc.edu
569841Snilay@cs.wisc.edubool
579841Snilay@cs.wisc.edusplit_last(const string &s, string &lhs, string &rhs, char c)
589841Snilay@cs.wisc.edu{
599841Snilay@cs.wisc.edu    string::size_type offset = s.rfind(c);
607538SBrad.Beckmann@amd.com    if (offset == string::npos) {
617538SBrad.Beckmann@amd.com        lhs = s;
627538SBrad.Beckmann@amd.com        rhs = "";
637538SBrad.Beckmann@amd.com        return false;
647538SBrad.Beckmann@amd.com    }
659576Snilay@cs.wisc.edu
669576Snilay@cs.wisc.edu    lhs = s.substr(0, offset);
678612Stushar@csail.mit.edu    rhs = s.substr(offset + 1);
688612Stushar@csail.mit.edu    return true;
697538SBrad.Beckmann@amd.com}
707538SBrad.Beckmann@amd.com
717917SBrad.Beckmann@amd.comvoid
727563SBrad.Beckmann@amd.comtokenize(vector<string>& v, const string &s, char token, bool ignore)
737563SBrad.Beckmann@amd.com{
747538SBrad.Beckmann@amd.com    string::size_type first = 0;
757538SBrad.Beckmann@amd.com    string::size_type last = s.find_first_of(token);
767538SBrad.Beckmann@amd.com
777538SBrad.Beckmann@amd.com    if (s.empty())
787538SBrad.Beckmann@amd.com        return;
797566SBrad.Beckmann@amd.com
807566SBrad.Beckmann@amd.com    if (ignore && last == first) {
817809Snilay@cs.wisc.edu        while (last == first)
827809Snilay@cs.wisc.edu            last = s.find_first_of(token, ++first);
837809Snilay@cs.wisc.edu
847809Snilay@cs.wisc.edu        if (last == string::npos) {
858638Sgloh            if (first != s.size())
868638Sgloh                v.push_back(s.substr(first));
877538SBrad.Beckmann@amd.com            return;
887538SBrad.Beckmann@amd.com        }
897538SBrad.Beckmann@amd.com    }
907538SBrad.Beckmann@amd.com
919100SBrad.Beckmann@amd.com    while (last != string::npos) {
929100SBrad.Beckmann@amd.com        v.push_back(s.substr(first, last - first));
939100SBrad.Beckmann@amd.com
949100SBrad.Beckmann@amd.com        if (ignore) {
959100SBrad.Beckmann@amd.com            first = s.find_first_not_of(token, last + 1);
969100SBrad.Beckmann@amd.com
979100SBrad.Beckmann@amd.com            if (first == string::npos)
989100SBrad.Beckmann@amd.com                return;
999100SBrad.Beckmann@amd.com        } else
1009100SBrad.Beckmann@amd.com            first = last + 1;
1018929Snilay@cs.wisc.edu
1026892SBrad.Beckmann@amd.com        last = s.find_first_of(token, first);
10310012Snilay@cs.wisc.edu    }
1048436SBrad.Beckmann@amd.com
1058436SBrad.Beckmann@amd.com    v.push_back(s.substr(first));
1067032SBrad.Beckmann@amd.com}
1077032SBrad.Beckmann@amd.com
1086923SBrad.Beckmann@amd.com/**
1099100SBrad.Beckmann@amd.com * @todo This function will not handle the smallest negative decimal
11010116Snilay@cs.wisc.edu * value for a signed type
1117557SBrad.Beckmann@amd.com */
1126923SBrad.Beckmann@amd.com
1136923SBrad.Beckmann@amd.comtemplate <class T>
1147557SBrad.Beckmann@amd.cominline bool
1158257SBrad.Beckmann@amd.com__to_number(string value, T &retval)
1168706Sandreas.hansson@arm.com{
1178706Sandreas.hansson@arm.com    static const T maxnum = ((T)-1);
1188706Sandreas.hansson@arm.com    static const bool sign = maxnum < 0;
1198923Sandreas.hansson@arm.com    static const int bits = sizeof(T) * 8;
1208706Sandreas.hansson@arm.com    static const T hexmax = maxnum & (((T)1 << (bits - 4 - sign)) - 1);
1218706Sandreas.hansson@arm.com    static const T octmax = maxnum & (((T)1 << (bits - 3 - sign)) - 1);
1228706Sandreas.hansson@arm.com    static const T signmax =
1238706Sandreas.hansson@arm.com        (sign) ? maxnum & (((T)1 << (bits - 1)) - 1) : maxnum;
1248732Sandreas.hansson@arm.com    static const T decmax = signmax / 10;
1258839Sandreas.hansson@arm.com
1268732Sandreas.hansson@arm.com#if 0
1278732Sandreas.hansson@arm.com    cout << "maxnum =  0x" << hex << (unsigned long long)maxnum << "\n"
1288257SBrad.Beckmann@amd.com         << "sign =    0x" << hex << (unsigned long long)sign << "\n"
1298257SBrad.Beckmann@amd.com         << "hexmax =  0x" << hex << (unsigned long long)hexmax << "\n"
1308257SBrad.Beckmann@amd.com         << "octmax =  0x" << hex << (unsigned long long)octmax << "\n"
1318257SBrad.Beckmann@amd.com         << "signmax = 0x" << hex << (unsigned long long)signmax << "\n"
1328257SBrad.Beckmann@amd.com         << "decmax =  0x" << hex << (unsigned long long)decmax << "\n";
1338257SBrad.Beckmann@amd.com#endif
1348257SBrad.Beckmann@amd.com
1358257SBrad.Beckmann@amd.com    eat_white(value);
1368257SBrad.Beckmann@amd.com
1378257SBrad.Beckmann@amd.com    bool negative = false;
1388257SBrad.Beckmann@amd.com    bool hex = false;
1398257SBrad.Beckmann@amd.com    bool oct = false;
1408257SBrad.Beckmann@amd.com    int last = value.size() - 1;
1418257SBrad.Beckmann@amd.com    retval = 0;
1428257SBrad.Beckmann@amd.com    int i = 0;
1438258SBrad.Beckmann@amd.com
1448258SBrad.Beckmann@amd.com    char c = value[i];
1459274Snilay@cs.wisc.edu    if (!IsDec(c)) {
1469148Spowerjg@cs.wisc.edu        if (c == '-' && sign)
1479148Spowerjg@cs.wisc.edu            negative = true;
1489862Snilay@cs.wisc.edu        else
1499862Snilay@cs.wisc.edu            return false;
1509862Snilay@cs.wisc.edu    }
1519862Snilay@cs.wisc.edu    else {
1529862Snilay@cs.wisc.edu        retval += c - '0';
1538257SBrad.Beckmann@amd.com        if (last == 0) return true;
1548612Stushar@csail.mit.edu    }
1558612Stushar@csail.mit.edu
1569593Snilay@cs.wisc.edu    if (c == '0')
1579593Snilay@cs.wisc.edu        oct = true;
1586892SBrad.Beckmann@amd.com
1596903SBrad.Beckmann@amd.com    c = value[++i];
1607563SBrad.Beckmann@amd.com    if (oct) {
1617025SBrad.Beckmann@amd.com        if (sign && negative)
1629148Spowerjg@cs.wisc.edu            return false;
1637025SBrad.Beckmann@amd.com
1647025SBrad.Beckmann@amd.com        if (!IsOct(c)) {
1657563SBrad.Beckmann@amd.com            if (c == 'X' || c == 'x') {
1666903SBrad.Beckmann@amd.com                hex = true;
1676903SBrad.Beckmann@amd.com                oct = false;
1687563SBrad.Beckmann@amd.com            } else
1699318Spower.jg@gmail.com                return false;
1709318Spower.jg@gmail.com        }
1717563SBrad.Beckmann@amd.com        else
1727563SBrad.Beckmann@amd.com            retval += c - '0';
1737563SBrad.Beckmann@amd.com    } else if (!IsDec(c))
1747563SBrad.Beckmann@amd.com        goto multiply;
1759318Spower.jg@gmail.com    else {
1769318Spower.jg@gmail.com        if (sign && negative && c == '0')
1779318Spower.jg@gmail.com            return false;
17810004Snilay@cs.wisc.edu
1799318Spower.jg@gmail.com        retval *= 10;
1809148Spowerjg@cs.wisc.edu        retval += c - '0';
1816903SBrad.Beckmann@amd.com        if (last == 1) {
1826903SBrad.Beckmann@amd.com            if (sign && negative) retval = -retval;
1837563SBrad.Beckmann@amd.com            return true;
1849148Spowerjg@cs.wisc.edu        }
1859826Sandreas.hansson@arm.com    }
1868931Sandreas.hansson@arm.com
1876892SBrad.Beckmann@amd.com    if (hex) {
1888436SBrad.Beckmann@amd.com        if (last == 1)
1898436SBrad.Beckmann@amd.com            return false;
19010116Snilay@cs.wisc.edu
19110116Snilay@cs.wisc.edu        for (i = 2; i <= last ; i++) {
19210116Snilay@cs.wisc.edu            c = value[i];
19310116Snilay@cs.wisc.edu            if (!IsHex(c))
19410116Snilay@cs.wisc.edu                return false;
19510116Snilay@cs.wisc.edu
19610116Snilay@cs.wisc.edu            if (retval > hexmax) return false;
19710116Snilay@cs.wisc.edu            retval *= 16;
19810116Snilay@cs.wisc.edu            retval += Hex2Int(c);
19910116Snilay@cs.wisc.edu        }
2008322Ssteve.reinhardt@amd.com        return true;
20110012Snilay@cs.wisc.edu    } else if (oct) {
2027809Snilay@cs.wisc.edu        for (i = 2; i <= last ; i++) {
203            c = value[i];
204            if (!IsOct(c))
205                return false;
206
207            if (retval > octmax) return false;
208            retval *= 8;
209            retval += (c - '0');
210        }
211        return true;
212    }
213
214    for (i = 2; i < last ; i++) {
215        c = value[i];
216        if (!IsDec(c))
217            goto multiply;
218
219        if (retval > decmax) return false;
220        bool atmax = retval == decmax;
221        retval *= 10;
222        retval += c - '0';
223        if (atmax && retval < decmax) return false;
224        if (sign && (retval & ((T)1 << (sizeof(T) * 8 - 1))))
225            return false;
226    }
227
228    c = value[last];
229    if (IsDec(c)) {
230
231        if (retval > decmax) return false;
232        bool atmax = retval == decmax;
233        retval *= 10;
234        retval += c - '0';
235        if (atmax && retval < decmax) return false;
236        if (sign && negative) {
237            if ((retval & ((T)1 << (sizeof(T) * 8 - 1))) &&
238                retval >= (T)-signmax)
239                return false;
240            retval = -retval;
241        }
242        else
243            if (sign && (retval & ((T)1 << ((sizeof(T) * 8) - 1))))
244                return false;
245        return true;
246    }
247
248  multiply:
249    signed long long mult = 1;
250    T val;
251    switch (c) {
252      case 'k':
253      case 'K':
254        if (i != last) return false;
255        mult = 1024;
256        val = signmax / mult;
257        break;
258      case 'm':
259      case 'M':
260        if (i != last) return false;
261        mult = 1024 * 1024;
262        val = signmax / mult;
263        break;
264      case 'g':
265      case 'G':
266        if (i != last) return false;
267        mult = 1024 * 1024 * 1024;
268        val = signmax / mult;
269        break;
270      case 'e':
271      case 'E':
272        if (i >= last) return false;
273
274        mult = 0;
275        for (i++; i <= last; i++) {
276            c = value[i];
277            if (!IsDec(c))
278                return false;
279
280            mult *= 10;
281            mult += c - '0';
282        }
283
284        for (i = 0; i < mult; i++) {
285            if (retval > signmax / 10)
286                return false;
287            retval *= 10;
288            if (sign && (retval & ((T)1 << (sizeof(T) * 8 - 1))))
289                return false;
290        }
291        if (sign && negative) {
292            if ((retval & ((T)1 << (sizeof(T) * 8 - 1))) &&
293                retval >= (T)-signmax)
294                return false;
295            retval = -retval;
296        }
297        else
298            if (sign && (retval & ((T)1 << ((sizeof(T) * 8) - 1))))
299                return false;
300
301        return true;
302
303      default:
304        return false;
305    }
306
307    if (sign && negative)
308        return false;
309
310    if (mult > (unsigned long long)signmax)
311        return false;
312
313    if (retval > val)
314        return false;
315
316    retval *= mult;
317
318    return true;
319}
320
321#define STN(type) \
322template<> \
323bool to_number<type>(const string &value, type &retval) \
324{ return __to_number(value, retval); }
325
326STN(unsigned long long);
327STN(signed long long);
328STN(unsigned long);
329STN(signed long);
330STN(unsigned int);
331STN(signed int);
332STN(unsigned short);
333STN(signed short);
334STN(unsigned char);
335STN(signed char);
336
337template<>
338bool to_number<bool>(const string &value, bool &retval)
339{
340    string lowered = to_lower(value);
341
342    if (value == "0") {
343        retval = false;
344        return true;
345    }
346
347    if (value == "1"){
348        retval = true;
349        return true;
350    }
351
352    if (lowered == "false") {
353        retval = false;
354        return true;
355    }
356
357    if (lowered == "true"){
358        retval = true;
359        return true;
360    }
361
362    if (lowered == "no") {
363        retval = false;
364        return true;
365    }
366
367    if (lowered == "yes"){
368        retval = true;
369        return true;
370    }
371
372    return false;
373}
374