diff options
author | Devtools Arcadia <arcadia-devtools@yandex-team.ru> | 2022-02-07 18:08:42 +0300 |
---|---|---|
committer | Devtools Arcadia <arcadia-devtools@mous.vla.yp-c.yandex.net> | 2022-02-07 18:08:42 +0300 |
commit | 1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch) | |
tree | e26c9fed0de5d9873cce7e00bc214573dc2195b7 /library/cpp/string_utils/parse_size | |
download | ydb-1110808a9d39d4b808aef724c861a2e1a38d2a69.tar.gz |
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'library/cpp/string_utils/parse_size')
-rw-r--r-- | library/cpp/string_utils/parse_size/parse_size.cpp | 95 | ||||
-rw-r--r-- | library/cpp/string_utils/parse_size/parse_size.h | 33 | ||||
-rw-r--r-- | library/cpp/string_utils/parse_size/parse_size_ut.cpp | 63 | ||||
-rw-r--r-- | library/cpp/string_utils/parse_size/ut/ya.make | 9 | ||||
-rw-r--r-- | library/cpp/string_utils/parse_size/ya.make | 10 |
5 files changed, 210 insertions, 0 deletions
diff --git a/library/cpp/string_utils/parse_size/parse_size.cpp b/library/cpp/string_utils/parse_size/parse_size.cpp new file mode 100644 index 0000000000..39188d560b --- /dev/null +++ b/library/cpp/string_utils/parse_size/parse_size.cpp @@ -0,0 +1,95 @@ +#include "parse_size.h" + +#include <util/generic/yexception.h> +#include <util/generic/ylimits.h> +#include <util/string/cast.h> +#include <util/stream/output.h> + +namespace { + enum ESuffixShifts { + ESS_KILO_BYTES = 10, + ESS_MEGA_BYTES = 20, + ESS_GIGA_BYTES = 30, + ESS_TERA_BYTES = 40, + }; + + bool TryShiftValue(ui64& value, ui64 shift) { + if (value > (Max<ui64>() >> shift)) { + return false; + } + + value <<= shift; + return true; + } + + ui64 ShiftValue(ui64 value, ui64 shift) { + if (!TryShiftValue(value, shift)) { + ythrow yexception() << "value overflow '" << value << " << " << shift << "'"; + } else { + return value; + } + } + +} + +namespace NSize { + ui64 ParseSize(TStringBuf str) { + if (! str.size()) + ythrow yexception() << "Wrong size " << str; + char suff = tolower(str[str.size() - 1]); + if (isdigit(suff)) + return FromString<ui64>(str); + ui64 shift = 1; + switch (suff) { + case 'k': + shift = ESS_KILO_BYTES; + break; + case 'm': + shift = ESS_MEGA_BYTES; + break; + case 'g': + shift = ESS_GIGA_BYTES; + break; + case 't': + shift = ESS_TERA_BYTES; + break; + default: + ythrow yexception() << "Unknown suffix " << str; + } + + ui64 value = FromString<ui64>(str.substr(0, str.size() - 1)); + + if (!TryShiftValue(value, shift)) { + ythrow yexception() << "Value overflow " << str; + } else { + return value; + } + } + + TSize FromKiloBytes(ui64 value) { + return TSize(ShiftValue(value, ESS_KILO_BYTES)); + } + + TSize FromMegaBytes(ui64 value) { + return TSize(ShiftValue(value, ESS_MEGA_BYTES)); + } + + TSize FromGigaBytes(ui64 value) { + return TSize(ShiftValue(value, ESS_GIGA_BYTES)); + } + + TSize FromTeraBytes(ui64 value) { + return TSize(ShiftValue(value, ESS_TERA_BYTES)); + } + +} + +template <> +NSize::TSize FromStringImpl<NSize::TSize>(const char* data, size_t len) { + return NSize::TSize(NSize::ParseSize(TStringBuf(data, len))); +} + +template <> +void Out<NSize::TSize>(IOutputStream& os, const NSize::TSize& size) { + os << size.GetValue(); +} diff --git a/library/cpp/string_utils/parse_size/parse_size.h b/library/cpp/string_utils/parse_size/parse_size.h new file mode 100644 index 0000000000..ad235ef02f --- /dev/null +++ b/library/cpp/string_utils/parse_size/parse_size.h @@ -0,0 +1,33 @@ +#pragma once + +#include <util/generic/strbuf.h> + +namespace NSize { + ui64 ParseSize(TStringBuf size); + + // Convenient disk size representation with string parsing and integer comparison + class TSize { + public: + TSize(ui64 value = 0) + : Value(value) + { + } + + ui64 GetValue() const { + return Value; + } + + operator ui64() const { + return Value; + } + + private: + ui64 Value; + }; + + TSize FromKiloBytes(ui64 value); + TSize FromMegaBytes(ui64 value); + TSize FromGigaBytes(ui64 value); + TSize FromTeraBytes(ui64 value); + +} diff --git a/library/cpp/string_utils/parse_size/parse_size_ut.cpp b/library/cpp/string_utils/parse_size/parse_size_ut.cpp new file mode 100644 index 0000000000..8fff4f56b2 --- /dev/null +++ b/library/cpp/string_utils/parse_size/parse_size_ut.cpp @@ -0,0 +1,63 @@ +#include "parse_size.h" + +#include <library/cpp/testing/unittest/registar.h> + +using namespace NSize; + +class TParseSizeTest: public TTestBase { + UNIT_TEST_SUITE(TParseSizeTest); + + UNIT_TEST(TestPlain); + UNIT_TEST(TestKiloBytes); + UNIT_TEST(TestMegaBytes); + UNIT_TEST(TestGigaBytes); + UNIT_TEST(TestTeraBytes); + UNIT_TEST(TestOverflow); + UNIT_TEST(TestStaticCreators); + UNIT_TEST(TestToString); + + UNIT_TEST_SUITE_END(); + +private: + void TestPlain() { + UNIT_ASSERT(ParseSize("1024") == 1024); + } + + void TestKiloBytes() { + UNIT_ASSERT(ParseSize("10K") == 1024 * 10); + UNIT_ASSERT(ParseSize("10k") == 1024 * 10); + } + + void TestMegaBytes() { + UNIT_ASSERT(ParseSize("10M") == 1024 * 1024 * 10); + UNIT_ASSERT(ParseSize("10m") == 1024 * 1024 * 10); + } + + void TestGigaBytes() { + UNIT_ASSERT(ParseSize("10G") == 1024ul * 1024ul * 1024ul * 10ul); + UNIT_ASSERT(ParseSize("10g") == 1024ul * 1024ul * 1024ul * 10ul); + } + + void TestTeraBytes() { + UNIT_ASSERT(ParseSize("10T") == 1024ul * 1024ul * 1024ul * 1024ul * 10ul); + UNIT_ASSERT(ParseSize("10t") == 1024ul * 1024ul * 1024ul * 1024ul * 10ul); + } + + void TestStaticCreators() { + UNIT_ASSERT_EQUAL(FromKiloBytes(10), 1024ul * 10ul); + UNIT_ASSERT_EQUAL(FromMegaBytes(10), 1024ul * 1024ul * 10ul); + UNIT_ASSERT_EQUAL(FromGigaBytes(10), 1024ul * 1024ul * 1024ul * 10ul); + UNIT_ASSERT_EQUAL(FromTeraBytes(10), 1024ul * 1024ul * 1024ul * 1024ul * 10ul); + } + + void TestOverflow() { + UNIT_ASSERT_EXCEPTION(ParseSize("20000000000G"), yexception); + UNIT_ASSERT_EXCEPTION(FromGigaBytes(20000000000ull), yexception); + } + + void TestToString() { + UNIT_ASSERT_VALUES_EQUAL(ToString(FromKiloBytes(1)), TString("1024")); + } +}; + +UNIT_TEST_SUITE_REGISTRATION(TParseSizeTest); diff --git a/library/cpp/string_utils/parse_size/ut/ya.make b/library/cpp/string_utils/parse_size/ut/ya.make new file mode 100644 index 0000000000..da19cf025b --- /dev/null +++ b/library/cpp/string_utils/parse_size/ut/ya.make @@ -0,0 +1,9 @@ +UNITTEST_FOR(library/cpp/string_utils/parse_size) + +OWNER(g:images-robot) + +SRCS( + parse_size_ut.cpp +) + +END() diff --git a/library/cpp/string_utils/parse_size/ya.make b/library/cpp/string_utils/parse_size/ya.make new file mode 100644 index 0000000000..4a62abcac2 --- /dev/null +++ b/library/cpp/string_utils/parse_size/ya.make @@ -0,0 +1,10 @@ +LIBRARY() + +OWNER(g:images-robot) + +SRCS( + parse_size.cpp + parse_size.h +) + +END() |