/* * Copyright (C) 2023-present ScyllaDB */ /* * SPDX-License-Identifier: LicenseRef-ScyllaDB-Source-Available-1.0 */ #include "utils/assert.hh" #include "pretty_printers.hh" #include #include template static constexpr std::tuple 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 auto fmt::formatter::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::format( utils::pretty_printed_data_size, fmt::format_context& ctx) const -> decltype(ctx.out()); template auto fmt::formatter::format, char>>( utils::pretty_printed_data_size, fmt::basic_format_context, char>& ctx) const -> decltype(ctx.out()); template auto fmt::formatter::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::format( const utils::pretty_printed_throughput&, fmt::format_context& ctx) const -> decltype(ctx.out()); template auto fmt::formatter::format, char>>( const utils::pretty_printed_throughput&, fmt::basic_format_context, char>& ctx) const -> decltype(ctx.out());