Commit 6afa2994 authored by Victor Zverovich's avatar Victor Zverovich

Allocate large enough buffer to make _ecvt_s happy. Swap the order of template...

Allocate large enough buffer to make _ecvt_s happy. Swap the order of template parameters in TempFormatter for convenience.
parent 452df673
...@@ -191,8 +191,8 @@ inline int SignBit(double value) { ...@@ -191,8 +191,8 @@ inline int SignBit(double value) {
if (value < 0) return 1; if (value < 0) return 1;
if (value == value) return 0; if (value == value) return 0;
int dec = 0, sign = 0; int dec = 0, sign = 0;
char dummy; char buffer[2]; // The buffer size must be >= 2 or _ecvt_s will fail.
_ecvt_s(&dummy, 1, value, 0, &dec, &sign); _ecvt_s(&buffer, sizeof(buffer), value, 0, &dec, &sign);
return sign; return sign;
} }
...@@ -1155,7 +1155,7 @@ class NoAction { ...@@ -1155,7 +1155,7 @@ class NoAction {
Objects of this class normally exist only as temporaries returned Objects of this class normally exist only as temporaries returned
by one of the formatting functions which explains the name. by one of the formatting functions which explains the name.
*/ */
template <typename Char, typename Action = NoAction> template <typename Action = NoAction, typename Char = char>
class TempFormatter : public internal::ArgInserter<Char> { class TempFormatter : public internal::ArgInserter<Char> {
private: private:
BasicFormatter<Char> formatter_; BasicFormatter<Char> formatter_;
...@@ -1232,8 +1232,8 @@ class TempFormatter : public internal::ArgInserter<Char> { ...@@ -1232,8 +1232,8 @@ class TempFormatter : public internal::ArgInserter<Char> {
See also `Format String Syntax`_. See also `Format String Syntax`_.
\endrst \endrst
*/ */
inline TempFormatter<char> Format(StringRef format) { inline TempFormatter<> Format(StringRef format) {
return TempFormatter<char>(format); return TempFormatter<>(format);
} }
// A formatting action that writes formatted output to stdout. // A formatting action that writes formatted output to stdout.
...@@ -1246,8 +1246,8 @@ struct Write { ...@@ -1246,8 +1246,8 @@ struct Write {
// Formats a string and prints it to stdout. // Formats a string and prints it to stdout.
// Example: // Example:
// Print("Elapsed time: {0:.2f} seconds") << 1.23; // Print("Elapsed time: {0:.2f} seconds") << 1.23;
inline TempFormatter<char, Write> Print(StringRef format) { inline TempFormatter<Write> Print(StringRef format) {
return TempFormatter<char, Write>(format); return TempFormatter<Write>(format);
} }
// Throws Exception(message) if format contains '}', otherwise throws // Throws Exception(message) if format contains '}', otherwise throws
......
...@@ -1086,7 +1086,7 @@ struct CountCalls { ...@@ -1086,7 +1086,7 @@ struct CountCalls {
TEST(TempFormatterTest, Action) { TEST(TempFormatterTest, Action) {
int num_calls = 0; int num_calls = 0;
{ {
fmt::TempFormatter<char, CountCalls> af("test", CountCalls(num_calls)); fmt::TempFormatter<CountCalls> af("test", CountCalls(num_calls));
EXPECT_EQ(0, num_calls); EXPECT_EQ(0, num_calls);
} }
EXPECT_EQ(1, num_calls); EXPECT_EQ(1, num_calls);
...@@ -1095,7 +1095,7 @@ TEST(TempFormatterTest, Action) { ...@@ -1095,7 +1095,7 @@ TEST(TempFormatterTest, Action) {
TEST(TempFormatterTest, ActionNotCalledOnError) { TEST(TempFormatterTest, ActionNotCalledOnError) {
int num_calls = 0; int num_calls = 0;
{ {
typedef fmt::TempFormatter<char, CountCalls> TestFormatter; typedef fmt::TempFormatter<CountCalls> TestFormatter;
EXPECT_THROW(TestFormatter af("{0", CountCalls(num_calls)), FormatError); EXPECT_THROW(TestFormatter af("{0", CountCalls(num_calls)), FormatError);
} }
EXPECT_EQ(0, num_calls); EXPECT_EQ(0, num_calls);
...@@ -1108,8 +1108,8 @@ TEST(TempFormatterTest, ActionNotCalledOnError) { ...@@ -1108,8 +1108,8 @@ TEST(TempFormatterTest, ActionNotCalledOnError) {
TEST(TempFormatterTest, ArgLifetime) { TEST(TempFormatterTest, ArgLifetime) {
// The following code is for testing purposes only. It is a definite abuse // The following code is for testing purposes only. It is a definite abuse
// of the API and shouldn't be used in real applications. // of the API and shouldn't be used in real applications.
const fmt::TempFormatter<char> &af = fmt::Format("{0}"); const fmt::TempFormatter<> &af = fmt::Format("{0}");
const_cast<fmt::TempFormatter<char>&>(af) << std::string("test"); const_cast<fmt::TempFormatter<>&>(af) << std::string("test");
// String object passed as an argument to TempFormatter has // String object passed as an argument to TempFormatter has
// been destroyed, but ArgInserter dtor hasn't been called yet. // been destroyed, but ArgInserter dtor hasn't been called yet.
// But that's OK since the Arg's dtor takes care of this and // But that's OK since the Arg's dtor takes care of this and
...@@ -1128,8 +1128,8 @@ struct PrintError { ...@@ -1128,8 +1128,8 @@ struct PrintError {
} }
}; };
fmt::TempFormatter<char, PrintError> ReportError(const char *format) { fmt::TempFormatter<PrintError> ReportError(const char *format) {
return fmt::TempFormatter<char, PrintError>(format); return fmt::TempFormatter<PrintError>(format);
} }
TEST(TempFormatterTest, Examples) { TEST(TempFormatterTest, Examples) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment