base: Clean up redundant string functions and use C++11
authorAndreas Hansson <andreas.hansson@arm.com>
Sat, 20 Sep 2014 21:17:49 +0000 (17:17 -0400)
committerAndreas Hansson <andreas.hansson@arm.com>
Sat, 20 Sep 2014 21:17:49 +0000 (17:17 -0400)
This patch does a bit of housekeeping on the string helper functions
and relies on the C++11 standard library where possible. It also does
away with our custom string hash as an implementation is already part
of the standard library.

src/base/statistics.hh
src/base/stats/text.cc
src/base/str.cc
src/base/str.hh
src/cpu/o3/lsq_unit_impl.hh
src/dev/uart8250.cc
src/sim/serialize.cc

index 7e5f1f5b9acffd9e2625be3296d14a98737f4b84..1b3d0fc54198ae085396d5555116d45ae35644b7 100644 (file)
@@ -741,7 +741,7 @@ class ScalarBase : public DataWrap<Derived, ScalarInfoProxy>
 class ProxyInfo : public ScalarInfo
 {
   public:
-    std::string str() const { return to_string(value()); }
+    std::string str() const { return std::to_string(value()); }
     size_type size() const { return 1; }
     bool check() const { return true; }
     void prepare() { }
@@ -2170,7 +2170,7 @@ class ConstNode : public Node
     const VResult &result() const { return vresult; }
     Result total() const { return vresult[0]; };
     size_type size() const { return 1; }
-    std::string str() const { return to_string(vresult[0]); }
+    std::string str() const { return std::to_string(vresult[0]); }
 };
 
 template <class T>
@@ -2200,7 +2200,7 @@ class ConstVectorNode : public Node
         size_type size = this->size();
         std::string tmp = "(";
         for (off_type i = 0; i < size; i++)
-            tmp += csprintf("%s ",to_string(vresult[i]));
+            tmp += csprintf("%s ", std::to_string(vresult[i]));
         tmp += ")";
         return tmp;
     }
index 2c5b004be188857659f2e0fd0a298e6e23f8307b..efe43c602b148562bf279dcfa620552e393a9463 100644 (file)
@@ -284,7 +284,7 @@ VectorPrint::operator()(std::ostream &stream) const
         // the case where there are no subnames) and append it to the
         // base name.
         if (forceSubnames)
-            print.name = base + (havesub ? subnames[0] : to_string(0));
+            print.name = base + (havesub ? subnames[0] : std::to_string(0));
         print.value = vec[0];
         print(stream);
         return;
@@ -300,7 +300,7 @@ VectorPrint::operator()(std::ostream &stream) const
             if (havesub && (i >= subnames.size() || subnames[i].empty()))
                 continue;
 
-            print.name = base + (havesub ? subnames[i] : to_string(i));
+            print.name = base + (havesub ? subnames[i] : std::to_string(i));
             print.desc = subdescs.empty() ? desc : subdescs[i];
 
             print.update(vec[i], _total);
@@ -355,7 +355,7 @@ DistPrint::DistPrint(const Text *text, const VectorDistInfo &info, int i)
     init(text, info);
 
     name = info.name + "_" +
-        (info.subnames[i].empty() ? (to_string(i)) : info.subnames[i]);
+        (info.subnames[i].empty() ? (std::to_string(i)) : info.subnames[i]);
 
     if (!info.subdescs[i].empty())
         desc = info.subdescs[i];
@@ -605,7 +605,7 @@ Text::visit(const Vector2dInfo &info)
         }
 
         print.name = info.name + "_" +
-            (havesub ? info.subnames[i] : to_string(i));
+            (havesub ? info.subnames[i] : std::to_string(i));
         print.desc = info.desc;
         print.vec = yvec;
         print.total = total;
index 45d3107b087964c4eba73c203dbdeb3a524b245d..849bc8afa260084605f39c95cf438335994cc261 100644 (file)
  * Authors: Nathan Binkert
  */
 
-#include <cctype>
-#include <cstring>
-#include <iostream>
-#include <limits>
 #include <string>
 #include <vector>
 
-#include "base/intmath.hh"
 #include "base/str.hh"
 
 using namespace std;
@@ -106,270 +101,3 @@ tokenize(vector<string>& v, const string &s, char token, bool ignore)
 
     v.push_back(s.substr(first));
 }
