about summary refs log tree commit diff
diff options
context:
space:
mode:
authorPhilipp Hagemeister <phihag@phihag.de>2014-04-21 04:59:44 +0200
committerPhilipp Hagemeister <phihag@phihag.de>2014-04-21 04:59:46 +0200
commitd1b9c912a42de3b99ae73553d38fbfa50b8ebc52 (patch)
tree90ca45d72c3c49245a84b9f1297f5e081b90f3c9
parentedec83a02579007da0f1043f7340ff2fe252a84b (diff)
downloadyoutube-dl-d1b9c912a42de3b99ae73553d38fbfa50b8ebc52.tar.gz
youtube-dl-d1b9c912a42de3b99ae73553d38fbfa50b8ebc52.tar.xz
youtube-dl-d1b9c912a42de3b99ae73553d38fbfa50b8ebc52.zip
[utils] Fix _windows_write_string (Fixes #2779)
It turns out that the function did not work for outputs longer than 1024 UCS-2 tokens.
Write non-BMP characters one by one to ensure that we count correctly.
-rw-r--r--youtube_dl/utils.py23
1 files changed, 16 insertions, 7 deletions
diff --git a/youtube_dl/utils.py b/youtube_dl/utils.py
index 9c9320934..116eb3610 100644
--- a/youtube_dl/utils.py
+++ b/youtube_dl/utils.py
@@ -923,9 +923,6 @@ def _windows_write_string(s, out):
         2: -12,
     }
 
-    def ucs2_len(s):
-        return sum((2 if ord(c) > 0xffff else 1) for c in s)
-
     fileno = out.fileno()
     if fileno not in WIN_OUTPUT_IDS:
         return False
@@ -959,13 +956,25 @@ def _windows_write_string(s, out):
     if not_a_console(h):
         return False
 
-    remaining = ucs2_len(s)
-    while remaining > 0:
+    def next_nonbmp_pos(s):
+        try:
+            return next(i for i, c in enumerate(s) if ord(c) > 0xffff)
+        except StopIteration:
+            return len(s)
+
+    while s:
+        count = min(next_nonbmp_pos(s), 1024)
+
         ret = WriteConsoleW(
-            h, s, min(remaining, 1024), ctypes.byref(written), None)
+            h, s, count if count else 2, ctypes.byref(written), None)
         if ret == 0:
             raise OSError('Failed to write string')
-        remaining -= written.value
+        if not count:  # We just wrote a non-BMP character
+            assert written.value == 2
+            s = s[1:]
+        else:
+            assert written.value > 0
+            s = s[written.value:]
     return True