]> git.ipfire.org Git - thirdparty/ccache.git/commitdiff
C++-ify parse_size_with_suffix
authorJoel Rosdahl <joel@rosdahl.net>
Mon, 27 Jul 2020 18:03:06 +0000 (20:03 +0200)
committerJoel Rosdahl <joel@rosdahl.net>
Tue, 28 Jul 2020 12:00:30 +0000 (14:00 +0200)
src/Config.cpp
src/Util.cpp
src/Util.hpp
src/ccache.cpp
src/legacy_util.cpp
src/legacy_util.hpp
unittest/CMakeLists.txt
unittest/test_Util.cpp
unittest/test_legacy_util.cpp [deleted file]

index f58ecc6400a76e1d14ee861c97956371e3690408..9a708e7dce83e0e2c1bdb1ce39aecae0884619af 100644 (file)
@@ -212,16 +212,6 @@ parse_double(const std::string& value)
   return result;
 }
 
-uint64_t
-parse_cache_size(const std::string& value)
-{
-  uint64_t result;
-  if (!parse_size_with_suffix(value.c_str(), &result)) {
-    throw Error(fmt::format("invalid size: \"{}\"", value));
-  }
-  return result;
-}
-
 std::string
 format_cache_size(uint64_t value)
 {
@@ -762,7 +752,7 @@ Config::set_item(const std::string& key,
     break;
 
   case ConfigItem::max_size:
-    m_max_size = parse_cache_size(value);
+    m_max_size = Util::parse_size(value);
     break;
 
   case ConfigItem::path:
index b8b92f89a2050fbeb9a97029b563e382323c880c..61b9506ed8007c446c58456e1ccc5f4b6c24880e 100644 (file)
@@ -737,6 +737,47 @@ parse_int(const std::string& value)
   return result;
 }
 
+uint64_t
+parse_size(const std::string& value)
+{
+  errno = 0;
+
+  char* p;
+  double result = strtod(value.c_str(), &p);
+  if (errno != 0 || result < 0 || p == value.c_str() || value.empty()) {
+    throw Error(fmt::format("invalid size: \"{}\"", value));
+  }
+
+  while (isspace(*p)) {
+    ++p;
+  }
+
+  if (*p != '\0') {
+    unsigned multiplier = *(p + 1) == 'i' ? 1024 : 1000;
+    switch (*p) {
+    case 'T':
+      result *= multiplier;
+    // Fallthrough.
+    case 'G':
+      result *= multiplier;
+    // Fallthrough.
+    case 'M':
+      result *= multiplier;
+    // Fallthrough.
+    case 'K':
+    case 'k':
+      result *= multiplier;
+      break;
+    default:
+      throw Error(fmt::format("invalid size: \"{}\"", value));
+    }
+  } else {
+    // Default suffix: G.
+    result *= 1000 * 1000 * 1000;
+  }
+  return static_cast<uint64_t>(result);
+}
+
 uint32_t
 parse_uint32(const std::string& value)
 {
index b2cd2844d7e5dd299724a8c917b0c882a51c2759..ca10f4bae7a445c88099335219ccc10576021cc7 100644 (file)
@@ -274,6 +274,11 @@ uint32_t parse_duration(const std::string& duration);
 // Throws `Error` on error.
 int parse_int(const std::string& value);
 
+// Parse a "size value", i.e. a string that can end in k, M, G, T (10-based
+// suffixes) or Ki, Mi, Gi, Ti (2-based suffixes). For backward compatibility, K
+// is also recognized as a synonym of k. Throws `Error` on parse error.
+uint64_t parse_size(const std::string& value);
+
 // Parse a string into an unsigned 32-bit integer.
 //
 // Throws `Error` on error.
index dfdc5ecd5042c11033aca0ab93b5642e658170a7..0b727c7acd7ac8d84d678103f57416db6c3eb681 100644 (file)
@@ -2329,10 +2329,7 @@ handle_main_options(int argc, const char* const* argv)
     }
 
     case 'M': { // --max-size
-      uint64_t size;
-      if (!parse_size_with_suffix(optarg, &size)) {
-        fatal("invalid size: %s", optarg);
-      }
+      uint64_t size = Util::parse_size(optarg);
       Config::set_value_in_file(
         ctx.config.primary_config_path(), "max_size", optarg);
       if (size == 0) {
index 00c97e302e59a6d9abcf3b227f357776f5ae447a..e007a704902a5dd4ad85926483f50dfa18a7efba 100644 (file)
@@ -342,51 +342,6 @@ reformat(char** ptr, const char* format, ...)
   }
 }
 
-// Parse a "size value", i.e. a string that can end in k, M, G, T (10-based
-// suffixes) or Ki, Mi, Gi, Ti (2-based suffixes). For backward compatibility,
-// K is also recognized as a synonym of k.
-bool
-parse_size_with_suffix(const char* str, uint64_t* size)
-{
-  errno = 0;
-
-  char* p;
-  double x = strtod(str, &p);
-  if (errno != 0 || x < 0 || p == str || *str == '\0') {
-    return false;
-  }
-
-  while (isspace(*p)) {
-    ++p;
-  }
-
-  if (*p != '\0') {
-    unsigned multiplier = *(p + 1) == 'i' ? 1024 : 1000;
-    switch (*p) {
-    case 'T':
-      x *= multiplier;
-    // Fallthrough.
-    case 'G':
-      x *= multiplier;
-    // Fallthrough.
-    case 'M':
-      x *= multiplier;
-    // Fallthrough.
-    case 'K':
-    case 'k':
-      x *= multiplier;
-      break;
-    default:
-      return false;
-    }
-  } else {
-    // Default suffix: G.
-    x *= 1000 * 1000 * 1000;
-  }
-  *size = (uint64_t)x;
-  return true;
-}
-
 #if !defined(_WIN32) && !defined(HAVE_LOCALTIME_R)
 // localtime_r replacement. (Mingw-w64 has an inline localtime_r which is not
 // detected by AC_CHECK_FUNCS.)
index 16049292df299d4baaa981b5ff040c739b948044..4310c068444291e4c0ef4e3abea5647578cd0ae6 100644 (file)
@@ -36,7 +36,6 @@ char* x_strdup(const char* s);
 char* x_strndup(const char* s, size_t n);
 void x_setenv(const char* name, const char* value);
 void x_unsetenv(const char* name);
-bool parse_size_with_suffix(const char* str, uint64_t* size);
 #ifndef HAVE_LOCALTIME_R
 struct tm* localtime_r(const time_t* timep, struct tm* result);
 #endif
index 5f919d94fbd3962e2c699351744c3fc8ee29b2f6..16aae0edd48c81325bec5c810578f372ccc28ec9 100644 (file)
@@ -17,7 +17,6 @@ set(
   test_argprocessing.cpp
   test_compopt.cpp
   test_hashutil.cpp
-  test_legacy_util.cpp
   test_logging.cpp)
 
 if(INODE_CACHE_SUPPORTED)
index 844cd6253916841526c1a54c8f29ddec0139c05f..eaa6965cdd34f614e78993a8cfe44d72a10c23f1 100644 (file)
@@ -568,6 +568,30 @@ TEST_CASE("Util::parse_int")
   }
 }
 
