OSDN Git Service

merge original branch.
[tortoisegit/TortoiseGitJp.git] / src / ResText / codecvt.cpp
1 #include "codecvt.h"\r
2 \r
3 using namespace std;\r
4 \r
5 ucs2_conversion::result\r
6 ucs2_conversion::do_in(mbstate_t&,\r
7                                            const char*  from, const char* from_end, const char*& from_next,\r
8                                            wchar_t* to, wchar_t* to_limit, wchar_t*& to_next) const\r
9 {\r
10         size_t max_input = (from_end - from) & ~1;\r
11         size_t max_output = (to_limit - to);\r
12         size_t count = min(max_input/2, max_output);\r
13 \r
14         result res = ok;\r
15 \r
16         from_next = from;\r
17         to_next = to;\r
18         for (;count--; from_next += 2, ++to_next) {\r
19                 unsigned char c1 = *from_next, c2 = *(from_next + 1);\r
20                 *to_next = c1 | c2 << 8;\r
21         }\r
22         if (to_next == to && from_next == from_end - 1) res = partial;\r
23         return res; \r
24 }\r
25 \r
26 ucs2_conversion::result\r
27 ucs2_conversion::do_out(mbstate_t&,\r
28                                   const wchar_t* from, const wchar_t* from_end, const wchar_t*& from_next,\r
29                                   char* to, char* to_limit, char*& to_next) const\r
30 {\r
31         size_t max_input = (from_end - from);\r
32         size_t max_output = (to_limit - to) & ~1;\r
33         size_t count = min(max_input, max_output/2);\r
34 \r
35         from_next = from;\r
36         to_next = to;\r
37         for (;count--; ++from_next, to_next += 2) {\r
38                 *(to_next + 0) = (char)(*from_next & 0xFF);\r
39                 *(to_next + 1) = (char)(*from_next >> 8 & 0xFF);\r
40         }\r
41         return ok;\r
42 }\r
43 \r
44 typedef unsigned char uchar;\r
45 \r
46 inline unsigned char \r
47 take_6_bits(unsigned value, size_t right_position)\r
48 {\r
49         return uchar((value >> right_position) & 63);\r
50 }\r
51 \r
52 \r
53 \r
54 inline size_t\r
55 most_signifant_bit_position(unsigned value)\r
56 {\r
57         size_t result(0);\r
58 \r
59         size_t half = 16;\r
60         for(; half > 0; half >>= 1) {\r
61                 if (1u << (result + half) <= value ) result += half;\r
62         }       \r
63         return result + 1;\r
64         //return *lower_bound(range(0u, 31u), \x -> (1 << x <= value));\r
65 }\r
66 \r
67 \r
68 \r
69 utf8_conversion::result\r
70 utf8_conversion::do_in(mbstate_t&,\r
71                                            const char*  from, const char* from_end, const char*& from_next,\r
72                                            wchar_t* to, wchar_t* to_limit, wchar_t*& to_next) const\r
73 {\r
74         from_next = from;\r
75         to_next = to;\r
76 \r
77         for(; to_next < to_limit && from_next < from_end; ++to_next) {\r
78 \r
79                 if (uchar(*from_next) < 0x80) *to_next = uchar(*from_next++);\r
80                 else {\r
81 \r
82                         // 111zxxxx : z = 0 xxxx are data bits\r
83                         size_t zero_bit_pos = most_signifant_bit_position(~*from_next);\r
84                         size_t extra_bytes  = 7 - zero_bit_pos;\r
85 \r
86                         if (size_t(from_end - from_next) < extra_bytes + 1) \r
87                                 return partial;\r
88 \r
89                         *to_next = uchar(*from_next++) & (wchar_t)((1 << (zero_bit_pos - 1)) - 1);\r
90 \r
91                         for (;extra_bytes--; ++from_next) {\r
92                                 *to_next = *to_next << 6  |  uchar(*from_next) & 63;\r
93                         }\r
94                 }\r
95         }       \r
96 \r
97         return ok;\r
98 }\r
99 \r
100 \r
101 utf8_conversion::result\r
102 utf8_conversion::do_out(mbstate_t&,\r
103                                   const wchar_t* from, const wchar_t* from_end, const wchar_t*& from_next,\r
104                                   char* to, char* to_limit, char*& to_next) const\r
105 {\r
106                 from_next = from;\r
107                 to_next = to;\r
108 \r
109                 for (;from_next < from_end; ++from_next) {\r
110 \r
111                         unsigned symbol = *from_next;\r
112 \r
113                         if (symbol < 0x7F) {\r
114                                 if (to_next < to_limit)\r
115                                         *to_next++ = (unsigned char)symbol;\r
116                                 else\r
117                                         return ok;\r
118                         } else {\r
119 \r
120                                 size_t msb_pos = most_signifant_bit_position(symbol);\r
121                                 size_t extra_bytes = msb_pos / 6;\r
122 \r
123                                 if (size_t(to_limit - to_next) >= extra_bytes + 1) {\r
124 \r
125                                         *to_next = uchar(0xFF80 >> extra_bytes);\r
126                                         *to_next++ |= take_6_bits(symbol, extra_bytes*6);\r
127 \r
128                                         for(;extra_bytes--;)\r
129                                                 *to_next++ = 0x80 | take_6_bits(symbol, extra_bytes*6);\r
130                                 }\r
131                                 else\r
132                                         return ok;\r
133                         }\r
134                 }\r
135                 return ok;\r
136 }\r
137 \r