Reactos
at master 124 lines 3.6 kB view raw
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 12using 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. 19static 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 105extern "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 117extern "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}