iconv 转换字符编码,兼容VC转换

#ifndef __CHAR_CONVERT_H__
#define __CHAR_CONVERT_H__

#ifdef OS_WINDOWS

#include <SDKDDKVer.h> //"targetver.h"

#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN             //  从 Windows 头文件中排除极少使用的信息
#endif

// Windows 头文件:
#include <windows.h>

#else // Linux
#include "iconv.h"

#ifndef ICONV_BUFFER_SIZE
#define ICONV_BUFFER_SIZE 1024
#endif

#define WCHAR wchar_t
#ifdef _UNICODE
#define TCHAR wchar_t
#else
#define TCHAR char
#endif

#endif
/
#define E_CHAR      CWCharToChar::EChar
#define E_WCHAR     CWCharToChar::EWChar
#define E_UTF8      CWCharToChar::EUtf8

#define NULL_STR    CWCharToChar::GetNullStr()

static char g_NULL[2] = {0};

/
// 简单的wchar_t 和 char 转换类, 且包含与UTF8的转换
class CWCharToChar
{
public:
    enum
    {
        EChar  = 1,
        EWChar = 2,
        EUtf8  = 4
    };

private:
    char    *   m_cDest;
    wchar_t *   m_wcDest;
    char    *   m_cUtf8;

    unsigned int m_nSrcType;

public:
    char    *   Char(void) { return m_cDest; }
    wchar_t *   WChar(void){ return m_wcDest; }

    bool        IsNullChar(void)  { return ( !m_cDest  || g_NULL == m_cDest ); }
    bool        IsNullWChar(void) { return ( !m_wcDest || g_NULL == (char*)m_wcDest ); }

#if defined( _UTF8_ )
    char    *   UTF8(void) { return m_cUtf8; }
    bool        IsNullUTF8(void) { return ( !m_cUtf8   || g_NULL == m_cUtf8 ); }
#endif

    TCHAR   *   TChar(void)
    {
#ifdef _UNICODE
        return WChar();
#else
        return Char();
#endif
    }
    
    // ANSI/GBK 转 Unicode和UTF8的构造函数

    CWCharToChar(const char* psrc, unsigned int nSrcType = EChar
#if defined( _UTF8_ )
                , unsigned int nDestType = EUtf8)
#else
                , unsigned int nDestType = EWChar)
#endif
        : m_cDest(NULL)
        , m_wcDest(NULL)
        , m_cUtf8(NULL)
        , m_nSrcType(nSrcType)
    {
        // 防止空指针
        if( !psrc ) return;
        if( !*psrc )  // 如果是空字符串,也返回空字符串
        {
            if( EChar == m_nSrcType ) m_cDest = (char*)psrc;
            if( EUtf8 == m_nSrcType ) m_cUtf8 = (char*)psrc;

            if( nDestType & EChar )  m_cDest  = g_NULL;
            if( nDestType & EUtf8 )  m_cUtf8  = g_NULL;
            if( nDestType & EWChar ) m_wcDest = (wchar_t*)g_NULL;

            return;
        }

#ifdef OS_WINDOWS
        if( EChar == m_nSrcType )
        {
            m_cDest = (char*)psrc;

#if defined( _UTF8_ )
            int nLen = MultiByteToWideChar (CP_ACP, 0, m_cDest, -1, NULL, 0);
            m_wcDest = new wchar_t[nLen];
            MultiByteToWideChar (CP_ACP, 0, m_cDest, -1, m_wcDest, nLen);

            nLen = WideCharToMultiByte(CP_UTF8, 0, m_wcDest, -1, NULL, 0, NULL, NULL);
            m_cUtf8 = new char[nLen + 1];
            WideCharToMultiByte (CP_UTF8, 0, m_wcDest, -1, m_cUtf8, nLen, NULL,NULL);
#else
            int nLen = MultiByteToWideChar (CP_ACP, 0, m_cDest, -1, NULL, 0);
            m_wcDest = new wchar_t[nLen];
            MultiByteToWideChar (CP_ACP, 0, m_cDest, -1, m_wcDest, nLen);
#endif
        }
        else if( EUtf8 == m_nSrcType )
        {
            m_cUtf8 = (char*)psrc;

            int nLen = MultiByteToWideChar(CP_UTF8, 0, m_cUtf8, -1, NULL,0);
            m_wcDest = new wchar_t[nLen+1];
            MultiByteToWideChar(CP_UTF8, 0, m_cUtf8, -1, m_wcDest, nLen);

            nLen = WideCharToMultiByte(CP_ACP, 0, m_wcDest, -1, NULL, 0, NULL, NULL);
            m_cDest = new char[nLen + 1];
            WideCharToMultiByte(CP_ACP, 0, m_wcDest, -1, m_cDest, nLen, NULL,NULL);
        }
#else // Linux
        if( EChar == m_nSrcType )
        {
            m_cDest = (char*)psrc;
            if( nDestType & EUtf8 )
                do_iconv_convert(psrc, &m_cUtf8, "GBK", "UTF-8");

            if( nDestType & EWChar)
                do_iconv_convert(psrc, (char**)&m_wcDest, "GBK", "wchar_t");
        }
        else if( EUtf8 == m_nSrcType )
        {
            m_cUtf8 = (char*)psrc;
            if( nDestType & EChar)
                do_iconv_convert(psrc, &m_cDest, "UTF-8", "GBK");

            if( nDestType & EWChar)
                do_iconv_convert(psrc, (char**)&m_wcDest, "UTF-8", "wchar_t");
        }
#endif
    }
    
    // Unicode 转 ANSI/GBK和UTF8的构造函数

    CWCharToChar(const wchar_t * psrc
#if defined( _UTF8_ )
                , unsigned int nDestType = EUtf8)
