Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

316 lines
7.5 KiB

  1. /***
  2. *xwctomb.c - Convert wide character to multibyte character, with locale.
  3. *
  4. * Copyright (c) 1995-2001, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. * Convert a wide character into the equivalent multibyte character.
  8. *
  9. *Revision History:
  10. * 12-XX-95 PJP Created from wctomb.c December 1995 by P.J. Plauger
  11. * 04-18-96 GJF Updated for current locale locking. Also, reformatted
  12. * and made several cosmetic changes.
  13. * 09-26-96 GJF Made _Getcvt() and wcsrtombs() multithread safe.
  14. *
  15. *******************************************************************************/
  16. #include <cruntime.h>
  17. #include <stdlib.h>
  18. #include <mtdll.h>
  19. #include <errno.h>
  20. #include <limits.h> /* for MB_LEN_MAX */
  21. #include <string.h> /* for memcpy */
  22. #include <stdio.h> /* for EOF */
  23. #include <xlocinfo.h> /* for _Cvtvec, _Wcrtomb */
  24. #ifdef _WIN32
  25. #include <locale.h>
  26. #include <setlocal.h>
  27. #endif /* _WIN32 */
  28. #ifndef _MT
  29. #define __Wcrtomb_lk _Wcrtomb
  30. #endif
  31. /***
  32. *int _Wcrtomb() - Convert wide character to multibyte character.
  33. *
  34. *Purpose:
  35. * Convert a wide character into the equivalent multi-byte character,
  36. * according to the specified LC_CTYPE category, or the current locale.
  37. * [ANSI].
  38. *
  39. * NOTE: Currently, the C libraries support the "C" locale only.
  40. * Non-C locale support now available under _INTL switch.
  41. *Entry:
  42. * char *s = pointer to multibyte character
  43. * wchar_t wchar = source wide character
  44. * mbstate_t *pst = pointer to state (not used)
  45. * const _Cvtvec *ploc = pointer to locale info
  46. *
  47. *Exit:
  48. * Returns:
  49. * -1 (if error) or number of bytes comprising converted mbc
  50. *
  51. *Exceptions:
  52. *
  53. *******************************************************************************/
  54. #ifdef _MT
  55. _CRTIMP2 int __cdecl __Wcrtomb_lk
  56. (
  57. char *s,
  58. wchar_t wchar,
  59. mbstate_t *,
  60. const _Cvtvec *ploc
  61. );
  62. _CRTIMP2 int __cdecl _Wcrtomb
  63. (
  64. char *s,
  65. wchar_t wchar,
  66. mbstate_t *pst,
  67. const _Cvtvec *ploc
  68. )
  69. {
  70. int retval;
  71. int local_lock_flag;
  72. _lock_locale( local_lock_flag )
  73. retval = __Wcrtomb_lk(s, wchar, 0, ploc);
  74. _unlock_locale( local_lock_flag )
  75. return retval;
  76. }
  77. #endif /* _MT */
  78. #ifdef _MT
  79. _CRTIMP2 int __cdecl __Wcrtomb_lk
  80. #else /* _MT */
  81. _CRTIMP2 int __cdecl _Wcrtomb
  82. #endif /* _MT */
  83. (
  84. char *s,
  85. wchar_t wchar,
  86. mbstate_t *pst,
  87. const _Cvtvec *ploc
  88. )
  89. {
  90. #ifdef _WIN32
  91. LCID handle;
  92. UINT codepage;
  93. if (ploc == 0)
  94. {
  95. handle = __lc_handle[LC_CTYPE];
  96. codepage = __lc_codepage;
  97. }
  98. else
  99. {
  100. handle = ploc->_Hand;
  101. codepage = ploc->_Page;
  102. }
  103. if ( handle == _CLOCALEHANDLE )
  104. {
  105. if ( wchar > 255 ) /* validate high byte */
  106. {
  107. errno = EILSEQ;
  108. return -1;
  109. }
  110. *s = (char) wchar;
  111. return sizeof(char);
  112. } else {
  113. int size;
  114. BOOL defused = 0;
  115. if ( ((size = WideCharToMultiByte(codepage,
  116. WC_COMPOSITECHECK | WC_SEPCHARS,
  117. &wchar,
  118. 1,
  119. s,
  120. MB_CUR_MAX,
  121. NULL,
  122. &defused)) == 0) ||
  123. (defused) )
  124. {
  125. errno = EILSEQ;
  126. return -1;
  127. }
  128. return size;
  129. }
  130. #else /* _WIN32 */
  131. if ( wchar > 255 ) /* validate high byte */
  132. {
  133. errno = EILSEQ;
  134. return -1;
  135. }
  136. *s = (char) wchar;
  137. return sizeof(char);
  138. #endif /* _WIN32 */
  139. }
  140. /***
  141. *_Cvtvec _Getcvt() - get conversion info for current locale
  142. *
  143. *Purpose:
  144. *
  145. *Entry:
  146. *
  147. *Exit:
  148. *
  149. *Exceptions:
  150. *
  151. *******************************************************************************/
  152. _CRTIMP2 _Cvtvec __cdecl _Getcvt()
  153. {
  154. _Cvtvec cvt;
  155. #ifdef _MT
  156. int local_lock_flag;
  157. #endif
  158. _lock_locale( local_lock_flag )
  159. cvt._Hand = __lc_handle[LC_CTYPE];
  160. cvt._Page = __lc_codepage;
  161. _unlock_locale( local_lock_flag )
  162. return (cvt);
  163. }
  164. /***
  165. *size_t wcrtomb(s, wchar, pst) - translate wchar_t to multibyte, restartably
  166. *
  167. *Purpose:
  168. *
  169. *Entry:
  170. *
  171. *Exit:
  172. *
  173. *Exceptions:
  174. *
  175. *******************************************************************************/
  176. _CRTIMP2 size_t __cdecl wcrtomb(
  177. char *s,
  178. wchar_t wchar,
  179. mbstate_t *pst
  180. )
  181. {
  182. return (s == 0 ? 1 : _Wcrtomb(s, wchar, 0, 0));
  183. }
  184. /***
  185. *size_t wcsrtombs(s, pwcs, n, pst) - translate wide char string to multibyte
  186. * string
  187. *
  188. *Purpose:
  189. *
  190. *Entry:
  191. *
  192. *Exit:
  193. *
  194. *Exceptions:
  195. *
  196. *******************************************************************************/
  197. _CRTIMP2 size_t __cdecl wcsrtombs(
  198. char *s,
  199. const wchar_t **pwcs,
  200. size_t n,
  201. mbstate_t *pst
  202. )
  203. {
  204. char buf[MB_LEN_MAX];
  205. int i;
  206. size_t nc = 0;
  207. const wchar_t *wcs = *pwcs;
  208. #ifdef _MT
  209. int local_lock_flag;
  210. #endif
  211. _lock_locale( local_lock_flag )
  212. if (s == 0)
  213. for (; ; nc += i, ++wcs)
  214. { /* translate but don't store */
  215. if ((i = __Wcrtomb_lk(buf, *wcs, 0, 0)) <= 0) {
  216. _unlock_locale( local_lock_flag )
  217. return ((size_t)-1);
  218. }
  219. else if (buf[i - 1] == '\0') {
  220. _unlock_locale( local_lock_flag )
  221. return (nc + i - 1);
  222. }
  223. }
  224. for (; 0 < n; nc += i, ++wcs, s += i, n -= i)
  225. { /* translate and store */
  226. char *t;
  227. if (n < MB_CUR_MAX)
  228. t = buf;
  229. else
  230. t = s;
  231. if ((i = __Wcrtomb_lk(t, *wcs, 0, 0)) <= 0)
  232. { /* encountered invalid sequence */
  233. nc = (size_t)-1;
  234. break;
  235. }
  236. if (s == t)
  237. ;
  238. else if (n < i)
  239. break; /* won't all fit */
  240. else
  241. memcpy(s, buf, i);
  242. if (s[i - 1] == '\0')
  243. { /* encountered terminating null */
  244. *pwcs = 0;
  245. _unlock_locale( local_lock_flag )
  246. return (nc + i - 1);
  247. }
  248. }
  249. _unlock_locale( local_lock_flag )
  250. *pwcs = wcs;
  251. return (nc);
  252. }
  253. /***
  254. *int wctob(wchar) - translate wint_t to one-byte multibyte
  255. *
  256. *Purpose:
  257. *
  258. *Entry:
  259. *
  260. *Exit:
  261. *
  262. *Exceptions:
  263. *
  264. *******************************************************************************/
  265. _CRTIMP2 int __cdecl wctob(
  266. wint_t wchar
  267. )
  268. {
  269. if (wchar == WEOF)
  270. return (EOF);
  271. else
  272. { /* check for one-byte translation */
  273. char buf[MB_LEN_MAX];
  274. return (_Wcrtomb(buf, wchar, 0, 0) == 1 ? buf[0] : EOF);
  275. }
  276. }