Advertisement
Guest User

Untitled

a guest
Mar 18th, 2018
115
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.13 KB | None | 0 0
  1. // This is workaround of console unicode input/output from https://alfps.wordpress.com/2011/12/08/unicode-part-2-utf-8-stream-mode/
  2.  
  3. #include "stdafx.h"
  4.  
  5. #include "stream_fixer.h"
  6.  
  7. typedef ptrdiff_t       Size;
  8.  
  9. bool throwX(string const& s) { throw runtime_error(s); }
  10. bool hopefully(bool v) { return v; }
  11.  
  12. class DirectInputBuffer
  13.     : public std::basic_streambuf< wchar_t >
  14. {
  15. private:
  16.     wstring     buffer_;
  17.  
  18.     Size bufferSize() const { return buffer_.size(); }
  19.     wchar_t* pBufferStart() { return &buffer_[0]; }
  20.     wchar_t* pBufferEnd() { return pBufferStart() + bufferSize(); }
  21.  
  22.     wchar_t* pStart() const { return eback(); }
  23.     wchar_t* pCurrent() const { return gptr(); }
  24.     wchar_t* pEnd() const { return egptr(); }
  25.  
  26.     static HANDLE inputHandle()
  27.     {
  28.         static HANDLE const handle = GetStdHandle(STD_INPUT_HANDLE);
  29.         return handle;
  30.     }
  31.  
  32. public:
  33.     typedef std::basic_streambuf< wchar_t >     Base;
  34.     typedef Base::traits_type                   Traits;
  35.  
  36.     DirectInputBuffer(Base const& anOriginalBuffer)
  37.         : Base(anOriginalBuffer)      // Copies buffer read area pointers.
  38.         , buffer_(256, L'#')
  39.     {}
  40.  
  41. protected:
  42.     virtual streamsize xsgetn(wchar_t* const pBuffer, streamsize const n)
  43.     {
  44.         wchar_t const   ctrlZ = wchar_t(1 + ('Z' - 'A'));
  45.  
  46.         DWORD       nCharactersRead = 0;
  47.  
  48.         bool const  readSucceeded = !!ReadConsole(
  49.             inputHandle(), pBuffer, static_cast< DWORD >(n), &nCharactersRead, nullptr
  50.         );
  51.  
  52.         if (readSucceeded)
  53.         {
  54.             wchar_t const* const    pCleanEnd =
  55.                 remove(pBuffer, pBuffer + nCharactersRead, L'\r');
  56.  
  57.             nCharactersRead = (DWORD)(pCleanEnd - pBuffer);
  58.  
  59.             bool const isInteractiveEOF =
  60.                 (nCharactersRead == 2 && pBuffer[0] == ctrlZ && pBuffer[1] == '\n');
  61.  
  62.             return (isInteractiveEOF ? 0 : static_cast< streamsize >(nCharactersRead));
  63.         }
  64.         return 0;
  65.     }
  66.  
  67.     virtual int_type underflow()
  68.     {
  69.         // Try to get some more input (maximum a line).
  70.         if (pCurrent() == 0 || pCurrent() >= pEnd())
  71.         {
  72.             streamsize const nCharactersRead =
  73.                 xsgetn(pBufferStart(), bufferSize());
  74.  
  75.             if (nCharactersRead > 0)
  76.             {
  77.                 setg(
  78.                     pBufferStart(),                     // Reading area start
  79.                     pBufferStart(),                     // Reading area current
  80.                     pBufferStart() + nCharactersRead    // Reading area end
  81.                 );
  82.             }
  83.         }
  84.  
  85.         if (pCurrent() == 0 || pCurrent() >= pEnd())
  86.         {
  87.             return Traits::eof();
  88.         }
  89.         return Traits::to_int_type(*pCurrent());
  90.     }
  91. };
  92.  
  93. void setUtf8Mode(FILE* f, char const name[])
  94. {
  95.     int const newMode = _setmode(_fileno(f), _O_U8TEXT);
  96.     hopefully(newMode != -1)
  97.         || throwX(string() + "setmode failed for " + name);
  98. }
  99.  
  100. bool inputIsFromConsole()
  101. {
  102.     static HANDLE const inputHandle = GetStdHandle(STD_INPUT_HANDLE);
  103.  
  104.     DWORD consoleMode;
  105.     return !!GetConsoleMode(inputHandle, &consoleMode);
  106. }
  107.  
  108. void FixIOStream()
  109. {
  110.     if (inputIsFromConsole())
  111.     {
  112.         static DirectInputBuffer buffer(*wcin.rdbuf());
  113.         wcin.rdbuf(&buffer);
  114.     }
  115.     setUtf8Mode(stdin, "stdin");
  116.     setUtf8Mode(stdout, "stdout");
  117. }
  118.  
  119. wstring lineFrom(wistream& stream)
  120. {
  121.     wstring     result;
  122.  
  123.     getline(stream, result);
  124.     hopefully(!stream.fail())
  125.         || throwX("lineFrom: getline failed");
  126.     return result;
  127. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement