cog/Frameworks/SSEQPlayer/SSEQPlayer/wstring_convert.h

184 lines
6.2 KiB
C++

// This comes from llvm's libcxx project. I've copied the code from there (with very minor modifications) for use with GCC and Clang when libcxx isn't being used.
#if (defined(__GNUC__) || defined(__clang__)) && !defined(_LIBCPP_VERSION)
#pragma once
#include <memory>
#include <string>
#include <locale>
namespace std
{
template<class _Codecvt, class _Elem = wchar_t, class _Wide_alloc = allocator<_Elem>, class _Byte_alloc = allocator<char>> class wstring_convert
{
public:
typedef basic_string<char, char_traits<char>, _Byte_alloc> byte_string;
typedef basic_string<_Elem, char_traits<_Elem>, _Wide_alloc> wide_string;
typedef typename _Codecvt::state_type state_type;
typedef typename wide_string::traits_type::int_type int_type;
private:
byte_string __byte_err_string_;
wide_string __wide_err_string_;
_Codecvt *__cvtptr_;
state_type __cvtstate_;
size_t __cvtcount_;
wstring_convert(const wstring_convert &__wc);
wstring_convert& operator=(const wstring_convert &__wc);
public:
wstring_convert(_Codecvt *__pcvt = new _Codecvt) : __cvtptr_(__pcvt), __cvtstate_(), __cvtcount_(0) { }
wstring_convert(_Codecvt *__pcvt, state_type __state) : __cvtptr_(__pcvt), __cvtstate_(__state), __cvtcount_(0) { }
wstring_convert(const byte_string &__byte_err, const wide_string &__wide_err = wide_string()) : __byte_err_string_(__byte_err), __wide_err_string_(__wide_err), __cvtptr_(new _Codecvt), __cvtstate_(), __cvtcount_(0) { }
wstring_convert(wstring_convert &&__wc) : __byte_err_string_(move(__wc.__byte_err_string_)), __wide_err_string_(move(__wc.__wide_err_string_)), __cvtptr_(__wc.__cvtptr_), __cvtstate_(__wc.__cvtstate_), __cvtcount_(__wc.__cvtstate_)
{
__wc.__cvtptr_ = nullptr;
}
~wstring_convert() { delete this->__cvtptr_; }
wide_string from_bytes(char __byte) { return from_bytes(&__byte, &__byte + 1); }
wide_string from_bytes(const char *__ptr) { return from_bytes(__ptr, __ptr + char_traits<char>::length(__ptr)); }
wide_string from_bytes(const byte_string &__str) { return from_bytes(__str.data(), __str.data() + __str.size()); }
wide_string from_bytes(const char *__frm, const char *__frm_end)
{
this->__cvtcount_ = 0;
if (this->__cvtptr_)
{
wide_string __ws(2 * (__frm_end - __frm), _Elem());
if (__frm != __frm_end)
__ws.resize(__ws.capacity());
auto __r = codecvt_base::ok;
auto __st = this->__cvtstate_;
if (__frm != __frm_end)
{
auto __to = &__ws[0];
auto __to_end = __to + __ws.size();
const char *__frm_nxt;
do
{
_Elem *__to_nxt;
__r = this->__cvtptr_->in(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt);
this->__cvtcount_ += __frm_nxt - __frm;
if (__frm_nxt == __frm)
__r = codecvt_base::error;
else if (__r == codecvt_base::noconv)
{
__ws.resize(__to - &__ws[0]);
// This only gets executed if _Elem is char
__ws.append(reinterpret_cast<const _Elem *>(__frm), reinterpret_cast<const _Elem *>(__frm_end));
__frm = __frm_nxt;
__r = codecvt_base::ok;
}
else if (__r == codecvt_base::ok)
{
__ws.resize(__to_nxt - &__ws[0]);
__frm = __frm_nxt;
}
else if (__r == codecvt_base::partial)
{
ptrdiff_t __s = __to_nxt - &__ws[0];
__ws.resize(2 * __s);
__to = &__ws[0] + __s;
__to_end = &__ws[0] + __ws.size();
__frm = __frm_nxt;
}
} while (__r == codecvt_base::partial && __frm_nxt < __frm_end);
}
if (__r == codecvt_base::ok)
return __ws;
}
if (this->__wide_err_string_.empty())
throw range_error("wstring_convert: from_bytes error");
return this->__wide_err_string_;
}
byte_string to_bytes(_Elem __wchar) { return to_bytes(&__wchar, &__wchar + 1); }
byte_string to_bytes(const _Elem *__wptr) { return to_bytes(__wptr, __wptr + char_traits<_Elem>::length(__wptr)); }
byte_string to_bytes(const wide_string &__wstr) { return to_bytes(__wstr.data(), __wstr.data() + __wstr.size()); }
byte_string to_bytes(const _Elem *__frm, const _Elem *__frm_end)
{
this->__cvtcount_ = 0;
if (this->__cvtptr_)
{
byte_string __bs(2 * (__frm_end - __frm), char());
if (__frm != __frm_end)
__bs.resize(__bs.capacity());
auto __r = codecvt_base::ok;
auto __st = this->__cvtstate_;
if (__frm != __frm_end)
{
auto __to = &__bs[0];
auto __to_end = __to + __bs.size();
const _Elem *__frm_nxt;
do
{
char *__to_nxt;
__r = this->__cvtptr_->out(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt);
this->__cvtcount_ += __frm_nxt - __frm;
if (__frm_nxt == __frm)
__r = codecvt_base::error;
else if (__r == codecvt_base::noconv)
{
__bs.resize(__to - &__bs[0]);
// This only gets executed if _Elem is char
__bs.append(reinterpret_cast<const char *>(__frm), reinterpret_cast<const char *>(__frm_end));
__frm = __frm_nxt;
__r = codecvt_base::ok;
}
else if (__r == codecvt_base::ok)
{
__bs.resize(__to_nxt - &__bs[0]);
__frm = __frm_nxt;
}
else if (__r == codecvt_base::partial)
{
ptrdiff_t __s = __to_nxt - &__bs[0];
__bs.resize(2 * __s);
__to = &__bs[0] + __s;
__to_end = &__bs[0] + __bs.size();
__frm = __frm_nxt;
}
} while (__r == codecvt_base::partial && __frm_nxt < __frm_end);
}
if (__r == codecvt_base::ok)
{
auto __s = __bs.size();
__bs.resize(__bs.capacity());
auto __to = &__bs[0] + __s;
auto __to_end = __to + __bs.size();
do
{
char *__to_nxt;
__r = this->__cvtptr_->unshift(__st, __to, __to_end, __to_nxt);
if (__r == codecvt_base::noconv)
{
__bs.resize(__to - &__bs[0]);
__r = codecvt_base::ok;
}
else if (__r == codecvt_base::ok)
__bs.resize(__to_nxt - &__bs[0]);
else if (__r == codecvt_base::partial)
{
ptrdiff_t __sp = __to_nxt - &__bs[0];
__bs.resize(2 * __sp);
__to = &__bs[0] + __sp;
__to_end = &__bs[0] + __bs.size();
}
} while (__r == codecvt_base::partial);
if (__r == codecvt_base::ok)
return __bs;
}
}
if (this->__byte_err_string_.empty())
throw range_error("wstring_convert: to_bytes error");
return this->__byte_err_string_;
}
size_t converted() const noexcept { return this->__cvtcount_; }
state_type state() const { return this->__cvtstate_; }
};
}
#endif