21#import <Foundation/Foundation.h>
23#include <winpr/config.h>
24#include <winpr/assert.h>
30#include <winpr/error.h>
31#include <winpr/print.h>
36#define MIN(a, b) (a) < (b) ? (a) : (b)
39#if __has_feature(objc_arc)
40#define COND_AUTORELEASE(x) x
42#define COND_AUTORELEASE(x) [x autorelease]
46#define TAG WINPR_TAG("unicode")
48int int_MultiByteToWideChar(UINT CodePage, DWORD dwFlags, LPCSTR lpMultiByteStr,
int cbMultiByte,
49 LPWSTR lpWideCharStr,
int cchWideChar)
51 const BOOL isNullTerminated = cbMultiByte < 0;
54 if ((cbMultiByte == 0) || (cbMultiByte < -1))
60 size_t len = strnlen(lpMultiByteStr, INT32_MAX);
63 cbMultiByte = (int)len + 1;
66 NSString *utf = COND_AUTORELEASE([[NSString alloc] initWithBytes:lpMultiByteStr
68 encoding:NSUTF8StringEncoding]);
71 WLog_WARN(TAG,
"[NSString alloc] NSUTF8StringEncoding failed [%d] '%s'", cbMultiByte,
77 (
const WCHAR *)[utf cStringUsingEncoding:NSUTF16LittleEndianStringEncoding];
78 const size_t utf16ByteLen = [utf lengthOfBytesUsingEncoding:NSUTF16LittleEndianStringEncoding];
79 const size_t utf16CharLen = utf16ByteLen /
sizeof(WCHAR);
82 WLog_WARN(TAG,
"[utf cStringUsingEncoding:NSUTF16LittleEndianStringEncoding] failed");
87 return WINPR_ASSERTING_INT_CAST(
int, utf16CharLen);
88 else if (cchWideChar < utf16CharLen)
90 SetLastError(ERROR_INSUFFICIENT_BUFFER);
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);
105int int_WideCharToMultiByte(UINT CodePage, DWORD dwFlags, LPCWSTR lpWideCharStr,
int cchWideChar,
106 LPSTR lpMultiByteStr,
int cbMultiByte, LPCSTR lpDefaultChar,
107 LPBOOL lpUsedDefaultChar)
109 const BOOL isNullTerminated = cchWideChar < 0;
112 if ((cchWideChar == 0) || (cchWideChar < -1))
116 if (isNullTerminated)
118 size_t len = _wcslen(lpWideCharStr);
119 if (len >= INT32_MAX)
121 cchWideChar = (int)len + 1;
124 NSString *utf = COND_AUTORELEASE([[NSString alloc] initWithCharacters:lpWideCharStr
125 length:cchWideChar]);
128 WLog_WARN(TAG,
"[NSString alloc] initWithCharacters failed [%d] 'XXX'", cchWideChar);
132 const char *utf8 = [utf cStringUsingEncoding:NSUTF8StringEncoding];
133 const size_t utf8Len = [utf lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
136 WLog_WARN(TAG,
"[utf cStringUsingEncoding:NSUTF8StringEncoding] failed");
140 if (cbMultiByte == 0)
141 return WINPR_ASSERTING_INT_CAST(
int, utf8Len);
142 else if (cbMultiByte < utf8Len)
144 SetLastError(ERROR_INSUFFICIENT_BUFFER);
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);