sys_string_conversions_mac.mm (5153B)
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "base/sys_string_conversions.h" 6 7 #import <Foundation/Foundation.h> 8 9 #include <vector> 10 11 #include "base/scoped_cftyperef.h" 12 #include "base/string_piece.h" 13 14 namespace base { 15 16 namespace { 17 18 // Convert the supplied CFString into the specified encoding, and return it as 19 // an STL string of the template type. Returns an empty string on failure. 20 // 21 // Do not assert in this function since it is used by the asssertion code! 22 template <typename StringType> 23 static StringType CFStringToSTLStringWithEncodingT(CFStringRef cfstring, 24 CFStringEncoding encoding) { 25 CFIndex length = CFStringGetLength(cfstring); 26 if (length == 0) return StringType(); 27 28 CFRange whole_string = CFRangeMake(0, length); 29 CFIndex out_size; 30 CFIndex converted = CFStringGetBytes(cfstring, whole_string, encoding, 31 0, // lossByte 32 false, // isExternalRepresentation 33 NULL, // buffer 34 0, // maxBufLen 35 &out_size); 36 if (converted == 0 || out_size == 0) return StringType(); 37 38 // out_size is the number of UInt8-sized units needed in the destination. 39 // A buffer allocated as UInt8 units might not be properly aligned to 40 // contain elements of StringType::value_type. Use a container for the 41 // proper value_type, and convert out_size by figuring the number of 42 // value_type elements per UInt8. Leave room for a NUL terminator. 43 typename StringType::size_type elements = 44 out_size * sizeof(UInt8) / sizeof(typename StringType::value_type) + 1; 45 46 std::vector<typename StringType::value_type> out_buffer(elements); 47 converted = 48 CFStringGetBytes(cfstring, whole_string, encoding, 49 0, // lossByte 50 false, // isExternalRepresentation 51 reinterpret_cast<UInt8*>(&out_buffer[0]), out_size, 52 NULL); // usedBufLen 53 if (converted == 0) return StringType(); 54 55 out_buffer[elements - 1] = '\0'; 56 return StringType(&out_buffer[0], elements - 1); 57 } 58 59 // Given an STL string |in| with an encoding specified by |in_encoding|, 60 // convert it to |out_encoding| and return it as an STL string of the 61 // |OutStringType| template type. Returns an empty string on failure. 62 // 63 // Do not assert in this function since it is used by the asssertion code! 64 template <typename InStringType, typename OutStringType> 65 static OutStringType STLStringToSTLStringWithEncodingsT( 66 const InStringType& in, CFStringEncoding in_encoding, 67 CFStringEncoding out_encoding) { 68 typename InStringType::size_type in_length = in.length(); 69 if (in_length == 0) return OutStringType(); 70 71 scoped_cftyperef<CFStringRef> cfstring(CFStringCreateWithBytesNoCopy( 72 NULL, reinterpret_cast<const UInt8*>(in.data()), 73 in_length * sizeof(typename InStringType::value_type), in_encoding, false, 74 kCFAllocatorNull)); 75 if (!cfstring) return OutStringType(); 76 77 return CFStringToSTLStringWithEncodingT<OutStringType>(cfstring, 78 out_encoding); 79 } 80 81 // Given an STL string |in| with an encoding specified by |in_encoding|, 82 // return it as a CFStringRef. Returns NULL on failure. 83 template <typename StringType> 84 static CFStringRef STLStringToCFStringWithEncodingsT( 85 const StringType& in, CFStringEncoding in_encoding) { 86 typename StringType::size_type in_length = in.length(); 87 if (in_length == 0) return CFSTR(""); 88 89 return CFStringCreateWithBytes( 90 kCFAllocatorDefault, reinterpret_cast<const UInt8*>(in.data()), 91 in_length * sizeof(typename StringType::value_type), in_encoding, false); 92 } 93 94 // Specify the byte ordering explicitly, otherwise CFString will be confused 95 // when strings don't carry BOMs, as they typically won't. 96 static const CFStringEncoding kNarrowStringEncoding = kCFStringEncodingUTF8; 97 98 #ifdef __BIG_ENDIAN__ 99 static const CFStringEncoding kWideStringEncoding = kCFStringEncodingUTF32BE; 100 #elif defined(__LITTLE_ENDIAN__) 101 static const CFStringEncoding kWideStringEncoding = kCFStringEncodingUTF32LE; 102 #endif // __LITTLE_ENDIAN__ 103 104 } // namespace 105 106 // Do not assert in this function since it is used by the asssertion code! 107 std::string SysWideToUTF8(const std::wstring& wide) { 108 return STLStringToSTLStringWithEncodingsT<std::wstring, std::string>( 109 wide, kWideStringEncoding, kNarrowStringEncoding); 110 } 111 112 // Do not assert in this function since it is used by the asssertion code! 113 std::wstring SysUTF8ToWide(const StringPiece& utf8) { 114 return STLStringToSTLStringWithEncodingsT<StringPiece, std::wstring>( 115 utf8, kNarrowStringEncoding, kWideStringEncoding); 116 } 117 118 std::string SysWideToNativeMB(const std::wstring& wide) { 119 return SysWideToUTF8(wide); 120 } 121 122 std::wstring SysNativeMBToWide(const StringPiece& native_mb) { 123 return SysUTF8ToWide(native_mb); 124 } 125 126 } // namespace base