]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
common: util: add 'unit_to_bytesize()' function
authorJoao Eduardo Luis <joao.luis@inktank.com>
Fri, 29 Mar 2013 15:27:35 +0000 (15:27 +0000)
committerSage Weil <sage@inktank.com>
Fri, 29 Mar 2013 23:47:28 +0000 (16:47 -0700)
Converts from a numerical value that may or may not contain an unit
modifier ('1024', '1K', '2M', ..., '1E') and returns the parsed size
in bytes.

Signed-off-by: Joao Eduardo Luis <joao.luis@inktank.com>
src/Makefile.am
src/common/util.cc
src/include/util.h
src/test/common/test_util.cc [new file with mode: 0644]

index 272e97367c18323492a9498954eaa3767fcc6fc9..ac91b5d757a150a1f2aeda876363136568e9aa9f 100644 (file)
@@ -656,6 +656,11 @@ unittest_addrs_CXXFLAGS = ${AM_CXXFLAGS} ${UNITTEST_CXXFLAGS}
 unittest_addrs_LDADD = libglobal.la $(PTHREAD_LIBS) -lm ${UNITTEST_LDADD} $(CRYPTO_LIBS) $(EXTRALIBS)
 check_PROGRAMS += unittest_addrs
 
+unittest_util_SOURCES = test/common/test_util.cc common/util.cc
+unittest_util_CXXFLAGS = ${AM_CXXFLAGS} ${UNITTEST_CXXFLAGS}
+unittest_util_LDADD = libcommon.la $(PTHREAD_LIBS) -lm ${UNITTEST_LDADD} $(CRYPTO_LIBS) $(EXTRALIBS)
+check_PROGRAMS += unittest_util
+
 unittest_workqueue_SOURCES = test/test_workqueue.cc
 unittest_workqueue_CXXFLAGS = ${AM_CXXFLAGS} ${UNITTEST_CXXFLAGS}
 unittest_workqueue_LDADD = libglobal.la $(PTHREAD_LIBS) -lm ${UNITTEST_LDADD} $(CRYPTO_LIBS) $(EXTRALIBS)
index 73b0c365badc8bb4d80ba0ed5339f4abf0e31003..6da37e8883330a45c6227eee5df64e19a71edc16 100644 (file)
  * 
  */
 
+#include <errno.h>
+
 #include "include/util.h"
+#include "common/errno.h"
+#include "common/strtol.h"
 
 // test if an entire buf is zero in 8-byte chunks
 bool buf_is_zero(const char *buf, size_t len)
@@ -34,3 +38,68 @@ bool buf_is_zero(const char *buf, size_t len)
 }
 
 
+int64_t unit_to_bytesize(string val, ostream *pss)
+{
+  if (val.empty()) {
+    if (pss)
+      *pss << "value is empty!";
+    return -EINVAL;
+  }
+
+  char c = val[val.length()-1];
+  int modifier = 0;
+  if (!::isdigit(c)) {
+    if (val.length() < 2) {
+      if (pss)
+        *pss << "invalid value: " << val;
+      return -EINVAL;
+    }
+    val = val.substr(0,val.length()-1);
+    switch (c) {
+    case 'B':
+      break;
+    case 'K':
+      modifier = 10;
+      break;
+    case 'M':
+      modifier = 20;
+      break;
+    case 'G':
+      modifier = 30;
+      break;
+    case 'T':
+      modifier = 40;
+      break;
+    case 'P':
+      modifier = 50;
+      break;
+    case 'E':
+      modifier = 60;
+      break;
+    default:
+      if (pss)
+        *pss << "unrecognized modifier '" << c << "'" << std::endl;
+      return -EINVAL;
+    }
+  }
+
+  if (val[0] == '+' || val[0] == '-') {
+    if (pss)
+      *pss << "expected numerical value, got: " << val;
+    return -EINVAL;
+  }
+
+  string err;
+  int64_t r = strict_strtoll(val.c_str(), 10, &err);
+  if ((r == 0) && !err.empty()) {
+    if (pss)
+      *pss << err;
+    return -1;
+  }
+  if (r < 0) {
+    if (pss)
+      *pss << "unable to parse positive integer '" << val << "'";
+    return -1;
+  }
+  return (r * (1LL << modifier));
+}
index d215678cfe92556cf78b53b44462c90fc3e60f3e..b30132e4c5356cc239fe9082ae813c084b1af978 100644 (file)
@@ -17,3 +17,4 @@
 
 bool buf_is_zero(const char *buf, size_t len);
 
+int64_t unit_to_bytesize(string val, ostream *pss);
diff --git a/src/test/common/test_util.cc b/src/test/common/test_util.cc
new file mode 100644 (file)
index 0000000..1671307
--- /dev/null
@@ -0,0 +1,31 @@
+// -*- mode:C; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- 
+// vim: ts=8 sw=2 smarttab
+/*
+ * Ceph - scalable distributed file system
+ *
+ * Copyright (C) 2011 New Dream Network
+ *
+ * This is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License version 2, as published by the Free Software
+ * Foundation.  See file COPYING.
+ *
+ */
+
+#include "include/util.h"
+#include "gtest/gtest.h"
+
+#include <sstream>
+
+TEST(util, unit_to_bytesize)
+{
+  ASSERT_EQ(1234ll, unit_to_bytesize("1234", &cerr));
+  ASSERT_EQ(1024ll, unit_to_bytesize("1K", &cerr));
+  ASSERT_EQ(1048576ll, unit_to_bytesize("1M", &cerr));
+  ASSERT_EQ(1073741824ll, unit_to_bytesize("1G", &cerr));
+  ASSERT_EQ(1099511627776ll, unit_to_bytesize("1T", &cerr));
+  ASSERT_EQ(1125899906842624ll, unit_to_bytesize("1P", &cerr));
+  ASSERT_EQ(1152921504606846976ll, unit_to_bytesize("1E", &cerr));
+
+  ASSERT_EQ(65536ll, unit_to_bytesize(" 64K", &cerr));
+}