2 * ByteSafeEncoding.cs - Implementation of the "I18N.Common.ByteSafeEncoding" class.
4 * Copyright (c) 2002 Southern Storm Software, Pty Ltd
5 * Copytight (c) 2011 Pablo Ruiz GarcĂa
7 * Permission is hereby granted, free of charge, to any person obtaining
8 * a copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 * OTHER DEALINGS IN THE SOFTWARE.
30 using System.Runtime.InteropServices;
33 // This class provides an abstract base for encodings that use a single
34 // byte per character. The bulk of the work is done in this class, with
35 // subclasses providing implementations of the "ToBytes" methods to perform
36 // the char->byte conversion.
41 public abstract class ByteSafeEncoding : MonoSafeEncoding
44 protected char[] toChars;
45 protected String encodingName;
46 protected String bodyName;
47 protected String headerName;
48 protected String webName;
49 protected bool isBrowserDisplay;
50 protected bool isBrowserSave;
51 protected bool isMailNewsDisplay;
52 protected bool isMailNewsSave;
53 protected int windowsCodePage;
55 static byte [] isNormalized;
56 static byte [] isNormalizedComputed;
57 static byte [] normalization_bytes;
61 protected ByteSafeEncoding(int codePage, char[] toChars,
62 String encodingName, String bodyName,
63 String headerName, String webName,
64 bool isBrowserDisplay, bool isBrowserSave,
65 bool isMailNewsDisplay, bool isMailNewsSave,
69 if (toChars.Length != byte.MaxValue + 1)
70 throw new ArgumentException("toChars");
72 this.toChars = toChars;
73 this.encodingName = encodingName;
74 this.bodyName = bodyName;
75 this.headerName = headerName;
76 this.webName = webName;
77 this.isBrowserDisplay = isBrowserDisplay;
78 this.isBrowserSave = isBrowserSave;
79 this.isMailNewsDisplay = isMailNewsDisplay;
80 this.isMailNewsSave = isMailNewsSave;
81 this.windowsCodePage = windowsCodePage;
85 public override bool IsAlwaysNormalized (NormalizationForm form)
87 if (form != NormalizationForm.FormC)
90 if (isNormalized == null)
91 isNormalized = new byte [0x10000 / 8];
92 if (isNormalizedComputed == null)
93 isNormalizedComputed = new byte [0x10000 / 8];
95 if (normalization_bytes == null) {
96 normalization_bytes = new byte [0x100];
97 lock (normalization_bytes) {
98 for (int i = 0; i < 0x100; i++)
99 normalization_bytes [i] = (byte) i;
103 byte offset = (byte) (1 << (CodePage % 8));
104 if ((isNormalizedComputed [CodePage / 8] & offset) == 0) {
105 Encoding e = Clone () as Encoding;
106 e.DecoderFallback = new DecoderReplacementFallback ("");
107 string s = e.GetString (normalization_bytes);
108 // note that the flag only stores FormC information.
109 if (s != s.Normalize (form))
110 isNormalized [CodePage / 8] |= offset;
111 isNormalizedComputed [CodePage / 8] |= offset;
114 return (isNormalized [CodePage / 8] & offset) == 0;
117 public override bool IsSingleByte {
122 public override int GetByteCount(String s)
125 throw new ArgumentNullException("s");
130 // Get the number of bytes needed to encode a character buffer.
131 public override int GetByteCount(char[] chars, int index, int count)
133 return count - index;
136 public override unsafe int GetByteCount(char* chars, int count)
141 // Convert an array of characters into a byte buffer,
142 // once the parameters have been validated.
143 protected abstract void ToBytes(char[] chars, int charIndex, int charCount, byte[] bytes, int byteIndex);
145 // Convert a string into a byte buffer, once the parameters
146 // have been validated.
147 protected virtual void ToBytes(String s, int charIndex, int charCount, byte[] bytes, int byteIndex)
149 // When it is not overriden, use ToBytes() with pointers
151 if (s.Length == 0 || bytes.Length == byteIndex)
154 ToBytes(s.ToCharArray(), charIndex, charCount, bytes, byteIndex);
157 // Get the bytes that result from encoding a character buffer.
158 public override int GetBytes(char[] chars, int charIndex, int charCount, byte[] bytes, int byteIndex)
162 throw new ArgumentNullException("chars");
166 throw new ArgumentNullException("bytes");
168 if(charIndex < 0 || charIndex > chars.Length)
170 throw new ArgumentOutOfRangeException
171 ("charIndex", Strings.GetString("ArgRange_Array"));
173 if(charCount < 0 || charCount > (chars.Length - charIndex))
175 throw new ArgumentOutOfRangeException
176 ("charCount", Strings.GetString("ArgRange_Array"));
178 if(byteIndex < 0 || byteIndex > bytes.Length)
180 throw new ArgumentOutOfRangeException
181 ("byteIndex", Strings.GetString("ArgRange_Array"));
183 if((bytes.Length - byteIndex) < charCount)
185 throw new ArgumentException
186 (Strings.GetString("Arg_InsufficientSpace"));
189 ToBytes(chars, charIndex, charCount, bytes, byteIndex);
193 // Convenience wrappers for "GetBytes".
194 public override int GetBytes(string s, int charIndex, int charCount, byte[] bytes, int byteIndex)
198 throw new ArgumentNullException("s");
202 throw new ArgumentNullException("bytes");
204 if(charIndex < 0 || charIndex > s.Length)
206 throw new ArgumentOutOfRangeException
208 Strings.GetString("ArgRange_StringIndex"));
210 if(charCount < 0 || charCount > (s.Length - charIndex))
212 throw new ArgumentOutOfRangeException
214 Strings.GetString("ArgRange_StringRange"));
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"));
227 ToBytes(s, charIndex, charCount, bytes, byteIndex);
231 public override byte[] GetBytes(string s)
234 throw new ArgumentNullException("s");
236 char[] data = s.ToCharArray();
238 return GetBytes(data, 0, data.Length);
241 // Get the number of characters needed to decode a byte buffer.
242 public override int GetCharCount(byte[] bytes, int index, int count)
246 throw new ArgumentNullException("bytes");
248 if(index < 0 || index > bytes.Length)
250 throw new ArgumentOutOfRangeException
251 ("index", Strings.GetString("ArgRange_Array"));
253 if(count < 0 || count > (bytes.Length - index))
255 throw new ArgumentOutOfRangeException
256 ("count", Strings.GetString("ArgRange_Array"));
261 // Get the characters that result from decoding a byte buffer.
262 public override int GetChars(byte[] bytes, int byteIndex, int byteCount,
263 char[] chars, int charIndex)
267 throw new ArgumentNullException("bytes");
271 throw new ArgumentNullException("chars");
273 if(byteIndex < 0 || byteIndex > bytes.Length)
275 throw new ArgumentOutOfRangeException
276 ("byteIndex", Strings.GetString("ArgRange_Array"));
278 if(byteCount < 0 || byteCount > (bytes.Length - byteIndex))
280 throw new ArgumentOutOfRangeException
281 ("byteCount", Strings.GetString("ArgRange_Array"));
283 if(charIndex < 0 || charIndex > chars.Length)
285 throw new ArgumentOutOfRangeException
286 ("charIndex", Strings.GetString("ArgRange_Array"));
288 if((chars.Length - charIndex) < byteCount)
290 throw new ArgumentException
291 (Strings.GetString("Arg_InsufficientSpace"));
293 int count = byteCount;
294 char[] cvt = toChars;
297 chars[charIndex++] = cvt[(int)(bytes[byteIndex++])];
302 // Get the maximum number of bytes needed to encode a
303 // specified number of characters.
304 public override int GetMaxByteCount(int charCount)
308 throw new ArgumentOutOfRangeException
310 Strings.GetString("ArgRange_NonNegative"));
315 // Get the maximum number of characters needed to decode a
316 // specified number of bytes.
317 public override int GetMaxCharCount(int byteCount)
321 throw new ArgumentOutOfRangeException
323 Strings.GetString("ArgRange_NonNegative"));
328 // Decode a buffer of bytes into a string.
329 public unsafe override String GetString(byte[] bytes, int index, int count)
333 throw new ArgumentNullException("bytes");
335 if(index < 0 || index > bytes.Length)
337 throw new ArgumentOutOfRangeException
338 ("index", Strings.GetString("ArgRange_Array"));
340 if(count < 0 || count > (bytes.Length - index))
342 throw new ArgumentOutOfRangeException
343 ("count", Strings.GetString("ArgRange_Array"));
349 string s = new string ((char) 0, count);
351 fixed (byte* bytePtr = bytes)
352 fixed (char* charPtr = s)
353 fixed (char* cvt = toChars) {
354 byte* b = bytePtr + index;
357 *(c++) = cvt[*(b++)];
362 public override String GetString(byte[] bytes)
366 throw new ArgumentNullException("bytes");
369 return GetString (bytes, 0, bytes.Length);
374 // Get the mail body name for this encoding.
375 public override String BodyName
383 // Get the human-readable name for this encoding.
384 public override String EncodingName
392 // Get the mail agent header name for this encoding.
393 public override String HeaderName
401 // Determine if this encoding can be displayed in a Web browser.
402 public override bool IsBrowserDisplay
406 return isBrowserDisplay;
410 // Determine if this encoding can be saved from a Web browser.
411 public override bool IsBrowserSave
415 return isBrowserSave;
419 // Determine if this encoding can be displayed in a mail/news agent.
420 public override bool IsMailNewsDisplay
424 return isMailNewsDisplay;
428 // Determine if this encoding can be saved from a mail/news agent.
429 public override bool IsMailNewsSave
433 return isMailNewsSave;
437 // Get the IANA-preferred Web name for this encoding.
438 public override String WebName
446 // Get the Windows code page represented by this object.
447 public override int WindowsCodePage
451 return windowsCodePage;
455 #endif // !ECMA_COMPAT
457 }; // class ByteEncoding
460 }; // namespace I18N.Encoding