implement utf-32 string printing in format

master
Daniel Kolesa 2018-01-01 20:59:39 +01:00
parent c35f7377bf
commit b75f5f4881
2 changed files with 59 additions and 31 deletions

View File

@ -980,36 +980,6 @@ private:
for (int w = p_width - int(n); --w >= 0; writer.put(c));
}
/* string base writer */
template<typename R>
void write_str(R &writer, bool escape, string_range val) const {
std::size_t n = val.size();
if (has_precision()) {
n = std::min(n, std::size_t(precision()));
}
write_spaces(writer, n, true);
if (escape) {
writer.put('"');
for (std::size_t i = 0; i < n; ++i) {
if (val.empty()) {
break;
}
char c = val.front();
char const *esc = detail::escape_fmt_char(c, '"');
if (esc) {
range_put_all(writer, string_range{esc});
} else {
writer.put(c);
}
val.pop_front();
}
writer.put('"');
} else {
range_put_all(writer, val.slice(0, n));
}
write_spaces(writer, n, false);
}
template<typename R, typename C>
void write_char_raw(R &writer, C val) const {
if constexpr(sizeof(C) == sizeof(std::uint8_t)) {
@ -1030,6 +1000,46 @@ private:
}
}
/* string base writer */
template<typename C, typename R>
void write_str(R &writer, bool escape, basic_char_range<C const> val) const {
std::size_t n = val.size();
if (has_precision()) {
n = std::min(n, std::size_t(precision()));
}
write_spaces(writer, n, true);
if (escape) {
writer.put('"');
for (std::size_t i = 0; i < n; ++i) {
if (val.empty()) {
break;
}
C c = val.front();
if (c <= 0x7F) {
char const *esc = detail::escape_fmt_char(c, '"');
if (esc) {
range_put_all(writer, string_range{esc});
} else {
write_char_raw(writer, c);
}
} else {
write_char_raw(writer, c);
}
val.pop_front();
}
writer.put('"');
} else {
if constexpr(sizeof(C) == sizeof(std::uint8_t)) {
range_put_all(writer, val.slice(0, n));
} else {
for (std::size_t i = 0; i < n; ++i) {
write_char_raw(writer, val[i]);
}
}
}
write_spaces(writer, n, false);
}
/* char values */
template<typename R, typename C>
void write_char(R &writer, bool escape, C val) const {
@ -1252,7 +1262,15 @@ private:
if (spec() != 's') {
throw format_error{"strings need the '%s' spec"};
}
write_str(writer, escape, val);
write_str<char>(writer, escape, val);
return;
}
/* third best, we can convert to UTF-32 slice */
if constexpr(std::is_constructible_v<u32string_range, T const &>) {
if (spec() != 's') {
throw format_error{"strings need the '%s' spec"};
}
write_str<char32_t>(writer, escape, val);
return;
}
/* tuples */

View File

@ -797,6 +797,16 @@ namespace utf {
return utf::length(r, r);
}
/* @brief Get the number of Unicode code points in a UTF-32 string.
*
* As a UTF-32 string encodes entire code points, this function
* never fails, so there is no need for an error-handling version
* and this is equivalent to simply calling `r.size()`.
*/
inline std::size_t length(u32string_range r) noexcept {
return r.size();
}
namespace detail {
struct codepoint_range: input_range<codepoint_range> {
using range_category = forward_range_tag;