mirror of
https://github.com/reactos/reactos.git
synced 2025-07-10 12:54:11 +00:00

Imported from https://www.nuget.org/packages/Microsoft.Windows.SDK.CRTSource/10.0.22621.3 License: MIT
94 lines
2.4 KiB
C++
94 lines
2.4 KiB
C++
//
|
|
// c16rtomb.cpp
|
|
//
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
//
|
|
|
|
#include <corecrt_internal_mbstring.h>
|
|
#include <corecrt_internal_ptd_propagation.h>
|
|
#include <uchar.h>
|
|
|
|
using namespace __crt_mbstring;
|
|
|
|
namespace
|
|
{
|
|
inline void store_first_surrogate(char16_t c16, mbstate_t* ps)
|
|
{
|
|
// Store the first (high) surrogate masked and shifted, so that all that's left to do
|
|
// is to add the maksed second surrogate.
|
|
// Note: _Wchar is the only field used in mbstate_t for this function
|
|
const char32_t c32 = ((c16 & ~0xd800) << 10) + 0x10000;
|
|
ps->_Wchar = c32;
|
|
}
|
|
|
|
inline char32_t combine_second_surrogate(char16_t c16, mbstate_t* ps)
|
|
{
|
|
return ps->_Wchar + (c16 & ~0xdc00);
|
|
}
|
|
|
|
inline constexpr bool has_surrogate(mbstate_t* ps)
|
|
{
|
|
return ps->_Wchar != 0;
|
|
}
|
|
|
|
inline constexpr bool is_first_surrogate(char16_t c16)
|
|
{
|
|
// UTF-16 high surrogate
|
|
return 0xd800 <= c16 && c16 <= 0xdbff;
|
|
}
|
|
|
|
inline constexpr bool is_second_surrogate(char16_t c16)
|
|
{
|
|
// UTF-16 low surrogate
|
|
return 0xdc00 <= c16 && c16 <= 0xdfff;
|
|
}
|
|
}
|
|
|
|
extern "C" size_t __cdecl c16rtomb(char* s, char16_t c16, mbstate_t* ps)
|
|
{
|
|
// TODO: Bug 13307590 says this is always assuming UTF-8.
|
|
__crt_cached_ptd_host ptd;
|
|
return __c16rtomb_utf8(s, c16, ps, ptd);
|
|
}
|
|
|
|
size_t __cdecl __crt_mbstring::__c16rtomb_utf8(char* s, char16_t c16, mbstate_t* ps, __crt_cached_ptd_host& ptd)
|
|
{
|
|
static mbstate_t internal_pst{};
|
|
if (ps == nullptr)
|
|
{
|
|
ps = &internal_pst;
|
|
}
|
|
|
|
if (!has_surrogate(ps))
|
|
{
|
|
if (is_second_surrogate(c16))
|
|
{
|
|
return return_illegal_sequence(ps, ptd);
|
|
}
|
|
else if (is_first_surrogate(c16))
|
|
{
|
|
store_first_surrogate(c16, ps);
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
return __c32rtomb_utf8(s, static_cast<char32_t>(c16), ps, ptd);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// We've already seen the first (high) surrogate, so we're
|
|
// expecting to complete this code point with its other half
|
|
// in the second (low) surrogate
|
|
if (!is_second_surrogate(c16))
|
|
{
|
|
return return_illegal_sequence(ps, ptd);
|
|
}
|
|
const char32_t c32 = combine_second_surrogate(c16, ps);
|
|
|
|
mbstate_t temp{};
|
|
const size_t retval = __c32rtomb_utf8(s, c32, &temp, ptd);
|
|
return reset_and_return(retval, ps);
|
|
}
|
|
}
|
|
|