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

  1. /***
  2. *wcsxfrm.c - Transform a wide-character string using locale information
  3. *
  4. *       Copyright (c) 1988-1998, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. *       Transform a wide-character string using the locale information as set by
  8. *       LC_COLLATE.
  9. *
  10. *******************************************************************************/
  11.  
  12.  
  13. #include <cruntime.h>
  14. #include <windows.h>
  15. #include <string.h>
  16. #include <limits.h>
  17. #include <locale.h>
  18. #include <setlocal.h>
  19. #include <stdlib.h>
  20. #include <mtdll.h>
  21. #include <awint.h>
  22. #include <dbgint.h>
  23.  
  24. /***
  25. *size_t wcsxfrm() - Transform a string using locale information
  26. *
  27. *Purpose:
  28. *       Transform the wide string pointed to by _string2 and place the
  29. *       resulting wide string into the array pointed to by _string1.
  30. *       No more than _count wide characters are placed into the
  31. *       resulting string (including the null).
  32. *
  33. *       The transformation is such that if wcscmp() is applied to
  34. *       the two transformed strings, the return value is equal to
  35. *       the result of wcscoll() applied to the two original strings.
  36. *       Thus, the conversion must take the locale LC_COLLATE info
  37. *       into account.
  38. *
  39. *       In the C locale, wcsxfrm() simply resolves to wcsncpy()/wcslen().
  40. *
  41. *Entry:
  42. *       wchar_t *_string1       = result string
  43. *       const wchar_t *_string2 = source string
  44. *       size_t _count           = max wide chars to move
  45. *
  46. *       [If _count is 0, _string1 is permitted to be NULL.]
  47. *
  48. *Exit:
  49. *       Length of the transformed string (not including the terminating
  50. *       null).  If the value returned is >= _count, the contents of the
  51. *       _string1 array are indeterminate.
  52. *
  53. *Exceptions:
  54. *       Non-standard: if OM/API error, return INT_MAX.
  55. *
  56. *******************************************************************************/
  57.  
  58. size_t __cdecl wcsxfrm (
  59.         wchar_t *_string1,
  60.         const wchar_t *_string2,
  61.         size_t _count
  62.         )
  63. {
  64.  
  65.         int size = INT_MAX;
  66.         unsigned char *bbuffer;
  67. #if defined (_MT)
  68.         int local_lock_flag;
  69. #endif  /* defined (_MT) */
  70.  
  71.         if (__lc_handle[LC_COLLATE] == _CLOCALEHANDLE) {
  72.             wcsncpy(_string1, _string2, _count);
  73.             return wcslen(_string2);
  74.         }
  75.  
  76.         _lock_locale( local_lock_flag )
  77.  
  78. #if defined (_MT)
  79.         if (__lc_handle[LC_COLLATE] == _CLOCALEHANDLE) {
  80.             _unlock_locale( local_lock_flag )
  81.             wcsncpy(_string1, _string2, _count);
  82.             return wcslen(_string2);
  83.         }
  84. #endif  /* defined (_MT) */
  85.  
  86.         /*
  87.          * When using LCMAP_SORTKEY, LCMapStringW handles BYTES not wide
  88.          * chars. We use a byte buffer to hold bytes and then convert the
  89.          * byte string to a wide char string and return this so it can be
  90.          * compared using wcscmp(). User's buffer is _count wide chars, so
  91.          * use an internal buffer of _count bytes.
  92.          */
  93.  
  94.         if (NULL == (bbuffer = (unsigned char *)_malloc_crt(_count)))
  95.             goto error_cleanup;
  96.  
  97.         if ( 0 == (size = __crtLCMapStringW( __lc_handle[LC_COLLATE],
  98.                                              LCMAP_SORTKEY,
  99.                                              _string2,
  100.                                              -1,
  101.                                              (wchar_t *)bbuffer,
  102.                                              _count,
  103.                                              __lc_collate_cp )) )
  104.         {
  105.             /* buffer not big enough, get size required. */
  106.  
  107.             if ( 0 == (size = __crtLCMapStringW( __lc_handle[LC_COLLATE],
  108.                                                  LCMAP_SORTKEY,
  109.                                                  _string2,
  110.                                                  -1,
  111.                                                  NULL,
  112.                                                  0,
  113.                                                  __lc_collate_cp )) )
  114.                    size = INT_MAX; /* default error */
  115.             else
  116.                 size--; /* don't count NULL */
  117.  
  118.         } else {
  119.             int i;
  120.             /* string successfully mapped, convert to wide char */
  121.  
  122.             for (i = 0; i < size; i++)
  123.                 _string1[i] = (wchar_t)bbuffer[i];
  124.  
  125.             size--; /* don't count NULL */
  126.         }
  127.  
  128. error_cleanup:
  129.         _unlock_locale( local_lock_flag )
  130.         _free_crt(bbuffer);
  131.  
  132.         return (size_t)size;
  133.  
  134.  
  135. }
  136.  
  137.