CMake/Source/cm_codecvt.hxx
Brad King 690acadc17 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
2017-05-25 15:03:03 -04:00

67 lines
1.9 KiB
C++

/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cm_codecvt_hxx
#define cm_codecvt_hxx
#include "cmConfigure.h"
#include <locale>
#include <wchar.h>
class codecvt : public std::codecvt<char, char, mbstate_t>
{
public:
enum Encoding
{
None,
UTF8,
ANSI
};
#ifdef CMAKE_BUILD_WITH_CMAKE
codecvt(Encoding e);
protected:
~codecvt() CM_OVERRIDE;
bool do_always_noconv() const throw() CM_OVERRIDE;
result do_out(mbstate_t& state, const char* from, const char* from_end,
const char*& from_next, char* to, char* to_end,
char*& to_next) const CM_OVERRIDE;
result do_unshift(mbstate_t& state, char* to, char*,
char*& to_next) const CM_OVERRIDE;
int do_max_length() const throw() CM_OVERRIDE;
int do_encoding() const throw() CM_OVERRIDE;
private:
// 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
{
// Buffer bytes we have consumed from a partial codepoint.
char partial[3];
// 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;
#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
};
#endif