# HG changeset patch # User Markus Mützel # Date 1552165765 -3600 # Node ID 1c8b20731af48dcab0e12632c76429342a21e55f # Parent 94d490815aa83439cc59f67dcca1f736d63c622a Convert encoding just before writing to stream (bug #55452). * oct-stream.[cc,h] (printf): Don't convert format string separately. * oct-stream.cc (do_print_conv): Pass on encoding to octave::format. (do_printf): Convert strings to encoding. * utils.[cc,h] (format): Add overload with encoding specifier. diff -r 94d490815aa8 -r 1c8b20731af4 libinterp/corefcn/oct-stream.cc --- a/libinterp/corefcn/oct-stream.cc Tue Mar 05 17:56:57 2019 +0100 +++ b/libinterp/corefcn/oct-stream.cc Sat Mar 09 22:09:25 2019 +0100 @@ -5571,23 +5571,24 @@ template int - do_printf_conv (std::ostream& os, const char *fmt, int nsa, int sa_1, - int sa_2, T arg, const std::string& who) + do_printf_conv (std::ostream& os, const std::string& encoding, + const char *fmt, int nsa, int sa_1, int sa_2, T arg, + const std::string& who) { int retval = 0; switch (nsa) { case 2: - retval = format (os, fmt, sa_1, sa_2, arg); + retval = format (os, encoding, fmt, sa_1, sa_2, arg); break; case 1: - retval = format (os, fmt, sa_1, arg); + retval = format (os, encoding, fmt, sa_1, arg); break; case 0: - retval = format (os, fmt, arg); + retval = format (os, encoding, fmt, arg); break; default: @@ -5747,7 +5748,8 @@ tval = (lo_ieee_is_NA (dval) ? "NA" : "NaN"); } - retval += do_printf_conv (os, tfmt.c_str (), nsa, sa_1, sa_2, tval, who); + retval += do_printf_conv (os, encoding (), tfmt.c_str (), nsa, sa_1, + sa_2, tval, who); } else { @@ -5766,8 +5768,8 @@ // Insert "long" modifier. tfmt.replace (tfmt.rfind (type), 1, llmod + type); - retval += do_printf_conv (os, tfmt.c_str (), nsa, sa_1, sa_2, - tval.value (), who); + retval += do_printf_conv (os, encoding (), tfmt.c_str (), nsa, + sa_1, sa_2, tval.value (), who); } else { @@ -5775,7 +5777,7 @@ double dval = val.double_value (true); - retval += do_printf_conv (os, tfmt.c_str (), nsa, + retval += do_printf_conv (os, encoding (), tfmt.c_str (), nsa, sa_1, sa_2, dval, who); } break; @@ -5788,8 +5790,8 @@ // Insert "long" modifier. tfmt.replace (tfmt.rfind (type), 1, llmod + type); - retval += do_printf_conv (os, tfmt.c_str (), nsa, sa_1, sa_2, - tval.value (), who); + retval += do_printf_conv (os, encoding (), tfmt.c_str (), nsa, + sa_1, sa_2, tval.value (), who); } else { @@ -5797,7 +5799,7 @@ double dval = val.double_value (true); - retval += do_printf_conv (os, tfmt.c_str (), nsa, + retval += do_printf_conv (os, encoding (), tfmt.c_str (), nsa, sa_1, sa_2, dval, who); } break; @@ -5807,8 +5809,8 @@ { double dval = val.double_value (true); - retval += do_printf_conv (os, tfmt.c_str (), nsa, sa_1, sa_2, - dval, who); + retval += do_printf_conv (os, encoding (), tfmt.c_str (), nsa, + sa_1, sa_2, dval, who); } break; @@ -5878,12 +5880,18 @@ if (elt->type == '%') { - os << '%'; + if (encoding ().compare ("utf-8")) + os << string::u8_to_encoding (who, "%", encoding ()); + else + os << '%'; retval++; } else if (elt->args == 0 && ! elt->text.empty ()) { - os << elt->text; + if (encoding ().compare ("utf-8")) + os << string::u8_to_encoding (who, elt->text, encoding ()); + else + os << elt->text; retval += (elt->text.length ()); } else if (elt->type == 's' || elt->type == 'c') @@ -5938,13 +5946,10 @@ } int - base_stream::printf (std::string fmt, + base_stream::printf (const std::string& fmt, const octave_value_list& args, const std::string& who) { - if (encoding ().compare ("utf-8")) - fmt = string::u8_to_encoding (who, fmt, encoding ()); - printf_format_list fmt_list (fmt); if (fmt_list.num_conversions () == -1) diff -r 94d490815aa8 -r 1c8b20731af4 libinterp/corefcn/oct-stream.h --- a/libinterp/corefcn/oct-stream.h Tue Mar 05 17:56:57 2019 +0100 +++ b/libinterp/corefcn/oct-stream.h Sat Mar 09 22:09:25 2019 +0100 @@ -235,7 +235,7 @@ int do_printf (printf_format_list& fmt_list, const octave_value_list& args, const std::string& who /* = "printf" */); - int printf (std::string fmt, const octave_value_list& args, + int printf (const std::string& fmt, const octave_value_list& args, const std::string& who /* = "printf" */); int puts (const std::string& s, const std::string& who /* = "puts" */); diff -r 94d490815aa8 -r 1c8b20731af4 libinterp/corefcn/utils.cc --- a/libinterp/corefcn/utils.cc Tue Mar 05 17:56:57 2019 +0100 +++ b/libinterp/corefcn/utils.cc Sat Mar 09 22:09:25 2019 +0100 @@ -42,6 +42,7 @@ #include "oct-cmplx.h" #include "oct-env.h" #include "oct-locbuf.h" +#include "oct-string.h" #include "pathsearch.h" #include "quit.h" #include "str-vec.h" @@ -1236,6 +1237,33 @@ return s.length (); } + size_t format (std::ostream& os, const std::string& enc, const char *fmt, ...) + { + size_t retval; + + va_list args; + va_start (args, fmt); + + retval = vformat (os, enc, fmt, args); + + va_end (args); + + return retval; + } + + size_t vformat (std::ostream& os, const std::string& enc, const char *fmt, + va_list args) + { + std::string s = vasprintf (fmt, args); + + if (enc.compare ("utf-8")) + os << string::u8_to_encoding ("printf", s, enc); + else + os << s; + + return s.length (); + } + std::string vasprintf (const char *fmt, va_list args) { std::string retval; diff -r 94d490815aa8 -r 1c8b20731af4 libinterp/corefcn/utils.h --- a/libinterp/corefcn/utils.h Tue Mar 05 17:56:57 2019 +0100 +++ b/libinterp/corefcn/utils.h Sat Mar 09 22:09:25 2019 +0100 @@ -109,8 +109,15 @@ format (std::ostream& os, const char *fmt, ...); extern OCTINTERP_API size_t + format (std::ostream& os, const std::string& enc, const char *fmt, ...); + + extern OCTINTERP_API size_t vformat (std::ostream& os, const char *fmt, va_list args); + extern OCTINTERP_API size_t + vformat (std::ostream& os, const std::string& enc, + const char *fmt, va_list args); + extern OCTINTERP_API std::string vasprintf (const char *fmt, va_list args);