-
-/**
- * @todo This function will not handle the smallest negative decimal
- * value for a signed type
- */
-
-template <class T>
-inline bool
-__to_number(string value, T &retval)
-{
-    static const T maxnum = ((T)-1);
-    static const bool sign = numeric_limits<T>::is_signed;
-    static const int bits = numeric_limits<T>::digits;
-    static const T hexmax = maxnum & (((T)1 << (bits - 4)) - 1);
-    static const T octmax = maxnum & (((T)1 << (bits - 3)) - 1);
-    static const T signmax = numeric_limits<T>::max();
-    static const T decmax = signmax / 10;
-
-#if 0
-    cout << "maxnum =  0x" << hex << (unsigned long long)maxnum << "\n"
-         << "sign =    0x" << hex << (unsigned long long)sign << "\n"
-         << "hexmax =  0x" << hex << (unsigned long long)hexmax << "\n"
-         << "octmax =  0x" << hex << (unsigned long long)octmax << "\n"
-         << "signmax = 0x" << hex << (unsigned long long)signmax << "\n"
-         << "decmax =  0x" << hex << (unsigned long long)decmax << "\n";
-#endif
-
-    eat_white(value);
-
-    bool negative = false;
-    bool hex = false;
-    bool oct = false;
-    int last = value.size() - 1;
-    retval = 0;
-    int i = 0;
-
-    char c = value[i];
-    if (!isDec(c)) {
-        if (c == '-' && sign)
-            negative = true;
-        else
-            return false;
-    }
-    else {
-        retval += c - '0';
-        if (last == 0) return true;
-    }
-
-    if (c == '0')
-        oct = true;
-
-    c = value[++i];
-    if (oct) {
-        if (sign && negative)
-            return false;
-
-        if (!isOct(c)) {
-            if (c == 'X' || c == 'x') {
-                hex = true;
-                oct = false;
-            } else
-                return false;
-        }
-        else
-            retval += c - '0';
-    } else if (!isDec(c))
-        goto multiply;
-    else {
-        if (sign && negative && c == '0')
-            return false;
-
-        retval *= 10;
-        retval += c - '0';
-        if (last == 1) {
-            if (sign && negative) retval = -retval;
-            return true;
-        }
-    }
-
-    if (hex) {
-        if (last == 1)
-            return false;
-
-        for (i = 2; i <= last ; i++) {
-            c = value[i];
-            if (!isHex(c))
-                return false;
-
-            if (retval > hexmax) return false;
-            retval *= 16;
-            retval += hex2Int(c);
-        }
-        return true;
-    } else if (oct) {
-        for (i = 2; i <= last ; i++) {
-            c = value[i];
-            if (!isOct(c))
-                return false;
-
-            if (retval > octmax) return false;
-            retval *= 8;
-            retval += (c - '0');
-        }
-        return true;
-    }
-
-    for (i = 2; i < last ; i++) {
-        c = value[i];
-        if (!isDec(c))
-            goto multiply;
-
-        if (retval > decmax) return false;
-        bool atmax = retval == decmax;
-        retval *= 10;
-        retval += c - '0';
-        if (atmax && retval < decmax) return false;
-        if (sign && (retval & ((T)1 << (sizeof(T) * 8 - 1))))
-            return false;
-    }
-
-    c = value[last];
-    if (isDec(c)) {
-
-        if (retval > decmax) return false;
-        bool atmax = retval == decmax;
-        retval *= 10;
-        retval += c - '0';
-        if (atmax && retval < decmax) return false;
-        if (sign && negative) {
-            if ((retval & ((T)1 << (sizeof(T) * 8 - 1))) &&
-                retval >= (T)-signmax)
-                return false;
-            retval = -retval;
-        }
-        else
-            if (sign && (retval & ((T)1 << ((sizeof(T) * 8) - 1))))
-                return false;
-        return true;
-    }
-
-  multiply:
-    signed long long mult = 1;
-    T val;
-    switch (c) {
-      case 'k':
-      case 'K':
-        if (i != last) return false;
-        mult = 1024;
-        val = signmax / mult;
-        break;
-      case 'm':
-      case 'M':
-        if (i != last) return false;
-        mult = 1024 * 1024;
-        val = signmax / mult;
-        break;
-      case 'g':
-      case 'G':
-        if (i != last) return false;
-        mult = 1024 * 1024 * 1024;
-        val = signmax / mult;
-        break;
-      case 'e':
-      case 'E':
-        if (i >= last) return false;
-
-        mult = 0;
-        for (i++; i <= last; i++) {
-            c = value[i];
-            if (!isDec(c))
-                return false;
-
-            mult *= 10;
-            mult += c - '0';
-        }
-
-        for (i = 0; i < mult; i++) {
-            if (retval > signmax / 10)
-                return false;
-            retval *= 10;
-            if (sign && (retval & ((T)1 << (sizeof(T) * 8 - 1))))
-                return false;
-        }
-        if (sign && negative) {
-            if ((retval & ((T)1 << (sizeof(T) * 8 - 1))) &&
-                retval >= (T)-signmax)
-                return false;
-            retval = -retval;
-        }
-        else
-            if (sign && (retval & ((T)1 << ((sizeof(T) * 8) - 1))))
-                return false;
-
-        return true;
-
-      default:
-        return false;
-    }
-
-    if (sign && negative)
-        return false;
-
-    if (mult > (unsigned long long)signmax)
-        return false;
-
-    if (retval > val)
-        return false;
-
-    retval *= mult;
-
-    return true;
-}
-
-#define STN(type) \
-template<> \
-bool to_number<type>(const string &value, type &retval) \
-{ return __to_number(value, retval); }
-
-STN(unsigned long long)
-STN(signed long long)
-STN(unsigned long)
-STN(signed long)
-STN(unsigned int)
-STN(signed int)
-STN(unsigned short)
-STN(signed short)
-STN(unsigned char)
-STN(signed char)
-STN(char)
-
-template<>
-bool to_number<bool>(const string &value, bool &retval)
-{
-    string lowered = to_lower(value);
-
-    if (value == "0") {
-        retval = false;
-        return true;
-    }
-
-    if (value == "1"){
-        retval = true;
-        return true;
-    }
-
-    if (lowered == "false") {
-        retval = false;
-        return true;
-    }
-
-    if (lowered == "true"){
-        retval = true;
-        return true;
-    }
-
-    if (lowered == "no") {
-        retval = false;
-        return true;
-    }
-
-    if (lowered == "yes"){
-        retval = true;
-        return true;
-    }
-
-    return false;
-}
index b3f3153ec1713f8b55f919cabd5fcdb68c117ab4..d73058bc0b58a48e213df1615dee775e606de484 100644 (file)
  *          Steve Reinhardt
  */
 
