xref: /reactos/sdk/lib/ucrt/convert/mblen.cpp (revision 04e0dc4a)
1 //
2 // mblen.cpp
3 //
4 //      Copyright (c) Microsoft Corporation. All rights reserved.
5 //
6 // The mblen() and _mblen_l() functions, which return the number of bytes
7 // contained in a multibyte character.
8 //
9 #include <corecrt_internal_mbstring.h>
10 #include <corecrt_internal_ptd_propagation.h>
11 
12 using namespace __crt_mbstring;
13 
14 // Computes the number of bytes contained in a multibyte character.  If the string
15 // is null, zero is returned to indicate that we support only state-independent
16 // character encodings.  If the next max_count bytes of the string are not a valid
17 // multibyte character, -1 is returned.  Otherwise, the number of bytes that
18 // compose the next multibyte character are returned.
_mblen_internal(char const * const string,size_t const max_count,__crt_cached_ptd_host & ptd)19 static int __cdecl _mblen_internal(
20     char const*        const string,
21     size_t             const max_count,
22     __crt_cached_ptd_host&   ptd
23     )
24 {
25     mbstate_t internal_state{};
26     if (!string || *string == '\0' || max_count == 0)
27     {
28         internal_state = {};
29         return 0;
30     }
31 
32     _locale_t const locale = ptd.get_locale();
33 
34     if (locale->locinfo->_public._locale_lc_codepage == CP_UTF8)
35     {
36         int result = static_cast<int>(__mbrtowc_utf8(nullptr, string, max_count, &internal_state, ptd));
37         if (result < 0)
38         {
39             result = -1;
40         }
41         return result;
42     }
43 
44     _ASSERTE(
45         locale->locinfo->_public._locale_mb_cur_max == 1 ||
46         locale->locinfo->_public._locale_mb_cur_max == 2);
47 
48     if (_isleadbyte_fast_internal(static_cast<unsigned char>(*string), locale))
49     {
50         _ASSERTE(locale->locinfo->_public._locale_lc_codepage != CP_UTF8 && L"UTF-8 isn't supported in this _mblen_l function yet!!!");
51 
52         // If this is a lead byte, then the codepage better be a multibyte codepage
53         _ASSERTE(locale->locinfo->_public._locale_mb_cur_max > 1);
54 
55         // Multi-byte character; verify that it is valid:
56         if (locale->locinfo->_public._locale_mb_cur_max <= 1)
57         {
58             return -1;
59         }
60 
61         if (max_count > INT_MAX || static_cast<int>(max_count) < locale->locinfo->_public._locale_mb_cur_max)
62         {
63             return -1;
64         }
65 
66         int const status = __acrt_MultiByteToWideChar(
67             locale->locinfo->_public._locale_lc_codepage,
68             MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
69             string,
70             locale->locinfo->_public._locale_mb_cur_max,
71             nullptr,
72             0);
73 
74         if (status == 0)
75         {
76             return -1;
77         }
78 
79         return locale->locinfo->_public._locale_mb_cur_max;
80     }
81     else
82     {
83         // Single byte character; verify that it is valid:
84         // CP_ACP is known to be valid for all values
85         if (locale->locinfo->_public._locale_lc_codepage != CP_ACP)
86         {
87             int const status = __acrt_MultiByteToWideChar(
88                 locale->locinfo->_public._locale_lc_codepage,
89                 MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
90                 string,
91                 1,
92                 nullptr,
93                 0);
94 
95             if (status == 0)
96             {
97                 return -1;
98             }
99         }
100 
101         return sizeof(char);
102     }
103 }
104 
_mblen_l(char const * const string,size_t const max_count,_locale_t const locale)105 extern "C" int __cdecl _mblen_l(
106     char const* const string,
107     size_t      const max_count,
108     _locale_t   const locale
109     )
110 {
111     __crt_cached_ptd_host ptd(locale);
112     return _mblen_internal(string, max_count, ptd);
113 }
114 
115 
116 
mblen(char const * const string,size_t const max_count)117 extern "C" int __cdecl mblen(
118     char const* const string,
119     size_t      const max_count
120     )
121 {
122     __crt_cached_ptd_host ptd;
123     return _mblen_internal(string, max_count, ptd);
124 }
125