ximol/codecvt.cpp

Go to the documentation of this file.
00001 /*****************************************************************************\
00002  *                                                                           *
00003  * library XiMoL                                                             *
00004  * Copyright (C) 2002, 2003, 2004 Florent Tournois                           *
00005  *                                                                           *
00006  * This library is free software; you can redistribute it and/or             *
00007  * modify it under the terms of the GNU Lesser General Public                *
00008  * License as published by the Free Software Foundation; either              *
00009  * version 2.1 of the License, or (at your option) any later version.        *
00010  *                                                                           *
00011  * This library is distributed in the hope that it will be useful,           *
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of            *
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU         *
00014  * Lesser General Public License for more details.                           *
00015  *                                                                           *
00016  * You should have received a copy of the GNU Lesser General Public          *
00017  * License along with this library; if not, write to the Free Software       *
00018  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA   *
00019  *                                                                           *
00020 \*****************************************************************************/
00021 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00022 /** \file 
00023         \brief Facet access (implementation).
00024 
00025         \author Tournois Florent
00026         \version 1.0
00027 
00028     $Id: codecvt.cpp,v 1.6 2004/02/25 18:58:39 tournois Exp $
00029     $Log: codecvt.cpp,v $
00030     Revision 1.6  2004/02/25 18:58:39  tournois
00031     imporve the gcc compatibility.
00032 
00033     Revision 1.5  2004/02/22 10:27:32  tournois
00034     Add some doc.
00035 
00036     Revision 1.4  2004/02/22 09:54:19  tournois
00037     Change years on the copyright.
00038 
00039     Revision 1.3  2003/11/16 13:25:25  tournois
00040     Change the error to use wide string.
00041     Change the translation to use wide string.
00042 
00043     Revision 1.2  2003/11/02 19:23:01  tournois
00044     Go to the boost coding standard.
00045     Change all name to lower case.
00046 
00047     Revision 1.1  2003/10/25 18:20:32  hfp
00048     XiMoL now provides a own codecvt (interface) based on standard.
00049     Hides use of iconv-library as implementation detail.
00050 
00051     Revision 1.6  2003/10/25 13:53:39  hfp
00052     review and separation
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 // nested types (private)
00068 ///////////////////////////////////////////////////////////////////////////////
00069 
00070 struct codecvt_state { // not exported
00071         iconv_t conv_in_out;
00072         iconv_t conv_out_in;
00073 };
00074 
00075 
00076 ///////////////////////////////////////////////////////////////////////////////
00077 // constructor(s) & destructor
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) // exception safety
00083 {
00084         p_internal_state_ = new codecvt_state; // should be created before create_encoding
00085 
00086         create_encoding(encoding_name);
00087 }
00088 
00089 ///////////////////////////////////////////////////////////////////////////////
00090 
00091 codecvt::~codecvt()
00092 {
00093         delete_encoding();
00094 
00095         delete p_internal_state_; // should be delete after delete_encoding
00096 }
00097 
00098 
00099 ///////////////////////////////////////////////////////////////////////////////
00100 // methods (public)
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


Donate to the XiMoL project SourceForge.net Logo If you have any questions about XiMoL, you could write to tournois@users.sourceforge.net.