6 #include "UtfConvert.hpp"
8 //NB: Routines here should not affect errno
10 //////////////////////////////////////////////////////
12 static size_t MB2Wide_Internal(const char *src_begin
, size_t &src_len
, std::wstring
&dst
, bool append
)
18 return std::string::npos
;
22 auto src_end
= src_begin
+ src_len
;
23 auto src_incomplete_tail
= src_end
;
24 size_t dst_incomplete_tail_pos
= (size_t)-1;
26 struct EscapedStringPushBack
: public StdPushBack
<std::wstring
>
28 EscapedStringPushBack(std::wstring
&dst
) : StdPushBack
<std::wstring
>(dst
) {}
30 inline void push_back(const value_type
&v
)
32 StdPushBack
<std::wstring
>::push_back(v
);
33 if (UNLIKELY(v
== WCHAR_ESCAPING
)) {
34 StdPushBack
<std::wstring
>::push_back(WCHAR_ESCAPING
);
41 size_t src_piece
= src_end
- src
;
42 const unsigned ucr
= UtfConvert(src
, src_piece
, pb
, true);
48 if (dst_incomplete_tail_pos
== (size_t)-1 && src
!= src_end
49 && src_end
- src
< MAX_MB_CHARS_PER_WCHAR
) {
50 dst_incomplete_tail_pos
= dst
.size();
51 src_incomplete_tail
= src
;
54 const auto remain
= src_end
- src
;
56 const unsigned char uc
= (unsigned char)*src
;
57 dst
.push_back(WCHAR_ESCAPING
);
58 dst
.push_back((wchar_t)MakeHexDigit(uc
>> 4));
59 dst
.push_back((wchar_t)MakeHexDigit(uc
& 0xf));
61 // fprintf(stderr, "CE: @%lu %x\n", src - src_begin, ucr);
64 if (dst_incomplete_tail_pos
!= (size_t)-1) {
65 src_len
= src_incomplete_tail
- src_begin
;
66 return dst_incomplete_tail_pos
;
68 src_len
= src
- src_begin
;
77 size_t MB2Wide_HonorIncomplete(const char *src
, size_t src_len
, std::wstring
&dst
, bool append
)
79 size_t dst_incomplete_tail_pos
= MB2Wide_Internal(src
, src_len
, dst
, append
);
80 if (dst_incomplete_tail_pos
!= std::string::npos
) {
81 dst
.resize(dst_incomplete_tail_pos
);
86 unsigned MB2Wide_Unescaped(const char *src_begin
, size_t &src_len
, wchar_t &dst
, bool fail_on_illformed
)
88 ArrayPushBack
<wchar_t> pb(&dst
, (&dst
) + 1);
89 unsigned out
= UtfConvert(src_begin
, src_len
, pb
, fail_on_illformed
);
90 out
&= ~CONV_NEED_MORE_DST
;
94 unsigned MB2Wide_Unescaped(const char *src
, size_t &src_len
, wchar_t *dst
, size_t &dst_len
, bool fail_on_illformed
)
96 ArrayPushBack
<wchar_t> pb(dst
, dst
+ dst_len
);
97 unsigned out
= UtfConvert(src
, src_len
, pb
, fail_on_illformed
);
102 unsigned int Wide2MB_Unescaped(const wchar_t *src
, size_t &src_len
, char *dst
, size_t &dst_len
, bool fail_on_illformed
)
104 ArrayPushBack
<char> pb(dst
, dst
+ dst_len
);
105 unsigned out
= UtfConvert(src
, src_len
, pb
, fail_on_illformed
);
110 void MB2Wide(const char *src
, size_t src_len
, std::wstring
&dst
, bool append
)
112 MB2Wide_Internal(src
, src_len
, dst
, append
);
117 void Wide2MB_UnescapedAppend(const wchar_t wc
, std::string
&dst
)
120 StdPushBack
<std::string
> pb(dst
);
121 UtfConvert(&wc
, len
, pb
, false);
124 void Wide2MB_UnescapedAppend(const wchar_t *src_begin
, size_t src_len
, std::string
&dst
)
126 StdPushBack
<std::string
> pb(dst
);
127 UtfConvert(src_begin
, src_len
, pb
, false);
130 static inline bool IsLowCaseHexDigit(const wchar_t c
)
132 return (c
>= L
'0' && c
<= L
'9') || (c
>= L
'a' && c
<= L
'f');
135 void Wide2MB(const wchar_t *src_begin
, size_t src_len
, std::string
&dst
, bool append
)
144 auto src
= src_begin
, src_end
= src_begin
+ src_len
;
146 while (src
!= src_end
) {
147 if (LIKELY(src
[0] != WCHAR_ESCAPING
)) {
151 if (src_begin
!= src
) {
152 Wide2MB_UnescapedAppend(src_begin
, src
- src_begin
, dst
);
154 if (LIKELY(src_end
- src
>= 3 && IsLowCaseHexDigit(src
[1]) && IsLowCaseHexDigit(src
[2]))) {
155 dst
+= ParseHexByte(&src
[1]);
159 Wide2MB_UnescapedAppend(src
, 1, dst
);
161 if (src_end
!= src
&& *src
== WCHAR_ESCAPING
) {
169 if (src_begin
!= src
) {
170 Wide2MB_UnescapedAppend(src_begin
, src
- src_begin
, dst
);
176 void Wide2MB(const wchar_t *src
, std::string
&dst
, bool append
)
178 Wide2MB(src
, wcslen(src
), dst
, append
);
181 void MB2Wide(const char *src
, std::wstring
&dst
, bool append
)
183 MB2Wide(src
, strlen(src
), dst
, append
);
186 std::string
Wide2MB(const wchar_t *src
)
189 Wide2MB(src
, dst
, true);
193 std::wstring
MB2Wide(const char *src
)
196 MB2Wide(src
, dst
, true);
200 void StrWide2MB(const std::wstring
&src
, std::string
&dst
, bool append
)
202 Wide2MB(src
.c_str(), src
.size(), dst
, append
);
205 std::string
StrWide2MB(const std::wstring
&src
)
208 Wide2MB(src
.c_str(), src
.size(), dst
, true);
212 void StrMB2Wide(const std::string
&src
, std::wstring
&dst
, bool append
)
214 MB2Wide(src
.c_str(), src
.size(), dst
, append
);
217 std::wstring
StrMB2Wide(const std::string
&src
)
220 MB2Wide(src
.c_str(), src
.size(), dst
, true);