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;
52 static byte [] isNormalized;
53 static byte [] isNormalizedComputed;
54 static byte [] normalization_bytes;
58 protected ByteEncoding(int codePage, char[] toChars,
59 String encodingName, String bodyName,
60 String headerName, String webName,
61 bool isBrowserDisplay, bool isBrowserSave,
62 bool isMailNewsDisplay, bool isMailNewsSave,
66 if (toChars.Length != byte.MaxValue + 1)
67 throw new ArgumentException("toChars");
69 this.toChars = toChars;
70 this.encodingName = encodingName;
71 this.bodyName = bodyName;
72 this.headerName = headerName;
73 this.webName = webName;
74 this.isBrowserDisplay = isBrowserDisplay;
75 this.isBrowserSave = isBrowserSave;
76 this.isMailNewsDisplay = isMailNewsDisplay;
77 this.isMailNewsSave = isMailNewsSave;
78 this.windowsCodePage = windowsCodePage;
82 public override bool IsAlwaysNormalized (NormalizationForm form)
84 if (form != NormalizationForm.FormC)
87 if (isNormalized == null)
88 isNormalized = new byte [0x10000 / 8];
89 if (isNormalizedComputed == null)
90 isNormalizedComputed = new byte [0x10000 / 8];
92 if (normalization_bytes == null) {
93 normalization_bytes = new byte [0x100];
94 lock (normalization_bytes) {
95 for (int i = 0; i < 0x100; i++)
96 normalization_bytes [i] = (byte) i;
100 byte offset = (byte) (1 << (CodePage % 8));
101 if ((isNormalizedComputed [CodePage / 8] & offset) == 0) {
102 Encoding e = Clone () as Encoding;
103 e.DecoderFallback = new DecoderReplacementFallback ("");
104 string s = e.GetString (normalization_bytes);
105 // note that the flag only stores FormC information.
106 if (s != s.Normalize (form))
107 isNormalized [CodePage / 8] |= offset;
108 isNormalizedComputed [CodePage / 8] |= offset;
111 return (isNormalized [CodePage / 8] & offset) == 0;
114 public override bool IsSingleByte {
119 public override int GetByteCount(String s)
123 throw new ArgumentNullException("s");
128 // Get the number of bytes needed to encode a character buffer.
129 public unsafe override int GetByteCountImpl (char* chars, int count)
134 // Convert an array of characters into a byte buffer,
135 // once the parameters have been validated.
136 protected unsafe abstract void ToBytes (
137 char* chars, int charCount, byte* bytes, int byteCount);
139 protected unsafe virtual void ToBytes (
140 char* chars, int charCount, byte* bytes, int byteCount)
142 // When it is not overriden, use ToBytes() with arrays.
143 char [] carr = new char [charCount];
144 Marshal.Copy ((IntPtr) chars, carr, 0, charCount);
145 byte [] barr = new byte [byteCount];
146 Marshal.Copy ((IntPtr) bytes, barr, 0, byteCount);
147 ToBytes (carr, 0, charCount, barr, 0);
151 // Convert an array of characters into a byte buffer,
152 // once the parameters have been validated.
153 protected unsafe virtual void ToBytes(char[] chars, int charIndex, int charCount,
154 byte[] bytes, int byteIndex)
156 // When it is not overriden, use ToBytes() with pointers
157 // (this is the ideal solution)
158 if (charCount == 0 || bytes.Length == byteIndex)
160 fixed (char* cptr = chars) {
161 fixed (byte* bptr = bytes) {
162 ToBytes (cptr + charIndex, charCount,
163 bptr + byteIndex, bytes.Length - byteIndex);
169 // Convert a string into a byte buffer, once the parameters
170 // have been validated.
171 protected unsafe virtual void ToBytes(String s, int charIndex, int charCount,
172 byte[] bytes, int byteIndex)
174 // When it is not overriden, use ToBytes() with pointers
176 if (s.Length == 0 || bytes.Length == byteIndex)
178 fixed (char* cptr = s) {
179 fixed (byte* bptr = bytes) {
180 ToBytes (cptr + charIndex, charCount,
181 bptr + byteIndex, bytes.Length - byteIndex);
187 //[CLSCompliant (false)]
188 public unsafe override int GetBytesImpl (char* chars, int charCount, byte* bytes, int byteCount)
190 ToBytes (chars, charCount, bytes, byteCount);
194 // Get the bytes that result from encoding a character buffer.
195 public override int GetBytes(char[] chars, int charIndex, int charCount,
196 byte[] bytes, int byteIndex)
200 throw new ArgumentNullException("chars");
204 throw new ArgumentNullException("bytes");
206 if(charIndex < 0 || charIndex > chars.Length)
208 throw new ArgumentOutOfRangeException
209 ("charIndex", Strings.GetString("ArgRange_Array"));
211 if(charCount < 0 || charCount > (chars.Length - charIndex))
213 throw new ArgumentOutOfRangeException
214 ("charCount", Strings.GetString("ArgRange_Array"));
216 if(byteIndex < 0 || byteIndex > bytes.Length)
218 throw new ArgumentOutOfRangeException
219 ("byteIndex", Strings.GetString("ArgRange_Array"));
221 if((bytes.Length - byteIndex) < charCount)
223 throw new ArgumentException
224 (Strings.GetString("Arg_InsufficientSpace"));
226 ToBytes(chars, charIndex, charCount, bytes, byteIndex);
230 // Convenience wrappers for "GetBytes".
231 public override int GetBytes(String s, int charIndex, int charCount,
232 byte[] bytes, int byteIndex)
236 throw new ArgumentNullException("s");
240 throw new ArgumentNullException("bytes");
242 if(charIndex < 0 || charIndex > s.Length)
244 throw new ArgumentOutOfRangeException
246 Strings.GetString("ArgRange_StringIndex"));
248 if(charCount < 0 || charCount > (s.Length - charIndex))
250 throw new ArgumentOutOfRangeException
252 Strings.GetString("ArgRange_StringRange"));
254 if(byteIndex < 0 || byteIndex > bytes.Length)
256 throw new ArgumentOutOfRangeException
257 ("byteIndex", Strings.GetString("ArgRange_Array"));
259 if((bytes.Length - byteIndex) < charCount)
261 throw new ArgumentException
262 (Strings.GetString("Arg_InsufficientSpace"));
264 ToBytes(s, charIndex, charCount, bytes, byteIndex);
269 // Get the number of characters needed to decode a byte buffer.
270 public override int GetCharCount(byte[] bytes, int index, int count)
274 throw new ArgumentNullException("bytes");
276 if(index < 0 || index > bytes.Length)
278 throw new ArgumentOutOfRangeException
279 ("index", Strings.GetString("ArgRange_Array"));
281 if(count < 0 || count > (bytes.Length - index))
283 throw new ArgumentOutOfRangeException
284 ("count", Strings.GetString("ArgRange_Array"));
289 // Get the characters that result from decoding a byte buffer.
290 public override int GetChars(byte[] bytes, int byteIndex, int byteCount,
291 char[] chars, int charIndex)
295 throw new ArgumentNullException("bytes");
299 throw new ArgumentNullException("chars");
301 if(byteIndex < 0 || byteIndex > bytes.Length)
303 throw new ArgumentOutOfRangeException
304 ("byteIndex", Strings.GetString("ArgRange_Array"));
306 if(byteCount < 0 || byteCount > (bytes.Length - byteIndex))
308 throw new ArgumentOutOfRangeException
309 ("byteCount", Strings.GetString("ArgRange_Array"));
311 if(charIndex < 0 || charIndex > chars.Length)
313 throw new ArgumentOutOfRangeException
314 ("charIndex", Strings.GetString("ArgRange_Array"));
316 if((chars.Length - charIndex) < byteCount)
318 throw new ArgumentException
319 (Strings.GetString("Arg_InsufficientSpace"));
321 int count = byteCount;
322 char[] cvt = toChars;
325 chars[charIndex++] = cvt[(int)(bytes[byteIndex++])];
330 // Get the maximum number of bytes needed to encode a
331 // specified number of characters.
332 public override int GetMaxByteCount(int charCount)
336 throw new ArgumentOutOfRangeException
338 Strings.GetString("ArgRange_NonNegative"));
343 // Get the maximum number of characters needed to decode a
344 // specified number of bytes.
345 public override int GetMaxCharCount(int byteCount)
349 throw new ArgumentOutOfRangeException
351 Strings.GetString("ArgRange_NonNegative"));
356 // Decode a buffer of bytes into a string.
357 public unsafe override String GetString(byte[] bytes, int index, int count)
361 throw new ArgumentNullException("bytes");
363 if(index < 0 || index > bytes.Length)
365 throw new ArgumentOutOfRangeException
366 ("index", Strings.GetString("ArgRange_Array"));
368 if(count < 0 || count > (bytes.Length - index))
370 throw new ArgumentOutOfRangeException
371 ("count", Strings.GetString("ArgRange_Array"));
375 return string.Empty;
\r
377 string s = new string ((char) 0, count);
\r
379 fixed (byte* bytePtr = bytes)
\r
380 fixed (char* charPtr = s)
\r
381 fixed (char* cvt = toChars) {
\r
382 byte* b = bytePtr + index;
\r
385 *(c++) = cvt[*(b++)];
390 public override String GetString(byte[] bytes)
394 throw new ArgumentNullException("bytes");
397 return GetString (bytes, 0, bytes.Length);
402 // Get the mail body name for this encoding.
403 public override String BodyName
411 // Get the human-readable name for this encoding.
412 public override String EncodingName
420 // Get the mail agent header name for this encoding.
421 public override String HeaderName
429 // Determine if this encoding can be displayed in a Web browser.
430 public override bool IsBrowserDisplay
434 return isBrowserDisplay;
438 // Determine if this encoding can be saved from a Web browser.
439 public override bool IsBrowserSave
443 return isBrowserSave;
447 // Determine if this encoding can be displayed in a mail/news agent.
448 public override bool IsMailNewsDisplay
452 return isMailNewsDisplay;
456 // Determine if this encoding can be saved from a mail/news agent.
457 public override bool IsMailNewsSave
461 return isMailNewsSave;
465 // Get the IANA-preferred Web name for this encoding.
466 public override String WebName
474 // Get the Windows code page represented by this object.
475 public override int WindowsCodePage
479 return windowsCodePage;
483 #endif // !ECMA_COMPAT
485 }; // class ByteEncoding
487 }; // namespace I18N.Encoding