From b630afdeda4a5e1b38ec93e98fd4a9e2fe86d510 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Sun, 4 Sep 2016 12:05:37 +0200 Subject: [PATCH] fs/io/BufferedOutputStream: add wchar_t overloads --- src/fs/io/BufferedOutputStream.cxx | 51 ++++++++++++++++++++++++++++++ src/fs/io/BufferedOutputStream.hxx | 18 +++++++++++ 2 files changed, 69 insertions(+) diff --git a/src/fs/io/BufferedOutputStream.cxx b/src/fs/io/BufferedOutputStream.cxx index 396fa91c7..7f7b7a4a5 100644 --- a/src/fs/io/BufferedOutputStream.cxx +++ b/src/fs/io/BufferedOutputStream.cxx @@ -25,6 +25,11 @@ #include #include +#ifdef _UNICODE +#include "system/Error.hxx" +#include +#endif + bool BufferedOutputStream::AppendToBuffer(const void *data, size_t size) noexcept { @@ -103,6 +108,52 @@ BufferedOutputStream::Format(const char *fmt, ...) buffer.Append(size); } +#ifdef _UNICODE + +void +BufferedOutputStream::Write(const wchar_t *p) +{ + WriteWideToUTF8(p, wcslen(p)); +} + +void +BufferedOutputStream::WriteWideToUTF8(const wchar_t *src, size_t src_length) +{ + if (src_length == 0) + return; + + auto r = buffer.Write(); + if (r.IsEmpty()) { + Flush(); + r = buffer.Write(); + } + + int length = WideCharToMultiByte(CP_UTF8, 0, src, src_length, + r.data, r.size, nullptr, nullptr); + if (length <= 0) { + const auto error = GetLastError(); + if (error != ERROR_INSUFFICIENT_BUFFER) + throw MakeLastError(error, "UTF-8 conversion failed"); + + /* how much buffer do we need? */ + length = WideCharToMultiByte(CP_UTF8, 0, src, src_length, + nullptr, 0, nullptr, nullptr); + if (length <= 0) + throw MakeLastError(error, "UTF-8 conversion failed"); + + /* grow the buffer and try again */ + length = WideCharToMultiByte(CP_UTF8, 0, src, src_length, + buffer.Write(length), length, + nullptr, nullptr); + if (length <= 0) + throw MakeLastError(error, "UTF-8 conversion failed"); + } + + buffer.Append(length); +} + +#endif + void BufferedOutputStream::Flush() { diff --git a/src/fs/io/BufferedOutputStream.hxx b/src/fs/io/BufferedOutputStream.hxx index 1a0ae021d..3d42bedf7 100644 --- a/src/fs/io/BufferedOutputStream.hxx +++ b/src/fs/io/BufferedOutputStream.hxx @@ -26,11 +26,17 @@ #include +#ifdef _UNICODE +#include +#endif + class OutputStream; /** * An #OutputStream wrapper that buffers its output to reduce the * number of OutputStream::Write() calls. + * + * All wchar_t based strings are converted to UTF-8. */ class BufferedOutputStream { OutputStream &os; @@ -52,6 +58,14 @@ public: gcc_printf(2,3) void Format(const char *fmt, ...); +#ifdef _UNICODE + void Write(const wchar_t &ch) { + WriteWideToUTF8(&ch, 1); + } + + void Write(const wchar_t *p); +#endif + /** * Write buffer contents to the #OutputStream. */ @@ -59,6 +73,10 @@ public: private: bool AppendToBuffer(const void *data, size_t size) noexcept; + +#ifdef _UNICODE + void WriteWideToUTF8(const wchar_t *p, size_t length); +#endif }; #endif