[LoongArch64] Part-5:add loongarch support in some files for LoongArch64. (#21769)
[mono-project.git] / mcs / class / I18N / Common / ByteSafeEncoding.cs
blob97216cab9f504585519db6c4c0ec7255ccf7b65e
1 /*
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.
26 namespace I18N.Common
29 using System;
30 using System.Runtime.InteropServices;
31 using System.Text;
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.
38 #if DISABLE_UNSAFE
40 [Serializable]
41 public abstract class ByteSafeEncoding : MonoSafeEncoding
43 // Internal state.
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;
58 // Constructor.
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,
64 int windowsCodePage)
65 : base(codePage)
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)
85 return false;
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 {
115 get { return true; }
118 public override int GetByteCount(String s)
120 if(s == null)
121 throw new ArgumentNullException("s");
123 return s.Length;
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)
134 return 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
146 // (Ideal solution)
147 if (s.Length == 0 || bytes.Length == byteIndex)
148 return;
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)
156 if(chars == null)
158 throw new ArgumentNullException("chars");
160 if(bytes == null)
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);
186 return charCount;
189 // Convenience wrappers for "GetBytes".
190 public override int GetBytes(string s, int charIndex, int charCount, byte[] bytes, int byteIndex)
192 if(s == null)
194 throw new ArgumentNullException("s");
196 if(bytes == null)
198 throw new ArgumentNullException("bytes");
200 if(charIndex < 0 || charIndex > s.Length)
202 throw new ArgumentOutOfRangeException
203 ("charIndex",
204 Strings.GetString("ArgRange_StringIndex"));
206 if(charCount < 0 || charCount > (s.Length - charIndex))
208 throw new ArgumentOutOfRangeException
209 ("charCount",
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);
224 return charCount;
227 public override byte[] GetBytes(string s)
229 if (s == null)
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)
240 if(bytes == null)
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"));
254 return count;
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)
261 if(bytes == null)
263 throw new ArgumentNullException("bytes");
265 if(chars == null)
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;
291 while(count-- > 0)
293 chars[charIndex++] = cvt[(int)(bytes[byteIndex++])];
295 return byteCount;
298 // Get the maximum number of bytes needed to encode a
299 // specified number of characters.
300 public override int GetMaxByteCount(int charCount)
302 if(charCount < 0)
304 throw new ArgumentOutOfRangeException
305 ("charCount",
306 Strings.GetString("ArgRange_NonNegative"));
308 return charCount;
311 // Get the maximum number of characters needed to decode a
312 // specified number of bytes.
313 public override int GetMaxCharCount(int byteCount)
315 if(byteCount < 0)
317 throw new ArgumentOutOfRangeException
318 ("byteCount",
319 Strings.GetString("ArgRange_NonNegative"));
321 return byteCount;
324 // Decode a buffer of bytes into a string.
325 public unsafe override String GetString(byte[] bytes, int index, int count)
327 if(bytes == null)
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"));
342 if (count == 0)
343 return string.Empty;
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;
351 char* c = charPtr;
352 while(count-- != 0)
353 *(c++) = cvt[*(b++)];
356 return s;
358 public override String GetString(byte[] bytes)
360 if(bytes == null)
362 throw new ArgumentNullException("bytes");
365 return GetString (bytes, 0, bytes.Length);
368 #if !ECMA_COMPAT
370 // Get the mail body name for this encoding.
371 public override String BodyName
375 return bodyName;
379 // Get the human-readable name for this encoding.
380 public override String EncodingName
384 return encodingName;
388 // Get the mail agent header name for this encoding.
389 public override String HeaderName
393 return 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
438 return 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
455 #endif
456 }; // namespace I18N.Encoding