/*
 * See the files COPYING and README for copyright information and how to reach
 * the author.
 *
 *  $Id: iconvwrapper.c,v 1.3 2006/09/16 18:33:36 lordjaxom Exp $
 */

#include "iconvwrapper.h"
#include <cerrno>
#include <sstream>

namespace iconvwrapper
{

	using namespace std;

	iconv::iconv( const string& from, const string& to ):
			m_descriptor( iconv_open( to.c_str(), from.c_str() ) ),
			m_valid( m_descriptor != iconv_t( -1 ) )
	{
	}

	iconv::~iconv()
	{
		if ( m_descriptor != iconv_t( -1 ) )
			iconv_close( m_descriptor );
	}

	void iconv::clear()
	{
		if ( m_descriptor == iconv_t( -1 ) )
			return;

		::iconv( m_descriptor, 0, 0, 0, 0 );
		m_valid = true;
	}

	std::string iconv::operator()( const string& text )
	{
		size_t inbytes = text.length();
		char* inbuf = strdup( text.c_str() );
		char* inpos = inbuf;
		char* outbuf = (char*) malloc( inbytes );
		ostringstream result;

		while ( inbytes > 0 ) {
			char* outpos = outbuf;
			size_t outbytes = text.length();

			if ( ::iconv( m_descriptor, &inpos, &inbytes, &outpos, &outbytes ) == (size_t) -1 && errno != E2BIG ) {
				m_valid = false;
				break;
			}

			result.write( outbuf, outpos - outbuf );
		}

		free(outbuf);
		free(inbuf);
		return result.str();
	}

}
