michael@0: // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. michael@0: // Use of this source code is governed by a BSD-style license that can be michael@0: // found in the LICENSE file. michael@0: michael@0: #include "base/sys_string_conversions.h" michael@0: michael@0: #import michael@0: michael@0: #include michael@0: michael@0: #include "base/scoped_cftyperef.h" michael@0: #include "base/string_piece.h" michael@0: michael@0: namespace base { michael@0: michael@0: namespace { michael@0: michael@0: // Convert the supplied CFString into the specified encoding, and return it as michael@0: // an STL string of the template type. Returns an empty string on failure. michael@0: // michael@0: // Do not assert in this function since it is used by the asssertion code! michael@0: template michael@0: static StringType CFStringToSTLStringWithEncodingT(CFStringRef cfstring, michael@0: CFStringEncoding encoding) { michael@0: CFIndex length = CFStringGetLength(cfstring); michael@0: if (length == 0) michael@0: return StringType(); michael@0: michael@0: CFRange whole_string = CFRangeMake(0, length); michael@0: CFIndex out_size; michael@0: CFIndex converted = CFStringGetBytes(cfstring, michael@0: whole_string, michael@0: encoding, michael@0: 0, // lossByte michael@0: false, // isExternalRepresentation michael@0: NULL, // buffer michael@0: 0, // maxBufLen michael@0: &out_size); michael@0: if (converted == 0 || out_size == 0) michael@0: return StringType(); michael@0: michael@0: // out_size is the number of UInt8-sized units needed in the destination. michael@0: // A buffer allocated as UInt8 units might not be properly aligned to michael@0: // contain elements of StringType::value_type. Use a container for the michael@0: // proper value_type, and convert out_size by figuring the number of michael@0: // value_type elements per UInt8. Leave room for a NUL terminator. michael@0: typename StringType::size_type elements = michael@0: out_size * sizeof(UInt8) / sizeof(typename StringType::value_type) + 1; michael@0: michael@0: std::vector out_buffer(elements); michael@0: converted = CFStringGetBytes(cfstring, michael@0: whole_string, michael@0: encoding, michael@0: 0, // lossByte michael@0: false, // isExternalRepresentation michael@0: reinterpret_cast(&out_buffer[0]), michael@0: out_size, michael@0: NULL); // usedBufLen michael@0: if (converted == 0) michael@0: return StringType(); michael@0: michael@0: out_buffer[elements - 1] = '\0'; michael@0: return StringType(&out_buffer[0], elements - 1); michael@0: } michael@0: michael@0: // Given an STL string |in| with an encoding specified by |in_encoding|, michael@0: // convert it to |out_encoding| and return it as an STL string of the michael@0: // |OutStringType| template type. Returns an empty string on failure. michael@0: // michael@0: // Do not assert in this function since it is used by the asssertion code! michael@0: template michael@0: static OutStringType STLStringToSTLStringWithEncodingsT( michael@0: const InStringType& in, michael@0: CFStringEncoding in_encoding, michael@0: CFStringEncoding out_encoding) { michael@0: typename InStringType::size_type in_length = in.length(); michael@0: if (in_length == 0) michael@0: return OutStringType(); michael@0: michael@0: scoped_cftyperef cfstring( michael@0: CFStringCreateWithBytesNoCopy(NULL, michael@0: reinterpret_cast(in.data()), michael@0: in_length * michael@0: sizeof(typename InStringType::value_type), michael@0: in_encoding, michael@0: false, michael@0: kCFAllocatorNull)); michael@0: if (!cfstring) michael@0: return OutStringType(); michael@0: michael@0: return CFStringToSTLStringWithEncodingT(cfstring, michael@0: out_encoding); michael@0: } michael@0: michael@0: // Given an STL string |in| with an encoding specified by |in_encoding|, michael@0: // return it as a CFStringRef. Returns NULL on failure. michael@0: template michael@0: static CFStringRef STLStringToCFStringWithEncodingsT( michael@0: const StringType& in, michael@0: CFStringEncoding in_encoding) { michael@0: typename StringType::size_type in_length = in.length(); michael@0: if (in_length == 0) michael@0: return CFSTR(""); michael@0: michael@0: return CFStringCreateWithBytes(kCFAllocatorDefault, michael@0: reinterpret_cast(in.data()), michael@0: in_length * michael@0: sizeof(typename StringType::value_type), michael@0: in_encoding, michael@0: false); michael@0: } michael@0: michael@0: // Specify the byte ordering explicitly, otherwise CFString will be confused michael@0: // when strings don't carry BOMs, as they typically won't. michael@0: static const CFStringEncoding kNarrowStringEncoding = kCFStringEncodingUTF8; michael@0: michael@0: #ifdef __BIG_ENDIAN__ michael@0: static const CFStringEncoding kWideStringEncoding = kCFStringEncodingUTF32BE; michael@0: #elif defined(__LITTLE_ENDIAN__) michael@0: static const CFStringEncoding kWideStringEncoding = kCFStringEncodingUTF32LE; michael@0: #endif // __LITTLE_ENDIAN__ michael@0: michael@0: } // namespace michael@0: michael@0: // Do not assert in this function since it is used by the asssertion code! michael@0: std::string SysWideToUTF8(const std::wstring& wide) { michael@0: return STLStringToSTLStringWithEncodingsT( michael@0: wide, kWideStringEncoding, kNarrowStringEncoding); michael@0: } michael@0: michael@0: // Do not assert in this function since it is used by the asssertion code! michael@0: std::wstring SysUTF8ToWide(const StringPiece& utf8) { michael@0: return STLStringToSTLStringWithEncodingsT( michael@0: utf8, kNarrowStringEncoding, kWideStringEncoding); michael@0: } michael@0: michael@0: std::string SysWideToNativeMB(const std::wstring& wide) { michael@0: return SysWideToUTF8(wide); michael@0: } michael@0: michael@0: std::wstring SysNativeMBToWide(const StringPiece& native_mb) { michael@0: return SysUTF8ToWide(native_mb); michael@0: } michael@0: michael@0: } // namespace base