-#ifndef __STR_HH__
-#define __STR_HH__
+#ifndef __BASE_STR_HH__
+#define __BASE_STR_HH__
 
-#include <cctype>
 #include <cstring>
-#include <sstream>
+#include <limits>
+#include <locale>
+#include <stdexcept>
 #include <string>
 #include <vector>
 
-template<class> class Hash;
-template<>
-class Hash<std::string> {
-public:
-  unsigned operator()(const std::string &s) {
-      std::string::const_iterator i = s.begin();
-      std::string::const_iterator end = s.end();
-      unsigned hash = 5381;
-
-      while (i < end)
-          hash = ((hash << 5) + hash) + *i++;
-
-      return hash;
-  }
-};
-
 inline void
 eat_lead_white(std::string &s)
 {
@@ -87,8 +72,8 @@ to_lower(const std::string &s)
 
     lower.reserve(len);
 
-    for (int i = 0; i < len; ++i)
-        lower.push_back(tolower(s[i]));
+    for (const auto &c : s)
+        lower.push_back(std::tolower(c));
 
     return lower;
 }
@@ -111,16 +96,87 @@ void
 tokenize(std::vector<std::string> &vector, const std::string &s,
          char token, bool ign = true);
 
-template <class T> bool
-to_number(const std::string &value, T &retval);
+/**
+ * @{
+ *
+ * @name String to number helper functions for signed and unsigned
+ *       integeral type, as well as floating-point types.
+ */
+template <class T>
+typename std::enable_if<std::is_integral<T>::value &&
+                        std::is_signed<T>::value, T>::type
+__to_number(const std::string &value)
+{
+    // start big and narrow it down if needed, determine the base dynamically
+    long long r = std::stoll(value, nullptr, 0);
+    if (r < std::numeric_limits<T>::min() || r > std::numeric_limits<T>::max())
+        throw std::out_of_range("Out of range");
+    return static_cast<T>(r);
+}
+
+template <class T>
+typename std::enable_if<std::is_integral<T>::value &&
+                        !std::is_signed<T>::value, T>::type
+__to_number(const std::string &value)
+{
+    // start big and narrow it down if needed, determine the base dynamically
+    unsigned long long r = std::stoull(value, nullptr, 0);
+    if (r > std::numeric_limits<T>::max())
+        throw std::out_of_range("Out of range");
+    return static_cast<T>(r);
+}
 
 template <class T>
