From 21d610fb26b275f489dacbd6c372ddf55323ea55 Mon Sep 17 00:00:00 2001 From: "deanm@google.com" Date: Wed, 13 Aug 2008 11:09:33 +0000 Subject: Implement IntToString-type methods without using a format string. I'm not sure if this will actually be more efficient. Also will make Int64ToString work on other platforms, since the old code used msvc-only %I64. Added a bunch of methods to have the whole Int/Int64 String/WString suite. git-svn-id: svn://svn.chromium.org/chrome/trunk/src@784 0039d316-1c4b-4281-b951-d872f2087c98 --- base/string_util.cc | 101 ++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 90 insertions(+), 11 deletions(-) (limited to 'base/string_util.cc') diff --git a/base/string_util.cc b/base/string_util.cc index bd02f3d..864612ae 100644 --- a/base/string_util.cc +++ b/base/string_util.cc @@ -852,24 +852,103 @@ static void StringAppendVT( } } -std::string Uint64ToString(uint64 value) { - return StringPrintf("%llu", value); -} +namespace { -std::string Int64ToString(int64 value) { - return StringPrintf("%I64d", value); -} +template +struct IntToStringT { + + // This is to avoid a compiler warning about unary minus on unsigned type. + // For example, say you had the following code: + // template + // INT abs(INT value) { return value < 0 ? -value : value; } + // Even though if INT is unsigned, it's impossible for value < 0, so the + // unary minus will never be taken, the compiler will still generate a + // warning. We do a little specialization dance... + template + struct ToUnsignedT { }; + + template + struct ToUnsignedT { + static UINT2 ToUnsigned(INT2 value) { + return static_cast(value); + } + }; + + template + struct ToUnsignedT { + static UINT2 ToUnsigned(INT2 value) { + return static_cast(value < 0 ? -value : value); + } + }; + + static STR IntToString(INT value) { + // log10(2) ~= 0.3 bytes needed per bit or per byte log10(2**8) ~= 2.4. + // So round up to allocate 3 output characters per byte, plus 1 for '-'. + const int kOutputBufSize = 3 * sizeof(INT) + 1; + + // Allocate the whole string right away, we will right back to front, and + // then return the substr of what we ended up using. + STR outbuf(kOutputBufSize, 0); + + bool is_neg = value < 0; + // Even though is_neg will never be true when INT is parameterized as + // unsigned, even the presence of the unary operation causes a warning. + UINT res = ToUnsignedT::ToUnsigned(value); + + for (typename STR::iterator it = outbuf.end();;) { + --it; + DCHECK(it != outbuf.begin()); + *it = static_cast((res % 10) + '0'); + res /= 10; + + // We're done.. + if (res == 0) { + if (is_neg) { + --it; + DCHECK(it != outbuf.begin()); + *it = static_cast('-'); + } + return STR(it, outbuf.end()); + } + } + NOTREACHED(); + return STR(); + } +}; -std::wstring Int64ToWString(int64 value) { - return StringPrintf(L"%I64d", value); } std::string IntToString(int value) { - return StringPrintf("%d", value); + return IntToStringT:: + IntToString(value); } - std::wstring IntToWString(int value) { - return StringPrintf(L"%d", value); + return IntToStringT:: + IntToString(value); +} +std::string UintToString(unsigned int value) { + return IntToStringT:: + IntToString(value); +} +std::wstring UintToWString(unsigned int value) { + return IntToStringT:: + IntToString(value); +} +std::string Int64ToString(int64 value) { + return IntToStringT:: + IntToString(value); +} +std::wstring Int64ToWString(int64 value) { + return IntToStringT:: + IntToString(value); +} +std::string Uint64ToString(uint64 value) { + return IntToStringT:: + IntToString(value); +} +std::wstring Uint64ToWString(uint64 value) { + return IntToStringT:: + IntToString(value); } inline void StringAppendV(std::string* dst, const char* format, va_list ap) { -- cgit v1.1