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.

373 lines
9.8 KiB

  1. /***
  2. *xmbtowc.c - Convert multibyte char to wide char.
  3. *
  4. * Copyright (c) 1995-2001, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. * Convert a multibyte character into the equivalent wide character.
  8. *
  9. *Revision History:
  10. * 12-XX-95 PJP Created from mbtowc.c December 1995 by P.J. Plauger
  11. * 04-17-96 GJF Updated for current locale locking. Also, reformatted
  12. * and made several cosmetic changes.
  13. * 09-25-96 GJF Made mbrlen, mbrtowc and mbsrtowcs multithread safe.
  14. * 09-17-97 JWM Added "return MB_CUR_MAX" to "if (*pst != 0)" branch.
  15. * 05-17-99 PML Remove all Macintosh support.
  16. * 01-29-01 GB Added _func function version of data variable used in msvcprt.lib
  17. * to work with STATIC_CPPLIB
  18. *
  19. *******************************************************************************/
  20. #include <cruntime.h>
  21. #include <stdlib.h>
  22. #include <mtdll.h>
  23. #include <errno.h>
  24. #include <dbgint.h>
  25. #include <ctype.h>
  26. #include <limits.h> /* for INT_MAX */
  27. #include <stdio.h> /* for EOF */
  28. #include <xlocinfo.h> /* for _Cvtvec, _Mbrtowc */
  29. #include <internal.h>
  30. #include <locale.h>
  31. #include <setlocal.h>
  32. #ifndef _MT
  33. #define _Mbrtowc_lk _Mbrtowc
  34. #endif
  35. /***
  36. *int _Mbrtowc() - Convert multibyte char to wide character.
  37. *
  38. *Purpose:
  39. * Convert a multi-byte character into the equivalent wide character,
  40. * according to the specified LC_CTYPE category, or the current locale.
  41. * [ANSI].
  42. *
  43. * NOTE: Currently, the C libraries support the "C" locale only.
  44. * Non-C locale support now available under _INTL switch.
  45. *Entry:
  46. * wchar_t *pwc = pointer to destination wide character
  47. * const char *s = pointer to multibyte character
  48. * size_t n = maximum length of multibyte character to consider
  49. * mbstate_t *pst = pointer to state
  50. * const _Cvtvec * = pointer to locale info
  51. *
  52. *Exit:
  53. * If s = NULL, returns 0, indicating we only use state-independent
  54. * character encodings.
  55. * If s != NULL, returns: 0 (if *s = null char)
  56. * -1 (if the next n or fewer bytes not valid mbc)
  57. * number of bytes comprising converted mbc
  58. *
  59. *Exceptions:
  60. *
  61. *******************************************************************************/
  62. #ifdef _MT
  63. static int __cdecl _Mbrtowc_lk
  64. (
  65. wchar_t *pwc,
  66. const char *s,
  67. size_t n,
  68. mbstate_t *pst,
  69. const _Cvtvec *ploc
  70. );
  71. int _CRTIMP2 __cdecl _Mbrtowc(
  72. wchar_t *pwc,
  73. const char *s,
  74. size_t n,
  75. mbstate_t *pst,
  76. const _Cvtvec *ploc
  77. )
  78. {
  79. int retval;
  80. #ifdef _MT
  81. int local_lock_flag;
  82. #endif
  83. _lock_locale( local_lock_flag )
  84. retval = _Mbrtowc_lk(pwc, s, n, pst, ploc);
  85. _unlock_locale( local_lock_flag )
  86. return retval;
  87. }
  88. #endif /* _MT */
  89. #ifdef _MT
  90. static int __cdecl _Mbrtowc_lk
  91. #else /* _MT */
  92. int _CRTIMP2 __cdecl _Mbrtowc
  93. #endif /* _MT */
  94. (
  95. wchar_t *pwc,
  96. const char *s,
  97. size_t n,
  98. mbstate_t *pst,
  99. const _Cvtvec *ploc
  100. )
  101. {
  102. _ASSERTE (___mb_cur_max_func() == 1 || ___mb_cur_max_func() == 2);
  103. if ( !s || n == 0 )
  104. /* indicate do not have state-dependent encodings,
  105. handle zero length string */
  106. return 0;
  107. if ( !*s )
  108. {
  109. /* handle NULL char */
  110. if (pwc)
  111. *pwc = 0;
  112. return 0;
  113. }
  114. { /* perform locale-dependent parse */
  115. LCID handle;
  116. UINT codepage;
  117. if (ploc == 0)
  118. {
  119. handle = ___lc_handle_func()[LC_CTYPE];
  120. codepage = ___lc_codepage_func();
  121. }
  122. else
  123. {
  124. handle = ploc->_Hand;
  125. codepage = ploc->_Page;
  126. }
  127. if ( handle == _CLOCALEHANDLE )
  128. {
  129. if (pwc)
  130. *pwc = (wchar_t)(unsigned char)*s;
  131. return sizeof(char);
  132. }
  133. if (*pst != 0)
  134. { /* complete two-byte multibyte character */
  135. ((char *)pst)[1] = *s;
  136. if (___mb_cur_max_func() <= 1 || (MultiByteToWideChar(codepage,
  137. MB_PRECOMPOSED|MB_ERR_INVALID_CHARS,
  138. (char *)pst, 2, pwc, (pwc) ? 1 : 0) == 0))
  139. { /* translation failed */
  140. *pst = 0;
  141. errno = EILSEQ;
  142. return -1;
  143. }
  144. *pst = 0;
  145. return ___mb_cur_max_func();
  146. }
  147. else if ( _cpp_isleadbyte((unsigned char)*s) )
  148. {
  149. /* multi-byte char */
  150. if (n < (size_t)___mb_cur_max_func())
  151. { /* save partial multibyte character */
  152. ((char *)pst)[0] = *s;
  153. return (-2);
  154. }
  155. else if ( ___mb_cur_max_func() <= 1 ||
  156. (MultiByteToWideChar( codepage,
  157. MB_PRECOMPOSED |
  158. MB_ERR_INVALID_CHARS,
  159. s,
  160. ___mb_cur_max_func(),
  161. pwc,
  162. (pwc) ? 1 : 0) == 0) )
  163. {
  164. /* validate high byte of mbcs char */
  165. if (!*(s+1))
  166. {
  167. *pst = 0;
  168. errno = EILSEQ;
  169. return -1;
  170. }
  171. /* else translation failed with no complaint? [pjp] */
  172. }
  173. return ___mb_cur_max_func();
  174. }
  175. else {
  176. /* single byte char */
  177. if ( MultiByteToWideChar( codepage,
  178. MB_PRECOMPOSED|MB_ERR_INVALID_CHARS,
  179. s,
  180. 1,
  181. pwc,
  182. (pwc) ? 1 : 0) == 0 )
  183. {
  184. errno = EILSEQ;
  185. return -1;
  186. }
  187. return sizeof(char);
  188. }
  189. }
  190. }
  191. /***
  192. *wint_t btowc(c) - translate single byte to wide char
  193. *
  194. *Purpose:
  195. *
  196. *Entry:
  197. *
  198. *Exit:
  199. *
  200. *Exceptions:
  201. *
  202. *******************************************************************************/
  203. wint_t _CRTIMP2 __cdecl btowc (
  204. int c
  205. )
  206. {
  207. if (c == EOF)
  208. return (WEOF);
  209. else
  210. { /* convert as one-byte string */
  211. char ch = (char)c;
  212. mbstate_t mbst = 0;
  213. wchar_t wc;
  214. return (_Mbrtowc(&wc, &ch, 1, &mbst, 0) < 0 ? WEOF : wc);
  215. }
  216. }
  217. /***
  218. *size_t mbrlen(s, n, pst) - determine next multibyte code, restartably
  219. *
  220. *Purpose:
  221. *
  222. *Entry:
  223. *
  224. *Exit:
  225. *
  226. *Exceptions:
  227. *
  228. *******************************************************************************/
  229. size_t _CRTIMP2 __cdecl mbrlen (
  230. const char *s,
  231. size_t n,
  232. mbstate_t *pst
  233. )
  234. {
  235. #ifdef _MT
  236. int local_lock_flag;
  237. #endif
  238. size_t retval;
  239. static mbstate_t mbst = {0};
  240. _lock_locale( local_lock_flag )
  241. retval = _Mbrtowc_lk(0, s != 0 ? s : 0, n, pst ? pst : &mbst, 0);
  242. _unlock_locale( local_lock_flag )
  243. return retval;
  244. }
  245. /***
  246. *size_t mbrtowc(pwc, s, n, pst) - translate multibyte to wchar_t, restartably
  247. *
  248. *Purpose:
  249. *
  250. *Entry:
  251. *
  252. *Exit:
  253. *
  254. *Exceptions:
  255. *
  256. *******************************************************************************/
  257. size_t _CRTIMP2 __cdecl mbrtowc (
  258. wchar_t *pwc,
  259. const char *s,
  260. size_t n,
  261. mbstate_t *pst
  262. )
  263. {
  264. #ifdef _MT
  265. int local_lock_flag;
  266. #endif
  267. size_t retval;
  268. static mbstate_t mbst = {0};
  269. _lock_locale( local_lock_flag )
  270. retval = (s != 0) ? _Mbrtowc_lk(pwc, s, n, pst ? pst : &mbst, 0)
  271. : _Mbrtowc_lk(0, "", n, pst ? pst : &mbst, 0);
  272. _unlock_locale( local_lock_flag )
  273. return retval;
  274. }
  275. /***
  276. *size_t mbsrtowcs(wcs, ps, n, pst) - translate multibyte string to wide,
  277. * restartably
  278. *
  279. *Purpose:
  280. *
  281. *Entry:
  282. *
  283. *Exit:
  284. *
  285. *Exceptions:
  286. *
  287. *******************************************************************************/
  288. size_t _CRTIMP2 __cdecl mbsrtowcs (
  289. wchar_t *wcs,
  290. const char **ps,
  291. size_t n,
  292. mbstate_t *pst
  293. )
  294. {
  295. const char *s = *ps;
  296. int i;
  297. size_t nwc = 0;
  298. #ifdef _MT
  299. int local_lock_flag;
  300. #endif
  301. static mbstate_t mbst = {0};
  302. if (pst == 0)
  303. pst = &mbst;
  304. _lock_locale( local_lock_flag )
  305. if (wcs == 0)
  306. for (; ; ++nwc, s += i)
  307. { /* translate but don't store */
  308. wchar_t wc;
  309. if ((i = _Mbrtowc_lk(&wc, s, INT_MAX, pst, 0)) < 0) {
  310. _unlock_locale( local_lock_flag )
  311. return ((size_t)-1);
  312. }
  313. else if (i == 0) {
  314. _unlock_locale( local_lock_flag )
  315. return (nwc);
  316. }
  317. }
  318. for (; 0 < n; ++nwc, s += i, ++wcs, --n)
  319. { /* translate and store */
  320. if ((i = _Mbrtowc_lk(wcs, s, INT_MAX, pst, 0)) < 0)
  321. { /* encountered invalid sequence */
  322. nwc = (size_t)-1;
  323. break;
  324. }
  325. else if (i == 0)
  326. { /* encountered terminating null */
  327. s = 0;
  328. break;
  329. }
  330. }
  331. *ps = s;
  332. _unlock_locale( local_lock_flag )
  333. return (nwc);
  334. }