|
|
//+------------------------------------------------------------
//
// Copyright (C) 2000, Microsoft Corporation
//
// File: CodePageConvert.cpp
//
// Contents: Implementation of functions
// HrCodePageConvert
// HrCodePageConvert
// HrCodePageConvertFree
// HrCodePageConvertInternal
//
// History:
// aszafer 2000/03/15 created
//
//-------------------------------------------------------------
#include "CodePageConvert.h"
#include "dbgtrace.h"
//+------------------------------------------------------------
//
// Function: HrCodePageConvert
//
// Synopsis: Converts a zero terminated string to a different code page
//
// NOTES:
// caller needs to provide buffer where target string is returned
//
// Arguments:
// uiSourceCodePage Source Code Page
// pszSourceString Source String
// uiTargetCodePage Target Code Page
// pszTargetString p to prealloc buffer where target string is returned
// cbTargetStringBuffer cbytes of preallocated buffer for target string
//
// Returns:
// S_OK: Success
// E_OUTOFMEMORY if dynamic allocation of an internal buffer fails
// HRESULT_FROM_WIN32(GetLastError()) if Wide<->Multibyte calls fail
// HRESULT_FROM_WIN32 (ERROR_INSUFFICIENT_BUFFER) if
// uiSourceCodePage = uiTargetCodePage and
// cbTargetStringBuffer is too small
//
// History:
// aszafer 2000/03/29 created
//
//-------------------------------------------------------------
HRESULT HrCodePageConvert ( IN UINT uiSourceCodePage, // Source code page
IN LPSTR pszSourceString, // Source String
IN UINT uiTargetCodePage, // Target code page
OUT LPSTR pszTargetString, // p to buffer where target string is returned
IN int cbTargetStringBuffer) // cbytes in buffer for target string
{
HRESULT hr = S_OK;
TraceFunctEnter("HrCodePageConvert");
_ASSERT(pszSourceString); _ASSERT(pszTargetString); _ASSERT(cbTargetStringBuffer); //
// Take care of trivial cases first
//
if (uiTargetCodePage == uiSourceCodePage){ if (pszTargetString == pszSourceString) goto CLEANUP ;
if (lstrlen(pszSourceString) < cbTargetStringBuffer){
lstrcpy(pszTargetString,pszSourceString); }else{
DebugTrace(0, "Insufficient cbTargetStringBuffer = %08lx",cbTargetStringBuffer); hr = HRESULT_FROM_WIN32 (ERROR_INSUFFICIENT_BUFFER) ;
}
goto CLEANUP ; }
//
// If case is not trivial, call into HrCodePageConvertInternal
//
hr = HrCodePageConvertInternal ( uiSourceCodePage, // source code page
pszSourceString, // source string
uiTargetCodePage, // target code page
pszTargetString, // target string or NULL
cbTargetStringBuffer, // cb in target string or 0
NULL ); // NULL or p to where target string is returned
if (FAILED(hr)) DebugTrace(0,"HrCodePageConvertInternal failed hr = %08lx", hr);
CLEANUP:
DebugTrace(0,"returning %08lx", hr); TraceFunctLeave();
return hr; }
//+------------------------------------------------------------
//
// Function: HrCodePageConvert
//
// Synopsis: Converts a zero terminated string to a different code page
//
// NOTES:
// 1. if the fucntion succeeds, the caller needs to call
// HrCodePageConvertFree (*ppszTargetString) when done,
// to free memory allocated inside this function
// 2. if the function fails, it will internally free all allocated memory
//
// Arguments:
// uiSourceCodePage Source Code Page
// pszSourceString Source String
// uiTargetCodePage Target Code Page
// ppszTargetString p to where to return target string
//
// Returns:
// S_OK: Success
// E_OUTOFMEMORY if dynamic allocation of an internal buffer fails
// HRESULT_FROM_WIN32(GetLastError()) if Wide<->Multibyte calls fail
//
// History:
// aszafer 2000/03/29 created
//
//-------------------------------------------------------------
HRESULT HrCodePageConvert ( IN UINT uiSourceCodePage, // Source code page
IN LPSTR pszSourceString, // Source string
IN UINT uiTargetCodePage, // Target code page
OUT LPSTR * ppszTargetString) // p to where target string is returned
{
HRESULT hr = S_OK; LPSTR pszTargetString = NULL; TraceFunctEnter("HrCodePageConvert");
_ASSERT(pszSourceString); _ASSERT(ppszTargetString); //
// Take care of trivial cases first
//
if (uiTargetCodePage == uiSourceCodePage){ pszTargetString = new CHAR[lstrlen(pszSourceString) + 1]; if (pszTargetString == NULL) {
hr = E_OUTOFMEMORY ; DebugTrace(0,"alloc for pszTargetString failed hr = %08lx", hr); goto CLEANUP ; }
lstrcpy(pszTargetString,pszSourceString); *ppszTargetString = pszTargetString; goto CLEANUP ; }
//
// If case is not trivial, call into HrCodePageConvertInternal
//
hr = HrCodePageConvertInternal ( uiSourceCodePage, // source code page
pszSourceString, // source string
uiTargetCodePage, // target code page
NULL, // target string or NULL
0, // cb in target string or 0
ppszTargetString ); // NULL or p to where target string is returned
if (FAILED(hr)) DebugTrace(0,"HrCodePageConvertInternal failed hr = %08lx", hr); CLEANUP: DebugTrace(0,"returning %08lx", hr); TraceFunctLeave();
return hr; }
//+------------------------------------------------------------
//
// Function: HrCodePageConvertInternal
//
// Synopsis: Converts a zero terminated string to a different code page
//
// NOTES:
// pointers to Source and Target strings may be the same
//
// Arguments:
// uiSourceCodePage Source Code Page
// pszSourceString Source String
// uiTargetCodePage Target Code Page
//
// either:
// pszTargetString p to buffer prealloc by caller where target string
// is returned
// cbTargetStringBuffer cbytes in prealloc buffer for target string
// ppszTargetString NULL,
//
// or:
// pszTargetString NULL
// cbTargetStringBuffer 0
// ppszTargetString p to where target string is to be returned
//
// Returns:
// S_OK: Success
// E_OUTOFMEMORY if dynamic allocation of an internal buffer fails
// HRESULT_FROM_WIN32(GetLastError()) if Wide<->Multibyte calls fail
//
// History:
// aszafer 2000/03/29 created
//
//-------------------------------------------------------------
HRESULT HrCodePageConvertInternal ( IN UINT uiSourceCodePage, // source code page
IN LPSTR pszSourceString, // source string
IN UINT uiTargetCodePage, // target code page
OUT LPSTR pszTargetString, // target string or NULL
IN int cbTargetStringBuffer, // cb in target string or 0
OUT LPSTR* ppszTargetString ) // NULL or p to where target string is returned
{
HRESULT hr = S_OK; WCHAR wsz[TEMPBUFFER_WCHARS] ; int cwch = sizeof(wsz)/sizeof(WCHAR) ; WCHAR* pwsz = wsz ; CHAR* psz ; int iSourceStringLengh ; int cch ; BOOL fAlloc1 = FALSE ; BOOL fAlloc2 = FALSE ;
TraceFunctEnter("HrCodePageConvertInternal");
_ASSERT(((pszTargetString != NULL) && (cbTargetStringBuffer != 0)) || (ppszTargetString != NULL) );
psz = pszTargetString; cch = cbTargetStringBuffer; //
// If stack allocated temp buffer may not be sufficient
// for unicode string, allocate from heap
//
iSourceStringLengh = lstrlen(pszSourceString) + 1 ; //includes terminator
if (iSourceStringLengh > TEMPBUFFER_WCHARS){ //
// Here we assume that each character in the source code page
// can be represented by a single unicode character
//
cwch = iSourceStringLengh ; pwsz = new WCHAR[iSourceStringLengh]; if (pwsz == NULL) {
hr = E_OUTOFMEMORY ; DebugTrace(0,"alloc for pwsz failed hr = %08lx", hr); goto CLEANUP ; }
fAlloc1 = TRUE ; } //
// Convert to unicode
//
cwch = MultiByteToWideChar( uiSourceCodePage, // code page
0, // dwFlags
pszSourceString, // string to map
-1 , // number of bytes in string
pwsz, // wide-character buffer
cwch ); // size of buffer
if(cwch == 0) { hr = HRESULT_FROM_WIN32(GetLastError()); DebugTrace(0,"MultiByteToWideChar2 failed hr = %08lx", hr); _ASSERT(FAILED(hr)); goto CLEANUP ; }
//
// If cbTargetStringBuffer == 0, allocate space for target string
//
if (cbTargetStringBuffer == 0){
cch = WideCharToMultiByte( uiTargetCodePage, // codepage
0, // dwFlags
pwsz, // wide-character string
cwch, // number of wchars in string
NULL, // buffer for new string
0, // size of buffer
NULL, // default for unmappable chars
NULL); // set when default char used
if(cch == 0) { hr = HRESULT_FROM_WIN32(GetLastError()); DebugTrace(0,"WideCharToMultiByte1 failed hr = %08lx", hr); _ASSERT(FAILED(hr)); goto CLEANUP ; }
psz = new CHAR[cch]; if (psz == NULL) { hr = E_OUTOFMEMORY ; DebugTrace(0,"alloc for psz failed hr = %08lx", hr); goto CLEANUP ; } fAlloc2 = TRUE ; }
//
// Convert to target code page
//
cch = WideCharToMultiByte( uiTargetCodePage, // codepage
0, // dwFlags
pwsz, // wide-character string
cwch, // number of wchars in string
psz, // buffer for new string
cch, // size of buffer
NULL, // default for unmappable chars
NULL); // set when default char used
if(cch == 0) { hr = HRESULT_FROM_WIN32(GetLastError()); DebugTrace(0,"WideCharToMultiByte2 failed hr = %08lx", hr); _ASSERT(FAILED(hr)); goto CLEANUP ; }
//
// If target string had to be allocated, output pointer to it
//
if (cbTargetStringBuffer == 0) *ppszTargetString = psz ;
CLEANUP:
if (fAlloc1) delete[] pwsz ;
if (FAILED(hr)){
if (fAlloc2) delete[] psz ; } DebugTrace(0,"returning %08lx", hr); TraceFunctLeave();
return hr; }
//+------------------------------------------------------------
//
// Function: HrCodePageConvertFree
//
// Synopsis: Use to free memory if HrCodePageConvert or HrCodePageConvertInternal
// allocate buffer for target string
//
// Arguments:
// pszTargetString p to buffer to be freed
//
// History:
// aszafer 2000/03/29 created
//
//-------------------------------------------------------------
VOID HrCodePageConvertFree(LPSTR pszTargetString) { _ASSERT(pszTargetString);
delete pszTargetString;
}
//+------------------------------------------------------------
//
// Function: wcsutf8cmpi
//
// Synopsis: Compare a Unicode string to a UTF8 string and see
// if they are identical
//
// Arguments: pwszStr1 - Unicode string
// pszStr2 - UTF8 string
//
// Returns: S_OK - identical
// S_FALSE - different
// E_* - error
//
//-------------------------------------------------------------
HRESULT wcsutf8cmpi(LPWSTR pwszStr1, LPCSTR pszStr2) { int rc; HRESULT hr; WCHAR wszStr2[TEMPBUFFER_WCHARS]; LPWSTR pwszStr2 = wszStr2; DWORD cStr2;
// convert string 2 to wide
cStr2 = MultiByteToWideChar(CP_UTF8, 0, pszStr2, -1, pwszStr2, 0); if (cStr2 > (sizeof(wszStr2) / sizeof(WCHAR)) ) { pwszStr2 = new WCHAR[cStr2 + 1]; if (pwszStr2 == NULL) { hr = E_OUTOFMEMORY; goto Exit; } } rc = MultiByteToWideChar(CP_UTF8, 0, pszStr2, -1, pwszStr2, cStr2); if (rc == 0) { hr = HRESULT_FROM_WIN32(GetLastError()); goto Exit; }
// do the comparison
rc = _wcsicmp(pwszStr1, pwszStr2); if (rc == 0) hr = S_OK; else hr = S_FALSE;
Exit: if (pwszStr2 != wszStr2) { delete[] pwszStr2; } return hr; }
//+------------------------------------------------------------
//
// Function: CodePageConvertFree
//
// Synopsis: Free memory allocated in CodePageConvert
//
// Arguments:
// pwszTargetString: Memory to free
//
// Returns: NOTHING
//
// History:
// jstamerj 2001/03/20 16:37:28: Created.
//
//-------------------------------------------------------------
VOID CodePageConvertFree( IN LPWSTR pwszTargetString) { delete [] pwszTargetString; } // CodePageConvertFree
//+------------------------------------------------------------
//
// Function: HrConvertToUnicodeWithAlloc
//
// Synopsis: Convet an MBCS string to unicode (And allocate the
// unicode string buffer)
//
// Arguments:
// uiSourceCodePage: Source code page
// pszSourceString: Source string
// ppwszTargetString: Out parameter -- will be set to pointer to
// allocated buffer. This should be free'd with CodePageConvertFree
//
// Returns:
// S_OK: Success
// E_OUTOFMEMORY
// or error from MultiByteToWideChar
//
// History:
// jstamerj 2001/03/20 16:38:52: Created.
//
//-------------------------------------------------------------
HRESULT HrConvertToUnicodeWithAlloc( IN UINT uiSourceCodePage, IN LPSTR pszSourceString, OUT LPWSTR* ppwszTargetString) { return HrConvertToUnicodeWithAlloc( uiSourceCodePage, lstrlen(pszSourceString), pszSourceString, ppwszTargetString); }
HRESULT HrConvertToUnicodeWithAlloc( IN UINT uiSourceCodePage, IN DWORD dwcbSourceString, IN LPSTR pszSourceString, OUT LPWSTR* ppwszTargetString) { HRESULT hr = S_OK; int ich = 0; int ich2 = 0; LPWSTR pwszTmp = NULL; TraceFunctEnterEx((LPARAM)0, "HrConvertToUnicodeWithAlloc");
ich = MultiByteToWideChar( uiSourceCodePage, 0, pszSourceString, dwcbSourceString, NULL, 0); if(ich == 0) { hr = HRESULT_FROM_WIN32(GetLastError()); ErrorTrace((LPARAM)0, "MultiByteToWideChar failed hr %08lx", hr); goto CLEANUP; }
pwszTmp = new WCHAR[ich + 1]; if(pwszTmp == NULL) { hr = E_OUTOFMEMORY; goto CLEANUP; }
ich2 = MultiByteToWideChar( uiSourceCodePage, 0, pszSourceString, dwcbSourceString, pwszTmp, ich); if(ich2 == 0) { hr = HRESULT_FROM_WIN32(GetLastError()); ErrorTrace((LPARAM)0, "MultiByteToWideChar2 failed hr %08lx", hr); goto CLEANUP; } pwszTmp[ich] = '\0'; //
// Success!
//
*ppwszTargetString = pwszTmp;
CLEANUP: if(FAILED(hr)) { if(pwszTmp) delete [] pwszTmp; } DebugTrace((LPARAM)0, "returning %08lx", hr); TraceFunctLeaveEx((LPARAM)0); return hr; } // HrConvertToUnicodeWithAlloc
|