Doc: Fix broken link
[TortoiseGit.git] / src / ResText / codecvt.cpp
blobeef3b010cf5ea0de7872acc5b3ffcbaff85af47a
1 #include "codecvt.h"
2 #include <algorithm>
4 ucs2_conversion::result
5 ucs2_conversion::do_in(mbstate_t&,
6 const char* from, const char* from_end, const char*& from_next,
7 wchar_t* to, wchar_t* to_limit, wchar_t*& to_next) const
9 size_t max_input = (from_end - from) & ~1;
10 size_t max_output = (to_limit - to);
11 size_t count = std::min(max_input/2, max_output);
13 result res = ok;
15 from_next = from;
16 to_next = to;
17 for (;count--; from_next += 2, ++to_next) {
18 unsigned char c1 = *from_next, c2 = *(from_next + 1);
19 *to_next = c1 | c2 << 8;
21 if (to_next == to && from_next == from_end - 1) res = partial;
22 return res;
25 ucs2_conversion::result
26 ucs2_conversion::do_out(mbstate_t&,
27 const wchar_t* from, const wchar_t* from_end, const wchar_t*& from_next,
28 char* to, char* to_limit, char*& to_next) const
30 size_t max_input = (from_end - from);
31 size_t max_output = (to_limit - to) & ~1;
32 size_t count = std::min(max_input, max_output/2);
34 from_next = from;
35 to_next = to;
36 for (;count--; ++from_next, to_next += 2) {
37 *(to_next + 0) = (char)(*from_next & 0xFF);
38 *(to_next + 1) = (char)(*from_next >> 8 & 0xFF);
40 return ok;
43 typedef unsigned char uchar;
45 inline unsigned char
46 take_6_bits(unsigned value, size_t right_position)
48 return uchar((value >> right_position) & 63);
53 inline size_t
54 most_signifant_bit_position(unsigned value)
56 size_t result(0);
58 size_t half = 16;
59 for(; half > 0; half >>= 1) {
60 if (1u << (result + half) <= value ) result += half;
62 return result + 1;
63 //return *lower_bound(range(0u, 31u), \x -> (1 << x <= value));
68 utf8_conversion::result
69 utf8_conversion::do_in(mbstate_t&,
70 const char* from, const char* from_end, const char*& from_next,
71 wchar_t* to, wchar_t* to_limit, wchar_t*& to_next) const
73 from_next = from;
74 to_next = to;
76 for(; to_next < to_limit && from_next < from_end; ++to_next) {
78 if (uchar(*from_next) < 0x80) *to_next = uchar(*from_next++);
79 else {
81 // 111zxxxx : z = 0 xxxx are data bits
82 size_t zero_bit_pos = most_signifant_bit_position(~*from_next);
83 size_t extra_bytes = 7 - zero_bit_pos;
85 if (size_t(from_end - from_next) < extra_bytes + 1)
86 return partial;
88 *to_next = uchar(*from_next++) & (wchar_t)((1 << (zero_bit_pos - 1)) - 1);
90 for (;extra_bytes--; ++from_next) {
91 *to_next = *to_next << 6 | uchar(*from_next) & 63;
96 return ok;
100 utf8_conversion::result
101 utf8_conversion::do_out(mbstate_t&,
102 const wchar_t* from, const wchar_t* from_end, const wchar_t*& from_next,
103 char* to, char* to_limit, char*& to_next) const
105 from_next = from;
106 to_next = to;
108 for (;from_next < from_end; ++from_next) {
110 unsigned symbol = *from_next;
112 if (symbol < 0x7F) {
113 if (to_next < to_limit)
114 *to_next++ = (unsigned char)symbol;
115 else
116 return ok;
117 } else {
119 size_t msb_pos = most_signifant_bit_position(symbol);
120 size_t extra_bytes = msb_pos / 6;
122 if (size_t(to_limit - to_next) >= extra_bytes + 1) {
124 *to_next = uchar(0xFF80 >> extra_bytes);
125 *to_next++ |= take_6_bits(symbol, extra_bytes*6);
127 for(;extra_bytes--;)
128 *to_next++ = 0x80 | take_6_bits(symbol, extra_bytes*6);
130 else
131 return ok;
134 return ok;