util: add _GiB for Gibibyte conversions

Introduce `operator""_GiB`, sharing the overflow-checked conversion logic with the existing `operator""_MiB`.

Use `1_GiB` in a few existing places where it is a drop-in replacement (e.g. `1024_MiB`, `1<<30`) and extend unit tests to cover boundary behavior.
This commit is contained in:
Lőrinc
2026-01-28 14:44:44 +01:00
parent ad0545ba96
commit b3edd30aa2
6 changed files with 78 additions and 29 deletions

View File

@@ -1636,7 +1636,7 @@ BOOST_AUTO_TEST_CASE(util_ParseByteUnits)
BOOST_CHECK_EQUAL(ParseByteUnits("2M", noop).value(), 2ULL << 20);
BOOST_CHECK_EQUAL(ParseByteUnits("3g", noop).value(), 3'000'000'000ULL);
BOOST_CHECK_EQUAL(ParseByteUnits("3G", noop).value(), 3ULL << 30);
BOOST_CHECK_EQUAL(ParseByteUnits("3G", noop).value(), 3_GiB);
BOOST_CHECK_EQUAL(ParseByteUnits("4t", noop).value(), 4'000'000'000'000ULL);
BOOST_CHECK_EQUAL(ParseByteUnits("4T", noop).value(), 4ULL << 40);
@@ -1829,10 +1829,11 @@ BOOST_AUTO_TEST_CASE(saturating_left_shift_test)
BOOST_AUTO_TEST_CASE(mib_string_literal_test)
{
// Basic equivalences and simple arithmetic operations
BOOST_CHECK_EQUAL(0_MiB, 0);
BOOST_CHECK_EQUAL(1_MiB, 1024 * 1024);
const auto max_mib{std::numeric_limits<size_t>::max() >> 20};
BOOST_CHECK_EXCEPTION(operator""_MiB(static_cast<unsigned long long>(max_mib) + 1), std::overflow_error, HasReason("MiB value too large for size_t byte conversion"));
constexpr auto max_mib{std::numeric_limits<size_t>::max() >> 20};
BOOST_CHECK_EXCEPTION(operator""_MiB(max_mib + 1), std::overflow_error, HasReason("MiB value too large for size_t byte conversion"));
}
BOOST_AUTO_TEST_CASE(ceil_div_test)
@@ -1872,4 +1873,37 @@ BOOST_AUTO_TEST_CASE(ceil_div_test)
BOOST_CHECK_EQUAL(CeilDiv(sizeof(uint64_t) * 8, 7u), (sizeof(uint64_t) * 8 + 6) / 7);
}
BOOST_AUTO_TEST_CASE(gib_string_literal_test)
{
// Basic equivalences and simple arithmetic operations
BOOST_CHECK_EQUAL(0_GiB, 0);
BOOST_CHECK_EQUAL(1_GiB, 1 << 30);
BOOST_CHECK_EQUAL(1_GiB, 1024 * 1024 * 1024);
BOOST_CHECK_EQUAL(1_GiB, 0x40000000U);
BOOST_CHECK_EQUAL(1_GiB, 1073741824U);
BOOST_CHECK_EQUAL(1_GiB, 1_MiB * 1024);
BOOST_CHECK_EQUAL(1_GiB, 1024_MiB);
BOOST_CHECK_EQUAL((1_GiB + 123) / double(1_GiB), (1_GiB + 123) / 1024.0 / 1024.0 / 1024.0);
BOOST_CHECK_EQUAL(2ULL * 1_GiB, 2ULL << 30);
BOOST_CHECK_EQUAL(4 * uint64_t{1_GiB}, uint64_t{4} << 30);
BOOST_CHECK_EQUAL(2_GiB, 2048_MiB);
BOOST_CHECK_EQUAL(3_GiB / 1_GiB, 3U);
BOOST_CHECK_EQUAL(3_GiB, 3U << 30);
// Overflow handling and specific codebase values
constexpr auto max_gib{std::numeric_limits<size_t>::max() >> 30};
if constexpr (SIZE_MAX == UINT32_MAX) {
BOOST_CHECK_EQUAL(max_gib, 3U);
BOOST_CHECK_EXCEPTION(4_GiB, std::overflow_error, HasReason("GiB value too large for size_t byte conversion"));
} else {
BOOST_CHECK_GT(max_gib, 3U);
BOOST_CHECK_EQUAL(4_GiB, size_t{4} << 30);
BOOST_CHECK_EQUAL(4_GiB, 4096_MiB);
BOOST_CHECK_EQUAL(8_GiB, 8192_MiB);
BOOST_CHECK_EQUAL(16_GiB, 16384_MiB);
BOOST_CHECK_EQUAL(32_GiB, 32768_MiB);
}
BOOST_CHECK_EXCEPTION(operator""_GiB(max_gib + 1), std::overflow_error, HasReason("GiB value too large for size_t byte conversion"));
}
BOOST_AUTO_TEST_SUITE_END()