1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
|
// 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/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], elements - 1);
}
// 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__
static const CFStringEncoding kWideStringEncoding = kCFStringEncodingUTF32BE;
#elif defined(__LITTLE_ENDIAN__)
static const CFStringEncoding kWideStringEncoding = kCFStringEncodingUTF32LE;
#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); }
} // namespace base
|