#else
                , unsigned int nDestType = EChar)
#endif
        : m_cDest(NULL)
        , m_wcDest(NULL)
        , m_cUtf8(NULL)
        , m_nSrcType(EWChar)
    {
        char * p = (char*)psrc;
        if( !p ) return ;

        m_wcDest = (wchar_t*)psrc;
        if( 0 == *p && 0 == *(p+1) ) // 如果是空字符串,也返回空字符串
        {
            if( nDestType & EChar )  m_cDest  = g_NULL;
            if( nDestType & EUtf8 )  m_cUtf8  = g_NULL;

            return;
        }

#ifdef OS_WINDOWS
        // ANSI/GBK
        {
            int nLen = WideCharToMultiByte(CP_OEMCP,NULL, m_wcDest,-1,NULL,0,NULL,FALSE);
            m_cDest = new char[nLen];
            WideCharToMultiByte (CP_OEMCP,NULL,m_wcDest,-1, m_cDest, nLen,NULL,FALSE);
        }

#if defined( _UTF8_ )
        {
            int nLen = WideCharToMultiByte(CP_UTF8, 0, m_wcDest, -1, NULL, 0, NULL, NULL);
            m_cUtf8 = new char[nLen + 1];
            WideCharToMultiByte (CP_UTF8, 0, m_wcDest, -1, m_cUtf8, nLen, NULL,NULL);
        }
#endif
#else  // Linux

        if( nDestType & EChar)
            do_iconv_convert((char*)psrc, &m_cDest, "wchar_t", "GBK");

        if( nDestType & EUtf8)
            do_iconv_convert((char*)psrc, (char**)&m_cUtf8, "wchar_t", "UTF-8");
#endif
    }

    
    ~CWCharToChar()
    {
        if( EChar == m_nSrcType )
        {
            if( m_wcDest && g_NULL != (char*)m_wcDest )   delete [] m_wcDest;
            if( m_cUtf8  && g_NULL != m_cUtf8 )           delete [] m_cUtf8;
        }
        else if( EWChar == m_nSrcType )
        {
            if( m_cDest && g_NULL != m_cDest)             delete [] m_cDest;
            if( m_cUtf8 && g_NULL != m_cUtf8)             delete [] m_cUtf8;
        }
        else if( EUtf8 == m_nSrcType )
        {
            if( m_cDest  && g_NULL != m_cDest)            delete [] m_cDest;
            if( m_wcDest && g_NULL != (char*)m_wcDest )   delete [] m_wcDest;
        }
    }

    
    // Using iconv  for Linux
#ifndef OS_WINDOWS

    int  do_iconv_convert(const char* pSrc, char**ppOut, const char* pszFromCode, const char* pszToCode)
    {
        iconv_t cd = iconv_open(pszToCode, pszFromCode);
        if(cd == (iconv_t)(-1))
        {
            printf("iconv_open failed, errno: %d - %s\n", errno, strerror(errno));
            *ppOut = g_NULL;  // 为了防止给std::string赋值抛异常而导致程序终止
            return -1;
        }
        iconv(cd, NULL, NULL, NULL, NULL);

        size_t nSLen = 0, nOLen = 0;
        if( m_nSrcType == EWChar )
#ifdef OS_WINDOWS
            nSLen = wcslen((wchar_t*)pSrc) * 2;  // 乘以2,转换成char的长度
#else  // Linux
            nSLen = wcslen((wchar_t*)pSrc) * 4;  // for Unicode -> GBK/UTF8, Linux 乘以4
#endif
        else
            nSLen = strlen(pSrc);

        if( 0 == strcmp( pszToCode, "wchar_t"))
            nOLen = nSLen * 4;        // for GBK -> Unicode
        else
            nOLen = nSLen * 2;

        size_t nORawLen = nOLen;
        char* pOut = new char[nOLen+4];
        char* pOutStart = pOut;

        char ** ppin = (char**)&pSrc;
        char ** ppout = &pOut;
#ifdef _DEBUG
        printf("Convert: %s[%lu] -> %s[%lu] bytes\n", pszFromCode, nSLen, pszToCode, nOLen);
#endif
        size_t ret = iconv(cd, (char**)ppin, &nSLen, (char**)ppout, &nOLen);
        if( 0 == ret )  // 转换完成成功
        {
            iconv_close(cd);
            int nOutLen = nORawLen - nOLen;
            *(pOutStart + nOutLen) = 0;
            *(pOutStart + nOutLen + 1) = 0; // 给转换Unicode之用
            *ppOut = pOutStart;

            return nOutLen;
        }
        else  // 全部或部分错误
        {
            printf("iconv failed, errno: %d - %s\n", errno, strerror(errno));
            iconv_close(cd);
            delete [] pOutStart;
            *ppOut = g_NULL;  // 为了防止给std::string赋值抛异常而导致程序终止
            return -1;
        }
    }

#endif

    static const char* GetNullStr(void){ return g_NULL; }
};

#endif //__CHAR_CONVERT_H__

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值