FreeRDP
Loading...
Searching...
No Matches
unicode_apple.m
1
21#import <Foundation/Foundation.h>
22
23#include <winpr/config.h>
24#include <winpr/assert.h>
25
26#include <errno.h>
27#include <wctype.h>
28
29#include <winpr/crt.h>
30#include <winpr/error.h>
31#include <winpr/print.h>
32
33#include "unicode.h"
34
35#ifndef MIN
36#define MIN(a, b) (a) < (b) ? (a) : (b)
37#endif
38
39#if __has_feature(objc_arc)
40#define COND_AUTORELEASE(x) x
41#else
42#define COND_AUTORELEASE(x) [x autorelease]
43#endif
44
45#include "../log.h"
46#define TAG WINPR_TAG("unicode")
47
48int int_MultiByteToWideChar(UINT CodePage, DWORD dwFlags, LPCSTR lpMultiByteStr, int cbMultiByte,
49 LPWSTR lpWideCharStr, int cchWideChar)
50{
51 const BOOL isNullTerminated = cbMultiByte < 0;
52
53 /* If cbMultiByte is 0, the function fails */
54 if ((cbMultiByte == 0) || (cbMultiByte < -1))
55 return 0;
56
57 /* If cbMultiByte is -1, the string is null-terminated */
58 if (isNullTerminated)
59 {
60 size_t len = strnlen(lpMultiByteStr, INT32_MAX);
61 if (len >= INT32_MAX)
62 return 0;
63 cbMultiByte = (int)len + 1;
64 }
65
66 NSString *utf = COND_AUTORELEASE([[NSString alloc] initWithBytes:lpMultiByteStr
67 length:cbMultiByte
68 encoding:NSUTF8StringEncoding]);
69 if (!utf)
70 {
71 WLog_WARN(TAG, "[NSString alloc] NSUTF8StringEncoding failed [%d] '%s'", cbMultiByte,
72 lpMultiByteStr);
73 return -1;
74 }
75
76 const WCHAR *utf16 =
77 (const WCHAR *)[utf cStringUsingEncoding:NSUTF16LittleEndianStringEncoding];
78 const size_t utf16ByteLen = [utf lengthOfBytesUsingEncoding:NSUTF16LittleEndianStringEncoding];
79 const size_t utf16CharLen = utf16ByteLen / sizeof(WCHAR);
80 if (!utf16)
81 {
82 WLog_WARN(TAG, "[utf cStringUsingEncoding:NSUTF16LittleEndianStringEncoding] failed");
83 return -1;
84 }
85
86 if (cchWideChar == 0)
87 return WINPR_ASSERTING_INT_CAST(int, utf16CharLen);
88 else if (cchWideChar < utf16CharLen)
89 {
90 SetLastError(ERROR_INSUFFICIENT_BUFFER);
91 return 0;
92 }
93 else
94 {
95 const size_t mlen = MIN((size_t)utf16CharLen, cchWideChar);
96 const size_t len = _wcsnlen(utf16, mlen);
97 memcpy(lpWideCharStr, utf16, len * sizeof(WCHAR));
98 if ((len < (size_t)cchWideChar) &&
99 ((len == 0) || ((len > 0) && (lpWideCharStr[len - 1] != '\0'))))
100 lpWideCharStr[len] = '\0';
101 return WINPR_ASSERTING_INT_CAST(int, utf16CharLen);
102 }
103}
104
105int int_WideCharToMultiByte(UINT CodePage, DWORD dwFlags, LPCWSTR lpWideCharStr, int cchWideChar,
106 LPSTR lpMultiByteStr, int cbMultiByte, LPCSTR lpDefaultChar,
107 LPBOOL lpUsedDefaultChar)
108{
109 const BOOL isNullTerminated = cchWideChar < 0;
110
111 /* If cchWideChar is 0, the function fails */
112 if ((cchWideChar == 0) || (cchWideChar < -1))
113 return 0;
114
115 /* If cchWideChar is -1, the string is null-terminated */
116 if (isNullTerminated)
117 {
118 size_t len = _wcslen(lpWideCharStr);
119 if (len >= INT32_MAX)
120 return 0;
121 cchWideChar = (int)len + 1;
122 }
123
124 NSString *utf = COND_AUTORELEASE([[NSString alloc] initWithCharacters:lpWideCharStr
125 length:cchWideChar]);
126 if (!utf)
127 {
128 WLog_WARN(TAG, "[NSString alloc] initWithCharacters failed [%d] 'XXX'", cchWideChar);
129 return -1;
130 }
131
132 const char *utf8 = [utf cStringUsingEncoding:NSUTF8StringEncoding];
133 const size_t utf8Len = [utf lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
134 if (!utf8)
135 {
136 WLog_WARN(TAG, "[utf cStringUsingEncoding:NSUTF8StringEncoding] failed");
137 return -1;
138 }
139
140 if (cbMultiByte == 0)
141 return WINPR_ASSERTING_INT_CAST(int, utf8Len);
142 else if (cbMultiByte < utf8Len)
143 {
144 SetLastError(ERROR_INSUFFICIENT_BUFFER);
145 return 0;
146 }
147 else
148 {
149 const size_t mlen = MIN((size_t)cbMultiByte, utf8Len);
150 const size_t len = strnlen(utf8, mlen);
151 memcpy(lpMultiByteStr, utf8, len * sizeof(char));
152 if ((len < (size_t)cbMultiByte) && (len > 0) && (lpMultiByteStr[len - 1] != '\0'))
153 lpMultiByteStr[len] = '\0';
154 return WINPR_ASSERTING_INT_CAST(int, utf8Len);
155 }
156}