The MinGW.org Windows System Libraries
修订版 | 5ffd683d2c767408f674e9ac9484210e85d581ed (tree) |
---|---|
时间 | 2020-04-03 04:37:13 |
作者 | Keith Marshall <keith@user...> |
Commiter | Keith Marshall |
Handle wcsrtombs() initial surrogate completion.
@@ -1,5 +1,14 @@ | ||
1 | 1 | 2020-04-02 Keith Marshall <keith@users.osdn.me> |
2 | 2 | |
3 | + Handle wcsrtombs() initial surrogate completion. | |
4 | + | |
5 | + * mingwex/wcsrtombs.c (__mingw_wcsrtombs_fallback) | |
6 | + [*ps -> high surrogate && **wcs -> low surrogate]: Complete surrogate | |
7 | + pair, and evaluate conversion; compute its length, and account for its | |
8 | + effect on alloted conversion buffer size. Reset *ps to initial state. | |
9 | + | |
10 | +2020-04-02 Keith Marshall <keith@users.osdn.me> | |
11 | + | |
3 | 12 | Correct wchar_t to MBCS unpaired surrogate handling. |
4 | 13 | |
5 | 14 | * mingwex/wcharmap.c (__mingw_wctomb_convert) [codeset >= CP_UTF7]: |
@@ -41,7 +41,7 @@ | ||
41 | 41 | |
42 | 42 | static size_t __mingw_wcsrtombs_fallback |
43 | 43 | ( char *restrict mbs, const wchar_t **restrict wcs, size_t len, |
44 | - mbstate_t *__UNUSED_PARAM(ps) | |
44 | + mbstate_t *restrict ps | |
45 | 45 | ) |
46 | 46 | { /* Fallback function, providing an implementation of the wcsrtombs() |
47 | 47 | * function, when none is available within the Microsoft C runtime, or |
@@ -52,7 +52,31 @@ static size_t __mingw_wcsrtombs_fallback | ||
52 | 52 | * the size of buffer required to accommodate the conversion. |
53 | 53 | */ |
54 | 54 | int errno_reset = save_error_status_and_clear( errno, 0 ); |
55 | - size_t wanted = __mingw_wctomb_convert( NULL, 0, *wcs, -1 ); | |
55 | + union { mbstate_t ps; wchar_t wc[2]; } resume = { (mbstate_t)(0) }; | |
56 | + size_t count = (size_t)(0), wanted = (size_t)(0); | |
57 | + | |
58 | + /* This wcsrtombs() implementation will not use any mbstate... | |
59 | + */ | |
60 | + if( ps != NULL ) | |
61 | + { /* ...unless it is provided by the caller, in which case we will, | |
62 | + * ultimately, reset it to initial state, after processing it... | |
63 | + */ | |
64 | + resume.ps = *ps; | |
65 | + *ps = (mbstate_t)(0); | |
66 | + if( IS_SURROGATE_PAIR( resume.wc[0], **wcs ) ) | |
67 | + { /* ...subject to the expectation that it represents deferred | |
68 | + * completion of a surrogate pair. | |
69 | + */ | |
70 | + resume.wc[1] = *(*wcs)++; | |
71 | + count = __mingw_wctomb_convert( NULL, 0, resume.wc, 2 ); | |
72 | + } | |
73 | + } | |
74 | + | |
75 | + /* The total buffer space wanted is the aggregate of any deferred | |
76 | + * surrogate pair completion, plus the contribution from conversion | |
77 | + * of the remainder of the wide character string. | |
78 | + */ | |
79 | + wanted = count + __mingw_wctomb_convert( NULL, 0, *wcs, -1 ); | |
56 | 80 | |
57 | 81 | if( mbs == NULL ) |
58 | 82 | /* There is no buffer designated to store the encoded multibyte |
@@ -69,7 +93,9 @@ static size_t __mingw_wcsrtombs_fallback | ||
69 | 93 | * initial minimum buffer size determination; encode the entire |
70 | 94 | * input sequence for return, and clean up the input state. |
71 | 95 | */ |
72 | - len = __mingw_wctomb_convert( mbs, len, *wcs, -1 ) - 1; | |
96 | + if( count != (size_t)(0) ) | |
97 | + mbs += __mingw_wctomb_convert( mbs, len, resume.wc, 2 ); | |
98 | + count += __mingw_wctomb_convert( mbs, len - count, *wcs, -1 ) - 1; | |
73 | 99 | *wcs = NULL; |
74 | 100 | } |
75 | 101 |
@@ -80,7 +106,21 @@ static size_t __mingw_wcsrtombs_fallback | ||
80 | 106 | * either exhaust the encoding buffer space, or we encounter the |
81 | 107 | * encoding error previously identified. |
82 | 108 | */ |
83 | - size_t count = 0; errno = 0; | |
109 | + errno = 0; | |
110 | + | |
111 | + /* Initially, if there's a pending surrogate completion, and there | |
112 | + * is insufficient buffer space to accommodate its conversion, then | |
113 | + * we must squash all conversion... | |
114 | + */ | |
115 | + if( count > len ) count = len = 0; | |
116 | + else if( count != 0 ) | |
117 | + { /* ...otherwise, we store the completed surrogate conversion, at | |
118 | + * the start of the buffer, adjusting the buffer pointer, and its | |
119 | + * residual length counter, to suit. | |
120 | + */ | |
121 | + mbs += __mingw_wctomb_convert( mbs, len, resume.wc, 2 ); | |
122 | + len -= count; | |
123 | + } | |
84 | 124 | while( (len >= __mingw_wctomb_convert( NULL, 0, *wcs, 1 )) && (errno == 0) ) |
85 | 125 | { |
86 | 126 | /* There is still sufficient space to store the encoding of one |
@@ -96,20 +136,12 @@ static size_t __mingw_wcsrtombs_fallback | ||
96 | 136 | * if we did, then we must bail out. |
97 | 137 | */ |
98 | 138 | if( errno != 0 ) return (size_t)(-1); |
99 | - | |
100 | - /* If we're still here, then we've encoded as much of the input | |
101 | - * sequence as we can accommodate; the input pointer has already | |
102 | - * been adjusted, as required, but we must preserve the count of | |
103 | - * cumulatively encoded bytes, for return. | |
104 | - */ | |
105 | - len = count; | |
106 | 139 | } |
107 | - | |
108 | 140 | /* We have now successfully encoded as much of the input sequence |
109 | 141 | * as possible, without encountering any encoding error; restore |
110 | 142 | * the saved errno state, and return the encoded byte count. |
111 | 143 | */ |
112 | - return errout( errno_reset, len ); | |
144 | + return errout( errno_reset, count ); | |
113 | 145 | } |
114 | 146 | |
115 | 147 | size_t __mingw_wcsrtombs |