diff options
author | mark@chromium.org <mark@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-10-08 21:02:56 +0000 |
---|---|---|
committer | mark@chromium.org <mark@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-10-08 21:02:56 +0000 |
commit | 03d95ac0d42dd9eaa7333b068361e4205c28ca7d (patch) | |
tree | 8d433e8c73cf002cc1bea78d40f00dec51d6848c /base/sys_string_conversions_mac.mm | |
parent | 89916bd485d5c6156030f9f4b62db0cadac87c85 (diff) | |
download | chromium_src-03d95ac0d42dd9eaa7333b068361e4205c28ca7d.zip chromium_src-03d95ac0d42dd9eaa7333b068361e4205c28ca7d.tar.gz chromium_src-03d95ac0d42dd9eaa7333b068361e4205c28ca7d.tar.bz2 |
Provide converters to and from NSString* in sys_string_conversions
Review URL: http://codereview.chromium.org/6355
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@3050 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base/sys_string_conversions_mac.mm')
-rw-r--r-- | base/sys_string_conversions_mac.mm | 187 |
1 files changed, 187 insertions, 0 deletions
diff --git a/base/sys_string_conversions_mac.mm b/base/sys_string_conversions_mac.mm new file mode 100644 index 0000000..02a4244 --- /dev/null +++ b/base/sys_string_conversions_mac.mm @@ -0,0 +1,187 @@ +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/sys_string_conversions.h" + +#import <Foundation/Foundation.h> + +#include <vector> + +#include "base/foundation_utils_mac.h" +#include "base/scoped_cftyperef.h" +#include "base/string_piece.h" + +namespace base { + +namespace { + +// Convert the supplied CFString into the specified encoding, and return it as +// an STL string of the template type. Returns an empty string on failure. +// +// Do not assert in this function since it is used by the asssertion code! +template<typename StringType> +static StringType CFStringToSTLStringWithEncodingT(CFStringRef cfstring, + CFStringEncoding encoding) { + CFIndex length = CFStringGetLength(cfstring); + if (length == 0) + return StringType(); + + CFRange whole_string = CFRangeMake(0, length); + CFIndex out_size; + CFIndex converted = CFStringGetBytes(cfstring, + whole_string, + encoding, + 0, // lossByte + false, // isExternalRepresentation + NULL, // buffer + 0, // maxBufLen + &out_size); + if (converted == 0 || out_size == 0) + return StringType(); + + // out_size is the number of UInt8-sized units needed in the destination. + // A buffer allocated as UInt8 units might not be properly aligned to + // contain elements of StringType::value_type. Use a container for the + // proper value_type, and convert out_size by figuring the number of + // value_type elements per UInt8. Leave room for a NUL terminator. + typename StringType::size_type elements = + out_size * sizeof(UInt8) / sizeof(typename StringType::value_type) + 1; + + std::vector<typename StringType::value_type> out_buffer(elements); + converted = CFStringGetBytes(cfstring, + whole_string, + encoding, + 0, // lossByte + false, // isExternalRepresentation + reinterpret_cast<UInt8*>(&out_buffer[0]), + out_size, + NULL); // usedBufLen + if (converted == 0) + return StringType(); + + out_buffer[elements - 1] = '\0'; + return StringType(&out_buffer[0]); +} + +// Given an STL string |in| with an encoding specified by |in_encoding|, +// convert it to |out_encoding| and return it as an STL string of the +// |OutStringType| template type. Returns an empty string on failure. +// +// Do not assert in this function since it is used by the asssertion code! +template<typename InStringType, typename OutStringType> +static OutStringType STLStringToSTLStringWithEncodingsT( + const InStringType& in, + CFStringEncoding in_encoding, + CFStringEncoding out_encoding) { + typename InStringType::size_type in_length = in.length(); + if (in_length == 0) + return OutStringType(); + + scoped_cftyperef<CFStringRef> cfstring( + CFStringCreateWithBytesNoCopy(NULL, + reinterpret_cast<const UInt8*>(in.data()), + in_length * + sizeof(typename InStringType::value_type), + in_encoding, + false, + kCFAllocatorNull)); + if (!cfstring) + return OutStringType(); + + return CFStringToSTLStringWithEncodingT<OutStringType>(cfstring, + out_encoding); +} + +// Given an STL string |in| with an encoding specified by |in_encoding|, +// return it as a CFStringRef. Returns NULL on failure. +template<typename StringType> +static CFStringRef STLStringToCFStringWithEncodingsT( + const StringType& in, + CFStringEncoding in_encoding) { + typename StringType::size_type in_length = in.length(); + if (in_length == 0) + return CFSTR(""); + + return CFStringCreateWithBytes(kCFAllocatorDefault, + reinterpret_cast<const UInt8*>(in.data()), + in_length * + sizeof(typename StringType::value_type), + in_encoding, + false); +} + +// Specify the byte ordering explicitly, otherwise CFString will be confused +// when strings don't carry BOMs, as they typically won't. +static const CFStringEncoding kNarrowStringEncoding = kCFStringEncodingUTF8; +#ifdef __BIG_ENDIAN__ +#if defined(WCHAR_T_IS_UTF16) +static const CFStringEncoding kWideStringEncoding = kCFStringEncodingUTF16BE; +#elif defined(WCHAR_T_IS_UTF32) +static const CFStringEncoding kWideStringEncoding = kCFStringEncodingUTF32BE; +#endif // WCHAR_T_IS_UTF32 +#elif defined(__LITTLE_ENDIAN__) +#if defined(WCHAR_T_IS_UTF16) +static const CFStringEncoding kWideStringEncoding = kCFStringEncodingUTF16LE; +#elif defined(WCHAR_T_IS_UTF32) +static const CFStringEncoding kWideStringEncoding = kCFStringEncodingUTF32LE; +#endif // WCHAR_T_IS_UTF32 +#endif // __LITTLE_ENDIAN__ + +} // namespace + +// Do not assert in this function since it is used by the asssertion code! +std::string SysWideToUTF8(const std::wstring& wide) { + return STLStringToSTLStringWithEncodingsT<std::wstring, std::string>( + wide, kWideStringEncoding, kNarrowStringEncoding); +} + +// Do not assert in this function since it is used by the asssertion code! +std::wstring SysUTF8ToWide(const StringPiece& utf8) { + return STLStringToSTLStringWithEncodingsT<StringPiece, std::wstring>( + utf8, kNarrowStringEncoding, kWideStringEncoding); +} + +std::string SysWideToNativeMB(const std::wstring& wide) { + return SysWideToUTF8(wide); +} + +std::wstring SysNativeMBToWide(const StringPiece& native_mb) { + return SysUTF8ToWide(native_mb); +} + +CFStringRef SysUTF8ToCFStringRef(const std::string& utf8) { + return STLStringToCFStringWithEncodingsT(utf8, kNarrowStringEncoding); +} + +CFStringRef SysWideToCFStringRef(const std::wstring& wide) { + return STLStringToCFStringWithEncodingsT(wide, kWideStringEncoding); +} + +NSString* SysUTF8ToNSString(const std::string& utf8) { + return CFTypeRefToNSObjectAutorelease(SysUTF8ToCFStringRef(utf8)); +} + +NSString* SysWideToNSString(const std::wstring& wide) { + return CFTypeRefToNSObjectAutorelease(SysWideToCFStringRef(wide)); +} + +std::string SysCFStringRefToUTF8(CFStringRef ref) { + return CFStringToSTLStringWithEncodingT<std::string>(ref, + kNarrowStringEncoding); +} + +std::wstring SysCFStringRefToWide(CFStringRef ref) { + return CFStringToSTLStringWithEncodingT<std::wstring>(ref, + kWideStringEncoding); +} + +std::string SysNSStringToUTF8(NSString* nsstring) { + return SysCFStringRefToUTF8(reinterpret_cast<CFStringRef>(nsstring)); +} + +std::wstring SysNSStringToWide(NSString* nsstring) { + return SysCFStringRefToWide(reinterpret_cast<CFStringRef>(nsstring)); +} + +} // namespace base |