From: Joao Eduardo Luis Date: Fri, 29 Mar 2013 15:27:35 +0000 (+0000) Subject: common: util: add 'unit_to_bytesize()' function X-Git-Tag: v0.62~126^2~3 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=e2a936d2ae16db2cf081fc17f32f7f4fe62659d7;p=ceph.git common: util: add 'unit_to_bytesize()' function 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 --- diff --git a/src/Makefile.am b/src/Makefile.am index 272e97367c1..ac91b5d757a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -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) diff --git a/src/common/util.cc b/src/common/util.cc index 73b0c365bad..6da37e88833 100644 --- a/src/common/util.cc +++ b/src/common/util.cc @@ -12,7 +12,11 @@ * */ +#include + #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)); +} diff --git a/src/include/util.h b/src/include/util.h index d215678cfe9..b30132e4c53 100644 --- a/src/include/util.h +++ b/src/include/util.h @@ -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 index 00000000000..16713077cfc --- /dev/null +++ b/src/test/common/test_util.cc @@ -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 + +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)); +}