home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / vc98 / crt / src / xmbtowc.c < prev    next >
C/C++ Source or Header  |  1998-06-16  |  10KB  |  384 lines

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