This commit is contained in:
Shakti213 2017-11-02 10:52:17 +00:00 committed by GitHub
commit 198c6562ad
2 changed files with 118 additions and 0 deletions

View File

@ -4085,6 +4085,100 @@ void format_arg(fmt::BasicFormatter<Char, ArgFormatter> &f,
}
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
#if FMT_USE_USER_DEFINED_LITERALS

View File

@ -1604,6 +1604,30 @@ TEST(FormatTest, JoinArg) {
#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>
std::string str(const T &value) {
return fmt::format("{}", value);