/
OSEncoding.Windows.cs
252 lines (201 loc) · 9.3 KB
/
OSEncoding.Windows.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System;
using System.Text;
using System.Collections.Generic;
namespace System.Text
{
internal sealed class OSEncoding : Encoding
{
private readonly int _codePage;
private string? _encodingName;
internal OSEncoding(int codePage) : base(codePage)
{
_codePage = codePage;
}
public override unsafe int GetByteCount(char[] chars, int index, int count)
{
ArgumentNullException.ThrowIfNull(chars);
if (index < 0 || count < 0)
throw new ArgumentOutOfRangeException(index < 0 ? nameof(index) : nameof(count), SR.ArgumentOutOfRange_NeedNonNegNum);
if (chars.Length - index < count)
throw new ArgumentOutOfRangeException(nameof(chars), SR.ArgumentOutOfRange_IndexCountBuffer);
if (count == 0)
return 0;
fixed (char* pChar = chars)
{
return WideCharToMultiByte(_codePage, pChar + index, count, null, 0);
}
}
public override unsafe int GetByteCount(string s)
{
ArgumentNullException.ThrowIfNull(s);
if (s.Length == 0)
return 0;
fixed (char* pChars = s)
{
return WideCharToMultiByte(_codePage, pChars, s.Length, null, 0);
}
}
public override unsafe int GetBytes(string s, int charIndex, int charCount, byte[] bytes, int byteIndex)
{
ArgumentNullException.ThrowIfNull(s);
ArgumentNullException.ThrowIfNull(bytes);
if (charIndex < 0 || charCount < 0)
throw new ArgumentOutOfRangeException(charIndex < 0 ? nameof(charIndex) : nameof(charCount), SR.ArgumentOutOfRange_NeedNonNegNum);
if (s.Length - charIndex < charCount)
throw new ArgumentOutOfRangeException(nameof(s), SR.ArgumentOutOfRange_IndexCount);
if (byteIndex < 0 || byteIndex > bytes.Length)
throw new ArgumentOutOfRangeException(nameof(byteIndex), SR.ArgumentOutOfRange_IndexMustBeLessOrEqual);
if (charCount == 0)
return 0;
if (bytes.Length == 0)
{
throw new ArgumentOutOfRangeException(SR.Argument_EncodingConversionOverflowBytes);
}
fixed (char* pChars = s)
fixed (byte* pBytes = &bytes[0])
{
return WideCharToMultiByte(_codePage, pChars + charIndex, charCount, pBytes + byteIndex, bytes.Length - byteIndex);
}
}
public override unsafe int GetBytes(char[] chars, int charIndex, int charCount, byte[] bytes, int byteIndex)
{
ArgumentNullException.ThrowIfNull(chars);
ArgumentNullException.ThrowIfNull(bytes);
if (charIndex < 0 || charCount < 0)
throw new ArgumentOutOfRangeException(charIndex < 0 ? nameof(charIndex) : nameof(charCount), SR.ArgumentOutOfRange_NeedNonNegNum);
if (chars.Length - charIndex < charCount)
throw new ArgumentOutOfRangeException(nameof(chars), SR.ArgumentOutOfRange_IndexCountBuffer);
if (byteIndex < 0 || byteIndex > bytes.Length)
throw new ArgumentOutOfRangeException(nameof(byteIndex), SR.ArgumentOutOfRange_IndexMustBeLessOrEqual);
if (charCount == 0)
return 0;
if (bytes.Length == 0)
{
throw new ArgumentOutOfRangeException(SR.Argument_EncodingConversionOverflowBytes);
}
fixed (char* pChars = chars)
fixed (byte* pBytes = &bytes[0])
{
return WideCharToMultiByte(_codePage, pChars + charIndex, charCount, pBytes + byteIndex, bytes.Length - byteIndex);
}
}
public override unsafe int GetCharCount(byte[] bytes, int index, int count)
{
ArgumentNullException.ThrowIfNull(bytes);
if (index < 0 || count < 0)
throw new ArgumentOutOfRangeException(index < 0 ? nameof(index) : nameof(count), SR.ArgumentOutOfRange_NeedNonNegNum);
if (bytes.Length - index < count)
throw new ArgumentOutOfRangeException(nameof(bytes), SR.ArgumentOutOfRange_IndexCountBuffer);
if (count == 0)
return 0;
fixed (byte* pBytes = bytes)
{
return MultiByteToWideChar(_codePage, pBytes + index, count, null, 0);
}
}
public override unsafe int GetChars(byte[] bytes, int byteIndex, int byteCount, char[] chars, int charIndex)
{
ArgumentNullException.ThrowIfNull(bytes);
ArgumentNullException.ThrowIfNull(chars);
if (byteIndex < 0 || byteCount < 0)
throw new ArgumentOutOfRangeException(byteIndex < 0 ? nameof(byteIndex) : nameof(byteCount), SR.ArgumentOutOfRange_NeedNonNegNum);
if (bytes.Length - byteIndex < byteCount)
throw new ArgumentOutOfRangeException(nameof(bytes), SR.ArgumentOutOfRange_IndexCountBuffer);
if (charIndex < 0 || charIndex > chars.Length)
throw new ArgumentOutOfRangeException(nameof(charIndex), SR.ArgumentOutOfRange_IndexMustBeLessOrEqual);
if (byteCount == 0)
return 0;
if (chars.Length == 0)
throw new ArgumentOutOfRangeException(SR.Argument_EncodingConversionOverflowChars);
fixed (byte* pBytes = bytes)
fixed (char* pChars = &chars[0])
{
return MultiByteToWideChar(_codePage, pBytes + byteIndex, byteCount, pChars + charIndex, chars.Length - charIndex);
}
}
public override int GetMaxByteCount(int charCount)
{
if (charCount < 0)
throw new ArgumentOutOfRangeException(nameof(charCount), SR.ArgumentOutOfRange_NeedNonNegNum);
long byteCount = (long)charCount * 14; // Max possible value for all encodings
if (byteCount > 0x7fffffff)
throw new ArgumentOutOfRangeException(nameof(charCount), SR.ArgumentOutOfRange_GetByteCountOverflow);
return (int)byteCount;
}
public override int GetMaxCharCount(int byteCount)
{
if (byteCount < 0)
throw new ArgumentOutOfRangeException(nameof(byteCount), SR.ArgumentOutOfRange_NeedNonNegNum);
long charCount = byteCount * 4; // Max possible value for all encodings
if (charCount > 0x7fffffff)
throw new ArgumentOutOfRangeException(nameof(byteCount), SR.ArgumentOutOfRange_GetCharCountOverflow);
return (int)charCount;
}
public override string EncodingName
{
get
{
if (_encodingName == null)
{
_encodingName = "Codepage - " + _codePage.ToString();
}
return _encodingName;
}
}
public override string WebName
{
get
{
return EncodingName;
}
}
public override Encoder GetEncoder()
{
return new OSEncoder(this);
}
public override Decoder GetDecoder()
{
switch (CodePage)
{
case 932: // Japanese (Shift-JIS)
case 936: // Chinese Simplified (GB2312)
case 949: // Korean
case 950: // Chinese Traditional (Big5)
case 1361: // Korean (Johab)
case 10001: // Japanese (Mac)
case 10002: // Chinese Traditional (Mac)
case 10003: // Korean (Mac)
case 10008: // Chinese Simplified (Mac)
case 20000: // Chinese Traditional (CNS)
case 20001: // TCA Taiwan
case 20002: // Chinese Traditional (Eten)
case 20003: // IBM5550 Taiwan
case 20004: // TeleText Taiwan
case 20005: // Wang Taiwan
case 20261: // T.61
case 20932: // Japanese (JIS 0208-1990 and 0212-1990)
case 20936: // Chinese Simplified (GB2312-80)
case 51949: // Korean (EUC)
return new DecoderDBCS(this);
default:
return base.GetDecoder();
}
}
internal static unsafe int WideCharToMultiByte(int codePage, char* pChars, int count, byte* pBytes, int byteCount)
{
int result = Interop.Kernel32.WideCharToMultiByte((uint)codePage, 0, pChars, count, pBytes, byteCount, null, null);
if (result <= 0)
throw new ArgumentException(SR.Argument_InvalidCharSequenceNoIndex);
return result;
}
internal static unsafe int MultiByteToWideChar(int codePage, byte* pBytes, int byteCount, char* pChars, int count)
{
int result = Interop.Kernel32.MultiByteToWideChar((uint)codePage, 0, pBytes, byteCount, pChars, count);
if (result <= 0)
throw new ArgumentException(SR.Argument_InvalidCharSequenceNoIndex);
return result;
}
}
}