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