str.cc revision 239
19243SN/A/*
210889Sandreas.hansson@arm.com * Copyright (c) 2003 The Regents of The University of Michigan
39243SN/A * All rights reserved.
49243SN/A *
59243SN/A * Redistribution and use in source and binary forms, with or without
69243SN/A * modification, are permitted provided that the following conditions are
79243SN/A * met: redistributions of source code must retain the above copyright
89243SN/A * notice, this list of conditions and the following disclaimer;
99243SN/A * redistributions in binary form must reproduce the above copyright
109243SN/A * notice, this list of conditions and the following disclaimer in the
119243SN/A * documentation and/or other materials provided with the distribution;
129243SN/A * neither the name of the copyright holders nor the names of its
139243SN/A * contributors may be used to endorse or promote products derived from
149831SN/A * this software without specific prior written permission.
159831SN/A *
169831SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
179243SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
189243SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
199243SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
209243SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
219243SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
229243SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
239243SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
249243SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
259243SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
269243SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
279243SN/A */
289243SN/A
299243SN/A#include <iostream>
309243SN/A
319243SN/A#include <string.h>
329243SN/A#include <ctype.h>
339243SN/A
349243SN/A#include <string>
359243SN/A#include <vector>
369243SN/A
379243SN/A#include "base/intmath.hh"
389243SN/A#include "base/str.hh"
399243SN/A
409243SN/Ausing namespace std;
419243SN/A
429967SN/Avoid
4310618SOmar.Naji@arm.comtokenize(vector<string>& v, const string &s, char token, bool ignore)
449243SN/A{
459243SN/A    string::size_type first = 0;
4610146Sandreas.hansson@arm.com    string::size_type last = s.find_first_of(token);
479356SN/A
4810146Sandreas.hansson@arm.com    if (ignore) {
4910247Sandreas.hansson@arm.com        if (last == first) {
5010208Sandreas.hansson@arm.com            while (last == first)
519352SN/A                last = s.find_first_of(token, ++first);
5210146Sandreas.hansson@arm.com
539814SN/A            if (last == string::npos) {
549243SN/A                v.push_back(s);
559243SN/A                return;
5610432SOmar.Naji@arm.com            }
579243SN/A        }
5810146Sandreas.hansson@arm.com    }
599243SN/A
6010619Sandreas.hansson@arm.com    while (last != string::npos) {
619243SN/A        v.push_back(s.substr(first, last - first));
6210211Sandreas.hansson@arm.com
6310618SOmar.Naji@arm.com        if (ignore) {
6410208Sandreas.hansson@arm.com            first = s.find_first_not_of(token, last + 1);
6510489SOmar.Naji@arm.com
669831SN/A            if (first == string::npos)
679831SN/A                return;
689831SN/A        } else
699831SN/A            first = last + 1;
709831SN/A
7110140SN/A        last = s.find_first_of(token, first);
7210646Sandreas.hansson@arm.com    }
739243SN/A
7410394Swendy.elsasser@arm.com    v.push_back(s.substr(first));
7510394Swendy.elsasser@arm.com}
769566SN/A
779243SN/A/**
789243SN/A * @todo This function will not handle the smallest negative decimal
7910140SN/A * value for a signed type
8010140SN/A */
8110147Sandreas.hansson@arm.com
8210147Sandreas.hansson@arm.comtemplate <class T>
8310393Swendy.elsasser@arm.cominline bool
8410394Swendy.elsasser@arm.com__to_number(string value, T &retval)
8510394Swendy.elsasser@arm.com{
8610394Swendy.elsasser@arm.com    static const T maxnum = ((T)-1);
879243SN/A    static const bool sign = maxnum < 0;
889243SN/A    static const int bits = sizeof(T) * 8;
8910141SN/A    static const T hexmax = maxnum & (((T)1 << (bits - 4 - sign)) - 1);
909726SN/A    static const T octmax = maxnum & (((T)1 << (bits - 3 - sign)) - 1);
919726SN/A    static const T signmax =
9210618SOmar.Naji@arm.com        (sign) ? maxnum & (((T)1 << (bits - 1)) - 1) : maxnum;
9310618SOmar.Naji@arm.com    static const T decmax = signmax / 10;
949243SN/A
9510620Sandreas.hansson@arm.com#if 0
9610620Sandreas.hansson@arm.com    cout << "maxnum =  0x" << hex << (unsigned long long)maxnum << "\n"
9710620Sandreas.hansson@arm.com         << "sign =    0x" << hex << (unsigned long long)sign << "\n"
9810620Sandreas.hansson@arm.com         << "hexmax =  0x" << hex << (unsigned long long)hexmax << "\n"
9910620Sandreas.hansson@arm.com         << "octmax =  0x" << hex << (unsigned long long)octmax << "\n"
10010889Sandreas.hansson@arm.com         << "signmax = 0x" << hex << (unsigned long long)signmax << "\n"
10110889Sandreas.hansson@arm.com         << "decmax =  0x" << hex << (unsigned long long)decmax << "\n";
10210889Sandreas.hansson@arm.com#endif
10310618SOmar.Naji@arm.com
10410618SOmar.Naji@arm.com    eat_white(value);
10510618SOmar.Naji@arm.com
10610432SOmar.Naji@arm.com    bool negative = false;
10710618SOmar.Naji@arm.com    bool hex = false;
10810618SOmar.Naji@arm.com    bool oct = false;
10910618SOmar.Naji@arm.com    int last = value.size() - 1;
11010432SOmar.Naji@arm.com    retval = 0;
11110246Sandreas.hansson@arm.com    int i = 0;
11210618SOmar.Naji@arm.com
11310561SOmar.Naji@arm.com    char c = value[i];
11410561SOmar.Naji@arm.com    if (!IsDec(c)) {
11510561SOmar.Naji@arm.com        if (c == '-' && sign)
11610394Swendy.elsasser@arm.com            negative = true;
11710394Swendy.elsasser@arm.com        else
11810394Swendy.elsasser@arm.com            return false;
11910394Swendy.elsasser@arm.com    }
12010394Swendy.elsasser@arm.com    else {
12110394Swendy.elsasser@arm.com        retval += c - '0';
12210394Swendy.elsasser@arm.com        if (last == 0) return true;
12310394Swendy.elsasser@arm.com    }
12410618SOmar.Naji@arm.com
12510394Swendy.elsasser@arm.com    if (c == '0')
12610394Swendy.elsasser@arm.com        oct = true;
12710618SOmar.Naji@arm.com
12810394Swendy.elsasser@arm.com    c = value[++i];
12910246Sandreas.hansson@arm.com    if (oct) {
13010246Sandreas.hansson@arm.com        if (sign && negative)
13110246Sandreas.hansson@arm.com            return false;
13210140SN/A
13310140SN/A        if (!IsOct(c)) {
13410140SN/A            if (c == 'X' || c == 'x') {
13510140SN/A                hex = true;
13610140SN/A                oct = false;
1379243SN/A            } else
1389243SN/A                return false;
1399567SN/A        }
1409243SN/A        else
14110489SOmar.Naji@arm.com            retval += c - '0';
14210489SOmar.Naji@arm.com    } else if (!IsDec(c))
14310489SOmar.Naji@arm.com        goto multiply;
14410489SOmar.Naji@arm.com    else {
14510489SOmar.Naji@arm.com        if (sign && negative && c == '0')
14610489SOmar.Naji@arm.com            return false;
14710489SOmar.Naji@arm.com
14810489SOmar.Naji@arm.com        retval *= 10;
14910489SOmar.Naji@arm.com        retval += c - '0';
15010489SOmar.Naji@arm.com        if (last == 1) {
1519243SN/A            if (sign && negative) retval = -retval;
1529243SN/A            return true;
1539831SN/A        }
1549831SN/A    }
1559831SN/A
1569831SN/A    if (hex) {
1579831SN/A        if (last == 1)
1589243SN/A            return false;
15910207Sandreas.hansson@arm.com
16010207Sandreas.hansson@arm.com        for (i = 2; i <= last ; i++) {
16110207Sandreas.hansson@arm.com            c = value[i];
16210207Sandreas.hansson@arm.com            if (!IsHex(c))
16310207Sandreas.hansson@arm.com                return false;
16410394Swendy.elsasser@arm.com
16510394Swendy.elsasser@arm.com            if (retval > hexmax) return false;
16610394Swendy.elsasser@arm.com            retval *= 16;
16710394Swendy.elsasser@arm.com            retval += Hex2Int(c);
16810394Swendy.elsasser@arm.com        }
16910394Swendy.elsasser@arm.com        return true;
17010394Swendy.elsasser@arm.com    } else if (oct) {
17110394Swendy.elsasser@arm.com        for (i = 2; i <= last ; i++) {
17210394Swendy.elsasser@arm.com            c = value[i];
17310394Swendy.elsasser@arm.com            if (!IsOct(c))
17410394Swendy.elsasser@arm.com                return false;
17510394Swendy.elsasser@arm.com
17610394Swendy.elsasser@arm.com            if (retval > octmax) return false;
17710394Swendy.elsasser@arm.com            retval *= 8;
17810394Swendy.elsasser@arm.com            retval += (c - '0');
17910394Swendy.elsasser@arm.com        }
18010394Swendy.elsasser@arm.com        return true;
18110394Swendy.elsasser@arm.com    }
18210394Swendy.elsasser@arm.com
18310394Swendy.elsasser@arm.com    for (i = 2; i < last ; i++) {
18410394Swendy.elsasser@arm.com        c = value[i];
18510394Swendy.elsasser@arm.com        if (!IsDec(c))
18610561SOmar.Naji@arm.com            goto multiply;
18710561SOmar.Naji@arm.com
18810394Swendy.elsasser@arm.com        if (retval > decmax) return false;
18910394Swendy.elsasser@arm.com        bool atmax = retval == decmax;
19010394Swendy.elsasser@arm.com        retval *= 10;
19110394Swendy.elsasser@arm.com        retval += c - '0';
19210394Swendy.elsasser@arm.com        if (atmax && retval < decmax) return false;
19310394Swendy.elsasser@arm.com        if (sign && (retval & ((T)1 << (sizeof(T) * 8 - 1))))
1949243SN/A            return false;
1959243SN/A    }
1969243SN/A
19710146Sandreas.hansson@arm.com    c = value[last];
19810140SN/A    if (IsDec(c)) {
19910466Sandreas.hansson@arm.com
20010466Sandreas.hansson@arm.com        if (retval > decmax) return false;
20110466Sandreas.hansson@arm.com        bool atmax = retval == decmax;
20210146Sandreas.hansson@arm.com        retval *= 10;
20310140SN/A        retval += c - '0';
20410140SN/A        if (atmax && retval < decmax) return false;
20510140SN/A        if (sign && negative) {
20610646Sandreas.hansson@arm.com            if ((retval & ((T)1 << (sizeof(T) * 8 - 1))) &&
20710646Sandreas.hansson@arm.com                retval >= (T)-signmax)
20810646Sandreas.hansson@arm.com                return false;
20910646Sandreas.hansson@arm.com            retval = -retval;
21010646Sandreas.hansson@arm.com        }
21110646Sandreas.hansson@arm.com        else
21210646Sandreas.hansson@arm.com            if (sign && (retval & ((T)1 << ((sizeof(T) * 8) - 1))))
21310646Sandreas.hansson@arm.com                return false;
21410646Sandreas.hansson@arm.com        return true;
21510646Sandreas.hansson@arm.com    }
21610646Sandreas.hansson@arm.com
21710646Sandreas.hansson@arm.com  multiply:
21810646Sandreas.hansson@arm.com    signed long long mult = 1;
21910646Sandreas.hansson@arm.com    T val;
22010646Sandreas.hansson@arm.com    switch (c) {
22110646Sandreas.hansson@arm.com      case 'k':
22210646Sandreas.hansson@arm.com      case 'K':
22310646Sandreas.hansson@arm.com        if (i != last) return false;
22410646Sandreas.hansson@arm.com        mult = 1024;
22510646Sandreas.hansson@arm.com        val = signmax / mult;
22610646Sandreas.hansson@arm.com        break;
22710646Sandreas.hansson@arm.com      case 'm':
22810646Sandreas.hansson@arm.com      case 'M':
22910646Sandreas.hansson@arm.com        if (i != last) return false;
23010646Sandreas.hansson@arm.com        mult = 1024 * 1024;
23110646Sandreas.hansson@arm.com        val = signmax / mult;
23210646Sandreas.hansson@arm.com        break;
23310646Sandreas.hansson@arm.com      case 'g':
23410646Sandreas.hansson@arm.com      case 'G':
23510646Sandreas.hansson@arm.com        if (i != last) return false;
23610646Sandreas.hansson@arm.com        mult = 1024 * 1024 * 1024;
23710646Sandreas.hansson@arm.com        val = signmax / mult;
23810646Sandreas.hansson@arm.com        break;
23910646Sandreas.hansson@arm.com      case 'e':
24010646Sandreas.hansson@arm.com      case 'E':
24110646Sandreas.hansson@arm.com        if (i >= last) return false;
24210646Sandreas.hansson@arm.com
24310646Sandreas.hansson@arm.com        mult = 0;
24410646Sandreas.hansson@arm.com        for (i++; i <= last; i++) {
24510646Sandreas.hansson@arm.com            c = value[i];
24610140SN/A            if (!IsDec(c))
24710140SN/A                return false;
24810140SN/A
24910146Sandreas.hansson@arm.com            mult *= 10;
2509243SN/A            mult += c - '0';
25110619Sandreas.hansson@arm.com        }
25210619Sandreas.hansson@arm.com
25310618SOmar.Naji@arm.com        for (i = 0; i < mult; i++) {
25410619Sandreas.hansson@arm.com            if (retval > signmax / 10)
25510619Sandreas.hansson@arm.com                return false;
25610619Sandreas.hansson@arm.com            retval *= 10;
25710619Sandreas.hansson@arm.com            if (sign && (retval & ((T)1 << (sizeof(T) * 8 - 1))))
25810619Sandreas.hansson@arm.com                return false;
25910619Sandreas.hansson@arm.com        }
26010619Sandreas.hansson@arm.com        if (sign && negative) {
26110619Sandreas.hansson@arm.com            if ((retval & ((T)1 << (sizeof(T) * 8 - 1))) &&
26210619Sandreas.hansson@arm.com                retval >= (T)-signmax)
26310619Sandreas.hansson@arm.com                return false;
26410619Sandreas.hansson@arm.com            retval = -retval;
26510619Sandreas.hansson@arm.com        }
26610619Sandreas.hansson@arm.com        else
26710619Sandreas.hansson@arm.com            if (sign && (retval & ((T)1 << ((sizeof(T) * 8) - 1))))
26810619Sandreas.hansson@arm.com                return false;
26910618SOmar.Naji@arm.com
2709243SN/A        return true;
2719243SN/A
2729243SN/A      default:
27310146Sandreas.hansson@arm.com        return false;
2749243SN/A    }
2759243SN/A
2769243SN/A    if (sign && negative)
2779243SN/A        return false;
2789243SN/A
2799243SN/A    if (mult > (unsigned long long)signmax)
2809243SN/A        return false;
2819243SN/A
2829243SN/A    if (retval > val)
2839243SN/A        return false;
2849243SN/A
2859243SN/A    retval *= mult;
2869243SN/A
2879243SN/A    return true;
2889243SN/A}
2899243SN/A
29010146Sandreas.hansson@arm.com#define STN(type) \
2919243SN/Atemplate<> \
2929831SN/Abool to_number<type>(const string &value, type &retval) \
2939831SN/A{ return __to_number(value, retval); }
2949831SN/A
2959243SN/ASTN(unsigned long long);
2969831SN/ASTN(signed long long);
2979831SN/ASTN(unsigned long);
2989243SN/ASTN(signed long);
2999243SN/ASTN(unsigned int);
3009243SN/ASTN(signed int);
30110146Sandreas.hansson@arm.comSTN(unsigned short);
3029243SN/ASTN(signed short);
3039831SN/ASTN(unsigned char);
3049831SN/ASTN(signed char);
3059831SN/A
3069243SN/Atemplate<>
3079243SN/Abool to_number<bool>(const string &value, bool &retval)
30810146Sandreas.hansson@arm.com{
30910146Sandreas.hansson@arm.com    string lowered = to_lower(value);
31010143SN/A
3119243SN/A    if (value == "0") {
3129669SN/A        retval = false;
31310136SN/A        return true;
31410136SN/A    }
3159243SN/A
3169967SN/A    if (value == "1"){
31710245Sandreas.hansson@arm.com        retval = true;
31810245Sandreas.hansson@arm.com        return true;
31910245Sandreas.hansson@arm.com    }
3209243SN/A
32110286Sandreas.hansson@arm.com    if (lowered == "false") {
32210286Sandreas.hansson@arm.com        retval = false;
3239831SN/A        return true;
3249243SN/A    }
3259491SN/A
3269831SN/A    if (lowered == "true"){
32710136SN/A        retval = true;
3289491SN/A        return true;
3299491SN/A    }
3309831SN/A
3319243SN/A    if (lowered == "no") {
3329669SN/A        retval = false;
3339566SN/A        return true;
3349566SN/A    }
3359669SN/A
3369669SN/A    if (lowered == "yes"){
3379669SN/A        retval = true;
3389669SN/A        return true;
3399669SN/A    }
3409669SN/A
3419669SN/A    return false;
3429669SN/A}
3439669SN/A