2 * ByteEncoding.cs - Implementation of the "I18N.Common.ByteEncoding" class.
4 * Copyright (c) 2002 Southern Storm Software, Pty Ltd
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * OTHER DEALINGS IN THE SOFTWARE.
29 using System.Runtime.InteropServices;
32 // This class provides an abstract base for encodings that use a single
33 // byte per character. The bulk of the work is done in this class, with
34 // subclasses providing implementations of the "ToBytes" methods to perform
35 // the char->byte conversion.
38 public abstract class ByteEncoding : MonoEncoding
41 protected char[] toChars;
42 protected String encodingName;
43 protected String bodyName;
44 protected String headerName;
45 protected String webName;
46 protected bool isBrowserDisplay;
47 protected bool isBrowserSave;
48 protected bool isMailNewsDisplay;
49 protected bool isMailNewsSave;
50 protected int windowsCodePage;
51 static byte [] isNormalized;
52 static byte [] isNormalizedComputed;
53 static byte [] normalization_bytes;
56 protected ByteEncoding(int codePage, char[] toChars,
57 String encodingName, String bodyName,
58 String headerName, String webName,
59 bool isBrowserDisplay, bool isBrowserSave,
60 bool isMailNewsDisplay, bool isMailNewsSave,
64 if (toChars.Length != byte.MaxValue + 1)
65 throw new ArgumentException("toChars");
67 this.toChars = toChars;
68 this.encodingName = encodingName;
69 this.bodyName = bodyName;
70 this.headerName = headerName;
71 this.webName = webName;
72 this.isBrowserDisplay = isBrowserDisplay;
73 this.isBrowserSave = isBrowserSave;
74 this.isMailNewsDisplay = isMailNewsDisplay;
75 this.isMailNewsSave = isMailNewsSave;
76 this.windowsCodePage = windowsCodePage;
79 public override bool IsAlwaysNormalized (NormalizationForm form)
81 if (form != NormalizationForm.FormC)
84 if (isNormalized == null)
85 isNormalized = new byte [0x10000 / 8];
86 if (isNormalizedComputed == null)
87 isNormalizedComputed = new byte [0x10000 / 8];
89 if (normalization_bytes == null) {
90 normalization_bytes = new byte [0x100];
91 lock (normalization_bytes) {
92 for (int i = 0; i < 0x100; i++)
93 normalization_bytes [i] = (byte) i;
97 byte offset = (byte) (1 << (CodePage % 8));
98 if ((isNormalizedComputed [CodePage / 8] & offset) == 0) {
99 Encoding e = Clone () as Encoding;
100 e.DecoderFallback = new DecoderReplacementFallback ("");
101 string s = e.GetString (normalization_bytes);
102 // note that the flag only stores FormC information.
103 if (s != s.Normalize (form))
104 isNormalized [CodePage / 8] |= offset;
105 isNormalizedComputed [CodePage / 8] |= offset;
108 return (isNormalized [CodePage / 8] & offset) == 0;
111 public override bool IsSingleByte {
115 public override int GetByteCount(String s)
119 throw new ArgumentNullException("s");
124 // Get the number of bytes needed to encode a character buffer.
125 public unsafe override int GetByteCountImpl (char* chars, int count)
130 // Convert an array of characters into a byte buffer,
131 // once the parameters have been validated.
132 protected unsafe abstract void ToBytes (
133 char* chars, int charCount, byte* bytes, int byteCount);
135 protected unsafe virtual void ToBytes (
136 char* chars, int charCount, byte* bytes, int byteCount)
138 // When it is not overriden, use ToBytes() with arrays.
139 char [] carr = new char [charCount];
140 Marshal.Copy ((IntPtr) chars, carr, 0, charCount);
141 byte [] barr = new byte [byteCount];
142 Marshal.Copy ((IntPtr) bytes, barr, 0, byteCount);
143 ToBytes (carr, 0, charCount, barr, 0);
147 // Convert an array of characters into a byte buffer,
148 // once the parameters have been validated.
149 protected unsafe virtual void ToBytes(char[] chars, int charIndex, int charCount,
150 byte[] bytes, int byteIndex)
152 // When it is not overriden, use ToBytes() with pointers
153 // (this is the ideal solution)
154 if (charCount == 0 || bytes.Length == byteIndex)
156 if (charIndex < 0 || charIndex > chars.Length) {
157 throw new ArgumentOutOfRangeException
158 ("charIndex", Strings.GetString("ArgRange_Array"));
160 if (byteIndex < 0 || byteIndex > bytes.Length) {
161 throw new ArgumentOutOfRangeException
162 ("byteIndex", Strings.GetString("ArgRange_Array"));
164 if (charCount < 0 || charIndex + charCount > chars.Length || byteIndex + charCount > bytes.Length) {
165 throw new ArgumentOutOfRangeException
166 ("charCount", Strings.GetString("ArgRange_Array"));
168 fixed (char* cptr = chars) {
169 fixed (byte* bptr = bytes) {
170 ToBytes (cptr + charIndex, charCount,
171 bptr + byteIndex, bytes.Length - byteIndex);
177 // Convert a string into a byte buffer, once the parameters
178 // have been validated.
179 protected unsafe virtual void ToBytes(String s, int charIndex, int charCount,
180 byte[] bytes, int byteIndex)
182 // When it is not overriden, use ToBytes() with pointers
184 if (s.Length == 0 || bytes.Length == byteIndex)
186 fixed (char* cptr = s) {
187 fixed (byte* bptr = bytes) {
188 ToBytes (cptr + charIndex, charCount,
189 bptr + byteIndex, bytes.Length - byteIndex);
195 //[CLSCompliant (false)]
196 public unsafe override int GetBytesImpl (char* chars, int charCount, byte* bytes, int byteCount)
198 ToBytes (chars, charCount, bytes, byteCount);
202 // Get the bytes that result from encoding a character buffer.
203 public override int GetBytes(char[] chars, int charIndex, int charCount,
204 byte[] bytes, int byteIndex)
208 throw new ArgumentNullException("chars");
212 throw new ArgumentNullException("bytes");
214 if(charIndex < 0 || charIndex > chars.Length)
216 throw new ArgumentOutOfRangeException
217 ("charIndex", Strings.GetString("ArgRange_Array"));
219 if(charCount < 0 || charCount > (chars.Length - charIndex))
221 throw new ArgumentOutOfRangeException
222 ("charCount", Strings.GetString("ArgRange_Array"));
224 if(byteIndex < 0 || byteIndex > bytes.Length)
226 throw new ArgumentOutOfRangeException
227 ("byteIndex", Strings.GetString("ArgRange_Array"));
229 if((bytes.Length - byteIndex) < charCount)
231 throw new ArgumentException
232 (Strings.GetString("Arg_InsufficientSpace"));
234 ToBytes(chars, charIndex, charCount, bytes, byteIndex);
238 // Convenience wrappers for "GetBytes".
239 public override int GetBytes(String s, int charIndex, int charCount,
240 byte[] bytes, int byteIndex)
244 throw new ArgumentNullException("s");
248 throw new ArgumentNullException("bytes");
250 if(charIndex < 0 || charIndex > s.Length)
252 throw new ArgumentOutOfRangeException
254 Strings.GetString("ArgRange_StringIndex"));
256 if(charCount < 0 || charCount > (s.Length - charIndex))
258 throw new ArgumentOutOfRangeException
260 Strings.GetString("ArgRange_StringRange"));
262 if(byteIndex < 0 || byteIndex > bytes.Length)
264 throw new ArgumentOutOfRangeException
265 ("byteIndex", Strings.GetString("ArgRange_Array"));
267 if((bytes.Length - byteIndex) < charCount)
269 throw new ArgumentException
270 (Strings.GetString("Arg_InsufficientSpace"));
272 ToBytes(s, charIndex, charCount, bytes, byteIndex);
277 // Get the number of characters needed to decode a byte buffer.
278 public override int GetCharCount(byte[] bytes, int index, int count)
282 throw new ArgumentNullException("bytes");
284 if(index < 0 || index > bytes.Length)
286 throw new ArgumentOutOfRangeException
287 ("index", Strings.GetString("ArgRange_Array"));
289 if(count < 0 || count > (bytes.Length - index))
291 throw new ArgumentOutOfRangeException
292 ("count", Strings.GetString("ArgRange_Array"));
297 // Get the characters that result from decoding a byte buffer.
298 public override int GetChars(byte[] bytes, int byteIndex, int byteCount,
299 char[] chars, int charIndex)
303 throw new ArgumentNullException("bytes");
307 throw new ArgumentNullException("chars");
309 if(byteIndex < 0 || byteIndex > bytes.Length)
311 throw new ArgumentOutOfRangeException
312 ("byteIndex", Strings.GetString("ArgRange_Array"));
314 if(byteCount < 0 || byteCount > (bytes.Length - byteIndex))
316 throw new ArgumentOutOfRangeException
317 ("byteCount", Strings.GetString("ArgRange_Array"));
319 if(charIndex < 0 || charIndex > chars.Length)
321 throw new ArgumentOutOfRangeException
322 ("charIndex", Strings.GetString("ArgRange_Array"));
324 if((chars.Length - charIndex) < byteCount)
326 throw new ArgumentException
327 (Strings.GetString("Arg_InsufficientSpace"));
329 int count = byteCount;
330 char[] cvt = toChars;
333 chars[charIndex++] = cvt[(int)(bytes[byteIndex++])];
338 // Get the maximum number of bytes needed to encode a
339 // specified number of characters.
340 public override int GetMaxByteCount(int charCount)
344 throw new ArgumentOutOfRangeException
346 Strings.GetString("ArgRange_NonNegative"));
351 // Get the maximum number of characters needed to decode a
352 // specified number of bytes.
353 public override int GetMaxCharCount(int byteCount)
357 throw new ArgumentOutOfRangeException
359 Strings.GetString("ArgRange_NonNegative"));
364 // Decode a buffer of bytes into a string.
365 public unsafe override String GetString(byte[] bytes, int index, int count)
369 throw new ArgumentNullException("bytes");
371 if(index < 0 || index > bytes.Length)
373 throw new ArgumentOutOfRangeException
374 ("index", Strings.GetString("ArgRange_Array"));
376 if(count < 0 || count > (bytes.Length - index))
378 throw new ArgumentOutOfRangeException
379 ("count", Strings.GetString("ArgRange_Array"));
385 string s = new string ((char) 0, count);
387 fixed (byte* bytePtr = bytes)
388 fixed (char* charPtr = s)
389 fixed (char* cvt = toChars) {
390 byte* b = bytePtr + index;
393 *(c++) = cvt[*(b++)];
398 public override String GetString(byte[] bytes)
402 throw new ArgumentNullException("bytes");
405 return GetString (bytes, 0, bytes.Length);
410 // Get the mail body name for this encoding.
411 public override String BodyName
419 // Get the human-readable name for this encoding.
420 public override String EncodingName
428 // Get the mail agent header name for this encoding.
429 public override String HeaderName
437 // Determine if this encoding can be displayed in a Web browser.
438 public override bool IsBrowserDisplay
442 return isBrowserDisplay;
446 // Determine if this encoding can be saved from a Web browser.
447 public override bool IsBrowserSave
451 return isBrowserSave;
455 // Determine if this encoding can be displayed in a mail/news agent.
456 public override bool IsMailNewsDisplay
460 return isMailNewsDisplay;
464 // Determine if this encoding can be saved from a mail/news agent.
465 public override bool IsMailNewsSave
469 return isMailNewsSave;
473 // Get the IANA-preferred Web name for this encoding.
474 public override String WebName
482 // Get the Windows code page represented by this object.
483 public override int WindowsCodePage
487 return windowsCodePage;
491 #endif // !ECMA_COMPAT
493 }; // class ByteEncoding
495 }; // namespace I18N.Encoding