Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion examples/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ int bc::system::main(int argc, char* argv[])
system::cout << "Enter text to input..." << std::endl;
std::string console;
system::cin >> console;
system::cout << "input[0] : " << console << std::endl;
system::cout << "input[0] : " << console << std::endl;

if (argc > 1)
system::cout << "argv[1] : " << argv[1] << std::endl;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,30 +35,30 @@ class BC_API console_streambuf
public:
DELETE_COPY_MOVE(console_streambuf);

/// Initialize stdio to use utf8 translation on Windows.
static void initialize(size_t stream_buffer_size) THROWS;
/// Initialize console in/out to use utf8 translation on Windows.
static void set_input(size_t stream_buffer_size) THROWS;
static void set_output() THROWS;

protected:
/// Protected construction, use static initialize method.
console_streambuf(const std::wstreambuf& stream_buffer,
size_t stream_buffer_size) THROWS;
console_streambuf(const std::wstreambuf& buffer, size_t size) THROWS;

/// Delete stream buffer.
virtual ~console_streambuf() NOEXCEPT;

/// Alternate console read.
virtual std::streamsize xsgetn(wchar_t* buffer,
std::streamsize size) THROWS;
std::streamsize xsgetn(wchar_t* buffer,
std::streamsize size) THROWS override;

/// Alternate console read.
virtual std::wstreambuf::int_type underflow() THROWS;
std::wstreambuf::int_type underflow() THROWS override;

#ifdef HAVE_MSC
private:
// These are not thread safe.

// The constructed buffer size.
size_t buffer_size_;
const size_t buffer_size_;

// The dynamically-allocated buffers.
wchar_t* buffer_;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class BC_API unicode_istream

/// Construct instance of a conditionally-narrowing input stream.
unicode_istream(std::istream& narrow_stream, std::wistream& wide_stream,
size_t wide_buffer_size) THROWS;
size_t wide_size) THROWS;

/// Delete the unicode_streambuf that wraps wide_stream.
virtual ~unicode_istream() NOEXCEPT;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class BC_API unicode_ostream

/// Construct instance of a conditionally-widening output stream.
unicode_ostream(std::ostream& narrow_stream, std::wostream& wide_stream,
size_t wide_buffer_size) THROWS;
size_t wide_size) THROWS;

/// Delete the unicode_streambuf that wraps wide_stream.
virtual ~unicode_ostream() NOEXCEPT;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,30 +37,30 @@ class BC_API unicode_streambuf
DELETE_COPY_MOVE(unicode_streambuf);

/// Construct unicode stream buffer from a weak reference to a wide buffer.
unicode_streambuf(std::wstreambuf* wide_buffer, size_t size) THROWS;
unicode_streambuf(std::wstreambuf* buffer, size_t size) THROWS;

/// Synchronize stream buffer.
virtual ~unicode_streambuf() NOEXCEPT;

protected:
/// Underflow for support of input streams.
virtual std::streambuf::int_type underflow() THROWS;
std::streambuf::int_type underflow() THROWS override;

/// Overflow for support of output streams.
virtual std::streambuf::int_type overflow(
std::streambuf::int_type character) THROWS;
std::streambuf::int_type overflow(
std::streambuf::int_type character) THROWS override;

//// Sync for support of output streams.
virtual int sync() THROWS;
/// Sync for support of output streams.
int sync() THROWS override;

private:
// These are not thread safe.

// The constructed wide buffer size in number of characters.
size_t wide_size_;
const size_t wide_size_;

// The derived narrow buffer size in utf8 (bytes).
size_t narrow_size_;
const size_t narrow_size_;

// The dynamically-allocated buffers.
wchar_t* wide_;
Expand Down
32 changes: 23 additions & 9 deletions src/unicode/utf8_everywhere/console_streambuf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,14 @@ static LPVOID get_input_handle() THROWS
return handle;
}

// Hack for faulty std::wcin translation of non-ASCII keyboard input.
void console_streambuf::initialize(size_t stream_buffer_size) THROWS
void console_streambuf::set_input(size_t stream_buffer_size) THROWS
{
// Set the console to operate in UTF-8 for this process.
// Set console input to operate in UTF-8 for this process.
// learn.microsoft.com/en-us/windows/console/setconsolecp
if (SetConsoleCP(CP_UTF8) == FALSE)
throw runtime_exception("Failed to set console to utf8.");
throw runtime_exception("Failed to set console input to utf8.");

// Hack for faulty std::wcin translation of non-ASCII keyboard input.
DWORD console_mode;
if (GetConsoleMode(get_input_handle(), &console_mode) != FALSE)
{
Expand All @@ -53,10 +54,19 @@ void console_streambuf::initialize(size_t stream_buffer_size) THROWS
}
}

console_streambuf::console_streambuf(
const std::wstreambuf& stream_buffer, size_t size) THROWS
: buffer_size_(size), buffer_(new wchar_t[buffer_size_]),
std::wstreambuf(stream_buffer)
void console_streambuf::set_output() THROWS
{
// Set console output to operate in UTF-8 for this process.
// learn.microsoft.com/en-us/windows/console/setconsoleoutputcp
if (SetConsoleOutputCP(CP_UTF8) == FALSE)
throw runtime_exception("Failed to set console output to utf8.");
}

console_streambuf::console_streambuf(const std::wstreambuf& buffer,
size_t size) THROWS
: buffer_size_(size),
buffer_(new wchar_t[size]),
std::wstreambuf(buffer)
{
}

Expand Down Expand Up @@ -92,7 +102,11 @@ std::wstreambuf::int_type console_streambuf::underflow() THROWS

#else

