Browse Source

Optimize `FormatInteger`

pull/4727/head
Gleb Mazovetskiy 4 years ago committed by Anders Jenbo
parent
commit
563ee3af7c
  1. 1
      Source/CMakeLists.txt
  2. 2
      Source/qol/xpbar.cpp
  3. 48
      Source/utils/format_int.cpp
  4. 45
      Source/utils/format_int.hpp
  5. 1
      test/CMakeLists.txt
  6. 40
      test/format_int_test.cpp

1
Source/CMakeLists.txt

@ -107,6 +107,7 @@ set(libdevilutionx_SRCS
utils/console.cpp
utils/display.cpp
utils/file_util.cpp
utils/format_int.cpp
utils/language.cpp
utils/logged_fstream.cpp
utils/paths.cpp

2
Source/qol/xpbar.cpp

@ -7,6 +7,8 @@
#include <array>
#include <fmt/core.h>
#include "DiabloUI/art_draw.h"
#include "control.h"
#include "engine/point.hpp"

48
Source/utils/format_int.cpp

@ -0,0 +1,48 @@
#include "utils/format_int.hpp"
#include <fmt/compile.h>
#include <fmt/core.h>
#include "utils/language.h"
#include "utils/stdcompat/string_view.hpp"
namespace devilution {
std::string FormatInteger(int n)
{
constexpr size_t GroupSize = 3;
char buf[40];
char *begin = buf;
const char *end = fmt::format_to(buf, FMT_COMPILE("{}"), n);
const size_t len = end - begin;
std::string out;
const size_t prefixLen = n < 0 ? 1 : 0;
const size_t numLen = len - prefixLen;
if (numLen <= GroupSize) {
out.append(begin, len);
return out;
}
const string_view separator = _(/* TRANSLATORS: Thousands separator */ ",");
out.reserve(len + separator.size() * (numLen - 1) / GroupSize);
if (n < 0) {
out += '-';
++begin;
}
size_t mlen = numLen % GroupSize;
if (mlen == 0)
mlen = GroupSize;
out.append(begin, mlen);
begin += mlen;
for (; begin != end; begin += GroupSize) {
AppendStrView(out, separator);
out.append(begin, GroupSize);
}
return out;
}
} // namespace devilution

45
Source/utils/format_int.hpp

@ -1,33 +1,12 @@
#pragma once
#include <string>
#include <fmt/format.h>
#include "utils/language.h"
#include "utils/stdcompat/string_view.hpp"
namespace devilution {
/**
* @brief Formats integer with thousands separator.
*/
inline std::string FormatInteger(int n)
{
std::string number = fmt::format("{:d}", n);
std::string out = "";
int length = number.length();
int mlength = length % 3;
if (mlength == 0)
mlength = 3;
out.append(number.substr(0, mlength));
for (int i = mlength; i < length; i += 3) {
AppendStrView(out, _(/* TRANSLATORS: Thousands separator */ ","));
out.append(number.substr(i, 3));
}
return out;
}
} // namespace devilution
#pragma once
#include <string>
namespace devilution {
/**
* @brief Formats integer with thousands separator.
*/
std::string FormatInteger(int n);
} // namespace devilution

1
test/CMakeLists.txt

@ -25,6 +25,7 @@ set(tests
drlg_l4_test
effects_test
file_util_test
format_int_test
inv_test
lighting_test
math_test

40
test/format_int_test.cpp

@ -0,0 +1,40 @@
#include <gtest/gtest.h>
#include "utils/format_int.hpp"
namespace devilution {
namespace {
TEST(FormatIntegerTest, OneDigit)
{
EXPECT_EQ(FormatInteger(1), "1");
EXPECT_EQ(FormatInteger(-1), "-1");
}
TEST(FormatIntegerTest, TwoDigits)
{
EXPECT_EQ(FormatInteger(12), "12");
EXPECT_EQ(FormatInteger(-12), "-12");
}
TEST(FormatIntegerTest, ThreeDigits)
{
EXPECT_EQ(FormatInteger(123), "123");
EXPECT_EQ(FormatInteger(-123), "-123");
}
TEST(FormatIntegerTest, FourDigits)
{
EXPECT_EQ(FormatInteger(1234), "1,234");
EXPECT_EQ(FormatInteger(-1234), "-1,234");
}
TEST(FormatIntegerTest, SevenDigits)
{
EXPECT_EQ(FormatInteger(1234567), "1,234,567");
EXPECT_EQ(FormatInteger(-1234567), "-1,234,567");
}
} // namespace
} // namespace devilution
Loading…
Cancel
Save