35 ConvertImp(
const std::string & to_code ,
const std::string & from_code ) ;
37 std::string narrow(
const std::wstring & s ,
const std::string & context ) ;
38 std::wstring widen(
const std::string & s ,
const std::string & context ) ;
48 static std::wstring to_wstring(
const std::vector<char> & ) ;
49 static void from_wstring( std::vector<char> & ,
const std::wstring & ) ;
50 static size_t call(
size_t (*fn)(iconv_t,
const char**,
size_t*,
char**,
size_t*) ,
51 iconv_t m ,
const char ** inbuf ,
size_t * inbytesleft ,
52 char ** outbuf ,
size_t * outbytesleft ) ;
53 static size_t call(
size_t (*fn)(iconv_t,
char**,
size_t*,
char**,
size_t*) ,
54 iconv_t m ,
const char ** inbuf ,
size_t * inbytesleft ,
55 char ** outbuf ,
size_t * outbytesleft ) ;
61 G::ConvertImp::ConvertImp(
const std::string & to_code ,
const std::string & from_code )
63 m = ::iconv_open( to_code.c_str() , from_code.c_str() ) ;
64 if( m == reinterpret_cast<iconv_t>(-1) )
65 throw G::Convert::Error(
"iconv_open failed for " + from_code +
" -> " + to_code ) ;
68 G::ConvertImp::~ConvertImp()
73 void G::ConvertImp::reset()
75 ::iconv( m ,
nullptr ,
nullptr ,
nullptr ,
nullptr ) ;
78 size_t G::ConvertImp::call(
size_t (*fn)(iconv_t,
const char**,
size_t*,
char**,
size_t*) ,
79 iconv_t m ,
const char ** inbuf ,
size_t * inbytesleft ,
80 char ** outbuf ,
size_t * outbytesleft )
82 return (*fn)( m , inbuf , inbytesleft , outbuf , outbytesleft ) ;
85 size_t G::ConvertImp::call(
size_t (*fn)(iconv_t,
char**,
size_t*,
char**,
size_t*) ,
86 iconv_t m ,
const char ** inbuf ,
size_t * inbytesleft ,
87 char ** outbuf ,
size_t * outbytesleft )
89 char * p =
const_cast<char*
>(*inbuf) ;
90 size_t rc = (*fn)( m , &p , inbytesleft , outbuf , outbytesleft ) ;
95 std::wstring G::ConvertImp::widen(
const std::string & s ,
const std::string & context )
100 const char * in_p_end = s.data() + s.length() ;
101 const char * in_p_start = s.data() ;
102 size_t in_n_start = s.size() ;
103 const char * in_p = in_p_start ;
104 size_t in_n = in_n_start ;
107 std::vector<char> out_buffer( 10U + s.size()*4U ) ;
108 char * out_p_start = &out_buffer[0] ;
109 size_t out_n_start = out_buffer.size() ;
110 char * out_p = out_p_start ;
111 size_t out_n = out_n_start ;
115 size_t rc = call( ::iconv , m , &in_p , &in_n , &out_p , &out_n ) ;
116 const size_t e =
static_cast<size_t>(ssize_t(-1)) ;
117 if( rc == e || in_p != in_p_end || out_n > out_n_start )
118 throw G::Convert::Error(
"iconv failed" + std::string(context.empty()?
"":
": ") + context ) ;
121 out_buffer.resize( out_n_start - out_n ) ;
122 return to_wstring( out_buffer ) ;
125 std::string G::ConvertImp::narrow(
const std::wstring & s ,
const std::string & context )
130 std::vector<char> in_buffer ;
131 from_wstring( in_buffer , s ) ;
132 const char * in_p_end = &in_buffer[0] + in_buffer.size() ;
133 const char * in_p_start = &in_buffer[0] ;
134 size_t in_n_start = in_buffer.size() ;
135 const char * in_p = in_p_start ;
136 size_t in_n = in_n_start ;
139 std::vector<char> out_buffer( 10U + in_buffer.size()*4U ) ;
140 char * out_p_start = &out_buffer[0] ;
141 size_t out_n_start = out_buffer.size() ;
142 char * out_p = out_p_start ;
143 size_t out_n = out_n_start ;
147 size_t rc = call( ::iconv , m , &in_p , &in_n , &out_p , &out_n ) ;
148 const size_t e =
static_cast<size_t>(ssize_t(-1)) ;
149 if( rc == e || in_p != in_p_end || out_n > out_n_start )
150 throw G::Convert::Error(
"iconv failed" + std::string(context.empty()?
"":
": ") + context ) ;
153 return std::string( &out_buffer[0] , &out_buffer[0] + (out_n_start-out_n) ) ;
156 void G::ConvertImp::from_wstring( std::vector<char> & buffer ,
const std::wstring & s )
159 buffer.reserve( s.size() + 2U ) ;
160 buffer.push_back( 0xff ) ;
161 buffer.push_back( 0xfe ) ;
162 for(
size_t i = 0U ; i < s.size() ; i++ )
164 unsigned int n = s.at(i) ;
165 buffer.push_back( n & 0xff ) ;
166 buffer.push_back( n >> 8U ) ;
170 std::wstring G::ConvertImp::to_wstring(
const std::vector<char> & buffer )
173 std::wstring result ;
174 result.reserve( buffer.size() ) ;
175 const unsigned char * p =
reinterpret_cast<const unsigned char*
>(&buffer[0]) ;
176 const unsigned char * end = p + buffer.size() ;
177 bool bom_ff_fe = buffer.size() >= 2U && p[0] == 0xff && p[1] == 0xfe ;
178 bool bom_fe_ff = buffer.size() >= 2U && p[0] == 0xfe && p[1] == 0xff ;
179 if( bom_ff_fe || bom_fe_ff ) p += 2 ;
180 int hi = bom_fe_ff ? 0 : 1 ;
181 int lo = bom_fe_ff ? 1 : 0 ;
182 for( ; (p+1) < end ; p += 2 )
184 wchar_t w =
static_cast<wchar_t>( (
static_cast<unsigned int>(p[hi]) << 8 ) | p[lo] ) ;
185 result.append( 1U , w ) ;
192 static ConvertImp c(
"UTF-8" ,
"UTF-16" ) ;
198 static ConvertImp c(
"ISO-8859-15" ,
"UTF-16" ) ;
204 static ConvertImp c(
"UTF-16" ,
"UTF-8" ) ;
210 static ConvertImp c(
"UTF-16" ,
"ISO-8859-15" ) ;
216 std::wstring G::Convert::widen(
const std::string & s ,
bool utf8 ,
const std::string & context )
220 return std::wstring() ;
224 return ConvertImp::utf8_to_utf16().widen( s , context ) ;
228 return ConvertImp::ansi_to_utf16().widen( s , context ) ;
232 std::string G::Convert::narrow(
const std::wstring & s ,
bool utf8 ,
const std::string & context )
236 return std::string() ;
240 return ConvertImp::utf16_to_utf8().narrow( s , context ) ;
244 return ConvertImp::utf16_to_ansi().narrow( s , context ) ;
A pimple-pattern implementation class for G::Convert.