void console_streambuf::initialize(size_t) THROWS
void console_streambuf::set_input(size_t) THROWS
{
}

void console_streambuf::set_output() THROWS
{
}

Expand Down
6 changes: 3 additions & 3 deletions src/unicode/utf8_everywhere/environment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -235,23 +235,23 @@ static std::once_flag io_mutex;
// Static initializer for bc::system::cin.
std::istream& cin_stream() THROWS
{
std::call_once(io_mutex, console_streambuf::initialize, utf16_buffer_size);
std::call_once(io_mutex, console_streambuf::set_input, utf16_buffer_size);
static unicode_istream input(std::cin, std::wcin, utf16_buffer_size);
return input;
}

// Static initializer for bc::system::cout.
std::ostream& cout_stream() THROWS
{
std::call_once(io_mutex, console_streambuf::initialize, utf16_buffer_size);
std::call_once(io_mutex, console_streambuf::set_output);
static unicode_ostream output(std::cout, std::wcout, utf16_buffer_size);
return output;
}

// Static initializer for bc::system::cerr.
std::ostream& cerr_stream() THROWS
{
std::call_once(io_mutex, console_streambuf::initialize, utf16_buffer_size);
std::call_once(io_mutex, console_streambuf::set_output);
static unicode_ostream error(std::cerr, std::wcerr, utf16_buffer_size);
return error;
}
Expand Down
13 changes: 5 additions & 8 deletions src/unicode/utf8_everywhere/unicode_istream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,13 @@
namespace libbitcoin {
namespace system {

unicode_istream::unicode_istream(
#ifdef HAVE_MSC
std::istream&, std::wistream& wide_stream,
size_t wide_buffer_size) THROWS
#else
std::istream& narrow_stream, std::wistream&, size_t)
#endif
#ifdef HAVE_MSC
: std::istream(new unicode_streambuf(wide_stream.rdbuf(), wide_buffer_size))
unicode_istream::unicode_istream(std::istream&, std::wistream& wide_stream,
size_t wide_size) THROWS
: std::istream(new unicode_streambuf(wide_stream.rdbuf(), wide_size))
#else
unicode_istream::unicode_istream(std::istream& narrow_stream,
std::wistream&, size_t) THROWS
: std::istream(narrow_stream.rdbuf())
#endif
{
Expand Down
13 changes: 5 additions & 8 deletions src/unicode/utf8_everywhere/unicode_ostream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,13 @@
namespace libbitcoin {
namespace system {

unicode_ostream::unicode_ostream(
#ifdef HAVE_MSC
std::ostream&, std::wostream& wide_stream,
size_t wide_buffer_size) THROWS
#else
std::ostream& narrow_stream, std::wostream&, size_t)
#endif
#ifdef HAVE_MSC
: std::ostream(new unicode_streambuf(wide_stream.rdbuf(), wide_buffer_size))
unicode_ostream::unicode_ostream(std::ostream&, std::wostream& wide_stream,
size_t wide_size) THROWS
: std::ostream(new unicode_streambuf(wide_stream.rdbuf(), wide_size))
#else
unicode_ostream::unicode_ostream(std::ostream& narrow_stream,
std::wostream&, size_t) THROWS
: std::ostream(narrow_stream.rdbuf())
#endif
{
Expand Down
15 changes: 9 additions & 6 deletions src/unicode/utf8_everywhere/unicode_streambuf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,15 @@
namespace libbitcoin {
namespace system {

unicode_streambuf::unicode_streambuf(std::wstreambuf* wide_buffer,
unicode_streambuf::unicode_streambuf(std::wstreambuf* buffer,
size_t size) THROWS
: wide_size_(size),
narrow_size_(wide_size_ * utf8_max_character_size),
narrow_(new char[narrow_size_]),
wide_(new wchar_t[narrow_size_]),
wide_buffer_(wide_buffer)
wide_buffer_(buffer)
{
if (is_zero(wide_size_) || wide_buffer == nullptr ||
if (is_zero(wide_size_) || is_null(wide_buffer_) ||
wide_size_ > (bc::max_size_t / utf8_max_character_size))
throw runtime_exception("unicode_streambuf parameters");

Expand All @@ -63,7 +63,7 @@ std::streambuf::int_type unicode_streambuf::underflow() THROWS
// streamsize is signed.
const auto size = static_cast<std::streamsize>(wide_size_);

// Read from the wide input buffer (non-negative).
// Read from the wide input buffer, blocking (non-negative).
const auto read = wide_buffer_->sgetn(wide_, size);

// Handle read termination.
Expand All @@ -90,7 +90,7 @@ std::streambuf::int_type unicode_streambuf::underflow() THROWS
// MSVC does not support a UTF8 locale and as such streams interpret
// narrow characters in the default locale. This implementation
// assumes the stream will treat each byte of a multibyte narrow
// chracter as an individual single byte character.
// character as an individual single byte character.
std::streambuf::int_type unicode_streambuf::overflow(
std::streambuf::int_type character) THROWS
{
Expand Down Expand Up @@ -134,7 +134,6 @@ std::streambuf::int_type unicode_streambuf::overflow(
return traits_type::eof();
}

// C++17: parallel policy for copy_n.
// write is necessarily no greater than unwritten.
// Copy the fractional character to the beginning of the buffer.
std::copy_n(&narrow_[write - unwritten], unwritten, narrow_);
Expand All @@ -155,6 +154,10 @@ std::streambuf::int_type unicode_streambuf::overflow(
// Flush our output sequence.
int unicode_streambuf::sync() THROWS
{
// Bypass for input.
if (is_null(std::streambuf::pptr()))
return std::streambuf::sync();

const int success = zero;
const int failure = negative_one;

Expand Down