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
;
54 static byte [] isNormalized
;
55 static byte [] isNormalizedComputed
;
56 static byte [] normalization_bytes
;
59 protected ByteSafeEncoding(int codePage
, char[] toChars
,
60 String encodingName
, String bodyName
,
61 String headerName
, String webName
,
62 bool isBrowserDisplay
, bool isBrowserSave
,
63 bool isMailNewsDisplay
, bool isMailNewsSave
,
67 if (toChars
.Length
!= byte.MaxValue
+ 1)
68 throw new ArgumentException("toChars");
70 this.toChars
= toChars
;
71 this.encodingName
= encodingName
;
72 this.bodyName
= bodyName
;
73 this.headerName
= headerName
;
74 this.webName
= webName
;
75 this.isBrowserDisplay
= isBrowserDisplay
;
76 this.isBrowserSave
= isBrowserSave
;
77 this.isMailNewsDisplay
= isMailNewsDisplay
;
78 this.isMailNewsSave
= isMailNewsSave
;
79 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
{
118 public override int GetByteCount(String s
)
121 throw new ArgumentNullException("s");
126 // Get the number of bytes needed to encode a character buffer.
127 public override int GetByteCount(char[] chars
, int index
, int count
)
129 return count
- index
;
132 public override unsafe int GetByteCount(char* chars
, int count
)
137 // Convert an array of characters into a byte buffer,
138 // once the parameters have been validated.
139 protected abstract void ToBytes(char[] chars
, int charIndex
, int charCount
, byte[] bytes
, int byteIndex
);
141 // Convert a string into a byte buffer, once the parameters
142 // have been validated.
143 protected virtual void ToBytes(String s
, int charIndex
, int charCount
, byte[] bytes
, int byteIndex
)
145 // When it is not overriden, use ToBytes() with pointers
147 if (s
.Length
== 0 || bytes
.Length
== byteIndex
)
150 ToBytes(s
.ToCharArray(), charIndex
, charCount
, bytes
, byteIndex
);
153 // Get the bytes that result from encoding a character buffer.
154 public override int GetBytes(char[] chars
, int charIndex
, int charCount
, byte[] bytes
, int byteIndex
)
158 throw new ArgumentNullException("chars");
162 throw new ArgumentNullException("bytes");
164 if(charIndex
< 0 || charIndex
> chars
.Length
)
166 throw new ArgumentOutOfRangeException
167 ("charIndex", Strings
.GetString("ArgRange_Array"));
169 if(charCount
< 0 || charCount
> (chars
.Length
- charIndex
))
171 throw new ArgumentOutOfRangeException
172 ("charCount", Strings
.GetString("ArgRange_Array"));
174 if(byteIndex
< 0 || byteIndex
> bytes
.Length
)
176 throw new ArgumentOutOfRangeException
177 ("byteIndex", Strings
.GetString("ArgRange_Array"));
179 if((bytes
.Length
- byteIndex
) < charCount
)
181 throw new ArgumentException
182 (Strings
.GetString("Arg_InsufficientSpace"));
185 ToBytes(chars
, charIndex
, charCount
, bytes
, byteIndex
);
189 // Convenience wrappers for "GetBytes".
190 public override int GetBytes(string s
, int charIndex
, int charCount
, byte[] bytes
, int byteIndex
)
194 throw new ArgumentNullException("s");
198 throw new ArgumentNullException("bytes");
200 if(charIndex
< 0 || charIndex
> s
.Length
)
202 throw new ArgumentOutOfRangeException
204 Strings
.GetString("ArgRange_StringIndex"));
206 if(charCount
< 0 || charCount
> (s
.Length
- charIndex
))
208 throw new ArgumentOutOfRangeException
210 Strings
.GetString("ArgRange_StringRange"));
212 if(byteIndex
< 0 || byteIndex
> bytes
.Length
)
214 throw new ArgumentOutOfRangeException
215 ("byteIndex", Strings
.GetString("ArgRange_Array"));
217 if((bytes
.Length
- byteIndex
) < charCount
)
219 throw new ArgumentException
220 (Strings
.GetString("Arg_InsufficientSpace"));
223 ToBytes(s
, charIndex
, charCount
, bytes
, byteIndex
);
227 public override byte[] GetBytes(string s
)
230 throw new ArgumentNullException("s");
232 char[] data
= s
.ToCharArray();
234 return GetBytes(data
, 0, data
.Length
);
237 // Get the number of characters needed to decode a byte buffer.
238 public override int GetCharCount(byte[] bytes
, int index
, int count
)
242 throw new ArgumentNullException("bytes");
244 if(index
< 0 || index
> bytes
.Length
)
246 throw new ArgumentOutOfRangeException
247 ("index", Strings
.GetString("ArgRange_Array"));
249 if(count
< 0 || count
> (bytes
.Length
- index
))
251 throw new ArgumentOutOfRangeException
252 ("count", Strings
.GetString("ArgRange_Array"));
257 // Get the characters that result from decoding a byte buffer.
258 public override int GetChars(byte[] bytes
, int byteIndex
, int byteCount
,
259 char[] chars
, int charIndex
)
263 throw new ArgumentNullException("bytes");
267 throw new ArgumentNullException("chars");
269 if(byteIndex
< 0 || byteIndex
> bytes
.Length
)
271 throw new ArgumentOutOfRangeException
272 ("byteIndex", Strings
.GetString("ArgRange_Array"));
274 if(byteCount
< 0 || byteCount
> (bytes
.Length
- byteIndex
))
276 throw new ArgumentOutOfRangeException
277 ("byteCount", Strings
.GetString("ArgRange_Array"));
279 if(charIndex
< 0 || charIndex
> chars
.Length
)
281 throw new ArgumentOutOfRangeException
282 ("charIndex", Strings
.GetString("ArgRange_Array"));
284 if((chars
.Length
- charIndex
) < byteCount
)
286 throw new ArgumentException
287 (Strings
.GetString("Arg_InsufficientSpace"));
289 int count
= byteCount
;
290 char[] cvt
= toChars
;
293 chars
[charIndex
++] = cvt
[(int)(bytes
[byteIndex
++])];
298 // Get the maximum number of bytes needed to encode a
299 // specified number of characters.
300 public override int GetMaxByteCount(int charCount
)
304 throw new ArgumentOutOfRangeException
306 Strings
.GetString("ArgRange_NonNegative"));
311 // Get the maximum number of characters needed to decode a
312 // specified number of bytes.
313 public override int GetMaxCharCount(int byteCount
)
317 throw new ArgumentOutOfRangeException
319 Strings
.GetString("ArgRange_NonNegative"));
324 // Decode a buffer of bytes into a string.
325 public unsafe override String
GetString(byte[] bytes
, int index
, int count
)
329 throw new ArgumentNullException("bytes");
331 if(index
< 0 || index
> bytes
.Length
)
333 throw new ArgumentOutOfRangeException
334 ("index", Strings
.GetString("ArgRange_Array"));
336 if(count
< 0 || count
> (bytes
.Length
- index
))
338 throw new ArgumentOutOfRangeException
339 ("count", Strings
.GetString("ArgRange_Array"));
345 string s
= new string ((char) 0, count
);
347 fixed (byte* bytePtr
= bytes
)
348 fixed (char* charPtr
= s
)
349 fixed (char* cvt
= toChars
) {
350 byte* b
= bytePtr
+ index
;
353 *(c
++) = cvt
[*(b
++)];
358 public override String
GetString(byte[] bytes
)
362 throw new ArgumentNullException("bytes");
365 return GetString (bytes
, 0, bytes
.Length
);
370 // Get the mail body name for this encoding.
371 public override String BodyName
379 // Get the human-readable name for this encoding.
380 public override String EncodingName
388 // Get the mail agent header name for this encoding.
389 public override String HeaderName
397 // Determine if this encoding can be displayed in a Web browser.
398 public override bool IsBrowserDisplay
402 return isBrowserDisplay
;
406 // Determine if this encoding can be saved from a Web browser.
407 public override bool IsBrowserSave
411 return isBrowserSave
;
415 // Determine if this encoding can be displayed in a mail/news agent.
416 public override bool IsMailNewsDisplay
420 return isMailNewsDisplay
;
424 // Determine if this encoding can be saved from a mail/news agent.
425 public override bool IsMailNewsSave
429 return isMailNewsSave
;
433 // Get the IANA-preferred Web name for this encoding.
434 public override String WebName
442 // Get the Windows code page represented by this object.
443 public override int WindowsCodePage
447 return windowsCodePage
;
451 #endif // !ECMA_COMPAT
453 }; // class ByteEncoding
456 }; // namespace I18N.Encoding