Commit 5edda531 authored by Victor Zverovich's avatar Victor Zverovich

Add fmt::format and deprecate fmt::Format.

parent 428d1147
...@@ -139,6 +139,10 @@ namespace fmt { ...@@ -139,6 +139,10 @@ namespace fmt {
FMT_GCC_EXTENSION typedef long long LongLong; FMT_GCC_EXTENSION typedef long long LongLong;
FMT_GCC_EXTENSION typedef unsigned long long ULongLong; FMT_GCC_EXTENSION typedef unsigned long long ULongLong;
#if FMT_USE_RVALUE_REFERENCES
using std::move;
#endif
template <typename Char> template <typename Char>
class BasicWriter; class BasicWriter;
...@@ -156,11 +160,12 @@ struct FormatSpec; ...@@ -156,11 +160,12 @@ struct FormatSpec;
or as a result of a formatting operation. It is most useful as a parameter or as a result of a formatting operation. It is most useful as a parameter
type to allow passing different types of strings in a function, for example:: type to allow passing different types of strings in a function, for example::
Formatter<> Format(StringRef format); template<typename... Args>
Writer format(StringRef format, const Args & ... args);
Format("{}") << 42; format("{}", 42);
Format(std::string("{}")) << 42; format(std::string("{}"), 42);
Format(Format("{{}}")) << 42; format(format("{{}}"), 42);
\endrst \endrst
*/ */
template <typename Char> template <typename Char>
...@@ -250,8 +255,14 @@ class Array { ...@@ -250,8 +255,14 @@ class Array {
if (ptr_ != data_) delete [] ptr_; if (ptr_ != data_) delete [] ptr_;
} }
FMT_DISALLOW_COPY_AND_ASSIGN(Array);
public:
Array() : size_(0), capacity_(SIZE), ptr_(data_) {}
~Array() { Free(); }
// Move data from other to this array. // Move data from other to this array.
void Move(Array &other) { void move(Array &other) {
size_ = other.size_; size_ = other.size_;
capacity_ = other.capacity_; capacity_ = other.capacity_;
if (other.ptr_ == other.data_) { if (other.ptr_ == other.data_) {
...@@ -265,21 +276,15 @@ class Array { ...@@ -265,21 +276,15 @@ class Array {
} }
} }
FMT_DISALLOW_COPY_AND_ASSIGN(Array);
public:
Array() : size_(0), capacity_(SIZE), ptr_(data_) {}
~Array() { Free(); }
#if FMT_USE_RVALUE_REFERENCES #if FMT_USE_RVALUE_REFERENCES
Array(Array &&other) { Array(Array &&other) {
Move(other); move(other);
} }
Array& operator=(Array &&other) { Array& operator=(Array &&other) {
assert(this != &other); assert(this != &other);
Free(); Free();
Move(other); move(other);
return *this; return *this;
} }
#endif #endif
...@@ -977,7 +982,8 @@ template <typename Char> ...@@ -977,7 +982,8 @@ template <typename Char>
class BasicWriter { class BasicWriter {
private: private:
// Output buffer. // Output buffer.
mutable internal::Array<Char, internal::INLINE_BUFFER_SIZE> buffer_; typedef internal::Array<Char, internal::INLINE_BUFFER_SIZE> Buffer;
mutable Buffer buffer_;
// Make BasicFormatter a friend so that it can access ArgInfo and Arg. // Make BasicFormatter a friend so that it can access ArgInfo and Arg.
friend class BasicFormatter<Char>; friend class BasicFormatter<Char>;
...@@ -1220,6 +1226,21 @@ class BasicWriter { ...@@ -1220,6 +1226,21 @@ class BasicWriter {
buffer_ = std::move(other.buffer_); buffer_ = std::move(other.buffer_);
return *this; return *this;
} }
#else
friend inline BasicWriter &move(BasicWriter &w) { return w; }
private:
struct Proxy { Buffer *buffer; };
public:
operator Proxy() {
Proxy p = {&buffer_};
return p;
}
// "Move" constructors.
BasicWriter(BasicWriter &other) { buffer_.move(other.buffer_); }
BasicWriter(Proxy p) { buffer_.move(*p.buffer); }
#endif #endif
/** /**
...@@ -1988,25 +2009,12 @@ inline Formatter<ANSITerminalSink> PrintColored(Color c, StringRef format) { ...@@ -1988,25 +2009,12 @@ inline Formatter<ANSITerminalSink> PrintColored(Color c, StringRef format) {
return f; return f;
} }
#if FMT_USE_VARIADIC_TEMPLATES && FMT_USE_RVALUE_REFERENCES
template <typename Char>
template<typename... Args>
void BasicWriter<Char>::Format(
BasicStringRef<Char> format, const Args & ... args) {
this->format(format, args...);
}
/** /**
\rst \rst
Formats a string similarly to Python's `str.format Formats a string similarly to Python's `str.format
<http://docs.python.org/3/library/stdtypes.html#str.format>`__ function <http://docs.python.org/3/library/stdtypes.html#str.format>`__ function
and returns an :cpp:class:`fmt::BasicWriter` object containing the output. and returns an :cpp:class:`fmt::BasicWriter` object containing the output.
This version of the Format function uses C++11 features such as
variadic templates and rvalue references. For C++98 version, see
the :cpp:func:`fmt::Format()` overload above.
*format* is a format string that contains literal text and replacement *format* is a format string that contains literal text and replacement
fields surrounded by braces ``{}``. The formatter object replaces the fields surrounded by braces ``{}``. The formatter object replaces the
fields with formatted arguments and stores the output in a memory buffer. fields with formatted arguments and stores the output in a memory buffer.
...@@ -2016,11 +2024,30 @@ void BasicWriter<Char>::Format( ...@@ -2016,11 +2024,30 @@ void BasicWriter<Char>::Format(
**Example**:: **Example**::
std::string message = str(Format("The answer is {}", 42)); std::string message = str(format("The answer is {}", 42));
See also `Format String Syntax`_. See also `Format String Syntax`_.
\endrst \endrst
*/ */
inline Writer format(StringRef format, const ArgList &args) {
Writer w;
w.format(format, args);
return move(w);
}
#if FMT_USE_VARIADIC_TEMPLATES && FMT_USE_RVALUE_REFERENCES
template <typename Char>
template<typename... Args>
void BasicWriter<Char>::Format(
BasicStringRef<Char> format, const Args & ... args) {
this->format(format, args...);
}
// This function is deprecated, use fmt::format instead.
template<typename... Args>
FMT_DEPRECATED(Writer Format(StringRef format, const Args & ... args));
template<typename... Args> template<typename... Args>
inline Writer Format(StringRef format, const Args & ... args) { inline Writer Format(StringRef format, const Args & ... args) {
Writer w; Writer w;
...@@ -2038,7 +2065,7 @@ inline WWriter Format(WStringRef format, const Args & ... args) { ...@@ -2038,7 +2065,7 @@ inline WWriter Format(WStringRef format, const Args & ... args) {
template<typename... Args> template<typename... Args>
void Print(StringRef format, const Args & ... args) { void Print(StringRef format, const Args & ... args) {
Writer w; Writer w;
w.Format(format, args...); w.format(format, args...);
std::fwrite(w.data(), 1, w.size(), stdout); std::fwrite(w.data(), 1, w.size(), stdout);
} }
...@@ -2252,6 +2279,8 @@ inline void FormatDec(char *&buffer, T value) { ...@@ -2252,6 +2279,8 @@ inline void FormatDec(char *&buffer, T value) {
#endif // FMT_USE_VARIADIC_TEMPLATES #endif // FMT_USE_VARIADIC_TEMPLATES
FMT_VARIADIC(fmt::Writer, format, fmt::StringRef)
// Restore warnings. // Restore warnings.
#if FMT_GCC_VERSION >= 406 #if FMT_GCC_VERSION >= 406
# pragma GCC diagnostic pop # pragma GCC diagnostic pop
......
...@@ -26,7 +26,7 @@ expect_compile_error("fmt::internal::Array<char, 5> a, b(a);") ...@@ -26,7 +26,7 @@ expect_compile_error("fmt::internal::Array<char, 5> a, b(a);")
expect_compile_error("fmt::internal::Array<char, 5> a, b; b = a;") expect_compile_error("fmt::internal::Array<char, 5> a, b; b = a;")
# Writer is noncopyable. # Writer is noncopyable.
expect_compile_error("fmt::Writer a, b(a);") expect_compile_error("const fmt::Writer a, b(a);")
expect_compile_error("fmt::Writer a, b; b = a;") expect_compile_error("fmt::Writer a, b; b = a;")
# Formatter is not copyable from a temporary. # Formatter is not copyable from a temporary.
......
...@@ -1359,9 +1359,9 @@ TEST(FormatterTest, FormatExamples) { ...@@ -1359,9 +1359,9 @@ TEST(FormatterTest, FormatExamples) {
std::string message = str(Format("The answer is {}") << 42); std::string message = str(Format("The answer is {}") << 42);
EXPECT_EQ("The answer is 42", message); EXPECT_EQ("The answer is 42", message);
EXPECT_EQ("42", str(Format("{}") << 42)); EXPECT_EQ("42", str(format("{}", 42)));
EXPECT_EQ("42", str(Format(std::string("{}")) << 42)); EXPECT_EQ("42", str(format(std::string("{}"), 42)));
EXPECT_EQ("42", str(Format(Format("{{}}")) << 42)); EXPECT_EQ("42", str(format(Format("{{}}"), 42)));
Writer writer; Writer writer;
writer.Format("Current point:\n"); writer.Format("Current point:\n");
...@@ -1565,17 +1565,15 @@ TEST(FormatterTest, Examples) { ...@@ -1565,17 +1565,15 @@ TEST(FormatterTest, Examples) {
std::string path = "somefile"; std::string path = "somefile";
ReportError("File not found: {0}") << path; ReportError("File not found: {0}") << path;
#if FMT_USE_VARIADIC_TEMPLATES && FMT_USE_RVALUE_REFERENCES EXPECT_EQ("The answer is 42", str(format("The answer is {}", 42)));
EXPECT_EQ("The answer is 42", str(Format("The answer is {}", 42)));
EXPECT_THROW_MSG( EXPECT_THROW_MSG(
Format("The answer is {:d}", "forty-two"), FormatError, format("The answer is {:d}", "forty-two"), FormatError,
"unknown format code 'd' for string"); "unknown format code 'd' for string");
EXPECT_EQ(L"Cyrillic letter \x42e", EXPECT_EQ(L"Cyrillic letter \x42e",
str(Format(L"Cyrillic letter {}", L'\x42e'))); str(Format(L"Cyrillic letter {}", L'\x42e')));
EXPECT_WRITE(stdout, EXPECT_WRITE(stdout,
fmt::Print("{}", std::numeric_limits<double>::infinity()), "inf"); fmt::Print("{}", std::numeric_limits<double>::infinity()), "inf");
#endif
} }
TEST(FormatIntTest, Data) { TEST(FormatIntTest, Data) {
...@@ -1644,12 +1642,10 @@ TEST(FormatTest, PrintColored) { ...@@ -1644,12 +1642,10 @@ TEST(FormatTest, PrintColored) {
#endif #endif
#if FMT_USE_VARIADIC_TEMPLATES && FMT_USE_RVALUE_REFERENCES
TEST(FormatTest, Variadic) { TEST(FormatTest, Variadic) {
EXPECT_EQ("abc1", str(Format("{}c{}", "ab", 1))); EXPECT_EQ("abc1", str(format("{}c{}", "ab", 1)));
EXPECT_EQ(L"abc1", str(Format(L"{}c{}", L"ab", 1))); EXPECT_EQ(L"abc1", str(Format(L"{}c{}", L"ab", 1)));
} }
#endif // FMT_USE_VARIADIC_TEMPLATES
template <typename T> template <typename T>
std::string str(const T &value) { std::string str(const T &value) {
......
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