Add bytes to string function

This commit is contained in:
Dan Paulat 2024-03-21 22:21:03 -05:00
parent 8d706c463c
commit 94726631cb
3 changed files with 103 additions and 0 deletions

View file

@ -7,6 +7,35 @@ namespace scwx
namespace util namespace util
{ {
class BytesToStringTest :
public testing::TestWithParam<std::pair<std::ptrdiff_t, std::string>>
{
};
TEST_P(BytesToStringTest, BytesToString)
{
auto& [bytes, expected] = GetParam();
std::string s = BytesToString(bytes);
EXPECT_EQ(s, expected);
}
INSTANTIATE_TEST_SUITE_P(StringsTest,
BytesToStringTest,
testing::Values(std::make_pair(123, "123 bytes"),
std::make_pair(1000, "0.98 KB"),
std::make_pair(1018, "0.99 KB"),
std::make_pair(1024, "1.0 KB"),
std::make_pair(1127, "1.1 KB"),
std::make_pair(1260, "1.23 KB"),
std::make_pair(24012, "23.4 KB"),
std::make_pair(353974, "346 KB"),
std::make_pair(1024000, "0.98 MB"),
std::make_pair(1048576000, "0.98 GB"),
std::make_pair(1073741824000,
"0.98 TB")));
TEST(StringsTest, ParseTokensColor) TEST(StringsTest, ParseTokensColor)
{ {
static const std::string line {"Color: red green blue alpha discarded"}; static const std::string line {"Color: red green blue alpha discarded"};

View file

@ -9,6 +9,16 @@ namespace scwx
namespace util namespace util
{ {
/**
* @brief Print the number of bytes using a dynamic suffix and limited number of
* decimal points.
*
* @param [in] bytes Number of bytes
*
* @return Human readable size string
*/
std::string BytesToString(std::ptrdiff_t bytes);
/** /**
* @brief Parse a list of tokens from a string * @brief Parse a list of tokens from a string
* *

View file

@ -4,12 +4,76 @@
#include <boost/algorithm/string/trim.hpp> #include <boost/algorithm/string/trim.hpp>
#include <boost/lexical_cast.hpp> #include <boost/lexical_cast.hpp>
#include <fmt/format.h>
namespace scwx namespace scwx
{ {
namespace util namespace util
{ {
std::string BytesToString(std::ptrdiff_t bytes)
{
auto FormatNumber = [](double number) -> std::string
{
int precision;
// Determine precision
if (number >= 100.0)
{
precision = 0;
}
else if (number >= 10.0)
{
precision = 1;
}
else
{
precision = 2;
}
// Format the number
std::string formattedNum = fmt::format("{:.{}f}", number, precision);
// Remove trailing zeroes
std::size_t found = formattedNum.find_last_not_of('0');
if (found != std::string::npos && formattedNum[found] == '.')
{
// Keep one trailing zero if it's a decimal point
found++;
}
formattedNum.erase(found + 1, std::string::npos);
return formattedNum;
};
// Print with appropriate suffix
if (bytes < 1000)
{
return fmt::format("{} bytes", bytes);
}
double kilobytes = bytes / 1024.0;
if (kilobytes < 1000.0)
{
return fmt::format("{} KB", FormatNumber(kilobytes));
}
double megabytes = kilobytes / 1024.0;
if (megabytes < 1000.0)
{
return fmt::format("{} MB", FormatNumber(megabytes));
}
double gigabytes = megabytes / 1024.0;
if (gigabytes < 1000.0)
{
return fmt::format("{} GB", FormatNumber(gigabytes));
}
double terabytes = gigabytes / 1024.0;
return fmt::format("{} TB", FormatNumber(terabytes));
}
std::vector<std::string> ParseTokens(const std::string& s, std::vector<std::string> ParseTokens(const std::string& s,
std::vector<std::string> delimiters, std::vector<std::string> delimiters,
std::size_t pos) std::size_t pos)