Source code of Windows XP (NT5)
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.

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