Drop the AGPL license in favor of a source-available license. See the blog post [1] for details. [1] https://www.scylladb.com/2024/12/18/why-were-moving-to-a-source-available-license/
100 lines
3.7 KiB
C++
100 lines
3.7 KiB
C++
/*
|
|
* Copyright (C) 2023-present ScyllaDB
|
|
*/
|
|
|
|
/*
|
|
* SPDX-License-Identifier: LicenseRef-ScyllaDB-Source-Available-1.0
|
|
*/
|
|
|
|
#include "utils/assert.hh"
|
|
#include "pretty_printers.hh"
|
|
#include <tuple>
|
|
#include <cassert>
|
|
|
|
template <typename Suffixes>
|
|
static constexpr std::tuple<size_t, std::string_view, std::string_view>
|
|
do_format(size_t n, Suffixes suffixes, unsigned scale, unsigned precision, bool bytes) {
|
|
SCYLLA_ASSERT(scale < precision);
|
|
size_t factor = n;
|
|
const char* suffix = "";
|
|
size_t remainder = 0;
|
|
for (auto next_suffix : suffixes) {
|
|
if (factor < precision && remainder == 0) {
|
|
// If there is no remainder we go below precision because we don't
|
|
// loose any.
|
|
break;
|
|
}
|
|
if (factor < scale) {
|
|
break;
|
|
}
|
|
remainder = factor % scale;
|
|
factor /= scale;
|
|
suffix = next_suffix;
|
|
}
|
|
if (!bytes) {
|
|
return {factor, suffix, ""};
|
|
}
|
|
if (factor == n) {
|
|
if (n == 1) {
|
|
return {factor, suffix, " byte"};
|
|
} else {
|
|
return {factor, suffix, " bytes"};
|
|
}
|
|
} else {
|
|
return {factor, suffix, "B"};
|
|
}
|
|
}
|
|
|
|
template <typename FormatContext>
|
|
auto fmt::formatter<utils::pretty_printed_data_size>::format(utils::pretty_printed_data_size data_size,
|
|
FormatContext& ctx) const -> decltype(ctx.out()) {
|
|
if (_prefix == prefix_type::IEC) {
|
|
// ISO/IEC units
|
|
static constexpr auto suffixes = {"Ki", "Mi", "Gi", "Ti", "Pi"};
|
|
auto [n, suffix, bytes] = do_format(data_size._size, suffixes, 1024, 8192, _bytes);
|
|
return fmt::format_to(ctx.out(), "{}{}{}", n, suffix, bytes);
|
|
} else if (_prefix == prefix_type::IEC_SANS_I) {
|
|
static constexpr auto suffixes = {"K", "M", "G", "T", "P"};
|
|
auto [n, suffix, bytes] = do_format(data_size._size, suffixes, 1024, 8192, false);
|
|
if (suffix.empty()) {
|
|
bytes = "B";
|
|
}
|
|
return fmt::format_to(ctx.out(), "{}{}{}", n, suffix, bytes);
|
|
} else {
|
|
// SI units
|
|
static constexpr auto suffixes = {"k", "M", "G", "T", "P"};
|
|
auto [n, suffix, bytes] = do_format(data_size._size, suffixes, 1000, 10000, _bytes);
|
|
return fmt::format_to(ctx.out(), "{}{}{}", n, suffix, bytes);
|
|
}
|
|
}
|
|
|
|
template
|
|
auto fmt::formatter<utils::pretty_printed_data_size>::format<fmt::format_context>(
|
|
utils::pretty_printed_data_size,
|
|
fmt::format_context& ctx) const
|
|
-> decltype(ctx.out());
|
|
template
|
|
auto fmt::formatter<utils::pretty_printed_data_size>::format<fmt::basic_format_context<std::back_insert_iterator<std::string>, char>>(
|
|
utils::pretty_printed_data_size,
|
|
fmt::basic_format_context<std::back_insert_iterator<std::string>, char>& ctx) const
|
|
-> decltype(ctx.out());
|
|
|
|
template <typename FormatContext>
|
|
auto fmt::formatter<utils::pretty_printed_throughput>::format(const utils::pretty_printed_throughput& tp,
|
|
FormatContext& ctx) const -> decltype(ctx.out()) {
|
|
uint64_t throughput = tp._duration.count() > 0 ? tp._size / tp._duration.count() : 0;
|
|
auto out = size_formatter::format(utils::pretty_printed_data_size{throughput}, ctx);
|
|
return fmt::format_to(out, "{}", "/s");
|
|
}
|
|
|
|
template
|
|
auto fmt::formatter<utils::pretty_printed_throughput>::format<fmt::format_context>(
|
|
const utils::pretty_printed_throughput&,
|
|
fmt::format_context& ctx) const
|
|
-> decltype(ctx.out());
|
|
template
|
|
auto fmt::formatter<utils::pretty_printed_throughput>::format<fmt::basic_format_context<std::back_insert_iterator<std::string>, char>>(
|
|
const utils::pretty_printed_throughput&,
|
|
fmt::basic_format_context<std::back_insert_iterator<std::string>, char>& ctx) const
|
|
-> decltype(ctx.out());
|