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.

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