mirror of
https://github.com/fmtlib/fmt.git
synced 2024-09-04 05:59:13 +00:00
Move is_char specializations to xchar.h
This commit is contained in:
parent
16c3514d01
commit
d551b88a6d
@ -724,6 +724,23 @@ inline auto get_container(std::back_insert_iterator<Container> it)
|
||||
return *accessor(it).container;
|
||||
}
|
||||
|
||||
template <typename Char, typename InputIt, typename OutputIt>
|
||||
FMT_CONSTEXPR auto copy_str(InputIt begin, InputIt end, OutputIt out)
|
||||
-> OutputIt {
|
||||
while (begin != end) *out++ = static_cast<Char>(*begin++);
|
||||
return out;
|
||||
}
|
||||
|
||||
template <typename Char, FMT_ENABLE_IF(std::is_same<Char, char>::value)>
|
||||
FMT_CONSTEXPR auto copy_str(const Char* begin, const Char* end, Char* out)
|
||||
-> Char* {
|
||||
if (is_constant_evaluated())
|
||||
return copy_str<Char, const Char*, Char*>(begin, end, out);
|
||||
auto size = to_unsigned(end - begin);
|
||||
memcpy(out, begin, size);
|
||||
return out + size;
|
||||
}
|
||||
|
||||
/**
|
||||
\rst
|
||||
A contiguous memory buffer with an optional growing ability. It is an internal
|
||||
@ -848,7 +865,12 @@ class iterator_buffer final : public Traits, public buffer<T> {
|
||||
void grow(size_t) final FMT_OVERRIDE {
|
||||
if (this->size() == buffer_size) flush();
|
||||
}
|
||||
void flush();
|
||||
|
||||
void flush() {
|
||||
auto size = this->size();
|
||||
this->clear();
|
||||
out_ = copy_str<T>(data_, data_ + this->limit(size), out_);
|
||||
}
|
||||
|
||||
public:
|
||||
explicit iterator_buffer(OutputIt out, size_t n = buffer_size)
|
||||
@ -1463,6 +1485,12 @@ FMT_CONSTEXPR FMT_INLINE auto visit_format_arg(
|
||||
|
||||
FMT_BEGIN_DETAIL_NAMESPACE
|
||||
|
||||
template <typename Char, typename InputIt>
|
||||
auto copy_str(InputIt begin, InputIt end, appender out) -> appender {
|
||||
get_container(out).append(begin, end);
|
||||
return out;
|
||||
}
|
||||
|
||||
#if FMT_GCC_VERSION && FMT_GCC_VERSION < 500
|
||||
// A workaround for gcc 4.8 to make void_t work in a SFINAE context.
|
||||
template <typename... Ts> struct void_t_impl { using type = void; };
|
||||
|
@ -432,46 +432,6 @@ using char8_type = char8_t;
|
||||
enum char8_type : unsigned char {};
|
||||
#endif
|
||||
|
||||
template <typename InputIt, typename OutChar>
|
||||
using needs_conversion = bool_constant<
|
||||
std::is_same<typename std::iterator_traits<InputIt>::value_type,
|
||||
char>::value &&
|
||||
std::is_same<OutChar, char8_type>::value>;
|
||||
|
||||
template <typename OutChar, typename InputIt, typename OutputIt,
|
||||
FMT_ENABLE_IF(!needs_conversion<InputIt, OutChar>::value)>
|
||||
FMT_CONSTEXPR auto copy_str(InputIt begin, InputIt end, OutputIt out)
|
||||
-> OutputIt {
|
||||
while (begin != end) *out++ = *begin++;
|
||||
return out;
|
||||
}
|
||||
|
||||
template <typename OutChar, typename InputIt,
|
||||
FMT_ENABLE_IF(!needs_conversion<InputIt, OutChar>::value)>
|
||||
FMT_CONSTEXPR20 auto copy_str(InputIt begin, InputIt end, OutChar* out)
|
||||
-> OutChar* {
|
||||
if (is_constant_evaluated()) {
|
||||
return copy_str<OutChar, InputIt, OutChar*>(begin, end, out);
|
||||
}
|
||||
auto size = to_unsigned(end - begin);
|
||||
std::uninitialized_copy(begin, end, make_checked(out, size));
|
||||
return out + size;
|
||||
}
|
||||
|
||||
template <typename OutChar, typename InputIt, typename OutputIt,
|
||||
FMT_ENABLE_IF(needs_conversion<InputIt, OutChar>::value)>
|
||||
auto copy_str(InputIt begin, InputIt end, OutputIt out) -> OutputIt {
|
||||
while (begin != end) *out++ = static_cast<char8_type>(*begin++);
|
||||
return out;
|
||||
}
|
||||
|
||||
template <typename OutChar, typename InputIt,
|
||||
FMT_ENABLE_IF(!needs_conversion<InputIt, OutChar>::value)>
|
||||
auto copy_str(InputIt begin, InputIt end, appender out) -> appender {
|
||||
get_container(out).append(begin, end);
|
||||
return out;
|
||||
}
|
||||
|
||||
template <typename OutChar, typename InputIt, typename OutputIt>
|
||||
FMT_CONSTEXPR FMT_NOINLINE auto copy_str_noinline(InputIt begin, InputIt end,
|
||||
OutputIt out) -> OutputIt {
|
||||
@ -633,13 +593,6 @@ void buffer<T>::append(const U* begin, const U* end) {
|
||||
}
|
||||
}
|
||||
|
||||
template <typename OutputIt, typename T, typename Traits>
|
||||
void iterator_buffer<OutputIt, T, Traits>::flush() {
|
||||
auto size = this->size();
|
||||
this->clear();
|
||||
out_ = copy_str<T>(data_, data_ + this->limit(size), out_);
|
||||
}
|
||||
|
||||
template <typename T, typename Enable = void>
|
||||
struct is_locale : std::false_type {};
|
||||
template <typename T>
|
||||
@ -648,11 +601,6 @@ struct is_locale<T, void_t<decltype(T::classic())>> : std::true_type {};
|
||||
|
||||
FMT_MODULE_EXPORT_BEGIN
|
||||
|
||||
template <> struct is_char<wchar_t> : std::true_type {};
|
||||
template <> struct is_char<detail::char8_type> : std::true_type {};
|
||||
template <> struct is_char<char16_t> : std::true_type {};
|
||||
template <> struct is_char<char32_t> : std::true_type {};
|
||||
|
||||
// The number of characters to store in the basic_memory_buffer object itself
|
||||
// to avoid dynamic memory allocation.
|
||||
enum { inline_buffer_size = 500 };
|
||||
|
@ -35,6 +35,11 @@ template <typename... Args>
|
||||
using wformat_string = basic_format_string<wchar_t, type_identity_t<Args>...>;
|
||||
#endif
|
||||
|
||||
template <> struct is_char<wchar_t> : std::true_type {};
|
||||
template <> struct is_char<detail::char8_type> : std::true_type {};
|
||||
template <> struct is_char<char16_t> : std::true_type {};
|
||||
template <> struct is_char<char32_t> : std::true_type {};
|
||||
|
||||
template <typename... Args>
|
||||
constexpr format_arg_store<wformat_context, Args...> make_wformat_args(
|
||||
const Args&... args) {
|
||||
|
@ -14,8 +14,6 @@
|
||||
TEST(color_test, format) {
|
||||
EXPECT_EQ(fmt::format(fg(fmt::rgb(255, 20, 30)), "rgb(255,20,30)"),
|
||||
"\x1b[38;2;255;020;030mrgb(255,20,30)\x1b[0m");
|
||||
EXPECT_EQ(fmt::format(fg(fmt::rgb(255, 20, 30)), L"rgb(255,20,30) wide"),
|
||||
L"\x1b[38;2;255;020;030mrgb(255,20,30) wide\x1b[0m");
|
||||
EXPECT_EQ(fmt::format(fg(fmt::color::blue), "blue"),
|
||||
"\x1b[38;2;000;000;255mblue\x1b[0m");
|
||||
EXPECT_EQ(
|
||||
|
@ -29,6 +29,10 @@ using testing::_;
|
||||
using testing::Invoke;
|
||||
using testing::Return;
|
||||
|
||||
#ifdef FMT_FORMAT_H_
|
||||
# error core-test includes format.h
|
||||
#endif
|
||||
|
||||
TEST(string_view_test, value_type) {
|
||||
static_assert(std::is_same<string_view::value_type, char>::value, "");
|
||||
}
|
||||
@ -90,34 +94,8 @@ template <typename Char>
|
||||
fmt::basic_string_view<Char> to_string_view(const test_string<Char>& s) {
|
||||
return {s.data(), s.length()};
|
||||
}
|
||||
|
||||
struct non_string {};
|
||||
} // namespace test_ns
|
||||
|
||||
template <typename T> class is_string_test : public testing::Test {};
|
||||
|
||||
using string_char_types = testing::Types<char, wchar_t, char16_t, char32_t>;
|
||||
TYPED_TEST_SUITE(is_string_test, string_char_types);
|
||||
|
||||
template <typename Char>
|
||||
struct derived_from_string_view : fmt::basic_string_view<Char> {};
|
||||
|
||||
TYPED_TEST(is_string_test, is_string) {
|
||||
EXPECT_TRUE(fmt::detail::is_string<TypeParam*>::value);
|
||||
EXPECT_TRUE(fmt::detail::is_string<const TypeParam*>::value);
|
||||
EXPECT_TRUE(fmt::detail::is_string<TypeParam[2]>::value);
|
||||
EXPECT_TRUE(fmt::detail::is_string<const TypeParam[2]>::value);
|
||||
EXPECT_TRUE(fmt::detail::is_string<std::basic_string<TypeParam>>::value);
|
||||
EXPECT_TRUE(fmt::detail::is_string<fmt::basic_string_view<TypeParam>>::value);
|
||||
EXPECT_TRUE(
|
||||
fmt::detail::is_string<derived_from_string_view<TypeParam>>::value);
|
||||
using fmt_string_view = fmt::detail::std_string_view<TypeParam>;
|
||||
EXPECT_TRUE(std::is_empty<fmt_string_view>::value !=
|
||||
fmt::detail::is_string<fmt_string_view>::value);
|
||||
EXPECT_TRUE(fmt::detail::is_string<test_ns::test_string<TypeParam>>::value);
|
||||
EXPECT_FALSE(fmt::detail::is_string<test_ns::non_string>::value);
|
||||
}
|
||||
|
||||
TEST(core_test, is_output_iterator) {
|
||||
EXPECT_TRUE((fmt::detail::is_output_iterator<char*, char>::value));
|
||||
EXPECT_FALSE((fmt::detail::is_output_iterator<const char*, char>::value));
|
||||
@ -428,6 +406,10 @@ TYPED_TEST(numeric_arg_test, make_and_visit) {
|
||||
CHECK_ARG_SIMPLE(std::numeric_limits<TypeParam>::max());
|
||||
}
|
||||
|
||||
namespace fmt {
|
||||
template <> struct is_char<wchar_t> : std::true_type {};
|
||||
} // namespace fmt
|
||||
|
||||
TEST(arg_test, char_arg) {
|
||||
CHECK_ARG(char, 'a', 'a');
|
||||
CHECK_ARG(wchar_t, L'a', 'a');
|
||||
|
@ -96,9 +96,6 @@ TEST(ostream_test, print) {
|
||||
std::ostringstream os;
|
||||
fmt::print(os, "Don't {}!", "panic");
|
||||
EXPECT_EQ("Don't panic!", os.str());
|
||||
std::wostringstream wos;
|
||||
fmt::print(wos, L"Don't {}!", L"panic");
|
||||
EXPECT_EQ(L"Don't panic!", wos.str());
|
||||
}
|
||||
|
||||
TEST(ostream_test, write_to_ostream) {
|
||||
|
@ -14,7 +14,6 @@ void throw_assertion_failure(const char* message);
|
||||
#define FMT_ASSERT(condition, message) \
|
||||
if (!(condition)) throw_assertion_failure(message);
|
||||
|
||||
#include "gtest-extra.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
class assertion_failure : public std::logic_error {
|
||||
|
@ -10,12 +10,57 @@
|
||||
#include <complex>
|
||||
|
||||
#include "fmt/chrono.h"
|
||||
#include "fmt/color.h"
|
||||
#include "fmt/ostream.h"
|
||||
#include "fmt/ranges.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using fmt::detail::max_value;
|
||||
|
||||
namespace test_ns {
|
||||
template <typename Char> class test_string {
|
||||
private:
|
||||
std::basic_string<Char> s_;
|
||||
|
||||
public:
|
||||
test_string(const Char* s) : s_(s) {}
|
||||
const Char* data() const { return s_.data(); }
|
||||
size_t length() const { return s_.size(); }
|
||||
operator const Char*() const { return s_.c_str(); }
|
||||
};
|
||||
|
||||
template <typename Char>
|
||||
fmt::basic_string_view<Char> to_string_view(const test_string<Char>& s) {
|
||||
return {s.data(), s.length()};
|
||||
}
|
||||
|
||||
struct non_string {};
|
||||
} // namespace test_ns
|
||||
|
||||
template <typename T> class is_string_test : public testing::Test {};
|
||||
|
||||
using string_char_types = testing::Types<char, wchar_t, char16_t, char32_t>;
|
||||
TYPED_TEST_SUITE(is_string_test, string_char_types);
|
||||
|
||||
template <typename Char>
|
||||
struct derived_from_string_view : fmt::basic_string_view<Char> {};
|
||||
|
||||
TYPED_TEST(is_string_test, is_string) {
|
||||
EXPECT_TRUE(fmt::detail::is_string<TypeParam*>::value);
|
||||
EXPECT_TRUE(fmt::detail::is_string<const TypeParam*>::value);
|
||||
EXPECT_TRUE(fmt::detail::is_string<TypeParam[2]>::value);
|
||||
EXPECT_TRUE(fmt::detail::is_string<const TypeParam[2]>::value);
|
||||
EXPECT_TRUE(fmt::detail::is_string<std::basic_string<TypeParam>>::value);
|
||||
EXPECT_TRUE(fmt::detail::is_string<fmt::basic_string_view<TypeParam>>::value);
|
||||
EXPECT_TRUE(
|
||||
fmt::detail::is_string<derived_from_string_view<TypeParam>>::value);
|
||||
using fmt_string_view = fmt::detail::std_string_view<TypeParam>;
|
||||
EXPECT_TRUE(std::is_empty<fmt_string_view>::value !=
|
||||
fmt::detail::is_string<fmt_string_view>::value);
|
||||
EXPECT_TRUE(fmt::detail::is_string<test_ns::test_string<TypeParam>>::value);
|
||||
EXPECT_FALSE(fmt::detail::is_string<test_ns::non_string>::value);
|
||||
}
|
||||
|
||||
// std::is_constructible is broken in MSVC until version 2015.
|
||||
#if !FMT_MSC_VER || FMT_MSC_VER >= 1900
|
||||
struct explicitly_convertible_to_wstring_view {
|
||||
@ -214,6 +259,17 @@ TEST(xchar_test, chrono) {
|
||||
EXPECT_EQ(L"42s", fmt::format(L"{}", std::chrono::seconds(42)));
|
||||
}
|
||||
|
||||
TEST(xchar_test, color) {
|
||||
EXPECT_EQ(fmt::format(fg(fmt::rgb(255, 20, 30)), L"rgb(255,20,30) wide"),
|
||||
L"\x1b[38;2;255;020;030mrgb(255,20,30) wide\x1b[0m");
|
||||
}
|
||||
|
||||
TEST(xchar_test, ostream) {
|
||||
std::wostringstream wos;
|
||||
fmt::print(wos, L"Don't {}!", L"panic");
|
||||
EXPECT_EQ(L"Don't panic!", wos.str());
|
||||
}
|
||||
|
||||
TEST(xchar_test, to_wstring) { EXPECT_EQ(L"42", fmt::to_wstring(42)); }
|
||||
|
||||
#ifndef FMT_STATIC_THOUSANDS_SEPARATOR
|
||||
|
Loading…
Reference in New Issue
Block a user