Add support for back_insert_iterator
This commit is contained in:
parent
91ee9c9acd
commit
9a53a706fc
@ -83,7 +83,7 @@ endfunction()
|
|||||||
# Define the fmt library, its includes and the needed defines.
|
# Define the fmt library, its includes and the needed defines.
|
||||||
# format.cc is added to FMT_HEADERS for the header-only configuration.
|
# format.cc is added to FMT_HEADERS for the header-only configuration.
|
||||||
add_headers(FMT_HEADERS core.h format.h format.cc locale.h ostream.h printf.h
|
add_headers(FMT_HEADERS core.h format.h format.cc locale.h ostream.h printf.h
|
||||||
string.h time.h)
|
time.h)
|
||||||
if (HAVE_OPEN)
|
if (HAVE_OPEN)
|
||||||
add_headers(FMT_HEADERS posix.h)
|
add_headers(FMT_HEADERS posix.h)
|
||||||
add_headers(FMT_SOURCES posix.cc)
|
add_headers(FMT_SOURCES posix.cc)
|
||||||
|
@ -176,6 +176,18 @@ class basic_string_view {
|
|||||||
using string_view = basic_string_view<char>;
|
using string_view = basic_string_view<char>;
|
||||||
using wstring_view = basic_string_view<wchar_t>;
|
using wstring_view = basic_string_view<wchar_t>;
|
||||||
|
|
||||||
|
template <typename Context>
|
||||||
|
class basic_arg;
|
||||||
|
|
||||||
|
template <typename Context>
|
||||||
|
class basic_format_args;
|
||||||
|
|
||||||
|
// A formatter for objects of type T.
|
||||||
|
template <typename T, typename Char = char, typename Enable = void>
|
||||||
|
struct formatter;
|
||||||
|
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
/** A contiguous memory buffer with an optional growing ability. */
|
/** A contiguous memory buffer with an optional growing ability. */
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class basic_buffer {
|
class basic_buffer {
|
||||||
@ -253,21 +265,6 @@ class basic_buffer {
|
|||||||
const T &operator[](std::size_t index) const { return ptr_[index]; }
|
const T &operator[](std::size_t index) const { return ptr_[index]; }
|
||||||
};
|
};
|
||||||
|
|
||||||
using buffer = basic_buffer<char>;
|
|
||||||
using wbuffer = basic_buffer<wchar_t>;
|
|
||||||
|
|
||||||
template <typename Context>
|
|
||||||
class basic_arg;
|
|
||||||
|
|
||||||
template <typename Context>
|
|
||||||
class basic_format_args;
|
|
||||||
|
|
||||||
// A formatter for objects of type T.
|
|
||||||
template <typename T, typename Char = char, typename Enable = void>
|
|
||||||
struct formatter;
|
|
||||||
|
|
||||||
namespace internal {
|
|
||||||
|
|
||||||
// A helper function to suppress bogus "conditional expression is constant"
|
// A helper function to suppress bogus "conditional expression is constant"
|
||||||
// warnings.
|
// warnings.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@ -583,7 +580,7 @@ class value {
|
|||||||
typename Context::template formatter_type<T> f;
|
typename Context::template formatter_type<T> f;
|
||||||
auto &&parse_ctx = ctx.parse_context();
|
auto &&parse_ctx = ctx.parse_context();
|
||||||
parse_ctx.advance_to(f.parse(parse_ctx));
|
parse_ctx.advance_to(f.parse(parse_ctx));
|
||||||
ctx.advance_to(f.format(*static_cast<const T*>(arg), ctx));
|
f.format(*static_cast<const T*>(arg), ctx);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -797,7 +794,7 @@ class context_base {
|
|||||||
Range range() { return range_; }
|
Range range() { return range_; }
|
||||||
|
|
||||||
// Returns an iterator to the beginning of the output range.
|
// Returns an iterator to the beginning of the output range.
|
||||||
iterator begin() { return out_; }
|
auto begin() { return std::back_inserter(range_.container()); }
|
||||||
|
|
||||||
// Advances the begin iterator to ``it``.
|
// Advances the begin iterator to ``it``.
|
||||||
void advance_to(iterator it) { out_ = it; }
|
void advance_to(iterator it) { out_ = it; }
|
||||||
@ -878,6 +875,9 @@ class basic_context :
|
|||||||
format_arg get_arg(basic_string_view<char_type> name);
|
format_arg get_arg(basic_string_view<char_type> name);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
using buffer = internal::basic_buffer<char>;
|
||||||
|
using wbuffer = internal::basic_buffer<wchar_t>;
|
||||||
|
|
||||||
using context = basic_context<internal::dynamic_range<buffer>>;
|
using context = basic_context<internal::dynamic_range<buffer>>;
|
||||||
using wcontext = basic_context<internal::dynamic_range<wbuffer>>;
|
using wcontext = basic_context<internal::dynamic_range<wbuffer>>;
|
||||||
|
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <iterator>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
@ -296,17 +297,6 @@ inline stdext::checked_array_iterator<T*> make_ptr(T *ptr, std::size_t size) {
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
inline T *make_ptr(T *ptr, std::size_t) { return ptr; }
|
inline T *make_ptr(T *ptr, std::size_t) { return ptr; }
|
||||||
#endif
|
#endif
|
||||||
} // namespace internal
|
|
||||||
|
|
||||||
// A wrapper around std::locale used to reduce compile times since <locale>
|
|
||||||
// is very heavy.
|
|
||||||
class locale;
|
|
||||||
|
|
||||||
class locale_provider {
|
|
||||||
public:
|
|
||||||
virtual ~locale_provider() {}
|
|
||||||
virtual fmt::locale locale();
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
template <typename U>
|
template <typename U>
|
||||||
@ -318,10 +308,32 @@ void basic_buffer<T>::append(const U *begin, const U *end) {
|
|||||||
size_ = new_size;
|
size_ = new_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Char>
|
template <typename Container>
|
||||||
inline std::basic_string<Char> to_string(const basic_buffer<Char>& buffer) {
|
class container_buffer
|
||||||
return std::basic_string<Char>(buffer.data(), buffer.size());
|
: public internal::basic_buffer<typename Container::value_type> {
|
||||||
}
|
private:
|
||||||
|
Container &container_;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void grow(std::size_t capacity) {
|
||||||
|
container_.resize(capacity);
|
||||||
|
this->set(&container_[0], capacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit container_buffer(Container &c) : container_(c) {}
|
||||||
|
};
|
||||||
|
} // namespace internal
|
||||||
|
|
||||||
|
// A wrapper around std::locale used to reduce compile times since <locale>
|
||||||
|
// is very heavy.
|
||||||
|
class locale;
|
||||||
|
|
||||||
|
class locale_provider {
|
||||||
|
public:
|
||||||
|
virtual ~locale_provider() {}
|
||||||
|
virtual fmt::locale locale();
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
\rst
|
\rst
|
||||||
@ -354,7 +366,7 @@ inline std::basic_string<Char> to_string(const basic_buffer<Char>& buffer) {
|
|||||||
*/
|
*/
|
||||||
template <typename T, std::size_t SIZE = internal::INLINE_BUFFER_SIZE,
|
template <typename T, std::size_t SIZE = internal::INLINE_BUFFER_SIZE,
|
||||||
typename Allocator = std::allocator<T> >
|
typename Allocator = std::allocator<T> >
|
||||||
class basic_memory_buffer : private Allocator, public basic_buffer<T> {
|
class basic_memory_buffer: private Allocator, public internal::basic_buffer<T> {
|
||||||
private:
|
private:
|
||||||
T store_[SIZE];
|
T store_[SIZE];
|
||||||
|
|
||||||
@ -453,7 +465,7 @@ typedef basic_memory_buffer<wchar_t> wmemory_buffer;
|
|||||||
\endrst
|
\endrst
|
||||||
*/
|
*/
|
||||||
template <typename Char>
|
template <typename Char>
|
||||||
class basic_fixed_buffer : public basic_buffer<Char> {
|
class basic_fixed_buffer : public internal::basic_buffer<Char> {
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
\rst
|
\rst
|
||||||
@ -2790,7 +2802,7 @@ struct formatter<
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename FormatContext>
|
template <typename FormatContext>
|
||||||
typename FormatContext::iterator format(const T &val, FormatContext &ctx) {
|
auto format(const T &val, FormatContext &ctx) -> decltype(ctx.begin()) {
|
||||||
internal::handle_dynamic_spec<internal::width_checker>(
|
internal::handle_dynamic_spec<internal::width_checker>(
|
||||||
specs_.width_, specs_.width_ref, ctx);
|
specs_.width_, specs_.width_ref, ctx);
|
||||||
internal::handle_dynamic_spec<internal::precision_checker>(
|
internal::handle_dynamic_spec<internal::precision_checker>(
|
||||||
@ -2893,9 +2905,9 @@ typename basic_context<Range>::format_arg
|
|||||||
|
|
||||||
/** Formats arguments and writes the output to the buffer. */
|
/** Formats arguments and writes the output to the buffer. */
|
||||||
template <typename ArgFormatter, typename Char, typename Context>
|
template <typename ArgFormatter, typename Char, typename Context>
|
||||||
void vformat_to(typename ArgFormatter::range out,
|
void do_vformat_to(typename ArgFormatter::range out,
|
||||||
basic_string_view<Char> format_str,
|
basic_string_view<Char> format_str,
|
||||||
basic_format_args<Context> args) {
|
basic_format_args<Context> args) {
|
||||||
using iterator = internal::null_terminating_iterator<Char>;
|
using iterator = internal::null_terminating_iterator<Char>;
|
||||||
using range = typename ArgFormatter::range;
|
using range = typename ArgFormatter::range;
|
||||||
|
|
||||||
@ -2983,32 +2995,64 @@ constexpr fill_spec_factory fill;
|
|||||||
constexpr format_spec_factory<width_spec> width;
|
constexpr format_spec_factory<width_spec> width;
|
||||||
constexpr format_spec_factory<type_spec> type;
|
constexpr format_spec_factory<type_spec> type;
|
||||||
|
|
||||||
template <typename Range>
|
/**
|
||||||
inline void vformat_range(Range out, string_view format_str, format_args args) {
|
\rst
|
||||||
vformat_to<arg_formatter<Range>>(out, format_str, args);
|
Converts *value* to ``std::string`` using the default format for type *T*.
|
||||||
|
|
||||||
|
**Example**::
|
||||||
|
|
||||||
|
#include "fmt/string.h"
|
||||||
|
|
||||||
|
std::string answer = fmt::to_string(42);
|
||||||
|
\endrst
|
||||||
|
*/
|
||||||
|
template <typename T>
|
||||||
|
std::string to_string(const T &value) {
|
||||||
|
std::string str;
|
||||||
|
internal::container_buffer<std::string> buf(str);
|
||||||
|
writer(buf).write(value);
|
||||||
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Range, typename... Args>
|
template <typename Char>
|
||||||
inline void format_range(Range out, string_view format_str,
|
std::basic_string<Char> to_string(const basic_memory_buffer<Char> &buffer) {
|
||||||
const Args & ... args) {
|
return std::basic_string<Char>(buffer.data(), buffer.size());
|
||||||
vformat_range(out, format_str, make_args(args...));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void vformat_to(buffer &buf, string_view format_str, format_args args) {
|
inline void vformat_to(buffer &buf, string_view format_str, format_args args) {
|
||||||
using range = internal::dynamic_range<buffer>;
|
using range = internal::dynamic_range<buffer>;
|
||||||
vformat_to<arg_formatter<range>>(buf, format_str, args);
|
do_vformat_to<arg_formatter<range>>(buf, format_str, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void vformat_to(wbuffer &buf, wstring_view format_str,
|
inline void vformat_to(wbuffer &buf, wstring_view format_str,
|
||||||
wformat_args args) {
|
wformat_args args) {
|
||||||
using range = internal::dynamic_range<wbuffer>;
|
using range = internal::dynamic_range<wbuffer>;
|
||||||
vformat_to<arg_formatter<range>>(buf, format_str, args);
|
do_vformat_to<arg_formatter<range>>(buf, format_str, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Container>
|
||||||
|
void vformat_to(std::back_insert_iterator<Container> out,
|
||||||
|
string_view format_str, format_args args) {
|
||||||
|
using iterator = std::back_insert_iterator<Container>;
|
||||||
|
struct container_extractor : iterator {
|
||||||
|
container_extractor(iterator it) : iterator(it) {}
|
||||||
|
using iterator::container;
|
||||||
|
} extractor(out);
|
||||||
|
internal::container_buffer<Container> buf(*extractor.container);
|
||||||
|
vformat_to(buf, format_str, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Container, typename... Args>
|
||||||
|
inline void format_to(std::back_insert_iterator<Container> out,
|
||||||
|
string_view format_str,
|
||||||
|
const Args & ... args) {
|
||||||
|
vformat_to(out, format_str, make_args(args...));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline std::string vformat(string_view format_str, format_args args) {
|
inline std::string vformat(string_view format_str, format_args args) {
|
||||||
memory_buffer buffer;
|
memory_buffer buffer;
|
||||||
vformat_to(buffer, format_str, args);
|
vformat_to(buffer, format_str, args);
|
||||||
return to_string(buffer);
|
return fmt::to_string(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline std::wstring vformat(wstring_view format_str, wformat_args args) {
|
inline std::wstring vformat(wstring_view format_str, wformat_args args) {
|
||||||
|
@ -232,8 +232,8 @@ class printf_arg_formatter : public internal::arg_formatter_base<Range> {
|
|||||||
specifier information for standard argument types.
|
specifier information for standard argument types.
|
||||||
\endrst
|
\endrst
|
||||||
*/
|
*/
|
||||||
printf_arg_formatter(basic_buffer<char_type> &buffer, format_specs &spec,
|
printf_arg_formatter(internal::basic_buffer<char_type> &buffer,
|
||||||
basic_printf_context<Range> &ctx)
|
format_specs &spec, basic_printf_context<Range> &ctx)
|
||||||
: base(buffer, spec), context_(ctx) {}
|
: base(buffer, spec), context_(ctx) {}
|
||||||
|
|
||||||
using base::operator();
|
using base::operator();
|
||||||
@ -522,7 +522,7 @@ void basic_printf_context<Range, AF>::format() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename Char, typename Context>
|
template <typename Char, typename Context>
|
||||||
void printf(basic_buffer<Char> &buf, basic_string_view<Char> format,
|
void printf(internal::basic_buffer<Char> &buf, basic_string_view<Char> format,
|
||||||
basic_format_args<Context> args) {
|
basic_format_args<Context> args) {
|
||||||
Context(buf, format, args).format();
|
Context(buf, format, args).format();
|
||||||
}
|
}
|
||||||
|
@ -1,92 +0,0 @@
|
|||||||
// Formatting library for C++ - string utilities
|
|
||||||
//
|
|
||||||
// Copyright (c) 2012 - 2016, Victor Zverovich
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// For the license information refer to format.h.
|
|
||||||
|
|
||||||
#ifndef FMT_STRING_H_
|
|
||||||
#define FMT_STRING_H_
|
|
||||||
|
|
||||||
#include "fmt/format.h"
|
|
||||||
|
|
||||||
namespace fmt {
|
|
||||||
|
|
||||||
/**
|
|
||||||
\rst
|
|
||||||
This class template represents a character buffer backed by std::string.
|
|
||||||
|
|
||||||
You can use one of the following typedefs for common character types
|
|
||||||
and the standard allocator:
|
|
||||||
|
|
||||||
+----------------+------------------------------+
|
|
||||||
| Type | Definition |
|
|
||||||
+================+==============================+
|
|
||||||
| string_buffer | basic_string_buffer<char> |
|
|
||||||
+----------------+------------------------------+
|
|
||||||
| wstring_buffer | basic_string_buffer<wchar_t> |
|
|
||||||
+----------------+------------------------------+
|
|
||||||
|
|
||||||
**Example**::
|
|
||||||
|
|
||||||
string_buffer out;
|
|
||||||
format_to(out, "The answer is {}", 42);
|
|
||||||
|
|
||||||
This will write the following output to the ``out`` object:
|
|
||||||
|
|
||||||
.. code-block:: none
|
|
||||||
|
|
||||||
The answer is 42
|
|
||||||
|
|
||||||
The output can be moved to an ``std::string`` with ``out.move_to()``.
|
|
||||||
\endrst
|
|
||||||
*/template <typename Char>
|
|
||||||
class basic_string_buffer : public basic_buffer<Char> {
|
|
||||||
private:
|
|
||||||
std::basic_string<Char> str_;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual void grow(std::size_t capacity) {
|
|
||||||
str_.resize(capacity);
|
|
||||||
this->set(&str_[0], capacity);
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
\rst
|
|
||||||
Moves the buffer content to *str* clearing the buffer.
|
|
||||||
\endrst
|
|
||||||
*/
|
|
||||||
void move_to(std::basic_string<Char> &str) {
|
|
||||||
str_.resize(this->size());
|
|
||||||
str.swap(str_);
|
|
||||||
this->resize(0);
|
|
||||||
this->set(0, 0);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef basic_string_buffer<char> string_buffer;
|
|
||||||
typedef basic_string_buffer<wchar_t> wstring_buffer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
\rst
|
|
||||||
Converts *value* to ``std::string`` using the default format for type *T*.
|
|
||||||
|
|
||||||
**Example**::
|
|
||||||
|
|
||||||
#include "fmt/string.h"
|
|
||||||
|
|
||||||
std::string answer = fmt::to_string(42);
|
|
||||||
\endrst
|
|
||||||
*/
|
|
||||||
template <typename T>
|
|
||||||
std::string to_string(const T &value) {
|
|
||||||
string_buffer buf;
|
|
||||||
writer(buf).write(value);
|
|
||||||
std::string str;
|
|
||||||
buf.move_to(str);
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // FMT_STRING_H_
|
|
@ -85,7 +85,6 @@ add_fmt_test(format-test)
|
|||||||
add_fmt_test(format-impl-test)
|
add_fmt_test(format-impl-test)
|
||||||
add_fmt_test(ostream-test)
|
add_fmt_test(ostream-test)
|
||||||
add_fmt_test(printf-test)
|
add_fmt_test(printf-test)
|
||||||
add_fmt_test(string-test)
|
|
||||||
add_fmt_test(time-test)
|
add_fmt_test(time-test)
|
||||||
add_fmt_test(util-test mock-allocator.h)
|
add_fmt_test(util-test mock-allocator.h)
|
||||||
add_fmt_test(custom-formatter-test)
|
add_fmt_test(custom-formatter-test)
|
||||||
|
@ -36,7 +36,7 @@ class CustomArgFormatter :
|
|||||||
std::string custom_vformat(fmt::string_view format_str, fmt::format_args args) {
|
std::string custom_vformat(fmt::string_view format_str, fmt::format_args args) {
|
||||||
fmt::memory_buffer buffer;
|
fmt::memory_buffer buffer;
|
||||||
// Pass custom argument formatter as a template arg to vwrite.
|
// Pass custom argument formatter as a template arg to vwrite.
|
||||||
fmt::vformat_to<CustomArgFormatter>(buffer, format_str, args);
|
fmt::do_vformat_to<CustomArgFormatter>(buffer, format_str, args);
|
||||||
return std::string(buffer.data(), buffer.size());
|
return std::string(buffer.data(), buffer.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,7 +88,7 @@ void std_format(long double value, std::wstring &result) {
|
|||||||
template <typename Char, typename T>
|
template <typename Char, typename T>
|
||||||
::testing::AssertionResult check_write(const T &value, const char *type) {
|
::testing::AssertionResult check_write(const T &value, const char *type) {
|
||||||
fmt::basic_memory_buffer<Char> buffer;
|
fmt::basic_memory_buffer<Char> buffer;
|
||||||
using range = fmt::internal::dynamic_range<fmt::basic_buffer<Char>>;
|
using range = fmt::internal::dynamic_range<fmt::internal::basic_buffer<Char>>;
|
||||||
fmt::basic_writer<range> writer(buffer);
|
fmt::basic_writer<range> writer(buffer);
|
||||||
writer.write(value);
|
writer.write(value);
|
||||||
std::basic_string<Char> actual = to_string(buffer);
|
std::basic_string<Char> actual = to_string(buffer);
|
||||||
@ -1224,7 +1224,7 @@ struct formatter<Date> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto format(const Date &d, context &ctx) {
|
auto format(const Date &d, context &ctx) {
|
||||||
format_range(ctx.range(), "{}-{}-{}", d.year(), d.month(), d.day());
|
format_to(ctx.begin(), "{}-{}-{}", d.year(), d.month(), d.day());
|
||||||
return ctx.begin();
|
return ctx.begin();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -1509,7 +1509,7 @@ class mock_arg_formatter :
|
|||||||
|
|
||||||
void custom_vformat(fmt::string_view format_str, fmt::format_args args) {
|
void custom_vformat(fmt::string_view format_str, fmt::format_args args) {
|
||||||
fmt::memory_buffer buffer;
|
fmt::memory_buffer buffer;
|
||||||
fmt::vformat_to<mock_arg_formatter>(buffer, format_str, args);
|
fmt::do_vformat_to<mock_arg_formatter>(buffer, format_str, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
@ -1907,3 +1907,18 @@ TEST(FormatTest, FormatStringErrors) {
|
|||||||
"cannot switch from automatic to manual argument indexing",
|
"cannot switch from automatic to manual argument indexing",
|
||||||
int, int);
|
int, int);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(FormatTest, OutputIterator) {
|
||||||
|
|
||||||
|
std::string s;
|
||||||
|
fmt::format_to(std::back_inserter(s), "{}", 42);
|
||||||
|
std::vector<char> v;
|
||||||
|
fmt::format_to(std::back_inserter(v), "{}", 42);
|
||||||
|
|
||||||
|
EXPECT_EQ("42", s);
|
||||||
|
EXPECT_EQ("42", std::string(v.begin(), v.end()));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(StringTest, ToString) {
|
||||||
|
EXPECT_EQ("42", fmt::to_string(42));
|
||||||
|
}
|
||||||
|
@ -136,12 +136,12 @@ TEST(OStreamTest, WriteToOStreamMaxSize) {
|
|||||||
if (max_size <= fmt::internal::to_unsigned(max_streamsize))
|
if (max_size <= fmt::internal::to_unsigned(max_streamsize))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
struct TestBuffer : fmt::basic_buffer<char> {
|
struct test_buffer : fmt::buffer {
|
||||||
explicit TestBuffer(std::size_t size) { resize(size); }
|
explicit test_buffer(std::size_t size) { resize(size); }
|
||||||
void grow(std::size_t) {}
|
void grow(std::size_t) {}
|
||||||
} buffer(max_size);
|
} buffer(max_size);
|
||||||
|
|
||||||
struct MockStreamBuf : std::streambuf {
|
struct mock_streambuf : std::streambuf {
|
||||||
MOCK_METHOD2(xsputn, std::streamsize (const void *s, std::streamsize n));
|
MOCK_METHOD2(xsputn, std::streamsize (const void *s, std::streamsize n));
|
||||||
std::streamsize xsputn(const char *s, std::streamsize n) {
|
std::streamsize xsputn(const char *s, std::streamsize n) {
|
||||||
const void *v = s;
|
const void *v = s;
|
||||||
@ -149,16 +149,16 @@ TEST(OStreamTest, WriteToOStreamMaxSize) {
|
|||||||
}
|
}
|
||||||
} streambuf;
|
} streambuf;
|
||||||
|
|
||||||
struct TestOStream : std::ostream {
|
struct test_ostream : std::ostream {
|
||||||
explicit TestOStream(MockStreamBuf &buffer) : std::ostream(&buffer) {}
|
explicit test_ostream(mock_streambuf &buffer) : std::ostream(&buffer) {}
|
||||||
} os(streambuf);
|
} os(streambuf);
|
||||||
|
|
||||||
testing::InSequence sequence;
|
testing::InSequence sequence;
|
||||||
const char *data = 0;
|
const char *data = 0;
|
||||||
std::size_t size = max_size;
|
std::size_t size = max_size;
|
||||||
do {
|
do {
|
||||||
typedef std::make_unsigned<std::streamsize>::type UStreamSize;
|
typedef std::make_unsigned<std::streamsize>::type ustreamsize;
|
||||||
UStreamSize n = std::min<UStreamSize>(
|
ustreamsize n = std::min<ustreamsize>(
|
||||||
size, fmt::internal::to_unsigned(max_streamsize));
|
size, fmt::internal::to_unsigned(max_streamsize));
|
||||||
EXPECT_CALL(streambuf, xsputn(data, static_cast<std::streamsize>(n)))
|
EXPECT_CALL(streambuf, xsputn(data, static_cast<std::streamsize>(n)))
|
||||||
.WillOnce(testing::Return(max_streamsize));
|
.WillOnce(testing::Return(max_streamsize));
|
||||||
|
@ -1,71 +0,0 @@
|
|||||||
/*
|
|
||||||
Tests of string utilities
|
|
||||||
|
|
||||||
Copyright (c) 2012 - 2016, Victor Zverovich
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
For the license information refer to format.h.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "fmt/string.h"
|
|
||||||
#include "gtest/gtest.h"
|
|
||||||
|
|
||||||
using fmt::string_buffer;
|
|
||||||
|
|
||||||
TEST(StringBufferTest, Empty) {
|
|
||||||
string_buffer buffer;
|
|
||||||
EXPECT_EQ(0u, buffer.size());
|
|
||||||
EXPECT_EQ(0u, buffer.capacity());
|
|
||||||
std::string data;
|
|
||||||
// std::string may have initial capacity.
|
|
||||||
std::size_t capacity = data.capacity();
|
|
||||||
buffer.move_to(data);
|
|
||||||
EXPECT_EQ("", data);
|
|
||||||
EXPECT_EQ(capacity, data.capacity());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(StringBufferTest, Reserve) {
|
|
||||||
string_buffer buffer;
|
|
||||||
std::size_t capacity = std::string().capacity() + 10;
|
|
||||||
buffer.reserve(capacity);
|
|
||||||
EXPECT_EQ(0u, buffer.size());
|
|
||||||
EXPECT_EQ(capacity, buffer.capacity());
|
|
||||||
std::string data;
|
|
||||||
buffer.move_to(data);
|
|
||||||
EXPECT_EQ("", data);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(StringBufferTest, Resize) {
|
|
||||||
string_buffer buffer;
|
|
||||||
std::size_t size = std::string().capacity() + 10;
|
|
||||||
buffer.resize(size);
|
|
||||||
EXPECT_EQ(size, buffer.size());
|
|
||||||
EXPECT_EQ(size, buffer.capacity());
|
|
||||||
std::string data;
|
|
||||||
buffer.move_to(data);
|
|
||||||
EXPECT_EQ(size, data.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(StringBufferTest, MoveTo) {
|
|
||||||
string_buffer buffer;
|
|
||||||
std::size_t size = std::string().capacity() + 10;
|
|
||||||
buffer.resize(size);
|
|
||||||
const char *p = &buffer[0];
|
|
||||||
std::string data;
|
|
||||||
buffer.move_to(data);
|
|
||||||
EXPECT_EQ(p, &data[0]);
|
|
||||||
EXPECT_EQ(0u, buffer.size());
|
|
||||||
EXPECT_EQ(0u, buffer.capacity());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(StringBufferTest, WString) {
|
|
||||||
fmt::wstring_buffer out;
|
|
||||||
out.push_back(L'x');
|
|
||||||
std::wstring s;
|
|
||||||
out.move_to(s);
|
|
||||||
EXPECT_EQ(L"x", s);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(StringTest, ToString) {
|
|
||||||
EXPECT_EQ("42", fmt::to_string(42));
|
|
||||||
}
|
|
@ -54,7 +54,7 @@
|
|||||||
#undef max
|
#undef max
|
||||||
|
|
||||||
using fmt::basic_arg;
|
using fmt::basic_arg;
|
||||||
using fmt::basic_buffer;
|
using fmt::internal::basic_buffer;
|
||||||
using fmt::basic_memory_buffer;
|
using fmt::basic_memory_buffer;
|
||||||
using fmt::string_view;
|
using fmt::string_view;
|
||||||
using fmt::internal::value;
|
using fmt::internal::value;
|
||||||
@ -192,7 +192,7 @@ TEST(BufferTest, Access) {
|
|||||||
EXPECT_EQ(11, buffer[0]);
|
EXPECT_EQ(11, buffer[0]);
|
||||||
buffer[3] = 42;
|
buffer[3] = 42;
|
||||||
EXPECT_EQ(42, *(&buffer[0] + 3));
|
EXPECT_EQ(42, *(&buffer[0] + 3));
|
||||||
const fmt::basic_buffer<char> &const_buffer = buffer;
|
const basic_buffer<char> &const_buffer = buffer;
|
||||||
EXPECT_EQ(42, const_buffer[3]);
|
EXPECT_EQ(42, const_buffer[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user