2 // Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
4 // Distributed under the Boost Software License, Version 1.0. (See
5 // accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt)
8 #ifndef BOOST_LOCALE_IMPL_ICONV_CODEPAGE_HPP
9 #define BOOST_LOCALE_IMPL_ICONV_CODEPAGE_HPP
11 #include <boost/locale/encoding.hpp>
12 #include "../util/iconv.hpp"
23 class iconverter_base {
36 size_t conv(char const **inbufc,size_t *inchar_left,
37 char **outbuf,size_t *outchar_left)
39 char **inbuf = const_cast<char **>(inbufc);
40 return call_iconv(cvt_,inbuf,inchar_left,outbuf,outchar_left);
43 bool do_open(char const *to,char const *from,method_type how)
46 cvt_ = iconv_open(to,from);
48 return cvt_ != (iconv_t)(-1);
51 template<typename OutChar,typename InChar>
52 std::basic_string<OutChar> real_convert(InChar const *ubegin,InChar const *uend)
54 std::basic_string<OutChar> sresult;
56 sresult.reserve(uend - ubegin);
60 char *out_start = reinterpret_cast<char *>(&result[0]);
61 char const *begin = reinterpret_cast<char const *>(ubegin);
62 char const *end = reinterpret_cast<char const *>(uend);
64 enum { normal , unshifting , done } state = normal;
68 size_t in_left = end - begin;
69 size_t out_left = sizeof(result);
71 char *out_ptr = out_start;
77 res = conv(&begin,&in_left,&out_ptr,&out_left);
79 res = conv(0,0,&out_ptr,&out_left);
83 size_t output_count = (out_ptr - out_start) / sizeof(OutChar);
85 if(res!=0 && res!=(size_t)(-1)) {
87 throw conversion_error();
91 sresult.append(&result[0],output_count);
93 if(res == (size_t)(-1)) {
94 if(err == EILSEQ || err == EINVAL) {
96 throw conversion_error();
100 begin+=sizeof(InChar);
108 else if (err==E2BIG) {
112 // We should never get there
115 throw conversion_error();
120 if(state == unshifting)
131 if(cvt_!=(iconv_t)(-1)) {
133 cvt_ = (iconv_t)(-1);
143 template<typename CharType>
144 class iconv_from_utf : public converter_from_utf<CharType>
148 typedef CharType char_type;
150 virtual bool open(char const *charset,method_type how)
152 return self_.do_open(charset,utf_name<CharType>(),how);
155 virtual std::string convert(char_type const *ubegin,char_type const *uend)
157 return self_.template real_convert<char,char_type>(ubegin,uend);
159 virtual ~iconv_from_utf() {}
161 iconverter_base self_;
164 class iconv_between: public converter_between
167 virtual bool open(char const *to_charset,char const *from_charset,method_type how)
169 return self_.do_open(to_charset,from_charset,how);
171 virtual std::string convert(char const *begin,char const *end)
173 return self_.real_convert<char,char>(begin,end);
175 virtual ~iconv_between() {}
177 iconverter_base self_;
181 template<typename CharType>
182 class iconv_to_utf : public converter_to_utf<CharType>
186 typedef CharType char_type;
187 typedef std::basic_string<char_type> string_type;
189 virtual bool open(char const *charset,method_type how)
191 return self_.do_open(utf_name<CharType>(),charset,how);
194 virtual string_type convert(char const *begin,char const *end)
196 return self_.template real_convert<char_type,char>(begin,end);
198 virtual ~iconv_to_utf() {}
200 iconverter_base self_;
214 // vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4