diff --git a/include/fmt/format.h b/include/fmt/format.h index e198233b..bd038494 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -45,6 +45,13 @@ #include "core.h" +#ifndef FMT_USE_TEXT +# define FMT_USE_TEXT 0 +#endif +#if FMT_USE_TEXT +# include +#endif + #ifdef __clang__ # define FMT_CLANG_VERSION (__clang_major__ * 100 + __clang_minor__) #else @@ -415,11 +422,6 @@ class output_range { sentinel end() const { return {}; } // Sentinel is not used yet. }; -template -inline size_t count_code_points(basic_string_view s) { - return s.size(); -} - // Counts the number of code points in a UTF-8 string. inline size_t count_code_points(basic_string_view s) { const char8_t* data = s.data(); @@ -912,6 +914,32 @@ inline It format_uint(It out, UInt value, int num_digits, bool upper = false) { return internal::copy_str(buffer, buffer + num_digits, out); } +template +inline size_t compute_width(basic_string_view s) { + return s.size(); +} + +inline size_t compute_width(string_view s) { +#if FMT_USE_TEXT + basic_memory_buffer code_points; + for (auto cp: boost::text::make_to_utf32_range(s)) code_points.push_back(cp); + size_t num_graphemes = 0; + for (auto g: boost::text::graphemes(code_points)) ++num_graphemes; + return num_graphemes; +#else + return s.size(); +#endif // FMT_USE_TEXT +} + +inline size_t compute_width(basic_string_view s) { +#if FMT_USE_TEXT + return compute_width(string_view( + reinterpret_cast(s.data(), s.size()))); +#else + return count_code_points(s); +#endif // FMT_USE_TEXT +} + #ifndef _WIN32 # define FMT_USE_WINDOWS_H 0 #elif !defined(FMT_USE_WINDOWS_H) @@ -1583,7 +1611,7 @@ template class basic_writer { size_t size() const { return size_; } size_t width() const { - return internal::count_code_points(basic_string_view(s, size_)); + return internal::compute_width(basic_string_view(s, size_)); } template void operator()(It&& it) const {