changeset 27279:1c8b20731af4

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.
author Markus Mützel <markus.muetzel@gmx.de>
date Sat, 09 Mar 2019 22:09:25 +0100
parents 94d490815aa8
children 8d30dc86e5d9
files libinterp/corefcn/oct-stream.cc libinterp/corefcn/oct-stream.h libinterp/corefcn/utils.cc libinterp/corefcn/utils.h
diffstat 4 files changed, 61 insertions(+), 21 deletions(-) [+]
line wrap: on
line diff
--- 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 <typename T>
   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)
--- 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" */);
--- 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;
--- 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);