Batch #11646 by cremane: 2 byte-identical, 1 confirmed by peer review. - fn_03451 StringFormat: byte-identical - fn_07595 ?GetBuffer@ThreadSafeBuffer@?A0xfae978cd@@QAEPADXZ: logic confirmed by peer review - fn_18252 FormatOwnedString: byte-identical Peer-reviewed-by: Yommy, KWDev Accepted without human review: peers confirmed the logic ("same" ahead by at least 3, with 70% of the votes).
138 lines
3.2 KiB
C++
138 lines
3.2 KiB
C++
#include "Utility/Text/FormatString.h"
|
|
#include "Utility/Threading/NSyncObject.h"
|
|
|
|
#include <array>
|
|
#include <cstdarg>
|
|
#include <cstdio>
|
|
#include <cstdlib>
|
|
#include <cstring>
|
|
#include <map>
|
|
#include <windows.h>
|
|
|
|
// GLOBAL: gl_24365
|
|
static char s_numberBuffer[1024];
|
|
|
|
// OFFSET: 0x005BAEF0
|
|
// FUNCTION: fn_03451
|
|
int StringFormat(char* buffer, std::size_t sizeInBytes, std::size_t count, const char* format, ...) {
|
|
int result;
|
|
va_list args;
|
|
|
|
va_start(args, format);
|
|
result = _vsnprintf_s_l(buffer, sizeInBytes, count, format, nullptr, args);
|
|
va_end(args);
|
|
|
|
return result;
|
|
}
|
|
|
|
namespace {
|
|
class ThreadSafeBuffer {
|
|
public:
|
|
// OFFSET: 0x00733F00
|
|
// FUNCTION: fn_07592
|
|
ThreadSafeBuffer() {
|
|
InitializeCriticalSection(&this->m_criticalSection);
|
|
}
|
|
|
|
// INLINED
|
|
virtual ~ThreadSafeBuffer() {
|
|
DeleteCriticalSection(&this->m_criticalSection);
|
|
}
|
|
|
|
char* GetBuffer();
|
|
|
|
private:
|
|
/* 0004 */ CRITICAL_SECTION m_criticalSection;
|
|
/* 001C */ std::map<int, std::array<char, 2048>> m_buffers;
|
|
};
|
|
|
|
// OFFSET: 0x00734390
|
|
// FUNCTION: fn_07595
|
|
char* ThreadSafeBuffer::GetBuffer() {
|
|
NSyncObject lock(&this->m_criticalSection);
|
|
const int thread = reinterpret_cast<int>(GetCurrentThread());
|
|
|
|
if (this->m_buffers.find(thread) == this->m_buffers.end()) {
|
|
std::array<char, 2048> buffer{};
|
|
this->m_buffers[thread] = buffer;
|
|
}
|
|
|
|
return this->m_buffers[thread].data();
|
|
}
|
|
}
|
|
|
|
// OFFSET: 0x00734470
|
|
// FUNCTION: fn_07596
|
|
const char* FormatString(const char* format, ...) {
|
|
static ThreadSafeBuffer s_buffer;
|
|
char* buffer = s_buffer.GetBuffer();
|
|
|
|
va_list args;
|
|
va_start(args, format);
|
|
std::vsnprintf(buffer, 2048, format, args);
|
|
va_end(args);
|
|
|
|
return s_buffer.GetBuffer();
|
|
}
|
|
|
|
// OFFSET: 0x00AF62D0
|
|
// FUNCTION: fn_18252
|
|
std::string FormatOwnedString(const char* format, ...) {
|
|
char buffer[4096];
|
|
va_list arguments;
|
|
|
|
va_start(arguments, format);
|
|
_vsnprintf_s(buffer, sizeof(buffer), _TRUNCATE, format, arguments);
|
|
va_end(arguments);
|
|
|
|
return std::string(buffer);
|
|
}
|
|
|
|
// OFFSET: 0x00A95590
|
|
// FUNCTION: fn_17181
|
|
std::string IntToString(int value, unsigned int digits) {
|
|
if (digits == 0) {
|
|
_itoa(value, s_numberBuffer, 10);
|
|
return std::string(s_numberBuffer);
|
|
}
|
|
|
|
std::sprintf(s_numberBuffer, "%.10d", value);
|
|
std::string text(s_numberBuffer);
|
|
if (text.size() > digits) {
|
|
text.erase(0, text.size() - digits);
|
|
}
|
|
|
|
return text;
|
|
}
|
|
|
|
// OFFSET: 0x00A95790
|
|
// FUNCTION: fn_17182
|
|
std::string IntToSignedString(int value, bool grouped, bool showPlus) {
|
|
if (!grouped) {
|
|
return IntToString(value, 0);
|
|
}
|
|
|
|
const unsigned int bits = static_cast<unsigned int>(value);
|
|
const unsigned int magnitude = value < 0 ? 0u - bits : bits;
|
|
std::string digits = IntToString(static_cast<int>(magnitude), 0);
|
|
std::string text;
|
|
const bool negative = value < 0;
|
|
for (std::size_t i = 0; i < digits.size(); ++i) {
|
|
if ((digits.size() - i) % 3 == 0) {
|
|
text += std::string(",");
|
|
}
|
|
text += digits.at(i);
|
|
}
|
|
|
|
if (text.at(0) == ',') {
|
|
text.erase(0, 1);
|
|
}
|
|
|
|
if (negative) {
|
|
text.insert(text.begin(), '-');
|
|
} else if (showPlus && value != 0) {
|
|
text.insert(text.begin(), '+');
|
|
}
|
|
|
|
return text;
|
|
}
|