iconv.cc

Go to the documentation of this file.
00001 ///
00002 /// \file       iconv.cc
00003 ///             iconv wrapper class, and pluggable interface for records
00004 ///
00005 
00006 /*
00007     Copyright (C) 2008-2009, Net Direct Inc. (http://www.netdirect.ca/)
00008 
00009     This program is free software; you can redistribute it and/or modify
00010     it under the terms of the GNU General Public License as published by
00011     the Free Software Foundation; either version 2 of the License, or
00012     (at your option) any later version.
00013 
00014     This program is distributed in the hope that it will be useful,
00015     but WITHOUT ANY WARRANTY; without even the implied warranty of
00016     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00017 
00018     See the GNU General Public License in the COPYING file at the
00019     root directory of this project for more details.
00020 */
00021 
00022 #include "iconv.h"
00023 #include "common.h"
00024 #include "error.h"
00025 #include <errno.h>
00026 
00027 namespace Barry {
00028 
00029 IConverter::IConverter(const char *tocode, bool throw_on_conv_err)
00030         : m_throw_on_conv_err(throw_on_conv_err)
00031 {
00032         m_from = iconv_open(tocode, BLACKBERRY_CHARSET);
00033         if( m_from == (iconv_t)(-1) ) {
00034                 throw ErrnoError("iconv_open failed (from)", errno);
00035         }
00036 
00037         m_to = iconv_open(BLACKBERRY_CHARSET, tocode);
00038         if( m_to == (iconv_t)(-1) ) {
00039                 ErrnoError err("iconv_open failed (to)", errno);
00040                 iconv_close(m_from);
00041                 throw err;
00042         }
00043 }
00044 
00045 IConverter::~IConverter()
00046 {
00047         iconv_close(m_from);
00048         iconv_close(m_to);
00049 }
00050 
00051 std::string IConverter::Convert(iconv_t cd, const std::string &str) const
00052 {
00053         size_t target = str.size() * 2;
00054         char *out = 0, *outstart = 0;
00055         size_t outbytesleft = 0;
00056         std::string ret;
00057 
00058         // this loop is for the very odd case that the output string
00059         // needs more than twice the input size
00060         for( int tries = 0; ; tries++ ) {
00061 
00062                 const char *in = str.data();
00063                 size_t inbytesleft = str.size();
00064                 out = outstart = (char*) m_buffer.GetBuffer(target);
00065                 outbytesleft = m_buffer.GetBufSize();
00066 
00067                 iconv(cd, NULL, NULL, NULL, NULL);      // reset cd's state
00068                 size_t status = iconv(cd, (char**)&in, &inbytesleft, &out, &outbytesleft);
00069 
00070                 if( status == (size_t)(-1) ) {
00071                         if( errno == E2BIG && tries < 2 ) {
00072                                 target += inbytesleft * 2;
00073                                 // try again with more memory...
00074                                 continue;
00075                         }
00076 
00077                         // should never happen :-)
00078                         // but if it does, and we get here, check
00079                         // whether the user wants to be notified by
00080                         // exception... if not, just fall through and
00081                         // store as much converted data as possible
00082                         if( m_throw_on_conv_err ) {
00083                                 throw ErrnoError("iconv failed", errno);
00084                         }
00085                 }
00086                 else {
00087                         // success
00088                         break;
00089                 }
00090         }
00091 
00092         // store any available converted data
00093         ret.assign(outstart, out - outstart);
00094         return ret;
00095 }
00096 
00097 std::string IConverter::FromBB(const std::string &str) const
00098 {
00099         return Convert(m_from, str);
00100 }
00101 
00102 std::string IConverter::ToBB(const std::string &str) const
00103 {
00104         return Convert(m_to, str);
00105 }
00106 
00107 } // namespace Barry
00108 

Generated on Mon Jan 12 10:51:12 2009 for Barry by  doxygen 1.5.7.1