/*=================================GetCompareInfo========================== **Action: Get the CompareInfo constructed from the data table in the specified assembly for the specified culture. ** The purpose of this method is to provide versioning for CompareInfo tables. ** If you pass Assembly which contains different sorting table, you will sort your strings using the data ** in the assembly. **Returns: The CompareInfo for the specified culture. **Arguments: ** culture the ID of the culture ** assembly the assembly which contains the sorting table. **Exceptions: ** ArugmentNullException when the assembly is null ** ArgumentException if culture is invalid. **============================================================================*/ /* Note: The design goal here is that we can still provide version even when the underlying algorithm for CompareInfo * is totally changed in the future. * In the case that the algorithm for CompareInfo is changed, we can use this method to * provide the old algorithm for the old tables. The idea is to change the implementation for GetCompareInfo() * to something like: * 1. Check the ID of the assembly. * 2. If the assembly needs old code, create an instance of the old CompareInfo class. The name of CompareInfo * will be like CompareInfoVersion1 and extends from CompareInfo. * 3. Otherwise, create an instance of the current CompareInfo. * The CompareInfo ctor always provides the implementation for the current data table. */ /// <include file='doc\CompareInfo.uex' path='docs/doc[@for="CompareInfo.GetCompareInfo"]/*' /> public static CompareInfo GetCompareInfo(int culture, Assembly assembly) { // Parameter checking. if (assembly == null) { throw new ArgumentNullException("assembly"); } if (assembly != typeof(Object).Module.Assembly) { throw new ArgumentException(Environment.GetResourceString("Argument_OnlyMscorlib")); } // culture is verified to see if it is valid when CompareInfo is constructed. GlobalizationAssembly ga = GlobalizationAssembly.GetGlobalizationAssembly(assembly); Object compInfo = ga.compareInfoCache[culture]; if (compInfo == null) { lock (typeof(GlobalizationAssembly)) { // // Re-check again to make sure that no one has created the CompareInfo for the culture yet before the current // thread enters this sync block. // if ((compInfo = ga.compareInfoCache[culture]) == null) { compInfo = new CompareInfo(ga, culture); ga.compareInfoCache[culture] = compInfo; } } } return((CompareInfo)compInfo); }
internal static unsafe void *GetNativeTextInfo(int cultureID) { // First, assume this culture does not has exceptions. I.e. we should use the default casingg table. // So we assign the native NativeTextInfo for the default casing table to it. void *pNativeTextInfo = m_pDefaultCasingTable; // Now, go thru the exception table to see if it has exception or not. for (int i = 0; i < m_exceptionCount; i++) { if (m_exceptionTable[i].langID == cultureID) { // This culture has exceptions. if (m_exceptionNativeTextInfo[i] == 0) { lock (InternalSyncObject) { // Read the exception casing file. if (m_pExceptionFile == null) { m_pExceptionFile = GlobalizationAssembly.GetGlobalizationResourceBytePtr(typeof(TextInfo).Assembly, CASING_EXCEPTIONS_FILE_NAME); } long tempPtr = (long)(InternalAllocateCasingTable(m_pExceptionFile, m_exceptionTable[i].exceptIndex)); System.Threading.Thread.MemoryBarrier(); m_exceptionNativeTextInfo[i] = tempPtr; } } pNativeTextInfo = (void *)m_exceptionNativeTextInfo[i]; break; } } return(pNativeTextInfo); }
//////////////////////////////////////////////////////////////////////// // // Actions: // This is the static ctor for TextInfo. It does the following items: // * Get the total count of cultures with exceptions. // * Set up an exception index table so that we can check if a culture has exception. If yes, which sub-table // in the exception table file we should use for this culture. // * Set up a cache for NativeTextInfo that we create for cultures with exceptions. // //////////////////////////////////////////////////////////////////////// static unsafe TextInfo() { //with AppDomains active, the static initializer is no longer good enough to ensure that only one //thread is ever in AllocateDefaultCasingTable at a given time. //We use InterlockedExchangePointer in the native side to ensure that only one instance of native CasingTable instance //is created per process. //We check if the table is already allocated in native, so we only need to synchronize //access in managed. byte *temp = GlobalizationAssembly.GetGlobalizationResourceBytePtr(typeof(TextInfo).Assembly, CASING_FILE_NAME); System.Threading.Thread.MemoryBarrier(); m_pDataTable = temp; TextInfoDataHeader *pHeader = (TextInfoDataHeader *)m_pDataTable; m_exceptionCount = pHeader->exceptionCount; // Setup exception tables m_exceptionTable = (ExceptionTableItem *)&(pHeader->exceptionLangId); m_exceptionNativeTextInfo = new long[m_exceptionCount]; // Create the native NativeTextInfo for the default linguistic casing table. m_pDefaultCasingTable = AllocateDefaultCasingTable(m_pDataTable); BCLDebug.Assert(m_pDataTable != null, "Error in reading the table."); BCLDebug.Assert(m_pDefaultCasingTable != null, "m_pDefaultCasingTable != null"); }
internal unsafe void InitializeBaseInfoTablePointers(String fileName, bool fromAssembly) { if (fromAssembly) { m_pDataFileStart = GlobalizationAssembly.GetGlobalizationResourceBytePtr(typeof(BaseInfoTable).Assembly, fileName); } else { this.memoryMapFile = new MemoryMapFile(fileName); if (this.memoryMapFile.FileSize == 0) { m_valid = false; return; } this.m_pDataFileStart = this.memoryMapFile.GetBytePtr(); } EndianessHeader *pEndianHeader = (EndianessHeader *)m_pDataFileStart; // Set up pointer to the CultureTableHeader #if BIGENDIAN BCLDebug.Assert(pEndianHeader->beOffset != 0, "Big-Endian data is expected."); m_pCultureHeader = (CultureTableHeader *)(m_pDataFileStart + pEndianHeader->beOffset); #else BCLDebug.Assert(pEndianHeader->leOffset != 0, "Little-Endian data is expected."); m_pCultureHeader = (CultureTableHeader *)(m_pDataFileStart + pEndianHeader->leOffset); #endif // Set up misc pointers and variables. // Different data items for calendar and culture, so they each have their own setting thingy. SetDataItemPointers(); }
private static CompareInfo GetCompareInfoWithPrefixedLcid(int cultureKey, Assembly assembly, int prefix) { if (assembly == null) { throw new ArgumentNullException("assembly"); } int cultureId = cultureKey & ~prefix; if (System.Globalization.CultureTableRecord.IsCustomCultureId(cultureId)) { throw new ArgumentException(Environment.GetResourceString("Argument_CustomCultureCannotBePassedByNumber", new object[] { "culture" })); } if (assembly != typeof(object).Module.Assembly) { throw new ArgumentException(Environment.GetResourceString("Argument_OnlyMscorlib")); } GlobalizationAssembly globalizationAssembly = GlobalizationAssembly.GetGlobalizationAssembly(assembly); object obj2 = globalizationAssembly.compareInfoCache[cultureKey]; if (obj2 == null) { lock (InternalSyncObject) { obj2 = globalizationAssembly.compareInfoCache[cultureKey]; if (obj2 == null) { obj2 = new CompareInfo(globalizationAssembly, cultureId); Thread.MemoryBarrier(); globalizationAssembly.compareInfoCache[cultureKey] = obj2; } } } return((CompareInfo)obj2); }
static GlobalizationAssembly() { lock (typeof(GlobalizationAssembly)) { if (m_defaultInstance==null) { // Initialize the default GlobalizationAseembly for the default assembly. m_defaultInstance = GetGlobalizationAssembly(Assembly.GetAssembly(typeof(GlobalizationAssembly))); } } }
static GlobalizationAssembly() { lock (typeof(GlobalizationAssembly)) { if (m_defaultInstance == null) { // Initialize the default GlobalizationAseembly for the default assembly. m_defaultInstance = GetGlobalizationAssembly(Assembly.GetAssembly(typeof(GlobalizationAssembly))); } } }
internal static GlobalizationAssembly GetGlobalizationAssembly(Assembly assembly) { GlobalizationAssembly assembly2 = (GlobalizationAssembly)m_assemblyHash[assembly]; if (assembly2 == null) { RuntimeHelpers.TryCode code = new RuntimeHelpers.TryCode(GlobalizationAssembly.CreateGlobalizationAssembly); RuntimeHelpers.ExecuteCodeWithLock(typeof(CultureTableRecord), code, assembly); assembly2 = (GlobalizationAssembly)m_assemblyHash[assembly]; } return(assembly2); }
private unsafe static bool InitTable() { byte *globalizationResourceBytePtr = GlobalizationAssembly.GetGlobalizationResourceBytePtr(typeof(CharUnicodeInfo).Assembly, "charinfo.nlp"); CharUnicodeInfo.UnicodeDataHeader *ptr = (CharUnicodeInfo.UnicodeDataHeader *)globalizationResourceBytePtr; CharUnicodeInfo.s_pCategoryLevel1Index = (ushort *)(globalizationResourceBytePtr + ptr->OffsetToCategoriesIndex); CharUnicodeInfo.s_pCategoriesValue = globalizationResourceBytePtr + ptr->OffsetToCategoriesValue; CharUnicodeInfo.s_pNumericLevel1Index = (ushort *)(globalizationResourceBytePtr + ptr->OffsetToNumbericIndex); CharUnicodeInfo.s_pNumericValues = globalizationResourceBytePtr + ptr->OffsetToNumbericValue; CharUnicodeInfo.s_pDigitValues = (CharUnicodeInfo.DigitValues *)(globalizationResourceBytePtr + ptr->OffsetToDigitValue); return(true); }
internal unsafe CompareInfo(GlobalizationAssembly ga, int culture) { if (culture < 0) { throw new ArgumentOutOfRangeException("culture", Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum")); } this.m_sortingLCID = this.GetSortingLCID(culture); if (!this.IsSynthetic) { this.m_pSortingTable = InitializeCompareInfo(GlobalizationAssembly.DefaultInstance.pNativeGlobalizationAssembly, this.m_sortingLCID); } this.culture = culture; }
private static void CreateGlobalizationAssembly(object assem) { Assembly assembly2 = (Assembly) assem; GlobalizationAssembly assembly = (GlobalizationAssembly) m_assemblyHash[assembly2]; if (assembly == null) { assembly = new GlobalizationAssembly { pNativeGlobalizationAssembly = nativeCreateGlobalizationAssembly(assembly2) }; Thread.MemoryBarrier(); m_assemblyHash[assembly2] = assembly; } }
internal int culture; // the culture ID used to create this instance. //////////////////////////////////////////////////////////////////////// // // CompareInfo Constructor // // //////////////////////////////////////////////////////////////////////// // Constructs an instance that most closely corresponds to the NLS locale // identifier. internal unsafe CompareInfo(GlobalizationAssembly ga, int culture) { if (culture < 0) { throw new ArgumentOutOfRangeException("culture", Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum")); } // NOTENOTE YSLin: In the future, move all the culture validation to the native code InitializeCompareInfo, since we make three // native calls below, which are expansive. // // Verify that this is a valid culture. // int dataItem = CultureTable.GetDataItemFromCultureID(CultureInfo.GetLangID(culture)); if (dataItem == -1) { throw new ArgumentException( String.Format(Environment.GetResourceString("Argument_CultureNotSupported"), culture), "culture"); } // We do the following because the native C++ SortingTable is based on the // WIN32 LCID. It doesn't work for neutral cultures liek 0x0009. So we convert culture // to a Win32 LCID here. // Note that we have to get Sort ID from culture. This will affect the result of string comparison. this.win32LCID = CultureTable.GetDefaultInt32Value(dataItem, CultureTable.WIN32LANGID); int sortID = CultureInfo.GetSortID(culture); if (sortID != 0) { // Need to verify if the Sort ID is valid. if (!CultureTable.IsValidSortID(dataItem, sortID)) { throw new ArgumentException( String.Format(Environment.GetResourceString("Argument_CultureNotSupported"), culture), "culture"); } // This is an alterinative sort LCID. Hey man, don't forget to take your SORTID with you. win32LCID |= sortID << 16; } // TODO: InitializeCompareInfo should use ga instead of getting the default instance. // Call to the native side to create/get the corresponding native C++ SortingTable for this culture. // The returned value is a 32-bit pointer to the native C++ SortingTable instance. // We cache this pointer so that we can call methods of the SortingTable directly. pSortingTable = InitializeCompareInfo(GlobalizationAssembly.m_defaultInstance.pNativeGlobalizationAssembly, win32LCID); // Since win32LCID can be different from the passed-in culture in the case of neutral cultures, store the culture ID in a different place. this.culture = culture; }
private static void CreateGlobalizationAssembly(object assem) { Assembly assembly2 = (Assembly)assem; GlobalizationAssembly assembly = (GlobalizationAssembly)m_assemblyHash[assembly2]; if (assembly == null) { assembly = new GlobalizationAssembly { pNativeGlobalizationAssembly = nativeCreateGlobalizationAssembly(assembly2) }; Thread.MemoryBarrier(); m_assemblyHash[assembly2] = assembly; } }
private unsafe static void CreateGlobalizationAssembly(object assem) { GlobalizationAssembly ga; Assembly assembly = (Assembly)assem; if ((ga = (GlobalizationAssembly)m_assemblyHash[assembly]) == null) { // This assembly is not used before, create a corresponding native NativeGlobalizationAssembly object for it. ga = new GlobalizationAssembly(); ga.pNativeGlobalizationAssembly = nativeCreateGlobalizationAssembly(assembly); System.Threading.Thread.MemoryBarrier(); m_assemblyHash[assembly] = ga; } }
//We need to allocate the underlying table that provides us with the information that we //use. We allocate this once in the class initializer and then we don't need to worry //about it again. // unsafe static CharUnicodeInfo() { m_pDataTable = GlobalizationAssembly.GetGlobalizationResourceBytePtr(typeof(CharUnicodeInfo).Assembly, UNICODE_INFO_FILE_NAME); UnicodeDataHeader *mainHeader = (UnicodeDataHeader *)m_pDataTable; // Set up the native pointer to different part of the tables. m_pCategoryLevel1Index = (ushort *)(m_pDataTable + mainHeader->OffsetToCategoriesIndex); m_pCategoriesValue = (byte *)(m_pDataTable + mainHeader->OffsetToCategoriesValue); m_pNumericLevel1Index = (ushort *)(m_pDataTable + mainHeader->OffsetToNumbericIndex); m_pNumericValues = (byte *)(m_pDataTable + mainHeader->OffsetToNumbericValue); m_pDigitValues = (DigitValues *)(m_pDataTable + mainHeader->OffsetToDigitValue); // Go to native side to make sure the native CharacterInfoTable pointer in the native side is initialized. nativeInitTable(m_pDataTable); }
unsafe static bool InitTable() { // Go to native side and get pointer to the native table byte *pDataTable = GlobalizationAssembly.GetGlobalizationResourceBytePtr(typeof(CharUnicodeInfo).Assembly, UNICODE_INFO_FILE_NAME); UnicodeDataHeader *mainHeader = (UnicodeDataHeader *)pDataTable; // Set up the native pointer to different part of the tables. s_pCategoryLevel1Index = (ushort *)(pDataTable + EndianSwap(mainHeader->OffsetToCategoriesIndex)); s_pCategoriesValue = (byte *)(pDataTable + EndianSwap(mainHeader->OffsetToCategoriesValue)); s_pNumericLevel1Index = (ushort *)(pDataTable + EndianSwap(mainHeader->OffsetToNumbericIndex)); s_pNumericValues = (byte *)(pDataTable + EndianSwap(mainHeader->OffsetToNumbericValue)); s_pDigitValues = (DigitValues *)(pDataTable + EndianSwap(mainHeader->OffsetToDigitValue)); return(true); }
/*=================================GetGlobalizationAssembly========================== **Action: Return the GlobalizationAssembly instance for the specified assembly. ** Every assembly should have one and only one instance of GlobalizationAssembly. **Returns: An instance of GlobalizationAssembly. **Arguments: **Exceptions: **============================================================================*/ unsafe internal static GlobalizationAssembly GetGlobalizationAssembly(Assembly assembly) { GlobalizationAssembly ga; if ((ga = (GlobalizationAssembly)m_assemblyHash[assembly]) == null) { lock (typeof(GlobalizationAssembly)) { if ((ga = (GlobalizationAssembly)m_assemblyHash[assembly]) == null) { // This assembly is not used before, create a corresponding native NativeGlobalizationAssembly object for it. ga = new GlobalizationAssembly(); ga.pNativeGlobalizationAssembly = nativeCreateGlobalizationAssembly(assembly); m_assemblyHash[assembly] = ga; } } } return(ga); }
internal unsafe void InitializeBaseInfoTablePointers(string fileName, bool fromAssembly) { if (fromAssembly) { this.m_pDataFileStart = GlobalizationAssembly.GetGlobalizationResourceBytePtr(typeof(BaseInfoTable).Assembly, fileName); } else { this.memoryMapFile = new AgileSafeNativeMemoryHandle(fileName); if (this.memoryMapFile.FileSize == 0L) { this.m_valid = false; return; } this.m_pDataFileStart = this.memoryMapFile.GetBytePtr(); } EndianessHeader *pDataFileStart = (EndianessHeader *)this.m_pDataFileStart; this.m_pCultureHeader = (CultureTableHeader *)(this.m_pDataFileStart + pDataFileStart->leOffset); this.SetDataItemPointers(); }
/*=================================GetGlobalizationAssembly========================== **Action: Return the GlobalizationAssembly instance for the specified assembly. ** Every assembly should have one and only one instance of GlobalizationAssembly. **Returns: An instance of GlobalizationAssembly. **Arguments: **Exceptions: ============================================================================*/ unsafe internal static GlobalizationAssembly GetGlobalizationAssembly(Assembly assembly) { GlobalizationAssembly ga; if ((ga = (GlobalizationAssembly)m_assemblyHash[assembly]) == null) { lock (typeof(GlobalizationAssembly)) { if ((ga = (GlobalizationAssembly)m_assemblyHash[assembly]) == null) { // This assembly is not used before, create a corresponding native NativeGlobalizationAssembly object for it. ga = new GlobalizationAssembly(); ga.pNativeGlobalizationAssembly = nativeCreateGlobalizationAssembly(assembly); m_assemblyHash[assembly] = ga; } } } return (ga); }
internal int culture; // the culture ID used to create this instance. //////////////////////////////////////////////////////////////////////// // // CompareInfo Constructor // // //////////////////////////////////////////////////////////////////////// // Constructs an instance that most closely corresponds to the NLS locale // identifier. internal unsafe CompareInfo(GlobalizationAssembly ga, int culture) { if (culture < 0) { throw new ArgumentOutOfRangeException("culture", Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum")); } // // Verify that this is a valid culture. // int dataItem = CultureTable.GetDataItemFromCultureID(CultureInfo.GetLangID(culture)); if (dataItem == -1) { throw new ArgumentException( String.Format(Environment.GetResourceString("Argument_CultureNotSupported"), culture), "culture"); } // We do the following because the native C++ SortingTable is based on the // WIN32 LCID. It doesn't work for neutral cultures liek 0x0009. So we convert culture // to a Win32 LCID here. // Note that we have to get Sort ID from culture. This will affect the result of string comparison. this.win32LCID = CultureTable.GetDefaultInt32Value(dataItem, CultureTable.WIN32LANGID); int sortID = CultureInfo.GetSortID(culture); if (sortID != 0) { // Need to verify if the Sort ID is valid. if (!CultureTable.IsValidSortID(dataItem, sortID)) { throw new ArgumentException( String.Format(Environment.GetResourceString("Argument_CultureNotSupported"), culture), "culture"); } // This is an alterinative sort LCID. Hey man, don't forget to take your SORTID with you. win32LCID |= sortID << 16; } // Call to the native side to create/get the corresponding native C++ SortingTable for this culture. // The returned value is a 32-bit pointer to the native C++ SortingTable instance. // We cache this pointer so that we can call methods of the SortingTable directly. pSortingTable = InitializeCompareInfo(GlobalizationAssembly.m_defaultInstance.pNativeGlobalizationAssembly, win32LCID); // Since win32LCID can be different from the passed-in culture in the case of neutral cultures, store the culture ID in a different place. this.culture = culture; }
private static unsafe bool InitTable() { byte *globalizationResourceBytePtr; CharUnicodeInfo.UnicodeDataHeader *unicodeDataHeaderPtr = (CharUnicodeInfo.UnicodeDataHeader *)(globalizationResourceBytePtr = GlobalizationAssembly.GetGlobalizationResourceBytePtr(typeof(CharUnicodeInfo).Assembly, "charinfo.nlp")); IntPtr num1 = (IntPtr)unicodeDataHeaderPtr->OffsetToCategoriesIndex; CharUnicodeInfo.s_pCategoryLevel1Index = (ushort *)(globalizationResourceBytePtr + num1.ToInt64()); IntPtr num2 = (IntPtr)unicodeDataHeaderPtr->OffsetToCategoriesValue; CharUnicodeInfo.s_pCategoriesValue = globalizationResourceBytePtr + num2.ToInt64(); IntPtr num3 = (IntPtr)unicodeDataHeaderPtr->OffsetToNumbericIndex; CharUnicodeInfo.s_pNumericLevel1Index = (ushort *)(globalizationResourceBytePtr + num3.ToInt64()); IntPtr num4 = (IntPtr)unicodeDataHeaderPtr->OffsetToNumbericValue; CharUnicodeInfo.s_pNumericValues = globalizationResourceBytePtr + num4.ToInt64(); IntPtr num5 = (IntPtr)unicodeDataHeaderPtr->OffsetToDigitValue; CharUnicodeInfo.s_pDigitValues = (CharUnicodeInfo.DigitValues *)(globalizationResourceBytePtr + num5.ToInt64()); return(true); }
private unsafe static void CreateGlobalizationAssembly(object assem) { GlobalizationAssembly ga; Assembly assembly = (Assembly) assem; if ((ga = (GlobalizationAssembly)m_assemblyHash[assembly]) == null) { // This assembly is not used before, create a corresponding native NativeGlobalizationAssembly object for it. ga = new GlobalizationAssembly(); ga.pNativeGlobalizationAssembly = nativeCreateGlobalizationAssembly(assembly); System.Threading.Thread.MemoryBarrier(); m_assemblyHash[assembly] = ga; } }
private String m_name = null; // The name of the culture of this instance //////////////////////////////////////////////////////////////////////// // // CompareInfo Constructor // // //////////////////////////////////////////////////////////////////////// // Constructs an instance that most closely corresponds to the NLS locale // identifier. internal unsafe CompareInfo(GlobalizationAssembly ga, int culture) { if (culture < 0) { throw new ArgumentOutOfRangeException("culture", Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum")); } // Get the Win32 LCID used to create NativeCompareInfo, which only takes Win32 LCID. this.m_sortingLCID = GetSortingLCID(culture); // If version support is enabled, InitializeCompareInfo should use ga instead of getting the default // instance. // Call to the native side to create/get the corresponding native C++ SortingTable for this culture. // The returned value is a 32-bit pointer to the native C++ SortingTable instance. // We cache this pointer so that we can call methods of the SortingTable directly. if (!IsSynthetic) { m_pSortingTable = InitializeCompareInfo(GlobalizationAssembly.DefaultInstance.pNativeGlobalizationAssembly, this.m_sortingLCID); } // Since this.m_sortingLCID can be different from the passed-in culture in the case of neutral cultures, store the culture ID in a different place. this.culture = culture; }