//---------------------------------------------------------------------------- // EgalTech 2013-2013 //---------------------------------------------------------------------------- // File : EgtStringConverter.h Data : 10.02.13 Versione : 1.3a1 // Contenuto : Insieme di classi per convertire stringhe tra vari formati. // // // // Modifiche : 10.02.13 DS Creazione modulo. // 15.03.14 DS Agg. classe wcharBuffer per buffer con Windows API. // // //---------------------------------------------------------------------------- #pragma once //----------------------------------------------------------------------------- #define NOMINMAX #include #include #include //----------------------------------------------------------------------------- // Funzioni ausiliarie //----------------------------------------------------------------------------- template inline void SmartAllocMemory( _CharType** ppBuff, int nLength, _CharType* pszFixedBuffer, int nFixedBufferLength) { // controlli if ( ppBuff == nullptr) return ; if ( nLength < 0 || pszFixedBuffer == nullptr) { *ppBuff = nullptr ; return ; } // se buffer già allocato, lo rialloco if ( *ppBuff != pszFixedBuffer) { if ( nLength > nFixedBufferLength) { *ppBuff = static_cast<_CharType*>( _recalloc( *ppBuff, nLength,sizeof( _CharType))) ; } else { free( *ppBuff) ; *ppBuff = pszFixedBuffer ; } } // altrimenti buffer non già allocato else { if ( nLength > nFixedBufferLength) { *ppBuff = static_cast<_CharType*>( calloc( nLength, sizeof( _CharType))) ; } else { *ppBuff = pszFixedBuffer ; } } } //----------------------------------------------------------------------------- template inline void SmartFreeMemory( _CharType* pBuff, _CharType* pszFixedBuffer, int nFixedBufferLength) { if ( pBuff != pszFixedBuffer) free( pBuff) ; #if defined( _DEBUG) else memset( pszFixedBuffer, 0xFE, nFixedBufferLength * sizeof(_CharType)) ; #endif } //----------------------------------------------------------------------------- inline bool IsTextUtf8( const char* psz) { // validità parametro if ( psz == nullptr) return false ; // ciclo sulla stringa const unsigned char* p = ( const unsigned char*) psz ; while ( *p != '\0') { // caratteri ASCII if ( 0x00 <= p[0] && p[0] <= 0x7F) p += 1 ; // 2 byte else if ( (0xC2 <= p[0] && p[0] <= 0xDF) && (0x80 <= p[1] && p[1] <= 0xBF) ) p += 2 ; // 3byte else if ( ( // escludo extralunghi p[0] == 0xE0 && ( 0xA0 <= p[1] && p[1] <= 0xBF) && ( 0x80 <= p[2] && p[2] <= 0xBF) ) || ( // normali (( 0xE1 <= p[0] && p[0] <= 0xEC) || p[0] == 0xEE || p[0] == 0xEF) && ( 0x80 <= p[1] && p[1] <= 0xBF) && ( 0x80 <= p[2] && p[2] <= 0xBF) ) || ( // escludo surrogati p[0] == 0xED && ( 0x80 <= p[1] && p[1] <= 0x9F) && ( 0x80 <= p[2] && p[2] <= 0xBF) ) ) p += 3 ; // 4byte else if ( ( // piani 1-3 p[0] == 0xF0 && ( 0x90 <= p[1] && p[1] <= 0xBF) && ( 0x80 <= p[2] && p[2] <= 0xBF) && ( 0x80 <= p[3] && p[3] <= 0xBF) ) || ( // piani 4-15 ( 0xF1 <= p[0] && p[0] <= 0xF3) && ( 0x80 <= p[1] && p[1] <= 0xBF) && ( 0x80 <= p[2] && p[2] <= 0xBF) && ( 0x80 <= p[3] && p[3] <= 0xBF) ) || ( // piano 16 p[0] == 0xF4 && ( 0x80 <= p[1] && p[1] <= 0x8F) && ( 0x80 <= p[2] && p[2] <= 0xBF) && ( 0x80 <= p[3] && p[3] <= 0xBF) ) ) p += 4 ; // non validi else return false ; } return true ; } //----------------------------------------------------------------------------- //! Classe per convertire stringhe A (char UTF-8) in stringhe W (wchar_t UTF-16) //----------------------------------------------------------------------------- template< int t_nBufferLength = 128> class AtoWEX { public : AtoWEX( const char* psz) : m_psz( m_szBuffer) { if ( IsTextUtf8( psz)) Init( psz, CP_UTF8) ; else Init( psz, CP_ACP) ; } AtoWEX( const char* psz, unsigned int nCodePage) : m_psz( m_szBuffer) { Init( psz, nCodePage) ; } ~AtoWEX( void) { SmartFreeMemory( m_psz, m_szBuffer, t_nBufferLength) ; } operator LPWSTR( void) { return ( m_psz) ; } private : void Init( const char* psz, unsigned int nCodePage) { if ( psz == nullptr) { m_psz = nullptr ; return ; } int nLengthA = lstrlenA( psz) + 1 ; int nLengthW = nLengthA ; SmartAllocMemory( &m_psz, nLengthW, m_szBuffer, t_nBufferLength) ; BOOL bFailed = ( MultiByteToWideChar( nCodePage, 0, psz, nLengthA, m_psz, nLengthW) == 0) ; if ( bFailed) { if ( GetLastError() == ERROR_INSUFFICIENT_BUFFER) { nLengthW = ::MultiByteToWideChar( nCodePage, 0, psz, nLengthA, nullptr, 0) ; SmartAllocMemory( &m_psz, nLengthW, m_szBuffer, t_nBufferLength) ; bFailed =( MultiByteToWideChar( nCodePage, 0, psz, nLengthA, m_psz, nLengthW) == 0) ; } } if ( bFailed) m_psz = nullptr ; } public : wchar_t* m_psz ; wchar_t m_szBuffer[t_nBufferLength] ; } ; typedef AtoWEX<> AtoW ; #define stringtoW(s) LPWSTR( AtoW( s.c_str())) #define strztoW(sz) LPWSTR( AtoW( sz)) //----------------------------------------------------------------------------- //! Classe per convertire stringhe W (wchar_t UTF-16) in stringhe A (char UTF-8) //----------------------------------------------------------------------------- template < int t_nBufferLength = 128> class WtoAEX { public : WtoAEX( const wchar_t* psz) : m_psz( m_szBuffer) { Init( psz, CP_UTF8) ; } WtoAEX( const wchar_t* psz, unsigned int nCodePage) : m_psz( m_szBuffer) { Init( psz, nCodePage) ; } ~WtoAEX( void) { SmartFreeMemory( m_psz, m_szBuffer, t_nBufferLength) ; } operator LPSTR( void) { return ( m_psz) ; } int GetLength( void) { return strlen( m_psz) ; } private : void Init( const wchar_t* psz, unsigned int nCodePage) { if ( psz == nullptr) { m_psz = nullptr ; return ; } int nLengthW = lstrlenW( psz) + 1 ; int nLengthA = ( 2 * nLengthW >= t_nBufferLength ? 2 * nLengthW : t_nBufferLength) ; SmartAllocMemory( &m_psz, nLengthA, m_szBuffer, t_nBufferLength) ; BOOL bFailed = ( WideCharToMultiByte( nCodePage, 0, psz, nLengthW, m_psz, nLengthA, nullptr, nullptr) == 0) ; if ( bFailed) { if ( GetLastError() == ERROR_INSUFFICIENT_BUFFER) { nLengthA = ::WideCharToMultiByte( nCodePage, 0, psz, nLengthW, nullptr, 0, nullptr, nullptr) ; SmartAllocMemory( &m_psz, nLengthA, m_szBuffer, t_nBufferLength) ; bFailed = ( WideCharToMultiByte( nCodePage, 0, psz, nLengthW, m_psz, nLengthA, nullptr, nullptr) == 0) ; } } if ( bFailed) m_psz = nullptr ; } public : char* m_psz ; char m_szBuffer[t_nBufferLength] ; } ; typedef WtoAEX<> WtoA ; #define wstringtoA(ws) LPSTR( WtoA( ws.c_str())) #define wstrztoA(wsz) LPSTR( WtoA( wsz)) //----------------------------------------------------------------------------- //! Classe contenente un buffer di wchar_t da passare alle funzioni Unicode delle API //! di Windows, con metodo per terminarlo e macro per convertirlo in char UTF-8.
//! Esempio di utilizzo :
//!    wcharBuffer wBuffer( nLen) ;
//!    int nChar = GetLine( nCurrLine, wBuffer.data(), nLen) ;
//!    wBuffer.terminate( nChar) ;
//!    string sCmd = wcharBtoA( wBuffer) ; 
//---------------------------------------------------------------------------- class wcharBuffer { public : wcharBuffer( size_t nDim) { m_wBuffer.resize( nDim) ; } wchar_t* data( void) { return m_wBuffer.data() ; } void terminate( size_t nLen) { nLen = ( nLen <= m_wBuffer.size() - 1 ? nLen : m_wBuffer.size() - 1) ; m_wBuffer[nLen] = '\0' ; } private : std::vector m_wBuffer ; } ; #define wcharBtoA(wcB) LPSTR( WtoA( wcB.data()))