mirror of
https://github.com/fmtlib/fmt.git
synced 2024-12-27 03:21:34 +00:00
Test and fix writing wide strings.
This commit is contained in:
parent
257b2106b3
commit
525de51320
17
format.h
17
format.h
@ -530,7 +530,9 @@ class BasicWriter {
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
void FormatDouble(T value, const FormatSpec &spec, int precision);
|
void FormatDouble(T value, const FormatSpec &spec, int precision);
|
||||||
|
|
||||||
CharPtr FormatString(const char *s, std::size_t size, const FormatSpec &spec);
|
template <typename StringChar>
|
||||||
|
CharPtr FormatString(const StringChar *s,
|
||||||
|
std::size_t size, const FormatSpec &spec);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
@ -833,8 +835,9 @@ void BasicWriter<Char>::FormatDouble(
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename Char>
|
template <typename Char>
|
||||||
|
template <typename StringChar>
|
||||||
typename BasicWriter<Char>::CharPtr BasicWriter<Char>::FormatString(
|
typename BasicWriter<Char>::CharPtr BasicWriter<Char>::FormatString(
|
||||||
const char *s, std::size_t size, const FormatSpec &spec) {
|
const StringChar *s, std::size_t size, const FormatSpec &spec) {
|
||||||
CharPtr out = CharPtr();
|
CharPtr out = CharPtr();
|
||||||
if (spec.width() > size) {
|
if (spec.width() > size) {
|
||||||
out = GrowBuffer(spec.width());
|
out = GrowBuffer(spec.width());
|
||||||
@ -1000,7 +1003,7 @@ class BasicFormatter {
|
|||||||
long double long_double_value;
|
long double long_double_value;
|
||||||
const void *pointer_value;
|
const void *pointer_value;
|
||||||
struct {
|
struct {
|
||||||
const char *value;
|
const Char *value;
|
||||||
std::size_t size;
|
std::size_t size;
|
||||||
} string;
|
} string;
|
||||||
struct {
|
struct {
|
||||||
@ -1022,12 +1025,12 @@ class BasicFormatter {
|
|||||||
: type(LONG_DOUBLE), long_double_value(value), formatter(0) {}
|
: type(LONG_DOUBLE), long_double_value(value), formatter(0) {}
|
||||||
Arg(char value) : type(CHAR), int_value(value), formatter(0) {}
|
Arg(char value) : type(CHAR), int_value(value), formatter(0) {}
|
||||||
|
|
||||||
Arg(const char *value) : type(STRING), formatter(0) {
|
Arg(const Char *value) : type(STRING), formatter(0) {
|
||||||
string.value = value;
|
string.value = value;
|
||||||
string.size = 0;
|
string.size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Arg(char *value) : type(STRING), formatter(0) {
|
Arg(Char *value) : type(STRING), formatter(0) {
|
||||||
string.value = value;
|
string.value = value;
|
||||||
string.size = 0;
|
string.size = 0;
|
||||||
}
|
}
|
||||||
@ -1604,13 +1607,13 @@ void BasicFormatter<Char>::DoFormat() {
|
|||||||
case STRING: {
|
case STRING: {
|
||||||
if (spec.type_ && spec.type_ != 's')
|
if (spec.type_ && spec.type_ != 's')
|
||||||
internal::ReportUnknownType(spec.type_, "string");
|
internal::ReportUnknownType(spec.type_, "string");
|
||||||
const char *str = arg.string.value;
|
const Char *str = arg.string.value;
|
||||||
std::size_t size = arg.string.size;
|
std::size_t size = arg.string.size;
|
||||||
if (size == 0) {
|
if (size == 0) {
|
||||||
if (!str)
|
if (!str)
|
||||||
throw FormatError("string pointer is null");
|
throw FormatError("string pointer is null");
|
||||||
if (*str)
|
if (*str)
|
||||||
size = std::strlen(str);
|
size = std::char_traits<Char>::length(str);
|
||||||
}
|
}
|
||||||
writer.FormatString(str, size, spec);
|
writer.FormatString(str, size, spec);
|
||||||
break;
|
break;
|
||||||
|
@ -1030,6 +1030,8 @@ TEST(FormatterTest, CustomFormat) {
|
|||||||
|
|
||||||
TEST(FormatterTest, WideFormatString) {
|
TEST(FormatterTest, WideFormatString) {
|
||||||
EXPECT_EQ(L"42", str(Format(L"{}") << 42));
|
EXPECT_EQ(L"42", str(Format(L"{}") << 42));
|
||||||
|
EXPECT_EQ(L"4.2", str(Format(L"{}") << 4.2));
|
||||||
|
EXPECT_EQ(L"abc", str(Format(L"{}") << L"abc"));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(FormatterTest, FormatStringFromSpeedTest) {
|
TEST(FormatterTest, FormatStringFromSpeedTest) {
|
||||||
@ -1104,7 +1106,7 @@ struct CountCalls {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST(TempFormatterTest, Action) {
|
TEST(FormatterTest, Action) {
|
||||||
int num_calls = 0;
|
int num_calls = 0;
|
||||||
{
|
{
|
||||||
fmt::Formatter<CountCalls> af("test", CountCalls(num_calls));
|
fmt::Formatter<CountCalls> af("test", CountCalls(num_calls));
|
||||||
@ -1113,7 +1115,7 @@ TEST(TempFormatterTest, Action) {
|
|||||||
EXPECT_EQ(1, num_calls);
|
EXPECT_EQ(1, num_calls);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(TempFormatterTest, ActionNotCalledOnError) {
|
TEST(FormatterTest, ActionNotCalledOnError) {
|
||||||
int num_calls = 0;
|
int num_calls = 0;
|
||||||
{
|
{
|
||||||
typedef fmt::Formatter<CountCalls> TestFormatter;
|
typedef fmt::Formatter<CountCalls> TestFormatter;
|
||||||
@ -1126,19 +1128,18 @@ TEST(TempFormatterTest, ActionNotCalledOnError) {
|
|||||||
// require an accessible copy constructor when binding a temporary to
|
// require an accessible copy constructor when binding a temporary to
|
||||||
// a const reference.
|
// a const reference.
|
||||||
#if __GNUC__ >= 4 && __GNUC_MINOR__ >= 7
|
#if __GNUC__ >= 4 && __GNUC_MINOR__ >= 7
|
||||||
TEST(TempFormatterTest, ArgLifetime) {
|
TEST(FormatterTest, 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::Formatter<> &af = fmt::Format("{0}");
|
const fmt::Formatter<> &af = fmt::Format("{0}");
|
||||||
const_cast<fmt::Formatter<>&>(af) << std::string("test");
|
const_cast<fmt::Formatter<>&>(af) << std::string("test");
|
||||||
// String object passed as an argument to TempFormatter has
|
// String object passed as an argument to Formatter has been destroyed,
|
||||||
// been destroyed, but ArgInserter dtor hasn't been called yet.
|
// but Formatter's dtor hasn't been called yet. That's OK since the Arg's
|
||||||
// But that's OK since the Arg's dtor takes care of this and
|
// dtor takes care of this and calls Format.
|
||||||
// calls Format.
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
TEST(TempFormatterTest, ConvertToStringRef) {
|
TEST(FormatterTest, ConvertToStringRef) {
|
||||||
EXPECT_STREQ("abc", StringRef(Format("a{0}c") << 'b').c_str());
|
EXPECT_STREQ("abc", StringRef(Format("a{0}c") << 'b').c_str());
|
||||||
EXPECT_EQ(3u, StringRef(Format("a{0}c") << 'b').size());
|
EXPECT_EQ(3u, StringRef(Format("a{0}c") << 'b').size());
|
||||||
}
|
}
|
||||||
@ -1153,7 +1154,7 @@ fmt::Formatter<PrintError> ReportError(const char *format) {
|
|||||||
return fmt::Formatter<PrintError>(format);
|
return fmt::Formatter<PrintError>(format);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(TempFormatterTest, Examples) {
|
TEST(FormatterTest, Examples) {
|
||||||
EXPECT_EQ("First, thou shalt count to three",
|
EXPECT_EQ("First, thou shalt count to three",
|
||||||
str(Format("First, thou shalt count to {0}") << "three"));
|
str(Format("First, thou shalt count to {0}") << "three"));
|
||||||
EXPECT_EQ("Bring me a shrubbery",
|
EXPECT_EQ("Bring me a shrubbery",
|
||||||
|
Loading…
Reference in New Issue
Block a user