Merge 9acbaacdae into 7a9c1ba190
This commit is contained in:
commit
198c6562ad
94
fmt/format.h
94
fmt/format.h
@ -4085,6 +4085,100 @@ void format_arg(fmt::BasicFormatter<Char, ArgFormatter> &f,
|
|||||||
}
|
}
|
||||||
format_str = end + 1;
|
format_str = end + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct ArgConcatNoSeparator {
|
||||||
|
template<typename T>
|
||||||
|
void add_separator(T&) const {}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename Char>
|
||||||
|
struct ArgConcatSeparator {
|
||||||
|
BasicCStringRef<Char> sep;
|
||||||
|
ArgConcatSeparator(const BasicCStringRef<Char> &sep): sep(sep) {}
|
||||||
|
template<typename ArgFormatter>
|
||||||
|
void add_separator(fmt::BasicFormatter<Char, ArgFormatter> &f) const {
|
||||||
|
f.writer().write(sep);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename Separator, typename ...Args>
|
||||||
|
struct ArgConcat {
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename Separator>
|
||||||
|
struct ArgConcat<Separator>: public Separator {
|
||||||
|
|
||||||
|
ArgConcat(const Separator &sep): Separator(sep) {}
|
||||||
|
|
||||||
|
template<typename Char, typename ArgFormatter>
|
||||||
|
void format(fmt::BasicFormatter<Char, ArgFormatter> &,
|
||||||
|
const Char *&) const {
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Char, typename ArgFormatter>
|
||||||
|
void format_first(fmt::BasicFormatter<Char, ArgFormatter> &,
|
||||||
|
const Char *&) const {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename Separator, typename A, typename ...Args>
|
||||||
|
struct ArgConcat<Separator, A, Args...>: public ArgConcat<Separator, Args...> {
|
||||||
|
A a;
|
||||||
|
|
||||||
|
ArgConcat(const Separator &sep, A a, Args...args):
|
||||||
|
ArgConcat<Separator, Args...>(sep, args...),
|
||||||
|
a(a){
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Char, typename ArgFormatter>
|
||||||
|
void format(fmt::BasicFormatter<Char, ArgFormatter> &f,
|
||||||
|
const Char *&format_str) const {
|
||||||
|
const Char* save = format_str;
|
||||||
|
this->add_separator(f);
|
||||||
|
f.format(format_str,
|
||||||
|
internal::MakeArg<fmt::BasicFormatter<Char, ArgFormatter> >(a));
|
||||||
|
ArgConcat<Separator, Args...>::format(f, save);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Char, typename ArgFormatter>
|
||||||
|
void format_first(fmt::BasicFormatter<Char, ArgFormatter> &f,
|
||||||
|
const Char *&format_str) const {
|
||||||
|
const Char* save = format_str;
|
||||||
|
f.format(format_str,
|
||||||
|
internal::MakeArg<fmt::BasicFormatter<Char, ArgFormatter> >(a));
|
||||||
|
ArgConcat<Separator, Args...>::format(f, save);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename ...Args>
|
||||||
|
ArgConcat<ArgConcatNoSeparator, Args...> concat(Args...args) {
|
||||||
|
return ArgConcat<ArgConcatNoSeparator, Args...>(ArgConcatNoSeparator(), args...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ...Args>
|
||||||
|
ArgConcat<ArgConcatSeparator<char>, Args...> concat_separated(const BasicCStringRef<char> &sep, Args...args) {
|
||||||
|
return ArgConcat<ArgConcatSeparator<char>, Args...>(ArgConcatSeparator<char>(sep), args...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ...Args>
|
||||||
|
ArgConcat<ArgConcatSeparator<wchar_t>, Args...> concat_separated(const BasicCStringRef<wchar_t> &sep, Args...args) {
|
||||||
|
return ArgConcat<ArgConcatSeparator<wchar_t>, Args...>(ArgConcatSeparator<wchar_t>(sep), args...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ArgFormatter, typename Char, typename Separator, typename ...Args>
|
||||||
|
void format_arg(fmt::BasicFormatter<Char, ArgFormatter> &f,
|
||||||
|
const Char *&format_str, const ArgConcat<Separator, Args...> &e) {
|
||||||
|
const Char* end = format_str;
|
||||||
|
if (*end == ':')
|
||||||
|
++end;
|
||||||
|
while (*end && *end != '}')
|
||||||
|
++end;
|
||||||
|
if (*end != '}')
|
||||||
|
FMT_THROW(FormatError("missing '}' in format string"));
|
||||||
|
|
||||||
|
e.format_first(f, format_str);
|
||||||
|
format_str = end + 1;
|
||||||
|
}
|
||||||
} // namespace fmt
|
} // namespace fmt
|
||||||
|
|
||||||
#if FMT_USE_USER_DEFINED_LITERALS
|
#if FMT_USE_USER_DEFINED_LITERALS
|
||||||
|
|||||||
@ -1604,6 +1604,30 @@ TEST(FormatTest, JoinArg) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(FormatTest, ConcatArg) {
|
||||||
|
using fmt::concat;
|
||||||
|
EXPECT_EQ("123", format("{}", concat(1,2,3)));
|
||||||
|
EXPECT_EQ("()", format("({})", concat()));
|
||||||
|
EXPECT_EQ("(001002003)", format("({:03})", concat(1,2,3)));
|
||||||
|
EXPECT_EQ("(1 hello world 2)", format("({})", concat(1," hello"," world ", 2)));
|
||||||
|
EXPECT_EQ("(1 hello world 2)", format("({}{})", concat(1," hello"," world "), 2));
|
||||||
|
EXPECT_EQ("(+01.20+03.40)", format("({:+06.2f})", concat(1.2f, 3.4f)));
|
||||||
|
|
||||||
|
EXPECT_EQ(L"(1, 2, 3)", format(L"({})", concat(1, L", ", 2, L", ", 3)));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(FormatTest, ConcatSeparatedArg) {
|
||||||
|
using fmt::concat_separated;
|
||||||
|
EXPECT_EQ("(1, 2, 3)", format("({})", concat_separated(", ", 1,2,3)));
|
||||||
|
EXPECT_EQ("()", format("({})", concat_separated(", ")));
|
||||||
|
EXPECT_EQ("(001, 002, 003)", format("({:03})", concat_separated(", ", 1,2,3)));
|
||||||
|
EXPECT_EQ("(1 hello world 2)", format("({})", concat_separated(" ", 1,"hello","world", 2)));
|
||||||
|
EXPECT_EQ("(1 hello world 2)", format("({} {})", concat_separated(" ", 1,"hello","world"), 2));
|
||||||
|
EXPECT_EQ("(+01.20, +03.40)", format("({:+06.2f})", concat_separated(", ", 1.2f, 3.4f)));
|
||||||
|
|
||||||
|
EXPECT_EQ(L"(1, 2, 3)", format(L"({})", concat_separated(L", ", 1, 2, 3)));
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
std::string str(const T &value) {
|
std::string str(const T &value) {
|
||||||
return fmt::format("{}", value);
|
return fmt::format("{}", value);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user