Re: From ANSI to Unicode
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 30.04.03 06:22
Оценка: 39 (5)
Здравствуйте, INsideR, Вы писали:

INR>Как преобразовать строку char * в её эквивалент на Unicode, не используя #define _UNICODE. И в каком типе данных можно хранить unicode строку? Есть ли классы для работы с Unicode строками, типа CString?


Насчет классов — std::wstring.
Насчет преобразования, см. ansi_to_unicode и unicode_to_ansi

////////////////////////////////////////////////////////////////////////////////
//Implementation of conversion utility from <t_char.h>
//                                           Dmitry Kovalenko. 19 august,2002.
#ifndef _t_char_converter_CC_
#define _t_char_converter_CC_

#include <structure/t_memory.h>

namespace structure{
////////////////////////////////////////////////////////////////////////////////
//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>
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();

#ifndef NDEBUG
 if(str_len!=-1)
  CHECK_READ_PTR((LPSTR)str,sizeof(CHAR)*str_len);
#endif

 //если str_len==-1, то WCTMB учитывает завершающий нулевой символ
 int wlen=::MultiByteToWideChar(CodePage,0,str,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);//вернем не только завершающий символ

 //резервируем место под все символы (включая и терминальный)
 result.resize(wlen);

 ::MultiByteToWideChar(CodePage,0,str,str_len,result.begin(),wlen);

 //удаляем терминальный UNICODE-символ
 return result.erase(result.size()-1,1);
}//t_ansi_to_unicode::convert (result...)

template<class unicode_string>
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 wstring ansi_to_unicode(LPCSTR t,size_t n,bool* error,UINT CodePage)
{
 typedef t_ansi_to_unicode<wstring> convertor_type;

 return convertor_type::convert(t,n,error,CodePage);
}//ansi_to_unicode

inline wstring ansi_to_unicode(const string& t,bool* error,UINT CodePage)
{
 typedef t_ansi_to_unicode<wstring> convertor_type;

 return convertor_type::convert(t.c_str(),t.size(),error,CodePage);
}//ansi_to_unicode

inline wstring& ansi_to_unicode(wstring& result,LPCSTR t,size_t n,bool* error,UINT CodePage)
{
 typedef t_ansi_to_unicode<wstring> convertor_type;

 return convertor_type::convert(result,t,n,error,CodePage);
}//ansi_to_unicode

inline wstring& ansi_to_unicode(wstring& result,const string& t,bool* error,UINT CodePage)
{
 typedef t_ansi_to_unicode<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>
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();

#ifndef NDEBUG
 if(wstr_len!=-1)
  CHECK_READ_PTR((LPWSTR)wstr,sizeof(WCHAR)*wstr_len);
#endif

 //если wstr_len==-1, то WCTMB учитывает завершающий нулевой символ
 int alen=::WideCharToMultiByte(CodePage,0,wstr,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);//вернем не только завершающий символ

 //резервируем место под все символы (включая и терминальный)
 result.resize(alen);

 ::WideCharToMultiByte(CodePage,0,wstr,wstr_len,result.begin(),alen,NULL,NULL);

 //исключаем терминальный символ
 //TODO: Уверенность относительно одного байта?
 return result.erase(result.size()-1,1);
}//t_unicode_to_ansi::convert

template<class ansi_string>
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 string unicode_to_ansi(LPCWSTR t,size_t n,bool* error,UINT CodePage)
{
 typedef t_unicode_to_ansi<string> convertor_type;

 return convertor_type::convert(t,n,error,CodePage);
}

inline string unicode_to_ansi(const wstring& t,bool* error,UINT CodePage)
{
 typedef t_unicode_to_ansi<string> convertor_type;

 return convertor_type::convert(t.c_str(),t.size(),error,CodePage);
}

inline string& unicode_to_ansi(string& result,LPCWSTR t,size_t n,bool* error,UINT CodePage)
{
 typedef t_unicode_to_ansi<string> convertor_type;

 return convertor_type::convert(result,t,n,error,CodePage);
}

inline string& unicode_to_ansi(string& result,const wstring& t,bool* error,UINT CodePage)
{
 typedef t_unicode_to_ansi<string> convertor_type;

 return convertor_type::convert(result,t.c_str(),t.size(),error,CodePage);
}

////////////////////////////////////////////////////////////////////////////////
};//namespace structure
#endif
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.