The Labs \ Source Viewer \ SSCLI \ System.Globalization \ InternalCodePageDataItem

  1. // ==++==
  2. //
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. //
  14. // ==--==
  15. namespace System.Globalization
  16. {
  17.     using System.Text;
  18.     using System.Runtime.InteropServices;
  19.     using System;
  20.     using System.Collections;
  21.     using System.Runtime.CompilerServices;
  22.     using System.Threading;
  23.     //
  24.     // Data table for encoding classes. Used by System.Text.Encoding.
  25.     // This class contains two hashtables to allow System.Text.Encoding
  26.     // to retrieve the data item either by codepage value or by webName.
  27.     //
  28.    
  29.     // Only statics, does not need to be marked with the serializable attribute
  30.     static internal class EncodingTable
  31.     {
  32.        
  33.         //This number is the size of the table in native. The value is retrieved by
  34.         //calling the native GetNumEncodingItems().
  35.         private static int lastEncodingItem = GetNumEncodingItems() - 1;
  36.        
  37.         //This number is the size of the code page table. Its generated when we walk the table the first time.
  38.         private static int lastCodePageItem;
  39.        
  40.         //
  41.         // This points to a native data table which maps an encoding name to the correct code page.
  42.         //
  43.         unsafe static internal InternalEncodingDataItem* encodingDataPtr = GetEncodingData();
  44.         //
  45.         // This points to a native data table which stores the properties for the code page, and
  46.         // the table is indexed by code page.
  47.         //
  48.         unsafe static internal InternalCodePageDataItem* codePageDataPtr = GetCodePageData();
  49.         //
  50.         // This caches the mapping of an encoding name to a code page.
  51.         //
  52.         static internal Hashtable hashByName = new Hashtable(StringComparer.OrdinalIgnoreCase);
  53.         //
  54.         // THe caches the data item which is indexed by the code page value.
  55.         //
  56.         static internal Hashtable hashByCodePage = new Hashtable();
  57.        
  58.         // Find the data item by binary searching the table that we have in native.
  59.         // nativeCompareOrdinalWC is an internal-only function.
  60.         unsafe private static int internalGetCodePageFromName(string name)
  61.         {
  62.             int left = 0;
  63.             int right = lastEncodingItem;
  64.             int index;
  65.             int result;
  66.            
  67.             //Binary search the array until we have only a couple of elements left and then
  68.             //just walk those elements.
  69.             while ((right - left) > 3) {
  70.                 index = ((right - left) / 2) + left;
  71.                
  72.                 bool success;
  73.                 result = String.nativeCompareOrdinalWC(name, encodingDataPtr[index].webName, true, out success);
  74.                
  75.                 if (result == 0) {
  76.                     //We found the item, return the associated codepage.
  77.                     return (encodingDataPtr[index].codePage);
  78.                 }
  79.                 else if (result < 0) {
  80.                     //The name that we're looking for is less than our current index.
  81.                     right = index;
  82.                 }
  83.                 else {
  84.                     //The name that we're looking for is greater than our current index
  85.                     left = index;
  86.                 }
  87.             }
  88.            
  89.             //Walk the remaining elements (it'll be 3 or fewer).
  90.             for (; left <= right; left++) {
  91.                 bool success;
  92.                 if (String.nativeCompareOrdinalWC(name, encodingDataPtr[left].webName, true, out success) == 0) {
  93.                     return (encodingDataPtr[left].codePage);
  94.                 }
  95.             }
  96.             // The encoding name is not valid.
  97.             throw new ArgumentException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Argument_EncodingNotSupported"), name), "name");
  98.         }
  99.        
  100.         // Return a list of all EncodingInfo objects describing all of our encodings
  101.         unsafe static internal EncodingInfo[] GetEncodings()
  102.         {
  103.             if (lastCodePageItem == 0) {
  104.                 int count;
  105.                 for (count = 0; codePageDataPtr[count].codePage != 0; count++) {
  106.                     // Count them
  107.                 }
  108.                 lastCodePageItem = count;
  109.             }
  110.            
  111.             EncodingInfo[] arrayEncodingInfo = new EncodingInfo[lastCodePageItem];
  112.            
  113.             int i;
  114.             for (i = 0; i < lastCodePageItem; i++)
  115.                 arrayEncodingInfo[i] = new EncodingInfo(codePageDataPtr[i].codePage, new string(codePageDataPtr[i].webName), Environment.GetResourceString("Globalization.cp_" + codePageDataPtr[i].codePage));
  116.            
  117.             return arrayEncodingInfo;
  118.         }
  119.        
  120. /*=================================GetCodePageFromName==========================
  121.         **Action: Given a encoding name, return the correct code page number for this encoding.
  122.         **Returns: The code page for the encoding.
  123.         **Arguments:
  124.         **  name    the name of the encoding
  125.         **Exceptions:
  126.         **  ArgumentNullException if name is null.
  127.         **  internalGetCodePageFromName will throw ArgumentException if name is not a valid encoding name.
  128.         ============================================================================*/       
  129.        
  130.         static internal int GetCodePageFromName(string name)
  131.         {
  132.             if (name == null) {
  133.                 throw new ArgumentNullException("name");
  134.             }
  135.            
  136.             object codePageObj;
  137.            
  138.             //
  139.             // The name is case-insensitive, but ToLower isn't free. Check for
  140.             // the code page in the given capitalization first.
  141.             //
  142.             codePageObj = hashByName[name];
  143.             if (codePageObj != null) {
  144.                 return ((int)codePageObj);
  145.             }
  146.            
  147.             //Okay, we didn't find it in the hash table, try looking it up in the
  148.             //unmanaged data.
  149.             int codePage = internalGetCodePageFromName(name);
  150.            
  151.             hashByName[name] = codePage;
  152.             return (codePage);
  153.         }
  154.        
  155.         unsafe static internal CodePageDataItem GetCodePageDataItem(int codepage)
  156.         {
  157.             CodePageDataItem dataItem;
  158.            
  159.             //Look up the item in the hashtable.
  160.             dataItem = (CodePageDataItem)hashByCodePage[codepage];
  161.            
  162.             //If we found it, return it.
  163.             if (dataItem != null) {
  164.                 return (dataItem);
  165.             }
  166.            
  167.             //If we didn't find it, try looking it up now.
  168.             //If we find it, add it to the hashtable.
  169.             //This is a linear search, but we probably won't be doing it very often.
  170.             //
  171.             int i = 0;
  172.             int data;
  173.             while ((data = codePageDataPtr[i].codePage) != 0) {
  174.                 if (data == codepage) {
  175.                     dataItem = new CodePageDataItem(i);
  176.                     hashByCodePage[codepage] = dataItem;
  177.                     return (dataItem);
  178.                 }
  179.                 i++;
  180.             }
  181.             //Nope, we didn't find it.
  182.             return (null);
  183.         }
  184.        
  185.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  186.         unsafe private static extern InternalEncodingDataItem* GetEncodingData();
  187.         //
  188.         // Return the number of encoding data items.
  189.         //
  190.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  191.         private static extern int GetNumEncodingItems();
  192.        
  193.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  194.         unsafe private static extern InternalCodePageDataItem* GetCodePageData();
  195.        
  196.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  197.         unsafe static internal extern byte* nativeCreateOpenFileMapping(string inSectionName, int inBytesToAllocate, out IntPtr mappedFileHandle);
  198.     }
  199.    
  200. /*=================================InternalEncodingDataItem==========================
  201.     **Action: This is used to map a encoding name to a correct code page number. By doing this,
  202.     ** we can get the properties of this encoding via the InternalCodePageDataItem.
  203.     **
  204.     ** We use this structure to access native data exposed by the native side.
  205.     ============================================================================*/   
  206.    
  207.     [System.Runtime.InteropServices.StructLayout(LayoutKind.Sequential)]
  208.     unsafe internal struct InternalEncodingDataItem
  209.     {
  210.         internal char* webName;
  211.         internal int codePage;
  212.     }
  213.    
  214. /*=================================InternalCodePageDataItem==========================
  215.     **Action: This is used to access the properties related to a code page.
  216.     ** We use this structure to access native data exposed by the native side.
  217.     ============================================================================*/   
  218.    
  219.     [System.Runtime.InteropServices.StructLayout(LayoutKind.Sequential)]
  220.     unsafe internal struct InternalCodePageDataItem
  221.     {
  222.         internal int codePage;
  223.         internal int uiFamilyCodePage;
  224.         internal char* webName;
  225.         internal char* headerName;
  226.         internal char* bodyName;
  227.         internal uint flags;
  228.     }
  229.    
  230. }

Developer Fusion