00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057 #include <ximol/codecvt.hpp>
00058 #include <ximol/encoders/error.hpp>
00059 #include <ximol/translation.hpp>
00060 #include <ximol/macros.hpp>
00061
00062 #include <iconv.h>
00063
00064
00065 XIMOL_BEGIN_NAMESPACE
00066
00067
00068
00069
00070 struct codecvt_state {
00071 iconv_t conv_in_out;
00072 iconv_t conv_out_in;
00073 };
00074
00075
00076
00077
00078
00079
00080 codecvt::codecvt(const ::std::string& encoding_name, size_t refs)
00081 : ::std::codecvt<xchar_t, char, mbstate_t>(refs)
00082 , p_internal_state_(NULL)
00083 {
00084 p_internal_state_ = new codecvt_state;
00085
00086 create_encoding(encoding_name);
00087 }
00088
00089
00090
00091 codecvt::~codecvt()
00092 {
00093 delete_encoding();
00094
00095 delete p_internal_state_;
00096 }
00097
00098
00099
00100
00101
00102
00103 void codecvt::create_encoding(const ::std::string& encoding_name)
00104 {
00105 ::std::string const strIntern(sizeof(xchar_t) == 2
00106 ? "UCS-2-INTERNAL"
00107 : "UCS-4-INTERNAL");
00108
00109 p_internal_state_->conv_in_out = iconv_open(encoding_name.c_str(), strIntern.c_str());
00110 if (p_internal_state_->conv_in_out == (iconv_t)-1)
00111 XIMOL_ENCODERS_THROW
00112 << _(L"Encoding '%o' not found. ", encoding_name)
00113 << XIMOL_ENCODERS_AS_ERROR;
00114
00115 p_internal_state_->conv_out_in = iconv_open(strIntern.c_str(), encoding_name.c_str());
00116 if (p_internal_state_->conv_out_in == (iconv_t)-1) XIMOL_ENCODERS_THROW
00117 << _(L"Encoding '%o' not found. ", encoding_name)
00118 << XIMOL_ENCODERS_AS_ERROR;
00119 }
00120
00121
00122
00123 void codecvt::delete_encoding()
00124 {
00125 iconv_close(p_internal_state_->conv_in_out);
00126 iconv_close(p_internal_state_->conv_out_in);
00127 }
00128
00129
00130
00131 codecvt::result codecvt::do_out(state_type& state,
00132 const intern_type* from,
00133 const intern_type* from_end,
00134 const intern_type*& from_next,
00135 extern_type* to,
00136 extern_type* to_limit,
00137 extern_type*& to_next) const
00138 {
00139 to_next=to;
00140 from_next=from;
00141 size_t inbuf=from_end-from_next;
00142 inbuf*=sizeof(intern_type);
00143 size_t outbuf=to_limit-to_next;
00144 outbuf*=sizeof(extern_type);
00145
00146 size_t init_inbuf=inbuf, init_outbuf=outbuf;
00147
00148 typedef const char** from_next_type;
00149
00150 size_t result = iconv(p_internal_state_->conv_in_out,(from_next_type)(&from_next),&inbuf,(char**)(&to_next),&outbuf);
00151
00152 if ( (inbuf==init_inbuf)
00153 ||(outbuf==init_outbuf))
00154 {
00155 from_next = from;
00156 to_next = to;
00157 return partial;
00158 }
00159
00160 if (result==(size_t)(-1))
00161 {
00162 from_next = from;
00163 to_next = to;
00164 if (errno==EINVAL) return partial;
00165 if (errno==EILSEQ) return error;
00166 if (errno==E2BIG) return partial;
00167 return error;
00168 }
00169
00170 return ok;
00171 }
00172
00173
00174
00175 codecvt::result codecvt::do_in(state_type& state,
00176 const extern_type* from,
00177 const extern_type* from_end,
00178 const extern_type*& from_next,
00179 intern_type* to,
00180 intern_type* to_limit,
00181 intern_type*& to_next) const
00182 {
00183 to_next=to;
00184 from_next=from;
00185 size_t inbuf=from_end-from_next;
00186 inbuf*=sizeof(extern_type);
00187 size_t outbuf=to_limit-to_next;
00188 outbuf*=sizeof(intern_type);
00189
00190 size_t init_inbuf=inbuf, init_outbuf=outbuf;
00191
00192 typedef const char** from_next_type;
00193
00194 size_t result = iconv(p_internal_state_->conv_out_in,(from_next_type)(&from_next),&inbuf,(char**)(&to_next),&outbuf);
00195
00196 if ( (inbuf==init_inbuf)
00197 ||(outbuf==init_outbuf))
00198 {
00199 from_next = from;
00200 to_next = to;
00201 return partial;
00202 }
00203
00204 if (result==(size_t)(-1))
00205 {
00206 from_next = from;
00207 to_next = to;
00208 if (errno==EINVAL) return partial;
00209 if (errno==EILSEQ) return error;
00210 if (errno==E2BIG) return partial;
00211 return error;
00212 }
00213
00214 return ok;
00215 }
00216
00217
00218
00219 codecvt::result codecvt::do_unshift(state_type& state,
00220 extern_type* to,
00221 extern_type* to_limit,
00222 extern_type*& to_next) const
00223 {
00224 to_next = to;
00225 return noconv;
00226 }
00227
00228
00229
00230 int codecvt::do_encoding() const throw()
00231 {
00232 return 0;
00233 }
00234
00235
00236
00237 bool codecvt::do_always_noconv() const throw()
00238 {
00239 return false;
00240 }
00241
00242
00243
00244 int codecvt::do_length(const state_type& state,
00245 const extern_type* from,
00246 const extern_type* end,
00247 size_t max) const
00248 {
00249 return (int)XIMOL_MIN((size_t) (end - from), max);
00250 }
00251
00252
00253
00254 int codecvt::do_max_length() const throw()
00255 {
00256 return 6;
00257 }
00258
00259
00260 XIMOL_END_NAMESPACE