locale-aware format_spec

master
Daniel Kolesa 2017-02-26 00:57:39 +01:00
parent 98fb0e3e2e
commit db991ca03d
1 changed files with 35 additions and 11 deletions

View File

@ -182,12 +182,24 @@ namespace detail {
} }
struct format_spec { struct format_spec {
format_spec(): p_fmt() {} format_spec(string_range fmt = nullptr):
format_spec(string_range fmt): p_fmt(fmt) {} p_fmt(fmt), p_loc()
{}
format_spec(string_range fmt, std::locale const &loc):
p_fmt(fmt), p_loc(loc)
{}
format_spec(std::locale const &loc):
p_fmt(), p_loc(loc)
{}
format_spec(char spec, int flags = 0): format_spec(char spec, int flags = 0):
p_flags(flags), p_flags(flags), p_spec(spec), p_loc()
p_spec(spec) {}
format_spec(char spec, std::locale const &loc, int flags = 0):
p_flags(flags), p_spec(spec), p_loc(loc)
{} {}
template<typename R> template<typename R>
@ -214,6 +226,16 @@ struct format_spec {
return p_fmt; return p_fmt;
} }
std::locale imbue(std::locale const &loc) {
std::locale ret{p_loc};
p_loc = loc;
return ret;
}
std::locale getloc() const {
return p_loc;
}
int width() const { return p_width; } int width() const { return p_width; }
int precision() const { return p_precision; } int precision() const { return p_precision; }
@ -611,6 +633,7 @@ private:
/* null streambuf because it's only used to read flags etc */ /* null streambuf because it's only used to read flags etc */
std::ios st{nullptr}; std::ios st{nullptr};
st.imbue(p_loc);
st.width(width()); st.width(width());
st.precision(has_precision() ? precision() : 6); st.precision(has_precision() ? precision() : 6);
@ -682,8 +705,8 @@ private:
throw format_error{"tuples need the '%s' spec"}; throw format_error{"tuples need the '%s' spec"};
} }
writer.put('{'); writer.put('{');
write_range_val(writer, [&writer, escape](auto const &rval) { write_range_val(writer, [&writer, escape, this](auto const &rval) {
format_spec sp{'s', escape ? FMT_FLAG_AT : 0}; format_spec sp{'s', p_loc, escape ? FMT_FLAG_AT : 0};
sp.write_arg(writer, 0, rval); sp.write_arg(writer, 0, rval);
}, ", ", val); }, ", ", val);
writer.put('}'); writer.put('}');
@ -759,10 +782,10 @@ private:
) const { ) const {
if constexpr(detail::is_tuple_like<T>) { if constexpr(detail::is_tuple_like<T>) {
if (expandval) { if (expandval) {
std::apply([&writer, escape, &fmt]( std::apply([&writer, escape, &fmt, this](
auto const &...args auto const &...args
) mutable { ) mutable {
format_spec sp{fmt}; format_spec sp{fmt, p_loc};
if (escape) { if (escape) {
sp.p_gflags |= FMT_FLAG_AT; sp.p_gflags |= FMT_FLAG_AT;
} }
@ -771,7 +794,7 @@ private:
return; return;
} }
} }
format_spec sp{fmt}; format_spec sp{fmt, p_loc};
if (escape) { if (escape) {
sp.p_gflags |= FMT_FLAG_AT; sp.p_gflags |= FMT_FLAG_AT;
} }
@ -828,7 +851,7 @@ private:
void write_tuple_val( void write_tuple_val(
R &writer, bool escape, string_range sep, T const &tup R &writer, bool escape, string_range sep, T const &tup
) const { ) const {
format_spec sp{'s', escape ? FMT_FLAG_AT : 0}; format_spec sp{'s', p_loc, escape ? FMT_FLAG_AT : 0};
sp.write_arg(writer, 0, std::get<I>(tup)); sp.write_arg(writer, 0, std::get<I>(tup));
if constexpr(I < (N - 1)) { if constexpr(I < (N - 1)) {
range_put_all(writer, sep); range_put_all(writer, sep);
@ -866,7 +889,7 @@ private:
if (!argpos) { if (!argpos) {
argpos = argidx++; argpos = argidx++;
} }
format_spec nspec(nested()); format_spec nspec(nested(), p_loc);
nspec.p_gflags |= (p_flags & FMT_FLAG_AT); nspec.p_gflags |= (p_flags & FMT_FLAG_AT);
if (is_tuple()) { if (is_tuple()) {
nspec.write_tuple(writer, argpos - 1, args...); nspec.write_tuple(writer, argpos - 1, args...);
@ -941,6 +964,7 @@ private:
}; };
string_range p_fmt; string_range p_fmt;
std::locale p_loc;
char p_buf[32]; char p_buf[32];
}; };