/* -*- Mode: C; tab-width: 4 -*- * * Copyright (c) 2009 Apple Computer, Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "StringServices.h" #include extern BOOL BSTRToUTF8 ( BSTR inString, std::string & outString ) { USES_CONVERSION; char * utf8String = NULL; OSStatus err = kNoErr; outString = ""; if ( inString ) { TCHAR * utf16String = NULL; size_t size = 0; utf16String = OLE2T( inString ); require_action( utf16String != NULL, exit, err = kUnknownErr ); if ( wcslen( utf16String ) > 0 ) { size = (size_t) WideCharToMultiByte( CP_UTF8, 0, utf16String, ( int ) wcslen( utf16String ), NULL, 0, NULL, NULL ); err = translate_errno( size != 0, GetLastError(), kUnknownErr ); require_noerr( err, exit ); try { utf8String = new char[ size + 1 ]; } catch ( ... ) { utf8String = NULL; } require_action( utf8String != NULL, exit, err = kNoMemoryErr ); size = (size_t) WideCharToMultiByte( CP_UTF8, 0, utf16String, ( int ) wcslen( utf16String ), utf8String, (int) size, NULL, NULL); err = translate_errno( size != 0, GetLastError(), kUnknownErr ); require_noerr( err, exit ); // have to add the trailing 0 because WideCharToMultiByte doesn't do it, // although it does return the correct size utf8String[size] = '\0'; outString = utf8String; } } exit: if ( utf8String != NULL ) { delete [] utf8String; } return ( !err ) ? TRUE : FALSE; } extern BOOL UTF8ToBSTR ( const char * inString, CComBSTR & outString ) { wchar_t * unicode = NULL; OSStatus err = 0; if ( inString ) { int n; n = MultiByteToWideChar( CP_UTF8, 0, inString, -1, NULL, 0 ); if ( n > 0 ) { try { unicode = new wchar_t[ n ]; } catch ( ... ) { unicode = NULL; } require_action( unicode, exit, err = ERROR_INSUFFICIENT_BUFFER ); n = MultiByteToWideChar( CP_UTF8, 0, inString, -1, unicode, n ); } outString = unicode; } exit: if ( unicode != NULL ) { delete [] unicode; } return ( !err ) ? TRUE : FALSE; } BOOL ByteArrayToVariant ( const void * inArray, size_t inArrayLen, VARIANT * outVariant ) { LPBYTE buf = NULL; HRESULT hr = 0; BOOL ok = TRUE; VariantClear( outVariant ); outVariant->vt = VT_ARRAY|VT_UI1; outVariant->parray = SafeArrayCreateVector( VT_UI1, 0, ( ULONG ) inArrayLen ); require_action( outVariant->parray, exit, ok = FALSE ); hr = SafeArrayAccessData( outVariant->parray, (LPVOID *)&buf ); require_action( hr == S_OK, exit, ok = FALSE ); memcpy( buf, inArray, inArrayLen ); hr = SafeArrayUnaccessData( outVariant->parray ); require_action( hr == S_OK, exit, ok = FALSE ); exit: return ok; } extern BOOL VariantToByteArray ( VARIANT * inVariant, std::vector< BYTE > & outArray ) { BOOL ok = TRUE; if ( V_VT( inVariant ) == VT_BSTR ) { BSTR bstr = V_BSTR( inVariant ); std::string utf8; BSTRToUTF8( bstr, utf8 ); outArray.reserve( utf8.size() ); outArray.assign( utf8.begin(), utf8.end() ); } else if ( V_VT( inVariant ) == VT_ARRAY ) { SAFEARRAY * psa = NULL; BYTE * pData = NULL; ULONG cElements = 0; HRESULT hr; psa = V_ARRAY( inVariant ); require_action( psa, exit, ok = FALSE ); require_action( SafeArrayGetDim( psa ) == 1, exit, ok = FALSE ); hr = SafeArrayAccessData( psa, ( LPVOID* )&pData ); require_action( hr == S_OK, exit, ok = FALSE ); cElements = psa->rgsabound[0].cElements; outArray.reserve( cElements ); outArray.assign( cElements, 0 ); memcpy( &outArray[ 0 ], pData, cElements ); SafeArrayUnaccessData( psa ); } else { ok = FALSE; } exit: return ok; }