Reactos
1//
2// c16rtomb.cpp
3//
4// Copyright (c) Microsoft Corporation. All rights reserved.
5//
6
7#include <corecrt_internal_mbstring.h>
8#include <corecrt_internal_ptd_propagation.h>
9#include <uchar.h>
10
11using namespace __crt_mbstring;
12
13namespace
14{
15 inline void store_first_surrogate(char16_t c16, mbstate_t* ps)
16 {
17 // Store the first (high) surrogate masked and shifted, so that all that's left to do
18 // is to add the maksed second surrogate.
19 // Note: _Wchar is the only field used in mbstate_t for this function
20 const char32_t c32 = ((c16 & ~0xd800) << 10) + 0x10000;
21 ps->_Wchar = c32;
22 }
23
24 inline char32_t combine_second_surrogate(char16_t c16, mbstate_t* ps)
25 {
26 return ps->_Wchar + (c16 & ~0xdc00);
27 }
28
29 inline constexpr bool has_surrogate(mbstate_t* ps)
30 {
31 return ps->_Wchar != 0;
32 }
33
34 inline constexpr bool is_first_surrogate(char16_t c16)
35 {
36 // UTF-16 high surrogate
37 return 0xd800 <= c16 && c16 <= 0xdbff;
38 }
39
40 inline constexpr bool is_second_surrogate(char16_t c16)
41 {
42 // UTF-16 low surrogate
43 return 0xdc00 <= c16 && c16 <= 0xdfff;
44 }
45}
46
47extern "C" size_t __cdecl c16rtomb(char* s, char16_t c16, mbstate_t* ps)
48{
49 // TODO: Bug 13307590 says this is always assuming UTF-8.
50 __crt_cached_ptd_host ptd;
51 return __c16rtomb_utf8(s, c16, ps, ptd);
52}
53
54size_t __cdecl __crt_mbstring::__c16rtomb_utf8(char* s, char16_t c16, mbstate_t* ps, __crt_cached_ptd_host& ptd)
55{
56 static mbstate_t internal_pst{};
57 if (ps == nullptr)
58 {
59 ps = &internal_pst;
60 }
61
62 if (!has_surrogate(ps))
63 {
64 if (is_second_surrogate(c16))
65 {
66 return return_illegal_sequence(ps, ptd);
67 }
68 else if (is_first_surrogate(c16))
69 {
70 store_first_surrogate(c16, ps);
71 return 0;
72 }
73 else
74 {
75 return __c32rtomb_utf8(s, static_cast<char32_t>(c16), ps, ptd);
76 }
77 }
78 else
79 {
80 // We've already seen the first (high) surrogate, so we're
81 // expecting to complete this code point with its other half
82 // in the second (low) surrogate
83 if (!is_second_surrogate(c16))
84 {
85 return return_illegal_sequence(ps, ptd);
86 }
87 const char32_t c32 = combine_second_surrogate(c16, ps);
88
89 mbstate_t temp{};
90 const size_t retval = __c32rtomb_utf8(s, c32, &temp, ptd);
91 return reset_and_return(retval, ps);
92 }
93}
94