📄 xlocbuf
字号:
// xlocbuf internal header (from <locale>)
#pragma once
#ifndef _XLOCBUF_
#define _XLOCBUF_
#ifndef RC_INVOKED
#include <xlocale>
#pragma pack(push,_CRT_PACKING)
#pragma warning(push,3)
_STD_BEGIN
// TEMPLATE CLASS wbuffer_convert
template<class _Codecvt,
class _Elem = wchar_t,
class _Traits = _STD char_traits<_Elem> >
class wbuffer_convert
: public _STD basic_streambuf<_Elem, _Traits>
{ // stream buffer associated with a codecvt facet
enum _Mode {_Unused, _Wrote, _Need, _Got, _Eof};
enum {_STRING_INC = 8};
public:
typedef wbuffer_convert<_Codecvt, _Elem, _Traits> _Myt;
typedef _STD streambuf _Mysb;
typedef _STD char_traits<char> _Byte_traits;
typedef typename _Traits::int_type int_type;
typedef typename _Traits::pos_type pos_type;
typedef typename _Traits::off_type off_type;
typedef typename _Traits::state_type state_type;
wbuffer_convert(_Mysb *_Strbuf = 0)
: _Pcvt(new _Codecvt),
_Mystrbuf(_Strbuf), _Status(_Unused), _Nback(0)
{ // construct with byte stream buffer pointer
static state_type _State0;
_State = _State0;
_Loc = _ADDFAC(_Loc, _Pcvt);
}
wbuffer_convert(_Mysb *_Strbuf, _Codecvt *_Pcvt_arg)
: _Pcvt(_Pcvt_arg),
_Mystrbuf(_Strbuf), _Status(_Unused), _Nback(0)
{ // construct with byte stream buffer pointer and codecvt
static state_type _State0;
_State = _State0;
_Loc = _ADDFAC(_Loc, _Pcvt);
}
wbuffer_convert(_Mysb *_Strbuf,
_Codecvt *_Pcvt_arg, state_type _State_arg)
: _Pcvt(_Pcvt_arg),
_Mystrbuf(_Strbuf), _Status(_Unused), _Nback(0)
{ // construct with byte stream buffer pointer, codecvt, and state
_State = _State_arg;
_Loc = _ADDFAC(_Loc, _Pcvt);
}
virtual ~wbuffer_convert()
{ // destroy the object
char *_Buf = (char *)_Str.c_str();
for (; _Status == _Wrote ; )
{ // put any trailing homing shift
char *_Dest;
if (_Str.size() < _STRING_INC)
_Str.assign(_STRING_INC, '\0');
switch (_Pcvt->unshift(_State,
_Buf, _Buf + _Str.size(), _Dest))
{ // test result of homing conversion
case _Codecvt::ok:
_Status = _Unused; // homed successfully
case _Codecvt::partial: // fall through
{ // put any generated bytes
int _Count = (int)(_Dest - _Buf);
if (0 < _Count
&& _Byte_traits::eq_int_type(
_Byte_traits::eof(),
(_Byte_traits::int_type)_Mystrbuf->sputn(_Buf,
_Count)))
return; // write failed
if (_Status == _Wrote && _Count == 0)
_Str.append(_STRING_INC, '\0'); // try with more space
break;
}
case _Codecvt::noconv:
return; // nothing to do
default:
return; // conversion failed
}
}
}
_Mysb *rdbuf() const
{ // return byte stream buffer pointer
return (_Mystrbuf);
}
_Mysb *rdbuf(_Mysb *_Strbuf)
{ // set byte stream buffer pointer
_Mysb *_Oldstrbuf = _Mystrbuf;
_Mystrbuf = _Strbuf;
return (_Oldstrbuf);
}
state_type state() const
{ // get state
return (_State);
}
protected:
virtual int_type overflow(int_type _Meta = _Traits::eof())
{ // put an element to stream
if (_Traits::eq_int_type(_Traits::eof(), _Meta))
return (_Traits::not_eof(_Meta)); // EOF, return success code
else if (_Mystrbuf == 0 || 0 < _Nback
|| _Status != _Unused && _Status != _Wrote)
return (_Traits::eof()); // no buffer or reading, fail
else
{ // put using codecvt facet
char *_Buf = (char *)_Str.c_str();
const _Elem _Ch = _Traits::to_char_type(_Meta);
const _Elem *_Src;
char *_Dest;
if (_Str.size() < _STRING_INC)
_Str.assign(_STRING_INC, '\0');
for (_Status = _Wrote; ; )
switch (_Pcvt->out(_State,
&_Ch, &_Ch + 1, _Src,
_Buf, _Buf + _Str.size(), _Dest))
{ // test result of converting one element
case _Codecvt::partial:
case _Codecvt::ok:
{ // converted something, try to put it out
int _Count = (int)(_Dest - _Buf);
if (0 < _Count
&& _Byte_traits::eq_int_type(
_Byte_traits::eof(),
(_Byte_traits::int_type)_Mystrbuf->sputn(_Buf,
_Count)))
return (_Traits::eof()); // write failed
if (_Src != &_Ch)
return (_Meta); // converted whole element
if (0 < _Count)
;
else if (_Str.size() < 4 * _STRING_INC)
_Str.append(_STRING_INC, '\0'); // try with more space
else
return (_Traits::eof()); // conversion failed
break;
}
case _Codecvt::noconv:
if (_Traits::eq_int_type(
_Traits::eof(),
(typename _Traits::int_type)_Mystrbuf->sputn(
(char *)&_Ch,
(_STD streamsize)sizeof (_Elem))))
return (_Traits::eof());
else
return (_Meta); // put native byte order
default:
return (_Traits::eof()); // conversion failed
}
}
}
virtual int_type pbackfail(int_type _Meta = _Traits::eof())
{ // put an element back to stream
if (sizeof (_Myback) / sizeof (_Myback[0]) <= _Nback
|| _Status == _Wrote)
return (_Traits::eof()); // nowhere to put back
else
{ // enough room, put it back
if (!_Traits::eq_int_type(_Traits::eof(), _Meta))
_Myback[_Nback] = _Traits::to_char_type(_Meta);
++_Nback;
if (_Status == _Unused)
_Status = _Got;
return (_Meta);
}
}
virtual int_type underflow()
{ // get an element from stream, but don't point past it
int_type _Meta;
if (0 < _Nback)
;
else if (_Traits::eq_int_type(_Traits::eof(), _Meta = _Get_elem()))
return (_Meta); // _Get_elem failed, return EOF
else
_Myback[_Nback++] = _Traits::to_char_type(_Meta);
return (_Traits::to_int_type(_Myback[_Nback - 1]));
}
virtual int_type uflow()
{ // get an element from stream, point past it
int_type _Meta;
if (0 < _Nback)
;
else if (_Traits::eq_int_type(_Traits::eof(), _Meta = _Get_elem()))
return (_Meta); // _Get_elem failed, return EOF
else
_Myback[_Nback++] = _Traits::to_char_type(_Meta);
return (_Traits::to_int_type(_Myback[--_Nback]));
}
virtual pos_type seekoff(off_type,
_STD ios::seekdir,
_STD ios::openmode =
(_STD ios::openmode)(_STD ios::in | _STD ios::out))
{ // change position by _Off
return (pos_type(-1)); // always fail
}
virtual pos_type seekpos(pos_type,
_STD ios::openmode =
(_STD ios::openmode)(_STD ios::in | _STD ios::out))
{ // change position to _Pos
return (pos_type(-1)); // always fail
}
private:
int_type _Get_elem()
{ // compose an element from byte stream buffer
if (_Mystrbuf != 0 && _Status != _Wrote)
{ // got buffer, haven't written, try to compose an element
if (_Status == _Eof)
;
else if (_Str.size() == 0)
_Status = _Need;
else
_Status = _Got;
for (; _Status != _Eof; )
{ // get using codecvt facet
char *_Buf = (char *)_Str.c_str();
_Elem _Ch, *_Dest;
const char *_Src;
int _Meta;
if (_Status != _Need)
;
else if (_Byte_traits::eq_int_type(_Byte_traits::eof(),
_Meta = _Mystrbuf->sbumpc()))
_Status = _Eof;
else
_Str.append(1, _Byte_traits::to_char_type(_Meta));
switch (_Pcvt->in(_State,
_Buf, _Buf + _Str.size(), _Src,
&_Ch, &_Ch + 1, _Dest))
{ // test result of converting one element
case _Codecvt::partial:
case _Codecvt::ok:
_Str.erase((size_t)0, // discard any used input
(size_t)(_Src - _Buf));
if (_Dest != &_Ch)
return (_Traits::to_int_type(_Ch));
break;
case _Codecvt::noconv:
if (_Str.size() < sizeof (_Elem))
break; // no conversion, but need more chars
_CSTD memcpy(&_Ch, _Buf,
sizeof (_Elem)); // copy raw bytes to element
_Str.erase((size_t)0, sizeof (_Elem));
return (_Traits::to_int_type(_Ch)); // return result
default:
_Status = _Eof; // conversion failed
}
}
}
return (_Traits::eof());
}
state_type _State; // code conversion state
_Codecvt *_Pcvt; // the codecvt facet
_Mysb *_Mystrbuf; // pointer to stream buffer
_Mode _Status; // buffer read/write status
size_t _Nback; // number of elements in putback buffer
_Elem _Myback[8]; // putback buffer
_STD string _Str; // unconsumed input bytes
_STD locale _Loc; // manages reference to codecvt facet
};
// TEMPLATE CLASS wstring_convert
template<class _Codecvt,
class _Elem = wchar_t,
class _Walloc = allocator<_Elem>,
class _Balloc = allocator<char> >
class wstring_convert
{ // converts between _Elem (wide) and char (byte) strings
enum {_BUF_INC = 8, _BUF_MAX = 16};
void _Init(_Codecvt *_Pcvt_arg = new _Codecvt)
{ // initialize the object
_Pcvt = _Pcvt_arg;
_Loc = locale(_Loc, _Pcvt);
_Nconv = 0;
}
public:
typedef _STD basic_string<char, char_traits<char>, _Balloc> byte_string;
typedef _STD basic_string<_Elem, char_traits<_Elem>, _Walloc> wide_string;
typedef typename _Codecvt::state_type state_type;
typedef typename wide_string::traits_type::int_type int_type;
wstring_convert()
: _Has_berr(false), _Has_werr(false), _Has_state(false)
{ // construct with no error strings
_Init();
}
wstring_convert(_Codecvt *_Pcvt_arg)
: _Has_berr(false), _Has_werr(false), _Has_state(false)
{ // construct with no error strings and codecvt
_Init(_Pcvt_arg);
}
wstring_convert(_Codecvt *_Pcvt_arg, state_type _State_arg)
: _Has_berr(false), _Has_werr(false), _Has_state(true)
{ // construct with no error strings, codecvt, and state
_Init(_Pcvt_arg);
_State = _State_arg;
}
wstring_convert(const byte_string& _Berr_arg)
: _Has_berr(true), _Has_werr(false), _Has_state(false),
_Berr(_Berr_arg)
{ // construct with byte error string
_Init();
}
wstring_convert(const byte_string& _Berr_arg,
const wide_string& _Werr_arg)
: _Has_berr(true), _Has_werr(true), _Has_state(false),
_Berr(_Berr_arg), _Werr(_Werr_arg)
{ // construct with byte and wide error strings
_Init();
}
virtual ~wstring_convert()
{ // destroy the object
}
size_t converted() const
{ // get conversion count
return (_Nconv);
}
state_type state() const
{ // get state
return (_State);
}
wide_string from_bytes(char _Byte)
{ // convert a byte to a wide string
return (from_bytes(&_Byte, &_Byte + 1));
}
wide_string from_bytes(const char *_Ptr)
{ // convert a NTBS to a wide string
return (from_bytes(_Ptr, _Ptr + strlen(_Ptr)));
}
wide_string from_bytes(const byte_string& _Bstr)
{ // convert a byte string to a wide string
const char *_Ptr = _Bstr.c_str();
return (from_bytes(_Ptr, _Ptr + _Bstr.size()));
}
wide_string from_bytes(const char *_First, const char *_Last)
{ // convert byte sequence [_First, _Last) to a wide string
static state_type _State0;
wide_string _Wbuf, _Wstr;
const char *_First_sav = _First;
if (!_Has_state)
_State = _State0; // reset state if not remembered
_Wbuf.append((_CSTD size_t)_BUF_INC, (_Elem)'\0');
for (_Nconv = 0; _First != _Last; _Nconv = _First - _First_sav)
{ // convert one or more bytes
_Elem *_Dest = &*_Wbuf.begin();
_Elem *_Dnext;
switch (_Pcvt->in(_State,
_First, _Last, _First,
_Dest, _Dest + _Wbuf.size(), _Dnext))
{ // test result of converting one or more bytes
case _Codecvt::partial:
case _Codecvt::ok:
if (_Dest < _Dnext)
_Wstr.append(_Dest, (_CSTD size_t)(_Dnext - _Dest));
else if (_Wbuf.size() < _BUF_MAX)
_Wbuf.append((_CSTD size_t)_BUF_INC, '\0');
else if (_Has_werr)
return (_Werr);
else
_THROW_NCEE(_STD range_error, "bad conversion");
break;
case _Codecvt::noconv:
for (; _First != _Last; ++_First)
_Wstr.append((_CSTD size_t)1,
(_Elem)(unsigned char)*_First);
break; // no conversion, just copy code values
default:
if (_Has_werr)
return (_Werr);
else
_THROW_NCEE(_STD range_error, "bad conversion");
}
}
return (_Wstr);
}
byte_string to_bytes(_Elem _Char)
{ // convert a wide char to a byte string
return (to_bytes(&_Char, &_Char + 1));
}
byte_string to_bytes(const _Elem *_Wptr)
{ // convert a NTWCS to a byte string
const _Elem *_Next = _Wptr;
for (; (int_type)*_Next != 0; ++_Next)
;
return (to_bytes(_Wptr, _Next));
}
byte_string to_bytes(const wide_string& _Wstr)
{ // convert a wide string to a byte string
const _Elem *_Wptr = _Wstr.c_str();
return (to_bytes(_Wptr, _Wptr + _Wstr.size()));
}
byte_string to_bytes(const _Elem *_First, const _Elem *_Last)
{ // convert wide sequence [_First, _Last) to a byte string
static state_type _State0;
byte_string _Bbuf, _Bstr;
const _Elem *_First_sav = _First;
if (!_Has_state)
_State = _State0; // reset state if not remembered
_Bbuf.append((_CSTD size_t)_BUF_INC, '\0');
for (_Nconv = 0; _First != _Last; _Nconv = _First - _First_sav)
{ // convert one or more wide chars
char *_Dest = &*_Bbuf.begin();
char *_Dnext;
switch (_Pcvt->out(_State,
_First, _Last, _First,
_Dest, _Dest + _Bbuf.size(), _Dnext))
{ // test result of converting one or more wide chars
case _Codecvt::partial:
case _Codecvt::ok:
if (_Dest < _Dnext)
_Bstr.append(_Dest, (_CSTD size_t)(_Dnext - _Dest));
else if (_Bbuf.size() < _BUF_MAX)
_Bbuf.append((_CSTD size_t)_BUF_INC, '\0');
else if (_Has_berr)
return (_Berr);
else
_THROW_NCEE(_STD range_error, "bad conversion");
break;
case _Codecvt::noconv:
for (; _First != _Last; ++_First)
_Bstr.append((_CSTD size_t)1,
(char)(int_type)*_First);
break; // no conversion, just copy code values
default:
if (_Has_berr)
return (_Berr);
else
_THROW_NCEE(_STD range_error, "bad conversion");
}
}
return (_Bstr);
}
private:
_Codecvt *_Pcvt; // the codecvt facet
_STD locale _Loc; // manages reference to codecvt facet
byte_string _Berr;
wide_string _Werr;
state_type _State; // the remembered state
bool _Has_state;
bool _Has_berr;
bool _Has_werr;
size_t _Nconv;
};
_STD_END
#pragma warning(pop)
#pragma pack(pop)
#endif /* RC_INVOKED */
#endif /* _XLOCBUF_ */
/*
* Copyright (c) 1992-2009 by P.J. Plauger. ALL RIGHTS RESERVED.
* Consult your license regarding permissions and restrictions.
V5.20:0009 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -