mirror of
https://github.com/ICDSystems/ICD.Common.Utils.git
synced 2026-02-14 04:05:04 +00:00
1043 lines
38 KiB
C#
1043 lines
38 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Globalization;
|
|
using System.Linq;
|
|
using ICD.Common.Utils.IO;
|
|
using ICD.Common.Utils.Sqlite;
|
|
|
|
namespace ICD.Common.Utils.Globalization
|
|
{
|
|
/// <summary>
|
|
/// Adds missing cultures to the limited selection provided by Crestron.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// This class is a slight modification of CultureEx provided by Neil Colvin in his SSharpCultureLibrary.
|
|
///
|
|
/// ICD Changes include:
|
|
/// - Using ICD wrapper classes (IO, SQLite, Reflection) to support Net Standard for testing
|
|
/// - Removing Neil's custom threading mechanisms (do we *really* want to do threading on Crestron?)
|
|
/// - Moving the database location out of NVRAM and into the program directory.
|
|
///
|
|
///
|
|
/// Neil Colvin - Actually 1.500.0013 - CultureInfo
|
|
/// http://www.crestronlabs.com/showthread.php?11036
|
|
///
|
|
/// It has been very frustrating to live with the limitations of the S#/CF when it comes to internationalization.
|
|
/// Crestron has chosen to include no international CultureInfo's in their build of Windows CE.
|
|
/// This makes writing generic modules that work in a wide variety of international environments very difficult.
|
|
/// To provide a solution to this problem, I have implemented a System.Globolization.CultureInfoEx class that provides
|
|
/// many of the missing pieces.
|
|
///
|
|
/// CultureInfoEx derives from CultureInfo, so it has the identical properties and methods, both static and instance,
|
|
/// It also has the one method missing in the CF build, GetCultures (CultureTypes type) so that all available cultures
|
|
/// can be obtained.
|
|
///
|
|
/// The important piece behind this is a SQLite database which includes the data for the entire set of CultureInfo's
|
|
/// that are available on Windows 10 (809 of them). This database is slightly more the 1 MB in size.
|
|
///
|
|
/// This allows CultureInfoEx to be relatively small (23 KB), yet support every culture. Since it is derived from
|
|
/// CultureInfo, it can be passed to any method taking a CultureInfo, or an IFormatProvider, as an argument (like
|
|
/// String.Format, for instance).
|
|
///
|
|
/// When a specific culture is referenced in the CultureInfoEx constructor or in the GetCulture method, it is created
|
|
/// on the fly from the SQLite database (and cached in the case of GetCulture so that it does not have to be recreated).
|
|
///
|
|
/// The SQLite database is read-only, so there is no difficulty with it being located in the control system internal
|
|
/// flash file system (it is currently defined to be located in the \NVRAM\DBs folder). It is totally thread safe as well.
|
|
///
|
|
/// If a resident CultureInfo is requested (like "en-US") the built in CultureInfo is used, not the one from the database.
|
|
///
|
|
/// ...
|
|
///
|
|
/// I have posted this library on my download site as SSharpCultureLibrary. The database is in the Databases Folder as a
|
|
/// zip file. It should either be in the same folder on the control system as the library, or if it is to be shared among
|
|
/// multiple slots, it should be in the \NVRAM\DBs folder.
|
|
///
|
|
/// It should be noted that this does not 100% replicate System.Globalization.CultureInfo, since sealed classes and built-in
|
|
/// functionality make that impossible.
|
|
///
|
|
/// For instance CompareInfo is a real problem because it is a sealed class. Although CultureInfoEx defaults a CompareInfo
|
|
/// in most cases, it is probably not the correct one. Also, any attempt to generate a CompareInfo for any but the "en-US"
|
|
/// culture will fail.
|
|
///
|
|
/// Also, many .NET functions implicitly use CultureInfo.CurrentCulture as their culture (like String.Format). To use one
|
|
/// the CultureInfoEx generated CultureInfo's, they must be used explicitly (all .NET functions which use
|
|
/// CultureInfo.CurrentCulture implicitely have a version which takes the CultureInfo explicitely as well).
|
|
///
|
|
/// However, this class does provide all of the needed culture specific formatting information needed to display information
|
|
/// correctly for that culture (both numbers and data/time).
|
|
///
|
|
///
|
|
/// Neil's SSharp/Mono libraries are licensed under MIT:
|
|
///
|
|
/// The MIT License (MIT)
|
|
///
|
|
/// Copyright (c) 2019 Nivloc Enterprises Ltd
|
|
///
|
|
/// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
/// of this software and associated documentation files (the "Software"), to deal
|
|
/// in the Software without restriction, including without limitation the rights
|
|
/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
/// copies of the Software, and to permit persons to whom the Software is
|
|
/// furnished to do so, subject to the following conditions:
|
|
///
|
|
/// The above copyright notice and this permission notice shall be included in
|
|
/// all copies or substantial portions of the Software.
|
|
///
|
|
/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
/// THE SOFTWARE.
|
|
/// </remarks>
|
|
public sealed class IcdCultureInfo : CultureInfo
|
|
{
|
|
private const string SQL_LOCAL_DATABASE_FILE = "CultureInfo.sqlite";
|
|
private const string SQL_CONNECTION_STRING_FORMAT =
|
|
#if SIMPLSHARP
|
|
"Data Source = {0}; Version = 3; ReadOnly = True";
|
|
#else
|
|
"Data Source = {0}";
|
|
#endif
|
|
private const string SQL_CMD_SELECT_BY_NAME = "select * from cultureinfo where name = @name collate nocase";
|
|
private const string SQL_CMD_SELECT_BY_LCID = "select * from cultureinfo where lcid = @lcid";
|
|
private const string SQL_CMD_SELECT_BY_ID = "select * from cultureinfo where id = @id";
|
|
private const string SQL_CMD_SELECT_NUMBER_FORMAT_BY_ID = "select * from numberformatinfo where id = @id";
|
|
private const string SQL_CMD_SELECT_DATE_TIME_FORMAT_BY_ID = "select * from datetimeformatinfo where id = @id";
|
|
|
|
private static readonly Dictionary<string, CultureTypes> s_DictAvailableCulturesByName;
|
|
private static readonly Dictionary<int, CultureTypes> s_DictAvailableCulturesByLcid;
|
|
private static readonly Dictionary<string, string> s_DictSpecificCulture;
|
|
private static readonly string[] s_AvailableCultureNames;
|
|
private static readonly Dictionary<string, CultureInfo> s_DictCacheByName;
|
|
private static readonly SafeCriticalSection s_LockCacheByName;
|
|
private static readonly Dictionary<int, CultureInfo> s_DictCacheByLcid;
|
|
private static readonly SafeCriticalSection s_LockCacheByLcid;
|
|
private static readonly Dictionary<int, NumberFormatInfo> s_DictNumberFormatInfos;
|
|
private static readonly Dictionary<int, DateTimeFormatInfo> s_DictDatetimeFormatInfos;
|
|
private static readonly string s_SqlConnectionString;
|
|
private static readonly bool s_IsDatabasePresent;
|
|
|
|
private static CultureInfo s_CurrentCulture;
|
|
private static CultureInfo s_CurrentUiCulture;
|
|
|
|
private Calendar m_Calendar;
|
|
private Type m_CalendarType;
|
|
private GregorianCalendarTypes? m_GregorianCalendarType;
|
|
private CompareInfo m_CompareInfo;
|
|
private string m_EnglishName;
|
|
private bool m_IsNeutralCulture;
|
|
private int m_Lcid;
|
|
private string m_Name;
|
|
private string m_NativeName;
|
|
private Calendar[] m_OptionalCalendars;
|
|
private Type[] m_OptionalCalendarTypes;
|
|
private GregorianCalendarTypes?[] m_OptionalGregorianCalendarTypes;
|
|
private CultureInfo m_Parent;
|
|
private int m_ParentId;
|
|
private TextInfo m_TextInfo;
|
|
private string m_ThreeLetterIsoLanguageName;
|
|
private string m_ThreeLetterWindowsLanguageName;
|
|
private string m_TwoLetterIsoLanguageName;
|
|
private NumberFormatInfo m_NumberFormat;
|
|
private int m_NumberFormatId;
|
|
private DateTimeFormatInfo m_DatetimeFormat;
|
|
private int m_DatetimeFormatId;
|
|
private bool m_IsResident;
|
|
|
|
#region Properties
|
|
|
|
public new static CultureInfo InvariantCulture { get { return CultureInfo.InvariantCulture; } }
|
|
|
|
public new static CultureInfo CurrentCulture
|
|
{
|
|
get { return s_CurrentCulture ?? CultureInfo.CurrentCulture; }
|
|
set
|
|
{
|
|
if (value == null)
|
|
throw new ArgumentNullException("value");
|
|
|
|
s_CurrentCulture = value;
|
|
}
|
|
}
|
|
|
|
// ReSharper disable InconsistentNaming
|
|
public new static CultureInfo CurrentUICulture
|
|
// ReSharper restore InconsistentNaming
|
|
{
|
|
get { return s_CurrentUiCulture ?? CultureInfo.CurrentUICulture; }
|
|
set
|
|
{
|
|
if (value == null)
|
|
throw new ArgumentNullException("value");
|
|
s_CurrentUiCulture = value;
|
|
}
|
|
}
|
|
|
|
public override Calendar Calendar
|
|
{
|
|
get
|
|
{
|
|
if (m_IsResident || m_CalendarType == null)
|
|
return base.Calendar;
|
|
Calendar calendar;
|
|
if ((calendar = m_Calendar) == null)
|
|
{
|
|
calendar =
|
|
m_Calendar =
|
|
m_CalendarType == typeof(GregorianCalendar) && m_GregorianCalendarType.HasValue
|
|
? ReflectionUtils.CreateInstance<Calendar>(m_CalendarType, new object[]
|
|
{
|
|
m_GregorianCalendarType
|
|
})
|
|
: ReflectionUtils.CreateInstance<Calendar>(m_CalendarType);
|
|
}
|
|
return calendar;
|
|
}
|
|
}
|
|
|
|
public override CompareInfo CompareInfo { get { return m_CompareInfo ?? base.CompareInfo; } }
|
|
|
|
public override DateTimeFormatInfo DateTimeFormat
|
|
{
|
|
get
|
|
{
|
|
if (m_IsResident)
|
|
return base.DateTimeFormat;
|
|
|
|
ThrowIfNeutralCulture(this);
|
|
|
|
if (m_DatetimeFormat == null)
|
|
{
|
|
DateTimeFormatInfo dateTimeFormatInfo = GetDateTimeFormat(m_DatetimeFormatId);
|
|
if (IsReadOnly)
|
|
dateTimeFormatInfo = DateTimeFormatInfo.ReadOnly(dateTimeFormatInfo);
|
|
m_DatetimeFormat = dateTimeFormatInfo;
|
|
}
|
|
return m_DatetimeFormat;
|
|
}
|
|
set
|
|
{
|
|
if (m_IsResident)
|
|
{
|
|
base.DateTimeFormat = value;
|
|
return;
|
|
}
|
|
ThrowIfReadOnly();
|
|
if (value == null)
|
|
throw new ArgumentException("value");
|
|
m_DatetimeFormat = value;
|
|
}
|
|
}
|
|
|
|
public override string EnglishName { get { return m_EnglishName; } }
|
|
|
|
public override bool IsNeutralCulture { get { return m_IsNeutralCulture; } }
|
|
|
|
public override int LCID { get { return m_Lcid; } }
|
|
|
|
public override string Name { get { return m_Name; } }
|
|
|
|
public override string NativeName { get { return m_NativeName; } }
|
|
|
|
public override NumberFormatInfo NumberFormat
|
|
{
|
|
get
|
|
{
|
|
if (m_IsResident)
|
|
return base.NumberFormat;
|
|
|
|
ThrowIfNeutralCulture(this);
|
|
|
|
if (m_NumberFormat == null)
|
|
{
|
|
NumberFormatInfo numberFormatInfo = GetNumberFormat(m_NumberFormatId);
|
|
if (IsReadOnly)
|
|
numberFormatInfo = NumberFormatInfo.ReadOnly(numberFormatInfo);
|
|
m_NumberFormat = numberFormatInfo;
|
|
}
|
|
return m_NumberFormat;
|
|
}
|
|
set
|
|
{
|
|
if (m_IsResident)
|
|
{
|
|
base.NumberFormat = value;
|
|
return;
|
|
}
|
|
ThrowIfReadOnly();
|
|
if (value == null)
|
|
throw new ArgumentException("value");
|
|
m_NumberFormat = value;
|
|
}
|
|
}
|
|
|
|
public override Calendar[] OptionalCalendars
|
|
{
|
|
get
|
|
{
|
|
Calendar[] calendars;
|
|
if ((calendars = m_OptionalCalendars) == null)
|
|
{
|
|
calendars =
|
|
(m_OptionalCalendars =
|
|
m_OptionalCalendarTypes.Select((t, ix) =>
|
|
new KeyValuePair
|
|
<Type, GregorianCalendarTypes?>(t,
|
|
m_OptionalGregorianCalendarTypes
|
|
[ix])).Where(kvp => kvp.Key != null).Select(delegate(KeyValuePair<Type, GregorianCalendarTypes?> kvp)
|
|
{
|
|
if (kvp.Key != typeof(GregorianCalendar) || !kvp.Value.HasValue)
|
|
return ReflectionUtils.CreateInstance<Calendar>(kvp.Key);
|
|
return ReflectionUtils.CreateInstance<Calendar>(kvp.Key, new object[]
|
|
{
|
|
kvp.Value
|
|
});
|
|
}).ToArray());
|
|
}
|
|
return calendars;
|
|
}
|
|
}
|
|
|
|
public override CultureInfo Parent
|
|
{
|
|
get
|
|
{
|
|
CultureInfo cultureInfo;
|
|
if ((cultureInfo = m_Parent) == null)
|
|
cultureInfo = m_Parent = new IcdCultureInfo(m_ParentId, 0);
|
|
return cultureInfo;
|
|
}
|
|
}
|
|
|
|
public override TextInfo TextInfo { get { return m_TextInfo ?? base.TextInfo; } }
|
|
|
|
public override string ThreeLetterISOLanguageName { get { return m_ThreeLetterIsoLanguageName; } }
|
|
|
|
public override string ThreeLetterWindowsLanguageName { get { return m_ThreeLetterWindowsLanguageName; } }
|
|
|
|
public override string TwoLetterISOLanguageName { get { return m_TwoLetterIsoLanguageName; } }
|
|
|
|
#endregion
|
|
|
|
#region Constructors
|
|
|
|
static IcdCultureInfo()
|
|
{
|
|
s_DictAvailableCulturesByName = new Dictionary<string, CultureTypes>(StringComparer.InvariantCultureIgnoreCase);
|
|
s_DictAvailableCulturesByLcid = new Dictionary<int, CultureTypes>();
|
|
s_DictSpecificCulture = new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase);
|
|
s_DictCacheByName = new Dictionary<string, CultureInfo>(StringComparer.InvariantCultureIgnoreCase);
|
|
s_LockCacheByName = new SafeCriticalSection();
|
|
s_DictCacheByLcid = new Dictionary<int, CultureInfo>();
|
|
s_LockCacheByLcid = new SafeCriticalSection();
|
|
s_DictNumberFormatInfos = new Dictionary<int, NumberFormatInfo>();
|
|
s_DictDatetimeFormatInfos = new Dictionary<int, DateTimeFormatInfo>();
|
|
|
|
string[] builtinCultures =
|
|
#if SIMPLSHARP
|
|
{
|
|
"",
|
|
"af",
|
|
"ar",
|
|
"az",
|
|
"be",
|
|
"bg",
|
|
"ca",
|
|
"cs",
|
|
"da",
|
|
"de",
|
|
"dv",
|
|
"el",
|
|
"en",
|
|
"en-US",
|
|
"es",
|
|
"et",
|
|
"eu",
|
|
"fa",
|
|
"fi",
|
|
"fo",
|
|
"fr",
|
|
"gl",
|
|
"gu",
|
|
"he",
|
|
"hi",
|
|
"hr",
|
|
"hu",
|
|
"hy",
|
|
"id",
|
|
"is",
|
|
"it",
|
|
"ja",
|
|
"ka",
|
|
"kk",
|
|
"kn",
|
|
"ko",
|
|
"kok",
|
|
"ky",
|
|
"lt",
|
|
"lv",
|
|
"mk",
|
|
"mn",
|
|
"mr",
|
|
"ms",
|
|
"nl",
|
|
"no",
|
|
"pa",
|
|
"pl",
|
|
"pt",
|
|
"ro",
|
|
"ru",
|
|
"sa",
|
|
"sk",
|
|
"sl",
|
|
"sq",
|
|
"sr",
|
|
"sv",
|
|
"sw",
|
|
"syr",
|
|
"ta",
|
|
"te",
|
|
"th",
|
|
"tr",
|
|
"tt",
|
|
"uk",
|
|
"ur",
|
|
"uz",
|
|
"vi",
|
|
"zh-Hans",
|
|
"zh-Hant",
|
|
"zh-CHS",
|
|
"zh-CHT"
|
|
};
|
|
#else
|
|
CultureInfo.GetCultures(CultureTypes.AllCultures)
|
|
.Select(c => c.Name)
|
|
.ToArray();
|
|
#endif
|
|
|
|
string databasePath = IcdPath.Combine(PathUtils.ProgramPath, SQL_LOCAL_DATABASE_FILE);
|
|
if (!IcdFile.Exists(databasePath))
|
|
{
|
|
s_IsDatabasePresent = false;
|
|
return;
|
|
}
|
|
|
|
s_SqlConnectionString = string.Format(SQL_CONNECTION_STRING_FORMAT, databasePath);
|
|
using (IcdSqliteConnection sQLiteConnection = new IcdSqliteConnection(s_SqlConnectionString))
|
|
{
|
|
try
|
|
{
|
|
sQLiteConnection.Open();
|
|
}
|
|
catch (Exception)
|
|
{
|
|
s_IsDatabasePresent = false;
|
|
return;
|
|
}
|
|
s_IsDatabasePresent = true;
|
|
IcdSqliteCommand sQLiteCommand = new IcdSqliteCommand("select count(*) from cultureinfo", sQLiteConnection);
|
|
int num = Convert.ToInt32(sQLiteCommand.ExecuteScalar());
|
|
s_AvailableCultureNames = new string[num + 1];
|
|
IcdSqliteCommand sQLiteCommand2 = new IcdSqliteCommand("select id, name, lcid, isneutralculture from cultureinfo",
|
|
sQLiteConnection);
|
|
using (IcdSqliteDataReader sQLiteDataReader = sQLiteCommand2.ExecuteReader())
|
|
{
|
|
while (sQLiteDataReader.Read())
|
|
{
|
|
int @int = sQLiteDataReader.GetInt32(0);
|
|
bool boolean = sQLiteDataReader.GetBoolean(3);
|
|
string @string = sQLiteDataReader.GetString(1);
|
|
s_DictAvailableCulturesByName[@string] = boolean ? CultureTypes.NeutralCultures : CultureTypes.SpecificCultures;
|
|
int int2 = sQLiteDataReader.GetInt32(2);
|
|
s_DictAvailableCulturesByLcid[int2] = boolean ? CultureTypes.NeutralCultures : CultureTypes.SpecificCultures;
|
|
s_AvailableCultureNames[@int] = @string;
|
|
}
|
|
}
|
|
|
|
sQLiteCommand2 = new IcdSqliteCommand("select id, specificculture from specificcultureinfo", sQLiteConnection);
|
|
using (IcdSqliteDataReader sQLiteDataReader2 = sQLiteCommand2.ExecuteReader())
|
|
{
|
|
while (sQLiteDataReader2.Read())
|
|
{
|
|
int int3 = sQLiteDataReader2.GetInt32(0);
|
|
string string2 = sQLiteDataReader2.GetString(1);
|
|
s_DictSpecificCulture[s_AvailableCultureNames[int3]] = string2;
|
|
}
|
|
}
|
|
}
|
|
|
|
string[] array = builtinCultures;
|
|
for (int i = 0; i < array.Length; i++)
|
|
{
|
|
string name = array[i];
|
|
try
|
|
{
|
|
CultureInfo cultureInfo = CultureInfo.GetCultureInfo(name);
|
|
|
|
Dictionary<string, CultureTypes> dictAvailableCulturesByName;
|
|
string name2;
|
|
(dictAvailableCulturesByName = s_DictAvailableCulturesByName)[name2 = cultureInfo.Name] =
|
|
dictAvailableCulturesByName[name2] | CultureTypes.InstalledWin32Cultures;
|
|
|
|
Dictionary<int, CultureTypes> dictAvailableCulturesByLcid;
|
|
int lCid;
|
|
(dictAvailableCulturesByLcid = s_DictAvailableCulturesByLcid)[lCid = cultureInfo.LCID] =
|
|
dictAvailableCulturesByLcid[lCid] | CultureTypes.InstalledWin32Cultures;
|
|
}
|
|
catch (Exception)
|
|
{
|
|
}
|
|
}
|
|
}
|
|
|
|
public IcdCultureInfo(int culture)
|
|
: this(culture, true)
|
|
{
|
|
}
|
|
|
|
public IcdCultureInfo(int culture, bool useUserOverride)
|
|
: base(GetResidentNeutralLcid(culture), useUserOverride)
|
|
{
|
|
if (culture < 0)
|
|
throw new ArgumentOutOfRangeException("culture", "must be >= 0");
|
|
|
|
CultureTypes cultureTypes;
|
|
if (!s_DictAvailableCulturesByLcid.TryGetValue(culture, out cultureTypes))
|
|
throw new ArgumentException("not supported");
|
|
|
|
if (!s_IsDatabasePresent || (cultureTypes & CultureTypes.InstalledWin32Cultures) != 0)
|
|
{
|
|
BuildCultureInfoEx(CultureInfo.GetCultureInfo(culture));
|
|
return;
|
|
}
|
|
|
|
CultureInfo ci;
|
|
bool flag;
|
|
s_LockCacheByLcid.Enter();
|
|
{
|
|
flag = s_DictCacheByLcid.TryGetValue(culture, out ci);
|
|
}
|
|
s_LockCacheByLcid.Leave();
|
|
|
|
if (flag)
|
|
{
|
|
BuildCultureInfoEx(ci);
|
|
return;
|
|
}
|
|
|
|
using (IcdSqliteConnection sQLiteConnection = new IcdSqliteConnection(s_SqlConnectionString))
|
|
{
|
|
sQLiteConnection.Open();
|
|
IcdSqliteCommand sQLiteCommand = new IcdSqliteCommand(SQL_CMD_SELECT_BY_LCID, sQLiteConnection);
|
|
sQLiteCommand.Parameters.AddWithValue("@lcid", culture);
|
|
using (IcdSqliteDataReader sQLiteDataReader = sQLiteCommand.ExecuteReader())
|
|
ProcessReader(sQLiteDataReader, sQLiteConnection);
|
|
}
|
|
}
|
|
|
|
public IcdCultureInfo(string name)
|
|
: this(name, true)
|
|
{
|
|
}
|
|
|
|
public IcdCultureInfo(string name, bool useUserOverrides)
|
|
: base(GetResidentNeutralName(name), useUserOverrides)
|
|
{
|
|
if (name == null)
|
|
throw new ArgumentNullException("name");
|
|
|
|
CultureTypes cultureTypes;
|
|
if (!s_DictAvailableCulturesByName.TryGetValue(name, out cultureTypes))
|
|
throw new ArgumentException("not supported");
|
|
|
|
if (!s_IsDatabasePresent || (cultureTypes & CultureTypes.InstalledWin32Cultures) != 0)
|
|
{
|
|
BuildCultureInfoEx(CultureInfo.GetCultureInfo(name));
|
|
return;
|
|
}
|
|
|
|
CultureInfo ci;
|
|
bool flag;
|
|
s_LockCacheByName.Enter();
|
|
{
|
|
flag = s_DictCacheByName.TryGetValue(name, out ci);
|
|
}
|
|
s_LockCacheByName.Leave();
|
|
if (flag)
|
|
{
|
|
BuildCultureInfoEx(ci);
|
|
return;
|
|
}
|
|
using (IcdSqliteConnection sQLiteConnection = new IcdSqliteConnection(s_SqlConnectionString))
|
|
{
|
|
sQLiteConnection.Open();
|
|
IcdSqliteCommand sQLiteCommand = new IcdSqliteCommand(SQL_CMD_SELECT_BY_NAME, sQLiteConnection);
|
|
sQLiteCommand.Parameters.AddWithValue("@name", name);
|
|
using (IcdSqliteDataReader sQLiteDataReader = sQLiteCommand.ExecuteReader())
|
|
ProcessReader(sQLiteDataReader, sQLiteConnection);
|
|
}
|
|
}
|
|
|
|
private IcdCultureInfo(int id, int clone)
|
|
: base(GetResidentNeutralName(s_AvailableCultureNames[id]))
|
|
{
|
|
if (!s_IsDatabasePresent)
|
|
throw new PlatformNotSupportedException("No database");
|
|
if (IsResident(s_AvailableCultureNames[id]))
|
|
{
|
|
BuildCultureInfoEx(CultureInfo.GetCultureInfo(s_AvailableCultureNames[id]));
|
|
return;
|
|
}
|
|
using (IcdSqliteConnection sQLiteConnection = new IcdSqliteConnection(s_SqlConnectionString))
|
|
{
|
|
sQLiteConnection.Open();
|
|
IcdSqliteCommand sQLiteCommand = new IcdSqliteCommand(SQL_CMD_SELECT_BY_ID, sQLiteConnection);
|
|
sQLiteCommand.Parameters.AddWithValue("@id", id);
|
|
using (IcdSqliteDataReader sQLiteDataReader = sQLiteCommand.ExecuteReader())
|
|
ProcessReader(sQLiteDataReader, sQLiteConnection);
|
|
}
|
|
}
|
|
|
|
private IcdCultureInfo(CultureInfo ci)
|
|
: base(GetResidentNeutralName(ci.Name))
|
|
{
|
|
BuildCultureInfoEx(ci);
|
|
}
|
|
|
|
public static IcdCultureInfo FromCultureInfo(CultureInfo ci)
|
|
{
|
|
return new IcdCultureInfo(ci);
|
|
}
|
|
|
|
#endregion
|
|
|
|
private void ProcessReader(IcdSqliteDataReader rdr, IcdSqliteConnection conn)
|
|
{
|
|
if (!rdr.Read())
|
|
throw new InvalidOperationException("failure reading database");
|
|
|
|
int ordinal = rdr.GetOrdinal("calendar");
|
|
string text = rdr.GetString(ordinal);
|
|
if (text.EndsWith(")"))
|
|
{
|
|
int num = text.IndexOf('(');
|
|
string value = text.Substring(num + 1, text.Length - num - 2);
|
|
text = text.Substring(0, num);
|
|
m_GregorianCalendarType = (GregorianCalendarTypes)Enum.Parse(typeof(GregorianCalendarTypes), value, true);
|
|
}
|
|
|
|
m_CalendarType = Type.GetType("System.Globalization." + text);
|
|
ordinal = rdr.GetOrdinal("englishname");
|
|
m_EnglishName = rdr.GetString(ordinal);
|
|
ordinal = rdr.GetOrdinal("isneutralculture");
|
|
m_IsNeutralCulture = rdr.GetBoolean(ordinal);
|
|
ordinal = rdr.GetOrdinal("lcid");
|
|
m_Lcid = rdr.GetInt32(ordinal);
|
|
ordinal = rdr.GetOrdinal("name");
|
|
m_Name = rdr.GetString(ordinal);
|
|
ordinal = rdr.GetOrdinal("nativename");
|
|
m_NativeName = rdr.GetString(ordinal);
|
|
ordinal = rdr.GetOrdinal("optionalcalendars");
|
|
string[] array = rdr.GetString(ordinal).Split('|');
|
|
m_OptionalGregorianCalendarTypes = new GregorianCalendarTypes?[array.Length];
|
|
m_OptionalCalendarTypes = new Type[array.Length];
|
|
for (int i = 0; i < array.Length; i++)
|
|
{
|
|
string text2 = array[i];
|
|
if (text2.EndsWith(")"))
|
|
{
|
|
int num2 = text2.IndexOf('(');
|
|
string value2 = text2.Substring(num2 + 1, text2.Length - num2 - 2);
|
|
text2 = text2.Substring(0, num2);
|
|
m_OptionalGregorianCalendarTypes[i] =
|
|
(GregorianCalendarTypes)Enum.Parse(typeof(GregorianCalendarTypes), value2, true);
|
|
}
|
|
m_OptionalCalendarTypes[i] = Type.GetType("System.Globalization." + text2);
|
|
}
|
|
ordinal = rdr.GetOrdinal("parent");
|
|
m_ParentId = rdr.GetInt32(ordinal);
|
|
ordinal = rdr.GetOrdinal("threeletterisolanguagename");
|
|
m_ThreeLetterIsoLanguageName = rdr.GetString(ordinal);
|
|
ordinal = rdr.GetOrdinal("threeletterwindowslanguagename");
|
|
m_ThreeLetterWindowsLanguageName = rdr.GetString(ordinal);
|
|
ordinal = rdr.GetOrdinal("twoletterisolanguagename");
|
|
m_TwoLetterIsoLanguageName = rdr.GetString(ordinal);
|
|
ordinal = rdr.GetOrdinal("datetimeformat");
|
|
m_DatetimeFormatId = rdr.GetInt32(ordinal);
|
|
ordinal = rdr.GetOrdinal("numberformat");
|
|
m_NumberFormatId = rdr.GetInt32(ordinal);
|
|
rdr.Close();
|
|
}
|
|
|
|
private static NumberFormatInfo GetNumberFormat(int id)
|
|
{
|
|
NumberFormatInfo numberFormat;
|
|
using (IcdSqliteConnection sQLiteConnection = new IcdSqliteConnection(s_SqlConnectionString))
|
|
{
|
|
sQLiteConnection.Open();
|
|
numberFormat = GetNumberFormat(id, sQLiteConnection);
|
|
}
|
|
return numberFormat;
|
|
}
|
|
|
|
private static NumberFormatInfo GetNumberFormat(int id, IcdSqliteConnection conn)
|
|
{
|
|
NumberFormatInfo numberFormatInfo;
|
|
if (s_DictNumberFormatInfos.TryGetValue(id, out numberFormatInfo))
|
|
return (NumberFormatInfo)numberFormatInfo.Clone();
|
|
|
|
IcdSqliteCommand sQLiteCommand = new IcdSqliteCommand(SQL_CMD_SELECT_NUMBER_FORMAT_BY_ID, conn);
|
|
sQLiteCommand.Parameters.AddWithValue("@id", id);
|
|
|
|
using (IcdSqliteDataReader sQLiteDataReader = sQLiteCommand.ExecuteReader())
|
|
{
|
|
if (!sQLiteDataReader.Read())
|
|
throw new InvalidOperationException("invalid number format database");
|
|
|
|
int ordinal = sQLiteDataReader.GetOrdinal("CurrencyDecimalDigits");
|
|
int ordinal2 = sQLiteDataReader.GetOrdinal("CurrencyDecimalSeparator");
|
|
int ordinal3 = sQLiteDataReader.GetOrdinal("CurrencyGroupSizes");
|
|
int ordinal4 = sQLiteDataReader.GetOrdinal("NumberGroupSizes");
|
|
int ordinal5 = sQLiteDataReader.GetOrdinal("PercentGroupSizes");
|
|
int ordinal6 = sQLiteDataReader.GetOrdinal("CurrencyGroupSeparator");
|
|
int ordinal7 = sQLiteDataReader.GetOrdinal("CurrencySymbol");
|
|
int ordinal8 = sQLiteDataReader.GetOrdinal("NaNSymbol");
|
|
int ordinal9 = sQLiteDataReader.GetOrdinal("CurrencyNegativePattern");
|
|
int ordinal10 = sQLiteDataReader.GetOrdinal("NumberNegativePattern");
|
|
int ordinal11 = sQLiteDataReader.GetOrdinal("PercentPositivePattern");
|
|
int ordinal12 = sQLiteDataReader.GetOrdinal("PercentNegativePattern");
|
|
int ordinal13 = sQLiteDataReader.GetOrdinal("NegativeInfinitySymbol");
|
|
int ordinal14 = sQLiteDataReader.GetOrdinal("NegativeSign");
|
|
int ordinal15 = sQLiteDataReader.GetOrdinal("NumberDecimalDigits");
|
|
int ordinal16 = sQLiteDataReader.GetOrdinal("NumberDecimalSeparator");
|
|
int ordinal17 = sQLiteDataReader.GetOrdinal("NumberGroupSeparator");
|
|
int ordinal18 = sQLiteDataReader.GetOrdinal("CurrencyPositivePattern");
|
|
int ordinal19 = sQLiteDataReader.GetOrdinal("PositiveInfinitySymbol");
|
|
int ordinal20 = sQLiteDataReader.GetOrdinal("PositiveSign");
|
|
int ordinal21 = sQLiteDataReader.GetOrdinal("PercentDecimalDigits");
|
|
int ordinal22 = sQLiteDataReader.GetOrdinal("PercentDecimalSeparator");
|
|
int ordinal23 = sQLiteDataReader.GetOrdinal("PercentGroupSeparator");
|
|
int ordinal24 = sQLiteDataReader.GetOrdinal("PercentSymbol");
|
|
int ordinal25 = sQLiteDataReader.GetOrdinal("PerMilleSymbol");
|
|
|
|
NumberFormatInfo numberFormatInfo2 = new NumberFormatInfo
|
|
{
|
|
CurrencyDecimalDigits = sQLiteDataReader.GetInt32(ordinal),
|
|
CurrencyDecimalSeparator = sQLiteDataReader.GetString(ordinal2),
|
|
CurrencyGroupSizes = sQLiteDataReader.GetString(ordinal3)
|
|
.Split(',')
|
|
.Select(s => int.Parse(s))
|
|
.ToArray(),
|
|
NumberGroupSizes = sQLiteDataReader.GetString(ordinal4)
|
|
.Split(',')
|
|
.Select(s => int.Parse(s))
|
|
.ToArray(),
|
|
PercentGroupSizes = sQLiteDataReader.GetString(ordinal5)
|
|
.Split(',')
|
|
.Select(s => int.Parse(s))
|
|
.ToArray(),
|
|
CurrencyGroupSeparator = sQLiteDataReader.GetString(ordinal6),
|
|
CurrencySymbol = sQLiteDataReader.GetString(ordinal7),
|
|
NaNSymbol = sQLiteDataReader.GetString(ordinal8),
|
|
CurrencyNegativePattern = sQLiteDataReader.GetInt32(ordinal9),
|
|
NumberNegativePattern = sQLiteDataReader.GetInt32(ordinal10),
|
|
PercentPositivePattern = sQLiteDataReader.GetInt32(ordinal11),
|
|
PercentNegativePattern = sQLiteDataReader.GetInt32(ordinal12),
|
|
NegativeInfinitySymbol = sQLiteDataReader.GetString(ordinal13),
|
|
NegativeSign = sQLiteDataReader.GetString(ordinal14),
|
|
NumberDecimalDigits = sQLiteDataReader.GetInt32(ordinal15),
|
|
NumberDecimalSeparator = sQLiteDataReader.GetString(ordinal16),
|
|
NumberGroupSeparator = sQLiteDataReader.GetString(ordinal17),
|
|
CurrencyPositivePattern = sQLiteDataReader.GetInt32(ordinal18),
|
|
PositiveInfinitySymbol = sQLiteDataReader.GetString(ordinal19),
|
|
PositiveSign = sQLiteDataReader.GetString(ordinal20),
|
|
PercentDecimalDigits = sQLiteDataReader.GetInt32(ordinal21),
|
|
PercentDecimalSeparator = sQLiteDataReader.GetString(ordinal22),
|
|
PercentGroupSeparator = sQLiteDataReader.GetString(ordinal23),
|
|
PercentSymbol = sQLiteDataReader.GetString(ordinal24),
|
|
PerMilleSymbol = sQLiteDataReader.GetString(ordinal25)
|
|
};
|
|
numberFormatInfo = numberFormatInfo2;
|
|
}
|
|
s_DictNumberFormatInfos[id] = numberFormatInfo;
|
|
return (NumberFormatInfo)numberFormatInfo.Clone();
|
|
}
|
|
|
|
private static DateTimeFormatInfo GetDateTimeFormat(int id)
|
|
{
|
|
DateTimeFormatInfo dateTimeFormat;
|
|
using (IcdSqliteConnection sQLiteConnection = new IcdSqliteConnection(s_SqlConnectionString))
|
|
{
|
|
sQLiteConnection.Open();
|
|
dateTimeFormat = GetDateTimeFormat(id, sQLiteConnection);
|
|
}
|
|
return dateTimeFormat;
|
|
}
|
|
|
|
private static DateTimeFormatInfo GetDateTimeFormat(int id, IcdSqliteConnection conn)
|
|
{
|
|
DateTimeFormatInfo dateTimeFormatInfo;
|
|
if (s_DictDatetimeFormatInfos.TryGetValue(id, out dateTimeFormatInfo))
|
|
return (DateTimeFormatInfo)dateTimeFormatInfo.Clone();
|
|
IcdSqliteCommand sQLiteCommand = new IcdSqliteCommand(SQL_CMD_SELECT_DATE_TIME_FORMAT_BY_ID, conn);
|
|
sQLiteCommand.Parameters.AddWithValue("@id", id);
|
|
using (IcdSqliteDataReader sQLiteDataReader = sQLiteCommand.ExecuteReader())
|
|
{
|
|
if (!sQLiteDataReader.Read())
|
|
throw new InvalidOperationException("invalid datetime format database");
|
|
int ordinal = sQLiteDataReader.GetOrdinal("AMDesignator");
|
|
sQLiteDataReader.GetOrdinal("Calendar");
|
|
int ordinal2 = sQLiteDataReader.GetOrdinal("DateSeparator");
|
|
int ordinal3 = sQLiteDataReader.GetOrdinal("FirstDayOfWeek");
|
|
int ordinal4 = sQLiteDataReader.GetOrdinal("CalendarWeekRule");
|
|
int ordinal5 = sQLiteDataReader.GetOrdinal("FullDateTimePattern");
|
|
int ordinal6 = sQLiteDataReader.GetOrdinal("LongDatePattern");
|
|
int ordinal7 = sQLiteDataReader.GetOrdinal("LongTimePattern");
|
|
int ordinal8 = sQLiteDataReader.GetOrdinal("MonthDayPattern");
|
|
int ordinal9 = sQLiteDataReader.GetOrdinal("PMDesignator");
|
|
int ordinal10 = sQLiteDataReader.GetOrdinal("ShortDatePattern");
|
|
int ordinal11 = sQLiteDataReader.GetOrdinal("ShortTimePattern");
|
|
int ordinal12 = sQLiteDataReader.GetOrdinal("TimeSeparator");
|
|
int ordinal13 = sQLiteDataReader.GetOrdinal("YearMonthPattern");
|
|
int ordinal14 = sQLiteDataReader.GetOrdinal("AbbreviatedDayNames");
|
|
int ordinal15 = sQLiteDataReader.GetOrdinal("ShortestDayNames");
|
|
int ordinal16 = sQLiteDataReader.GetOrdinal("DayNames");
|
|
int ordinal17 = sQLiteDataReader.GetOrdinal("AbbreviatedMonthNames");
|
|
int ordinal18 = sQLiteDataReader.GetOrdinal("MonthNames");
|
|
int ordinal19 = sQLiteDataReader.GetOrdinal("AbbreviatedMonthGenitiveNames");
|
|
int ordinal20 = sQLiteDataReader.GetOrdinal("MonthGenitiveNames");
|
|
dateTimeFormatInfo = new DateTimeFormatInfo
|
|
{
|
|
AMDesignator = sQLiteDataReader.GetString(ordinal),
|
|
DateSeparator = sQLiteDataReader.GetString(ordinal2),
|
|
FirstDayOfWeek = (DayOfWeek)Enum.Parse(typeof(DayOfWeek), sQLiteDataReader.GetString(ordinal3), true),
|
|
CalendarWeekRule =
|
|
(CalendarWeekRule)Enum.Parse(typeof(CalendarWeekRule), sQLiteDataReader.GetString(ordinal4), true),
|
|
FullDateTimePattern = sQLiteDataReader.GetString(ordinal5),
|
|
LongDatePattern = sQLiteDataReader.GetString(ordinal6),
|
|
LongTimePattern = sQLiteDataReader.GetString(ordinal7),
|
|
MonthDayPattern = sQLiteDataReader.GetString(ordinal8),
|
|
PMDesignator = sQLiteDataReader.GetString(ordinal9),
|
|
ShortDatePattern = sQLiteDataReader.GetString(ordinal10),
|
|
ShortTimePattern = sQLiteDataReader.GetString(ordinal11),
|
|
TimeSeparator = sQLiteDataReader.GetString(ordinal12),
|
|
YearMonthPattern = sQLiteDataReader.GetString(ordinal13),
|
|
AbbreviatedDayNames = sQLiteDataReader.GetString(ordinal14).Split('|'),
|
|
ShortestDayNames = sQLiteDataReader.GetString(ordinal15).Split('|'),
|
|
DayNames = sQLiteDataReader.GetString(ordinal16).Split('|'),
|
|
AbbreviatedMonthNames = sQLiteDataReader.GetString(ordinal17).Split('|'),
|
|
MonthNames = sQLiteDataReader.GetString(ordinal18).Split('|'),
|
|
AbbreviatedMonthGenitiveNames = sQLiteDataReader.GetString(ordinal19).Split('|'),
|
|
MonthGenitiveNames = sQLiteDataReader.GetString(ordinal20).Split('|')
|
|
};
|
|
}
|
|
s_DictDatetimeFormatInfos[id] = dateTimeFormatInfo;
|
|
return (DateTimeFormatInfo)dateTimeFormatInfo.Clone();
|
|
}
|
|
|
|
private void BuildCultureInfoEx(CultureInfo ci)
|
|
{
|
|
IcdCultureInfo icdCultureInfo = ci as IcdCultureInfo;
|
|
if (icdCultureInfo == null)
|
|
{
|
|
m_IsResident = true;
|
|
m_Calendar = ci.Calendar;
|
|
m_OptionalCalendars = ci.OptionalCalendars;
|
|
m_Parent = ci.Parent;
|
|
m_TextInfo = ci.TextInfo;
|
|
try
|
|
{
|
|
m_CompareInfo = ci.CompareInfo;
|
|
goto IL_CE;
|
|
}
|
|
catch (PlatformNotSupportedException)
|
|
{
|
|
m_CompareInfo = CultureInfo.InvariantCulture.CompareInfo;
|
|
goto IL_CE;
|
|
}
|
|
}
|
|
m_Calendar = icdCultureInfo.m_Calendar;
|
|
m_CalendarType = icdCultureInfo.m_CalendarType;
|
|
m_GregorianCalendarType = icdCultureInfo.m_GregorianCalendarType;
|
|
m_OptionalCalendars = icdCultureInfo.m_OptionalCalendars;
|
|
m_OptionalCalendarTypes = icdCultureInfo.m_OptionalCalendarTypes;
|
|
m_OptionalGregorianCalendarTypes = icdCultureInfo.m_OptionalGregorianCalendarTypes;
|
|
m_Parent = icdCultureInfo.m_Parent;
|
|
m_TextInfo = icdCultureInfo.m_TextInfo;
|
|
m_CompareInfo = icdCultureInfo.m_CompareInfo;
|
|
IL_CE:
|
|
m_EnglishName = ci.EnglishName;
|
|
m_IsNeutralCulture = ci.IsNeutralCulture;
|
|
m_Lcid = ci.LCID;
|
|
m_Name = ci.Name;
|
|
m_NativeName = ci.NativeName;
|
|
m_ThreeLetterIsoLanguageName = ci.ThreeLetterISOLanguageName;
|
|
m_ThreeLetterWindowsLanguageName = ci.ThreeLetterWindowsLanguageName;
|
|
m_TwoLetterIsoLanguageName = ci.TwoLetterISOLanguageName;
|
|
if (!m_IsNeutralCulture)
|
|
{
|
|
if (icdCultureInfo == null)
|
|
{
|
|
m_DatetimeFormat = ci.DateTimeFormat;
|
|
m_NumberFormat = ci.NumberFormat;
|
|
return;
|
|
}
|
|
m_DatetimeFormatId = icdCultureInfo.m_DatetimeFormatId;
|
|
m_DatetimeFormat = icdCultureInfo.m_DatetimeFormat;
|
|
m_NumberFormatId = icdCultureInfo.m_NumberFormatId;
|
|
m_NumberFormat = icdCultureInfo.m_NumberFormat;
|
|
}
|
|
}
|
|
|
|
#region Methods
|
|
|
|
public new static CultureInfo GetCultureInfo(string name)
|
|
{
|
|
CultureInfo cultureInfo;
|
|
s_LockCacheByName.Enter();
|
|
{
|
|
if (s_DictCacheByName.TryGetValue(name, out cultureInfo))
|
|
return cultureInfo;
|
|
}
|
|
s_LockCacheByName.Leave();
|
|
cultureInfo = new IcdCultureInfo(name);
|
|
if (!cultureInfo.IsNeutralCulture)
|
|
cultureInfo = ReadOnly(cultureInfo);
|
|
s_LockCacheByName.Enter();
|
|
{
|
|
s_DictCacheByName[cultureInfo.Name] = cultureInfo;
|
|
s_DictCacheByLcid[cultureInfo.LCID] = cultureInfo;
|
|
}
|
|
s_LockCacheByName.Leave();
|
|
return cultureInfo;
|
|
}
|
|
|
|
public new static CultureInfo GetCultureInfo(int culture)
|
|
{
|
|
CultureInfo cultureInfo;
|
|
s_LockCacheByLcid.Enter();
|
|
{
|
|
if (s_DictCacheByLcid.TryGetValue(culture, out cultureInfo))
|
|
return cultureInfo;
|
|
}
|
|
s_LockCacheByLcid.Leave();
|
|
cultureInfo = new IcdCultureInfo(culture);
|
|
if (!cultureInfo.IsNeutralCulture)
|
|
cultureInfo = ReadOnly(cultureInfo);
|
|
s_LockCacheByLcid.Enter();
|
|
{
|
|
s_DictCacheByName[cultureInfo.Name] = cultureInfo;
|
|
s_DictCacheByLcid[cultureInfo.LCID] = cultureInfo;
|
|
}
|
|
s_LockCacheByLcid.Leave();
|
|
return cultureInfo;
|
|
}
|
|
|
|
public new static CultureInfo[] GetCultures(CultureTypes types)
|
|
{
|
|
return s_DictAvailableCulturesByName.Where(de => (de.Value & types) != 0)
|
|
.Select(de => new IcdCultureInfo(de.Key))
|
|
.Cast<CultureInfo>()
|
|
.ToArray();
|
|
}
|
|
|
|
public new static CultureInfo CreateSpecificCulture(string name)
|
|
{
|
|
IcdCultureInfo icdCultureInfo = new IcdCultureInfo(name);
|
|
if (!icdCultureInfo.IsNeutralCulture)
|
|
return icdCultureInfo;
|
|
if ((icdCultureInfo.LCID & 1023) == 4)
|
|
throw new ArgumentException();
|
|
return new IcdCultureInfo(s_DictSpecificCulture[name]);
|
|
}
|
|
|
|
public override object Clone()
|
|
{
|
|
return new IcdCultureInfo(this);
|
|
}
|
|
|
|
public override bool Equals(object value)
|
|
{
|
|
CultureInfo cultureInfo = value as CultureInfo;
|
|
return cultureInfo != null && Name.Equals(cultureInfo.Name) && CompareInfo.Equals(cultureInfo.CompareInfo);
|
|
}
|
|
|
|
public override int GetHashCode()
|
|
{
|
|
return Name.GetHashCode() + CompareInfo.GetHashCode();
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
return m_Name;
|
|
}
|
|
|
|
public new void ClearCachedData()
|
|
{
|
|
s_LockCacheByName.Enter();
|
|
s_LockCacheByLcid.Enter();
|
|
{
|
|
s_DictCacheByName.Clear();
|
|
s_DictCacheByLcid.Clear();
|
|
}
|
|
s_LockCacheByLcid.Enter();
|
|
s_LockCacheByName.Enter();
|
|
|
|
base.ClearCachedData();
|
|
}
|
|
|
|
#endregion
|
|
|
|
private void ThrowIfReadOnly()
|
|
{
|
|
if (IsReadOnly)
|
|
throw new InvalidOperationException();
|
|
}
|
|
|
|
private static void ThrowIfNeutralCulture(CultureInfo culture)
|
|
{
|
|
if (culture.IsNeutralCulture)
|
|
throw new NotSupportedException("A neutral culture does not provide enough information to display the correct numeric format");
|
|
}
|
|
|
|
private static bool IsResident(string name)
|
|
{
|
|
CultureTypes cultureTypes;
|
|
return s_DictAvailableCulturesByName.TryGetValue(name, out cultureTypes) &&
|
|
(cultureTypes & CultureTypes.InstalledWin32Cultures) != 0;
|
|
}
|
|
|
|
private static bool IsResidentAndNeutral(string name)
|
|
{
|
|
CultureTypes cultureTypes;
|
|
return s_DictAvailableCulturesByName.TryGetValue(name, out cultureTypes) &&
|
|
(cultureTypes & (CultureTypes.InstalledWin32Cultures | CultureTypes.NeutralCultures)) ==
|
|
(CultureTypes.InstalledWin32Cultures | CultureTypes.NeutralCultures);
|
|
}
|
|
|
|
private static string GetResidentNeutralName(string name)
|
|
{
|
|
if (IsResident(name))
|
|
return name;
|
|
if (name.Length <= 2 || !IsResidentAndNeutral(name.Substring(0, 2)))
|
|
return string.Empty;
|
|
return name.Substring(0, 2);
|
|
}
|
|
|
|
private static bool IsResident(int culture)
|
|
{
|
|
CultureTypes cultureTypes;
|
|
return s_DictAvailableCulturesByLcid.TryGetValue(culture, out cultureTypes) &&
|
|
(cultureTypes & CultureTypes.InstalledWin32Cultures) != 0;
|
|
}
|
|
|
|
private static int GetResidentNeutralLcid(int culture)
|
|
{
|
|
return IsResident(culture) ? culture : 127;
|
|
}
|
|
}
|
|
}
|