| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194 |
- // Licensed to the .NET Foundation under one or more agreements.
- // The .NET Foundation licenses this file to you under the MIT license.
- // See the LICENSE file in the project root for more information.
- using System.Collections;
- using System.Diagnostics;
- using System.Threading;
- namespace System.Text
- {
- //
- // Data table for encoding classes. Used by System.Text.Encoding.
- // This class contains two hashtables to allow System.Text.Encoding
- // to retrieve the data item either by codepage value or by webName.
- //
- internal static partial class EncodingTable
- {
- private static readonly Hashtable s_nameToCodePage = Hashtable.Synchronized(new Hashtable(StringComparer.OrdinalIgnoreCase));
- private static CodePageDataItem[] s_codePageToCodePageData;
- /*=================================GetCodePageFromName==========================
- **Action: Given a encoding name, return the correct code page number for this encoding.
- **Returns: The code page for the encoding.
- **Arguments:
- ** name the name of the encoding
- **Exceptions:
- ** ArgumentNullException if name is null.
- ** internalGetCodePageFromName will throw ArgumentException if name is not a valid encoding name.
- ============================================================================*/
- internal static int GetCodePageFromName(string name)
- {
- if (name == null)
- throw new ArgumentNullException(nameof(name));
- object codePageObj;
- codePageObj = s_nameToCodePage[name];
- if (codePageObj != null)
- {
- return (int)codePageObj;
- }
- int codePage = InternalGetCodePageFromName(name);
- s_nameToCodePage[name] = codePage;
- return codePage;
- }
- // Find the data item by binary searching the table.
- private static int InternalGetCodePageFromName(string name)
- {
- int left = 0;
- int right = s_encodingNameIndices.Length - 2;
- int index;
- int result;
- Debug.Assert(s_encodingNameIndices.Length == s_codePagesByName.Length + 1);
- Debug.Assert(s_encodingNameIndices[s_encodingNameIndices.Length - 1] == s_encodingNames.Length);
- ReadOnlySpan<char> invariantName = name.ToLowerInvariant().AsSpan();
- //Binary search the array until we have only a couple of elements left and then
- //just walk those elements.
- while ((right - left) > 3)
- {
- index = ((right - left) / 2) + left;
- Debug.Assert(index < s_encodingNameIndices.Length - 1);
- result = string.CompareOrdinal(invariantName, s_encodingNames.AsSpan(s_encodingNameIndices[index], s_encodingNameIndices[index + 1] - s_encodingNameIndices[index]));
- if (result == 0)
- {
- //We found the item, return the associated codePage.
- return s_codePagesByName[index];
- }
- else if (result < 0)
- {
- //The name that we're looking for is less than our current index.
- right = index;
- }
- else
- {
- //The name that we're looking for is greater than our current index
- left = index;
- }
- }
- //Walk the remaining elements (it'll be 3 or fewer).
- for (; left <= right; left++)
- {
- Debug.Assert(left < s_encodingNameIndices.Length - 1);
- if (string.CompareOrdinal(invariantName, s_encodingNames.AsSpan(s_encodingNameIndices[left], s_encodingNameIndices[left + 1] - s_encodingNameIndices[left])) == 0)
- {
- return s_codePagesByName[left];
- }
- }
- // The encoding name is not valid.
- throw new ArgumentException(
- SR.Format(SR.Argument_EncodingNotSupported, name),
- nameof(name));
- }
- // Return a list of all EncodingInfo objects describing all of our encodings
- internal static EncodingInfo[] GetEncodings()
- {
- EncodingInfo[] arrayEncodingInfo = new EncodingInfo[s_mappedCodePages.Length];
- for (int i = 0; i < s_mappedCodePages.Length; i++)
- {
- arrayEncodingInfo[i] = new EncodingInfo(
- s_mappedCodePages[i],
- s_webNames.Substring(s_webNameIndices[i], s_webNameIndices[i + 1] - s_webNameIndices[i]),
- GetDisplayName(s_mappedCodePages[i], i)
- );
- }
- return arrayEncodingInfo;
- }
- internal static CodePageDataItem GetCodePageDataItem(int codePage)
- {
- if (s_codePageToCodePageData == null)
- {
- Interlocked.CompareExchange(ref s_codePageToCodePageData, new CodePageDataItem[s_mappedCodePages.Length], null);
- }
- // Keep in sync with s_mappedCodePages
- int index;
- switch (codePage)
- {
- case 1200: // utf-16
- index = 0;
- break;
- case 1201: // utf-16be
- index = 1;
- break;
- case 12000: // utf-32
- index = 2;
- break;
- case 12001: // utf-32be
- index = 3;
- break;
- case 20127: // us-ascii
- index = 4;
- break;
- case 28591: // iso-8859-1
- index = 5;
- break;
- case 65000: // utf-7
- index = 6;
- break;
- case 65001: // utf-8
- index = 7;
- break;
- default:
- return null;
- }
- CodePageDataItem data = s_codePageToCodePageData[index];
- if (data == null)
- {
- Interlocked.CompareExchange(ref s_codePageToCodePageData[index], InternalGetCodePageDataItem(codePage, index), null);
- data = s_codePageToCodePageData[index];
- }
- return data;
- }
- private static CodePageDataItem InternalGetCodePageDataItem(int codePage, int index)
- {
- int uiFamilyCodePage = s_uiFamilyCodePages[index];
- string webName = s_webNames.Substring(s_webNameIndices[index], s_webNameIndices[index + 1] - s_webNameIndices[index]);
- // All supported code pages have identical header names, and body names.
- string headerName = webName;
- string bodyName = webName;
- string displayName = GetDisplayName(codePage, index);
- uint flags = s_flags[index];
- return new CodePageDataItem(codePage, uiFamilyCodePage, webName, headerName, bodyName, displayName, flags);
- }
- private static string GetDisplayName(int codePage, int englishNameIndex)
- {
- string displayName = SR.GetResourceString("Globalization_cp_" + codePage.ToString());
- if (string.IsNullOrEmpty(displayName))
- displayName = s_englishNames.Substring(s_englishNameIndices[englishNameIndex], s_englishNameIndices[englishNameIndex + 1] - s_englishNameIndices[englishNameIndex]);
- return displayName;
- }
- }
- }
|