#ifndef _t_char_converter_CC_
#define _t_char_converter_CC_
#include <assert.h>
#include "kmtcmn.h"
namespace kmt{
namespace conv{
////////////////////////////////////////////////////////////////////////////////
//containing
template<class unicode_string>
struct t_ansi_to_unicode;
template<class ansi_string>
struct t_unicode_to_ansi;
////////////////////////////////////////////////////////////////////////////////
//struct t_ansi_to_unicode
template<class unicode_string>
struct t_ansi_to_unicode
{
typedef unicode_string string_type;
typedef typename string_type::value_type char_type;
//typedef t_void_allocator allocator_type;
//typedef t_typed_simple_buffer<char_type,allocator_type> buffer_type;
//convert 't' to 'result' and return 'result'
static string_type& convert(string_type& result,LPCSTR t,size_t n=-1,bool* error=NULL,UINT CodePage=CP_ACP);
static string_type convert(LPCSTR t,size_t n=-1,bool* error=NULL,UINT CodePage=CP_ACP);
};//struct t_ansi_to_unicode
////////////////////////////////////////////////////////////////////////////////
//template struct t_ansi_to_unicode
template<class unicode_string>
typename t_ansi_to_unicode<unicode_string>::string_type&
t_ansi_to_unicode<unicode_string>::convert(string_type& result,
LPCSTR str,size_t str_len,bool* error,UINT CodePage)
{
if(error)
*error=false;
if(str==NULL || str_len==0)
return result.erase();
//åñëè str_len==-1, òî WCTMB ó÷èòûâàåò çàâåðøàþùèé íóëåâîé ñèìâîë
int wlen=::MultiByteToWideChar(CodePage,0,str, (int)str_len,NULL,0);
assert(wlen>=0);
if(wlen==0 || (wlen==1 && str_len==-1))//error èëè str==""
{
if(error)
*error=::GetLastError()?true:false;
return result.erase();
}
if(str_len!=-1)
wlen+=1;//ó÷èòûâàåì çàâåðøàþùèé UNICODE-ñèìâîë
assert(wlen>1);//âåðíåì íå òîëüêî çàâåðøàþùèé ñèìâîë
//ðåçåðâèðóåì ìåñòî ïîä âñå ñèìâîëû (âêëþ÷àÿ è òåðìèíàëüíûé)
string_type::value_type *pbuf= new string_type::value_type[wlen];
int rw=::MultiByteToWideChar(CodePage,0,str,(int)str_len,pbuf,wlen);
result.erase();
result.append(pbuf, pbuf+rw);
delete[] pbuf;
return result;//.erase(result.size()-1,1);
}//t_ansi_to_unicode::convert (result...)
template<class unicode_string>
typename t_ansi_to_unicode<unicode_string>::string_type
t_ansi_to_unicode<unicode_string>::convert(LPCSTR str,size_t str_len,bool* error,UINT CodePage)
{
string_type result;
return convert(result,str,str_len,error,CodePage);
}//t_ansi_to_unicode::convert
////////////////////////////////////////////////////////////////////////////////
//inline implementation
inline std::wstring ansi_to_unicode(LPCSTR t,size_t n,bool* error,UINT CodePage)
{
typedef t_ansi_to_unicode<std::wstring> convertor_type;
return convertor_type::convert(t,n,error,CodePage);
}//ansi_to_unicode
inline std::wstring ansi_to_unicode(const std::string& t,bool* error,UINT CodePage)
{
typedef t_ansi_to_unicode<std::wstring> convertor_type;
return convertor_type::convert(t.c_str(),t.size(),error,CodePage);
}//ansi_to_unicode
inline std::wstring& ansi_to_unicode(std::wstring& result,LPCSTR t,size_t n,bool* error,UINT CodePage)
{
typedef t_ansi_to_unicode<std::wstring> convertor_type;
return convertor_type::convert(result,t,n,error,CodePage);
}//ansi_to_unicode
inline std::wstring& ansi_to_unicode(std::wstring& result,const std::string& t,bool* error,UINT CodePage)
{
typedef t_ansi_to_unicode<std::wstring> convertor_type;
return convertor_type::convert(result,t.c_str(),t.size(),error,CodePage);
}
////////////////////////////////////////////////////////////////////////////////
//struct t_unicode_to_ansi
template<class ansi_string>
struct t_unicode_to_ansi
{
typedef ansi_string string_type;
typedef typename string_type::value_type char_type;
//typedef t_void_allocator allocator_type;
//typedef t_typed_simple_buffer<char_type,allocator_type> buffer_type;
//convert 't' to 'result' and resurn 'result'
static string_type& convert(string_type& result,LPCWSTR t,size_t n=-1,bool* error=NULL,UINT CodePage=CP_ACP);
static string_type convert(LPCWSTR t,size_t n=-1,bool* error=NULL,UINT CodePage=CP_ACP);
};//struct t_unicode_to_ansi
////////////////////////////////////////////////////////////////////////////////
//template struct t_unicode_to_ansi
template<class ansi_string>
typename t_unicode_to_ansi<ansi_string>::string_type&
t_unicode_to_ansi<ansi_string>::convert(string_type& result,
LPCWSTR wstr,size_t wstr_len,bool* error,UINT CodePage)
{
if(error)
*error=false;
if(wstr==NULL || wstr_len==0)
return result.erase();
//åñëè wstr_len==-1, òî WCTMB ó÷èòûâàåò çàâåðøàþùèé íóëåâîé ñèìâîë
int alen=::WideCharToMultiByte(CodePage,0,wstr,(int)wstr_len,NULL,0,NULL,NULL);
assert(alen>=0);
if(alen==0 || (alen==1 && wstr_len==-1))//error èëè wstr==L""
{
if(error)
*error=GetLastError()?true:false;
return result.erase();
}
//TODO: Çäåñü ïðåäïîëàãàåòñÿ, ÷òî äëÿ âñåõ ANSI êîäèðîâîê òåðìèíàëüíûé ñèìâîë
// çàíèìàåò 1 áàéò
if(wstr_len!=-1)
alen+=1;//ó÷èòûâàåì çàâåðøàþùèé ñèìâîë
assert(alen>1);//âåðíåì íå òîëüêî çàâåðøàþùèé ñèìâîë
//ðåçåðâèðóåì ìåñòî ïîä âñå ñèìâîëû (âêëþ÷àÿ è òåðìèíàëüíûé)
string_type::value_type *pbuf= new string_type::value_type[alen];
int rw=::WideCharToMultiByte(CodePage,0,wstr,(int)wstr_len,pbuf,alen,NULL,NULL);
result.erase();
result.append(pbuf, pbuf+rw);
delete[] pbuf;
//èñêëþ÷àåì òåðìèíàëüíûé ñèìâîë
//TODO: Óâåðåííîñòü îòíîñèòåëüíî îäíîãî áàéòà?
return result;//.erase(result.size()-1,1);
}//t_unicode_to_ansi::convert
template<class ansi_string>
typename t_unicode_to_ansi<ansi_string>::string_type
t_unicode_to_ansi<ansi_string>::convert(LPCWSTR wstr,size_t wstr_len,bool* error,UINT CodePage)
{
string_type result;
return convert(result,wstr,wstr_len,error,CodePage);
}//t_unicode_to_ansi::convert
//inline implementation --------------------------------------------------
inline std::string unicode_to_ansi(LPCWSTR t,size_t n,bool* error=NULL,UINT CodePage=CP_ACP)
{
typedef t_unicode_to_ansi<std::string> convertor_type;
return convertor_type::convert(t,n,error,CodePage);
}
inline std::string unicode_to_ansi(const std::wstring& t,bool* error=NULL,UINT CodePage=CP_ACP)
{
typedef t_unicode_to_ansi<std::string> convertor_type;
return convertor_type::convert(t.c_str(),t.size(),error,CodePage);
}
inline std::string& unicode_to_ansi(std::string& result,LPCWSTR t,size_t n,bool* error=NULL,UINT CodePage=CP_ACP)
{
typedef t_unicode_to_ansi<std::string> convertor_type;
return convertor_type::convert(result,t,n,error,CodePage);
}
inline std::string& unicode_to_ansi(std::string& result,const std::wstring& t,bool* error=NULL ,UINT CodePage=CP_ACP)
{
typedef t_unicode_to_ansi<std::string> convertor_type;
return convertor_type::convert(result,t.c_str(),t.size(),error,CodePage);
}
inline std::string tchar2ansi(kmt::unicode::tstring t,bool* error=NULL ,UINT CodePage=CP_ACP)
{
#ifndef _UNICODE
return unicode_to_ansi(t,error, CodePage);
#else
return t;
#endif //_UNICODE
}
////////////////////////////////////////////////////////////////////////////////
};//namespace conv
};//namespace kmt
#endif