+TEST_CASE("Util::parse_size")
+{
+  CHECK(Util::parse_size("0") == 0);
+  CHECK(Util::parse_size("42") // Default suffix: G
+        == static_cast<uint64_t>(42) * 1000 * 1000 * 1000);
+  CHECK(Util::parse_size("78k") == 78 * 1000);
+  CHECK(Util::parse_size("78K") == 78 * 1000);
+  CHECK(Util::parse_size("1.1 M") == (int64_t(1.1 * 1000 * 1000)));
+  CHECK(Util::parse_size("438.55M") == (int64_t(438.55 * 1000 * 1000)));
+  CHECK(Util::parse_size("1 G") == 1 * 1000 * 1000 * 1000);
+  CHECK(Util::parse_size("2T")
+        == static_cast<uint64_t>(2) * 1000 * 1000 * 1000 * 1000);
+  CHECK(Util::parse_size("78 Ki") == 78 * 1024);
+  CHECK(Util::parse_size("1.1Mi") == (int64_t(1.1 * 1024 * 1024)));
+  CHECK(Util::parse_size("438.55 Mi") == (int64_t(438.55 * 1024 * 1024)));
+  CHECK(Util::parse_size("1Gi") == 1 * 1024 * 1024 * 1024);
+  CHECK(Util::parse_size("2 Ti")
+        == static_cast<uint64_t>(2) * 1024 * 1024 * 1024 * 1024);
+
+  CHECK_THROWS_WITH(Util::parse_size(""), "invalid size: \"\"");
+  CHECK_THROWS_WITH(Util::parse_size("x"), "invalid size: \"x\"");
+  CHECK_THROWS_WITH(Util::parse_size("10x"), "invalid size: \"10x\"");
+}
+
 TEST_CASE("Util::parse_uint32")
 {
   CHECK(Util::parse_uint32("0") == 0);
diff --git a/unittest/test_legacy_util.cpp b/unittest/test_legacy_util.cpp
deleted file mode 100644 (file)
index 0630cbf..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright (C) 2010-2020 Joel Rosdahl and other contributors
-//
-// See doc/AUTHORS.adoc for a complete list of contributors.
-//
-// This program is free software; you can redistribute it and/or modify it
-// under the terms of the GNU General Public License as published by the Free
-// Software Foundation; either version 3 of the License, or (at your option)
-// any later version.
-//
-// This program is distributed in the hope that it will be useful, but WITHOUT
-// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
-// more details.
-//
-// You should have received a copy of the GNU General Public License along with
-// this program; if not, write to the Free Software Foundation, Inc., 51
-// Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-
-#include "../src/legacy_util.hpp"
-
-#include "third_party/doctest.h"
-
-#define CHECK_STR_EQ_FREE2(a, b)                                               \
-  do {                                                                         \
-    CHECK(strcmp((a), (b)) == 0);                                              \
-    free(b);                                                                   \
-  } while (false)
-
-TEST_SUITE_BEGIN("legacy_util");
-
-TEST_CASE("parse_size_with_suffix")
-{
-  uint64_t size;
-  size_t i;
-  struct
-  {
-    const char* size;
-    int64_t expected;
-  } sizes[] = {
-    {"0", 0},
-    {"42", (int64_t)42 * 1000 * 1000 * 1000}, // Default suffix: G
-
-    {"78k", 78 * 1000},
-    {"78K", 78 * 1000},
-    {"1.1 M", (int64_t)(1.1 * 1000 * 1000)},
-    {"438.55M", (int64_t)(438.55 * 1000 * 1000)},
-    {"1 G", 1 * 1000 * 1000 * 1000},
-    {"2T", (int64_t)2 * 1000 * 1000 * 1000 * 1000},
-
-    {"78 Ki", 78 * 1024},
-    {"1.1Mi", (int64_t)(1.1 * 1024 * 1024)},
-    {"438.55 Mi", (int64_t)(438.55 * 1024 * 1024)},
-    {"1Gi", 1 * 1024 * 1024 * 1024},
-    {"2 Ti", (int64_t)2 * 1024 * 1024 * 1024 * 1024},
-  };
-
-  for (i = 0; i < ARRAY_SIZE(sizes); ++i) {
-    CHECK(parse_size_with_suffix(sizes[i].size, &size));
-    CHECK(size == sizes[i].expected);
-  }
-}
-
-TEST_SUITE_END();