-inline std::string
-to_string(const T &value)
+typename std::enable_if<std::is_floating_point<T>::value, T>::type
+__to_number(const std::string &value)
 {
-    std::stringstream str;
-    str << value;
-    return str.str();
+    // start big and narrow it down if needed
+    long double r = std::stold(value);
+    if (r < std::numeric_limits<T>::min() || r > std::numeric_limits<T>::max())
+        throw std::out_of_range("Out of range");
+    return static_cast<T>(r);
+}
+/** @} */
+
+/**
+ * Turn a string representation of a number, either integral or
+ * floating point, into an actual number.
+ *
+ * @param value The string representing the number
+ * @param retval The resulting value
+ * @return True if the parsing was successful
+ */
+template <class T>
+inline bool
+to_number(const std::string &value, T &retval)
+{
+    try {
+        retval = __to_number<T>(value);
+        return true;
+    } catch (const std::out_of_range&) {
+        return false;
+    } catch (const std::invalid_argument&) {
+        return false;
+    }
+}
+
+/**
+ * Turn a string representation of a boolean into a boolean value.
+ */
+inline bool
+to_bool(const std::string &value, bool &retval)
+{
+    std::string s = to_lower(value);
+
+    if (s == "true") {
+        retval = true;
+        return true;
+    } else if (s == "false") {
+        retval = false;
+        return true;
+    }
+
+    return false;
 }
 
 // Put quotes around string arg if it contains spaces.
@@ -172,4 +228,4 @@ startswith(const std::string &s, const std::string &prefix)
 }
 
 
-#endif //__STR_HH__
+#endif //__BASE_STR_HH__
index b63a590fbfaafa7e93a89ba3d3d423d868fd2279..0be4f57c4032f3955c36371d8687ae2001a2114b 100644 (file)
@@ -215,7 +215,7 @@ LSQUnit<Impl>::name() const
     if (Impl::MaxThreads == 1) {
         return iewStage->name() + ".lsq";
     } else {
-        return iewStage->name() + ".lsq.thread" + to_string(lsqID);
+        return iewStage->name() + ".lsq.thread" + std::to_string(lsqID);
     }
 }
 
index dfaf9088d4fc90c027084604947d2374db99e442..40ee7d38f223cb27d4f4e5055b63aa1638606eb6 100644 (file)
@@ -36,7 +36,6 @@
 #include <vector>
 
 #include "base/inifile.hh"
-#include "base/str.hh"        // for to_number
 #include "base/trace.hh"
 #include "config/the_isa.hh"
 #include "debug/Uart.hh"
index 18af044d0af04d1469e59d04b66d167778a3b235..27bf872541e051a72d407afb9f1a491b09ca193e 100644 (file)
@@ -111,38 +111,25 @@ showParam(ostream &os, const unsigned char &value)
 }
 
 
-// Use sscanf() for FP types as to_number() only handles integers
 template <>
 bool
 parseParam(const string &s, float &value)
 {
-    return (sscanf(s.c_str(), "%f", &value) == 1);
+    return to_number(s, value);
 }
 
 template <>
 bool
 parseParam(const string &s, double &value)
 {
-    return (sscanf(s.c_str(), "%lf", &value) == 1);
+    return to_number(s, value);
 }
 
 template <>
 bool
 parseParam(const string &s, bool &value)
 {
-    const string &ls = to_lower(s);
-
-    if (ls == "true") {
-        value = true;
-        return true;
-    }
-
-    if (ls == "false") {
-        value = false;
-        return true;
-    }
-
-    return false;
+    return to_bool(s, value);
 }
 
 // Display bools as strings