using System.Threading;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
+using System.Diagnostics.Contracts;
namespace System.Globalization
{
bool m_useUserOverride;
[NonSerialized]
volatile NumberFormatInfo numInfo;
- volatile DateTimeFormatInfo dateTimeInfo;
+ internal volatile DateTimeFormatInfo dateTimeInfo;
volatile TextInfo textInfo;
private string m_name;
[NonSerialized]
// Used by Thread.set_CurrentCulture
internal byte[] cached_serialized_form;
+
+ [NonSerialized]internal CultureData m_cultureData;
+ [NonSerialized]internal bool m_isInherited;
internal const int InvariantCultureId = 0x7F;
const int CalendarTypeBits = 8;
RegionInfo.ClearCachedData ();
TimeZone.ClearCachedData ();
- DateTime.ClearCachedData ();
TimeZoneInfo.ClearCachedData ();
}
infos [0] = (CultureInfo) InvariantCulture.Clone ();
}
+ for (int i = 1; i < infos.Length; ++i) {
+ var ci = infos [i];
+ infos [i].m_cultureData = CultureData.GetCultureData (ci.m_name, false, ci.datetime_index, ci.CalendarType, ci.iso2lang);
+ }
+
return infos;
}
if (!constructed) Construct ();
CheckNeutral ();
- // TODO: Have to lock because construct_datetime_format is not atomic
- lock (this) {
- if (cultureID == InvariantCultureId && m_isReadOnly)
- dateTimeInfo = DateTimeFormatInfo.InvariantInfo;
- else if (dateTimeInfo == null) {
- dateTimeInfo = new DateTimeFormatInfo (this, m_isReadOnly);
- if (cultureID != InvariantCultureId)
- construct_datetime_format ();
- }
- }
-
+ var temp = new DateTimeFormatInfo (m_cultureData, Calendar);
+ temp.m_isReadOnly = m_isReadOnly;
+ System.Threading.Thread.MemoryBarrier();
+ dateTimeInfo = temp;
return dateTimeInfo;
}
[MethodImplAttribute (MethodImplOptions.InternalCall)]
private extern static CultureInfo [] internal_get_cultures (bool neutral, bool specific, bool installed);
- [MethodImplAttribute (MethodImplOptions.InternalCall)]
- private extern void construct_datetime_format ();
-
[MethodImplAttribute (MethodImplOptions.InternalCall)]
private extern void construct_number_format ();
iso3lang="IVL";
iso2lang="iv";
win3lang="IVL";
- default_calendar_type = 1 << CalendarTypeBits;
+ default_calendar_type = 1 << CalendarTypeBits | (int) GregorianCalendarTypes.Localized;
}
private unsafe TextInfo CreateTextInfo (bool readOnly)
if (culture == InvariantCultureId) {
/* Short circuit the invariant culture */
ConstructInvariant (read_only);
+ m_cultureData = CultureData.Invariant;
return;
}
var msg = string.Format (InvariantCulture, "Culture ID {0} (0x{1}) is not a supported culture.", culture.ToString (InvariantCulture), culture.ToString ("X4", InvariantCulture));
throw new CultureNotFoundException ("culture", msg);
}
+
+ m_cultureData = CultureData.GetCultureData (m_name, m_useUserOverride, datetime_index, CalendarType, iso2lang);
}
public CultureInfo (string name) : this (name, true) {}
constructed = true;
m_isReadOnly = read_only;
m_useUserOverride = useUserOverride;
+ m_isInherited = GetType() != typeof(System.Globalization.CultureInfo);
if (name.Length == 0) {
/* Short circuit the invariant culture */
ConstructInvariant (read_only);
+ m_cultureData = CultureData.Invariant;
return;
}
if (!construct_internal_locale_from_name (name.ToLowerInvariant ())) {
throw CreateNotFoundException (name);
}
+
+ m_cultureData = CultureData.GetCultureData (m_name, useUserOverride, datetime_index, CalendarType, iso2lang);
}
// This is used when creating by specific name and creating by
if (ci.IsNeutralCulture)
ci = CreateSpecificCultureFromNeutral (ci.Name);
+ ci.m_cultureData = CultureData.GetCultureData (ci.m_name, false, ci.datetime_index, ci.CalendarType, ci.iso2lang);
return ci;
}
return new CultureInfo (id);
}
+ internal int CalendarType {
+ get {
+ switch (default_calendar_type >> CalendarTypeBits) {
+ case 1:
+ return Calendar.CAL_GREGORIAN;
+ case 2:
+ return Calendar.CAL_THAI;
+ case 3:
+ return Calendar.CAL_UMALQURA;
+ case 4:
+ return Calendar.CAL_HIJRI;
+ default:
+ throw new NotImplementedException ("CalendarType");
+ }
+ }
+ }
+
static Calendar CreateCalendar (int calendarType)
{
string name = null;
Type type = Type.GetType (name, false);
if (type == null)
- return CreateCalendar (1 << CalendarTypeBits); // return invariant calandar if not found
+ return new GregorianCalendar (GregorianCalendarTypes.Localized); // return invariant calendar if not found
return (Calendar) Activator.CreateInstance (type);
}
Thread.default_ui_culture = value;
}
}
+
+#region reference sources
+ // TODO:
+ internal static readonly bool IsTaiwanSku;
+
+ //
+ // CheckDomainSafetyObject throw if the object is customized object which cannot be attached to
+ // other object (like CultureInfo or DateTimeFormatInfo).
+ //
+
+ internal static void CheckDomainSafetyObject(Object obj, Object container)
+ {
+ if (obj.GetType().Assembly != typeof(System.Globalization.CultureInfo).Assembly) {
+
+ throw new InvalidOperationException(
+ String.Format(
+ CultureInfo.CurrentCulture,
+ Environment.GetResourceString("InvalidOperation_SubclassedObject"),
+ obj.GetType(),
+ container.GetType()));
+ }
+ Contract.EndContractBlock();
+ }
+
+ // For resource lookup, we consider a culture the invariant culture by name equality.
+ // We perform this check frequently during resource lookup, so adding a property for
+ // improved readability.
+ internal bool HasInvariantCultureName
+ {
+ get { return Name == CultureInfo.InvariantCulture.Name; }
+ }
+
+ internal static bool VerifyCultureName(String cultureName, bool throwException)
+ {
+ // This function is used by ResourceManager.GetResourceFileName().
+ // ResourceManager searches for resource using CultureInfo.Name,
+ // so we should check against CultureInfo.Name.
+
+ for (int i=0; i<cultureName.Length; i++) {
+ char c = cultureName[i];
+ //
+
+ if (Char.IsLetterOrDigit(c) || c=='-' || c=='_') {
+ continue;
+ }
+ if (throwException) {
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidResourceCultureName", cultureName));
+ }
+ return false;
+ }
+ return true;
+ }
+
+#endregion
}
}