]> git.saurik.com Git - apple/cf.git/blob - CFPlatformConverters.c
CF-550.13.tar.gz
[apple/cf.git] / CFPlatformConverters.c
1 /*
2 * Copyright (c) 2009 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24 /* CFPlatformConverters.c
25 Copyright (c) 1998-2009, Apple Inc. All rights reserved.
26 Responsibility: Aki Inoue
27 */
28
29 #include "CFInternal.h"
30 #include <CoreFoundation/CFString.h>
31 #include "CFStringEncodingConverterExt.h"
32 #include <CoreFoundation/CFStringEncodingExt.h>
33 #include <CoreFoundation/CFPreferences.h>
34 #include "CFUniChar.h"
35 #include "CFUnicodeDecomposition.h"
36 #include "CFStringEncodingConverterPriv.h"
37 #include "CFICUConverters.h"
38
39
40 CF_INLINE bool __CFIsPlatformConverterAvailable(int encoding) {
41
42 #if DEPLOYMENT_TARGET_WINDOWS
43 return (IsValidCodePage(CFStringConvertEncodingToWindowsCodepage(encoding)) ? true : false);
44 #else
45 return false;
46 #endif
47 }
48
49 static const CFStringEncodingConverter __CFICUBootstrap = {
50 NULL /* toBytes */, NULL /* toUnicode */, 6 /* maxBytesPerChar */, 4 /* maxDecomposedCharLen */,
51 kCFStringEncodingConverterICU /* encodingClass */,
52 NULL /* toBytesLen */, NULL /* toUnicodeLen */, NULL /* toBytesFallback */,
53 NULL /* toUnicodeFallback */, NULL /* toBytesPrecompose */, NULL, /* isValidCombiningChar */
54 };
55
56 static const CFStringEncodingConverter __CFPlatformBootstrap = {
57 NULL /* toBytes */, NULL /* toUnicode */, 6 /* maxBytesPerChar */, 4 /* maxDecomposedCharLen */,
58 kCFStringEncodingConverterPlatformSpecific /* encodingClass */,
59 NULL /* toBytesLen */, NULL /* toUnicodeLen */, NULL /* toBytesFallback */,
60 NULL /* toUnicodeFallback */, NULL /* toBytesPrecompose */, NULL, /* isValidCombiningChar */
61 };
62
63 __private_extern__ const CFStringEncodingConverter *__CFStringEncodingGetExternalConverter(uint32_t encoding) {
64
65 if (NULL != __CFStringEncodingGetICUName(encoding)) return &__CFICUBootstrap;
66
67 return (__CFIsPlatformConverterAvailable(encoding) ? &__CFPlatformBootstrap : NULL);
68 }
69
70 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
71 __private_extern__ CFStringEncoding *__CFStringEncodingCreateListOfAvailablePlatformConverters(CFAllocatorRef allocator, CFIndex *numberOfConverters) {
72
73 return NULL;
74 }
75 #elif DEPLOYMENT_TARGET_WINDOWS
76
77 #include <tchar.h>
78
79 static uint32_t __CFWin32EncodingIndex = 0;
80 static CFStringEncoding *__CFWin32EncodingList = NULL;
81
82 static char CALLBACK __CFWin32EnumCodePageProc(LPTSTR string) {
83 uint32_t encoding = CFStringConvertWindowsCodepageToEncoding(_tcstoul(string, NULL, 10));
84 CFIndex idx;
85
86 if (encoding != kCFStringEncodingInvalidId) { // We list only encodings we know
87 if (__CFWin32EncodingList) {
88 for (idx = 0;idx < (CFIndex)__CFWin32EncodingIndex;idx++) if (__CFWin32EncodingList[idx] == encoding) break;
89 if (idx != __CFWin32EncodingIndex) return true;
90 __CFWin32EncodingList[__CFWin32EncodingIndex] = encoding;
91 }
92 ++__CFWin32EncodingIndex;
93 }
94 return true;
95 }
96
97 __private_extern__ CFStringEncoding *__CFStringEncodingCreateListOfAvailablePlatformConverters(CFAllocatorRef allocator, CFIndex *numberOfConverters) {
98 CFStringEncoding *encodings;
99
100 EnumSystemCodePages((CODEPAGE_ENUMPROC)&__CFWin32EnumCodePageProc, CP_INSTALLED);
101 __CFWin32EncodingList = (uint32_t *)CFAllocatorAllocate(allocator, sizeof(uint32_t) * __CFWin32EncodingIndex, 0);
102 EnumSystemCodePages((CODEPAGE_ENUMPROC)&__CFWin32EnumCodePageProc, CP_INSTALLED);
103
104 *numberOfConverters = __CFWin32EncodingIndex;
105 encodings = __CFWin32EncodingList;
106
107 __CFWin32EncodingIndex = 0;
108 __CFWin32EncodingList = NULL;
109
110 return encodings;
111 }
112 #else
113 __private_extern__ CFStringEncoding *__CFStringEncodingCreateListOfAvailablePlatformConverters(CFAllocatorRef allocator, CFIndex *numberOfConverters) { return NULL; }
114 #endif
115
116 __private_extern__ CFIndex __CFStringEncodingPlatformUnicodeToBytes(uint32_t encoding, uint32_t flags, const UniChar *characters, CFIndex numChars, CFIndex *usedCharLen, uint8_t *bytes, CFIndex maxByteLen, CFIndex *usedByteLen) {
117
118 #if DEPLOYMENT_TARGET_WINDOWS
119 WORD dwFlags = 0;
120 CFIndex usedLen;
121
122 dwFlags |= (flags & (kCFStringEncodingAllowLossyConversion|kCFStringEncodingSubstituteCombinings) ? WC_DEFAULTCHAR : 0);
123 dwFlags |= (flags & kCFStringEncodingComposeCombinings ? WC_COMPOSITECHECK : 0);
124 dwFlags |= (flags & kCFStringEncodingIgnoreCombinings ? WC_DISCARDNS : 0);
125
126 if ((usedLen = WideCharToMultiByte(CFStringConvertEncodingToWindowsCodepage(encoding), dwFlags, (LPCWSTR)characters, numChars, (LPSTR)bytes, maxByteLen, NULL, NULL)) == 0) {
127 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
128 CPINFO cpInfo;
129
130 if (!GetCPInfo(CFStringConvertEncodingToWindowsCodepage(encoding), &cpInfo)) {
131 cpInfo.MaxCharSize = 1; // Is this right ???
132 }
133 if (cpInfo.MaxCharSize == 1) {
134 numChars = maxByteLen;
135 } else {
136 usedLen = WideCharToMultiByte(CFStringConvertEncodingToWindowsCodepage(encoding), dwFlags, (LPCWSTR)characters, numChars, NULL, 0, NULL, NULL);
137 usedLen -= maxByteLen;
138 numChars = (numChars > usedLen ? numChars - usedLen : 1);
139 }
140 if (WideCharToMultiByte(CFStringConvertEncodingToWindowsCodepage(encoding), dwFlags, (LPCWSTR)characters, numChars, (LPSTR)bytes, maxByteLen, NULL, NULL) == 0) {
141 if (usedCharLen) *usedCharLen = 0;
142 if (usedByteLen) *usedByteLen = 0;
143 } else {
144 CFIndex lastUsedLen = 0;
145
146 while ((usedLen = WideCharToMultiByte(CFStringConvertEncodingToWindowsCodepage(encoding), dwFlags, (LPCWSTR)characters, ++numChars, (LPSTR)bytes, maxByteLen, NULL, NULL))) lastUsedLen = usedLen;
147 if (usedCharLen) *usedCharLen = (numChars - 1);
148 if (usedByteLen) *usedByteLen = lastUsedLen;
149 }
150
151 return kCFStringEncodingInsufficientOutputBufferLength;
152 } else {
153 return kCFStringEncodingInvalidInputStream;
154 }
155 } else {
156 if (usedCharLen) *usedCharLen = numChars;
157 if (usedByteLen) *usedByteLen = usedLen;
158 return kCFStringEncodingConversionSuccess;
159 }
160 #endif /* DEPLOYMENT_TARGET_WINDOWS */
161
162 return kCFStringEncodingConverterUnavailable;
163 }
164
165 __private_extern__ CFIndex __CFStringEncodingPlatformBytesToUnicode(uint32_t encoding, uint32_t flags, const uint8_t *bytes, CFIndex numBytes, CFIndex *usedByteLen, UniChar *characters, CFIndex maxCharLen, CFIndex *usedCharLen) {
166
167 #if DEPLOYMENT_TARGET_WINDOWS
168 WORD dwFlags = 0;
169 CFIndex usedLen;
170
171 dwFlags |= (flags & (kCFStringEncodingAllowLossyConversion|kCFStringEncodingSubstituteCombinings) ? 0 : MB_ERR_INVALID_CHARS);
172 dwFlags |= (flags & (kCFStringEncodingUseCanonical|kCFStringEncodingUseHFSPlusCanonical) ? MB_COMPOSITE : MB_PRECOMPOSED);
173
174 if ((usedLen = MultiByteToWideChar(CFStringConvertEncodingToWindowsCodepage(encoding), dwFlags, (LPCSTR)bytes, numBytes, (LPWSTR)characters, maxCharLen) == 0)) {
175 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
176 CPINFO cpInfo;
177
178 if (!GetCPInfo(CFStringConvertEncodingToWindowsCodepage(encoding), &cpInfo)) {
179 cpInfo.MaxCharSize = 1; // Is this right ???
180 }
181 if (cpInfo.MaxCharSize == 1) {
182 numBytes = maxCharLen;
183 } else {
184 usedLen = MultiByteToWideChar(CFStringConvertEncodingToWindowsCodepage(encoding), dwFlags, (LPCSTR)bytes, numBytes, (LPWSTR)characters, maxCharLen);
185 usedLen -= maxCharLen;
186 numBytes = (numBytes > usedLen ? numBytes - usedLen : 1);
187 }
188 while ((usedLen = MultiByteToWideChar(CFStringConvertEncodingToWindowsCodepage(encoding), dwFlags, (LPCSTR)bytes, numBytes, (LPWSTR)characters, maxCharLen)) == 0) {
189 if ((--numBytes) == 0) break;
190 }
191 if (usedCharLen) *usedCharLen = usedLen;
192 if (usedByteLen) *usedByteLen = numBytes;
193
194 return kCFStringEncodingInsufficientOutputBufferLength;
195 } else {
196 return kCFStringEncodingInvalidInputStream;
197 }
198 } else {
199 if (usedCharLen) *usedCharLen = usedLen;
200 if (usedByteLen) *usedByteLen = numBytes;
201 return kCFStringEncodingConversionSuccess;
202 }
203 #endif /* DEPLOYMENT_TARGET_WINDOWS */
204
205 return kCFStringEncodingConverterUnavailable;
206 }
207
208 __private_extern__ CFIndex __CFStringEncodingPlatformCharLengthForBytes(uint32_t encoding, uint32_t flags, const uint8_t *bytes, CFIndex numBytes) {
209 CFIndex usedCharLen;
210 return (__CFStringEncodingPlatformBytesToUnicode(encoding, flags, bytes, numBytes, NULL, NULL, 0, &usedCharLen) == kCFStringEncodingConversionSuccess ? usedCharLen : 0);
211 }
212
213 __private_extern__ CFIndex __CFStringEncodingPlatformByteLengthForCharacters(uint32_t encoding, uint32_t flags, const UniChar *characters, CFIndex numChars) {
214 CFIndex usedByteLen;
215 return (__CFStringEncodingPlatformUnicodeToBytes(encoding, flags, characters, numChars, NULL, NULL, 0, &usedByteLen) == kCFStringEncodingConversionSuccess ? usedByteLen : 0);
216 }
217
218 #undef __CFCarbonCore_GetTextEncodingBase0
219