Reactos
at master 119 lines 3.3 kB view raw
1// 2// _mbslen.cpp 3// 4// Copyright (c) Microsoft Corporation. All rights reserved. 5// 6// Defines the mbstrlen functions, which return the number of multibyte 7// characters in a multibyte string, excluding the null terminator. This 8// function is locale-dependent. If the string contains invalid multibyte 9// characters, -1 is returned and errno is set to EILSEQ. 10// 11// There are two variations of these functions: mbstrnlen (note the 'n'), 12// which takes a max_size, which is the maximum number of bytes to scan 13// in the string. These variations also validate their arguments. The 14// variations without the 'n' (mbstrlen) stop only when the null terminator 15// is reached and do not validate their arguments. 16// 17#include <corecrt_internal.h> 18#include <stdlib.h> 19 20 21 22_Check_return_ 23_Post_satisfies_((return <= _String_length_(string) && return <= max_size) || return == (size_t)-1) 24static size_t __cdecl common_mbstrlen_l( 25 char const* const string, 26 size_t const max_size, 27 _locale_t const locale 28 ) 29{ 30 _LocaleUpdate locale_update(locale); 31 32 _ASSERTE( 33 locale_update.GetLocaleT()->locinfo->_public._locale_mb_cur_max == 1 || 34 locale_update.GetLocaleT()->locinfo->_public._locale_mb_cur_max == 2); 35 36 // Handle single byte character sets: 37 if (locale_update.GetLocaleT()->locinfo->_public._locale_mb_cur_max == 1) 38 { 39 return strnlen(string, max_size); 40 } 41 42 // Verify that all of the multibyte characters are valid: 43 if (__acrt_MultiByteToWideChar( 44 locale_update.GetLocaleT()->locinfo->_public._locale_lc_codepage, 45 MB_PRECOMPOSED | MB_ERR_INVALID_CHARS, 46 string, 47 static_cast<int>(max_size), 48 nullptr, 49 0 50 ) == 0) 51 { 52 // There was a bad multibyte character: 53 errno = EILSEQ; 54 return static_cast<size_t>(-1); 55 } 56 57 // Count multibyte characters: 58 size_t n = 0; // Number of multibyte characters read 59 size_t size = 0; // Number of bytes read 60 for (char const* it = string; size < max_size && *it; ++n, ++it, ++size) 61 { 62 if (_isleadbyte_fast_internal(static_cast<unsigned char>(*it), locale_update.GetLocaleT())) 63 { 64 ++size; 65 if (size >= max_size) 66 break; 67 68 ++it; 69 if (*it == '\0') 70 break; 71 } 72 } 73 74 return size >= max_size ? max_size : n; 75} 76 77 78 79extern "C" size_t __cdecl _mbstrlen_l( 80 char const* const string, 81 _locale_t const locale 82 ) 83{ 84 return common_mbstrlen_l(string, _CRT_UNBOUNDED_BUFFER_SIZE, locale); 85} 86 87extern "C" size_t __cdecl _mbstrlen(char const* const string) 88{ 89 if (!__acrt_locale_changed()) 90 { 91 return strlen(string); 92 } 93 else 94 { 95 return _mbstrlen_l(string, nullptr); 96 } 97} 98 99 100 101extern "C" size_t __cdecl _mbstrnlen_l( 102 char const* const string, 103 size_t const max_size, 104 _locale_t const locale 105 ) 106{ 107 _VALIDATE_RETURN(string != nullptr, EINVAL, static_cast<size_t>(-1)); 108 _VALIDATE_RETURN(max_size <= INT_MAX, EINVAL, static_cast<size_t>(-1)); 109 110 return common_mbstrlen_l(string, max_size, locale); 111} 112 113extern "C" size_t __cdecl _mbstrnlen( 114 char const* const string, 115 size_t const max_size 116 ) 117{ 118 return _mbstrnlen_l(string, max_size, nullptr); 119}