--- /dev/null
+/* -*- 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.
+
+ Change History (most recent first):
+
+$Log: StringServices.cpp,v $
+Revision 1.2 2009/06/02 18:43:57 herscher
+<rdar://problem/3948252> Allow component consumers to pass in null strings
+
+Revision 1.1 2009/05/26 04:43:54 herscher
+<rdar://problem/3948252> COM component that can be used with any .NET language and VB.
+\r
+\r
+*/\r
+\r
+#include "StringServices.h"\r
+#include <DebugServices.h>\r
+\r
+\r
+extern BOOL\r
+BSTRToUTF8\r
+ (\r
+ BSTR inString,\r
+ std::string & outString\r
+ )\r
+{\r
+ USES_CONVERSION;\r
+ \r
+ char * utf8String = NULL;\r
+ OSStatus err = kNoErr;\r
+\r
+ outString = "";
+
+ if ( inString )\r
+ {
+ TCHAR * utf16String = NULL;
+ size_t size = 0;
+\r
+ utf16String = OLE2T( inString );\r
+ require_action( utf16String != NULL, exit, err = kUnknownErr );\r
+\r
+ if ( wcslen( utf16String ) > 0 )\r
+ {\r
+ size = (size_t) WideCharToMultiByte( CP_UTF8, 0, utf16String, ( int ) wcslen( utf16String ), NULL, 0, NULL, NULL );\r
+ err = translate_errno( size != 0, GetLastError(), kUnknownErr );\r
+ require_noerr( err, exit );\r
+\r
+ try\r
+ {\r
+ utf8String = new char[ size + 1 ];\r
+ }\r
+ catch ( ... )\r
+ {\r
+ utf8String = NULL;\r
+ }\r
+\r
+ require_action( utf8String != NULL, exit, err = kNoMemoryErr );\r
+ size = (size_t) WideCharToMultiByte( CP_UTF8, 0, utf16String, ( int ) wcslen( utf16String ), utf8String, (int) size, NULL, NULL);\r
+ err = translate_errno( size != 0, GetLastError(), kUnknownErr );\r
+ require_noerr( err, exit );\r
+\r
+ // have to add the trailing 0 because WideCharToMultiByte doesn't do it,\r
+ // although it does return the correct size\r
+\r
+ utf8String[size] = '\0';\r
+ outString = utf8String;\r
+ }
+ }\r
+\r
+exit:\r
+\r
+ if ( utf8String != NULL )\r
+ {\r
+ delete [] utf8String;\r
+ }\r
+\r
+ return ( !err ) ? TRUE : FALSE;\r
+}\r
+\r
+\r
+extern BOOL\r
+UTF8ToBSTR\r
+ (\r
+ const char * inString,\r
+ CComBSTR & outString\r
+ )\r
+{\r
+ wchar_t * unicode = NULL;\r
+ OSStatus err = 0;\r
+\r
+ if ( inString )\r
+ {
+ int n;
+
+ n = MultiByteToWideChar( CP_UTF8, 0, inString, -1, NULL, 0 );\r
+ \r
+ if ( n > 0 )\r
+ {\r
+ try\r
+ {\r
+ unicode = new wchar_t[ n ];\r
+ }\r
+ catch ( ... )\r
+ {\r
+ unicode = NULL;\r
+ }\r
+\r
+ require_action( unicode, exit, err = ERROR_INSUFFICIENT_BUFFER );\r
+\r
+ n = MultiByteToWideChar( CP_UTF8, 0, inString, -1, unicode, n );\r
+ }\r
+\r
+ outString = unicode;\r
+ }
+\r
+exit:\r
+\r
+ if ( unicode != NULL )\r
+ {\r
+ delete [] unicode;\r
+ }\r
+\r
+ return ( !err ) ? TRUE : FALSE;\r
+}\r
+\r
+\r
+BOOL\r
+ByteArrayToVariant\r
+ (\r
+ const void * inArray,\r
+ size_t inArrayLen,\r
+ VARIANT * outVariant\r
+ )\r
+{\r
+ LPBYTE buf = NULL;\r
+ HRESULT hr = 0;\r
+ BOOL ok = TRUE;\r
+\r
+ VariantClear( outVariant );\r
+ outVariant->vt = VT_ARRAY|VT_UI1;\r
+ outVariant->parray = SafeArrayCreateVector( VT_UI1, 0, ( ULONG ) inArrayLen );\r
+ require_action( outVariant->parray, exit, ok = FALSE );\r
+ hr = SafeArrayAccessData( outVariant->parray, (LPVOID *)&buf );\r
+ require_action( hr == S_OK, exit, ok = FALSE );\r
+ memcpy( buf, inArray, inArrayLen );\r
+ hr = SafeArrayUnaccessData( outVariant->parray );\r
+ require_action( hr == S_OK, exit, ok = FALSE );\r
+\r
+exit:\r
+\r
+ return ok;\r
+}\r
+\r
+\r
+extern BOOL\r
+VariantToByteArray\r
+ (\r
+ VARIANT * inVariant,\r
+ std::vector< BYTE > & outArray\r
+ )\r
+{\r
+ SAFEARRAY * psa = NULL;\r
+ BYTE * pData = NULL;\r
+ ULONG cElements = 0;\r
+ HRESULT hr;\r
+ BOOL ok = TRUE;\r
+\r
+ require_action( V_VT( inVariant ) == ( VT_ARRAY|VT_UI1 ), exit, ok = FALSE );\r
+ psa = V_ARRAY( inVariant );\r
+ require_action( psa, exit, ok = FALSE );\r
+ require_action( SafeArrayGetDim( psa ) == 1, exit, ok = FALSE );\r
+ hr = SafeArrayAccessData( psa, ( LPVOID* )&pData );\r
+ require_action( hr == S_OK, exit, ok = FALSE );\r
+ cElements = psa->rgsabound[0].cElements;\r
+ outArray.reserve( cElements );\r
+ outArray.assign( cElements, 0 );\r
+ memcpy( &outArray[ 0 ], pData, cElements );\r
+ SafeArrayUnaccessData( psa );\r
+\r
+exit:\r
+\r
+ return ok;\r
+}
\ No newline at end of file