diff options
author | Brad King <brad.king@kitware.com> | 2017-05-25 11:26:36 -0400 |
---|---|---|
committer | Brad King <brad.king@kitware.com> | 2017-05-25 15:03:03 -0400 |
commit | 690acadc17263621f5361d48057c6f938e698a58 (patch) | |
tree | f82f1104363a018cba98a166acd98988a6c13150 /Source/cm_codecvt.hxx | |
parent | ae5f98a5e36da8cf3c75625ffb9a1d34aa2407cb (diff) | |
download | cmake-690acadc17263621f5361d48057c6f938e698a58.tar.gz |
codecvt: Re-implement do_out and do_unshift
The previous implementation assumed that only one byte would be given
in the `from` buffer by the caller at a time. This may be true for
MSVC but is not for the GNU library on Windows. Re-implement these
methods to handle more than one byte per call.
Also simplify the state management by keeping all state between calls
directly in the `mbstate_t` argument instead of using it to index our
own heap-allocated state.
Fixes: #16893
Diffstat (limited to 'Source/cm_codecvt.hxx')
-rw-r--r-- | Source/cm_codecvt.hxx | 28 |
1 files changed, 18 insertions, 10 deletions
diff --git a/Source/cm_codecvt.hxx b/Source/cm_codecvt.hxx index b9b52eccf8..30c6d5407d 100644 --- a/Source/cm_codecvt.hxx +++ b/Source/cm_codecvt.hxx @@ -6,7 +6,6 @@ #include "cmConfigure.h" #include <locale> -#include <vector> #include <wchar.h> class codecvt : public std::codecvt<char, char, mbstate_t> @@ -35,21 +34,30 @@ protected: int do_encoding() const throw() CM_OVERRIDE; private: - typedef struct + // The mbstate_t argument to do_out and do_unshift is responsible + // for storing state between calls. We cannot control the type + // since we want to imbue on standard streams. However, we do + // know that it is a trivial type. Define our own type to overlay + // on it safely with no alignment requirements. + struct State { - bool used; - unsigned char totalBytes; - unsigned char bytesLeft; - char bytes[4]; - } State; + // Buffer bytes we have consumed from a partial codepoint. + char partial[3]; - unsigned int findStateId() const; + // Number of bytes we have buffered from a partial codepoint. + unsigned char buffered : 4; + + // Size of the current codepoint in bytes. + unsigned char size : 4; + }; bool m_noconv; - mutable std::vector<State> m_states; - mutable unsigned int m_lastState; #if defined(_WIN32) unsigned int m_codepage; + result Decode(mbstate_t& state, int need, const char*& from_next, + char*& to_next, char* to_end) const; + result DecodePartial(mbstate_t& state, char*& to_next, char* to_end) const; + void BufferPartial(mbstate_t& state, int need, const char*& from_next) const; #endif #endif |