internal NumberFormatInfo(int dataItem, bool useUserOverride) { this.m_dataItem = dataItem; this.m_useUserOverride = useUserOverride; if (this.m_dataItem != 0) { // // /* * We don't have information for the following four. All cultures use * the same value set in the ctor of NumberFormatInfo. * PercentGroupSize * PercentDecimalDigits * PercentGroupSeparator * PerMilleSymbol */ // We directly use fields here since these data is coming from data table or Win32, so we // don't need to verify their values. this.percentDecimalDigits = this.numberDecimalDigits = CultureTable.GetInt32Value(m_dataItem, CultureTable.IDIGITS, m_useUserOverride); this.numberNegativePattern = CultureTable.GetInt32Value(m_dataItem, CultureTable.INEGNUMBER, m_useUserOverride); this.currencyDecimalDigits = CultureTable.GetInt32Value(m_dataItem, CultureTable.ICURRDIGITS, m_useUserOverride); this.currencyPositivePattern = CultureTable.GetInt32Value(m_dataItem, CultureTable.ICURRENCY, m_useUserOverride); this.currencyNegativePattern = CultureTable.GetInt32Value(m_dataItem, CultureTable.INEGCURR, m_useUserOverride); this.percentNegativePattern = CultureTable.GetInt32Value(m_dataItem, CultureTable.INEGATIVEPERCENT, m_useUserOverride); this.percentPositivePattern = CultureTable.GetInt32Value(m_dataItem, CultureTable.IPOSITIVEPERCENT, m_useUserOverride); this.negativeSign = CultureTable.GetStringValue(m_dataItem, CultureTable.SNEGATIVESIGN, m_useUserOverride); this.percentSymbol = CultureTable.GetStringValue(m_dataItem, CultureTable.SPERCENT, m_useUserOverride); this.percentDecimalSeparator = this.numberDecimalSeparator = CultureTable.GetStringValue(m_dataItem, CultureTable.SDECIMAL, m_useUserOverride); this.percentGroupSizes = this.numberGroupSizes = CultureInfo.ParseGroupString(CultureTable.GetStringValue(m_dataItem, CultureTable.SGROUPING, m_useUserOverride)); this.percentGroupSeparator = this.numberGroupSeparator = CultureTable.GetStringValue(m_dataItem, CultureTable.STHOUSAND, m_useUserOverride); this.positiveSign = CultureTable.GetStringValue(m_dataItem, CultureTable.SPOSITIVESIGN, m_useUserOverride); this.currencyDecimalSeparator = CultureTable.GetStringValue(m_dataItem, CultureTable.SMONDECIMALSEP, m_useUserOverride); //Special case for Italian. The currency decimal separator in the control panel is the empty string. When the user //specifies C4 as the currency format, this results in the number apparently getting multiplied by 10000 because the //decimal point doesn't show up. We'll just hack this here because our default currency format will never use this. if (currencyDecimalSeparator.Length == 0) { this.currencyDecimalSeparator = CultureTable.GetStringValue(m_dataItem, CultureTable.SMONDECIMALSEP, false); } this.currencyGroupSizes = CultureInfo.ParseGroupString(CultureTable.GetStringValue(m_dataItem, CultureTable.SMONGROUPING, m_useUserOverride)); this.currencyGroupSeparator = CultureTable.GetStringValue(m_dataItem, CultureTable.SMONTHOUSANDSEP, m_useUserOverride); this.currencySymbol = CultureTable.GetStringValue(m_dataItem, CultureTable.SCURRENCY, m_useUserOverride); this.ansiCurrencySymbol = CultureTable.GetStringValue(m_dataItem, CultureTable.SANSICURRENCYSYMBOL, false); if (this.ansiCurrencySymbol.Length == 0) { this.ansiCurrencySymbol = null; } this.negativeInfinitySymbol = CultureTable.GetStringValue(m_dataItem, CultureTable.SNEGINFINITY, m_useUserOverride); this.positiveInfinitySymbol = CultureTable.GetStringValue(m_dataItem, CultureTable.SPOSINFINITY, m_useUserOverride); this.nanSymbol = CultureTable.GetStringValue(m_dataItem, CultureTable.SNAN, m_useUserOverride); } }
internal static bool IsValidSortID(int dataItem, int sortID) { BCLDebug.Assert(sortID >= 0 && sortID <= 0xffff, "sortID is invalid"); // SortID is 16-bit positive integer. return( sortID == 0 || CultureTable.GetDefaultInt32Value(dataItem, CultureTable.IALTSORTID) == sortID ); }
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; }
//////////////////////////////////////////////////////////////////////// // // TextInfo Constructors // // Implements CultureInfo.TextInfo. // //////////////////////////////////////////////////////////////////////// internal TextInfo(int cultureID, int nDataItem, bool useUserOverride) { m_nDataItem = nDataItem; m_useUserOverride = useUserOverride; m_win32LangID = CultureTable.GetDefaultInt32Value(m_nDataItem, CultureTable.WIN32LANGID); BCLDebug.Assert(CultureInfo.GetSortID(m_win32LangID) == 0, "CultureInfo.GetSortID(m_win32LangID) == 0"); lock (typeof(TextInfo)) { // Calling this method need syncronization since shared // data is used in the native side. m_pNativeTextInfo = InternalAllocateCasingTable(m_win32LangID); } }
/// <include file='doc\CultureInfo.uex' path='docs/doc[@for="CultureInfo.CultureInfo3"]/*' /> public CultureInfo(int culture, bool useUserOverride) { if (culture < 0) { throw new ArgumentOutOfRangeException("culture", Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum")); } if (culture == SPANISH_TRADITIONAL_SORT) { // HACKHACK // We are nuking 0x040a (Spanish Traditional sort) in NLS+. // So if you create 0x040a, it's just like 0x0c0a (Spanish International sort). // For a table setup reason, we can not really remove the data item for 0x040a in culture.nlp. // As a workaround, what we do is to make the data for 0x040a to be exactly the same as 0x0c0a. // Unfortunately, the culture name is the only exception. // So in the table, we still have "es-ES-Ts" in there which we can not make it "es-ES". // Again, this is for table setup reason. So if we are creating // CultureInfo using 0x040a, hardcode culture name to be "es-ES" here so that we won't // get "es-ES-Ts" in the table. m_name = "es-ES"; } m_dataItem = CultureTable.GetDataItemFromCultureID(GetLangID(culture)); if (m_dataItem < 0) { throw new ArgumentException( String.Format(Environment.GetResourceString("Argument_CultureNotSupported"), culture), "culture"); } this.m_useUserOverride = useUserOverride; int sortID; if ((sortID = GetSortID(culture)) != 0) { // // Check if the sort ID is valid. // if (!CultureTable.IsValidSortID(m_dataItem, sortID)) { throw new ArgumentException( String.Format(Environment.GetResourceString("Argument_CultureNotSupported"), culture), "culture"); } } this.cultureID = culture; }
/// <include file='doc\CultureInfo.uex' path='docs/doc[@for="CultureInfo.CultureInfo1"]/*' /> public CultureInfo(String name, bool useUserOverride) { if (name == null) { throw new ArgumentNullException("name", Environment.GetResourceString("ArgumentNull_String")); } this.m_dataItem = CultureTable.GetDataItemFromName(name); if (m_dataItem < 0) { throw new ArgumentException( String.Format(Environment.GetResourceString("Argument_InvalidCultureName"), name), "name"); } this.m_useUserOverride = useUserOverride; this.cultureID = CultureTable.GetDefaultInt32Value(m_dataItem, CultureTable.ILANGUAGE); }
/*=================================GetCompareInfo========================== **Action: Get the CompareInfo for the specified culture. **Returns: The CompareInfo for the specified culture. **Arguments: ** name the name of the culture. **Exceptions: ** ArgumentException if name is invalid. **============================================================================*/ /// <include file='doc\CompareInfo.uex' path='docs/doc[@for="CompareInfo.GetCompareInfo3"]/*' /> public static CompareInfo GetCompareInfo(String name) { if (name == null) { throw new ArgumentNullException("name"); } int dataItem = CultureTable.GetDataItemFromName(name); if (dataItem == -1) { throw new ArgumentException( String.Format(Environment.GetResourceString("Argument_InvalidCultureName"), name), "name"); } int culture = CultureTable.GetDefaultInt32Value(dataItem, CultureTable.WIN32LANGID); return(GetCompareInfo(culture)); }
/*=================================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 version for CompareInfo tables. **Returns: The CompareInfo for the specified culture. **Arguments: ** name the name of the culture ** assembly the assembly which contains the sorting table. **Exceptions: ** ArugmentNullException when the assembly is null ** ArgumentException if name is invalid. **============================================================================*/ /// <include file='doc\CompareInfo.uex' path='docs/doc[@for="CompareInfo.GetCompareInfo1"]/*' /> public static CompareInfo GetCompareInfo(String name, Assembly assembly) { if (name == null || assembly == null) { throw new ArgumentNullException(name == null ? "name" : "assembly"); } if (assembly != typeof(Object).Module.Assembly) { throw new ArgumentException(Environment.GetResourceString("Argument_OnlyMscorlib")); } int dataItem = CultureTable.GetDataItemFromName(name); if (dataItem == -1) { throw new ArgumentException( String.Format(Environment.GetResourceString("Argument_InvalidCultureName"), name), "name"); } int culture = CultureTable.GetDefaultInt32Value(dataItem, CultureTable.WIN32LANGID); return(GetCompareInfo(culture, assembly)); }
/// <include file='doc\CultureInfo.uex' path='docs/doc[@for="CultureInfo.GetCultures"]/*' /> public static CultureInfo[] GetCultures(CultureTypes types) { return(CultureTable.GetCultures(types)); }
static CultureTable() { m_defaultInstance = new CultureTable("culture.nlp", true); }
internal static CultureInfo GetCultureInfoHelper(int lcid, string name, string altName) { CultureInfo info; Hashtable nameCachedCultures = m_NameCachedCultures; if (name != null) { name = CultureTableRecord.AnsiToLower(name); } if (altName != null) { altName = CultureTableRecord.AnsiToLower(altName); } if (nameCachedCultures == null) { nameCachedCultures = Hashtable.Synchronized(new Hashtable()); } else if (lcid == -1) { info = (CultureInfo)nameCachedCultures[name + ((char)0xfffd) + altName]; if (info != null) { return(info); } } else if (lcid == 0) { info = (CultureInfo)nameCachedCultures[name]; if (info != null) { return(info); } } Hashtable lcidCachedCultures = m_LcidCachedCultures; if (lcidCachedCultures == null) { lcidCachedCultures = Hashtable.Synchronized(new Hashtable()); } else if (lcid > 0) { info = (CultureInfo)lcidCachedCultures[lcid]; if (info != null) { return(info); } } try { switch (lcid) { case -1: info = new CultureInfo(name, altName); goto Label_010A; case 0: info = new CultureInfo(name, false); goto Label_010A; } if ((m_userDefaultCulture != null) && (m_userDefaultCulture.LCID == lcid)) { info = (CultureInfo)m_userDefaultCulture.Clone(); info.m_cultureTableRecord = info.m_cultureTableRecord.CloneWithUserOverride(false); } else { info = new CultureInfo(lcid, false); } } catch (ArgumentException) { return(null); } Label_010A: info.m_isReadOnly = true; if (lcid == -1) { nameCachedCultures[name + ((char)0xfffd) + altName] = info; info.TextInfo.SetReadOnlyState(true); } else { if (!CultureTable.IsNewNeutralChineseCulture(info)) { lcidCachedCultures[info.LCID] = info; } string str = CultureTableRecord.AnsiToLower(info.m_name); nameCachedCultures[str] = info; } if (-1 != lcid) { m_LcidCachedCultures = lcidCachedCultures; } m_NameCachedCultures = nameCachedCultures; return(info); }
// // this constructor will create the CultureTableRecord object and point to the // culture table at the slot dataItem. // private unsafe CultureTableRecord(string regionName, int dataItem, bool useUserOverride) { BCLDebug.Assert(regionName != null && regionName.Length > 0, "[CultureTableRecord.CultureTableRecord(regionName,bool)]Expected non-null/empty name"); BCLDebug.Assert(dataItem > 0, "[CultureTableRecord.CultureTableRecord(regionName, dataItem, bool)] dataItem > 0 should be true."); // Assuming it works we'll want these this.m_bUseUserOverride = useUserOverride; this.m_CultureName = regionName; this.m_CultureTable = CultureTable.Default; // Found it, use it this.m_pData = (CultureTableData*)(this.m_CultureTable.m_pItemData + this.m_CultureTable.m_itemSize * dataItem); this.m_pPool = this.m_CultureTable.m_pDataPool; // Use ID from the file this.m_CultureID = this.ILANGUAGE; }
// // m_bUseUserOverride indicates that if we need to check for user-override values for this CultureInfo instance. // For the user default culture of the system, user can choose to override some of the values // associated with that culture. For example, the default short-date format for en-US is // "M/d/yyyy", however, one may change it to "dd/MM/yyyy" from the Regional Option in // the control panel. // So when a CultureInfo is created, one can specify if the create CultureInfo should check // for user-override values, or should always get the default values. // // // AVOID USING P/INVOKE IN THIS CODEPATH. // AVOID USING P/INVOKE IN THIS CODEPATH. // AVOID USING P/INVOKE IN THIS CODEPATH. // // P/Invoke will cause COM to be initialized and sets the thread apartment model. Since CultureInfo is used early in the CLR process, // this will prevent Loader from having a chance to look at the executable and setting the apartment model to the one the application wants. // // Search order for creating a culture. // /* First, search by name if this is a known culture name from culture.nlp, and it is an alternative sort name (such as de-DE_phoneb) { Get the name from the LANGID by removing the sort ID (so the name becomes de-DE). This is the name used for search replacment culture. } Check if this specified name has a custom/replacement culture file. if there is a custom/replacement culture file { // This is a custom culture, or a replacement culture. return; [CUSTOM/REPLACEMENT CULTURE (.NET CULTURE/SYNTHETIC CULTURE) FOUND BY NAME] } From culture.nlp, check if tihs is a vlid culture name if this is a valid culture name { // This is a .NET culture. return; [NON-REPLACEMENT .NET CULTURE FOUND BY NAME] } Check if this is a valid name from synthetic culture if this is a valid synthetic culture name { // This is a synthetic culture. Set the cultureID, so we will // create it when we search by LCID later. // [SYNTHETIC CULTURE FOUND BY NAME] } else { throw exception; [INVALID NAME] } Then Search by LCID we'll come here only if the lcid is filled with synthetic culture Id. // This is synthetic culture. Get the name for this LANGID of this synthetic LCID. if there is a replacement culture for this LCID by checking name. { Use it and return the replacement culture for synthetic culture. return; [REPLACEMENT SYNTHETIC CULTURE] } Init and return the synthetic culture. return; [NON-REPLACEMENT SYNTHETIC CULTURE] } otherwise throw exception */ // // * IMPORTANT * cultureName should be in lower case. // private unsafe CultureTableRecord(String cultureName, bool useUserOverride) { BCLDebug.Assert(cultureName != null, "[CultureTableRecord::ctor] cultureName should be valid."); int cultureID = 0; // Special case for invariant name if (cultureName.Length == 0) { useUserOverride = false; cultureID = CultureInfo.LOCALE_INVARIANT; } this.m_bUseUserOverride = useUserOverride; // We prefer to look up by name (if available) int iDataItem = -1; if (cultureName.Length > 0) { // Check if this is an alternative sort name. String defaultTableActualName; int defaultTableCultureID; string name = cultureName; int defaultTableDataItem = CultureTable.Default.GetDataItemFromCultureName(name, out defaultTableCultureID, out defaultTableActualName); if (defaultTableDataItem >= 0 && (CultureInfo.GetSortID(defaultTableCultureID) > 0 || defaultTableCultureID == SPANISH_TRADITIONAL_SORT)) { String replacmentCultureName; int nonSortId; if (defaultTableCultureID == SPANISH_TRADITIONAL_SORT) nonSortId = SPANISH_INTERNATIONAL_SORT; else nonSortId = CultureInfo.GetLangID(defaultTableCultureID); // This is an alternative sort culture. if (CultureTable.Default.GetDataItemFromCultureID(nonSortId, out replacmentCultureName) >= 0) { // This is the replacement culture name for an alternative sort. name = ValidateCulturePieceToLower(replacmentCultureName, "cultureName", MAXSIZE_FULLTAGNAME); } } // If the compatibility flag is defined and culture is replacemet culture then we don't // open the custom culture file. instead we'll try to get framework/OS culture. if (!Environment.GetCompatibilityFlag(CompatibilityFlag.DisableReplacementCustomCulture) || IsCustomCultureId(defaultTableCultureID)) { // we always try the replacement custom cultures first. // Before call this function, call ValidateCulturePieceToLower() to verify // that the name does not contain illegal characters (such as "." or backslash. m_CultureTable = GetCustomCultureTable(name); } if (m_CultureTable != null) { // // [CUSTOM/REPLACEMENT CULTURE (.NET CULTURE/SYNTHETIC CULTURE) FOUND BY NAME] // iDataItem = this.m_CultureTable.GetDataItemFromCultureName(name, out this.m_ActualCultureID, out this.m_ActualName); if (defaultTableDataItem >= 0) { // This is a replacment culture (since defaultTableDataItem >= 0), use the default ID/Name from the table. // For de-DE_phoneb, this will set the the actualCultureID to be 0x10407, instead of the LCID for replacment cutlure 0x0407. this.m_ActualCultureID = defaultTableCultureID; this.m_ActualName = defaultTableActualName; } } if (iDataItem < 0 && defaultTableDataItem >= 0) { // // [NON-REPLACEMENT .NET CULTURE FOUND BY NAME] // this.m_CultureTable = CultureTable.Default; this.m_ActualCultureID = defaultTableCultureID; this.m_ActualName = defaultTableActualName; iDataItem = defaultTableDataItem; } } // If we couldn't get it by name, try culture ID. if (iDataItem < 0 && cultureID > 0) { if (cultureID == CultureInfo.LOCALE_INVARIANT) { // Special case for the Invariant culture. iDataItem = CultureTable.Default.GetDataItemFromCultureID(cultureID, out this.m_ActualName); if (iDataItem > 0) { m_ActualCultureID = cultureID; m_CultureTable = CultureTable.Default; } } } // If we found one, use it and return if (iDataItem >= 0) { // Found it, use it this.m_pData = (CultureTableData*)(this.m_CultureTable.m_pItemData + this.m_CultureTable.m_itemSize * iDataItem); this.m_pPool = this.m_CultureTable.m_pDataPool; // Use name & ID from the file ('cept spanish traditional, which has to stay the same) this.m_CultureName = this.SNAME; this.m_CultureID = (m_ActualCultureID == SPANISH_TRADITIONAL_SORT) ? m_ActualCultureID : this.ILANGUAGE; return; } // Error, if we have a name throw that name if (cultureName != null) throw new ArgumentException( String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString("Argument_InvalidCultureName"), cultureName), "name"); // No name, throw the LCID throw new ArgumentException( String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString("Argument_CultureNotSupported"), cultureID), "culture"); }
// // This constructor used only to create a Framework culture. it doesn't create custom // culture nor synthetic culture. // This is used when requesting the native calendar name for a custom culture with // empty string native calendar name. // internal unsafe CultureTableRecord(int cultureId, bool useUserOverride) { this.m_bUseUserOverride = useUserOverride; int defaultTableDataItem = CultureTable.Default.GetDataItemFromCultureID(cultureId, out m_ActualName); if (defaultTableDataItem < 0) { throw new ArgumentException( String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString("Argument_CultureNotSupported"), cultureId), "culture"); } m_ActualCultureID = cultureId; m_CultureTable = CultureTable.Default; m_pData = (CultureTableData*)(m_CultureTable.m_pItemData + m_CultureTable.m_itemSize * defaultTableDataItem); m_pPool = m_CultureTable.m_pDataPool; m_CultureName = SNAME; m_CultureID = (cultureId == SPANISH_TRADITIONAL_SORT) ? cultureId : ILANGUAGE; BCLDebug.Assert(!IsCustomCulture , "[CultureTableRecord::ctor] we shouldn't have custom culture."); BCLDebug.Assert(!IsSynthetic, "[CultureTableRecord::ctor] we shouldn't have synthetic culture."); }
private unsafe CultureTable GetCustomCultureTable(string name) { CultureTable cultureTable = null; string customCultureFile = GetCustomCultureFile(name); if (customCultureFile == null) { return null; } try { cultureTable = new CultureTable(customCultureFile, false); if (!cultureTable.IsValid) { // If we have invalid culture table then we have custom culture. in that case we'll try // to see if the culture name is one of the framework or synthetic cultures and then // try to create it otherwise we'll throw. String defaultTableActualName; int defaultTableCultureID; int defaultTableDataItem = CultureTable.Default.GetDataItemFromCultureName( name, out defaultTableCultureID, out defaultTableActualName); if (defaultTableDataItem < 0) // not built in framework culture { } return null; // returning null means fallback to framework or synthetic culture. } } catch (FileNotFoundException) { // // getting here means custom culture file get unregistered/renamed from different AppDomain/Process. // just update the cache to point to the empty string as subsequent calls will not bother trying again. // cultureTable = null; } return cultureTable; }