FreeRDP
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 #include "../log.h"
40 #define TAG WINPR_TAG("unicode")
41 
42 int int_MultiByteToWideChar(UINT CodePage, DWORD dwFlags, LPCSTR lpMultiByteStr, int cbMultiByte,
43  LPWSTR lpWideCharStr, int cchWideChar)
44 {
45  const BOOL isNullTerminated = cbMultiByte < 0;
46 
47  /* If cbMultiByte is 0, the function fails */
48  if ((cbMultiByte == 0) || (cbMultiByte < -1))
49  return 0;
50 
51  /* If cbMultiByte is -1, the string is null-terminated */
52  if (isNullTerminated)
53  {
54  size_t len = strnlen(lpMultiByteStr, INT32_MAX);
55  if (len >= INT32_MAX)
56  return 0;
57  cbMultiByte = (int)len + 1;
58  }
59 
60  NSString *utf = [[NSString alloc] initWithBytes:lpMultiByteStr
61  length:cbMultiByte
62  encoding:NSUTF8StringEncoding];
63  if (!utf)
64  {
65  WLog_WARN(TAG, "[NSString alloc] NSUTF8StringEncoding failed [%d] '%s'", cbMultiByte,
66  lpMultiByteStr);
67  return -1;
68  }
69 
70  const WCHAR *utf16 =
71  (const WCHAR *)[utf cStringUsingEncoding:NSUTF16LittleEndianStringEncoding];
72  const size_t utf16ByteLen = [utf lengthOfBytesUsingEncoding:NSUTF16LittleEndianStringEncoding];
73  const size_t utf16CharLen = utf16ByteLen / sizeof(WCHAR);
74  if (!utf16)
75  {
76  WLog_WARN(TAG, "[utf cStringUsingEncoding:NSUTF16LittleEndianStringEncoding] failed");
77  return -1;
78  }
79 
80  if (cchWideChar == 0)
81  return utf16CharLen;
82  else if (cchWideChar < utf16CharLen)
83  {
84  SetLastError(ERROR_INSUFFICIENT_BUFFER);
85  return 0;
86  }
87  else
88  {
89  const size_t mlen = MIN((size_t)utf16CharLen, cchWideChar);
90  const size_t len = _wcsnlen(utf16, mlen);
91  memcpy(lpWideCharStr, utf16, len * sizeof(WCHAR));
92  if ((len < (size_t)cchWideChar) && (len > 0) && (lpWideCharStr[len - 1] != '\0'))
93  lpWideCharStr[len] = '\0';
94  return utf16CharLen;
95  }
96 }
97 
98 int int_WideCharToMultiByte(UINT CodePage, DWORD dwFlags, LPCWSTR lpWideCharStr, int cchWideChar,
99  LPSTR lpMultiByteStr, int cbMultiByte, LPCSTR lpDefaultChar,
100  LPBOOL lpUsedDefaultChar)
101 {
102  const BOOL isNullTerminated = cchWideChar < 0;
103 
104  /* If cchWideChar is 0, the function fails */
105  if ((cchWideChar == 0) || (cchWideChar < -1))
106  return 0;
107 
108  /* If cchWideChar is -1, the string is null-terminated */
109  if (isNullTerminated)
110  {
111  size_t len = _wcslen(lpWideCharStr);
112  if (len >= INT32_MAX)
113  return 0;
114  cchWideChar = (int)len + 1;
115  }
116 
117  NSString *utf = [[NSString alloc] initWithCharacters:lpWideCharStr length:cchWideChar];
118  if (!utf)
119  {
120  WLog_WARN(TAG, "[NSString alloc] initWithCharacters failed [%d] 'XXX'", cchWideChar);
121  return -1;
122  }
123 
124  const char *utf8 = [utf cStringUsingEncoding:NSUTF8StringEncoding];
125  const size_t utf8Len = [utf lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
126  if (!utf8)
127  {
128  WLog_WARN(TAG, "[utf cStringUsingEncoding:NSUTF8StringEncoding] failed");
129  return -1;
130  }
131 
132  if (cbMultiByte == 0)
133  return utf8Len;
134  else if (cbMultiByte < utf8Len)
135  {
136  SetLastError(ERROR_INSUFFICIENT_BUFFER);
137  return 0;
138  }
139  else
140  {
141  const size_t mlen = MIN((size_t)cbMultiByte, utf8Len);
142  const size_t len = strnlen(utf8, mlen);
143  memcpy(lpMultiByteStr, utf8, len * sizeof(char));
144  if ((len < (size_t)cbMultiByte) && (len > 0) && (lpMultiByteStr[len - 1] != '\0'))
145  lpMultiByteStr[len] = '\0';
146  return utf8Len;
147  }
148 }