From a2c684d4094d00c715d67238cf4f4650248d4ded Mon Sep 17 00:00:00 2001 From: Tarek Mahmoud Sayed Date: Tue, 28 Feb 2017 18:51:12 -0800 Subject: [PATCH] Globalization merge (#9835) * Merging the Globalization code in coreclr This change is merging the globalization code used for Linux and Windows. here Is come notes about this merge: - Mainly picked most of the code from the corefx folder as it is well formatted and cleaned up before and then tweaked the implementation to work on Windows - Tries to reduce the dependencies from Globalization code on the VM. this will give flexibility to work on the code without worrying the VM - Provided the missing implementation as I removed many internal calls to the VM. This also help in having .Net Native have complete implementation for .net standard 2.0 - We may need to have some small tweaks when merging this globalization code to corert - We'll need to do some clean up for the code which not used anymore in the VM * Fix ifdef's * Fix field name in linux build * Fix field name in linux compilation * Misc cleanup & return randomized hashing * Fix missing method for Linux * one more minor fix * Fix Linux build --- src/classlibnative/inc/nlsinfo.h | 6 +- src/classlibnative/nls/nlsinfo.cpp | 270 +- src/mscorlib/System.Private.CoreLib.csproj | 137 +- .../Interop/Windows/Normaliz/Interop.Idna.cs | 38 + .../Windows/kernel32/Interop.Globalization.cs | 131 + src/mscorlib/corefx/SR.cs | 5 + .../corefx/System/Globalization/Calendar.cs | 859 ------ .../System/Globalization/CalendarAlgorithmType.cs | 20 - .../corefx/System/Globalization/CalendarData.cs | 376 --- .../System/Globalization/CalendarWeekRule.cs | 18 - .../Globalization/CalendricalCalculationsHelper.cs | 412 --- .../corefx/System/Globalization/CharUnicodeInfo.cs | 391 --- .../Globalization/ChineseLunisolarCalendar.cs | 395 --- .../corefx/System/Globalization/CompareInfo.cs | 1094 ------- .../corefx/System/Globalization/CultureData.cs | 2470 ---------------- .../System/Globalization/CultureInfo.Unix.cs | 31 - .../System/Globalization/CultureInfo.Windows.cs | 57 - .../corefx/System/Globalization/CultureInfo.cs | 1558 ---------- .../Globalization/CultureNotFoundException.cs | 122 - .../corefx/System/Globalization/CultureTypes.cs | 28 - .../System/Globalization/DateTimeFormatInfo.cs | 3087 -------------------- .../Globalization/DateTimeFormatInfoScanner.cs | 742 ----- .../corefx/System/Globalization/DayLightTime.cs | 53 - .../corefx/System/Globalization/DigitShapes.cs | 18 - .../Globalization/EastAsianLunisolarCalendar.cs | 717 ----- .../System/Globalization/GregorianCalendar.cs | 666 ----- .../Globalization/GregorianCalendarHelper.cs | 668 ----- .../System/Globalization/GregorianCalendarTypes.cs | 21 - .../corefx/System/Globalization/HebrewCalendar.cs | 1129 ------- .../corefx/System/Globalization/HebrewNumber.cs | 458 --- .../corefx/System/Globalization/HijriCalendar.cs | 679 ----- .../corefx/System/Globalization/IdnMapping.cs | 152 - .../System/Globalization/JapaneseCalendar.cs | 411 --- .../Globalization/JapaneseLunisolarCalendar.cs | 311 -- .../corefx/System/Globalization/JulianCalendar.cs | 444 --- .../corefx/System/Globalization/KoreanCalendar.cs | 267 -- .../Globalization/KoreanLunisolarCalendar.cs | 1329 --------- .../System/Globalization/NumberFormatInfo.cs | 900 ------ .../corefx/System/Globalization/PersianCalendar.cs | 611 ---- .../corefx/System/Globalization/RegionInfo.cs | 421 --- .../corefx/System/Globalization/SortKey.cs | 208 -- .../corefx/System/Globalization/SortVersion.cs | 101 - .../corefx/System/Globalization/StringInfo.cs | 374 --- .../corefx/System/Globalization/TaiwanCalendar.cs | 285 -- .../Globalization/TaiwanLunisolarCalendar.cs | 330 --- .../System/Globalization/TextElementEnumerator.cs | 153 - .../corefx/System/Globalization/TextInfo.cs | 746 ----- .../System/Globalization/ThaiBuddhistCalendar.cs | 236 -- .../corefx/System/Globalization/TimeSpanStyles.cs | 13 - .../System/Globalization/UmAlQuraCalendar.cs | 870 ------ .../corefx/System/Globalization/UnicodeCategory.cs | 70 - src/mscorlib/src/System/Globalization/Calendar.cs | 119 +- .../System/Globalization/CalendarAlgorithmType.cs | 1 - .../System/Globalization/CalendarData.Unix.cs | 0 .../System/Globalization/CalendarData.Windows.cs | 45 +- .../src/System/Globalization/CalendarData.cs | 110 +- .../Globalization/CalendricalCalculationsHelper.cs | 66 +- .../src/System/Globalization/CharUnicodeInfo.cs | 259 +- .../System/Globalization/CharUnicodeInfoData.cs | 0 .../Globalization/ChineseLunisolarCalendar.cs | 50 +- .../System/Globalization/CompareInfo.Unix.cs | 4 +- .../System/Globalization/CompareInfo.Windows.cs | 157 +- .../src/System/Globalization/CompareInfo.cs | 637 ++-- .../System/Globalization/CultureData.Unix.cs | 2 +- .../System/Globalization/CultureData.Windows.cs | 200 +- .../src/System/Globalization/CultureData.cs | 2403 +++++++-------- .../src/System/Globalization/CultureInfo.Unix.cs | 124 + .../System/Globalization/CultureInfo.Windows.cs | 292 ++ .../src/System/Globalization/CultureInfo.cs | 1061 ++----- .../Globalization/CultureNotFoundException.cs | 72 +- .../src/System/Globalization/CultureTypes.cs | 5 +- .../src/System/Globalization/DateTimeFormatInfo.cs | 836 +++--- .../Globalization/DateTimeFormatInfoScanner.cs | 70 +- .../src/System/Globalization/DaylightTime.cs | 44 +- .../src/System/Globalization/DigitShapes.cs | 11 +- .../Globalization/EastAsianLunisolarCalendar.cs | 37 +- .../src/System/Globalization/GregorianCalendar.cs | 99 +- .../Globalization/GregorianCalendarHelper.cs | 54 +- .../System/Globalization/GregorianCalendarTypes.cs | 14 +- .../src/System/Globalization/HebrewCalendar.cs | 109 +- .../src/System/Globalization/HebrewNumber.cs | 91 +- .../System/Globalization/HijriCalendar.Unix.cs | 0 .../System/Globalization/HijriCalendar.Win32.cs | 0 .../System/Globalization/HijriCalendar.WinRT.cs | 0 .../src/System/Globalization/HijriCalendar.cs | 174 +- .../System/Globalization/IdnMapping.Unix.cs | 0 .../System/Globalization/IdnMapping.Windows.cs | 14 +- .../src/System/Globalization/IdnMapping.cs | 1123 +------ .../Globalization/InternalGlobalizationHelper.cs | 0 .../System/Globalization/JapaneseCalendar.Unix.cs | 0 .../System/Globalization/JapaneseCalendar.Win32.cs | 0 .../System/Globalization/JapaneseCalendar.WinRT.cs | 0 .../src/System/Globalization/JapaneseCalendar.cs | 230 +- .../Globalization/JapaneseLunisolarCalendar.cs | 23 +- .../src/System/Globalization/JulianCalendar.cs | 76 +- .../src/System/Globalization/KoreanCalendar.cs | 33 +- .../Globalization/KoreanLunisolarCalendar.cs | 50 +- .../System/Globalization/LocaleData.Unix.cs | 0 .../src/System/Globalization/NumberFormatInfo.cs | 167 +- .../src/System/Globalization/PersianCalendar.cs | 70 +- .../src/System/Globalization/RegionInfo.cs | 148 +- src/mscorlib/src/System/Globalization/SortKey.cs | 71 +- .../src/System/Globalization/SortVersion.cs | 23 +- .../src/System/Globalization/StringInfo.cs | 101 +- .../src/System/Globalization/Tables/charinfo.nlp | Bin 36992 -> 0 bytes .../src/System/Globalization/TaiwanCalendar.cs | 46 +- .../Globalization/TaiwanLunisolarCalendar.cs | 46 +- .../System/Globalization/TextElementEnumerator.cs | 88 +- .../System/Globalization/TextInfo.Unix.cs | 0 .../System/Globalization/TextInfo.Windows.cs | 10 +- src/mscorlib/src/System/Globalization/TextInfo.cs | 638 ++-- .../System/Globalization/ThaiBuddhistCalendar.cs | 17 +- .../src/System/Globalization/UmAlQuraCalendar.cs | 486 ++- .../src/System/Globalization/UnicodeCategory.cs | 9 - .../src/System/Resources/ResourceManager.cs | 8 +- src/mscorlib/src/System/String.Comparison.cs | 26 - src/mscorlib/src/System/Threading/Thread.cs | 120 +- src/utilcode/newapis.cpp | 3 - src/vm/ecalllist.h | 1 - src/vm/mscorlib.h | 105 +- src/vm/object.h | 145 +- 121 files changed, 4282 insertions(+), 31629 deletions(-) create mode 100644 src/mscorlib/corefx/Interop/Windows/Normaliz/Interop.Idna.cs create mode 100644 src/mscorlib/corefx/Interop/Windows/kernel32/Interop.Globalization.cs delete mode 100644 src/mscorlib/corefx/System/Globalization/Calendar.cs delete mode 100644 src/mscorlib/corefx/System/Globalization/CalendarAlgorithmType.cs delete mode 100644 src/mscorlib/corefx/System/Globalization/CalendarData.cs delete mode 100644 src/mscorlib/corefx/System/Globalization/CalendarWeekRule.cs delete mode 100644 src/mscorlib/corefx/System/Globalization/CalendricalCalculationsHelper.cs delete mode 100644 src/mscorlib/corefx/System/Globalization/CharUnicodeInfo.cs delete mode 100644 src/mscorlib/corefx/System/Globalization/ChineseLunisolarCalendar.cs delete mode 100644 src/mscorlib/corefx/System/Globalization/CompareInfo.cs delete mode 100644 src/mscorlib/corefx/System/Globalization/CultureData.cs delete mode 100644 src/mscorlib/corefx/System/Globalization/CultureInfo.Unix.cs delete mode 100644 src/mscorlib/corefx/System/Globalization/CultureInfo.Windows.cs delete mode 100644 src/mscorlib/corefx/System/Globalization/CultureInfo.cs delete mode 100644 src/mscorlib/corefx/System/Globalization/CultureNotFoundException.cs delete mode 100644 src/mscorlib/corefx/System/Globalization/CultureTypes.cs delete mode 100644 src/mscorlib/corefx/System/Globalization/DateTimeFormatInfo.cs delete mode 100644 src/mscorlib/corefx/System/Globalization/DateTimeFormatInfoScanner.cs delete mode 100644 src/mscorlib/corefx/System/Globalization/DayLightTime.cs delete mode 100644 src/mscorlib/corefx/System/Globalization/DigitShapes.cs delete mode 100644 src/mscorlib/corefx/System/Globalization/EastAsianLunisolarCalendar.cs delete mode 100644 src/mscorlib/corefx/System/Globalization/GregorianCalendar.cs delete mode 100644 src/mscorlib/corefx/System/Globalization/GregorianCalendarHelper.cs delete mode 100644 src/mscorlib/corefx/System/Globalization/GregorianCalendarTypes.cs delete mode 100644 src/mscorlib/corefx/System/Globalization/HebrewCalendar.cs delete mode 100644 src/mscorlib/corefx/System/Globalization/HebrewNumber.cs delete mode 100644 src/mscorlib/corefx/System/Globalization/HijriCalendar.cs delete mode 100644 src/mscorlib/corefx/System/Globalization/IdnMapping.cs delete mode 100644 src/mscorlib/corefx/System/Globalization/JapaneseCalendar.cs delete mode 100644 src/mscorlib/corefx/System/Globalization/JapaneseLunisolarCalendar.cs delete mode 100644 src/mscorlib/corefx/System/Globalization/JulianCalendar.cs delete mode 100644 src/mscorlib/corefx/System/Globalization/KoreanCalendar.cs delete mode 100644 src/mscorlib/corefx/System/Globalization/KoreanLunisolarCalendar.cs delete mode 100644 src/mscorlib/corefx/System/Globalization/NumberFormatInfo.cs delete mode 100644 src/mscorlib/corefx/System/Globalization/PersianCalendar.cs delete mode 100644 src/mscorlib/corefx/System/Globalization/RegionInfo.cs delete mode 100644 src/mscorlib/corefx/System/Globalization/SortKey.cs delete mode 100644 src/mscorlib/corefx/System/Globalization/SortVersion.cs delete mode 100644 src/mscorlib/corefx/System/Globalization/StringInfo.cs delete mode 100644 src/mscorlib/corefx/System/Globalization/TaiwanCalendar.cs delete mode 100644 src/mscorlib/corefx/System/Globalization/TaiwanLunisolarCalendar.cs delete mode 100644 src/mscorlib/corefx/System/Globalization/TextElementEnumerator.cs delete mode 100644 src/mscorlib/corefx/System/Globalization/TextInfo.cs delete mode 100644 src/mscorlib/corefx/System/Globalization/ThaiBuddhistCalendar.cs delete mode 100644 src/mscorlib/corefx/System/Globalization/TimeSpanStyles.cs delete mode 100644 src/mscorlib/corefx/System/Globalization/UmAlQuraCalendar.cs delete mode 100644 src/mscorlib/corefx/System/Globalization/UnicodeCategory.cs rename src/mscorlib/{corefx => src}/System/Globalization/CalendarData.Unix.cs (100%) rename src/mscorlib/{corefx => src}/System/Globalization/CalendarData.Windows.cs (91%) rename src/mscorlib/{corefx => src}/System/Globalization/CharUnicodeInfoData.cs (100%) rename src/mscorlib/{corefx => src}/System/Globalization/CompareInfo.Unix.cs (99%) rename src/mscorlib/{corefx => src}/System/Globalization/CompareInfo.Windows.cs (73%) rename src/mscorlib/{corefx => src}/System/Globalization/CultureData.Unix.cs (99%) rename src/mscorlib/{corefx => src}/System/Globalization/CultureData.Windows.cs (76%) create mode 100644 src/mscorlib/src/System/Globalization/CultureInfo.Unix.cs create mode 100644 src/mscorlib/src/System/Globalization/CultureInfo.Windows.cs rename src/mscorlib/{corefx => src}/System/Globalization/HijriCalendar.Unix.cs (100%) rename src/mscorlib/{corefx => src}/System/Globalization/HijriCalendar.Win32.cs (100%) rename src/mscorlib/{corefx => src}/System/Globalization/HijriCalendar.WinRT.cs (100%) rename src/mscorlib/{corefx => src}/System/Globalization/IdnMapping.Unix.cs (100%) rename src/mscorlib/{corefx => src}/System/Globalization/IdnMapping.Windows.cs (82%) rename src/mscorlib/{corefx => src}/System/Globalization/InternalGlobalizationHelper.cs (100%) rename src/mscorlib/{corefx => src}/System/Globalization/JapaneseCalendar.Unix.cs (100%) rename src/mscorlib/{corefx => src}/System/Globalization/JapaneseCalendar.Win32.cs (100%) rename src/mscorlib/{corefx => src}/System/Globalization/JapaneseCalendar.WinRT.cs (100%) rename src/mscorlib/{corefx => src}/System/Globalization/LocaleData.Unix.cs (100%) delete mode 100644 src/mscorlib/src/System/Globalization/Tables/charinfo.nlp rename src/mscorlib/{corefx => src}/System/Globalization/TextInfo.Unix.cs (100%) rename src/mscorlib/{corefx => src}/System/Globalization/TextInfo.Windows.cs (90%) diff --git a/src/classlibnative/inc/nlsinfo.h b/src/classlibnative/inc/nlsinfo.h index 1650ab3..3373f1d 100644 --- a/src/classlibnative/inc/nlsinfo.h +++ b/src/classlibnative/inc/nlsinfo.h @@ -63,7 +63,6 @@ class CharTypeTable; class CasingTable; class SortingTable; class NativeTextInfo; -class CultureDataBaseObject; class COMNlsInfo { @@ -91,13 +90,12 @@ public: // // Native helper functions for CultureData // - static FCDECL1(FC_BOOL_RET, nativeInitCultureData, CultureDataBaseObject *data); static FCDECL3(FC_BOOL_RET, nativeGetNumberFormatInfoValues, StringObject* localeNameUNSAFE, NumberFormatInfo* nfi, CLR_BOOL useUserOverride); static FCDECL1(Object*, LCIDToLocaleName, LCID lcid); static FCDECL1(INT32, LocaleNameToLCID, StringObject* localeNameUNSAFE); static INT32 QCALLTYPE InternalCompareString (INT_PTR handle, INT_PTR handleOrigin, LPCWSTR localeName, LPCWSTR string1, INT32 offset1, INT32 length1, LPCWSTR string2, INT32 offset2, INT32 length2, INT32 flags); - static INT32 QCALLTYPE InternalGetGlobalizedHashCode(INT_PTR handle, INT_PTR handleOrigin, LPCWSTR localeName, LPCWSTR pString, INT32 length, INT32 dwFlagsIn, BOOL bForceRandomizedHashing, INT64 additionalEntropy); + static INT32 QCALLTYPE InternalGetGlobalizedHashCode(INT_PTR handle, LPCWSTR localeName, LPCWSTR pString, INT32 length, INT32 dwFlagsIn, INT64 additionalEntropy); static BOOL QCALLTYPE InternalIsSortable(INT_PTR handle, INT_PTR handleOrigin, LPCWSTR localeName, LPCWSTR pString, INT32 length); static INT_PTR QCALLTYPE InternalInitSortHandle(LPCWSTR localeName, INT_PTR* handleOrigin); @@ -215,8 +213,6 @@ private: const static int m_nCodePageTableItems; const static CodePageDataItem CodePageDataTable[]; - - static INT_PTR EnsureValidSortHandle(INT_PTR handle, INT_PTR handleOrigin, LPCWSTR localeName); }; #endif // _NLSINFO_H_ diff --git a/src/classlibnative/nls/nlsinfo.cpp b/src/classlibnative/nls/nlsinfo.cpp index da565e5..7afe116 100644 --- a/src/classlibnative/nls/nlsinfo.cpp +++ b/src/classlibnative/nls/nlsinfo.cpp @@ -341,17 +341,6 @@ INT32 COMNlsInfo::CallGetUserDefaultUILanguage() return s_lcid; } -INT_PTR COMNlsInfo::EnsureValidSortHandle(INT_PTR handle, INT_PTR handleOrigin, LPCWSTR localeName) -{ - LIMITED_METHOD_CONTRACT; - - // For CoreCLR, on Windows 8 and up the handle will be valid. on downlevels the handle will be null - return handle; -} - - - - FCIMPL2(Object*, COMNlsInfo::nativeGetLocaleInfoEx, StringObject* localeNameUNSAFE, INT32 lcType) { @@ -1402,8 +1391,6 @@ INT32 QCALLTYPE COMNlsInfo::InternalCompareString( INT32 result = 1; BEGIN_QCALL; - handle = EnsureValidSortHandle(handle, handleOrigin, localeName); - { result = NewApis::CompareStringEx(handle != NULL ? NULL : localeName, flags, &string1[offset1], length1, &string2[offset2], length2,NULL,NULL, (LPARAM) handle); } @@ -1479,7 +1466,7 @@ BOOL UseConstantSpaceHashAlgorithm() // InternalGetGlobalizedHashCode // //////////////////////////////////////////////////////////////////////////// -INT32 QCALLTYPE COMNlsInfo::InternalGetGlobalizedHashCode(INT_PTR handle, INT_PTR handleOrigin, LPCWSTR localeName, LPCWSTR string, INT32 length, INT32 dwFlagsIn, BOOL bForceRandomizedHashing, INT64 additionalEntropy) +INT32 QCALLTYPE COMNlsInfo::InternalGetGlobalizedHashCode(INT_PTR handle, LPCWSTR localeName, LPCWSTR string, INT32 length, INT32 dwFlagsIn, INT64 additionalEntropy) { CONTRACTL { @@ -1491,7 +1478,6 @@ INT32 QCALLTYPE COMNlsInfo::InternalGetGlobalizedHashCode(INT_PTR handle, INT_PT INT32 iReturnHash = 0; BEGIN_QCALL; - handle = EnsureValidSortHandle(handle, handleOrigin, localeName); int byteCount = 0; // @@ -1501,61 +1487,35 @@ INT32 QCALLTYPE COMNlsInfo::InternalGetGlobalizedHashCode(INT_PTR handle, INT_PT COMPlusThrowArgumentNull(W("string"),W("ArgumentNull_String")); } + DWORD dwFlags = (LCMAP_SORTKEY | dwFlagsIn); - if(length > 0 && UseConstantSpaceHashAlgorithm() - // Note that we can't simply do the hash without the entropy and then try to add it after the fact we need the hash function itself to pass entropy to its inputs. -#ifdef FEATURE_RANDOMIZED_STRING_HASHING - && !bForceRandomizedHashing - && !COMNlsHashProvider::s_NlsHashProvider.GetUseRandomHashing() -#endif // FEATURE_RANDOMIZED_STRING_HASHING - ) + // + // Caller has already verified that the string is not of zero length + // + // Assert if we might hit an AV in LCMapStringEx for the invariant culture. + _ASSERTE(length > 0 || (dwFlags & LCMAP_LINGUISTIC_CASING) == 0); { - { - int iRes = 0; - int iHashValue = 0; - - { - iRes = NewApis::LCMapStringEx(localeName, dwFlagsIn | LCMAP_HASH, string, length, (LPWSTR) &iHashValue, sizeof(INT32), NULL, NULL, 0); - } + byteCount=NewApis::LCMapStringEx(handle != NULL ? NULL : localeName, dwFlags, string, length, NULL, 0, NULL, NULL, (LPARAM) handle); + } - if(iRes != 0) - { - iReturnHash = iHashValue; - } - } + //A count of 0 indicates that we either had an error or had a zero length string originally. + if (byteCount==0) + { + COMPlusThrow(kArgumentException, W("Arg_MustBeString")); } - if(iReturnHash == 0) + // We used to use a NewArrayHolder here, but it turns out that hurts our large # process + // scalability in ASP.Net hosting scenarios, using the quick bytes instead mostly stack + // allocates and ups throughput by 8% in 100 process case, 5% in 1000 process case { - DWORD dwFlags = (LCMAP_SORTKEY | dwFlagsIn); + CQuickBytesSpecifySize qbBuffer; + BYTE* pByte = (BYTE*)qbBuffer.AllocThrows(byteCount); - // - // Caller has already verified that the string is not of zero length - // - // Assert if we might hit an AV in LCMapStringEx for the invariant culture. - _ASSERTE(length > 0 || (dwFlags & LCMAP_LINGUISTIC_CASING) == 0); { - byteCount=NewApis::LCMapStringEx(handle != NULL ? NULL : localeName, dwFlags, string, length, NULL, 0, NULL, NULL, (LPARAM) handle); - } - - //A count of 0 indicates that we either had an error or had a zero length string originally. - if (byteCount==0) { - COMPlusThrow(kArgumentException, W("Arg_MustBeString")); + NewApis::LCMapStringEx(handle != NULL ? NULL : localeName, dwFlags, string, length, (LPWSTR)pByte, byteCount, NULL,NULL, (LPARAM) handle); } - // We used to use a NewArrayHolder here, but it turns out that hurts our large # process - // scalability in ASP.Net hosting scenarios, using the quick bytes instead mostly stack - // allocates and ups throughput by 8% in 100 process case, 5% in 1000 process case - { - CQuickBytesSpecifySize qbBuffer; - BYTE* pByte = (BYTE*)qbBuffer.AllocThrows(byteCount); - - { - NewApis::LCMapStringEx(handle != NULL ? NULL : localeName, dwFlags, string, length, (LPWSTR)pByte, byteCount, NULL,NULL, (LPARAM) handle); - } - - iReturnHash = COMNlsHashProvider::s_NlsHashProvider.HashSortKey(pByte, byteCount, bForceRandomizedHashing, additionalEntropy); - } + iReturnHash = COMNlsHashProvider::s_NlsHashProvider.HashSortKey(pByte, byteCount, true, additionalEntropy); } END_QCALL; return(iReturnHash); @@ -1592,8 +1552,6 @@ FCIMPL5(FC_CHAR_RET, COMNlsInfo::InternalChangeCaseChar, // Check for Invariant to avoid A/V in LCMapStringEx DWORD linguisticCasing = (isInvariantLocale) ? 0 : LCMAP_LINGUISTIC_CASING; - handle = EnsureValidSortHandle(handle, handleOrigin, localeName->GetBuffer()); - { ret_LCMapStringEx = NewApis::LCMapStringEx(handle != NULL ? NULL : localeName->GetBuffer(), bIsToUpper?LCMAP_UPPERCASE | linguisticCasing: @@ -1650,8 +1608,6 @@ FCIMPL5(Object*, COMNlsInfo::InternalChangeCaseString, HELPER_METHOD_FRAME_BEGIN_RET_PROTECT(gc) - handle = EnsureValidSortHandle(handle, handleOrigin, gc.pLocale->GetBuffer()); - // // Get the length of the string. // @@ -1804,8 +1760,6 @@ FCIMPL6(INT32, COMNlsInfo::InternalGetCaseInsHash, } else { - handle = EnsureValidSortHandle(handle, handleOrigin, localeName->GetBuffer()); - // Make it upper case CQuickBytes newBuffer; INT32 length = strA->GetStringLength(); @@ -2170,190 +2124,6 @@ FCIMPL0(INT32, COMNlsInfo::nativeGetNumEncodingItems) } FCIMPLEND - - -typedef CultureDataBaseObject* CULTUREDATAREF; - -// nativeInitCultureData checks with the OS to see if this is a valid culture. -// If so we populate a limited number of fields. If its not valid we return false. -// -// The fields we populate: -// -// sWindowsName -- The name that windows thinks this culture is, ie: -// en-US if you pass in en-US -// de-DE_phoneb if you pass in de-DE_phoneb -// fj-FJ if you pass in fj (neutral, on a pre-Windows 7 machine) -// fj if you pass in fj (neutral, post-Windows 7 machine) -// -// sRealName -- The name you used to construct the culture, in pretty form -// en-US if you pass in EN-us -// en if you pass in en -// de-DE_phoneb if you pass in de-DE_phoneb -// -// sSpecificCulture -- The specific culture for this culture -// en-US for en-US -// en-US for en -// de-DE_phoneb for alt sort -// fj-FJ for fj (neutral) -// -// sName -- The IETF name of this culture (ie: no sort info, could be neutral) -// en-US if you pass in en-US -// en if you pass in en -// de-DE if you pass in de-DE_phoneb -// -// bNeutral -- TRUE if it is a neutral locale -// -// For a neutral we just populate the neutral name, but we leave the windows name pointing to the -// windows locale that's going to provide data for us. -// -FCIMPL1(FC_BOOL_RET, COMNlsInfo::nativeInitCultureData, CultureDataBaseObject *cultureDataUNSAFE) -{ - FCALL_CONTRACT; - - BOOL success=FALSE; - - struct _gc - { - STRINGREF stringResult; - CULTUREDATAREF cultureData; - } gc; - - gc.stringResult = NULL; - gc.cultureData = (CULTUREDATAREF) cultureDataUNSAFE; - HELPER_METHOD_FRAME_BEGIN_RET_PROTECT(gc); - - WCHAR buffer[LOCALE_NAME_MAX_LENGTH]; - int result; - - StackSString realNameBuffer( ((STRINGREF)gc.cultureData->sRealName)->GetBuffer() ); - - // Call GetLocaleInfoEx and see if the OS knows about it. - // Note that GetLocaleInfoEx has variations: - // * Pre-Vista it fails and has to go downlevel - // * Vista succeeds, but not for neutrals - // * Win7 succeeds for all locales. - // * Mac does ??? - // The differences should be handled by the NewApis wrapper - result = NewApis::GetLocaleInfoEx(realNameBuffer, LOCALE_SNAME, buffer, NumItems(buffer)); - - // Did it fail? - if (result == 0) - { - // Not a real locale, fail - goto Exit; - } - - // It worked, note that the name is the locale name, so use that (even for neutrals) - // We need to clean up our "real" name, which should look like the windows name right now - // so overwrite the input with the cleaned up name - gc.stringResult = StringObject::NewString(buffer, result-1); - SetObjectReference((OBJECTREF*)&(gc.cultureData->sRealName), gc.stringResult, NULL); - - // Check for neutrality, don't expect to fail - // (buffer has our name in it, so we don't have to do the gc. stuff) - DWORD bNeutral; - if (0 == NewApis::GetLocaleInfoEx(buffer, LOCALE_INEUTRAL | LOCALE_RETURN_NUMBER, (LPWSTR)&bNeutral, sizeof(bNeutral)/sizeof(WCHAR))) - goto Exit; - - // Remember our neutrality - gc.cultureData->bNeutral = (bNeutral != 0); - - gc.cultureData->bWin32Installed = (IsOSValidLocaleName(buffer, gc.cultureData->bNeutral) != 0); - gc.cultureData->bFramework = (IsWhidbeyFrameworkCulture(buffer) != 0); - - - // Note: Parents will be set dynamically - - // Start by assuming the windows name'll be the same as the specific name since windows knows - // about specifics on all versions. For macs it also works. Only for downlevel Neutral locales - // does this have to change. - gc.stringResult = StringObject::NewString(buffer, result-1); - SetObjectReference((OBJECTREF*)&(gc.cultureData->sWindowsName), gc.stringResult, NULL); - - // Neutrals and non-neutrals are slightly different - if (gc.cultureData->bNeutral) - { - // Neutral Locale - - // IETF name looks like neutral name - gc.stringResult = StringObject::NewString(buffer, result-1); - SetObjectReference((OBJECTREF*)&(gc.cultureData->sName), gc.stringResult, NULL); - - // Specific locale name is whatever ResolveLocaleName (win7+) returns. - // (Buffer has our name in it, and we can recycle that because windows resolves it before writing to the buffer) - result = NewApis::ResolveLocaleName(buffer, buffer, NumItems(buffer)); - - // 0 is failure, 1 is invariant (""), which we expect - if (result < 1) goto Exit; - - // We found a locale name, so use it. - // In vista this should look like a sort name (de-DE_phoneb) or a specific culture (en-US) and be in the "pretty" form - gc.stringResult = StringObject::NewString(buffer, result - 1); - SetObjectReference((OBJECTREF*)&(gc.cultureData->sSpecificCulture), gc.stringResult, NULL); - - if (!IsWindows7()) - { - // For neutrals on Windows 7 + the neutral windows name can be the same as the neutral name, - // but on pre windows 7 names it has to be the specific, so we have to fix it in that case. - gc.stringResult = StringObject::NewString(buffer, result - 1); - SetObjectReference((OBJECTREF*)&(gc.cultureData->sWindowsName), gc.stringResult, NULL); - } - - - } - else - { - // Specific Locale - - // Specific culture's the same as the locale name since we know its not neutral - // On mac we'll use this as well, even for neutrals. There's no obvious specific - // culture to use and this isn't exposed, but behaviorally this is correct on mac. - // Note that specifics include the sort name (de-DE_phoneb) - gc.stringResult = StringObject::NewString(buffer, result-1); - SetObjectReference((OBJECTREF*)&(gc.cultureData->sSpecificCulture), gc.stringResult, NULL); - - // We need the IETF name (sname) - // If we aren't an alt sort locale then this is the same as the windows name. - // If we are an alt sort locale then this is the same as the part before the _ in the windows name - // This is for like de-DE_phoneb and es-ES_tradnl that hsouldn't have the _ part - - int localeNameLength = result - 1; - - LCID lcid = NewApis::LocaleNameToLCID(buffer, 0); - if (!IsCustomCultureId(lcid)) - { - LPCWSTR index = wcschr(buffer, W('_')); - if(index) // Not a custom culture and looks like an alt sort name - { - // Looks like an alt sort, and has a appropriate sort LCID (so not custom), make it smaller for the RFC 4646 style name - localeNameLength = static_cast(index - buffer); - } - } - - gc.stringResult = StringObject::NewString(buffer, localeNameLength); - _ASSERTE(gc.stringResult != NULL); - - // Now use that name - SetObjectReference((OBJECTREF*)&(gc.cultureData->sName), gc.stringResult, NULL); - } - - // For Silverlight make sure that the sorting tables are available (< Vista may not have east asian installed) - result = NewApis::CompareStringEx(((STRINGREF)gc.cultureData->sWindowsName)->GetBuffer(), - 0, W("A"), 1, W("B"), 1, NULL, NULL, 0); - if (result == 0) goto Exit; - - // It succeeded. - success = TRUE; - -Exit: {} - - HELPER_METHOD_FRAME_END(); - - FC_RETURN_BOOL(success); -} -FCIMPLEND - - // Return true if we're on Windows 7 (ie: if we have neutral native support) BOOL COMNlsInfo::IsWindows7() { diff --git a/src/mscorlib/System.Private.CoreLib.csproj b/src/mscorlib/System.Private.CoreLib.csproj index d588bed..43056cd 100644 --- a/src/mscorlib/System.Private.CoreLib.csproj +++ b/src/mscorlib/System.Private.CoreLib.csproj @@ -561,110 +561,84 @@ - - - - - - - - - - + + + + + + + + - - - + - + + - - + + + + + + + + - - + + + - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -678,16 +652,10 @@ - - - - - - - - - - + + + + @@ -994,6 +962,8 @@ + + @@ -1060,11 +1030,6 @@ - - - charinfo.nlp - - true true diff --git a/src/mscorlib/corefx/Interop/Windows/Normaliz/Interop.Idna.cs b/src/mscorlib/corefx/Interop/Windows/Normaliz/Interop.Idna.cs new file mode 100644 index 0000000..cad457d --- /dev/null +++ b/src/mscorlib/corefx/Interop/Windows/Normaliz/Interop.Idna.cs @@ -0,0 +1,38 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Runtime.InteropServices; + +internal partial class Interop +{ + internal partial class Normaliz + { + // + // Idn APIs + // + + [DllImport("Normaliz.dll", CharSet = CharSet.Unicode, SetLastError = true)] + internal static extern int IdnToAscii( + uint dwFlags, + IntPtr lpUnicodeCharStr, + int cchUnicodeChar, + [System.Runtime.InteropServices.OutAttribute()] + IntPtr lpASCIICharStr, + int cchASCIIChar); + + [DllImport("Normaliz.dll", CharSet = CharSet.Unicode, SetLastError = true)] + internal static extern int IdnToUnicode( + uint dwFlags, + IntPtr lpASCIICharStr, + int cchASCIIChar, + [System.Runtime.InteropServices.OutAttribute()] + IntPtr lpUnicodeCharStr, + int cchUnicodeChar); + + internal const int IDN_ALLOW_UNASSIGNED = 0x1; + internal const int IDN_USE_STD3_ASCII_RULES = 0x2; + internal const int ERROR_INVALID_NAME = 123; + } +} diff --git a/src/mscorlib/corefx/Interop/Windows/kernel32/Interop.Globalization.cs b/src/mscorlib/corefx/Interop/Windows/kernel32/Interop.Globalization.cs new file mode 100644 index 0000000..d187e00 --- /dev/null +++ b/src/mscorlib/corefx/Interop/Windows/kernel32/Interop.Globalization.cs @@ -0,0 +1,131 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Runtime.InteropServices; + +internal static partial class Interop +{ + internal static unsafe partial class Kernel32 + { + internal const int LOCALE_NAME_MAX_LENGTH = 85; + internal const uint LOCALE_ALLOW_NEUTRAL_NAMES = 0x08000000; // Flag to allow returning neutral names/lcids for name conversion + internal const uint LOCALE_SUPPLEMENTAL = 0x00000002; + internal const uint LOCALE_REPLACEMENT = 0x00000008; + internal const uint LOCALE_NEUTRALDATA = 0x00000010; + internal const uint LOCALE_SPECIFICDATA = 0x00000020; + internal const int COMPARE_STRING = 0x0001; + + [DllImport("kernel32.dll", CharSet = CharSet.Unicode)] + internal extern static unsafe int LCIDToLocaleName(int locale, char *pLocaleName, int cchName, uint dwFlags); + + [DllImport("kernel32.dll", CharSet = CharSet.Unicode)] + internal extern static int LocaleNameToLCID(string lpName, uint dwFlags); + + [DllImport("kernel32.dll", CharSet = CharSet.Unicode)] + internal extern static unsafe int LCMapStringEx( + string lpLocaleName, + uint dwMapFlags, + char* lpSrcStr, + int cchSrc, + void* lpDestStr, + int cchDest, + void* lpVersionInformation, + void* lpReserved, + IntPtr sortHandle); + + [DllImport("kernel32.dll", EntryPoint = "FindNLSStringEx")] + internal extern static unsafe int FindNLSStringEx( + char* lpLocaleName, + uint dwFindNLSStringFlags, + char* lpStringSource, + int cchSource, + char* lpStringValue, + int cchValue, + int* pcchFound, + void* lpVersionInformation, + void* lpReserved, + IntPtr sortHandle); + + [DllImport("kernel32.dll", EntryPoint = "CompareStringEx")] + internal extern static unsafe int CompareStringEx( + char* lpLocaleName, + uint dwCmpFlags, + char* lpString1, + int cchCount1, + char* lpString2, + int cchCount2, + void* lpVersionInformation, + void* lpReserved, + IntPtr lParam); + + [DllImport("kernel32.dll", EntryPoint = "CompareStringOrdinal")] + internal extern static unsafe int CompareStringOrdinal( + char* lpString1, + int cchCount1, + char* lpString2, + int cchCount2, + bool bIgnoreCase); + + [DllImport("kernel32.dll", EntryPoint = "FindStringOrdinal")] + internal extern static unsafe int FindStringOrdinal( + uint dwFindStringOrdinalFlags, + char* lpStringSource, + int cchSource, + char* lpStringValue, + int cchValue, + int bIgnoreCase); + + [DllImport("kernel32.dll", CharSet = CharSet.Unicode)] + internal extern static unsafe bool IsNLSDefinedString( + int Function, + uint dwFlags, + IntPtr lpVersionInformation, + char* lpString, + int cchStr); + + [DllImport("Kernel32.dll", CharSet = CharSet.Auto)] + internal static extern bool GetUserPreferredUILanguages(uint dwFlags, out uint pulNumLanguages, char [] pwszLanguagesBuffer, ref uint pcchLanguagesBuffer); + + [DllImport("kernel32.dll", CharSet = CharSet.Unicode)] + internal static extern int GetLocaleInfoEx(string lpLocaleName, uint LCType, IntPtr lpLCData, int cchData); + + [DllImport("kernel32.dll", CharSet = CharSet.Unicode)] + internal extern static bool EnumSystemLocalesEx(EnumLocalesProcEx lpLocaleEnumProcEx, uint dwFlags, IntPtr lParam, IntPtr reserved); + + internal delegate BOOL EnumLocalesProcEx(IntPtr lpLocaleString, uint dwFlags, IntPtr lParam); + + [DllImport("kernel32.dll", CharSet = CharSet.Unicode)] + internal extern static int ResolveLocaleName(string lpNameToResolve, char* lpLocaleName, int cchLocaleName); + + [DllImport("kernel32.dll", CharSet = CharSet.Unicode)] + internal extern static bool EnumTimeFormatsEx(EnumTimeFormatsProcEx lpTimeFmtEnumProcEx, string lpLocaleName, uint dwFlags, IntPtr lParam); + + internal delegate BOOL EnumTimeFormatsProcEx(IntPtr lpTimeFormatString, IntPtr lParam); + + [DllImport("kernel32.dll", CharSet = CharSet.Unicode)] + internal extern static int GetCalendarInfoEx(string lpLocaleName, uint Calendar, IntPtr lpReserved, uint CalType, IntPtr lpCalData, int cchData, out int lpValue); + + [DllImport("kernel32.dll", CharSet = CharSet.Unicode)] + internal extern static int GetCalendarInfoEx(string lpLocaleName, uint Calendar, IntPtr lpReserved, uint CalType, IntPtr lpCalData, int cchData, IntPtr lpValue); + + [DllImport("kernel32.dll", CharSet = CharSet.Unicode)] + internal extern static bool EnumCalendarInfoExEx(EnumCalendarInfoProcExEx pCalInfoEnumProcExEx, string lpLocaleName, uint Calendar, string lpReserved, uint CalType, IntPtr lParam); + + internal delegate BOOL EnumCalendarInfoProcExEx(IntPtr lpCalendarInfoString, uint Calendar, IntPtr lpReserved, IntPtr lParam); + + [StructLayout(LayoutKind.Sequential)] + internal struct NlsVersionInfoEx + { + internal int dwNLSVersionInfoSize; + internal int dwNLSVersion; + internal int dwDefinedVersion; + internal int dwEffectiveId; + internal Guid guidCustomVersion; + } + + [DllImport("kernel32.dll", CharSet = CharSet.Unicode)] + internal extern static unsafe bool GetNLSVersionEx(int function, string localeName, NlsVersionInfoEx* lpVersionInformation); + } +} diff --git a/src/mscorlib/corefx/SR.cs b/src/mscorlib/corefx/SR.cs index b33bb79..35fe39c 100644 --- a/src/mscorlib/corefx/SR.cs +++ b/src/mscorlib/corefx/SR.cs @@ -211,6 +211,11 @@ internal static class SR get { return Environment.GetResourceString("Argument_InvalidCharSequence"); } } + public static string Argument_InvalidCharSequenceNoIndex + { + get { return Environment.GetResourceString("Argument_InvalidCharSequenceNoIndex"); } + } + public static string Argument_InvalidCultureName { get { return Environment.GetResourceString("Argument_InvalidCultureName"); } diff --git a/src/mscorlib/corefx/System/Globalization/Calendar.cs b/src/mscorlib/corefx/System/Globalization/Calendar.cs deleted file mode 100644 index 274fe6f..0000000 --- a/src/mscorlib/corefx/System/Globalization/Calendar.cs +++ /dev/null @@ -1,859 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System.Diagnostics; -using System.Diagnostics.Contracts; -using System.Runtime.Serialization; - -namespace System.Globalization -{ - // This abstract class represents a calendar. A calendar reckons time in - // divisions such as weeks, months and years. The number, length and start of - // the divisions vary in each calendar. - // - // Any instant in time can be represented as an n-tuple of numeric values using - // a particular calendar. For example, the next vernal equinox occurs at (0.0, 0 - // , 46, 8, 20, 3, 1999) in the Gregorian calendar. An implementation of - // Calendar can map any DateTime value to such an n-tuple and vice versa. The - // DateTimeFormat class can map between such n-tuples and a textual - // representation such as "8:46 AM March 20th 1999 AD". - // - // Most calendars identify a year which begins the current era. There may be any - // number of previous eras. The Calendar class identifies the eras as enumerated - // integers where the current era (CurrentEra) has the value zero. - // - // For consistency, the first unit in each interval, e.g. the first month, is - // assigned the value one. - // The calculation of hour/minute/second is moved to Calendar from GregorianCalendar, - // since most of the calendars (or all?) have the same way of calcuating hour/minute/second. - - [Serializable] - public abstract partial class Calendar : ICloneable - { - // Number of 100ns (10E-7 second) ticks per time unit - internal const long TicksPerMillisecond = 10000; - internal const long TicksPerSecond = TicksPerMillisecond * 1000; - internal const long TicksPerMinute = TicksPerSecond * 60; - internal const long TicksPerHour = TicksPerMinute * 60; - internal const long TicksPerDay = TicksPerHour * 24; - - // Number of milliseconds per time unit - internal const int MillisPerSecond = 1000; - internal const int MillisPerMinute = MillisPerSecond * 60; - internal const int MillisPerHour = MillisPerMinute * 60; - internal const int MillisPerDay = MillisPerHour * 24; - - // Number of days in a non-leap year - internal const int DaysPerYear = 365; - // Number of days in 4 years - internal const int DaysPer4Years = DaysPerYear * 4 + 1; - // Number of days in 100 years - internal const int DaysPer100Years = DaysPer4Years * 25 - 1; - // Number of days in 400 years - internal const int DaysPer400Years = DaysPer100Years * 4 + 1; - - // Number of days from 1/1/0001 to 1/1/10000 - internal const int DaysTo10000 = DaysPer400Years * 25 - 366; - - internal const long MaxMillis = (long)DaysTo10000 * MillisPerDay; - - - private int _currentEraValue = -1; - - [OptionalField(VersionAdded = 2)] - private bool _isReadOnly = false; - -#if CORECLR - internal const CalendarId CAL_HEBREW = CalendarId.HEBREW; - internal const CalendarId CAL_HIJRI = CalendarId.HIJRI; - internal const CalendarId CAL_JAPAN = CalendarId.JAPAN; - internal const CalendarId CAL_JULIAN = CalendarId.JULIAN; - internal const CalendarId CAL_TAIWAN = CalendarId.TAIWAN; - internal const CalendarId CAL_UMALQURA = CalendarId.UMALQURA; - internal const CalendarId CAL_PERSIAN = CalendarId.PERSIAN; -#endif - - // The minimum supported DateTime range for the calendar. - - public virtual DateTime MinSupportedDateTime - { - get - { - return (DateTime.MinValue); - } - } - - // The maximum supported DateTime range for the calendar. - - public virtual DateTime MaxSupportedDateTime - { - get - { - return (DateTime.MaxValue); - } - } - - public virtual CalendarAlgorithmType AlgorithmType - { - get - { - return CalendarAlgorithmType.Unknown; - } - } - - protected Calendar() - { - //Do-nothing constructor. - } - - /// - // This can not be abstract, otherwise no one can create a subclass of Calendar. - // - internal virtual CalendarId ID - { - get - { - return CalendarId.UNINITIALIZED_VALUE; - } - } - - /// - // Return the Base calendar ID for calendars that didn't have defined data in calendarData - // - - internal virtual CalendarId BaseCalendarID - { - get { return ID; } - } - - //////////////////////////////////////////////////////////////////////// - // - // IsReadOnly - // - // Detect if the object is readonly. - // - //////////////////////////////////////////////////////////////////////// - public bool IsReadOnly - { - get { return (_isReadOnly); } - } - - //////////////////////////////////////////////////////////////////////// - // - // Clone - // - // Is the implementation of ICloneable. - // - //////////////////////////////////////////////////////////////////////// - public virtual object Clone() - { - object o = MemberwiseClone(); - ((Calendar)o).SetReadOnlyState(false); - return (o); - } - - //////////////////////////////////////////////////////////////////////// - // - // ReadOnly - // - // Create a cloned readonly instance or return the input one if it is - // readonly. - // - //////////////////////////////////////////////////////////////////////// - public static Calendar ReadOnly(Calendar calendar) - { - if (calendar == null) { throw new ArgumentNullException(nameof(calendar)); } - Contract.EndContractBlock(); - if (calendar.IsReadOnly) { return (calendar); } - - Calendar clonedCalendar = (Calendar)(calendar.MemberwiseClone()); - clonedCalendar.SetReadOnlyState(true); - - return (clonedCalendar); - } - - internal void VerifyWritable() - { - if (_isReadOnly) - { - throw new InvalidOperationException(SR.InvalidOperation_ReadOnly); - } - } - - internal void SetReadOnlyState(bool readOnly) - { - _isReadOnly = readOnly; - } - - - /*=================================CurrentEraValue========================== - **Action: This is used to convert CurretEra(0) to an appropriate era value. - **Returns: - **Arguments: - **Exceptions: - **Notes: - ** The value is from calendar.nlp. - ============================================================================*/ - - internal virtual int CurrentEraValue - { - get - { - // The following code assumes that the current era value can not be -1. - if (_currentEraValue == -1) - { - Debug.Assert(BaseCalendarID != CalendarId.UNINITIALIZED_VALUE, "[Calendar.CurrentEraValue] Expected a real calendar ID"); - _currentEraValue = CalendarData.GetCalendarData(BaseCalendarID).iCurrentEra; - } - return (_currentEraValue); - } - } - - // The current era for a calendar. - - public const int CurrentEra = 0; - - internal int twoDigitYearMax = -1; - - internal static void CheckAddResult(long ticks, DateTime minValue, DateTime maxValue) - { - if (ticks < minValue.Ticks || ticks > maxValue.Ticks) - { - throw new ArgumentException( - String.Format(CultureInfo.InvariantCulture, SR.Format(SR.Argument_ResultCalendarRange, - minValue, maxValue))); - } - Contract.EndContractBlock(); - } - - internal DateTime Add(DateTime time, double value, int scale) - { - // From ECMA CLI spec, Partition III, section 3.27: - // - // If overflow occurs converting a floating-point type to an integer, or if the floating-point value - // being converted to an integer is a NaN, the value returned is unspecified. - // - // Based upon this, this method should be performing the comparison against the double - // before attempting a cast. Otherwise, the result is undefined. - double tempMillis = (value * scale + (value >= 0 ? 0.5 : -0.5)); - if (!((tempMillis > -(double)MaxMillis) && (tempMillis < (double)MaxMillis))) - { - throw new ArgumentOutOfRangeException(nameof(value), SR.ArgumentOutOfRange_AddValue); - } - - long millis = (long)tempMillis; - long ticks = time.Ticks + millis * TicksPerMillisecond; - CheckAddResult(ticks, MinSupportedDateTime, MaxSupportedDateTime); - return (new DateTime(ticks)); - } - - // Returns the DateTime resulting from adding the given number of - // milliseconds to the specified DateTime. The result is computed by rounding - // the number of milliseconds given by value to the nearest integer, - // and adding that interval to the specified DateTime. The value - // argument is permitted to be negative. - // - - public virtual DateTime AddMilliseconds(DateTime time, double milliseconds) - { - return (Add(time, milliseconds, 1)); - } - - - // Returns the DateTime resulting from adding a fractional number of - // days to the specified DateTime. The result is computed by rounding the - // fractional number of days given by value to the nearest - // millisecond, and adding that interval to the specified DateTime. The - // value argument is permitted to be negative. - // - - public virtual DateTime AddDays(DateTime time, int days) - { - return (Add(time, days, MillisPerDay)); - } - - // Returns the DateTime resulting from adding a fractional number of - // hours to the specified DateTime. The result is computed by rounding the - // fractional number of hours given by value to the nearest - // millisecond, and adding that interval to the specified DateTime. The - // value argument is permitted to be negative. - // - - public virtual DateTime AddHours(DateTime time, int hours) - { - return (Add(time, hours, MillisPerHour)); - } - - - // Returns the DateTime resulting from adding a fractional number of - // minutes to the specified DateTime. The result is computed by rounding the - // fractional number of minutes given by value to the nearest - // millisecond, and adding that interval to the specified DateTime. The - // value argument is permitted to be negative. - // - - public virtual DateTime AddMinutes(DateTime time, int minutes) - { - return (Add(time, minutes, MillisPerMinute)); - } - - - // Returns the DateTime resulting from adding the given number of - // months to the specified DateTime. The result is computed by incrementing - // (or decrementing) the year and month parts of the specified DateTime by - // value months, and, if required, adjusting the day part of the - // resulting date downwards to the last day of the resulting month in the - // resulting year. The time-of-day part of the result is the same as the - // time-of-day part of the specified DateTime. - // - // In more precise terms, considering the specified DateTime to be of the - // form y / m / d + t, where y is the - // year, m is the month, d is the day, and t is the - // time-of-day, the result is y1 / m1 / d1 + t, - // where y1 and m1 are computed by adding value months - // to y and m, and d1 is the largest value less than - // or equal to d that denotes a valid day in month m1 of year - // y1. - // - - public abstract DateTime AddMonths(DateTime time, int months); - - // Returns the DateTime resulting from adding a number of - // seconds to the specified DateTime. The result is computed by rounding the - // fractional number of seconds given by value to the nearest - // millisecond, and adding that interval to the specified DateTime. The - // value argument is permitted to be negative. - // - - public virtual DateTime AddSeconds(DateTime time, int seconds) - { - return Add(time, seconds, MillisPerSecond); - } - - // Returns the DateTime resulting from adding a number of - // weeks to the specified DateTime. The - // value argument is permitted to be negative. - // - - public virtual DateTime AddWeeks(DateTime time, int weeks) - { - return (AddDays(time, weeks * 7)); - } - - - // Returns the DateTime resulting from adding the given number of - // years to the specified DateTime. The result is computed by incrementing - // (or decrementing) the year part of the specified DateTime by value - // years. If the month and day of the specified DateTime is 2/29, and if the - // resulting year is not a leap year, the month and day of the resulting - // DateTime becomes 2/28. Otherwise, the month, day, and time-of-day - // parts of the result are the same as those of the specified DateTime. - // - - public abstract DateTime AddYears(DateTime time, int years); - - // Returns the day-of-month part of the specified DateTime. The returned - // value is an integer between 1 and 31. - // - - public abstract int GetDayOfMonth(DateTime time); - - // Returns the day-of-week part of the specified DateTime. The returned value - // is an integer between 0 and 6, where 0 indicates Sunday, 1 indicates - // Monday, 2 indicates Tuesday, 3 indicates Wednesday, 4 indicates - // Thursday, 5 indicates Friday, and 6 indicates Saturday. - // - - public abstract DayOfWeek GetDayOfWeek(DateTime time); - - // Returns the day-of-year part of the specified DateTime. The returned value - // is an integer between 1 and 366. - // - - public abstract int GetDayOfYear(DateTime time); - - // Returns the number of days in the month given by the year and - // month arguments. - // - - public virtual int GetDaysInMonth(int year, int month) - { - return (GetDaysInMonth(year, month, CurrentEra)); - } - - // Returns the number of days in the month given by the year and - // month arguments for the specified era. - // - - public abstract int GetDaysInMonth(int year, int month, int era); - - // Returns the number of days in the year given by the year argument for the current era. - // - - public virtual int GetDaysInYear(int year) - { - return (GetDaysInYear(year, CurrentEra)); - } - - // Returns the number of days in the year given by the year argument for the current era. - // - - public abstract int GetDaysInYear(int year, int era); - - // Returns the era for the specified DateTime value. - - public abstract int GetEra(DateTime time); - - /*=================================Eras========================== - **Action: Get the list of era values. - **Returns: The int array of the era names supported in this calendar. - ** null if era is not used. - **Arguments: None. - **Exceptions: None. - ============================================================================*/ - - - public abstract int[] Eras - { - get; - } - - - // Returns the hour part of the specified DateTime. The returned value is an - // integer between 0 and 23. - // - - public virtual int GetHour(DateTime time) - { - return ((int)((time.Ticks / TicksPerHour) % 24)); - } - - // Returns the millisecond part of the specified DateTime. The returned value - // is an integer between 0 and 999. - // - - public virtual double GetMilliseconds(DateTime time) - { - return (double)((time.Ticks / TicksPerMillisecond) % 1000); - } - - // Returns the minute part of the specified DateTime. The returned value is - // an integer between 0 and 59. - // - - public virtual int GetMinute(DateTime time) - { - return ((int)((time.Ticks / TicksPerMinute) % 60)); - } - - // Returns the month part of the specified DateTime. The returned value is an - // integer between 1 and 12. - // - - public abstract int GetMonth(DateTime time); - - // Returns the number of months in the specified year in the current era. - - public virtual int GetMonthsInYear(int year) - { - return (GetMonthsInYear(year, CurrentEra)); - } - - // Returns the number of months in the specified year and era. - - public abstract int GetMonthsInYear(int year, int era); - - // Returns the second part of the specified DateTime. The returned value is - // an integer between 0 and 59. - // - - public virtual int GetSecond(DateTime time) - { - return ((int)((time.Ticks / TicksPerSecond) % 60)); - } - - /*=================================GetFirstDayWeekOfYear========================== - **Action: Get the week of year using the FirstDay rule. - **Returns: the week of year. - **Arguments: - ** time - ** firstDayOfWeek the first day of week (0=Sunday, 1=Monday, ... 6=Saturday) - **Notes: - ** The CalendarWeekRule.FirstDay rule: Week 1 begins on the first day of the year. - ** Assume f is the specifed firstDayOfWeek, - ** and n is the day of week for January 1 of the specified year. - ** Assign offset = n - f; - ** Case 1: offset = 0 - ** E.g. - ** f=1 - ** weekday 0 1 2 3 4 5 6 0 1 - ** date 1/1 - ** week# 1 2 - ** then week of year = (GetDayOfYear(time) - 1) / 7 + 1 - ** - ** Case 2: offset < 0 - ** e.g. - ** n=1 f=3 - ** weekday 0 1 2 3 4 5 6 0 - ** date 1/1 - ** week# 1 2 - ** This means that the first week actually starts 5 days before 1/1. - ** So week of year = (GetDayOfYear(time) + (7 + offset) - 1) / 7 + 1 - ** Case 3: offset > 0 - ** e.g. - ** f=0 n=2 - ** weekday 0 1 2 3 4 5 6 0 1 2 - ** date 1/1 - ** week# 1 2 - ** This means that the first week actually starts 2 days before 1/1. - ** So Week of year = (GetDayOfYear(time) + offset - 1) / 7 + 1 - ============================================================================*/ - - internal int GetFirstDayWeekOfYear(DateTime time, int firstDayOfWeek) - { - int dayOfYear = GetDayOfYear(time) - 1; // Make the day of year to be 0-based, so that 1/1 is day 0. - // Calculate the day of week for the first day of the year. - // dayOfWeek - (dayOfYear % 7) is the day of week for the first day of this year. Note that - // this value can be less than 0. It's fine since we are making it positive again in calculating offset. - int dayForJan1 = (int)GetDayOfWeek(time) - (dayOfYear % 7); - int offset = (dayForJan1 - firstDayOfWeek + 14) % 7; - Debug.Assert(offset >= 0, "Calendar.GetFirstDayWeekOfYear(): offset >= 0"); - return ((dayOfYear + offset) / 7 + 1); - } - - private int GetWeekOfYearFullDays(DateTime time, int firstDayOfWeek, int fullDays) - { - int dayForJan1; - int offset; - int day; - - int dayOfYear = GetDayOfYear(time) - 1; // Make the day of year to be 0-based, so that 1/1 is day 0. - // - // Calculate the number of days between the first day of year (1/1) and the first day of the week. - // This value will be a positive value from 0 ~ 6. We call this value as "offset". - // - // If offset is 0, it means that the 1/1 is the start of the first week. - // Assume the first day of the week is Monday, it will look like this: - // Sun Mon Tue Wed Thu Fri Sat - // 12/31 1/1 1/2 1/3 1/4 1/5 1/6 - // +--> First week starts here. - // - // If offset is 1, it means that the first day of the week is 1 day ahead of 1/1. - // Assume the first day of the week is Monday, it will look like this: - // Sun Mon Tue Wed Thu Fri Sat - // 1/1 1/2 1/3 1/4 1/5 1/6 1/7 - // +--> First week starts here. - // - // If offset is 2, it means that the first day of the week is 2 days ahead of 1/1. - // Assume the first day of the week is Monday, it will look like this: - // Sat Sun Mon Tue Wed Thu Fri Sat - // 1/1 1/2 1/3 1/4 1/5 1/6 1/7 1/8 - // +--> First week starts here. - - - - // Day of week is 0-based. - // Get the day of week for 1/1. This can be derived from the day of week of the target day. - // Note that we can get a negative value. It's ok since we are going to make it a positive value when calculating the offset. - dayForJan1 = (int)GetDayOfWeek(time) - (dayOfYear % 7); - - // Now, calculate the offset. Subtract the first day of week from the dayForJan1. And make it a positive value. - offset = (firstDayOfWeek - dayForJan1 + 14) % 7; - if (offset != 0 && offset >= fullDays) - { - // - // If the offset is greater than the value of fullDays, it means that - // the first week of the year starts on the week where Jan/1 falls on. - // - offset -= 7; - } - // - // Calculate the day of year for specified time by taking offset into account. - // - day = dayOfYear - offset; - if (day >= 0) - { - // - // If the day of year value is greater than zero, get the week of year. - // - return (day / 7 + 1); - } - // - // Otherwise, the specified time falls on the week of previous year. - // Call this method again by passing the last day of previous year. - // - // the last day of the previous year may "underflow" to no longer be a valid date time for - // this calendar if we just subtract so we need the subclass to provide us with - // that information - if (time <= MinSupportedDateTime.AddDays(dayOfYear)) - { - return GetWeekOfYearOfMinSupportedDateTime(firstDayOfWeek, fullDays); - } - return (GetWeekOfYearFullDays(time.AddDays(-(dayOfYear + 1)), firstDayOfWeek, fullDays)); - } - - private int GetWeekOfYearOfMinSupportedDateTime(int firstDayOfWeek, int minimumDaysInFirstWeek) - { - int dayOfYear = GetDayOfYear(MinSupportedDateTime) - 1; // Make the day of year to be 0-based, so that 1/1 is day 0. - int dayOfWeekOfFirstOfYear = (int)GetDayOfWeek(MinSupportedDateTime) - dayOfYear % 7; - - // Calculate the offset (how many days from the start of the year to the start of the week) - int offset = (firstDayOfWeek + 7 - dayOfWeekOfFirstOfYear) % 7; - if (offset == 0 || offset >= minimumDaysInFirstWeek) - { - // First of year falls in the first week of the year - return 1; - } - - int daysInYearBeforeMinSupportedYear = DaysInYearBeforeMinSupportedYear - 1; // Make the day of year to be 0-based, so that 1/1 is day 0. - int dayOfWeekOfFirstOfPreviousYear = dayOfWeekOfFirstOfYear - 1 - (daysInYearBeforeMinSupportedYear % 7); - - // starting from first day of the year, how many days do you have to go forward - // before getting to the first day of the week? - int daysInInitialPartialWeek = (firstDayOfWeek - dayOfWeekOfFirstOfPreviousYear + 14) % 7; - int day = daysInYearBeforeMinSupportedYear - daysInInitialPartialWeek; - if (daysInInitialPartialWeek >= minimumDaysInFirstWeek) - { - // If the offset is greater than the minimum Days in the first week, it means that - // First of year is part of the first week of the year even though it is only a partial week - // add another week - day += 7; - } - - return (day / 7 + 1); - } - - // it would be nice to make this abstract but we can't since that would break previous implementations - protected virtual int DaysInYearBeforeMinSupportedYear - { - get - { - return 365; - } - } - - - // Returns the week of year for the specified DateTime. The returned value is an - // integer between 1 and 53. - // - - public virtual int GetWeekOfYear(DateTime time, CalendarWeekRule rule, DayOfWeek firstDayOfWeek) - { - if ((int)firstDayOfWeek < 0 || (int)firstDayOfWeek > 6) - { - throw new ArgumentOutOfRangeException( - nameof(firstDayOfWeek), SR.Format(SR.ArgumentOutOfRange_Range, - DayOfWeek.Sunday, DayOfWeek.Saturday)); - } - Contract.EndContractBlock(); - switch (rule) - { - case CalendarWeekRule.FirstDay: - return (GetFirstDayWeekOfYear(time, (int)firstDayOfWeek)); - case CalendarWeekRule.FirstFullWeek: - return (GetWeekOfYearFullDays(time, (int)firstDayOfWeek, 7)); - case CalendarWeekRule.FirstFourDayWeek: - return (GetWeekOfYearFullDays(time, (int)firstDayOfWeek, 4)); - } - throw new ArgumentOutOfRangeException( - nameof(rule), SR.Format(SR.ArgumentOutOfRange_Range, - CalendarWeekRule.FirstDay, CalendarWeekRule.FirstFourDayWeek)); - } - - // Returns the year part of the specified DateTime. The returned value is an - // integer between 1 and 9999. - // - - public abstract int GetYear(DateTime time); - - // Checks whether a given day in the current era is a leap day. This method returns true if - // the date is a leap day, or false if not. - // - - public virtual bool IsLeapDay(int year, int month, int day) - { - return (IsLeapDay(year, month, day, CurrentEra)); - } - - // Checks whether a given day in the specified era is a leap day. This method returns true if - // the date is a leap day, or false if not. - // - - public abstract bool IsLeapDay(int year, int month, int day, int era); - - // Checks whether a given month in the current era is a leap month. This method returns true if - // month is a leap month, or false if not. - // - - public virtual bool IsLeapMonth(int year, int month) - { - return (IsLeapMonth(year, month, CurrentEra)); - } - - // Checks whether a given month in the specified era is a leap month. This method returns true if - // month is a leap month, or false if not. - // - - public abstract bool IsLeapMonth(int year, int month, int era); - - // Returns the leap month in a calendar year of the current era. This method returns 0 - // if this calendar does not have leap month, or this year is not a leap year. - // - - public virtual int GetLeapMonth(int year) - { - return (GetLeapMonth(year, CurrentEra)); - } - - // Returns the leap month in a calendar year of the specified era. This method returns 0 - // if this calendar does not have leap month, or this year is not a leap year. - // - - public virtual int GetLeapMonth(int year, int era) - { - if (!IsLeapYear(year, era)) - return 0; - - int monthsCount = GetMonthsInYear(year, era); - for (int month = 1; month <= monthsCount; month++) - { - if (IsLeapMonth(year, month, era)) - return month; - } - - return 0; - } - - // Checks whether a given year in the current era is a leap year. This method returns true if - // year is a leap year, or false if not. - // - - public virtual bool IsLeapYear(int year) - { - return (IsLeapYear(year, CurrentEra)); - } - - // Checks whether a given year in the specified era is a leap year. This method returns true if - // year is a leap year, or false if not. - // - - public abstract bool IsLeapYear(int year, int era); - - // Returns the date and time converted to a DateTime value. Throws an exception if the n-tuple is invalid. - // - - public virtual DateTime ToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond) - { - return (ToDateTime(year, month, day, hour, minute, second, millisecond, CurrentEra)); - } - - // Returns the date and time converted to a DateTime value. Throws an exception if the n-tuple is invalid. - // - - public abstract DateTime ToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era); - - internal virtual Boolean TryToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era, out DateTime result) - { - result = DateTime.MinValue; - try - { - result = ToDateTime(year, month, day, hour, minute, second, millisecond, era); - return true; - } - catch (ArgumentException) - { - return false; - } - } - - internal virtual bool IsValidYear(int year, int era) - { - return (year >= GetYear(MinSupportedDateTime) && year <= GetYear(MaxSupportedDateTime)); - } - - internal virtual bool IsValidMonth(int year, int month, int era) - { - return (IsValidYear(year, era) && month >= 1 && month <= GetMonthsInYear(year, era)); - } - - internal virtual bool IsValidDay(int year, int month, int day, int era) - { - return (IsValidMonth(year, month, era) && day >= 1 && day <= GetDaysInMonth(year, month, era)); - } - - - // Returns and assigns the maximum value to represent a two digit year. This - // value is the upper boundary of a 100 year range that allows a two digit year - // to be properly translated to a four digit year. For example, if 2029 is the - // upper boundary, then a two digit value of 30 should be interpreted as 1930 - // while a two digit value of 29 should be interpreted as 2029. In this example - // , the 100 year range would be from 1930-2029. See ToFourDigitYear(). - - public virtual int TwoDigitYearMax - { - get - { - return (twoDigitYearMax); - } - - set - { - VerifyWritable(); - twoDigitYearMax = value; - } - } - - // Converts the year value to the appropriate century by using the - // TwoDigitYearMax property. For example, if the TwoDigitYearMax value is 2029, - // then a two digit value of 30 will get converted to 1930 while a two digit - // value of 29 will get converted to 2029. - - public virtual int ToFourDigitYear(int year) - { - if (year < 0) - { - throw new ArgumentOutOfRangeException(nameof(year), - SR.ArgumentOutOfRange_NeedNonNegNum); - } - Contract.EndContractBlock(); - if (year < 100) - { - return ((TwoDigitYearMax / 100 - (year > TwoDigitYearMax % 100 ? 1 : 0)) * 100 + year); - } - // If the year value is above 100, just return the year value. Don't have to do - // the TwoDigitYearMax comparison. - return (year); - } - - // Return the tick count corresponding to the given hour, minute, second. - // Will check the if the parameters are valid. - internal static long TimeToTicks(int hour, int minute, int second, int millisecond) - { - if (hour >= 0 && hour < 24 && minute >= 0 && minute < 60 && second >= 0 && second < 60) - { - if (millisecond < 0 || millisecond >= MillisPerSecond) - { - throw new ArgumentOutOfRangeException( - nameof(millisecond), - String.Format( - CultureInfo.InvariantCulture, - SR.Format(SR.ArgumentOutOfRange_Range, 0, MillisPerSecond - 1))); - } - return InternalGloablizationHelper.TimeToTicks(hour, minute, second) + millisecond * TicksPerMillisecond; - } - throw new ArgumentOutOfRangeException(null, SR.ArgumentOutOfRange_BadHourMinuteSecond); - } - - internal static int GetSystemTwoDigitYearSetting(CalendarId CalID, int defaultYearValue) - { - // Call nativeGetTwoDigitYearMax - int twoDigitYearMax = CalendarData.GetTwoDigitYearMax(CalID); - if (twoDigitYearMax < 0) - { - twoDigitYearMax = defaultYearValue; - } - return (twoDigitYearMax); - } - } -} diff --git a/src/mscorlib/corefx/System/Globalization/CalendarAlgorithmType.cs b/src/mscorlib/corefx/System/Globalization/CalendarAlgorithmType.cs deleted file mode 100644 index 159b0e6..0000000 --- a/src/mscorlib/corefx/System/Globalization/CalendarAlgorithmType.cs +++ /dev/null @@ -1,20 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; - -namespace System.Globalization -{ - public enum CalendarAlgorithmType - { - Unknown = 0, // This is the default value to return in the Calendar base class. - SolarCalendar = 1, // Solar-base calendar, such as GregorianCalendar, jaoaneseCalendar, JulianCalendar, etc. - // Solar calendars are based on the solar year and seasons. - LunarCalendar = 2, // Lunar-based calendar, such as Hijri and UmAlQuraCalendar. - // Lunar calendars are based on the path of the moon. The seasons are not accurately represented. - LunisolarCalendar = 3 // Lunisolar-based calendar which use leap month rule, such as HebrewCalendar and Asian Lunisolar calendars. - // Lunisolar calendars are based on the cycle of the moon, but consider the seasons as a secondary consideration, - // so they align with the seasons as well as lunar events. - } -} diff --git a/src/mscorlib/corefx/System/Globalization/CalendarData.cs b/src/mscorlib/corefx/System/Globalization/CalendarData.cs deleted file mode 100644 index ad97ca9..0000000 --- a/src/mscorlib/corefx/System/Globalization/CalendarData.cs +++ /dev/null @@ -1,376 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System.Diagnostics; - -namespace System.Globalization -{ - // List of calendar data - // Note the we cache overrides. - // Note that localized names (resource names) aren't available from here. - // - // NOTE: Calendars depend on the locale name that creates it. Only a few - // properties are available without locales using CalendarData.GetCalendar(CalendarData) - - internal partial class CalendarData - { - // Max calendars - internal const int MAX_CALENDARS = 23; - - // Identity - internal String sNativeName; // Calendar Name for the locale - - // Formats - internal String[] saShortDates; // Short Data format, default first - internal String[] saYearMonths; // Year/Month Data format, default first - internal String[] saLongDates; // Long Data format, default first - internal String sMonthDay; // Month/Day format - - // Calendar Parts Names - internal String[] saEraNames; // Names of Eras - internal String[] saAbbrevEraNames; // Abbreviated Era Names - internal String[] saAbbrevEnglishEraNames; // Abbreviated Era Names in English - internal String[] saDayNames; // Day Names, null to use locale data, starts on Sunday - internal String[] saAbbrevDayNames; // Abbrev Day Names, null to use locale data, starts on Sunday - internal String[] saSuperShortDayNames; // Super short Day of week names - internal String[] saMonthNames; // Month Names (13) - internal String[] saAbbrevMonthNames; // Abbrev Month Names (13) - internal String[] saMonthGenitiveNames; // Genitive Month Names (13) - internal String[] saAbbrevMonthGenitiveNames; // Genitive Abbrev Month Names (13) - internal String[] saLeapYearMonthNames; // Multiple strings for the month names in a leap year. - - // Integers at end to make marshaller happier - internal int iTwoDigitYearMax = 2029; // Max 2 digit year (for Y2K bug data entry) - internal int iCurrentEra = 0; // current era # (usually 1) - - // Use overrides? - internal bool bUseUserOverrides; // True if we want user overrides. - - // Static invariant for the invariant locale - internal static readonly CalendarData Invariant = CreateInvariant(); - - // Private constructor - private CalendarData() { } - - // Invariant factory - private static CalendarData CreateInvariant() - { - // Set our default/gregorian US calendar data - // Calendar IDs are 1-based, arrays are 0 based. - CalendarData invariant = new CalendarData(); - - // Set default data for calendar - // Note that we don't load resources since this IS NOT supposed to change (by definition) - invariant.sNativeName = "Gregorian Calendar"; // Calendar Name - - // Year - invariant.iTwoDigitYearMax = 2029; // Max 2 digit year (for Y2K bug data entry) - invariant.iCurrentEra = 1; // Current era # - - // Formats - invariant.saShortDates = new String[] { "MM/dd/yyyy", "yyyy-MM-dd" }; // short date format - invariant.saLongDates = new String[] { "dddd, dd MMMM yyyy" }; // long date format - invariant.saYearMonths = new String[] { "yyyy MMMM" }; // year month format - invariant.sMonthDay = "MMMM dd"; // Month day pattern - - // Calendar Parts Names - invariant.saEraNames = new String[] { "A.D." }; // Era names - invariant.saAbbrevEraNames = new String[] { "AD" }; // Abbreviated Era names - invariant.saAbbrevEnglishEraNames = new String[] { "AD" }; // Abbreviated era names in English - invariant.saDayNames = new String[] { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" };// day names - invariant.saAbbrevDayNames = new String[] { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; // abbreviated day names - invariant.saSuperShortDayNames = new String[] { "Su", "Mo", "Tu", "We", "Th", "Fr", "Sa" }; // The super short day names - invariant.saMonthNames = new String[] { "January", "February", "March", "April", "May", "June", - "July", "August", "September", "October", "November", "December", String.Empty}; // month names - invariant.saAbbrevMonthNames = new String[] { "Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", String.Empty}; // abbreviated month names - invariant.saMonthGenitiveNames = invariant.saMonthNames; // Genitive month names (same as month names for invariant) - invariant.saAbbrevMonthGenitiveNames = invariant.saAbbrevMonthNames; // Abbreviated genitive month names (same as abbrev month names for invariant) - invariant.saLeapYearMonthNames = invariant.saMonthNames; // leap year month names are unused in Gregorian English (invariant) - - invariant.bUseUserOverrides = false; - - return invariant; - } - - // - // Get a bunch of data for a calendar - // - internal CalendarData(String localeName, CalendarId calendarId, bool bUseUserOverrides) - { - this.bUseUserOverrides = bUseUserOverrides; - - if (!LoadCalendarDataFromSystem(localeName, calendarId)) - { - Debug.Assert(false, "[CalendarData] LoadCalendarDataFromSystem call isn't expected to fail for calendar " + calendarId + " locale " + localeName); - - // Something failed, try invariant for missing parts - // This is really not good, but we don't want the callers to crash. - if (this.sNativeName == null) this.sNativeName = String.Empty; // Calendar Name for the locale. - - // Formats - if (this.saShortDates == null) this.saShortDates = Invariant.saShortDates; // Short Data format, default first - if (this.saYearMonths == null) this.saYearMonths = Invariant.saYearMonths; // Year/Month Data format, default first - if (this.saLongDates == null) this.saLongDates = Invariant.saLongDates; // Long Data format, default first - if (this.sMonthDay == null) this.sMonthDay = Invariant.sMonthDay; // Month/Day format - - // Calendar Parts Names - if (this.saEraNames == null) this.saEraNames = Invariant.saEraNames; // Names of Eras - if (this.saAbbrevEraNames == null) this.saAbbrevEraNames = Invariant.saAbbrevEraNames; // Abbreviated Era Names - if (this.saAbbrevEnglishEraNames == null) this.saAbbrevEnglishEraNames = Invariant.saAbbrevEnglishEraNames; // Abbreviated Era Names in English - if (this.saDayNames == null) this.saDayNames = Invariant.saDayNames; // Day Names, null to use locale data, starts on Sunday - if (this.saAbbrevDayNames == null) this.saAbbrevDayNames = Invariant.saAbbrevDayNames; // Abbrev Day Names, null to use locale data, starts on Sunday - if (this.saSuperShortDayNames == null) this.saSuperShortDayNames = Invariant.saSuperShortDayNames; // Super short Day of week names - if (this.saMonthNames == null) this.saMonthNames = Invariant.saMonthNames; // Month Names (13) - if (this.saAbbrevMonthNames == null) this.saAbbrevMonthNames = Invariant.saAbbrevMonthNames; // Abbrev Month Names (13) - // Genitive and Leap names can follow the fallback below - } - - if (calendarId == CalendarId.TAIWAN) - { - if (SystemSupportsTaiwaneseCalendar()) - { - // We got the month/day names from the OS (same as gregorian), but the native name is wrong - this.sNativeName = "\x4e2d\x83ef\x6c11\x570b\x66c6"; - } - else - { - this.sNativeName = String.Empty; - } - } - - // Check for null genitive names (in case unmanaged side skips it for non-gregorian calendars, etc) - if (this.saMonthGenitiveNames == null || this.saMonthGenitiveNames.Length == 0 || String.IsNullOrEmpty(this.saMonthGenitiveNames[0])) - this.saMonthGenitiveNames = this.saMonthNames; // Genitive month names (same as month names for invariant) - if (this.saAbbrevMonthGenitiveNames == null || this.saAbbrevMonthGenitiveNames.Length == 0 || String.IsNullOrEmpty(this.saAbbrevMonthGenitiveNames[0])) - this.saAbbrevMonthGenitiveNames = this.saAbbrevMonthNames; // Abbreviated genitive month names (same as abbrev month names for invariant) - if (this.saLeapYearMonthNames == null || this.saLeapYearMonthNames.Length == 0 || String.IsNullOrEmpty(this.saLeapYearMonthNames[0])) - this.saLeapYearMonthNames = this.saMonthNames; - - InitializeEraNames(localeName, calendarId); - - InitializeAbbreviatedEraNames(localeName, calendarId); - - // Abbreviated English Era Names are only used for the Japanese calendar. - if (calendarId == CalendarId.JAPAN) - { - this.saAbbrevEnglishEraNames = JapaneseCalendar.EnglishEraNames(); - } - else - { - // For all others just use the an empty string (doesn't matter we'll never ask for it for other calendars) - this.saAbbrevEnglishEraNames = new String[] { "" }; - } - - // Japanese is the only thing with > 1 era. Its current era # is how many ever - // eras are in the array. (And the others all have 1 string in the array) - this.iCurrentEra = this.saEraNames.Length; - } - - private void InitializeEraNames(string localeName, CalendarId calendarId) - { - // Note that the saEraNames only include "A.D." We don't have localized names for other calendars available from windows - switch (calendarId) - { - // For Localized Gregorian we really expect the data from the OS. - case CalendarId.GREGORIAN: - // Fallback for CoreCLR < Win7 or culture.dll missing - if (this.saEraNames == null || this.saEraNames.Length == 0 || String.IsNullOrEmpty(this.saEraNames[0])) - { - this.saEraNames = new String[] { "A.D." }; - } - break; - - // The rest of the calendars have constant data, so we'll just use that - case CalendarId.GREGORIAN_US: - case CalendarId.JULIAN: - this.saEraNames = new String[] { "A.D." }; - break; - case CalendarId.HEBREW: - this.saEraNames = new String[] { "C.E." }; - break; - case CalendarId.HIJRI: - case CalendarId.UMALQURA: - if (localeName == "dv-MV") - { - // Special case for Divehi - this.saEraNames = new String[] { "\x0780\x07a8\x0796\x07b0\x0783\x07a9" }; - } - else - { - this.saEraNames = new String[] { "\x0628\x0639\x062F \x0627\x0644\x0647\x062C\x0631\x0629" }; - } - break; - case CalendarId.GREGORIAN_ARABIC: - case CalendarId.GREGORIAN_XLIT_ENGLISH: - case CalendarId.GREGORIAN_XLIT_FRENCH: - // These are all the same: - this.saEraNames = new String[] { "\x0645" }; - break; - - case CalendarId.GREGORIAN_ME_FRENCH: - this.saEraNames = new String[] { "ap. J.-C." }; - break; - - case CalendarId.TAIWAN: - if (SystemSupportsTaiwaneseCalendar()) - { - this.saEraNames = new String[] { "\x4e2d\x83ef\x6c11\x570b" }; - } - else - { - this.saEraNames = new String[] { String.Empty }; - } - break; - - case CalendarId.KOREA: - this.saEraNames = new String[] { "\xb2e8\xae30" }; - break; - - case CalendarId.THAI: - this.saEraNames = new String[] { "\x0e1e\x002e\x0e28\x002e" }; - break; - - case CalendarId.JAPAN: - case CalendarId.JAPANESELUNISOLAR: - this.saEraNames = JapaneseCalendar.EraNames(); - break; - - case CalendarId.PERSIAN: - if (this.saEraNames == null || this.saEraNames.Length == 0 || String.IsNullOrEmpty(this.saEraNames[0])) - { - this.saEraNames = new String[] { "\x0647\x002e\x0634" }; - } - break; - - default: - // Most calendars are just "A.D." - this.saEraNames = Invariant.saEraNames; - break; - } - } - - private void InitializeAbbreviatedEraNames(string localeName, CalendarId calendarId) - { - // Note that the saAbbrevEraNames only include "AD" We don't have localized names for other calendars available from windows - switch (calendarId) - { - // For Localized Gregorian we really expect the data from the OS. - case CalendarId.GREGORIAN: - // Fallback for CoreCLR < Win7 or culture.dll missing - if (this.saAbbrevEraNames == null || this.saAbbrevEraNames.Length == 0 || String.IsNullOrEmpty(this.saAbbrevEraNames[0])) - { - this.saAbbrevEraNames = new String[] { "AD" }; - } - break; - - // The rest of the calendars have constant data, so we'll just use that - case CalendarId.GREGORIAN_US: - case CalendarId.JULIAN: - this.saAbbrevEraNames = new String[] { "AD" }; - break; - case CalendarId.JAPAN: - case CalendarId.JAPANESELUNISOLAR: - this.saAbbrevEraNames = JapaneseCalendar.AbbrevEraNames(); - break; - case CalendarId.HIJRI: - case CalendarId.UMALQURA: - if (localeName == "dv-MV") - { - // Special case for Divehi - this.saAbbrevEraNames = new String[] { "\x0780\x002e" }; - } - else - { - this.saAbbrevEraNames = new String[] { "\x0647\x0640" }; - } - break; - case CalendarId.TAIWAN: - // Get era name and abbreviate it - this.saAbbrevEraNames = new String[1]; - if (this.saEraNames[0].Length == 4) - { - this.saAbbrevEraNames[0] = this.saEraNames[0].Substring(2, 2); - } - else - { - this.saAbbrevEraNames[0] = this.saEraNames[0]; - } - break; - - case CalendarId.PERSIAN: - if (this.saAbbrevEraNames == null || this.saAbbrevEraNames.Length == 0 || String.IsNullOrEmpty(this.saAbbrevEraNames[0])) - { - this.saAbbrevEraNames = this.saEraNames; - } - break; - - default: - // Most calendars just use the full name - this.saAbbrevEraNames = this.saEraNames; - break; - } - } - - internal static CalendarData GetCalendarData(CalendarId calendarId) - { - // - // Get a calendar. - // Unfortunately we depend on the locale in the OS, so we need a locale - // no matter what. So just get the appropriate calendar from the - // appropriate locale here - // - - // Get a culture name - // TODO: Note that this doesn't handle the new calendars (lunisolar, etc) - String culture = CalendarIdToCultureName(calendarId); - - // Return our calendar - return CultureInfo.GetCultureInfo(culture).m_cultureData.GetCalendar(calendarId); - } - - private static String CalendarIdToCultureName(CalendarId calendarId) - { - switch (calendarId) - { - case CalendarId.GREGORIAN_US: - return "fa-IR"; // "fa-IR" Iran - - case CalendarId.JAPAN: - return "ja-JP"; // "ja-JP" Japan - - case CalendarId.TAIWAN: - return "zh-TW"; // zh-TW Taiwan - - case CalendarId.KOREA: - return "ko-KR"; // "ko-KR" Korea - - case CalendarId.HIJRI: - case CalendarId.GREGORIAN_ARABIC: - case CalendarId.UMALQURA: - return "ar-SA"; // "ar-SA" Saudi Arabia - - case CalendarId.THAI: - return "th-TH"; // "th-TH" Thailand - - case CalendarId.HEBREW: - return "he-IL"; // "he-IL" Israel - - case CalendarId.GREGORIAN_ME_FRENCH: - return "ar-DZ"; // "ar-DZ" Algeria - - case CalendarId.GREGORIAN_XLIT_ENGLISH: - case CalendarId.GREGORIAN_XLIT_FRENCH: - return "ar-IQ"; // "ar-IQ"; Iraq - - default: - // Default to gregorian en-US - break; - } - - return "en-US"; - } - } -} - diff --git a/src/mscorlib/corefx/System/Globalization/CalendarWeekRule.cs b/src/mscorlib/corefx/System/Globalization/CalendarWeekRule.cs deleted file mode 100644 index 4013ce7..0000000 --- a/src/mscorlib/corefx/System/Globalization/CalendarWeekRule.cs +++ /dev/null @@ -1,18 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; - -namespace System.Globalization -{ - [Serializable] - public enum CalendarWeekRule - { - FirstDay = 0, // Week 1 begins on the first day of the year - - FirstFullWeek = 1, // Week 1 begins on first FirstDayOfWeek not before the first day of the year - - FirstFourDayWeek = 2 // Week 1 begins on first FirstDayOfWeek such that FirstDayOfWeek+3 is not before the first day of the year - }; -} diff --git a/src/mscorlib/corefx/System/Globalization/CalendricalCalculationsHelper.cs b/src/mscorlib/corefx/System/Globalization/CalendricalCalculationsHelper.cs deleted file mode 100644 index 7de75d6..0000000 --- a/src/mscorlib/corefx/System/Globalization/CalendricalCalculationsHelper.cs +++ /dev/null @@ -1,412 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System.Diagnostics; - -namespace System.Globalization -{ - internal class CalendricalCalculationsHelper - { - private const double FullCircleOfArc = 360.0; // 360.0; - private const int HalfCircleOfArc = 180; - private const double TwelveHours = 0.5; // half a day - private const double Noon2000Jan01 = 730120.5; - internal const double MeanTropicalYearInDays = 365.242189; - private const double MeanSpeedOfSun = MeanTropicalYearInDays / FullCircleOfArc; - private const double LongitudeSpring = 0.0; - private const double TwoDegreesAfterSpring = 2.0; - private const int SecondsPerDay = 24 * 60 * 60; // 24 hours * 60 minutes * 60 seconds - - private const int DaysInUniformLengthCentury = 36525; - private const int SecondsPerMinute = 60; - private const int MinutesPerDegree = 60; - - private static readonly long s_startOf1810 = GetNumberOfDays(new DateTime(1810, 1, 1)); - private static readonly long s_startOf1900Century = GetNumberOfDays(new DateTime(1900, 1, 1)); - - private static readonly double[] s_coefficients1900to1987 = new double[] { -0.00002, 0.000297, 0.025184, -0.181133, 0.553040, -0.861938, 0.677066, -0.212591 }; - private static readonly double[] s_coefficients1800to1899 = new double[] { -0.000009, 0.003844, 0.083563, 0.865736, 4.867575, 15.845535, 31.332267, 38.291999, 28.316289, 11.636204, 2.043794 }; - private static readonly double[] s_coefficients1700to1799 = new double[] { 8.118780842, -0.005092142, 0.003336121, -0.0000266484 }; - private static readonly double[] s_coefficients1620to1699 = new double[] { 196.58333, -4.0675, 0.0219167 }; - private static readonly double[] s_lambdaCoefficients = new double[] { 280.46645, 36000.76983, 0.0003032 }; - private static readonly double[] s_anomalyCoefficients = new double[] { 357.52910, 35999.05030, -0.0001559, -0.00000048 }; - private static readonly double[] s_eccentricityCoefficients = new double[] { 0.016708617, -0.000042037, -0.0000001236 }; - private static readonly double[] s_coefficients = new double[] { Angle(23, 26, 21.448), Angle(0, 0, -46.8150), Angle(0, 0, -0.00059), Angle(0, 0, 0.001813) }; - private static readonly double[] s_coefficientsA = new double[] { 124.90, -1934.134, 0.002063 }; - private static readonly double[] s_coefficientsB = new double[] { 201.11, 72001.5377, 0.00057 }; - - private static double RadiansFromDegrees(double degree) - { - return degree * Math.PI / 180; - } - - private static double SinOfDegree(double degree) - { - return Math.Sin(RadiansFromDegrees(degree)); - } - - private static double CosOfDegree(double degree) - { - return Math.Cos(RadiansFromDegrees(degree)); - } - private static double TanOfDegree(double degree) - { - return Math.Tan(RadiansFromDegrees(degree)); - } - - public static double Angle(int degrees, int minutes, double seconds) - { - return ((seconds / SecondsPerMinute + minutes) / MinutesPerDegree) + degrees; - } - - private static double Obliquity(double julianCenturies) - { - return PolynomialSum(s_coefficients, julianCenturies); - } - - internal static long GetNumberOfDays(DateTime date) - { - return date.Ticks / GregorianCalendar.TicksPerDay; - } - - private static int GetGregorianYear(double numberOfDays) - { - return new DateTime(Math.Min((long)(Math.Floor(numberOfDays) * GregorianCalendar.TicksPerDay), DateTime.MaxValue.Ticks)).Year; - } - - private enum CorrectionAlgorithm - { - Default, - Year1988to2019, - Year1900to1987, - Year1800to1899, - Year1700to1799, - Year1620to1699 - } - - private struct EphemerisCorrectionAlgorithmMap - { - public EphemerisCorrectionAlgorithmMap(int year, CorrectionAlgorithm algorithm) - { - _lowestYear = year; - _algorithm = algorithm; - } - - internal int _lowestYear; - internal CorrectionAlgorithm _algorithm; - }; - - private static readonly EphemerisCorrectionAlgorithmMap[] s_ephemerisCorrectionTable = new EphemerisCorrectionAlgorithmMap[] - { - // lowest year that starts algorithm, algorithm to use - new EphemerisCorrectionAlgorithmMap(2020, CorrectionAlgorithm.Default), - new EphemerisCorrectionAlgorithmMap(1988, CorrectionAlgorithm.Year1988to2019), - new EphemerisCorrectionAlgorithmMap(1900, CorrectionAlgorithm.Year1900to1987), - new EphemerisCorrectionAlgorithmMap(1800, CorrectionAlgorithm.Year1800to1899), - new EphemerisCorrectionAlgorithmMap(1700, CorrectionAlgorithm.Year1700to1799), - new EphemerisCorrectionAlgorithmMap(1620, CorrectionAlgorithm.Year1620to1699), - new EphemerisCorrectionAlgorithmMap(int.MinValue, CorrectionAlgorithm.Default) // default must be last - }; - - private static double Reminder(double divisor, double dividend) - { - double whole = Math.Floor(divisor / dividend); - return divisor - (dividend * whole); - } - - private static double NormalizeLongitude(double longitude) - { - longitude = Reminder(longitude, FullCircleOfArc); - if (longitude < 0) - { - longitude += FullCircleOfArc; - } - return longitude; - } - - public static double AsDayFraction(double longitude) - { - return longitude / FullCircleOfArc; - } - - private static double PolynomialSum(double[] coefficients, double indeterminate) - { - double sum = coefficients[0]; - double indeterminateRaised = 1; - for (int i = 1; i < coefficients.Length; i++) - { - indeterminateRaised *= indeterminate; - sum += (coefficients[i] * indeterminateRaised); - } - - return sum; - } - - private static double CenturiesFrom1900(int gregorianYear) - { - long july1stOfYear = GetNumberOfDays(new DateTime(gregorianYear, 7, 1)); - return (double)(july1stOfYear - s_startOf1900Century) / DaysInUniformLengthCentury; - } - - // the following formulas defines a polynomial function which gives us the amount that the earth is slowing down for specific year ranges - private static double DefaultEphemerisCorrection(int gregorianYear) - { - Debug.Assert(gregorianYear < 1620 || 2020 <= gregorianYear); - long january1stOfYear = GetNumberOfDays(new DateTime(gregorianYear, 1, 1)); - double daysSinceStartOf1810 = january1stOfYear - s_startOf1810; - double x = TwelveHours + daysSinceStartOf1810; - return ((Math.Pow(x, 2) / 41048480) - 15) / SecondsPerDay; - } - - private static double EphemerisCorrection1988to2019(int gregorianYear) - { - Debug.Assert(1988 <= gregorianYear && gregorianYear <= 2019); - return (double)(gregorianYear - 1933) / SecondsPerDay; - } - - private static double EphemerisCorrection1900to1987(int gregorianYear) - { - Debug.Assert(1900 <= gregorianYear && gregorianYear <= 1987); - double centuriesFrom1900 = CenturiesFrom1900(gregorianYear); - return PolynomialSum(s_coefficients1900to1987, centuriesFrom1900); - } - - private static double EphemerisCorrection1800to1899(int gregorianYear) - { - Debug.Assert(1800 <= gregorianYear && gregorianYear <= 1899); - double centuriesFrom1900 = CenturiesFrom1900(gregorianYear); - return PolynomialSum(s_coefficients1800to1899, centuriesFrom1900); - } - - private static double EphemerisCorrection1700to1799(int gregorianYear) - { - Debug.Assert(1700 <= gregorianYear && gregorianYear <= 1799); - double yearsSince1700 = gregorianYear - 1700; - return PolynomialSum(s_coefficients1700to1799, yearsSince1700) / SecondsPerDay; - } - - private static double EphemerisCorrection1620to1699(int gregorianYear) - { - Debug.Assert(1620 <= gregorianYear && gregorianYear <= 1699); - double yearsSince1600 = gregorianYear - 1600; - return PolynomialSum(s_coefficients1620to1699, yearsSince1600) / SecondsPerDay; - } - - // ephemeris-correction: correction to account for the slowing down of the rotation of the earth - private static double EphemerisCorrection(double time) - { - int year = GetGregorianYear(time); - foreach (EphemerisCorrectionAlgorithmMap map in s_ephemerisCorrectionTable) - { - if (map._lowestYear <= year) - { - switch (map._algorithm) - { - case CorrectionAlgorithm.Default: return DefaultEphemerisCorrection(year); - case CorrectionAlgorithm.Year1988to2019: return EphemerisCorrection1988to2019(year); - case CorrectionAlgorithm.Year1900to1987: return EphemerisCorrection1900to1987(year); - case CorrectionAlgorithm.Year1800to1899: return EphemerisCorrection1800to1899(year); - case CorrectionAlgorithm.Year1700to1799: return EphemerisCorrection1700to1799(year); - case CorrectionAlgorithm.Year1620to1699: return EphemerisCorrection1620to1699(year); - } - - break; // break the loop and assert eventually - } - } - - Debug.Assert(false, "Not expected to come here"); - return DefaultEphemerisCorrection(year); - } - - public static double JulianCenturies(double moment) - { - double dynamicalMoment = moment + EphemerisCorrection(moment); - return (dynamicalMoment - Noon2000Jan01) / DaysInUniformLengthCentury; - } - - private static bool IsNegative(double value) - { - return Math.Sign(value) == -1; - } - - private static double CopySign(double value, double sign) - { - return (IsNegative(value) == IsNegative(sign)) ? value : -value; - } - - // equation-of-time; approximate the difference between apparent solar time and mean solar time - // formal definition is EOT = GHA - GMHA - // GHA is the Greenwich Hour Angle of the apparent (actual) Sun - // GMHA is the Greenwich Mean Hour Angle of the mean (fictitious) Sun - // http://www.esrl.noaa.gov/gmd/grad/solcalc/ - // http://en.wikipedia.org/wiki/Equation_of_time - private static double EquationOfTime(double time) - { - double julianCenturies = JulianCenturies(time); - double lambda = PolynomialSum(s_lambdaCoefficients, julianCenturies); - double anomaly = PolynomialSum(s_anomalyCoefficients, julianCenturies); - double eccentricity = PolynomialSum(s_eccentricityCoefficients, julianCenturies); - - double epsilon = Obliquity(julianCenturies); - double tanHalfEpsilon = TanOfDegree(epsilon / 2); - double y = tanHalfEpsilon * tanHalfEpsilon; - - double dividend = ((y * SinOfDegree(2 * lambda)) - - (2 * eccentricity * SinOfDegree(anomaly)) - + (4 * eccentricity * y * SinOfDegree(anomaly) * CosOfDegree(2 * lambda)) - - (0.5 * Math.Pow(y, 2) * SinOfDegree(4 * lambda)) - - (1.25 * Math.Pow(eccentricity, 2) * SinOfDegree(2 * anomaly))); - double divisor = 2 * Math.PI; - double equation = dividend / divisor; - - // approximation of equation of time is not valid for dates that are many millennia in the past or future - // thus limited to a half day - return CopySign(Math.Min(Math.Abs(equation), TwelveHours), equation); - } - - private static double AsLocalTime(double apparentMidday, double longitude) - { - // slightly inaccurate since equation of time takes mean time not apparent time as its argument, but the difference is negligible - double universalTime = apparentMidday - AsDayFraction(longitude); - return apparentMidday - EquationOfTime(universalTime); - } - - // midday - public static double Midday(double date, double longitude) - { - return AsLocalTime(date + TwelveHours, longitude) - AsDayFraction(longitude); - } - - private static double InitLongitude(double longitude) - { - return NormalizeLongitude(longitude + HalfCircleOfArc) - HalfCircleOfArc; - } - - // midday-in-tehran - public static double MiddayAtPersianObservationSite(double date) - { - return Midday(date, InitLongitude(52.5)); // 52.5 degrees east - longitude of UTC+3:30 which defines Iranian Standard Time - } - - private static double PeriodicTerm(double julianCenturies, int x, double y, double z) - { - return x * SinOfDegree(y + z * julianCenturies); - } - - private static double SumLongSequenceOfPeriodicTerms(double julianCenturies) - { - double sum = 0.0; - sum += PeriodicTerm(julianCenturies, 403406, 270.54861, 0.9287892); - sum += PeriodicTerm(julianCenturies, 195207, 340.19128, 35999.1376958); - sum += PeriodicTerm(julianCenturies, 119433, 63.91854, 35999.4089666); - sum += PeriodicTerm(julianCenturies, 112392, 331.2622, 35998.7287385); - sum += PeriodicTerm(julianCenturies, 3891, 317.843, 71998.20261); - sum += PeriodicTerm(julianCenturies, 2819, 86.631, 71998.4403); - sum += PeriodicTerm(julianCenturies, 1721, 240.052, 36000.35726); - sum += PeriodicTerm(julianCenturies, 660, 310.26, 71997.4812); - sum += PeriodicTerm(julianCenturies, 350, 247.23, 32964.4678); - sum += PeriodicTerm(julianCenturies, 334, 260.87, -19.441); - sum += PeriodicTerm(julianCenturies, 314, 297.82, 445267.1117); - sum += PeriodicTerm(julianCenturies, 268, 343.14, 45036.884); - sum += PeriodicTerm(julianCenturies, 242, 166.79, 3.1008); - sum += PeriodicTerm(julianCenturies, 234, 81.53, 22518.4434); - sum += PeriodicTerm(julianCenturies, 158, 3.5, -19.9739); - sum += PeriodicTerm(julianCenturies, 132, 132.75, 65928.9345); - sum += PeriodicTerm(julianCenturies, 129, 182.95, 9038.0293); - sum += PeriodicTerm(julianCenturies, 114, 162.03, 3034.7684); - sum += PeriodicTerm(julianCenturies, 99, 29.8, 33718.148); - sum += PeriodicTerm(julianCenturies, 93, 266.4, 3034.448); - sum += PeriodicTerm(julianCenturies, 86, 249.2, -2280.773); - sum += PeriodicTerm(julianCenturies, 78, 157.6, 29929.992); - sum += PeriodicTerm(julianCenturies, 72, 257.8, 31556.493); - sum += PeriodicTerm(julianCenturies, 68, 185.1, 149.588); - sum += PeriodicTerm(julianCenturies, 64, 69.9, 9037.75); - sum += PeriodicTerm(julianCenturies, 46, 8.0, 107997.405); - sum += PeriodicTerm(julianCenturies, 38, 197.1, -4444.176); - sum += PeriodicTerm(julianCenturies, 37, 250.4, 151.771); - sum += PeriodicTerm(julianCenturies, 32, 65.3, 67555.316); - sum += PeriodicTerm(julianCenturies, 29, 162.7, 31556.08); - sum += PeriodicTerm(julianCenturies, 28, 341.5, -4561.54); - sum += PeriodicTerm(julianCenturies, 27, 291.6, 107996.706); - sum += PeriodicTerm(julianCenturies, 27, 98.5, 1221.655); - sum += PeriodicTerm(julianCenturies, 25, 146.7, 62894.167); - sum += PeriodicTerm(julianCenturies, 24, 110.0, 31437.369); - sum += PeriodicTerm(julianCenturies, 21, 5.2, 14578.298); - sum += PeriodicTerm(julianCenturies, 21, 342.6, -31931.757); - sum += PeriodicTerm(julianCenturies, 20, 230.9, 34777.243); - sum += PeriodicTerm(julianCenturies, 18, 256.1, 1221.999); - sum += PeriodicTerm(julianCenturies, 17, 45.3, 62894.511); - sum += PeriodicTerm(julianCenturies, 14, 242.9, -4442.039); - sum += PeriodicTerm(julianCenturies, 13, 115.2, 107997.909); - sum += PeriodicTerm(julianCenturies, 13, 151.8, 119.066); - sum += PeriodicTerm(julianCenturies, 13, 285.3, 16859.071); - sum += PeriodicTerm(julianCenturies, 12, 53.3, -4.578); - sum += PeriodicTerm(julianCenturies, 10, 126.6, 26895.292); - sum += PeriodicTerm(julianCenturies, 10, 205.7, -39.127); - sum += PeriodicTerm(julianCenturies, 10, 85.9, 12297.536); - sum += PeriodicTerm(julianCenturies, 10, 146.1, 90073.778); - return sum; - } - - private static double Aberration(double julianCenturies) - { - return (0.0000974 * CosOfDegree(177.63 + (35999.01848 * julianCenturies))) - 0.005575; - } - - private static double Nutation(double julianCenturies) - { - double a = PolynomialSum(s_coefficientsA, julianCenturies); - double b = PolynomialSum(s_coefficientsB, julianCenturies); - return (-0.004778 * SinOfDegree(a)) - (0.0003667 * SinOfDegree(b)); - } - - public static double Compute(double time) - { - double julianCenturies = JulianCenturies(time); - double lambda = 282.7771834 - + (36000.76953744 * julianCenturies) - + (0.000005729577951308232 * SumLongSequenceOfPeriodicTerms(julianCenturies)); - - double longitude = lambda + Aberration(julianCenturies) + Nutation(julianCenturies); - return InitLongitude(longitude); - } - - public static double AsSeason(double longitude) - { - return (longitude < 0) ? (longitude + FullCircleOfArc) : longitude; - } - - private static double EstimatePrior(double longitude, double time) - { - double timeSunLastAtLongitude = time - (MeanSpeedOfSun * AsSeason(InitLongitude(Compute(time) - longitude))); - double longitudeErrorDelta = InitLongitude(Compute(timeSunLastAtLongitude) - longitude); - return Math.Min(time, timeSunLastAtLongitude - (MeanSpeedOfSun * longitudeErrorDelta)); - } - - // persian-new-year-on-or-before - // number of days is the absolute date. The absolute date is the number of days from January 1st, 1 A.D. - // 1/1/0001 is absolute date 1. - internal static long PersianNewYearOnOrBefore(long numberOfDays) - { - double date = (double)numberOfDays; - - double approx = EstimatePrior(LongitudeSpring, MiddayAtPersianObservationSite(date)); - long lowerBoundNewYearDay = (long)Math.Floor(approx) - 1; - long upperBoundNewYearDay = lowerBoundNewYearDay + 3; // estimate is generally within a day of the actual occurrance (at the limits, the error expands, since the calculations rely on the mean tropical year which changes...) - long day = lowerBoundNewYearDay; - for (; day != upperBoundNewYearDay; ++day) - { - double midday = MiddayAtPersianObservationSite((double)day); - double l = Compute(midday); - if ((LongitudeSpring <= l) && (l <= TwoDegreesAfterSpring)) - { - break; - } - } - Debug.Assert(day != upperBoundNewYearDay); - - return day - 1; - } - } -} diff --git a/src/mscorlib/corefx/System/Globalization/CharUnicodeInfo.cs b/src/mscorlib/corefx/System/Globalization/CharUnicodeInfo.cs deleted file mode 100644 index 38ce441..0000000 --- a/src/mscorlib/corefx/System/Globalization/CharUnicodeInfo.cs +++ /dev/null @@ -1,391 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -//////////////////////////////////////////////////////////////////////////// -// -// -// Purpose: This class implements a set of methods for retrieving -// character type information. Character type information is -// independent of culture and region. -// -// -//////////////////////////////////////////////////////////////////////////// - -using System.Diagnostics; -using System.Diagnostics.Contracts; - -namespace System.Globalization -{ - public static partial class CharUnicodeInfo - { - //--------------------------------------------------------------------// - // Internal Information // - //--------------------------------------------------------------------// - - // - // Native methods to access the Unicode category data tables in charinfo.nlp. - // - internal const char HIGH_SURROGATE_START = '\ud800'; - internal const char HIGH_SURROGATE_END = '\udbff'; - internal const char LOW_SURROGATE_START = '\udc00'; - internal const char LOW_SURROGATE_END = '\udfff'; - - internal const int UNICODE_CATEGORY_OFFSET = 0; - internal const int BIDI_CATEGORY_OFFSET = 1; - - - - // The starting codepoint for Unicode plane 1. Plane 1 contains 0x010000 ~ 0x01ffff. - internal const int UNICODE_PLANE01_START = 0x10000; - - - //////////////////////////////////////////////////////////////////////// - // - // Actions: - // Convert the BMP character or surrogate pointed by index to a UTF32 value. - // This is similar to Char.ConvertToUTF32, but the difference is that - // it does not throw exceptions when invalid surrogate characters are passed in. - // - // WARNING: since it doesn't throw an exception it CAN return a value - // in the surrogate range D800-DFFF, which are not legal unicode values. - // - //////////////////////////////////////////////////////////////////////// - - internal static int InternalConvertToUtf32(String s, int index) - { - Debug.Assert(s != null, "s != null"); - Debug.Assert(index >= 0 && index < s.Length, "index < s.Length"); - if (index < s.Length - 1) - { - int temp1 = (int)s[index] - HIGH_SURROGATE_START; - if (temp1 >= 0 && temp1 <= 0x3ff) - { - int temp2 = (int)s[index + 1] - LOW_SURROGATE_START; - if (temp2 >= 0 && temp2 <= 0x3ff) - { - // Convert the surrogate to UTF32 and get the result. - return ((temp1 * 0x400) + temp2 + UNICODE_PLANE01_START); - } - } - } - return ((int)s[index]); - } - //////////////////////////////////////////////////////////////////////// - // - // Convert a character or a surrogate pair starting at index of string s - // to UTF32 value. - // - // Parameters: - // s The string - // index The starting index. It can point to a BMP character or - // a surrogate pair. - // len The length of the string. - // charLength [out] If the index points to a BMP char, charLength - // will be 1. If the index points to a surrogate pair, - // charLength will be 2. - // - // WARNING: since it doesn't throw an exception it CAN return a value - // in the surrogate range D800-DFFF, which are not legal unicode values. - // - // Returns: - // The UTF32 value - // - //////////////////////////////////////////////////////////////////////// - - internal static int InternalConvertToUtf32(String s, int index, out int charLength) - { - Debug.Assert(s != null, "s != null"); - Debug.Assert(s.Length > 0, "s.Length > 0"); - Debug.Assert(index >= 0 && index < s.Length, "index >= 0 && index < s.Length"); - charLength = 1; - if (index < s.Length - 1) - { - int temp1 = (int)s[index] - HIGH_SURROGATE_START; - if (temp1 >= 0 && temp1 <= 0x3ff) - { - int temp2 = (int)s[index + 1] - LOW_SURROGATE_START; - if (temp2 >= 0 && temp2 <= 0x3ff) - { - // Convert the surrogate to UTF32 and get the result. - charLength++; - return ((temp1 * 0x400) + temp2 + UNICODE_PLANE01_START); - } - } - } - return ((int)s[index]); - } - - //////////////////////////////////////////////////////////////////////// - // - // IsWhiteSpace - // - // Determines if the given character is a white space character. - // - //////////////////////////////////////////////////////////////////////// - - internal static bool IsWhiteSpace(String s, int index) - { - Debug.Assert(s != null, "s!=null"); - Debug.Assert(index >= 0 && index < s.Length, "index >= 0 && index < s.Length"); - - UnicodeCategory uc = GetUnicodeCategory(s, index); - // In Unicode 3.0, U+2028 is the only character which is under the category "LineSeparator". - // And U+2029 is th eonly character which is under the category "ParagraphSeparator". - switch (uc) - { - case (UnicodeCategory.SpaceSeparator): - case (UnicodeCategory.LineSeparator): - case (UnicodeCategory.ParagraphSeparator): - return (true); - } - return (false); - } - - - internal static bool IsWhiteSpace(char c) - { - UnicodeCategory uc = GetUnicodeCategory(c); - // In Unicode 3.0, U+2028 is the only character which is under the category "LineSeparator". - // And U+2029 is th eonly character which is under the category "ParagraphSeparator". - switch (uc) - { - case (UnicodeCategory.SpaceSeparator): - case (UnicodeCategory.LineSeparator): - case (UnicodeCategory.ParagraphSeparator): - return (true); - } - - return (false); - } - - - // - // This is called by the public char and string, index versions - // - // Note that for ch in the range D800-DFFF we just treat it as any other non-numeric character - // - internal static unsafe double InternalGetNumericValue(int ch) - { - Debug.Assert(ch >= 0 && ch <= 0x10ffff, "ch is not in valid Unicode range."); - // Get the level 2 item from the highest 12 bit (8 - 19) of ch. - ushort index = s_pNumericLevel1Index[ch >> 8]; - // Get the level 2 WORD offset from the 4 - 7 bit of ch. This provides the base offset of the level 3 table. - // The offset is referred to an float item in m_pNumericFloatData. - // Note that & has the lower precedence than addition, so don't forget the parathesis. - index = s_pNumericLevel1Index[index + ((ch >> 4) & 0x000f)]; - - fixed (ushort* pUshortPtr = &(s_pNumericLevel1Index[index])) - { - byte* pBytePtr = (byte*)pUshortPtr; - fixed (byte* pByteNum = s_pNumericValues) - { - double* pDouble = (double*)pByteNum; - return pDouble[pBytePtr[(ch & 0x000f)]]; - } - } - } - - internal static unsafe ushort InternalGetDigitValues(int ch) - { - Debug.Assert(ch >= 0 && ch <= 0x10ffff, "ch is not in valid Unicode range."); - // Get the level 2 item from the highest 12 bit (8 - 19) of ch. - ushort index = s_pNumericLevel1Index[ch >> 8]; - // Get the level 2 WORD offset from the 4 - 7 bit of ch. This provides the base offset of the level 3 table. - // Note that & has the lower precedence than addition, so don't forget the parathesis. - index = s_pNumericLevel1Index[index + ((ch >> 4) & 0x000f)]; - - fixed (ushort* pUshortPtr = &(s_pNumericLevel1Index[index])) - { - byte* pBytePtr = (byte*)pUshortPtr; - return s_pDigitValues[pBytePtr[(ch & 0x000f)]]; - } - } - - //////////////////////////////////////////////////////////////////////// - // - //Returns the numeric value associated with the character c. If the character is a fraction, - // the return value will not be an integer. If the character does not have a numeric value, the return value is -1. - // - //Returns: - // the numeric value for the specified Unicode character. If the character does not have a numeric value, the return value is -1. - //Arguments: - // ch a Unicode character - //Exceptions: - // ArgumentNullException - // ArgumentOutOfRangeException - // - //////////////////////////////////////////////////////////////////////// - - - public static double GetNumericValue(char ch) - { - return (InternalGetNumericValue(ch)); - } - - - public static double GetNumericValue(String s, int index) - { - if (s == null) - { - throw new ArgumentNullException(nameof(s)); - } - if (index < 0 || index >= s.Length) - { - throw new ArgumentOutOfRangeException(nameof(index), SR.ArgumentOutOfRange_Index); - } - Contract.EndContractBlock(); - return (InternalGetNumericValue(InternalConvertToUtf32(s, index))); - } - - public static int GetDecimalDigitValue(char ch) - { - return (sbyte)(InternalGetDigitValues(ch) >> 8); - } - - public static int GetDecimalDigitValue(String s, int index) - { - if (s == null) - { - throw new ArgumentNullException(nameof(s)); - } - - if (index < 0 || index >= s.Length) - { - throw new ArgumentOutOfRangeException(nameof(index), SR.ArgumentOutOfRange_Index); - } - Contract.EndContractBlock(); - - return (sbyte)(InternalGetDigitValues(InternalConvertToUtf32(s, index)) >> 8); - } - - public static int GetDigitValue(char ch) - { - return (sbyte)(InternalGetDigitValues(ch) & 0x00FF); - } - - public static int GetDigitValue(String s, int index) - { - if (s == null) - { - throw new ArgumentNullException(nameof(s)); - } - - if (index < 0 || index >= s.Length) - { - throw new ArgumentOutOfRangeException(nameof(index), SR.ArgumentOutOfRange_Index); - } - - Contract.EndContractBlock(); - return (sbyte)(InternalGetDigitValues(InternalConvertToUtf32(s, index)) & 0x00FF); - } - - public static UnicodeCategory GetUnicodeCategory(char ch) - { - return (InternalGetUnicodeCategory(ch)); - } - - public static UnicodeCategory GetUnicodeCategory(String s, int index) - { - if (s == null) - throw new ArgumentNullException(nameof(s)); - if (((uint)index) >= ((uint)s.Length)) - { - throw new ArgumentOutOfRangeException(nameof(index)); - } - Contract.EndContractBlock(); - return InternalGetUnicodeCategory(s, index); - } - - internal static unsafe UnicodeCategory InternalGetUnicodeCategory(int ch) - { - return ((UnicodeCategory)InternalGetCategoryValue(ch, UNICODE_CATEGORY_OFFSET)); - } - - - //////////////////////////////////////////////////////////////////////// - // - //Action: Returns the Unicode Category property for the character c. - //Returns: - // an value in UnicodeCategory enum - //Arguments: - // ch a Unicode character - //Exceptions: - // None - // - //Note that this API will return values for D800-DF00 surrogate halves. - // - //////////////////////////////////////////////////////////////////////// - - internal static unsafe byte InternalGetCategoryValue(int ch, int offset) - { - Debug.Assert(ch >= 0 && ch <= 0x10ffff, "ch is not in valid Unicode range."); - // Get the level 2 item from the highest 12 bit (8 - 19) of ch. - ushort index = s_pCategoryLevel1Index[ch >> 8]; - // Get the level 2 WORD offset from the 4 - 7 bit of ch. This provides the base offset of the level 3 table. - // Note that & has the lower precedence than addition, so don't forget the parathesis. - index = s_pCategoryLevel1Index[index + ((ch >> 4) & 0x000f)]; - - fixed (ushort* pUshortPtr = &(s_pCategoryLevel1Index[index])) - { - byte* pBytePtr = (byte*)pUshortPtr; - // Get the result from the 0 -3 bit of ch. - byte valueIndex = pBytePtr[(ch & 0x000f)]; - byte uc = s_pCategoriesValue[valueIndex * 2 + offset]; - // - // Make sure that OtherNotAssigned is the last category in UnicodeCategory. - // If that changes, change the following assertion as well. - // - //Debug.Assert(uc >= 0 && uc <= UnicodeCategory.OtherNotAssigned, "Table returns incorrect Unicode category"); - return (uc); - } - } - - //////////////////////////////////////////////////////////////////////// - // - //Action: Returns the Unicode Category property for the character c. - //Returns: - // an value in UnicodeCategory enum - //Arguments: - // value a Unicode String - // index Index for the specified string. - //Exceptions: - // None - // - //////////////////////////////////////////////////////////////////////// - - internal static UnicodeCategory InternalGetUnicodeCategory(String value, int index) - { - Debug.Assert(value != null, "value can not be null"); - Debug.Assert(index < value.Length, "index < value.Length"); - - return (InternalGetUnicodeCategory(InternalConvertToUtf32(value, index))); - } - - //////////////////////////////////////////////////////////////////////// - // - // Get the Unicode category of the character starting at index. If the character is in BMP, charLength will return 1. - // If the character is a valid surrogate pair, charLength will return 2. - // - //////////////////////////////////////////////////////////////////////// - - internal static UnicodeCategory InternalGetUnicodeCategory(String str, int index, out int charLength) - { - Debug.Assert(str != null, "str can not be null"); - Debug.Assert(str.Length > 0, "str.Length > 0"); ; - Debug.Assert(index >= 0 && index < str.Length, "index >= 0 && index < str.Length"); - - return (InternalGetUnicodeCategory(InternalConvertToUtf32(str, index, out charLength))); - } - - internal static bool IsCombiningCategory(UnicodeCategory uc) - { - Debug.Assert(uc >= 0, "uc >= 0"); - return ( - uc == UnicodeCategory.NonSpacingMark || - uc == UnicodeCategory.SpacingCombiningMark || - uc == UnicodeCategory.EnclosingMark - ); - } - } -} diff --git a/src/mscorlib/corefx/System/Globalization/ChineseLunisolarCalendar.cs b/src/mscorlib/corefx/System/Globalization/ChineseLunisolarCalendar.cs deleted file mode 100644 index 5002555..0000000 --- a/src/mscorlib/corefx/System/Globalization/ChineseLunisolarCalendar.cs +++ /dev/null @@ -1,395 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.Diagnostics.Contracts; - -namespace System.Globalization -{ - //////////////////////////////////////////////////////////////////////////// - // - // Notes about ChineseLunisolarCalendar - // - //////////////////////////////////////////////////////////////////////////// - /* - ** Calendar support range: - ** Calendar Minimum Maximum - ** ========== ========== ========== - ** Gregorian 1901/02/19 2101/01/28 - ** ChineseLunisolar 1901/01/01 2100/12/29 - */ - [Serializable] - public class ChineseLunisolarCalendar : EastAsianLunisolarCalendar - { - // - // The era value for the current era. - // - - public const int ChineseEra = 1; - - internal const int MIN_LUNISOLAR_YEAR = 1901; - internal const int MAX_LUNISOLAR_YEAR = 2100; - - internal const int MIN_GREGORIAN_YEAR = 1901; - internal const int MIN_GREGORIAN_MONTH = 2; - internal const int MIN_GREGORIAN_DAY = 19; - - internal const int MAX_GREGORIAN_YEAR = 2101; - internal const int MAX_GREGORIAN_MONTH = 1; - internal const int MAX_GREGORIAN_DAY = 28; - - internal static DateTime minDate = new DateTime(MIN_GREGORIAN_YEAR, MIN_GREGORIAN_MONTH, MIN_GREGORIAN_DAY); - internal static DateTime maxDate = new DateTime((new DateTime(MAX_GREGORIAN_YEAR, MAX_GREGORIAN_MONTH, MAX_GREGORIAN_DAY, 23, 59, 59, 999)).Ticks + 9999); - - public override DateTime MinSupportedDateTime - { - get - { - return (minDate); - } - } - - - public override DateTime MaxSupportedDateTime - { - get - { - return (maxDate); - } - } - - protected override int DaysInYearBeforeMinSupportedYear - { - get - { - // 1900: 1-29 2-30 3-29 4-29 5-30 6-29 7-30 8-30 Leap8-29 9-30 10-30 11-29 12-30 from Calendrical Tabulations - return 384; - } - } - - - private static readonly int[,] s_yinfo = - { - /*Y LM Lmon Lday DaysPerMonth D1 D2 D3 D4 D5 D6 D7 D8 D9 D10 D11 D12 D13 #Days - 1901 */ - { 0 , 2 , 19 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354 -1902 */{ 0 , 2 , 8 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355 -1903 */{ 5 , 1 , 29 , 21096 },/* 29 30 29 30 29 29 30 29 29 30 30 29 30 383 -1904 */{ 0 , 2 , 16 , 53856 },/* 30 30 29 30 29 29 30 29 29 30 30 29 0 354 -1905 */{ 0 , 2 , 4 , 55632 },/* 30 30 29 30 30 29 29 30 29 30 29 30 0 355 -1906 */{ 4 , 1 , 25 , 27304 },/* 29 30 30 29 30 29 30 29 30 29 30 29 30 384 -1907 */{ 0 , 2 , 13 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354 -1908 */{ 0 , 2 , 2 , 39632 },/* 30 29 29 30 30 29 30 29 30 30 29 30 0 355 -1909 */{ 2 , 1 , 22 , 19176 },/* 29 30 29 29 30 29 30 29 30 30 30 29 30 384 -1910 */{ 0 , 2 , 10 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354 -1911 */{ 6 , 1 , 30 , 42200 },/* 30 29 30 29 29 30 29 29 30 30 29 30 30 384 -1912 */{ 0 , 2 , 18 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354 -1913 */{ 0 , 2 , 6 , 53840 },/* 30 30 29 30 29 29 30 29 29 30 29 30 0 354 -1914 */{ 5 , 1 , 26 , 54568 },/* 30 30 29 30 29 30 29 30 29 29 30 29 30 384 -1915 */{ 0 , 2 , 14 , 46400 },/* 30 29 30 30 29 30 29 30 29 30 29 29 0 354 -1916 */{ 0 , 2 , 3 , 54944 },/* 30 30 29 30 29 30 30 29 30 29 30 29 0 355 -1917 */{ 2 , 1 , 23 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 29 384 -1918 */{ 0 , 2 , 11 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355 -1919 */{ 7 , 2 , 1 , 18872 },/* 29 30 29 29 30 29 29 30 30 29 30 30 30 384 -1920 */{ 0 , 2 , 20 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354 -1921 */{ 0 , 2 , 8 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354 -1922 */{ 5 , 1 , 28 , 45656 },/* 30 29 30 30 29 29 30 29 29 30 29 30 30 384 -1923 */{ 0 , 2 , 16 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 0 354 -1924 */{ 0 , 2 , 5 , 27968 },/* 29 30 30 29 30 30 29 30 29 30 29 29 0 354 -1925 */{ 4 , 1 , 24 , 44456 },/* 30 29 30 29 30 30 29 30 30 29 30 29 30 385 -1926 */{ 0 , 2 , 13 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354 -1927 */{ 0 , 2 , 2 , 38256 },/* 30 29 29 30 29 30 29 30 29 30 30 30 0 355 -1928 */{ 2 , 1 , 23 , 18808 },/* 29 30 29 29 30 29 29 30 29 30 30 30 30 384 -1929 */{ 0 , 2 , 10 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354 -1930 */{ 6 , 1 , 30 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 29 383 -1931 */{ 0 , 2 , 17 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354 -1932 */{ 0 , 2 , 6 , 59984 },/* 30 30 30 29 30 29 30 29 29 30 29 30 0 355 -1933 */{ 5 , 1 , 26 , 27976 },/* 29 30 30 29 30 30 29 30 29 30 29 29 30 384 -1934 */{ 0 , 2 , 14 , 23248 },/* 29 30 29 30 30 29 30 29 30 30 29 30 0 355 -1935 */{ 0 , 2 , 4 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354 -1936 */{ 3 , 1 , 24 , 37744 },/* 30 29 29 30 29 29 30 30 29 30 30 30 29 384 -1937 */{ 0 , 2 , 11 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354 -1938 */{ 7 , 1 , 31 , 51560 },/* 30 30 29 29 30 29 29 30 29 30 30 29 30 384 -1939 */{ 0 , 2 , 19 , 51536 },/* 30 30 29 29 30 29 29 30 29 30 29 30 0 354 -1940 */{ 0 , 2 , 8 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354 -1941 */{ 6 , 1 , 27 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 29 384 -1942 */{ 0 , 2 , 15 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355 -1943 */{ 0 , 2 , 5 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354 -1944 */{ 4 , 1 , 25 , 43736 },/* 30 29 30 29 30 29 30 29 30 30 29 30 30 385 -1945 */{ 0 , 2 , 13 , 9680 },/* 29 29 30 29 29 30 29 30 30 30 29 30 0 354 -1946 */{ 0 , 2 , 2 , 37584 },/* 30 29 29 30 29 29 30 29 30 30 29 30 0 354 -1947 */{ 2 , 1 , 22 , 51544 },/* 30 30 29 29 30 29 29 30 29 30 29 30 30 384 -1948 */{ 0 , 2 , 10 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354 -1949 */{ 7 , 1 , 29 , 46248 },/* 30 29 30 30 29 30 29 29 30 29 30 29 30 384 -1950 */{ 0 , 2 , 17 , 27808 },/* 29 30 30 29 30 30 29 29 30 29 30 29 0 354 -1951 */{ 0 , 2 , 6 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355 -1952 */{ 5 , 1 , 27 , 21928 },/* 29 30 29 30 29 30 29 30 30 29 30 29 30 384 -1953 */{ 0 , 2 , 14 , 19872 },/* 29 30 29 29 30 30 29 30 30 29 30 29 0 354 -1954 */{ 0 , 2 , 3 , 42416 },/* 30 29 30 29 29 30 29 30 30 29 30 30 0 355 -1955 */{ 3 , 1 , 24 , 21176 },/* 29 30 29 30 29 29 30 29 30 29 30 30 30 384 -1956 */{ 0 , 2 , 12 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354 -1957 */{ 8 , 1 , 31 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 29 383 -1958 */{ 0 , 2 , 18 , 59728 },/* 30 30 30 29 30 29 29 30 29 30 29 30 0 355 -1959 */{ 0 , 2 , 8 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354 -1960 */{ 6 , 1 , 28 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 29 384 -1961 */{ 0 , 2 , 15 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 0 355 -1962 */{ 0 , 2 , 5 , 19296 },/* 29 30 29 29 30 29 30 30 29 30 30 29 0 354 -1963 */{ 4 , 1 , 25 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 29 384 -1964 */{ 0 , 2 , 13 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355 -1965 */{ 0 , 2 , 2 , 21088 },/* 29 30 29 30 29 29 30 29 29 30 30 29 0 353 -1966 */{ 3 , 1 , 21 , 59696 },/* 30 30 30 29 30 29 29 30 29 29 30 30 29 384 -1967 */{ 0 , 2 , 9 , 55632 },/* 30 30 29 30 30 29 29 30 29 30 29 30 0 355 -1968 */{ 7 , 1 , 30 , 23208 },/* 29 30 29 30 30 29 30 29 30 29 30 29 30 384 -1969 */{ 0 , 2 , 17 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354 -1970 */{ 0 , 2 , 6 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 0 355 -1971 */{ 5 , 1 , 27 , 19176 },/* 29 30 29 29 30 29 30 29 30 30 30 29 30 384 -1972 */{ 0 , 2 , 15 , 19152 },/* 29 30 29 29 30 29 30 29 30 30 29 30 0 354 -1973 */{ 0 , 2 , 3 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354 -1974 */{ 4 , 1 , 23 , 53864 },/* 30 30 29 30 29 29 30 29 29 30 30 29 30 384 -1975 */{ 0 , 2 , 11 , 53840 },/* 30 30 29 30 29 29 30 29 29 30 29 30 0 354 -1976 */{ 8 , 1 , 31 , 54568 },/* 30 30 29 30 29 30 29 30 29 29 30 29 30 384 -1977 */{ 0 , 2 , 18 , 46400 },/* 30 29 30 30 29 30 29 30 29 30 29 29 0 354 -1978 */{ 0 , 2 , 7 , 46752 },/* 30 29 30 30 29 30 30 29 30 29 30 29 0 355 -1979 */{ 6 , 1 , 28 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 29 384 -1980 */{ 0 , 2 , 16 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355 -1981 */{ 0 , 2 , 5 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354 -1982 */{ 4 , 1 , 25 , 42168 },/* 30 29 30 29 29 30 29 29 30 29 30 30 30 384 -1983 */{ 0 , 2 , 13 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354 -1984 */{ 10 , 2 , 2 , 45656 },/* 30 29 30 30 29 29 30 29 29 30 29 30 30 384 -1985 */{ 0 , 2 , 20 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 0 354 -1986 */{ 0 , 2 , 9 , 27968 },/* 29 30 30 29 30 30 29 30 29 30 29 29 0 354 -1987 */{ 6 , 1 , 29 , 44448 },/* 30 29 30 29 30 30 29 30 30 29 30 29 29 384 -1988 */{ 0 , 2 , 17 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 0 355 -1989 */{ 0 , 2 , 6 , 38256 },/* 30 29 29 30 29 30 29 30 29 30 30 30 0 355 -1990 */{ 5 , 1 , 27 , 18808 },/* 29 30 29 29 30 29 29 30 29 30 30 30 30 384 -1991 */{ 0 , 2 , 15 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354 -1992 */{ 0 , 2 , 4 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 0 354 -1993 */{ 3 , 1 , 23 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 29 383 -1994 */{ 0 , 2 , 10 , 59984 },/* 30 30 30 29 30 29 30 29 29 30 29 30 0 355 -1995 */{ 8 , 1 , 31 , 27432 },/* 29 30 30 29 30 29 30 30 29 29 30 29 30 384 -1996 */{ 0 , 2 , 19 , 23232 },/* 29 30 29 30 30 29 30 29 30 30 29 29 0 354 -1997 */{ 0 , 2 , 7 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 0 355 -1998 */{ 5 , 1 , 28 , 37736 },/* 30 29 29 30 29 29 30 30 29 30 30 29 30 384 -1999 */{ 0 , 2 , 16 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354 -2000 */{ 0 , 2 , 5 , 51552 },/* 30 30 29 29 30 29 29 30 29 30 30 29 0 354 -2001 */{ 4 , 1 , 24 , 54440 },/* 30 30 29 30 29 30 29 29 30 29 30 29 30 384 -2002 */{ 0 , 2 , 12 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354 -2003 */{ 0 , 2 , 1 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 0 355 -2004 */{ 2 , 1 , 22 , 23208 },/* 29 30 29 30 30 29 30 29 30 29 30 29 30 384 -2005 */{ 0 , 2 , 9 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354 -2006 */{ 7 , 1 , 29 , 43736 },/* 30 29 30 29 30 29 30 29 30 30 29 30 30 385 -2007 */{ 0 , 2 , 18 , 9680 },/* 29 29 30 29 29 30 29 30 30 30 29 30 0 354 -2008 */{ 0 , 2 , 7 , 37584 },/* 30 29 29 30 29 29 30 29 30 30 29 30 0 354 -2009 */{ 5 , 1 , 26 , 51544 },/* 30 30 29 29 30 29 29 30 29 30 29 30 30 384 -2010 */{ 0 , 2 , 14 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354 -2011 */{ 0 , 2 , 3 , 46240 },/* 30 29 30 30 29 30 29 29 30 29 30 29 0 354 -2012 */{ 4 , 1 , 23 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 29 384 -2013 */{ 0 , 2 , 10 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355 -2014 */{ 9 , 1 , 31 , 21928 },/* 29 30 29 30 29 30 29 30 30 29 30 29 30 384 -2015 */{ 0 , 2 , 19 , 19360 },/* 29 30 29 29 30 29 30 30 30 29 30 29 0 354 -2016 */{ 0 , 2 , 8 , 42416 },/* 30 29 30 29 29 30 29 30 30 29 30 30 0 355 -2017 */{ 6 , 1 , 28 , 21176 },/* 29 30 29 30 29 29 30 29 30 29 30 30 30 384 -2018 */{ 0 , 2 , 16 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354 -2019 */{ 0 , 2 , 5 , 43312 },/* 30 29 30 29 30 29 29 30 29 29 30 30 0 354 -2020 */{ 4 , 1 , 25 , 29864 },/* 29 30 30 30 29 30 29 29 30 29 30 29 30 384 -2021 */{ 0 , 2 , 12 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354 -2022 */{ 0 , 2 , 1 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355 -2023 */{ 2 , 1 , 22 , 19880 },/* 29 30 29 29 30 30 29 30 30 29 30 29 30 384 -2024 */{ 0 , 2 , 10 , 19296 },/* 29 30 29 29 30 29 30 30 29 30 30 29 0 354 -2025 */{ 6 , 1 , 29 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 29 384 -2026 */{ 0 , 2 , 17 , 42208 },/* 30 29 30 29 29 30 29 29 30 30 30 29 0 354 -2027 */{ 0 , 2 , 6 , 53856 },/* 30 30 29 30 29 29 30 29 29 30 30 29 0 354 -2028 */{ 5 , 1 , 26 , 59696 },/* 30 30 30 29 30 29 29 30 29 29 30 30 29 384 -2029 */{ 0 , 2 , 13 , 54576 },/* 30 30 29 30 29 30 29 30 29 29 30 30 0 355 -2030 */{ 0 , 2 , 3 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354 -2031 */{ 3 , 1 , 23 , 27472 },/* 29 30 30 29 30 29 30 30 29 30 29 30 29 384 -2032 */{ 0 , 2 , 11 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 0 355 -2033 */{ 11 , 1 , 31 , 19176 },/* 29 30 29 29 30 29 30 29 30 30 30 29 30 384 -2034 */{ 0 , 2 , 19 , 19152 },/* 29 30 29 29 30 29 30 29 30 30 29 30 0 354 -2035 */{ 0 , 2 , 8 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354 -2036 */{ 6 , 1 , 28 , 53848 },/* 30 30 29 30 29 29 30 29 29 30 29 30 30 384 -2037 */{ 0 , 2 , 15 , 53840 },/* 30 30 29 30 29 29 30 29 29 30 29 30 0 354 -2038 */{ 0 , 2 , 4 , 54560 },/* 30 30 29 30 29 30 29 30 29 29 30 29 0 354 -2039 */{ 5 , 1 , 24 , 55968 },/* 30 30 29 30 30 29 30 29 30 29 30 29 29 384 -2040 */{ 0 , 2 , 12 , 46496 },/* 30 29 30 30 29 30 29 30 30 29 30 29 0 355 -2041 */{ 0 , 2 , 1 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 0 355 -2042 */{ 2 , 1 , 22 , 19160 },/* 29 30 29 29 30 29 30 29 30 30 29 30 30 384 -2043 */{ 0 , 2 , 10 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354 -2044 */{ 7 , 1 , 30 , 42168 },/* 30 29 30 29 29 30 29 29 30 29 30 30 30 384 -2045 */{ 0 , 2 , 17 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354 -2046 */{ 0 , 2 , 6 , 43600 },/* 30 29 30 29 30 29 30 29 29 30 29 30 0 354 -2047 */{ 5 , 1 , 26 , 46376 },/* 30 29 30 30 29 30 29 30 29 29 30 29 30 384 -2048 */{ 0 , 2 , 14 , 27936 },/* 29 30 30 29 30 30 29 30 29 29 30 29 0 354 -2049 */{ 0 , 2 , 2 , 44448 },/* 30 29 30 29 30 30 29 30 30 29 30 29 0 355 -2050 */{ 3 , 1 , 23 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 29 384 -2051 */{ 0 , 2 , 11 , 37744 },/* 30 29 29 30 29 29 30 30 29 30 30 30 0 355 -2052 */{ 8 , 2 , 1 , 18808 },/* 29 30 29 29 30 29 29 30 29 30 30 30 30 384 -2053 */{ 0 , 2 , 19 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354 -2054 */{ 0 , 2 , 8 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 0 354 -2055 */{ 6 , 1 , 28 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 29 383 -2056 */{ 0 , 2 , 15 , 59984 },/* 30 30 30 29 30 29 30 29 29 30 29 30 0 355 -2057 */{ 0 , 2 , 4 , 27424 },/* 29 30 30 29 30 29 30 30 29 29 30 29 0 354 -2058 */{ 4 , 1 , 24 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 29 384 -2059 */{ 0 , 2 , 12 , 43744 },/* 30 29 30 29 30 29 30 29 30 30 30 29 0 355 -2060 */{ 0 , 2 , 2 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354 -2061 */{ 3 , 1 , 21 , 51568 },/* 30 30 29 29 30 29 29 30 29 30 30 30 29 384 -2062 */{ 0 , 2 , 9 , 51552 },/* 30 30 29 29 30 29 29 30 29 30 30 29 0 354 -2063 */{ 7 , 1 , 29 , 54440 },/* 30 30 29 30 29 30 29 29 30 29 30 29 30 384 -2064 */{ 0 , 2 , 17 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354 -2065 */{ 0 , 2 , 5 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 0 355 -2066 */{ 5 , 1 , 26 , 23208 },/* 29 30 29 30 30 29 30 29 30 29 30 29 30 384 -2067 */{ 0 , 2 , 14 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354 -2068 */{ 0 , 2 , 3 , 42704 },/* 30 29 30 29 29 30 30 29 30 30 29 30 0 355 -2069 */{ 4 , 1 , 23 , 21224 },/* 29 30 29 30 29 29 30 29 30 30 30 29 30 384 -2070 */{ 0 , 2 , 11 , 21200 },/* 29 30 29 30 29 29 30 29 30 30 29 30 0 354 -2071 */{ 8 , 1 , 31 , 43352 },/* 30 29 30 29 30 29 29 30 29 30 29 30 30 384 -2072 */{ 0 , 2 , 19 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354 -2073 */{ 0 , 2 , 7 , 46240 },/* 30 29 30 30 29 30 29 29 30 29 30 29 0 354 -2074 */{ 6 , 1 , 27 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 29 384 -2075 */{ 0 , 2 , 15 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355 -2076 */{ 0 , 2 , 5 , 21920 },/* 29 30 29 30 29 30 29 30 30 29 30 29 0 354 -2077 */{ 4 , 1 , 24 , 42448 },/* 30 29 30 29 29 30 29 30 30 30 29 30 29 384 -2078 */{ 0 , 2 , 12 , 42416 },/* 30 29 30 29 29 30 29 30 30 29 30 30 0 355 -2079 */{ 0 , 2 , 2 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354 -2080 */{ 3 , 1 , 22 , 43320 },/* 30 29 30 29 30 29 29 30 29 29 30 30 30 384 -2081 */{ 0 , 2 , 9 , 26928 },/* 29 30 30 29 30 29 29 30 29 29 30 30 0 354 -2082 */{ 7 , 1 , 29 , 29336 },/* 29 30 30 30 29 29 30 29 30 29 29 30 30 384 -2083 */{ 0 , 2 , 17 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354 -2084 */{ 0 , 2 , 6 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355 -2085 */{ 5 , 1 , 26 , 19880 },/* 29 30 29 29 30 30 29 30 30 29 30 29 30 384 -2086 */{ 0 , 2 , 14 , 19296 },/* 29 30 29 29 30 29 30 30 29 30 30 29 0 354 -2087 */{ 0 , 2 , 3 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355 -2088 */{ 4 , 1 , 24 , 21104 },/* 29 30 29 30 29 29 30 29 29 30 30 30 29 383 -2089 */{ 0 , 2 , 10 , 53856 },/* 30 30 29 30 29 29 30 29 29 30 30 29 0 354 -2090 */{ 8 , 1 , 30 , 59696 },/* 30 30 30 29 30 29 29 30 29 29 30 30 29 384 -2091 */{ 0 , 2 , 18 , 54560 },/* 30 30 29 30 29 30 29 30 29 29 30 29 0 354 -2092 */{ 0 , 2 , 7 , 55968 },/* 30 30 29 30 30 29 30 29 30 29 30 29 0 355 -2093 */{ 6 , 1 , 27 , 27472 },/* 29 30 30 29 30 29 30 30 29 30 29 30 29 384 -2094 */{ 0 , 2 , 15 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 0 355 -2095 */{ 0 , 2 , 5 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354 -2096 */{ 4 , 1 , 25 , 42216 },/* 30 29 30 29 29 30 29 29 30 30 30 29 30 384 -2097 */{ 0 , 2 , 12 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354 -2098 */{ 0 , 2 , 1 , 53584 },/* 30 30 29 30 29 29 29 30 29 30 29 30 0 354 -2099 */{ 2 , 1 , 21 , 55592 },/* 30 30 29 30 30 29 29 30 29 29 30 29 30 384 -2100 */{ 0 , 2 , 9 , 54560 },/* 30 30 29 30 29 30 29 30 29 29 30 29 0 354 - */}; - - - internal override int MinCalendarYear - { - get - { - return (MIN_LUNISOLAR_YEAR); - } - } - - internal override int MaxCalendarYear - { - get - { - return (MAX_LUNISOLAR_YEAR); - } - } - - internal override DateTime MinDate - { - get - { - return (minDate); - } - } - - internal override DateTime MaxDate - { - get - { - return (maxDate); - } - } - - internal override EraInfo[] CalEraInfo - { - get - { - return (null); - } - } - - internal override int GetYearInfo(int lunarYear, int index) - { - if ((lunarYear < MIN_LUNISOLAR_YEAR) || (lunarYear > MAX_LUNISOLAR_YEAR)) - { - throw new ArgumentOutOfRangeException( - "year", - String.Format( - CultureInfo.CurrentCulture, - SR.ArgumentOutOfRange_Range, MIN_LUNISOLAR_YEAR, MAX_LUNISOLAR_YEAR)); - } - Contract.EndContractBlock(); - - return s_yinfo[lunarYear - MIN_LUNISOLAR_YEAR, index]; - } - - internal override int GetYear(int year, DateTime time) - { - return year; - } - - internal override int GetGregorianYear(int year, int era) - { - if (era != CurrentEra && era != ChineseEra) - { - throw new ArgumentOutOfRangeException(nameof(era), SR.ArgumentOutOfRange_InvalidEraValue); - } - - if (year < MIN_LUNISOLAR_YEAR || year > MAX_LUNISOLAR_YEAR) - { - throw new ArgumentOutOfRangeException( - nameof(year), - String.Format( - CultureInfo.CurrentCulture, - SR.ArgumentOutOfRange_Range, MIN_LUNISOLAR_YEAR, MAX_LUNISOLAR_YEAR)); - } - Contract.EndContractBlock(); - - return year; - } - - public ChineseLunisolarCalendar() - { - } - - public override int GetEra(DateTime time) - { - CheckTicksRange(time.Ticks); - return (ChineseEra); - } - - internal override CalendarId ID - { - get - { - return (CalendarId.CHINESELUNISOLAR); - } - } - - internal override CalendarId BaseCalendarID - { - get - { - //Use CAL_GREGORIAN just to get CurrentEraValue as 1 since we do not have data under the ID CAL_ChineseLunisolar yet - return (CalendarId.GREGORIAN); - } - } - - - public override int[] Eras - { - get - { - return (new int[] { ChineseEra }); - } - } - } -} diff --git a/src/mscorlib/corefx/System/Globalization/CompareInfo.cs b/src/mscorlib/corefx/System/Globalization/CompareInfo.cs deleted file mode 100644 index 94cfcad..0000000 --- a/src/mscorlib/corefx/System/Globalization/CompareInfo.cs +++ /dev/null @@ -1,1094 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -//////////////////////////////////////////////////////////////////////////// -// -// -// -// Purpose: This class implements a set of methods for comparing -// strings. -// -// -//////////////////////////////////////////////////////////////////////////// - -using System.Reflection; -using System.Diagnostics; -using System.Diagnostics.Contracts; -using System.Runtime.Serialization; - -namespace System.Globalization -{ - [Flags] - [Serializable] - public enum CompareOptions - { - None = 0x00000000, - IgnoreCase = 0x00000001, - IgnoreNonSpace = 0x00000002, - IgnoreSymbols = 0x00000004, - IgnoreKanaType = 0x00000008, // ignore kanatype - IgnoreWidth = 0x00000010, // ignore width - OrdinalIgnoreCase = 0x10000000, // This flag can not be used with other flags. - StringSort = 0x20000000, // use string sort method - Ordinal = 0x40000000, // This flag can not be used with other flags. - } - - [Serializable] - public partial class CompareInfo : IDeserializationCallback - { - // Mask used to check if IndexOf()/LastIndexOf()/IsPrefix()/IsPostfix() has the right flags. - private const CompareOptions ValidIndexMaskOffFlags = - ~(CompareOptions.IgnoreCase | CompareOptions.IgnoreSymbols | CompareOptions.IgnoreNonSpace | - CompareOptions.IgnoreWidth | CompareOptions.IgnoreKanaType); - - // Mask used to check if Compare() has the right flags. - private const CompareOptions ValidCompareMaskOffFlags = - ~(CompareOptions.IgnoreCase | CompareOptions.IgnoreSymbols | CompareOptions.IgnoreNonSpace | - CompareOptions.IgnoreWidth | CompareOptions.IgnoreKanaType | CompareOptions.StringSort); - - // Mask used to check if GetHashCodeOfString() has the right flags. - private const CompareOptions ValidHashCodeOfStringMaskOffFlags = - ~(CompareOptions.IgnoreCase | CompareOptions.IgnoreSymbols | CompareOptions.IgnoreNonSpace | - CompareOptions.IgnoreWidth | CompareOptions.IgnoreKanaType); - - // Mask used to check if we have the right flags. - private const CompareOptions ValidSortkeyCtorMaskOffFlags = - ~(CompareOptions.IgnoreCase | CompareOptions.IgnoreSymbols | CompareOptions.IgnoreNonSpace | - CompareOptions.IgnoreWidth | CompareOptions.IgnoreKanaType | CompareOptions.StringSort); - - // - // CompareInfos have an interesting identity. They are attached to the locale that created them, - // ie: en-US would have an en-US sort. For haw-US (custom), then we serialize it as haw-US. - // The interesting part is that since haw-US doesn't have its own sort, it has to point at another - // locale, which is what SCOMPAREINFO does. - - [OptionalField(VersionAdded = 2)] - private String _name; // The name used to construct this CompareInfo - [NonSerialized] - private String _sortName; // The name that defines our behavior - - [OptionalField(VersionAdded = 3)] - private SortVersion _sortVersion; - - /*=================================GetCompareInfo========================== - **Action: Get the CompareInfo constructed from the data table in the specified assembly for the specified culture. - ** Warning: The assembly versioning mechanism is dead! - **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. - ============================================================================*/ - // Assembly constructor should be deprecated, we don't act on the assembly information any more - public static CompareInfo GetCompareInfo(int culture, Assembly assembly) - { - // Parameter checking. - if (assembly == null) - { - throw new ArgumentNullException(nameof(assembly)); - } - if (assembly != typeof(Object).Module.Assembly) - { - throw new ArgumentException(SR.Argument_OnlyMscorlib); - } - Contract.EndContractBlock(); - - 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. - ============================================================================*/ - // Assembly constructor should be deprecated, we don't act on the assembly information any more - public static CompareInfo GetCompareInfo(String name, Assembly assembly) - { - if (name == null || assembly == null) - { - throw new ArgumentNullException(name == null ? nameof(name) : nameof(assembly)); - } - Contract.EndContractBlock(); - - if (assembly != typeof(Object).Module.Assembly) - { - throw new ArgumentException(SR.Argument_OnlyMscorlib); - } - - return GetCompareInfo(name); - } - - /*=================================GetCompareInfo========================== - **Action: Get the CompareInfo for the specified culture. - ** This method is provided for ease of integration with NLS-based software. - **Returns: The CompareInfo for the specified culture. - **Arguments: - ** culture the ID of the culture. - **Exceptions: - ** ArgumentException if culture is invalid. - ============================================================================*/ - // People really shouldn't be calling LCID versions, no custom support - public static CompareInfo GetCompareInfo(int culture) - { - if (CultureData.IsCustomCultureId(culture)) - { - // Customized culture cannot be created by the LCID. - throw new ArgumentException(SR.Argument_CustomCultureCannotBePassedByNumber, nameof(culture)); - } - - return CultureInfo.GetCultureInfo(culture).CompareInfo; - } - - /*=================================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. - ============================================================================*/ - - public static CompareInfo GetCompareInfo(String name) - { - if (name == null) - { - throw new ArgumentNullException(nameof(name)); - } - Contract.EndContractBlock(); - - return CultureInfo.GetCultureInfo(name).CompareInfo; - } - - public static unsafe bool IsSortable(char ch) - { - char *pChar = &ch; - return IsSortable(pChar, 1); - } - - public static unsafe bool IsSortable(string text) - { - if (text == null) - { - // A null param is invalid here. - throw new ArgumentNullException(nameof(text)); - } - - if (0 == text.Length) - { - // A zero length string is not invalid, but it is also not sortable. - return (false); - } - - fixed (char *pChar = text) - { - return IsSortable(pChar, text.Length); - } - } - - - [OnDeserializing] - private void OnDeserializing(StreamingContext ctx) - { - _name = null; - } - - void IDeserializationCallback.OnDeserialization(Object sender) - { - OnDeserialized(); - } - - [OnDeserialized] - private void OnDeserialized(StreamingContext ctx) - { - OnDeserialized(); - } - - private void OnDeserialized() - { - if (_name != null) - { - InitSort(CultureInfo.GetCultureInfo(_name)); - } - } - - [OnSerializing] - private void OnSerializing(StreamingContext ctx) { } - - ///////////////////////////----- Name -----///////////////////////////////// - // - // Returns the name of the culture (well actually, of the sort). - // Very important for providing a non-LCID way of identifying - // what the sort is. - // - // Note that this name isn't dereferenced in case the CompareInfo is a different locale - // which is consistent with the behaviors of earlier versions. (so if you ask for a sort - // and the locale's changed behavior, then you'll get changed behavior, which is like - // what happens for a version update) - // - //////////////////////////////////////////////////////////////////////// - - public virtual String Name - { - get - { - Debug.Assert(_name != null, "CompareInfo.Name Expected _name to be set"); - if (_name == "zh-CHT" || _name == "zh-CHS") - { - return _name; - } - - return _sortName; - } - } - - //////////////////////////////////////////////////////////////////////// - // - // Compare - // - // Compares the two strings with the given options. Returns 0 if the - // two strings are equal, a number less than 0 if string1 is less - // than string2, and a number greater than 0 if string1 is greater - // than string2. - // - //////////////////////////////////////////////////////////////////////// - - public virtual int Compare(String string1, String string2) - { - return (Compare(string1, string2, CompareOptions.None)); - } - - public unsafe virtual int Compare(String string1, String string2, CompareOptions options) - { - if (options == CompareOptions.OrdinalIgnoreCase) - { - return String.Compare(string1, string2, StringComparison.OrdinalIgnoreCase); - } - - // Verify the options before we do any real comparison. - if ((options & CompareOptions.Ordinal) != 0) - { - if (options != CompareOptions.Ordinal) - { - throw new ArgumentException(SR.Argument_CompareOptionOrdinal, nameof(options)); - } - return String.CompareOrdinal(string1, string2); - } - - if ((options & ValidCompareMaskOffFlags) != 0) - { - throw new ArgumentException(SR.Argument_InvalidFlag, nameof(options)); - } - - //Our paradigm is that null sorts less than any other string and - //that two nulls sort as equal. - if (string1 == null) - { - if (string2 == null) - { - return (0); // Equal - } - return (-1); // null < non-null - } - if (string2 == null) - { - return (1); // non-null > null - } - - return CompareString(string1, 0, string1.Length, string2, 0, string2.Length, options); - } - - - //////////////////////////////////////////////////////////////////////// - // - // Compare - // - // Compares the specified regions of the two strings with the given - // options. - // Returns 0 if the two strings are equal, a number less than 0 if - // string1 is less than string2, and a number greater than 0 if - // string1 is greater than string2. - // - //////////////////////////////////////////////////////////////////////// - - - public unsafe virtual int Compare(String string1, int offset1, int length1, String string2, int offset2, int length2) - { - return Compare(string1, offset1, length1, string2, offset2, length2, 0); - } - - - public unsafe virtual int Compare(String string1, int offset1, String string2, int offset2, CompareOptions options) - { - return Compare(string1, offset1, string1 == null ? 0 : string1.Length - offset1, - string2, offset2, string2 == null ? 0 : string2.Length - offset2, options); - } - - - public unsafe virtual int Compare(String string1, int offset1, String string2, int offset2) - { - return Compare(string1, offset1, string2, offset2, 0); - } - - - public unsafe virtual int Compare(String string1, int offset1, int length1, String string2, int offset2, int length2, CompareOptions options) - { - if (options == CompareOptions.OrdinalIgnoreCase) - { - int result = String.Compare(string1, offset1, string2, offset2, length1 < length2 ? length1 : length2, StringComparison.OrdinalIgnoreCase); - if ((length1 != length2) && result == 0) - return (length1 > length2 ? 1 : -1); - return (result); - } - - // Verify inputs - if (length1 < 0 || length2 < 0) - { - throw new ArgumentOutOfRangeException((length1 < 0) ? nameof(length1) : nameof(length2), SR.ArgumentOutOfRange_NeedPosNum); - } - if (offset1 < 0 || offset2 < 0) - { - throw new ArgumentOutOfRangeException((offset1 < 0) ? nameof(offset1) : nameof(offset2), SR.ArgumentOutOfRange_NeedPosNum); - } - if (offset1 > (string1 == null ? 0 : string1.Length) - length1) - { - throw new ArgumentOutOfRangeException(nameof(string1), SR.ArgumentOutOfRange_OffsetLength); - } - if (offset2 > (string2 == null ? 0 : string2.Length) - length2) - { - throw new ArgumentOutOfRangeException(nameof(string2), SR.ArgumentOutOfRange_OffsetLength); - } - if ((options & CompareOptions.Ordinal) != 0) - { - if (options != CompareOptions.Ordinal) - { - throw new ArgumentException(SR.Argument_CompareOptionOrdinal, - nameof(options)); - } - } - else if ((options & ValidCompareMaskOffFlags) != 0) - { - throw new ArgumentException(SR.Argument_InvalidFlag, nameof(options)); - } - - // - // Check for the null case. - // - if (string1 == null) - { - if (string2 == null) - { - return (0); - } - return (-1); - } - if (string2 == null) - { - return (1); - } - - if (options == CompareOptions.Ordinal) - { - return CompareOrdinal(string1, offset1, length1, - string2, offset2, length2); - } - return CompareString(string1, offset1, length1, - string2, offset2, length2, - options); - } - - private static int CompareOrdinal(string string1, int offset1, int length1, string string2, int offset2, int length2) - { - int result = String.CompareOrdinal(string1, offset1, string2, offset2, - (length1 < length2 ? length1 : length2)); - if ((length1 != length2) && result == 0) - { - return (length1 > length2 ? 1 : -1); - } - return (result); - } - - // - // CompareOrdinalIgnoreCase compare two string oridnally with ignoring the case. - // it assumes the strings are Ascii string till we hit non Ascii character in strA or strB and then we continue the comparison by - // calling the OS. - // - internal static unsafe int CompareOrdinalIgnoreCase(string strA, int indexA, int lengthA, string strB, int indexB, int lengthB) - { - Debug.Assert(indexA + lengthA <= strA.Length); - Debug.Assert(indexB + lengthB <= strB.Length); - - int length = Math.Min(lengthA, lengthB); - int range = length; - - fixed (char* ap = strA) fixed (char* bp = strB) - { - char* a = ap + indexA; - char* b = bp + indexB; - - while (length != 0 && (*a <= 0x80) && (*b <= 0x80)) - { - int charA = *a; - int charB = *b; - - if (charA == charB) - { - a++; b++; - length--; - continue; - } - - // uppercase both chars - notice that we need just one compare per char - if ((uint)(charA - 'a') <= (uint)('z' - 'a')) charA -= 0x20; - if ((uint)(charB - 'a') <= (uint)('z' - 'a')) charB -= 0x20; - - //Return the (case-insensitive) difference between them. - if (charA != charB) - return charA - charB; - - // Next char - a++; b++; - length--; - } - - if (length == 0) - return lengthA - lengthB; - - range -= length; - - return CompareStringOrdinalIgnoreCase(a, lengthA - range, b, lengthB - range); - } - } - - //////////////////////////////////////////////////////////////////////// - // - // IsPrefix - // - // Determines whether prefix is a prefix of string. If prefix equals - // String.Empty, true is returned. - // - //////////////////////////////////////////////////////////////////////// - public unsafe virtual bool IsPrefix(String source, String prefix, CompareOptions options) - { - if (source == null || prefix == null) - { - throw new ArgumentNullException((source == null ? nameof(source) : nameof(prefix)), - SR.ArgumentNull_String); - } - Contract.EndContractBlock(); - - if (prefix.Length == 0) - { - return (true); - } - - if (source.Length == 0) - { - return false; - } - - if (options == CompareOptions.OrdinalIgnoreCase) - { - return source.StartsWith(prefix, StringComparison.OrdinalIgnoreCase); - } - - if (options == CompareOptions.Ordinal) - { - return source.StartsWith(prefix, StringComparison.Ordinal); - } - - if ((options & ValidIndexMaskOffFlags) != 0) - { - throw new ArgumentException(SR.Argument_InvalidFlag, nameof(options)); - } - - return StartsWith(source, prefix, options); - } - - public virtual bool IsPrefix(String source, String prefix) - { - return (IsPrefix(source, prefix, 0)); - } - - //////////////////////////////////////////////////////////////////////// - // - // IsSuffix - // - // Determines whether suffix is a suffix of string. If suffix equals - // String.Empty, true is returned. - // - //////////////////////////////////////////////////////////////////////// - public unsafe virtual bool IsSuffix(String source, String suffix, CompareOptions options) - { - if (source == null || suffix == null) - { - throw new ArgumentNullException((source == null ? nameof(source) : nameof(suffix)), - SR.ArgumentNull_String); - } - Contract.EndContractBlock(); - - if (suffix.Length == 0) - { - return (true); - } - - if (source.Length == 0) - { - return false; - } - - if (options == CompareOptions.OrdinalIgnoreCase) - { - return source.EndsWith(suffix, StringComparison.OrdinalIgnoreCase); - } - - if (options == CompareOptions.Ordinal) - { - return source.EndsWith(suffix, StringComparison.Ordinal); - } - - if ((options & ValidIndexMaskOffFlags) != 0) - { - throw new ArgumentException(SR.Argument_InvalidFlag, nameof(options)); - } - - return EndsWith(source, suffix, options); - } - - - public virtual bool IsSuffix(String source, String suffix) - { - return (IsSuffix(source, suffix, 0)); - } - - //////////////////////////////////////////////////////////////////////// - // - // IndexOf - // - // Returns the first index where value is found in string. The - // search starts from startIndex and ends at endIndex. Returns -1 if - // the specified value is not found. If value equals String.Empty, - // startIndex is returned. Throws IndexOutOfRange if startIndex or - // endIndex is less than zero or greater than the length of string. - // Throws ArgumentException if value is null. - // - //////////////////////////////////////////////////////////////////////// - - - public unsafe virtual int IndexOf(String source, char value) - { - if (source == null) - throw new ArgumentNullException(nameof(source)); - Contract.EndContractBlock(); - - return IndexOf(source, value, 0, source.Length, CompareOptions.None); - } - - - public unsafe virtual int IndexOf(String source, String value) - { - if (source == null) - throw new ArgumentNullException(nameof(source)); - Contract.EndContractBlock(); - - return IndexOf(source, value, 0, source.Length, CompareOptions.None); - } - - - public unsafe virtual int IndexOf(String source, char value, CompareOptions options) - { - if (source == null) - throw new ArgumentNullException(nameof(source)); - Contract.EndContractBlock(); - - return IndexOf(source, value, 0, source.Length, options); - } - - - public unsafe virtual int IndexOf(String source, String value, CompareOptions options) - { - if (source == null) - throw new ArgumentNullException(nameof(source)); - Contract.EndContractBlock(); - - return IndexOf(source, value, 0, source.Length, options); - } - - public unsafe virtual int IndexOf(String source, char value, int startIndex) - { - if (source == null) - throw new ArgumentNullException(nameof(source)); - Contract.EndContractBlock(); - - return IndexOf(source, value, startIndex, source.Length - startIndex, CompareOptions.None); - } - - public unsafe virtual int IndexOf(String source, String value, int startIndex) - { - if (source == null) - throw new ArgumentNullException(nameof(source)); - Contract.EndContractBlock(); - - return IndexOf(source, value, startIndex, source.Length - startIndex, CompareOptions.None); - } - - public unsafe virtual int IndexOf(String source, char value, int startIndex, CompareOptions options) - { - if (source == null) - throw new ArgumentNullException(nameof(source)); - Contract.EndContractBlock(); - - return IndexOf(source, value, startIndex, source.Length - startIndex, options); - } - - - public unsafe virtual int IndexOf(String source, String value, int startIndex, CompareOptions options) - { - if (source == null) - throw new ArgumentNullException(nameof(source)); - Contract.EndContractBlock(); - - return IndexOf(source, value, startIndex, source.Length - startIndex, options); - } - - - public unsafe virtual int IndexOf(String source, char value, int startIndex, int count) - { - return IndexOf(source, value, startIndex, count, CompareOptions.None); - } - - - public unsafe virtual int IndexOf(String source, String value, int startIndex, int count) - { - return IndexOf(source, value, startIndex, count, CompareOptions.None); - } - - public unsafe virtual int IndexOf(String source, char value, int startIndex, int count, CompareOptions options) - { - // Validate inputs - if (source == null) - throw new ArgumentNullException(nameof(source)); - - if (startIndex < 0 || startIndex > source.Length) - throw new ArgumentOutOfRangeException(nameof(startIndex), SR.ArgumentOutOfRange_Index); - - if (count < 0 || startIndex > source.Length - count) - throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_Count); - Contract.EndContractBlock(); - - if (options == CompareOptions.OrdinalIgnoreCase) - { - return source.IndexOf(value.ToString(), startIndex, count, StringComparison.OrdinalIgnoreCase); - } - - // Validate CompareOptions - // Ordinal can't be selected with other flags - if ((options & ValidIndexMaskOffFlags) != 0 && (options != CompareOptions.Ordinal)) - throw new ArgumentException(SR.Argument_InvalidFlag, nameof(options)); - - return IndexOfCore(source, new string(value, 1), startIndex, count, options, null); - } - - - public unsafe virtual int IndexOf(String source, String value, int startIndex, int count, CompareOptions options) - { - // Validate inputs - if (source == null) - throw new ArgumentNullException(nameof(source)); - if (value == null) - throw new ArgumentNullException(nameof(value)); - - if (startIndex > source.Length) - { - throw new ArgumentOutOfRangeException(nameof(startIndex), SR.ArgumentOutOfRange_Index); - } - Contract.EndContractBlock(); - - // In Everett we used to return -1 for empty string even if startIndex is negative number so we keeping same behavior here. - // We return 0 if both source and value are empty strings for Everett compatibility too. - if (source.Length == 0) - { - if (value.Length == 0) - { - return 0; - } - return -1; - } - - if (startIndex < 0) - { - throw new ArgumentOutOfRangeException(nameof(startIndex), SR.ArgumentOutOfRange_Index); - } - - if (count < 0 || startIndex > source.Length - count) - throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_Count); - - if (options == CompareOptions.OrdinalIgnoreCase) - { - return IndexOfOrdinal(source, value, startIndex, count, ignoreCase: true); - } - - // Validate CompareOptions - // Ordinal can't be selected with other flags - if ((options & ValidIndexMaskOffFlags) != 0 && (options != CompareOptions.Ordinal)) - throw new ArgumentException(SR.Argument_InvalidFlag, nameof(options)); - - return IndexOfCore(source, value, startIndex, count, options, null); - } - - //////////////////////////////////////////////////////////////////////// - // - // LastIndexOf - // - // Returns the last index where value is found in string. The - // search starts from startIndex and ends at endIndex. Returns -1 if - // the specified value is not found. If value equals String.Empty, - // endIndex is returned. Throws IndexOutOfRange if startIndex or - // endIndex is less than zero or greater than the length of string. - // Throws ArgumentException if value is null. - // - //////////////////////////////////////////////////////////////////////// - - - public unsafe virtual int LastIndexOf(String source, char value) - { - if (source == null) - throw new ArgumentNullException(nameof(source)); - Contract.EndContractBlock(); - - // Can't start at negative index, so make sure we check for the length == 0 case. - return LastIndexOf(source, value, source.Length - 1, - source.Length, CompareOptions.None); - } - - - public virtual int LastIndexOf(String source, String value) - { - if (source == null) - throw new ArgumentNullException(nameof(source)); - Contract.EndContractBlock(); - - // Can't start at negative index, so make sure we check for the length == 0 case. - return LastIndexOf(source, value, source.Length - 1, - source.Length, CompareOptions.None); - } - - - public virtual int LastIndexOf(String source, char value, CompareOptions options) - { - if (source == null) - throw new ArgumentNullException(nameof(source)); - Contract.EndContractBlock(); - - // Can't start at negative index, so make sure we check for the length == 0 case. - return LastIndexOf(source, value, source.Length - 1, - source.Length, options); - } - - public unsafe virtual int LastIndexOf(String source, String value, CompareOptions options) - { - if (source == null) - throw new ArgumentNullException(nameof(source)); - Contract.EndContractBlock(); - - // Can't start at negative index, so make sure we check for the length == 0 case. - return LastIndexOf(source, value, source.Length - 1, - source.Length, options); - } - - public unsafe virtual int LastIndexOf(String source, char value, int startIndex) - { - return LastIndexOf(source, value, startIndex, startIndex + 1, CompareOptions.None); - } - - - public unsafe virtual int LastIndexOf(String source, String value, int startIndex) - { - return LastIndexOf(source, value, startIndex, startIndex + 1, CompareOptions.None); - } - - public unsafe virtual int LastIndexOf(String source, char value, int startIndex, CompareOptions options) - { - return LastIndexOf(source, value, startIndex, startIndex + 1, options); - } - - - public unsafe virtual int LastIndexOf(String source, String value, int startIndex, CompareOptions options) - { - return LastIndexOf(source, value, startIndex, startIndex + 1, options); - } - - - public unsafe virtual int LastIndexOf(String source, char value, int startIndex, int count) - { - return LastIndexOf(source, value, startIndex, count, CompareOptions.None); - } - - - public unsafe virtual int LastIndexOf(String source, String value, int startIndex, int count) - { - return LastIndexOf(source, value, startIndex, count, CompareOptions.None); - } - - - public unsafe virtual int LastIndexOf(String source, char value, int startIndex, int count, CompareOptions options) - { - // Verify Arguments - if (source == null) - throw new ArgumentNullException(nameof(source)); - Contract.EndContractBlock(); - - // Validate CompareOptions - // Ordinal can't be selected with other flags - if ((options & ValidIndexMaskOffFlags) != 0 && - (options != CompareOptions.Ordinal) && - (options != CompareOptions.OrdinalIgnoreCase)) - throw new ArgumentException(SR.Argument_InvalidFlag, nameof(options)); - - // Special case for 0 length input strings - if (source.Length == 0 && (startIndex == -1 || startIndex == 0)) - return -1; - - // Make sure we're not out of range - if (startIndex < 0 || startIndex > source.Length) - throw new ArgumentOutOfRangeException(nameof(startIndex), SR.ArgumentOutOfRange_Index); - - // Make sure that we allow startIndex == source.Length - if (startIndex == source.Length) - { - startIndex--; - if (count > 0) - count--; - } - - // 2nd have of this also catches when startIndex == MAXINT, so MAXINT - 0 + 1 == -1, which is < 0. - if (count < 0 || startIndex - count + 1 < 0) - throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_Count); - - if (options == CompareOptions.OrdinalIgnoreCase) - { - return source.LastIndexOf(value.ToString(), startIndex, count, StringComparison.OrdinalIgnoreCase); - } - - return LastIndexOfCore(source, value.ToString(), startIndex, count, options); - } - - - public unsafe virtual int LastIndexOf(String source, String value, int startIndex, int count, CompareOptions options) - { - // Verify Arguments - if (source == null) - throw new ArgumentNullException(nameof(source)); - if (value == null) - throw new ArgumentNullException(nameof(value)); - Contract.EndContractBlock(); - - // Validate CompareOptions - // Ordinal can't be selected with other flags - if ((options & ValidIndexMaskOffFlags) != 0 && - (options != CompareOptions.Ordinal) && - (options != CompareOptions.OrdinalIgnoreCase)) - throw new ArgumentException(SR.Argument_InvalidFlag, nameof(options)); - - // Special case for 0 length input strings - if (source.Length == 0 && (startIndex == -1 || startIndex == 0)) - return (value.Length == 0) ? 0 : -1; - - // Make sure we're not out of range - if (startIndex < 0 || startIndex > source.Length) - throw new ArgumentOutOfRangeException(nameof(startIndex), SR.ArgumentOutOfRange_Index); - - // Make sure that we allow startIndex == source.Length - if (startIndex == source.Length) - { - startIndex--; - if (count > 0) - count--; - - // If we are looking for nothing, just return 0 - if (value.Length == 0 && count >= 0 && startIndex - count + 1 >= 0) - return startIndex; - } - - // 2nd half of this also catches when startIndex == MAXINT, so MAXINT - 0 + 1 == -1, which is < 0. - if (count < 0 || startIndex - count + 1 < 0) - throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_Count); - - if (options == CompareOptions.OrdinalIgnoreCase) - { - return LastIndexOfOrdinal(source, value, startIndex, count, ignoreCase: true); - } - - return LastIndexOfCore(source, value, startIndex, count, options); - } - - //////////////////////////////////////////////////////////////////////// - // - // GetSortKey - // - // Gets the SortKey for the given string with the given options. - // - //////////////////////////////////////////////////////////////////////// - public unsafe virtual SortKey GetSortKey(String source, CompareOptions options) - { - return CreateSortKey(source, options); - } - - - public unsafe virtual SortKey GetSortKey(String source) - { - return CreateSortKey(source, CompareOptions.None); - } - - //////////////////////////////////////////////////////////////////////// - // - // Equals - // - // Implements Object.Equals(). Returns a boolean indicating whether - // or not object refers to the same CompareInfo as the current - // instance. - // - //////////////////////////////////////////////////////////////////////// - - - public override bool Equals(Object value) - { - CompareInfo that = value as CompareInfo; - - if (that != null) - { - return this.Name == that.Name; - } - - return (false); - } - - - //////////////////////////////////////////////////////////////////////// - // - // GetHashCode - // - // Implements Object.GetHashCode(). Returns the hash code for the - // CompareInfo. The hash code is guaranteed to be the same for - // CompareInfo A and B where A.Equals(B) is true. - // - //////////////////////////////////////////////////////////////////////// - - - public override int GetHashCode() - { - return (this.Name.GetHashCode()); - } - - - //////////////////////////////////////////////////////////////////////// - // - // GetHashCodeOfString - // - // This internal method allows a method that allows the equivalent of creating a Sortkey for a - // string from CompareInfo, and generate a hashcode value from it. It is not very convenient - // to use this method as is and it creates an unnecessary Sortkey object that will be GC'ed. - // - // The hash code is guaranteed to be the same for string A and B where A.Equals(B) is true and both - // the CompareInfo and the CompareOptions are the same. If two different CompareInfo objects - // treat the string the same way, this implementation will treat them differently (the same way that - // Sortkey does at the moment). - // - // This method will never be made public itself, but public consumers of it could be created, e.g.: - // - // string.GetHashCode(CultureInfo) - // string.GetHashCode(CompareInfo) - // string.GetHashCode(CultureInfo, CompareOptions) - // string.GetHashCode(CompareInfo, CompareOptions) - // etc. - // - // (the methods above that take a CultureInfo would use CultureInfo.CompareInfo) - // - //////////////////////////////////////////////////////////////////////// - internal int GetHashCodeOfString(string source, CompareOptions options) - { - // - // Parameter validation - // - if (null == source) - { - throw new ArgumentNullException(nameof(source)); - } - - if ((options & ValidHashCodeOfStringMaskOffFlags) != 0) - { - throw new ArgumentException(SR.Argument_InvalidFlag, nameof(options)); - } - Contract.EndContractBlock(); - - return GetHashCodeOfStringCore(source, options); - } - - public virtual int GetHashCode(string source, CompareOptions options) - { - if (source == null) - { - throw new ArgumentNullException(nameof(source)); - } - - if (options == CompareOptions.Ordinal) - { - return source.GetHashCode(); - } - - if (options == CompareOptions.OrdinalIgnoreCase) - { - return TextInfo.GetHashCodeOrdinalIgnoreCase(source); - } - - // - // GetHashCodeOfString does more parameters validation. basically will throw when - // having Ordinal, OrdinalIgnoreCase and StringSort - // - - return GetHashCodeOfString(source, options); - } - - //////////////////////////////////////////////////////////////////////// - // - // ToString - // - // Implements Object.ToString(). Returns a string describing the - // CompareInfo. - // - //////////////////////////////////////////////////////////////////////// - public override String ToString() - { - return ("CompareInfo - " + this.Name); - } - - public SortVersion Version - { - get - { - if (_sortVersion == null) - { - _sortVersion = GetSortVersion(); - } - - return _sortVersion; - } - } - - public int LCID - { - get - { - return CultureInfo.GetCultureInfo(Name).LCID; - } - } - } -} diff --git a/src/mscorlib/corefx/System/Globalization/CultureData.cs b/src/mscorlib/corefx/System/Globalization/CultureData.cs deleted file mode 100644 index 0a8c2c2..0000000 --- a/src/mscorlib/corefx/System/Globalization/CultureData.cs +++ /dev/null @@ -1,2470 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System.Collections.Generic; -using System.Diagnostics; -using System.Text; -using System.Threading; - -namespace System.Globalization -{ - -#if CORECLR - using StringStringDictionary = Dictionary; - using StringCultureDataDictionary = Dictionary; - using LcidToCultureNameDictionary = Dictionary; - using Lock = Object; -#else - using StringStringDictionary = LowLevelDictionary; - using StringCultureDataDictionary = LowLevelDictionary; - using LcidToCultureNameDictionary = LowLevelDictionary; -#endif - - // - // List of culture data - // Note the we cache overrides. - // Note that localized names (resource names) aren't available from here. - // - - // - // Our names are a tad confusing. - // - // sWindowsName -- The name that windows thinks this culture is, ie: - // en-US if you pass in en-US - // de-DE_phoneb if you pass in de-DE_phoneb - // fj-FJ if you pass in fj (neutral, on a pre-Windows 7 machine) - // fj if you pass in fj (neutral, post-Windows 7 machine) - // - // sRealName -- The name you used to construct the culture, in pretty form - // en-US if you pass in EN-us - // en if you pass in en - // de-DE_phoneb if you pass in de-DE_phoneb - // - // sSpecificCulture -- The specific culture for this culture - // en-US for en-US - // en-US for en - // de-DE_phoneb for alt sort - // fj-FJ for fj (neutral) - // - // sName -- The IETF name of this culture (ie: no sort info, could be neutral) - // en-US if you pass in en-US - // en if you pass in en - // de-DE if you pass in de-DE_phoneb - // - internal partial class CultureData - { - private const int undef = -1; - - // Override flag - private String _sRealName; // Name you passed in (ie: en-US, en, or de-DE_phoneb) - private String _sWindowsName; // Name OS thinks the object is (ie: de-DE_phoneb, or en-US (even if en was passed in)) - - // Identity - private String _sName; // locale name (ie: en-us, NO sort info, but could be neutral) - private String _sParent; // Parent name (which may be a custom locale/culture) - private String _sLocalizedDisplayName; // Localized pretty name for this locale - private String _sEnglishDisplayName; // English pretty name for this locale - private String _sNativeDisplayName; // Native pretty name for this locale - private String _sSpecificCulture; // The culture name to be used in CultureInfo.CreateSpecificCulture(), en-US form if neutral, sort name if sort - - // Language - private String _sISO639Language; // ISO 639 Language Name - private String _sISO639Language2; // ISO 639 Language Name - private String _sLocalizedLanguage; // Localized name for this language - private String _sEnglishLanguage; // English name for this language - private String _sNativeLanguage; // Native name of this language - private String _sAbbrevLang; // abbreviated language name (Windows Language Name) ex: ENU - private string _sConsoleFallbackName; // The culture name for the console fallback UI culture - private int _iInputLanguageHandle=undef;// input language handle - - // Region - private String _sRegionName; // (RegionInfo) - private String _sLocalizedCountry; // localized country name - private String _sEnglishCountry; // english country name (RegionInfo) - private String _sNativeCountry; // native country name - private String _sISO3166CountryName; // ISO 3166 (RegionInfo), ie: US - private String _sISO3166CountryName2; // 3 char ISO 3166 country name 2 2(RegionInfo) ex: USA (ISO) - private int _iGeoId = undef; // GeoId - - // Numbers - private String _sPositiveSign; // (user can override) positive sign - private String _sNegativeSign; // (user can override) negative sign - // (nfi populates these 5, don't have to be = undef) - private int _iDigits; // (user can override) number of fractional digits - private int _iNegativeNumber; // (user can override) negative number format - private int[] _waGrouping; // (user can override) grouping of digits - private String _sDecimalSeparator; // (user can override) decimal separator - private String _sThousandSeparator; // (user can override) thousands separator - private String _sNaN; // Not a Number - private String _sPositiveInfinity; // + Infinity - private String _sNegativeInfinity; // - Infinity - - // Percent - private int _iNegativePercent = undef; // Negative Percent (0-3) - private int _iPositivePercent = undef; // Positive Percent (0-11) - private String _sPercent; // Percent (%) symbol - private String _sPerMille; // PerMille symbol - - // Currency - private String _sCurrency; // (user can override) local monetary symbol - private String _sIntlMonetarySymbol; // international monetary symbol (RegionInfo) - private String _sEnglishCurrency; // English name for this currency - private String _sNativeCurrency; // Native name for this currency - // (nfi populates these 4, don't have to be = undef) - private int _iCurrencyDigits; // (user can override) # local monetary fractional digits - private int _iCurrency; // (user can override) positive currency format - private int _iNegativeCurrency; // (user can override) negative currency format - private int[] _waMonetaryGrouping; // (user can override) monetary grouping of digits - private String _sMonetaryDecimal; // (user can override) monetary decimal separator - private String _sMonetaryThousand; // (user can override) monetary thousands separator - - // Misc - private int _iMeasure = undef; // (user can override) system of measurement 0=metric, 1=US (RegionInfo) - private String _sListSeparator; // (user can override) list separator - - // Time - private String _sAM1159; // (user can override) AM designator - private String _sPM2359; // (user can override) PM designator - private String _sTimeSeparator; - private volatile String[] _saLongTimes; // (user can override) time format - private volatile String[] _saShortTimes; // short time format - private volatile String[] _saDurationFormats; // time duration format - - // Calendar specific data - private int _iFirstDayOfWeek = undef; // (user can override) first day of week (gregorian really) - private int _iFirstWeekOfYear = undef; // (user can override) first week of year (gregorian really) - private volatile CalendarId[] _waCalendars; // all available calendar type(s). The first one is the default calendar - - // Store for specific data about each calendar - private CalendarData[] _calendars; // Store for specific calendar data - - // Text information - private int _iReadingLayout = undef; // Reading layout data - // 0 - Left to right (eg en-US) - // 1 - Right to left (eg arabic locales) - // 2 - Vertical top to bottom with columns to the left and also left to right (ja-JP locales) - // 3 - Vertical top to bottom with columns proceeding to the right - - // CoreCLR depends on this even though its not exposed publicly. - - private int _iDefaultAnsiCodePage = undef; // default ansi code page ID (ACP) - private int _iDefaultOemCodePage = undef; // default oem code page ID (OCP or OEM) - private int _iDefaultMacCodePage = undef; // default macintosh code page - private int _iDefaultEbcdicCodePage = undef; // default EBCDIC code page - - private int _iLanguage; // locale ID (0409) - NO sort information - private bool _bUseOverrides; // use user overrides? - private bool _bNeutral; // Flags for the culture (ie: neutral or not right now) - - - // Region Name to Culture Name mapping table - // (In future would be nice to be in registry or something) - - //Using a property so we avoid creating the dictionary untill we need it - private static StringStringDictionary RegionNames - { - get - { - if (s_RegionNames == null) - { - StringStringDictionary regionNames = new StringStringDictionary(211 /* prime */); - - regionNames.Add("029", "en-029"); - regionNames.Add("AE", "ar-AE"); - regionNames.Add("AF", "prs-AF"); - regionNames.Add("AL", "sq-AL"); - regionNames.Add("AM", "hy-AM"); - regionNames.Add("AR", "es-AR"); - regionNames.Add("AT", "de-AT"); - regionNames.Add("AU", "en-AU"); - regionNames.Add("AZ", "az-Cyrl-AZ"); - regionNames.Add("BA", "bs-Latn-BA"); - regionNames.Add("BD", "bn-BD"); - regionNames.Add("BE", "nl-BE"); - regionNames.Add("BG", "bg-BG"); - regionNames.Add("BH", "ar-BH"); - regionNames.Add("BN", "ms-BN"); - regionNames.Add("BO", "es-BO"); - regionNames.Add("BR", "pt-BR"); - regionNames.Add("BY", "be-BY"); - regionNames.Add("BZ", "en-BZ"); - regionNames.Add("CA", "en-CA"); - regionNames.Add("CH", "it-CH"); - regionNames.Add("CL", "es-CL"); - regionNames.Add("CN", "zh-CN"); - regionNames.Add("CO", "es-CO"); - regionNames.Add("CR", "es-CR"); - regionNames.Add("CS", "sr-Cyrl-CS"); - regionNames.Add("CZ", "cs-CZ"); - regionNames.Add("DE", "de-DE"); - regionNames.Add("DK", "da-DK"); - regionNames.Add("DO", "es-DO"); - regionNames.Add("DZ", "ar-DZ"); - regionNames.Add("EC", "es-EC"); - regionNames.Add("EE", "et-EE"); - regionNames.Add("EG", "ar-EG"); - regionNames.Add("ES", "es-ES"); - regionNames.Add("ET", "am-ET"); - regionNames.Add("FI", "fi-FI"); - regionNames.Add("FO", "fo-FO"); - regionNames.Add("FR", "fr-FR"); - regionNames.Add("GB", "en-GB"); - regionNames.Add("GE", "ka-GE"); - regionNames.Add("GL", "kl-GL"); - regionNames.Add("GR", "el-GR"); - regionNames.Add("GT", "es-GT"); - regionNames.Add("HK", "zh-HK"); - regionNames.Add("HN", "es-HN"); - regionNames.Add("HR", "hr-HR"); - regionNames.Add("HU", "hu-HU"); - regionNames.Add("ID", "id-ID"); - regionNames.Add("IE", "en-IE"); - regionNames.Add("IL", "he-IL"); - regionNames.Add("IN", "hi-IN"); - regionNames.Add("IQ", "ar-IQ"); - regionNames.Add("IR", "fa-IR"); - regionNames.Add("IS", "is-IS"); - regionNames.Add("IT", "it-IT"); - regionNames.Add("IV", ""); - regionNames.Add("JM", "en-JM"); - regionNames.Add("JO", "ar-JO"); - regionNames.Add("JP", "ja-JP"); - regionNames.Add("KE", "sw-KE"); - regionNames.Add("KG", "ky-KG"); - regionNames.Add("KH", "km-KH"); - regionNames.Add("KR", "ko-KR"); - regionNames.Add("KW", "ar-KW"); - regionNames.Add("KZ", "kk-KZ"); - regionNames.Add("LA", "lo-LA"); - regionNames.Add("LB", "ar-LB"); - regionNames.Add("LI", "de-LI"); - regionNames.Add("LK", "si-LK"); - regionNames.Add("LT", "lt-LT"); - regionNames.Add("LU", "lb-LU"); - regionNames.Add("LV", "lv-LV"); - regionNames.Add("LY", "ar-LY"); - regionNames.Add("MA", "ar-MA"); - regionNames.Add("MC", "fr-MC"); - regionNames.Add("ME", "sr-Latn-ME"); - regionNames.Add("MK", "mk-MK"); - regionNames.Add("MN", "mn-MN"); - regionNames.Add("MO", "zh-MO"); - regionNames.Add("MT", "mt-MT"); - regionNames.Add("MV", "dv-MV"); - regionNames.Add("MX", "es-MX"); - regionNames.Add("MY", "ms-MY"); - regionNames.Add("NG", "ig-NG"); - regionNames.Add("NI", "es-NI"); - regionNames.Add("NL", "nl-NL"); - regionNames.Add("NO", "nn-NO"); - regionNames.Add("NP", "ne-NP"); - regionNames.Add("NZ", "en-NZ"); - regionNames.Add("OM", "ar-OM"); - regionNames.Add("PA", "es-PA"); - regionNames.Add("PE", "es-PE"); - regionNames.Add("PH", "en-PH"); - regionNames.Add("PK", "ur-PK"); - regionNames.Add("PL", "pl-PL"); - regionNames.Add("PR", "es-PR"); - regionNames.Add("PT", "pt-PT"); - regionNames.Add("PY", "es-PY"); - regionNames.Add("QA", "ar-QA"); - regionNames.Add("RO", "ro-RO"); - regionNames.Add("RS", "sr-Latn-RS"); - regionNames.Add("RU", "ru-RU"); - regionNames.Add("RW", "rw-RW"); - regionNames.Add("SA", "ar-SA"); - regionNames.Add("SE", "sv-SE"); - regionNames.Add("SG", "zh-SG"); - regionNames.Add("SI", "sl-SI"); - regionNames.Add("SK", "sk-SK"); - regionNames.Add("SN", "wo-SN"); - regionNames.Add("SV", "es-SV"); - regionNames.Add("SY", "ar-SY"); - regionNames.Add("TH", "th-TH"); - regionNames.Add("TJ", "tg-Cyrl-TJ"); - regionNames.Add("TM", "tk-TM"); - regionNames.Add("TN", "ar-TN"); - regionNames.Add("TR", "tr-TR"); - regionNames.Add("TT", "en-TT"); - regionNames.Add("TW", "zh-TW"); - regionNames.Add("UA", "uk-UA"); - regionNames.Add("US", "en-US"); - regionNames.Add("UY", "es-UY"); - regionNames.Add("UZ", "uz-Cyrl-UZ"); - regionNames.Add("VE", "es-VE"); - regionNames.Add("VN", "vi-VN"); - regionNames.Add("YE", "ar-YE"); - regionNames.Add("ZA", "af-ZA"); - regionNames.Add("ZW", "en-ZW"); - - s_RegionNames = regionNames; - } - - return s_RegionNames; - } - } - - // Cache of regions we've already looked up - private static volatile StringCultureDataDictionary s_cachedRegions; - private static volatile StringStringDictionary s_RegionNames; - - internal static CultureData GetCultureDataForRegion(String cultureName, bool useUserOverride) - { - // First do a shortcut for Invariant - if (String.IsNullOrEmpty(cultureName)) - { - return CultureData.Invariant; - } - - // - // First check if GetCultureData() can find it (ie: its a real culture) - // - CultureData retVal = GetCultureData(cultureName, useUserOverride); - if (retVal != null && (retVal.IsNeutralCulture == false)) return retVal; - - // - // Not a specific culture, perhaps it's region-only name - // (Remember this isn't a core clr path where that's not supported) - // - - // If it was neutral remember that so that RegionInfo() can throw the right exception - CultureData neutral = retVal; - - // Try the hash table next - String hashName = AnsiToLower(useUserOverride ? cultureName : cultureName + '*'); - StringCultureDataDictionary tempHashTable = s_cachedRegions; - if (tempHashTable == null) - { - // No table yet, make a new one - tempHashTable = new StringCultureDataDictionary(); - } - else - { - // Check the hash table - lock (s_lock) - { - tempHashTable.TryGetValue(hashName, out retVal); - } - if (retVal != null) - { - return retVal; - } - } - - // - // Not found in the hash table, look it up the hard way - // - - // If not a valid mapping from the registry we'll have to try the hard coded table - if (retVal == null || (retVal.IsNeutralCulture == true)) - { - // Not a valid mapping, try the hard coded table - string name; - if (RegionNames.TryGetValue(cultureName, out name)) - { - // Make sure we can get culture data for it - retVal = GetCultureData(name, useUserOverride); - } - } - - // If not found in the hard coded table we'll have to find a culture that works for us - if (retVal == null || (retVal.IsNeutralCulture == true)) - { - retVal = GetCultureDataFromRegionName(cultureName); - } - - // If we found one we can use, then cache it for next time - if (retVal != null && (retVal.IsNeutralCulture == false)) - { - // first add it to the cache - lock (s_lock) - { - tempHashTable[hashName] = retVal; - } - - // Copy the hashtable to the corresponding member variables. This will potentially overwrite - // new tables simultaneously created by a new thread, but maximizes thread safety. - s_cachedRegions = tempHashTable; - } - else - { - // Unable to find a matching culture/region, return null or neutral - // (regionInfo throws a more specific exception on neutrals) - retVal = neutral; - } - - // Return the found culture to use, null, or the neutral culture. - return retVal; - } - - // Clear our internal caches - internal static void ClearCachedData() - { - s_cachedCultures = null; - s_cachedRegions = null; - } - - internal static CultureInfo[] GetCultures(CultureTypes types) - { - // Disable warning 618: System.Globalization.CultureTypes.FrameworkCultures' is obsolete -#pragma warning disable 618 - // Validate flags - if ((int)types <= 0 || ((int)types & (int)~(CultureTypes.NeutralCultures | CultureTypes.SpecificCultures | - CultureTypes.InstalledWin32Cultures | CultureTypes.UserCustomCulture | - CultureTypes.ReplacementCultures | CultureTypes.WindowsOnlyCultures | - CultureTypes.FrameworkCultures)) != 0) - { - throw new ArgumentOutOfRangeException(nameof(types), - SR.Format(SR.ArgumentOutOfRange_Range, CultureTypes.NeutralCultures, CultureTypes.FrameworkCultures)); - } - - // We have deprecated CultureTypes.FrameworkCultures. - // When this enum is used, we will enumerate Whidbey framework cultures (for compatibility). - // - - // We have deprecated CultureTypes.WindowsOnlyCultures. - // When this enum is used, we will return an empty array for this enum. - if ((types & CultureTypes.WindowsOnlyCultures) != 0) - { - // Remove the enum as it is an no-op. - types &= (~CultureTypes.WindowsOnlyCultures); - } - -#pragma warning restore 618 - return EnumCultures(types); - } - - ///////////////////////////////////////////////////////////////////////// - // Build our invariant information - // - // We need an invariant instance, which we build hard-coded - ///////////////////////////////////////////////////////////////////////// - internal static CultureData Invariant - { - get - { - if (s_Invariant == null) - { - // Make a new culturedata - CultureData invariant = new CultureData(); - - // Basics - // Note that we override the resources since this IS NOT supposed to change (by definition) - invariant._bUseOverrides = false; - invariant._sRealName = ""; // Name you passed in (ie: en-US, en, or de-DE_phoneb) - invariant._sWindowsName = ""; // Name OS thinks the object is (ie: de-DE_phoneb, or en-US (even if en was passed in)) - - // Identity - invariant._sName = ""; // locale name (ie: en-us) - invariant._sParent = ""; // Parent name (which may be a custom locale/culture) - invariant._bNeutral = false; // Flags for the culture (ie: neutral or not right now) - invariant._sEnglishDisplayName = "Invariant Language (Invariant Country)"; // English pretty name for this locale - invariant._sNativeDisplayName = "Invariant Language (Invariant Country)"; // Native pretty name for this locale - invariant._sSpecificCulture = ""; // The culture name to be used in CultureInfo.CreateSpecificCulture() - - // Language - invariant._sISO639Language = "iv"; // ISO 639 Language Name - invariant._sISO639Language2 = "ivl"; // 3 char ISO 639 lang name 2 - invariant._sLocalizedLanguage = "Invariant Language"; // Display name for this Language - invariant._sEnglishLanguage = "Invariant Language"; // English name for this language - invariant._sNativeLanguage = "Invariant Language"; // Native name of this language - invariant._sAbbrevLang = "IVL"; // abbreviated language name (Windows Language Name) - invariant._sConsoleFallbackName = ""; // The culture name for the console fallback UI culture - invariant._iInputLanguageHandle = 0x07F; // input language handle - - // Region - invariant._sRegionName = "IV"; // (RegionInfo) - invariant._sEnglishCountry = "Invariant Country"; // english country name (RegionInfo) - invariant._sNativeCountry = "Invariant Country"; // native country name (Windows Only) - invariant._sISO3166CountryName = "IV"; // (RegionInfo), ie: US - invariant._sISO3166CountryName2 = "ivc"; // 3 char ISO 3166 country name 2 2(RegionInfo) - invariant._iGeoId = 244; // GeoId (Windows Only) - - // Numbers - invariant._sPositiveSign = "+"; // positive sign - invariant._sNegativeSign = "-"; // negative sign - invariant._iDigits = 2; // number of fractional digits - invariant._iNegativeNumber = 1; // negative number format - invariant._waGrouping = new int[] { 3 }; // grouping of digits - invariant._sDecimalSeparator = "."; // decimal separator - invariant._sThousandSeparator = ","; // thousands separator - invariant._sNaN = "NaN"; // Not a Number - invariant._sPositiveInfinity = "Infinity"; // + Infinity - invariant._sNegativeInfinity = "-Infinity"; // - Infinity - - // Percent - invariant._iNegativePercent = 0; // Negative Percent (0-3) - invariant._iPositivePercent = 0; // Positive Percent (0-11) - invariant._sPercent = "%"; // Percent (%) symbol - invariant._sPerMille = "\x2030"; // PerMille symbol - - // Currency - invariant._sCurrency = "\x00a4"; // local monetary symbol: for international monetary symbol - invariant._sIntlMonetarySymbol = "XDR"; // international monetary symbol (RegionInfo) - invariant._sEnglishCurrency = "International Monetary Fund"; // English name for this currency (Windows Only) - invariant._sNativeCurrency = "International Monetary Fund"; // Native name for this currency (Windows Only) - invariant._iCurrencyDigits = 2; // # local monetary fractional digits - invariant._iCurrency = 0; // positive currency format - invariant._iNegativeCurrency = 0; // negative currency format - invariant._waMonetaryGrouping = new int[] { 3 }; // monetary grouping of digits - invariant._sMonetaryDecimal = "."; // monetary decimal separator - invariant._sMonetaryThousand = ","; // monetary thousands separator - - // Misc - invariant._iMeasure = 0; // system of measurement 0=metric, 1=US (RegionInfo) - invariant._sListSeparator = ","; // list separator - - // Time - invariant._sAM1159 = "AM"; // AM designator - invariant._sPM2359 = "PM"; // PM designator - invariant._saLongTimes = new String[] { "HH:mm:ss" }; // time format - invariant._saShortTimes = new String[] { "HH:mm", "hh:mm tt", "H:mm", "h:mm tt" }; // short time format - invariant._saDurationFormats = new String[] { "HH:mm:ss" }; // time duration format - - - // Calendar specific data - invariant._iFirstDayOfWeek = 0; // first day of week - invariant._iFirstWeekOfYear = 0; // first week of year - invariant._waCalendars = new CalendarId[] { CalendarId.GREGORIAN }; // all available calendar type(s). The first one is the default calendar - - // Store for specific data about each calendar - invariant._calendars = new CalendarData[CalendarData.MAX_CALENDARS]; - invariant._calendars[0] = CalendarData.Invariant; - - // Text information - invariant._iReadingLayout = 0; - - // These are desktop only, not coreclr - - invariant._iLanguage = CultureInfo.LOCALE_INVARIANT; // locale ID (0409) - NO sort information - invariant._iDefaultAnsiCodePage = 1252; // default ansi code page ID (ACP) - invariant._iDefaultOemCodePage = 437; // default oem code page ID (OCP or OEM) - invariant._iDefaultMacCodePage = 10000; // default macintosh code page - invariant._iDefaultEbcdicCodePage = 037; // default EBCDIC code page - // Remember it - s_Invariant = invariant; - } - return s_Invariant; - } - } - private volatile static CultureData s_Invariant; - - /////////////// - // Constructors // - /////////////// - // Cache of cultures we've already looked up - private static volatile StringCultureDataDictionary s_cachedCultures; - private static readonly Lock s_lock = new Lock(); - - internal static CultureData GetCultureData(String cultureName, bool useUserOverride) - { - // First do a shortcut for Invariant - if (String.IsNullOrEmpty(cultureName)) - { - return CultureData.Invariant; - } - - // Try the hash table first - String hashName = AnsiToLower(useUserOverride ? cultureName : cultureName + '*'); - StringCultureDataDictionary tempHashTable = s_cachedCultures; - if (tempHashTable == null) - { - // No table yet, make a new one - tempHashTable = new StringCultureDataDictionary(); - } - else - { - // Check the hash table - bool ret; - CultureData retVal; - lock (s_lock) - { - ret = tempHashTable.TryGetValue(hashName, out retVal); - } - if (ret && retVal != null) - { - return retVal; - } - } - - // Not found in the hash table, need to see if we can build one that works for us - CultureData culture = CreateCultureData(cultureName, useUserOverride); - if (culture == null) - { - return null; - } - - // Found one, add it to the cache - lock (s_lock) - { - tempHashTable[hashName] = culture; - } - - // Copy the hashtable to the corresponding member variables. This will potentially overwrite - // new tables simultaneously created by a new thread, but maximizes thread safety. - s_cachedCultures = tempHashTable; - - return culture; - } - - private static CultureData CreateCultureData(string cultureName, bool useUserOverride) - { - CultureData culture = new CultureData(); - culture._bUseOverrides = useUserOverride; - culture._sRealName = cultureName; - - // Ask native code if that one's real - if (culture.InitCultureData() == false) - { - if (culture.InitCompatibilityCultureData() == false) - { - return null; - } - } - - return culture; - } - - private bool InitCompatibilityCultureData() - { - // for compatibility handle the deprecated ids: zh-chs, zh-cht - string cultureName = _sRealName; - - string fallbackCultureName; - string realCultureName; - switch (AnsiToLower(cultureName)) - { - case "zh-chs": - fallbackCultureName = "zh-Hans"; - realCultureName = "zh-CHS"; - break; - case "zh-cht": - fallbackCultureName = "zh-Hant"; - realCultureName = "zh-CHT"; - break; - default: - return false; - } - - _sRealName = fallbackCultureName; - if (InitCultureData() == false) - { - return false; - } - // fixup our data - _sName = realCultureName; // the name that goes back to the user - _sParent = fallbackCultureName; - - return true; - } - - // We'd rather people use the named version since this doesn't allow custom locales - internal static CultureData GetCultureData(int culture, bool bUseUserOverride) - { - string localeName = null; - CultureData retVal = null; - - if (culture == CultureInfo.LOCALE_INVARIANT) - return Invariant; - - // Convert the lcid to a name, then use that - // Note that this'll return neutral names (unlike Vista native API) - localeName = LCIDToLocaleName(culture); - - if (!String.IsNullOrEmpty(localeName)) - { - // Valid name, use it - retVal = GetCultureData(localeName, bUseUserOverride); - } - - // If not successful, throw - if (retVal == null) - throw new CultureNotFoundException(nameof(culture), culture, SR.Argument_CultureNotSupported); - - // Return the one we found - return retVal; - } - - //////////////////////////////////////////////////////////////////////// - // - // All the accessors - // - // Accessors for our data object items - // - //////////////////////////////////////////////////////////////////////// - - /////////// - // Identity // - /////////// - - // The real name used to construct the locale (ie: de-DE_phoneb) - internal String CultureName - { - get - { - Debug.Assert(_sRealName != null, "[CultureData.CultureName] Expected _sRealName to be populated by already"); - // since windows doesn't know about zh-CHS and zh-CHT, - // we leave sRealName == zh-Hanx but we still need to - // pretend that it was zh-CHX. - switch (_sName) - { - case "zh-CHS": - case "zh-CHT": - return _sName; - } - return _sRealName; - } - } - - // Are overrides enabled? - internal bool UseUserOverride - { - get - { - return _bUseOverrides; - } - } - - // locale name (ie: de-DE, NO sort information) - internal String SNAME - { - get - { - if (_sName == null) - { - _sName = String.Empty; - } - return _sName; - } - } - - // Parent name (which may be a custom locale/culture) - internal String SPARENT - { - get - { - if (_sParent == null) - { - // Ask using the real name, so that we get parents of neutrals - _sParent = GetLocaleInfo(_sRealName, LocaleStringData.ParentName); - } - return _sParent; - } - } - - // Localized pretty name for this locale (ie: Inglis (estados Unitos)) - internal String SLOCALIZEDDISPLAYNAME - { - get - { - if (_sLocalizedDisplayName == null) - { - if (this.IsSupplementalCustomCulture) - { - if (this.IsNeutralCulture) - { - _sLocalizedDisplayName = this.SNATIVELANGUAGE; - } - else - { - _sLocalizedDisplayName = this.SNATIVEDISPLAYNAME; - } - } - else - { - try - { - const string ZH_CHT = "zh-CHT"; - const string ZH_CHS = "zh-CHS"; - - if (SNAME.Equals(ZH_CHT, StringComparison.OrdinalIgnoreCase)) - { - _sLocalizedDisplayName = GetLanguageDisplayName("zh-Hant"); - } - else if (SNAME.Equals(ZH_CHS, StringComparison.OrdinalIgnoreCase)) - { - _sLocalizedDisplayName = GetLanguageDisplayName("zh-Hans"); - } - else - { - _sLocalizedDisplayName = GetLanguageDisplayName(SNAME); - } - } - catch (Exception) - { - // do nothing - } - } - // If it hasn't been found (Windows 8 and up), fallback to the system - if (String.IsNullOrEmpty(_sLocalizedDisplayName)) - { - // If its neutral use the language name - if (this.IsNeutralCulture) - { - _sLocalizedDisplayName = this.SLOCALIZEDLANGUAGE; - } - else - { - // Usually the UI culture shouldn't be different than what we got from WinRT except - // if DefaultThreadCurrentUICulture was set - CultureInfo ci; - - if (CultureInfo.DefaultThreadCurrentUICulture != null && - ((ci = GetUserDefaultCulture()) != null) && - !CultureInfo.DefaultThreadCurrentUICulture.Name.Equals(ci.Name)) - { - _sLocalizedDisplayName = this.SNATIVEDISPLAYNAME; - } - else - { - _sLocalizedDisplayName = GetLocaleInfo(LocaleStringData.LocalizedDisplayName); - } - } - } - } - - return _sLocalizedDisplayName; - } - } - - // English pretty name for this locale (ie: English (United States)) - internal String SENGDISPLAYNAME - { - get - { - if (_sEnglishDisplayName == null) - { - // If its neutral use the language name - if (this.IsNeutralCulture) - { - _sEnglishDisplayName = this.SENGLISHLANGUAGE; - // differentiate the legacy display names - switch (_sName) - { - case "zh-CHS": - case "zh-CHT": - _sEnglishDisplayName += " Legacy"; - break; - } - } - else - { - _sEnglishDisplayName = GetLocaleInfo(LocaleStringData.EnglishDisplayName); - - // if it isn't found build one: - if (String.IsNullOrEmpty(_sEnglishDisplayName)) - { - // Our existing names mostly look like: - // "English" + "United States" -> "English (United States)" - // "Azeri (Latin)" + "Azerbaijan" -> "Azeri (Latin, Azerbaijan)" - if (this.SENGLISHLANGUAGE[this.SENGLISHLANGUAGE.Length - 1] == ')') - { - // "Azeri (Latin)" + "Azerbaijan" -> "Azeri (Latin, Azerbaijan)" - _sEnglishDisplayName = - this.SENGLISHLANGUAGE.Substring(0, _sEnglishLanguage.Length - 1) + - ", " + this.SENGCOUNTRY + ")"; - } - else - { - // "English" + "United States" -> "English (United States)" - _sEnglishDisplayName = this.SENGLISHLANGUAGE + " (" + this.SENGCOUNTRY + ")"; - } - } - } - } - return _sEnglishDisplayName; - } - } - - // Native pretty name for this locale (ie: Deutsch (Deutschland)) - internal String SNATIVEDISPLAYNAME - { - get - { - if (_sNativeDisplayName == null) - { - // If its neutral use the language name - if (this.IsNeutralCulture) - { - _sNativeDisplayName = this.SNATIVELANGUAGE; - // differentiate the legacy display names - switch (_sName) - { - case "zh-CHS": - _sNativeDisplayName += " \u65E7\u7248"; - break; - case "zh-CHT": - _sNativeDisplayName += " \u820A\u7248"; - break; - } - } - else - { - _sNativeDisplayName = GetLocaleInfo(LocaleStringData.NativeDisplayName); - - // if it isn't found build one: - if (String.IsNullOrEmpty(_sNativeDisplayName)) - { - // These should primarily be "Deutsch (Deutschland)" type names - _sNativeDisplayName = this.SNATIVELANGUAGE + " (" + this.SNATIVECOUNTRY + ")"; - } - } - } - return _sNativeDisplayName; - } - } - - // The culture name to be used in CultureInfo.CreateSpecificCulture() - internal string SSPECIFICCULTURE - { - get - { - // This got populated during the culture initialization - Debug.Assert(_sSpecificCulture != null, "[CultureData.SSPECIFICCULTURE] Expected this.sSpecificCulture to be populated by culture data initialization already"); - return _sSpecificCulture; - } - } - - ///////////// - // Language // - ///////////// - - // iso 639 language name, ie: en - internal String SISO639LANGNAME - { - get - { - if (_sISO639Language == null) - { - _sISO639Language = GetLocaleInfo(LocaleStringData.Iso639LanguageTwoLetterName); - } - return _sISO639Language; - } - } - - // iso 639 language name, ie: eng - internal string SISO639LANGNAME2 - { - get - { - if (_sISO639Language2 == null) - { - _sISO639Language2 = GetLocaleInfo(LocaleStringData.Iso639LanguageThreeLetterName); - } - return _sISO639Language2; - } - } - - // abbreviated windows language name (ie: enu) (non-standard, avoid this) - internal string SABBREVLANGNAME - { - get - { - if (_sAbbrevLang == null) - { - _sAbbrevLang = GetThreeLetterWindowsLanguageName(_sRealName); - } - return _sAbbrevLang; - } - } - - // Localized name for this language (Windows Only) ie: Inglis - // This is only valid for Windows 8 and higher neutrals: - internal String SLOCALIZEDLANGUAGE - { - get - { - if (_sLocalizedLanguage == null) - { - // Usually the UI culture shouldn't be different than what we got from WinRT except - // if DefaultThreadCurrentUICulture was set - CultureInfo ci; - - if (CultureInfo.DefaultThreadCurrentUICulture != null && - ((ci = GetUserDefaultCulture()) != null) && - !CultureInfo.DefaultThreadCurrentUICulture.Name.Equals(ci.Name)) - { - _sLocalizedLanguage = SNATIVELANGUAGE; - } - else - { - _sLocalizedLanguage = GetLocaleInfo(LocaleStringData.LocalizedLanguageName); - } - } - - return _sLocalizedLanguage; - } - } - - // English name for this language (Windows Only) ie: German - internal String SENGLISHLANGUAGE - { - get - { - if (_sEnglishLanguage == null) - { - _sEnglishLanguage = GetLocaleInfo(LocaleStringData.EnglishLanguageName); - } - return _sEnglishLanguage; - } - } - - // Native name of this language (Windows Only) ie: Deutsch - internal String SNATIVELANGUAGE - { - get - { - if (_sNativeLanguage == null) - { - _sNativeLanguage = GetLocaleInfo(LocaleStringData.NativeLanguageName); - } - return _sNativeLanguage; - } - } - - /////////// - // Region // - /////////// - - // region name (eg US) - internal String SREGIONNAME - { - get - { - if (_sRegionName == null) - { - _sRegionName = GetLocaleInfo(LocaleStringData.Iso3166CountryName); - } - return _sRegionName; - } - } - - internal int IGEOID - { - get - { - if (_iGeoId == undef) - { - _iGeoId = GetGeoId(_sRealName); - } - return _iGeoId; - } - } - - // localized name for the country - internal string SLOCALIZEDCOUNTRY - { - get - { - if (_sLocalizedCountry == null) - { - try - { - _sLocalizedCountry = GetRegionDisplayName(SISO3166CTRYNAME); - } - catch (Exception) - { - // do nothing. we'll fallback - } - - if (_sLocalizedCountry == null) - { - _sLocalizedCountry = SNATIVECOUNTRY; - } - } - return _sLocalizedCountry; - } - } - - // english country name (RegionInfo) ie: Germany - internal String SENGCOUNTRY - { - get - { - if (_sEnglishCountry == null) - { - _sEnglishCountry = GetLocaleInfo(LocaleStringData.EnglishCountryName); - } - return _sEnglishCountry; - } - } - - // native country name (RegionInfo) ie: Deutschland - internal String SNATIVECOUNTRY - { - get - { - if (_sNativeCountry == null) - { - _sNativeCountry = GetLocaleInfo(LocaleStringData.NativeCountryName); - } - return _sNativeCountry; - } - } - - // ISO 3166 Country Name - internal String SISO3166CTRYNAME - { - get - { - if (_sISO3166CountryName == null) - { - _sISO3166CountryName = GetLocaleInfo(LocaleStringData.Iso3166CountryName); - } - return _sISO3166CountryName; - } - } - - // 3 letter ISO 3166 country code - internal String SISO3166CTRYNAME2 - { - get - { - if (_sISO3166CountryName2 == null) - { - _sISO3166CountryName2 = GetLocaleInfo(LocaleStringData.Iso3166CountryName2); - } - return _sISO3166CountryName2; - } - } - - internal int IINPUTLANGUAGEHANDLE - { - get - { - if (_iInputLanguageHandle == undef) - { - if (IsSupplementalCustomCulture) - { - _iInputLanguageHandle = 0x0409; - } - else - { - // Input Language is same as LCID for built-in cultures - _iInputLanguageHandle = this.ILANGUAGE; - } - } - return _iInputLanguageHandle; - } - } - - // Console fallback name (ie: locale to use for console apps for unicode-only locales) - internal string SCONSOLEFALLBACKNAME - { - get - { - if (_sConsoleFallbackName == null) - { - _sConsoleFallbackName = GetConsoleFallbackName(_sRealName); - } - return _sConsoleFallbackName; - } - } - - // (user can override) grouping of digits - internal int[] WAGROUPING - { - get - { - if (_waGrouping == null) - { - _waGrouping = GetLocaleInfo(LocaleGroupingData.Digit); - } - return _waGrouping; - } - } - - - // internal String sDecimalSeparator ; // (user can override) decimal separator - // internal String sThousandSeparator ; // (user can override) thousands separator - - // Not a Number - internal String SNAN - { - get - { - if (_sNaN == null) - { - _sNaN = GetLocaleInfo(LocaleStringData.NaNSymbol); - } - return _sNaN; - } - } - - // + Infinity - internal String SPOSINFINITY - { - get - { - if (_sPositiveInfinity == null) - { - _sPositiveInfinity = GetLocaleInfo(LocaleStringData.PositiveInfinitySymbol); - } - return _sPositiveInfinity; - } - } - - // - Infinity - internal String SNEGINFINITY - { - get - { - if (_sNegativeInfinity == null) - { - _sNegativeInfinity = GetLocaleInfo(LocaleStringData.NegativeInfinitySymbol); - } - return _sNegativeInfinity; - } - } - - - //////////// - // Percent // - /////////// - - // Negative Percent (0-3) - internal int INEGATIVEPERCENT - { - get - { - if (_iNegativePercent == undef) - { - // Note that <= Windows Vista this is synthesized by native code - _iNegativePercent = GetLocaleInfo(LocaleNumberData.NegativePercentFormat); - } - return _iNegativePercent; - } - } - - // Positive Percent (0-11) - internal int IPOSITIVEPERCENT - { - get - { - if (_iPositivePercent == undef) - { - // Note that <= Windows Vista this is synthesized by native code - _iPositivePercent = GetLocaleInfo(LocaleNumberData.PositivePercentFormat); - } - return _iPositivePercent; - } - } - - // Percent (%) symbol - internal String SPERCENT - { - get - { - if (_sPercent == null) - { - _sPercent = GetLocaleInfo(LocaleStringData.PercentSymbol); - } - return _sPercent; - } - } - - // PerMille symbol - internal String SPERMILLE - { - get - { - if (_sPerMille == null) - { - _sPerMille = GetLocaleInfo(LocaleStringData.PerMilleSymbol); - } - return _sPerMille; - } - } - - ///////////// - // Currency // - ///////////// - - // (user can override) local monetary symbol, eg: $ - internal String SCURRENCY - { - get - { - if (_sCurrency == null) - { - _sCurrency = GetLocaleInfo(LocaleStringData.MonetarySymbol); - } - return _sCurrency; - } - } - - // international monetary symbol (RegionInfo), eg: USD - internal String SINTLSYMBOL - { - get - { - if (_sIntlMonetarySymbol == null) - { - _sIntlMonetarySymbol = GetLocaleInfo(LocaleStringData.Iso4217MonetarySymbol); - } - return _sIntlMonetarySymbol; - } - } - - // English name for this currency (RegionInfo), eg: US Dollar - internal String SENGLISHCURRENCY - { - get - { - if (_sEnglishCurrency == null) - { - _sEnglishCurrency = GetLocaleInfo(LocaleStringData.CurrencyEnglishName); - } - return _sEnglishCurrency; - } - } - - // Native name for this currency (RegionInfo), eg: Schweiz Frank - internal String SNATIVECURRENCY - { - get - { - if (_sNativeCurrency == null) - { - _sNativeCurrency = GetLocaleInfo(LocaleStringData.CurrencyNativeName); - } - return _sNativeCurrency; - } - } - - // internal int iCurrencyDigits ; // (user can override) # local monetary fractional digits - // internal int iCurrency ; // (user can override) positive currency format - // internal int iNegativeCurrency ; // (user can override) negative currency format - - // (user can override) monetary grouping of digits - internal int[] WAMONGROUPING - { - get - { - if (_waMonetaryGrouping == null) - { - _waMonetaryGrouping = GetLocaleInfo(LocaleGroupingData.Monetary); - } - return _waMonetaryGrouping; - } - } - - // (user can override) system of measurement 0=metric, 1=US (RegionInfo) - internal int IMEASURE - { - get - { - if (_iMeasure == undef) - { - _iMeasure = GetLocaleInfo(LocaleNumberData.MeasurementSystem); - } - return _iMeasure; - } - } - - // (user can override) list Separator - internal String SLIST - { - get - { - if (_sListSeparator == null) - { - _sListSeparator = GetLocaleInfo(LocaleStringData.ListSeparator); - } - return _sListSeparator; - } - } - - - //////////////////////////// - // Calendar/Time (Gregorian) // - //////////////////////////// - - // (user can override) AM designator - internal String SAM1159 - { - get - { - if (_sAM1159 == null) - { - _sAM1159 = GetLocaleInfo(LocaleStringData.AMDesignator); - } - return _sAM1159; - } - } - - // (user can override) PM designator - internal String SPM2359 - { - get - { - if (_sPM2359 == null) - { - _sPM2359 = GetLocaleInfo(LocaleStringData.PMDesignator); - } - return _sPM2359; - } - } - - // (user can override) time format - internal String[] LongTimes - { - get - { - if (_saLongTimes == null) - { - String[] longTimes = GetTimeFormats(); - if (longTimes == null || longTimes.Length == 0) - { - _saLongTimes = Invariant._saLongTimes; - } - else - { - _saLongTimes = longTimes; - } - } - return _saLongTimes; - } - } - - // short time format - // Short times (derived from long times format) - // TODO: NLS Arrowhead - On Windows 7 we should have short times so this isn't necessary - internal String[] ShortTimes - { - get - { - if (_saShortTimes == null) - { - // Try to get the short times from the OS/culture.dll - String[] shortTimes = null; - shortTimes = GetShortTimeFormats(); - - if (shortTimes == null || shortTimes.Length == 0) - { - // - // If we couldn't find short times, then compute them from long times - // (eg: CORECLR on < Win7 OS & fallback for missing culture.dll) - // - shortTimes = DeriveShortTimesFromLong(); - } - - /* The above logic doesn't make sense on Mac, since the OS can provide us a "short time pattern". - * currently this is the 4th element in the array returned by LongTimes. We'll add this to our array - * if it doesn't exist. - */ - shortTimes = AdjustShortTimesForMac(shortTimes); - - // Found short times, use them - _saShortTimes = shortTimes; - } - return _saShortTimes; - } - } - - private string[] AdjustShortTimesForMac(string[] shortTimes) - { - return shortTimes; - } - - private string[] DeriveShortTimesFromLong() - { - // Our logic is to look for h,H,m,s,t. If we find an s, then we check the string - // between it and the previous marker, if any. If its a short, unescaped separator, - // then we don't retain that part. - // We then check after the ss and remove anything before the next h,H,m,t... - string[] shortTimes = new string[LongTimes.Length]; - - for (int i = 0; i < LongTimes.Length; i++) - { - shortTimes[i] = StripSecondsFromPattern(LongTimes[i]); - } - return shortTimes; - } - - private static string StripSecondsFromPattern(string time) - { - bool bEscape = false; - int iLastToken = -1; - - // Find the seconds - for (int j = 0; j < time.Length; j++) - { - // Change escape mode? - if (time[j] == '\'') - { - // Continue - bEscape = !bEscape; - continue; - } - - // See if there was a single \ - if (time[j] == '\\') - { - // Skip next char - j++; - continue; - } - - if (bEscape) - { - continue; - } - - switch (time[j]) - { - // Check for seconds - case 's': - // Found seconds, see if there was something unescaped and short between - // the last marker and the seconds. Windows says separator can be a - // maximum of three characters (without null) - // If 1st or last characters were ', then ignore it - if ((j - iLastToken) <= 4 && (j - iLastToken) > 1 && - (time[iLastToken + 1] != '\'') && - (time[j - 1] != '\'')) - { - // There was something there we want to remember - if (iLastToken >= 0) - { - j = iLastToken + 1; - } - } - - bool containsSpace; - int endIndex = GetIndexOfNextTokenAfterSeconds(time, j, out containsSpace); - - string sep; - - if (containsSpace) - { - sep = " "; - } - else - { - sep = ""; - } - - time = time.Substring(0, j) + sep + time.Substring(endIndex); - break; - case 'm': - case 'H': - case 'h': - iLastToken = j; - break; - } - } - return time; - } - - private static int GetIndexOfNextTokenAfterSeconds(string time, int index, out bool containsSpace) - { - bool bEscape = false; - containsSpace = false; - for (; index < time.Length; index++) - { - switch (time[index]) - { - case '\'': - bEscape = !bEscape; - continue; - case '\\': - index++; - if (time[index] == ' ') - { - containsSpace = true; - } - continue; - case ' ': - containsSpace = true; - break; - case 't': - case 'm': - case 'H': - case 'h': - if (bEscape) - { - continue; - } - return index; - } - } - containsSpace = false; - return index; - } - - // (user can override) first day of week - internal int IFIRSTDAYOFWEEK - { - get - { - if (_iFirstDayOfWeek == undef) - { - _iFirstDayOfWeek = GetFirstDayOfWeek(); - } - return _iFirstDayOfWeek; - } - } - - // (user can override) first week of year - internal int IFIRSTWEEKOFYEAR - { - get - { - if (_iFirstWeekOfYear == undef) - { - _iFirstWeekOfYear = GetLocaleInfo(LocaleNumberData.FirstWeekOfYear); - } - return _iFirstWeekOfYear; - } - } - - // (user can override default only) short date format - internal String[] ShortDates(CalendarId calendarId) - { - return GetCalendar(calendarId).saShortDates; - } - - // (user can override default only) long date format - internal String[] LongDates(CalendarId calendarId) - { - return GetCalendar(calendarId).saLongDates; - } - - // (user can override) date year/month format. - internal String[] YearMonths(CalendarId calendarId) - { - return GetCalendar(calendarId).saYearMonths; - } - - // day names - internal string[] DayNames(CalendarId calendarId) - { - return GetCalendar(calendarId).saDayNames; - } - - // abbreviated day names - internal string[] AbbreviatedDayNames(CalendarId calendarId) - { - // Get abbreviated day names for this calendar from the OS if necessary - return GetCalendar(calendarId).saAbbrevDayNames; - } - - // The super short day names - internal string[] SuperShortDayNames(CalendarId calendarId) - { - return GetCalendar(calendarId).saSuperShortDayNames; - } - - // month names - internal string[] MonthNames(CalendarId calendarId) - { - return GetCalendar(calendarId).saMonthNames; - } - - // Genitive month names - internal string[] GenitiveMonthNames(CalendarId calendarId) - { - return GetCalendar(calendarId).saMonthGenitiveNames; - } - - // month names - internal string[] AbbreviatedMonthNames(CalendarId calendarId) - { - return GetCalendar(calendarId).saAbbrevMonthNames; - } - - // Genitive month names - internal string[] AbbreviatedGenitiveMonthNames(CalendarId calendarId) - { - return GetCalendar(calendarId).saAbbrevMonthGenitiveNames; - } - - // Leap year month names - // Note: This only applies to Hebrew, and it basically adds a "1" to the 6th month name - // the non-leap names skip the 7th name in the normal month name array - internal string[] LeapYearMonthNames(CalendarId calendarId) - { - return GetCalendar(calendarId).saLeapYearMonthNames; - } - - // month/day format (single string, no override) - internal String MonthDay(CalendarId calendarId) - { - return GetCalendar(calendarId).sMonthDay; - } - - - - ///////////// - // Calendars // - ///////////// - - // all available calendar type(s), The first one is the default calendar. - internal CalendarId[] CalendarIds - { - get - { - if (_waCalendars == null) - { - // We pass in an array of ints, and native side fills it up with count calendars. - // We then have to copy that list to a new array of the right size. - // Default calendar should be first - CalendarId[] calendars = new CalendarId[23]; - Debug.Assert(_sWindowsName != null, "[CultureData.CalendarIds] Expected _sWindowsName to be populated by already"); - int count = CalendarData.GetCalendars(_sWindowsName, _bUseOverrides, calendars); - - // See if we had a calendar to add. - if (count == 0) - { - // Failed for some reason, just grab Gregorian from Invariant - _waCalendars = Invariant._waCalendars; - } - else - { - // The OS may not return calendar 4 for zh-TW, but we've always allowed it. - // TODO: Is this hack necessary long-term? - if (_sWindowsName == "zh-TW") - { - bool found = false; - - // Do we need to insert calendar 4? - for (int i = 0; i < count; i++) - { - // Stop if we found calendar four - if (calendars[i] == CalendarId.TAIWAN) - { - found = true; - break; - } - } - - // If not found then insert it - if (!found) - { - // Insert it as the 2nd calendar - count++; - // Copy them from the 2nd position to the end, -1 for skipping 1st, -1 for one being added. - Array.Copy(calendars, 1, calendars, 2, 23 - 1 - 1); - calendars[1] = CalendarId.TAIWAN; - } - } - - // It worked, remember the list - CalendarId[] temp = new CalendarId[count]; - Array.Copy(calendars, temp, count); - - // Want 1st calendar to be default - // Prior to Vista the enumeration didn't have default calendar first - if (temp.Length > 1) - { - CalendarId i = (CalendarId)GetLocaleInfo(LocaleNumberData.CalendarType); - if (temp[1] == i) - { - temp[1] = temp[0]; - temp[0] = i; - } - } - - _waCalendars = temp; - } - } - - return _waCalendars; - } - } - - // Native calendar names. index of optional calendar - 1, empty if no optional calendar at that number - internal string CalendarName(CalendarId calendarId) - { - // Get the calendar - return GetCalendar(calendarId).sNativeName; - } - - internal CalendarData GetCalendar(CalendarId calendarId) - { - Debug.Assert(calendarId > 0 && calendarId <= CalendarId.LAST_CALENDAR, - "[CultureData.GetCalendar] Expect calendarId to be in a valid range"); - - // arrays are 0 based, calendarIds are 1 based - int calendarIndex = (int)calendarId - 1; - - // Have to have calendars - if (_calendars == null) - { - _calendars = new CalendarData[CalendarData.MAX_CALENDARS]; - } - - // we need the following local variable to avoid returning null - // when another thread creates a new array of CalendarData (above) - // right after we insert the newly created CalendarData (below) - CalendarData calendarData = _calendars[calendarIndex]; - // Make sure that calendar has data - if (calendarData == null) - { - Debug.Assert(_sWindowsName != null, "[CultureData.GetCalendar] Expected _sWindowsName to be populated by already"); - calendarData = new CalendarData(_sWindowsName, calendarId, this.UseUserOverride); - _calendars[calendarIndex] = calendarData; - } - - return calendarData; - } - - /////////////////// - // Text Information // - /////////////////// - - // IsRightToLeft - internal bool IsRightToLeft - { - get - { - // Returns one of the following 4 reading layout values: - // 0 - Left to right (eg en-US) - // 1 - Right to left (eg arabic locales) - // 2 - Vertical top to bottom with columns to the left and also left to right (ja-JP locales) - // 3 - Vertical top to bottom with columns proceeding to the right - return (this.IREADINGLAYOUT == 1); - } - } - - // IREADINGLAYOUT - // Returns one of the following 4 reading layout values: - // 0 - Left to right (eg en-US) - // 1 - Right to left (eg arabic locales) - // 2 - Vertical top to bottom with columns to the left and also left to right (ja-JP locales) - // 3 - Vertical top to bottom with columns proceeding to the right - // - // If exposed as a public API, we'd have an enum with those 4 values - private int IREADINGLAYOUT - { - get - { - if (_iReadingLayout == undef) - { - Debug.Assert(_sRealName != null, "[CultureData.IsRightToLeft] Expected _sRealName to be populated by already"); - _iReadingLayout = GetLocaleInfo(LocaleNumberData.ReadingLayout); - } - - return (_iReadingLayout); - } - } - - // The TextInfo name never includes that alternate sort and is always specific - // For customs, it uses the SortLocale (since the textinfo is not exposed in Win7) - // en -> en-US - // en-US -> en-US - // fj (custom neutral) -> en-US (assuming that en-US is the sort locale for fj) - // fj_FJ (custom specific) -> en-US (assuming that en-US is the sort locale for fj-FJ) - // es-ES_tradnl -> es-ES - internal String STEXTINFO // Text info name to use for text information - { - get - { - // Note: Custom cultures might point at another culture's textinfo, however windows knows how - // to redirect it to the desired textinfo culture, so this is OK. - Debug.Assert(_sRealName != null, "[CultureData.STEXTINFO] Expected _sRealName to be populated by already"); - return (_sRealName); - } - } - - // Compare info name (including sorting key) to use if custom - internal String SCOMPAREINFO - { - get - { - Debug.Assert(_sRealName != null, "[CultureData.SCOMPAREINFO] Expected _sRealName to be populated by already"); - return (_sRealName); - } - } - - internal bool IsSupplementalCustomCulture - { - get - { - return IsCustomCultureId(this.ILANGUAGE); - } - } - - internal int IDEFAULTANSICODEPAGE // default ansi code page ID (ACP) - { - get - { - if (_iDefaultAnsiCodePage == undef) - { - _iDefaultAnsiCodePage = GetAnsiCodePage(_sRealName); - } - return _iDefaultAnsiCodePage; - } - } - - internal int IDEFAULTOEMCODEPAGE // default oem code page ID (OCP or OEM) - { - get - { - if (_iDefaultOemCodePage == undef) - { - _iDefaultOemCodePage = GetOemCodePage(_sRealName); - } - return _iDefaultOemCodePage; - } - } - - internal int IDEFAULTMACCODEPAGE // default macintosh code page - { - get - { - if (_iDefaultMacCodePage == undef) - { - _iDefaultMacCodePage = GetMacCodePage(_sRealName); - } - return _iDefaultMacCodePage; - } - } - - internal int IDEFAULTEBCDICCODEPAGE // default EBCDIC code page - { - get - { - if (_iDefaultEbcdicCodePage == undef) - { - _iDefaultEbcdicCodePage = GetEbcdicCodePage(_sRealName); - } - return _iDefaultEbcdicCodePage; - } - } - - internal int ILANGUAGE - { - get - { - if (_iLanguage == 0) - { - Debug.Assert(_sRealName != null, "[CultureData.ILANGUAGE] Expected this.sRealName to be populated by COMNlsInfo::nativeInitCultureData already"); - _iLanguage = LocaleNameToLCID(_sRealName); - } - return _iLanguage; - } - } - - internal bool IsNeutralCulture - { - get - { - // InitCultureData told us if we're neutral or not - return _bNeutral; - } - } - - internal bool IsInvariantCulture - { - get - { - return String.IsNullOrEmpty(this.SNAME); - } - } - - // Get an instance of our default calendar - internal Calendar DefaultCalendar - { - get - { - CalendarId defaultCalId = (CalendarId)GetLocaleInfo(LocaleNumberData.CalendarType); - - if (defaultCalId == 0) - { - defaultCalId = this.CalendarIds[0]; - } - - return CultureInfo.GetCalendarInstance(defaultCalId); - } - } - - // All of our era names - internal String[] EraNames(CalendarId calendarId) - { - Debug.Assert(calendarId > 0, "[CultureData.saEraNames] Expected Calendar.ID > 0"); - - return this.GetCalendar(calendarId).saEraNames; - } - - internal String[] AbbrevEraNames(CalendarId calendarId) - { - Debug.Assert(calendarId > 0, "[CultureData.saAbbrevEraNames] Expected Calendar.ID > 0"); - - return this.GetCalendar(calendarId).saAbbrevEraNames; - } - - internal String[] AbbreviatedEnglishEraNames(CalendarId calendarId) - { - Debug.Assert(calendarId > 0, "[CultureData.saAbbrevEraNames] Expected Calendar.ID > 0"); - - return this.GetCalendar(calendarId).saAbbrevEnglishEraNames; - } - - //// String array DEFAULTS - //// Note: GetDTFIOverrideValues does the user overrides for these, so we don't have to. - - - // Time separator (derived from time format) - internal String TimeSeparator - { - get - { - if (_sTimeSeparator == null) - { - string longTimeFormat = GetTimeFormatString(); - if (String.IsNullOrEmpty(longTimeFormat)) - { - longTimeFormat = LongTimes[0]; - } - - // Compute STIME from time format - _sTimeSeparator = GetTimeSeparator(longTimeFormat); - } - return _sTimeSeparator; - } - } - - // Date separator (derived from short date format) - internal String DateSeparator(CalendarId calendarId) - { - return GetDateSeparator(ShortDates(calendarId)[0]); - } - - ////////////////////////////////////// - // Helper Functions to get derived properties // - ////////////////////////////////////// - - //////////////////////////////////////////////////////////////////////////// - // - // Unescape a NLS style quote string - // - // This removes single quotes: - // 'fred' -> fred - // 'fred -> fred - // fred' -> fred - // fred's -> freds - // - // This removes the first \ of escaped characters: - // fred\'s -> fred's - // a\\b -> a\b - // a\b -> ab - // - // We don't build the stringbuilder unless we find a ' or a \. If we find a ' or a \, we - // always build a stringbuilder because we need to remove the ' or \. - // - //////////////////////////////////////////////////////////////////////////// - private static String UnescapeNlsString(String str, int start, int end) - { - Debug.Assert(str != null); - Debug.Assert(start >= 0); - Debug.Assert(end >= 0); - StringBuilder result = null; - - for (int i = start; i < str.Length && i <= end; i++) - { - switch (str[i]) - { - case '\'': - if (result == null) - { - result = new StringBuilder(str, start, i - start, str.Length); - } - break; - case '\\': - if (result == null) - { - result = new StringBuilder(str, start, i - start, str.Length); - } - ++i; - if (i < str.Length) - { - result.Append(str[i]); - } - break; - default: - if (result != null) - { - result.Append(str[i]); - } - break; - } - } - - if (result == null) - return (str.Substring(start, end - start + 1)); - - return (result.ToString()); - } - - private static String GetTimeSeparator(String format) - { - // Time format separator (ie: : in 12:39:00) - // - // We calculate this from the provided time format - // - - // - // Find the time separator so that we can pretend we know STIME. - // - return GetSeparator(format, "Hhms"); - } - - private static String GetDateSeparator(String format) - { - // Date format separator (ie: / in 9/1/03) - // - // We calculate this from the provided short date - // - - // - // Find the date separator so that we can pretend we know SDATE. - // - return GetSeparator(format, "dyM"); - } - - private static string GetSeparator(string format, string timeParts) - { - int index = IndexOfTimePart(format, 0, timeParts); - - if (index != -1) - { - // Found a time part, find out when it changes - char cTimePart = format[index]; - - do - { - index++; - } while (index < format.Length && format[index] == cTimePart); - - int separatorStart = index; - - // Now we need to find the end of the separator - if (separatorStart < format.Length) - { - int separatorEnd = IndexOfTimePart(format, separatorStart, timeParts); - if (separatorEnd != -1) - { - // From [separatorStart, count) is our string, except we need to unescape - return UnescapeNlsString(format, separatorStart, separatorEnd - 1); - } - } - } - - return String.Empty; - } - - private static int IndexOfTimePart(string format, int startIndex, string timeParts) - { - Debug.Assert(startIndex >= 0, "startIndex cannot be negative"); - Debug.Assert(timeParts.IndexOfAny(new char[] { '\'', '\\' }) == -1, "timeParts cannot include quote characters"); - bool inQuote = false; - for (int i = startIndex; i < format.Length; ++i) - { - // See if we have a time Part - if (!inQuote && timeParts.IndexOf(format[i]) != -1) - { - return i; - } - switch (format[i]) - { - case '\\': - if (i + 1 < format.Length) - { - ++i; - switch (format[i]) - { - case '\'': - case '\\': - break; - default: - --i; //backup since we will move over this next - break; - } - } - break; - case '\'': - inQuote = !inQuote; - break; - } - } - - return -1; - } - - internal static bool IsCustomCultureId(int cultureId) - { - return (cultureId == CultureInfo.LOCALE_CUSTOM_DEFAULT || cultureId == CultureInfo.LOCALE_CUSTOM_UNSPECIFIED); - } - - internal void GetNFIValues(NumberFormatInfo nfi) - { - if (this.IsInvariantCulture) - { - // FUTURE: NumberFormatInfo already has default values for many of these fields. Can we not do this? - nfi.positiveSign = _sPositiveSign; - nfi.negativeSign = _sNegativeSign; - - nfi.numberGroupSeparator = _sThousandSeparator; - nfi.numberDecimalSeparator = _sDecimalSeparator; - nfi.numberDecimalDigits = _iDigits; - nfi.numberNegativePattern = _iNegativeNumber; - - nfi.currencySymbol = _sCurrency; - nfi.currencyGroupSeparator = _sMonetaryThousand; - nfi.currencyDecimalSeparator = _sMonetaryDecimal; - nfi.currencyDecimalDigits = _iCurrencyDigits; - nfi.currencyNegativePattern = _iNegativeCurrency; - nfi.currencyPositivePattern = _iCurrency; - } - else - { - Debug.Assert(_sWindowsName != null, "[CultureData.GetNFIValues] Expected _sWindowsName to be populated by already"); - // String values - nfi.positiveSign = GetLocaleInfo(LocaleStringData.PositiveSign); - nfi.negativeSign = GetLocaleInfo(LocaleStringData.NegativeSign); - - nfi.numberDecimalSeparator = GetLocaleInfo(LocaleStringData.DecimalSeparator); - nfi.numberGroupSeparator = GetLocaleInfo(LocaleStringData.ThousandSeparator); - nfi.currencyGroupSeparator = GetLocaleInfo(LocaleStringData.MonetaryThousandSeparator); - nfi.currencyDecimalSeparator = GetLocaleInfo(LocaleStringData.MonetaryDecimalSeparator); - nfi.currencySymbol = GetLocaleInfo(LocaleStringData.MonetarySymbol); - - // Numeric values - nfi.numberDecimalDigits = GetLocaleInfo(LocaleNumberData.FractionalDigitsCount); - nfi.currencyDecimalDigits = GetLocaleInfo(LocaleNumberData.MonetaryFractionalDigitsCount); - nfi.currencyPositivePattern = GetLocaleInfo(LocaleNumberData.PositiveMonetaryNumberFormat); - nfi.currencyNegativePattern = GetLocaleInfo(LocaleNumberData.NegativeMonetaryNumberFormat); - nfi.numberNegativePattern = GetLocaleInfo(LocaleNumberData.NegativeNumberFormat); - - // LOCALE_SNATIVEDIGITS (array of 10 single character strings). - string digits = GetLocaleInfo(LocaleStringData.Digits); - nfi.nativeDigits = new string[10]; - for (int i = 0; i < nfi.nativeDigits.Length; i++) - { - nfi.nativeDigits[i] = new string(digits[i], 1); - } - - nfi.digitSubstitution = GetDigitSubstitution(_sRealName); - } - - // - // Gather additional data - // - nfi.numberGroupSizes = this.WAGROUPING; - nfi.currencyGroupSizes = this.WAMONGROUPING; - - // prefer the cached value since these do not have user overrides - nfi.percentNegativePattern = this.INEGATIVEPERCENT; - nfi.percentPositivePattern = this.IPOSITIVEPERCENT; - nfi.percentSymbol = this.SPERCENT; - nfi.perMilleSymbol = this.SPERMILLE; - - nfi.negativeInfinitySymbol = this.SNEGINFINITY; - nfi.positiveInfinitySymbol = this.SPOSINFINITY; - nfi.nanSymbol = this.SNAN; - - // - // We don't have percent values, so use the number values - // - nfi.percentDecimalDigits = nfi.numberDecimalDigits; - nfi.percentDecimalSeparator = nfi.numberDecimalSeparator; - nfi.percentGroupSizes = nfi.numberGroupSizes; - nfi.percentGroupSeparator = nfi.numberGroupSeparator; - - // - // Clean up a few odd values - // - - // Windows usually returns an empty positive sign, but we like it to be "+" - if (nfi.positiveSign == null || nfi.positiveSign.Length == 0) nfi.positiveSign = "+"; - - //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 nfi. - if (nfi.currencyDecimalSeparator == null || nfi.currencyDecimalSeparator.Length == 0) - { - nfi.currencyDecimalSeparator = nfi.numberDecimalSeparator; - } - } - - // Helper - // This is ONLY used for caching names and shouldn't be used for anything else - internal static string AnsiToLower(string testString) - { - int index = 0; - - while (index'Z' )) - { - index++; - } - if (index >= testString.Length) - { - return testString; // we didn't really change the string - } - - StringBuilder sb = new StringBuilder(testString.Length); - for (int i=0; i= 'A' ? (char)(ch - 'A' + 'a') : ch); - } - - return (sb.ToString()); - } - - /// - /// The numeric values of the enum members match their Win32 counterparts. The CultureData Win32 PAL implementation - /// takes a dependency on this fact, in order to prevent having to construct a mapping from internal values to LCTypes. - /// - private enum LocaleStringData : uint - { - /// localized name of locale, eg "German (Germany)" in UI language (coresponds to LOCALE_SLOCALIZEDDISPLAYNAME) - LocalizedDisplayName = 0x00000002, - /// Display name (language + country usually) in English, eg "German (Germany)" (coresponds to LOCALE_SENGLISHDISPLAYNAME) - EnglishDisplayName = 0x00000072, - /// Display name in native locale language, eg "Deutsch (Deutschland) (coresponds to LOCALE_SNATIVEDISPLAYNAME) - NativeDisplayName = 0x00000073, - /// Language Display Name for a language, eg "German" in UI language (coresponds to LOCALE_SLOCALIZEDLANGUAGENAME) - LocalizedLanguageName = 0x0000006f, - /// English name of language, eg "German" (coresponds to LOCALE_SENGLISHLANGUAGENAME) - EnglishLanguageName = 0x00001001, - /// native name of language, eg "Deutsch" (coresponds to LOCALE_SNATIVELANGUAGENAME) - NativeLanguageName = 0x00000004, - /// localized name of country, eg "Germany" in UI language (coresponds to LOCALE_SLOCALIZEDCOUNTRYNAME) - LocalizedCountryName = 0x00000006, - /// English name of country, eg "Germany" (coresponds to LOCALE_SENGLISHCOUNTRYNAME) - EnglishCountryName = 0x00001002, - /// native name of country, eg "Deutschland" (coresponds to LOCALE_SNATIVECOUNTRYNAME) - NativeCountryName = 0x00000008, - /// abbreviated language name (coresponds to LOCALE_SABBREVLANGNAME) - AbbreviatedWindowsLanguageName = 0x00000003, - /// list item separator (coresponds to LOCALE_SLIST) - ListSeparator = 0x0000000C, - /// decimal separator (coresponds to LOCALE_SDECIMAL) - DecimalSeparator = 0x0000000E, - /// thousand separator (coresponds to LOCALE_STHOUSAND) - ThousandSeparator = 0x0000000F, - /// digit grouping (coresponds to LOCALE_SGROUPING) - Digits = 0x00000013, - /// local monetary symbol (coresponds to LOCALE_SCURRENCY) - MonetarySymbol = 0x00000014, - /// English currency name (coresponds to LOCALE_SENGCURRNAME) - CurrencyEnglishName = 0x00001007, - /// Native currency name (coresponds to LOCALE_SNATIVECURRNAME) - CurrencyNativeName = 0x00001008, - /// uintl monetary symbol (coresponds to LOCALE_SINTLSYMBOL) - Iso4217MonetarySymbol = 0x00000015, - /// monetary decimal separator (coresponds to LOCALE_SMONDECIMALSEP) - MonetaryDecimalSeparator = 0x00000016, - /// monetary thousand separator (coresponds to LOCALE_SMONTHOUSANDSEP) - MonetaryThousandSeparator = 0x00000017, - /// AM designator (coresponds to LOCALE_S1159) - AMDesignator = 0x00000028, - /// PM designator (coresponds to LOCALE_S2359) - PMDesignator = 0x00000029, - /// positive sign (coresponds to LOCALE_SPOSITIVESIGN) - PositiveSign = 0x00000050, - /// negative sign (coresponds to LOCALE_SNEGATIVESIGN) - NegativeSign = 0x00000051, - /// ISO abbreviated language name (coresponds to LOCALE_SISO639LANGNAME) - Iso639LanguageTwoLetterName = 0x00000059, - /// ISO abbreviated country name (coresponds to LOCALE_SISO639LANGNAME2) - Iso639LanguageThreeLetterName = 0x00000067, - /// ISO abbreviated language name (coresponds to LOCALE_SISO639LANGNAME) - Iso639LanguageName = 0x00000059, - /// ISO abbreviated country name (coresponds to LOCALE_SISO3166CTRYNAME) - Iso3166CountryName = 0x0000005A, - /// 3 letter ISO country code (coresponds to LOCALE_SISO3166CTRYNAME2) - Iso3166CountryName2 = 0x00000068, // 3 character ISO country name - /// Not a Number (coresponds to LOCALE_SNAN) - NaNSymbol = 0x00000069, - /// + Infinity (coresponds to LOCALE_SPOSINFINITY) - PositiveInfinitySymbol = 0x0000006a, - /// - Infinity (coresponds to LOCALE_SNEGINFINITY) - NegativeInfinitySymbol = 0x0000006b, - /// Fallback name for resources (coresponds to LOCALE_SPARENT) - ParentName = 0x0000006d, - /// Fallback name for within the console (coresponds to LOCALE_SCONSOLEFALLBACKNAME) - ConsoleFallbackName = 0x0000006e, - /// Returns the percent symbol (coresponds to LOCALE_SPERCENT) - PercentSymbol = 0x00000076, - /// Returns the permille (U+2030) symbol (coresponds to LOCALE_SPERMILLE) - PerMilleSymbol = 0x00000077 - } - - /// - /// The numeric values of the enum members match their Win32 counterparts. The CultureData Win32 PAL implementation - /// takes a dependency on this fact, in order to prevent having to construct a mapping from internal values to LCTypes. - /// - private enum LocaleGroupingData : uint - { - /// digit grouping (coresponds to LOCALE_SGROUPING) - Digit = 0x00000010, - /// monetary grouping (coresponds to LOCALE_SMONGROUPING) - Monetary = 0x00000018, - } - - /// - /// The numeric values of the enum members match their Win32 counterparts. The CultureData Win32 PAL implementation - /// takes a dependency on this fact, in order to prevent having to construct a mapping from internal values to LCTypes. - /// - private enum LocaleNumberData : uint - { - /// language id (coresponds to LOCALE_ILANGUAGE) - LanguageId = 0x00000001, - /// geographical location id, (coresponds to LOCALE_IGEOID) - GeoId = 0x00000008, - /// 0 = context, 1 = none, 2 = national (coresponds to LOCALE_IDIGITSUBSTITUTION) - DigitSubstitution = 0x00001014, - /// 0 = metric, 1 = US (coresponds to LOCALE_IMEASURE) - MeasurementSystem = 0x0000000D, - /// number of fractional digits (coresponds to LOCALE_IDIGITS) - FractionalDigitsCount = 0x00000011, - /// negative number mode (coresponds to LOCALE_INEGNUMBER) - NegativeNumberFormat = 0x00001010, - /// # local monetary digits (coresponds to LOCALE_ICURRDIGITS) - MonetaryFractionalDigitsCount = 0x00000019, - /// positive currency mode (coresponds to LOCALE_ICURRENCY) - PositiveMonetaryNumberFormat = 0x0000001B, - /// negative currency mode (coresponds to LOCALE_INEGCURR) - NegativeMonetaryNumberFormat = 0x0000001C, - /// type of calendar specifier (coresponds to LOCALE_ICALENDARTYPE) - CalendarType = 0x00001009, - /// first day of week specifier (coresponds to LOCALE_IFIRSTDAYOFWEEK) - FirstDayOfWeek = 0x0000100C, - /// first week of year specifier (coresponds to LOCALE_IFIRSTWEEKOFYEAR) - FirstWeekOfYear = 0x0000100D, - /// - /// Returns one of the following 4 reading layout values: - /// 0 - Left to right (eg en-US) - /// 1 - Right to left (eg arabic locales) - /// 2 - Vertical top to bottom with columns to the left and also left to right (ja-JP locales) - /// 3 - Vertical top to bottom with columns proceeding to the right - /// (coresponds to LOCALE_IREADINGLAYOUT) - /// - ReadingLayout = 0x00000070, - /// Returns 0-11 for the negative percent format (coresponds to LOCALE_INEGATIVEPERCENT) - NegativePercentFormat = 0x00000074, - /// Returns 0-3 for the positive percent format (coresponds to LOCALE_IPOSITIVEPERCENT) - PositivePercentFormat = 0x00000075, - /// default ansi code page (coresponds to LOCALE_IDEFAULTCODEPAGE) - OemCodePage = 0x0000000B, - /// default ansi code page (coresponds to LOCALE_IDEFAULTANSICODEPAGE) - AnsiCodePage = 0x00001004, - /// default mac code page (coresponds to LOCALE_IDEFAULTMACCODEPAGE) - MacCodePage = 0x00001011, - /// default ebcdic code page (coresponds to LOCALE_IDEFAULTEBCDICCODEPAGE) - EbcdicCodePage = 0x00001012, - } - } -} diff --git a/src/mscorlib/corefx/System/Globalization/CultureInfo.Unix.cs b/src/mscorlib/corefx/System/Globalization/CultureInfo.Unix.cs deleted file mode 100644 index 6911688..0000000 --- a/src/mscorlib/corefx/System/Globalization/CultureInfo.Unix.cs +++ /dev/null @@ -1,31 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -namespace System.Globalization -{ - public partial class CultureInfo : IFormatProvider - { - private static CultureInfo GetUserDefaultCultureCacheOverride() - { - return null; // ICU doesn't provide a user override - } - - internal static CultureInfo GetUserDefaultCulture() - { - CultureInfo cultureInfo = null; - string localeName; - if (CultureData.GetDefaultLocaleName(out localeName)) - { - cultureInfo = GetCultureByName(localeName, true); - cultureInfo.m_isReadOnly = true; - } - else - { - cultureInfo = CultureInfo.InvariantCulture; - } - - return cultureInfo; - } - } -} diff --git a/src/mscorlib/corefx/System/Globalization/CultureInfo.Windows.cs b/src/mscorlib/corefx/System/Globalization/CultureInfo.Windows.cs deleted file mode 100644 index c019eb2..0000000 --- a/src/mscorlib/corefx/System/Globalization/CultureInfo.Windows.cs +++ /dev/null @@ -1,57 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -#if ENABLE_WINRT -using Internal.Runtime.Augments; -#endif - -namespace System.Globalization -{ - public partial class CultureInfo : IFormatProvider - { - /// - /// Gets the default user culture from WinRT, if available. - /// - /// - /// This method may return null, if there is no default user culture or if WinRT isn't available. - /// - private static CultureInfo GetUserDefaultCultureCacheOverride() - { -#if ENABLE_WINRT - WinRTInteropCallbacks callbacks = WinRTInterop.UnsafeCallbacks; - if (callbacks != null && callbacks.IsAppxModel()) - { - return (CultureInfo)callbacks.GetUserDefaultCulture(); - } -#endif - - return null; - } - - internal static CultureInfo GetUserDefaultCulture() - { - const uint LOCALE_SNAME = 0x0000005c; - const string LOCALE_NAME_USER_DEFAULT = null; - const string LOCALE_NAME_SYSTEM_DEFAULT = "!x-sys-default-locale"; - - string strDefault = Interop.mincore.GetLocaleInfoEx(LOCALE_NAME_USER_DEFAULT, LOCALE_SNAME); - if (strDefault == null) - { - strDefault = Interop.mincore.GetLocaleInfoEx(LOCALE_NAME_SYSTEM_DEFAULT, LOCALE_SNAME); - - if (strDefault == null) - { - // If system default doesn't work, use invariant - return CultureInfo.InvariantCulture; - } - } - - CultureInfo temp = GetCultureByName(strDefault, true); - - temp._isReadOnly = true; - - return temp; - } - } -} diff --git a/src/mscorlib/corefx/System/Globalization/CultureInfo.cs b/src/mscorlib/corefx/System/Globalization/CultureInfo.cs deleted file mode 100644 index 0c937f2..0000000 --- a/src/mscorlib/corefx/System/Globalization/CultureInfo.cs +++ /dev/null @@ -1,1558 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -//////////////////////////////////////////////////////////////////////////// -// -// -// -// Purpose: This class represents the software preferences of a particular -// culture or community. It includes information such as the -// language, writing system, and a calendar used by the culture -// as well as methods for common operations such as printing -// dates and sorting strings. -// -// -// -// !!!! NOTE WHEN CHANGING THIS CLASS !!!! -// -// If adding or removing members to this class, please update CultureInfoBaseObject -// in ndp/clr/src/vm/object.h. Note, the "actual" layout of the class may be -// different than the order in which members are declared. For instance, all -// reference types will come first in the class before value types (like ints, bools, etc) -// regardless of the order in which they are declared. The best way to see the -// actual order of the class is to do a !dumpobj on an instance of the managed -// object inside of the debugger. -// -//////////////////////////////////////////////////////////////////////////// - -using System.Collections.Generic; -using System.Diagnostics; -using System.Diagnostics.Contracts; -using System.Runtime.Serialization; -using System.Threading; - -namespace System.Globalization -{ - -#if CORECLR - using StringCultureInfoDictionary = Dictionary; - using StringLcidDictionary = Dictionary; - - using Lock = Object; -#else - using StringCultureInfoDictionary = LowLevelDictionary; - using StringLcidDictionary = LowLevelDictionary; -#endif - - [Serializable] - public partial class CultureInfo : IFormatProvider, ICloneable - { - //--------------------------------------------------------------------// - // Internal Information // - //--------------------------------------------------------------------// - - //--------------------------------------------------------------------// - // Data members to be serialized: - //--------------------------------------------------------------------// - - // We use an RFC4646 type string to construct CultureInfo. - // This string is stored in m_name and is authoritative. - // We use the m_cultureData to get the data for our object - - private bool m_isReadOnly; - private CompareInfo compareInfo; - private TextInfo textInfo; - internal NumberFormatInfo numInfo; - internal DateTimeFormatInfo dateTimeInfo; - private Calendar calendar; - // - // The CultureData instance that we are going to read data from. - // For supported culture, this will be the CultureData instance that read data from mscorlib assembly. - // For customized culture, this will be the CultureData instance that read data from user customized culture binary file. - // - [NonSerialized] - internal CultureData m_cultureData; - - [NonSerialized] - internal bool m_isInherited; - - [NonSerialized] - private CultureInfo m_consoleFallbackCulture; - - // Names are confusing. Here are 3 names we have: - // - // new CultureInfo() m_name m_nonSortName m_sortName - // en-US en-US en-US en-US - // de-de_phoneb de-DE_phoneb de-DE de-DE_phoneb - // fj-fj (custom) fj-FJ fj-FJ en-US (if specified sort is en-US) - // en en - // - // Note that in Silverlight we ask the OS for the text and sort behavior, so the - // textinfo and compareinfo names are the same as the name - - // Note that the name used to be serialized for Everett; it is now serialized - // because alernate sorts can have alternate names. - // This has a de-DE, de-DE_phoneb or fj-FJ style name - internal string m_name; - - // This will hold the non sorting name to be returned from CultureInfo.Name property. - // This has a de-DE style name even for de-DE_phoneb type cultures - [NonSerialized] - private string m_nonSortName; - - // This will hold the sorting name to be returned from CultureInfo.SortName property. - // This might be completely unrelated to the culture name if a custom culture. Ie en-US for fj-FJ. - // Otherwise its the sort name, ie: de-DE or de-DE_phoneb - [NonSerialized] - private string m_sortName; - - //--------------------------------------------------------------------// - // - // Static data members - // - //--------------------------------------------------------------------// - - //Get the current user default culture. This one is almost always used, so we create it by default. - private static volatile CultureInfo s_userDefaultCulture; - - // - // All of the following will be created on demand. - // - - // WARNING: We allow diagnostic tools to directly inspect these three members (s_InvariantCultureInfo, s_DefaultThreadCurrentUICulture and s_DefaultThreadCurrentCulture) - // See https://github.com/dotnet/corert/blob/master/Documentation/design-docs/diagnostics/diagnostics-tools-contract.md for more details. - // Please do not change the type, the name, or the semantic usage of this member without understanding the implication for tools. - // Get in touch with the diagnostics team if you have questions. - - //The Invariant culture; - private static volatile CultureInfo s_InvariantCultureInfo; - - //These are defaults that we use if a thread has not opted into having an explicit culture - private static volatile CultureInfo s_DefaultThreadCurrentUICulture; - private static volatile CultureInfo s_DefaultThreadCurrentCulture; - - [ThreadStatic] - private static volatile CultureInfo s_currentThreadCulture; - [ThreadStatic] - private static volatile CultureInfo s_currentThreadUICulture; - - private static readonly Lock m_lock = new Lock(); - private static volatile StringCultureInfoDictionary s_NameCachedCultures; - private static volatile StringLcidDictionary s_LcidCachedCultures; - - //The parent culture. - [NonSerialized] - private CultureInfo m_parent; - - // LOCALE constants of interest to us internally and privately for LCID functions - // (ie: avoid using these and use names if possible) - internal const int LOCALE_NEUTRAL = 0x0000; - private const int LOCALE_USER_DEFAULT = 0x0400; - private const int LOCALE_SYSTEM_DEFAULT = 0x0800; - internal const int LOCALE_CUSTOM_UNSPECIFIED = 0x1000; - internal const int LOCALE_CUSTOM_DEFAULT = 0x0c00; - internal const int LOCALE_INVARIANT = 0x007F; - - static AsyncLocal s_asyncLocalCurrentCulture; - static AsyncLocal s_asyncLocalCurrentUICulture; - - static void AsyncLocalSetCurrentCulture(AsyncLocalValueChangedArgs args) - { - s_currentThreadCulture = args.CurrentValue; - } - - static void AsyncLocalSetCurrentUICulture(AsyncLocalValueChangedArgs args) - { - s_currentThreadUICulture = args.CurrentValue; - } - - // - // The CultureData instance that reads the data provided by our CultureData class. - // - // Using a field initializer rather than a static constructor so that the whole class can be lazy - // init. - private static readonly bool init = Init(); - private static bool Init() - { - if (s_InvariantCultureInfo == null) - { - CultureInfo temp = new CultureInfo("", false); - temp.m_isReadOnly = true; - s_InvariantCultureInfo = temp; - } - - s_userDefaultCulture = GetUserDefaultCulture(); - return true; - } - - //////////////////////////////////////////////////////////////////////// - // - // CultureInfo Constructors - // - //////////////////////////////////////////////////////////////////////// - - - public CultureInfo(String name) - : this(name, true) - { - } - - - public CultureInfo(String name, bool useUserOverride) - { - if (name == null) - { - throw new ArgumentNullException(nameof(name), - SR.ArgumentNull_String); - } - - InitializeFromName(name, useUserOverride); - } - - public CultureInfo(int culture) : this(culture, true) - { - } - - public CultureInfo(int culture, bool useUserOverride) - { - // We don't check for other invalid LCIDS here... - if (culture < 0) - { - throw new ArgumentOutOfRangeException(nameof(culture), SR.ArgumentOutOfRange_NeedPosNum); - } - Contract.EndContractBlock(); - - InitializeFromCultureId(culture, useUserOverride); - } - - private void InitializeFromCultureId(int culture, bool useUserOverride) - { - switch (culture) - { - case LOCALE_CUSTOM_DEFAULT: - case LOCALE_SYSTEM_DEFAULT: - case LOCALE_NEUTRAL: - case LOCALE_USER_DEFAULT: - case LOCALE_CUSTOM_UNSPECIFIED: - // Can't support unknown custom cultures and we do not support neutral or - // non-custom user locales. - throw new CultureNotFoundException(nameof(culture), culture, SR.Argument_CultureNotSupported); - - default: - // Now see if this LCID is supported in the system default CultureData table. - m_cultureData = CultureData.GetCultureData(culture, useUserOverride); - break; - } - m_isInherited = (this.GetType() != typeof(System.Globalization.CultureInfo)); - m_name = m_cultureData.CultureName; - } - - private void InitializeFromName(string name, bool useUserOverride) - { - // Get our data providing record - this.m_cultureData = CultureData.GetCultureData(name, useUserOverride); - - if (this.m_cultureData == null) - { - throw new CultureNotFoundException(nameof(name), name, SR.Argument_CultureNotSupported); - } - - this.m_name = this.m_cultureData.CultureName; - this.m_isInherited = (this.GetType() != typeof(System.Globalization.CultureInfo)); - } - - // Constructor called by SQL Server's special munged culture - creates a culture with - // a TextInfo and CompareInfo that come from a supplied alternate source. This object - // is ALWAYS read-only. - // Note that we really cannot use an LCID version of this override as the cached - // name we create for it has to include both names, and the logic for this is in - // the GetCultureInfo override *only*. - internal CultureInfo(String cultureName, String textAndCompareCultureName) - { - if (cultureName == null) - { - throw new ArgumentNullException(nameof(cultureName),SR.ArgumentNull_String); - } - Contract.EndContractBlock(); - - m_cultureData = CultureData.GetCultureData(cultureName, false); - if (m_cultureData == null) - throw new CultureNotFoundException(nameof(cultureName), cultureName, SR.Argument_CultureNotSupported); - - m_name = m_cultureData.CultureName; - - CultureInfo altCulture = GetCultureInfo(textAndCompareCultureName); - compareInfo = altCulture.CompareInfo; - textInfo = altCulture.TextInfo; - } - - // We do this to try to return the system UI language and the default user languages - // This method will fallback if this fails (like Invariant) - // - // TODO: It would appear that this is only ever called with userOveride = true - // and this method only has one caller. Can we fold it into the caller? - private static CultureInfo GetCultureByName(String name, bool userOverride) - { - CultureInfo ci = null; - // Try to get our culture - try - { - ci = userOverride ? new CultureInfo(name) : CultureInfo.GetCultureInfo(name); - } - catch (ArgumentException) - { - } - - if (ci == null) - { - ci = InvariantCulture; - } - - return ci; - } - - // - // Return a specific culture. A tad irrelevent now since we always return valid data - // for neutral locales. - // - // Note that there's interesting behavior that tries to find a smaller name, ala RFC4647, - // if we can't find a bigger name. That doesn't help with things like "zh" though, so - // the approach is of questionable value - // - public static CultureInfo CreateSpecificCulture(String name) - { - Contract.Ensures(Contract.Result() != null); - - CultureInfo culture; - - try - { - culture = new CultureInfo(name); - } - catch (ArgumentException) - { - // When CultureInfo throws this exception, it may be because someone passed the form - // like "az-az" because it came out of an http accept lang. We should try a little - // parsing to perhaps fall back to "az" here and use *it* to create the neutral. - - int idx; - - culture = null; - for (idx = 0; idx < name.Length; idx++) - { - if ('-' == name[idx]) - { - try - { - culture = new CultureInfo(name.Substring(0, idx)); - break; - } - catch (ArgumentException) - { - // throw the original exception so the name in the string will be right - throw; - } - } - } - - if (culture == null) - { - // nothing to save here; throw the original exception - throw; - } - } - - // In the most common case, they've given us a specific culture, so we'll just return that. - if (!(culture.IsNeutralCulture)) - { - return culture; - } - - return (new CultureInfo(culture.m_cultureData.SSPECIFICCULTURE)); - } - - // // - // // Return a specific culture. A tad irrelevent now since we always return valid data - // // for neutral locales. - // // - // // Note that there's interesting behavior that tries to find a smaller name, ala RFC4647, - // // if we can't find a bigger name. That doesn't help with things like "zh" though, so - // // the approach is of questionable value - // // - - 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]; - // TODO: Names can only be RFC4646 names (ie: a-zA-Z0-9) while this allows any unicode letter/digit - if (Char.IsLetterOrDigit(c) || c == '-' || c == '_') - { - continue; - } - if (throwException) - { - throw new ArgumentException(SR.Format(SR.Argument_InvalidResourceCultureName, cultureName)); - } - return false; - } - return true; - } - - internal static bool VerifyCultureName(CultureInfo culture, bool throwException) - { - //If we have an instance of one of our CultureInfos, the user can't have changed the - //name and we know that all names are valid in files. - if (!culture.m_isInherited) - { - return true; - } - - return VerifyCultureName(culture.Name, throwException); - } - - // We need to store the override from the culture data record. - private bool m_useUserOverride; - - [OnSerializing] - private void OnSerializing(StreamingContext ctx) - { - m_name = m_cultureData.CultureName; - m_useUserOverride = m_cultureData.UseUserOverride; - } - - [OnDeserialized] - private void OnDeserialized(StreamingContext ctx) - { - Debug.Assert(m_name != null, "[CultureInfo.OnDeserialized] m_name != null"); - InitializeFromName(m_name, m_useUserOverride); - } - - //////////////////////////////////////////////////////////////////////// - // - // CurrentCulture - // - // This instance provides methods based on the current user settings. - // These settings are volatile and may change over the lifetime of the - // thread. - // - //////////////////////////////////////////////////////////////////////// - - // - // We use the following order to return CurrentCulture and CurrentUICulture - // o Use WinRT to return the current user profile language - // o use current thread culture if the user already set one using CurrentCulture/CurrentUICulture - // o use thread culture if the user already set one using DefaultThreadCurrentCulture - // or DefaultThreadCurrentUICulture - // o Use NLS default user culture - // o Use NLS default system culture - // o Use Invariant culture - // - public static CultureInfo CurrentCulture - { - get - { - CultureInfo ci = GetUserDefaultCultureCacheOverride(); - if (ci != null) - { - return ci; - } - - if (s_currentThreadCulture != null) - { - return s_currentThreadCulture; - } - - ci = s_DefaultThreadCurrentCulture; - if (ci != null) - { - return ci; - } - - // if s_userDefaultCulture == null means CultureInfo statics didn't get initialized yet. this can happen if there early static - // method get executed which eventually hit the cultureInfo code while CultureInfo statics didn’t get chance to initialize - if (s_userDefaultCulture == null) - { - Init(); - } - - Debug.Assert(s_userDefaultCulture != null); - return s_userDefaultCulture; - } - - set - { - if (value == null) - { - throw new ArgumentNullException(nameof(value)); - } - - if (s_asyncLocalCurrentCulture == null) - { - Interlocked.CompareExchange(ref s_asyncLocalCurrentCulture, new AsyncLocal(AsyncLocalSetCurrentCulture), null); - } - // this one will set s_currentThreadCulture too - s_asyncLocalCurrentCulture.Value = value; - } - } - - public static CultureInfo CurrentUICulture - { - get - { - CultureInfo ci = GetUserDefaultCultureCacheOverride(); - if (ci != null) - { - return ci; - } - - if (s_currentThreadUICulture != null) - { - return s_currentThreadUICulture; - } - - ci = s_DefaultThreadCurrentUICulture; - if (ci != null) - { - return ci; - } - - // if s_userDefaultCulture == null means CultureInfo statics didn't get initialized yet. this can happen if there early static - // method get executed which eventually hit the cultureInfo code while CultureInfo statics didn’t get chance to initialize - if (s_userDefaultCulture == null) - { - Init(); - } - - Debug.Assert(s_userDefaultCulture != null); - return s_userDefaultCulture; - } - - set - { - if (value == null) - { - throw new ArgumentNullException(nameof(value)); - } - - CultureInfo.VerifyCultureName(value, true); - - if (s_asyncLocalCurrentUICulture == null) - { - Interlocked.CompareExchange(ref s_asyncLocalCurrentUICulture, new AsyncLocal(AsyncLocalSetCurrentUICulture), null); - } - - // this one will set s_currentThreadUICulture too - s_asyncLocalCurrentUICulture.Value = value; - } - } - - public static CultureInfo InstalledUICulture - { - get - { - Contract.Ensures(Contract.Result() != null); - if (s_userDefaultCulture == null) - { - Init(); - } - Debug.Assert(s_userDefaultCulture != null, "[CultureInfo.InstalledUICulture] s_userDefaultCulture != null"); - return s_userDefaultCulture; - } - } - - public static CultureInfo DefaultThreadCurrentCulture - { - get { return s_DefaultThreadCurrentCulture; } - set - { - // If you add pre-conditions to this method, check to see if you also need to - // add them to Thread.CurrentCulture.set. - - s_DefaultThreadCurrentCulture = value; - } - } - - public static CultureInfo DefaultThreadCurrentUICulture - { - get { return s_DefaultThreadCurrentUICulture; } - set - { - //If they're trying to use a Culture with a name that we can't use in resource lookup, - //don't even let them set it on the thread. - - // If you add more pre-conditions to this method, check to see if you also need to - // add them to Thread.CurrentUICulture.set. - - if (value != null) - { - CultureInfo.VerifyCultureName(value, true); - } - - s_DefaultThreadCurrentUICulture = value; - } - } - - //////////////////////////////////////////////////////////////////////// - // - // InvariantCulture - // - // This instance provides methods, for example for casing and sorting, - // that are independent of the system and current user settings. It - // should be used only by processes such as some system services that - // require such invariant results (eg. file systems). In general, - // the results are not linguistically correct and do not match any - // culture info. - // - //////////////////////////////////////////////////////////////////////// - - - public static CultureInfo InvariantCulture - { - get - { - return (s_InvariantCultureInfo); - } - } - - - //////////////////////////////////////////////////////////////////////// - // - // Parent - // - // Return the parent CultureInfo for the current instance. - // - //////////////////////////////////////////////////////////////////////// - - public virtual CultureInfo Parent - { - get - { - if (null == m_parent) - { - try - { - string parentName = this.m_cultureData.SPARENT; - - if (String.IsNullOrEmpty(parentName)) - { - m_parent = InvariantCulture; - } - else - { - m_parent = new CultureInfo(parentName, this.m_cultureData.UseUserOverride); - } - } - catch (ArgumentException) - { - // For whatever reason our IPARENT or SPARENT wasn't correct, so use invariant - // We can't allow ourselves to fail. In case of custom cultures the parent of the - // current custom culture isn't installed. - m_parent = InvariantCulture; - } - } - return m_parent; - } - } - - public virtual int LCID - { - get - { - return (this.m_cultureData.ILANGUAGE); - } - } - - public virtual int KeyboardLayoutId - { - get - { - return m_cultureData.IINPUTLANGUAGEHANDLE; - } - } - - public static CultureInfo[] GetCultures(CultureTypes types) - { - Contract.Ensures(Contract.Result() != null); - // internally we treat UserCustomCultures as Supplementals but v2 - // treats as Supplementals and Replacements - if((types & CultureTypes.UserCustomCulture) == CultureTypes.UserCustomCulture) - { - types |= CultureTypes.ReplacementCultures; - } - return (CultureData.GetCultures(types)); - } - - //////////////////////////////////////////////////////////////////////// - // - // Name - // - // Returns the full name of the CultureInfo. The name is in format like - // "en-US" This version does NOT include sort information in the name. - // - //////////////////////////////////////////////////////////////////////// - public virtual String Name - { - get - { - // We return non sorting name here. - if (this.m_nonSortName == null) - { - this.m_nonSortName = this.m_cultureData.SNAME; - if (this.m_nonSortName == null) - { - this.m_nonSortName = String.Empty; - } - } - return this.m_nonSortName; - } - } - - // This one has the sort information (ie: de-DE_phoneb) - internal String SortName - { - get - { - if (this.m_sortName == null) - { - this.m_sortName = this.m_cultureData.SCOMPAREINFO; - } - - return this.m_sortName; - } - } - - public string IetfLanguageTag - { - get - { - Contract.Ensures(Contract.Result() != null); - - // special case the compatibility cultures - switch (this.Name) - { - case "zh-CHT": - return "zh-Hant"; - case "zh-CHS": - return "zh-Hans"; - default: - return this.Name; - } - } - } - - //////////////////////////////////////////////////////////////////////// - // - // DisplayName - // - // Returns the full name of the CultureInfo in the localized language. - // For example, if the localized language of the runtime is Spanish and the CultureInfo is - // US English, "Ingles (Estados Unidos)" will be returned. - // - //////////////////////////////////////////////////////////////////////// - public virtual String DisplayName - { - get - { - Contract.Ensures(Contract.Result() != null); - Debug.Assert(m_name != null, "[CultureInfo.DisplayName] Always expect m_name to be set"); - - return m_cultureData.SLOCALIZEDDISPLAYNAME; - } - } - - //////////////////////////////////////////////////////////////////////// - // - // GetNativeName - // - // Returns the full name of the CultureInfo in the native language. - // For example, if the CultureInfo is US English, "English - // (United States)" will be returned. - // - //////////////////////////////////////////////////////////////////////// - public virtual String NativeName - { - get - { - Contract.Ensures(Contract.Result() != null); - return (this.m_cultureData.SNATIVEDISPLAYNAME); - } - } - - //////////////////////////////////////////////////////////////////////// - // - // GetEnglishName - // - // Returns the full name of the CultureInfo in English. - // For example, if the CultureInfo is US English, "English - // (United States)" will be returned. - // - //////////////////////////////////////////////////////////////////////// - public virtual String EnglishName - { - get - { - Contract.Ensures(Contract.Result() != null); - return (this.m_cultureData.SENGDISPLAYNAME); - } - } - - // ie: en - public virtual String TwoLetterISOLanguageName - { - get - { - Contract.Ensures(Contract.Result() != null); - return (this.m_cultureData.SISO639LANGNAME); - } - } - - // ie: eng - public virtual String ThreeLetterISOLanguageName - { - get - { - Contract.Ensures(Contract.Result() != null); - return m_cultureData.SISO639LANGNAME2; - } - } - - //////////////////////////////////////////////////////////////////////// - // - // ThreeLetterWindowsLanguageName - // - // Returns the 3 letter windows language name for the current instance. eg: "ENU" - // The ISO names are much preferred - // - //////////////////////////////////////////////////////////////////////// - public virtual String ThreeLetterWindowsLanguageName - { - get - { - Contract.Ensures(Contract.Result() != null); - return m_cultureData.SABBREVLANGNAME; - } - } - - //////////////////////////////////////////////////////////////////////// - // - // CompareInfo Read-Only Property - // - // Gets the CompareInfo for this culture. - // - //////////////////////////////////////////////////////////////////////// - public virtual CompareInfo CompareInfo - { - get - { - if (this.compareInfo == null) - { - // Since CompareInfo's don't have any overrideable properties, get the CompareInfo from - // the Non-Overridden CultureInfo so that we only create one CompareInfo per culture - CompareInfo temp = UseUserOverride - ? GetCultureInfo(this.m_name).CompareInfo - : new CompareInfo(this); - if (OkayToCacheClassWithCompatibilityBehavior) - { - this.compareInfo = temp; - } - else - { - return temp; - } - } - return (compareInfo); - } - } - - private static bool OkayToCacheClassWithCompatibilityBehavior - { - get - { - return true; - } - } - - //////////////////////////////////////////////////////////////////////// - // - // TextInfo - // - // Gets the TextInfo for this culture. - // - //////////////////////////////////////////////////////////////////////// - public virtual TextInfo TextInfo - { - get - { - if (textInfo == null) - { - // Make a new textInfo - TextInfo tempTextInfo = new TextInfo(this.m_cultureData); - tempTextInfo.SetReadOnlyState(m_isReadOnly); - - if (OkayToCacheClassWithCompatibilityBehavior) - { - textInfo = tempTextInfo; - } - else - { - return tempTextInfo; - } - } - return (textInfo); - } - } - - //////////////////////////////////////////////////////////////////////// - // - // Equals - // - // Implements Object.Equals(). Returns a boolean indicating whether - // or not object refers to the same CultureInfo as the current instance. - // - //////////////////////////////////////////////////////////////////////// - - - public override bool Equals(Object value) - { - if (Object.ReferenceEquals(this, value)) - return true; - - CultureInfo that = value as CultureInfo; - - if (that != null) - { - // using CompareInfo to verify the data passed through the constructor - // CultureInfo(String cultureName, String textAndCompareCultureName) - - return (this.Name.Equals(that.Name) && this.CompareInfo.Equals(that.CompareInfo)); - } - - return (false); - } - - - //////////////////////////////////////////////////////////////////////// - // - // GetHashCode - // - // Implements Object.GetHashCode(). Returns the hash code for the - // CultureInfo. The hash code is guaranteed to be the same for CultureInfo A - // and B where A.Equals(B) is true. - // - //////////////////////////////////////////////////////////////////////// - - public override int GetHashCode() - { - return (this.Name.GetHashCode() + this.CompareInfo.GetHashCode()); - } - - - //////////////////////////////////////////////////////////////////////// - // - // ToString - // - // Implements Object.ToString(). Returns the name of the CultureInfo, - // eg. "de-DE_phoneb", "en-US", or "fj-FJ". - // - //////////////////////////////////////////////////////////////////////// - - - public override String ToString() - { - return m_name; - } - - - public virtual Object GetFormat(Type formatType) - { - if (formatType == typeof(NumberFormatInfo)) - return (NumberFormat); - if (formatType == typeof(DateTimeFormatInfo)) - return (DateTimeFormat); - return (null); - } - - public virtual bool IsNeutralCulture - { - get - { - return this.m_cultureData.IsNeutralCulture; - } - } - - public CultureTypes CultureTypes - { - get - { - CultureTypes types = 0; - - if (m_cultureData.IsNeutralCulture) - types |= CultureTypes.NeutralCultures; - else - types |= CultureTypes.SpecificCultures; - - types |= m_cultureData.IsWin32Installed ? CultureTypes.InstalledWin32Cultures : 0; - -// Disable warning 618: System.Globalization.CultureTypes.FrameworkCultures' is obsolete -#pragma warning disable 618 - types |= m_cultureData.IsFramework ? CultureTypes.FrameworkCultures : 0; - -#pragma warning restore 618 - types |= m_cultureData.IsSupplementalCustomCulture ? CultureTypes.UserCustomCulture : 0; - types |= m_cultureData.IsReplacementCulture ? CultureTypes.ReplacementCultures | CultureTypes.UserCustomCulture : 0; - - return types; - } - } - - public virtual NumberFormatInfo NumberFormat - { - get - { - if (numInfo == null) - { - NumberFormatInfo temp = new NumberFormatInfo(this.m_cultureData); - temp.isReadOnly = m_isReadOnly; - Interlocked.CompareExchange(ref numInfo, temp, null); - } - return (numInfo); - } - set - { - if (value == null) - { - throw new ArgumentNullException(nameof(value), SR.ArgumentNull_Obj); - } - VerifyWritable(); - numInfo = value; - } - } - - //////////////////////////////////////////////////////////////////////// - // - // GetDateTimeFormatInfo - // - // Create a DateTimeFormatInfo, and fill in the properties according to - // the CultureID. - // - //////////////////////////////////////////////////////////////////////// - public virtual DateTimeFormatInfo DateTimeFormat - { - get - { - if (dateTimeInfo == null) - { - // Change the calendar of DTFI to the specified calendar of this CultureInfo. - DateTimeFormatInfo temp = new DateTimeFormatInfo(this.m_cultureData, this.Calendar); - temp._isReadOnly = m_isReadOnly; - Interlocked.CompareExchange(ref dateTimeInfo, temp, null); - } - return (dateTimeInfo); - } - - set - { - if (value == null) - { - throw new ArgumentNullException(nameof(value), SR.ArgumentNull_Obj); - } - VerifyWritable(); - dateTimeInfo = value; - } - } - - public void ClearCachedData() - { - s_userDefaultCulture = null; - - RegionInfo.s_currentRegionInfo = null; - #pragma warning disable 0618 // disable the obsolete warning - TimeZone.ResetTimeZone(); - #pragma warning restore 0618 - TimeZoneInfo.ClearCachedData(); - s_LcidCachedCultures = null; - s_NameCachedCultures = null; - - CultureData.ClearCachedData(); - } - - /*=================================GetCalendarInstance========================== - **Action: Map a Win32 CALID to an instance of supported calendar. - **Returns: An instance of calendar. - **Arguments: calType The Win32 CALID - **Exceptions: - ** Shouldn't throw exception since the calType value is from our data table or from Win32 registry. - ** If we are in trouble (like getting a weird value from Win32 registry), just return the GregorianCalendar. - ============================================================================*/ - internal static Calendar GetCalendarInstance(CalendarId calType) - { - if (calType == CalendarId.GREGORIAN) - { - return (new GregorianCalendar()); - } - return GetCalendarInstanceRare(calType); - } - - //This function exists as a shortcut to prevent us from loading all of the non-gregorian - //calendars unless they're required. - internal static Calendar GetCalendarInstanceRare(CalendarId calType) - { - Debug.Assert(calType != CalendarId.GREGORIAN, "calType!=CalendarId.GREGORIAN"); - - switch (calType) - { - case CalendarId.GREGORIAN_US: // Gregorian (U.S.) calendar - case CalendarId.GREGORIAN_ME_FRENCH: // Gregorian Middle East French calendar - case CalendarId.GREGORIAN_ARABIC: // Gregorian Arabic calendar - case CalendarId.GREGORIAN_XLIT_ENGLISH: // Gregorian Transliterated English calendar - case CalendarId.GREGORIAN_XLIT_FRENCH: // Gregorian Transliterated French calendar - return (new GregorianCalendar((GregorianCalendarTypes)calType)); - case CalendarId.TAIWAN: // Taiwan Era calendar - return (new TaiwanCalendar()); - case CalendarId.JAPAN: // Japanese Emperor Era calendar - return (new JapaneseCalendar()); - case CalendarId.KOREA: // Korean Tangun Era calendar - return (new KoreanCalendar()); - case CalendarId.THAI: // Thai calendar - return (new ThaiBuddhistCalendar()); - case CalendarId.HIJRI: // Hijri (Arabic Lunar) calendar - return (new HijriCalendar()); - case CalendarId.HEBREW: // Hebrew (Lunar) calendar - return (new HebrewCalendar()); - case CalendarId.UMALQURA: - return (new UmAlQuraCalendar()); - case CalendarId.PERSIAN: - return (new PersianCalendar()); - } - return (new GregorianCalendar()); - } - - /*=================================Calendar========================== - **Action: Return/set the default calendar used by this culture. - ** This value can be overridden by regional option if this is a current culture. - **Returns: - **Arguments: - **Exceptions: - ** ArgumentNull_Obj if the set value is null. - ============================================================================*/ - public virtual Calendar Calendar - { - get - { - if (calendar == null) - { - Debug.Assert(this.m_cultureData.CalendarIds.Length > 0, "this.m_cultureData.CalendarIds.Length > 0"); - // Get the default calendar for this culture. Note that the value can be - // from registry if this is a user default culture. - Calendar newObj = this.m_cultureData.DefaultCalendar; - - System.Threading.Interlocked.MemoryBarrier(); - newObj.SetReadOnlyState(m_isReadOnly); - calendar = newObj; - } - return (calendar); - } - } - - /*=================================OptionCalendars========================== - **Action: Return an array of the optional calendar for this culture. - **Returns: an array of Calendar. - **Arguments: - **Exceptions: - ============================================================================*/ - - - public virtual Calendar[] OptionalCalendars - { - get - { - Contract.Ensures(Contract.Result() != null); - - // - // This property always returns a new copy of the calendar array. - // - CalendarId[] calID = this.m_cultureData.CalendarIds; - Calendar[] cals = new Calendar[calID.Length]; - for (int i = 0; i < cals.Length; i++) - { - cals[i] = GetCalendarInstance(calID[i]); - } - return (cals); - } - } - - public bool UseUserOverride - { - get - { - return m_cultureData.UseUserOverride; - } - } - - public CultureInfo GetConsoleFallbackUICulture() - { - Contract.Ensures(Contract.Result() != null); - - CultureInfo temp = m_consoleFallbackCulture; - if (temp == null) - { - temp = CreateSpecificCulture(m_cultureData.SCONSOLEFALLBACKNAME); - temp.m_isReadOnly = true; - m_consoleFallbackCulture = temp; - } - return (temp); - } - - public virtual Object Clone() - { - CultureInfo ci = (CultureInfo)MemberwiseClone(); - ci.m_isReadOnly = false; - - //If this is exactly our type, we can make certain optimizations so that we don't allocate NumberFormatInfo or DTFI unless - //they've already been allocated. If this is a derived type, we'll take a more generic codepath. - if (!m_isInherited) - { - if (this.dateTimeInfo != null) - { - ci.dateTimeInfo = (DateTimeFormatInfo)this.dateTimeInfo.Clone(); - } - if (this.numInfo != null) - { - ci.numInfo = (NumberFormatInfo)this.numInfo.Clone(); - } - } - else - { - ci.DateTimeFormat = (DateTimeFormatInfo)this.DateTimeFormat.Clone(); - ci.NumberFormat = (NumberFormatInfo)this.NumberFormat.Clone(); - } - - if (textInfo != null) - { - ci.textInfo = (TextInfo)textInfo.Clone(); - } - - if (calendar != null) - { - ci.calendar = (Calendar)calendar.Clone(); - } - - return (ci); - } - - public static CultureInfo ReadOnly(CultureInfo ci) - { - if (ci == null) - { - throw new ArgumentNullException(nameof(ci)); - } - Contract.Ensures(Contract.Result() != null); - Contract.EndContractBlock(); - - if (ci.IsReadOnly) - { - return (ci); - } - CultureInfo newInfo = (CultureInfo)(ci.MemberwiseClone()); - - if (!ci.IsNeutralCulture) - { - //If this is exactly our type, we can make certain optimizations so that we don't allocate NumberFormatInfo or DTFI unless - //they've already been allocated. If this is a derived type, we'll take a more generic codepath. - if (!ci.m_isInherited) - { - if (ci.dateTimeInfo != null) - { - newInfo.dateTimeInfo = DateTimeFormatInfo.ReadOnly(ci.dateTimeInfo); - } - if (ci.numInfo != null) - { - newInfo.numInfo = NumberFormatInfo.ReadOnly(ci.numInfo); - } - } - else - { - newInfo.DateTimeFormat = DateTimeFormatInfo.ReadOnly(ci.DateTimeFormat); - newInfo.NumberFormat = NumberFormatInfo.ReadOnly(ci.NumberFormat); - } - } - - if (ci.textInfo != null) - { - newInfo.textInfo = TextInfo.ReadOnly(ci.textInfo); - } - - if (ci.calendar != null) - { - newInfo.calendar = Calendar.ReadOnly(ci.calendar); - } - - // Don't set the read-only flag too early. - // We should set the read-only flag here. Otherwise, info.DateTimeFormat will not be able to set. - newInfo.m_isReadOnly = true; - - return (newInfo); - } - - - public bool IsReadOnly - { - get - { - return (m_isReadOnly); - } - } - - private void VerifyWritable() - { - if (m_isReadOnly) - { - throw new InvalidOperationException(SR.InvalidOperation_ReadOnly); - } - } - - // 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; } - } - - // Helper function both both overloads of GetCachedReadOnlyCulture. If lcid is 0, we use the name. - // If lcid is -1, use the altName and create one of those special SQL cultures. - internal static CultureInfo GetCultureInfoHelper(int lcid, string name, string altName) - { - // retval is our return value. - CultureInfo retval; - - // Temporary hashtable for the names. - StringCultureInfoDictionary tempNameHT = s_NameCachedCultures; - - if (name != null) - { - name = CultureData.AnsiToLower(name); - } - - if (altName != null) - { - altName = CultureData.AnsiToLower(altName); - } - - // We expect the same result for both hashtables, but will test individually for added safety. - if (tempNameHT == null) - { - tempNameHT = new StringCultureInfoDictionary(); - } - else - { - // If we are called by name, check if the object exists in the hashtable. If so, return it. - if (lcid == -1 || lcid == 0) - { - bool ret; - lock (m_lock) - { - ret = tempNameHT.TryGetValue(lcid == 0 ? name : name + '\xfffd' + altName, out retval); - } - - if (ret && retval != null) - { - return retval; - } - } - } - - // Next, the Lcid table. - StringLcidDictionary tempLcidHT = s_LcidCachedCultures; - - if (tempLcidHT == null) - { - // Case insensitive is not an issue here, save the constructor call. - tempLcidHT = new StringLcidDictionary(); - } - else - { - // If we were called by Lcid, check if the object exists in the table. If so, return it. - if (lcid > 0) - { - bool ret; - lock (m_lock) - { - ret = tempLcidHT.TryGetValue(lcid, out retval); - } - if (ret && retval != null) - { - return retval; - } - } - } - - // We now have two temporary hashtables and the desired object was not found. - // We'll construct it. We catch any exceptions from the constructor call and return null. - try - { - switch (lcid) - { - case -1: - // call the private constructor - retval = new CultureInfo(name, altName); - break; - - case 0: - retval = new CultureInfo(name, false); - break; - - default: - retval = new CultureInfo(lcid, false); - break; - } - } - catch (ArgumentException) - { - return null; - } - - // Set it to read-only - retval.m_isReadOnly = true; - - if (lcid == -1) - { - lock (m_lock) - { - // This new culture will be added only to the name hash table. - tempNameHT[name + '\xfffd' + altName] = retval; - } - // when lcid == -1 then TextInfo object is already get created and we need to set it as read only. - retval.TextInfo.SetReadOnlyState(true); - } - else if (lcid == 0) - { - // Remember our name (as constructed). Do NOT use alternate sort name versions because - // we have internal state representing the sort. (So someone would get the wrong cached version) - string newName = CultureData.AnsiToLower(retval.m_name); - - // We add this new culture info object to both tables. - lock (m_lock) - { - tempNameHT[newName] = retval; - } - } - else - { - lock (m_lock) - { - tempLcidHT[lcid] = retval; - } - } - - // Copy the two hashtables to the corresponding member variables. This will potentially overwrite - // new tables simultaneously created by a new thread, but maximizes thread safety. - if (-1 != lcid) - { - // Only when we modify the lcid hash table, is there a need to overwrite. - s_LcidCachedCultures = tempLcidHT; - } - - s_NameCachedCultures = tempNameHT; - - // Finally, return our new CultureInfo object. - return retval; - } - - // Gets a cached copy of the specified culture from an internal hashtable (or creates it - // if not found). (LCID version)... use named version - public static CultureInfo GetCultureInfo(int culture) - { - // Must check for -1 now since the helper function uses the value to signal - // the altCulture code path for SQL Server. - // Also check for zero as this would fail trying to add as a key to the hash. - if (culture <= 0) - { - throw new ArgumentOutOfRangeException(nameof(culture), SR.ArgumentOutOfRange_NeedPosNum); - } - Contract.Ensures(Contract.Result() != null); - Contract.EndContractBlock(); - CultureInfo retval = GetCultureInfoHelper(culture, null, null); - if (null == retval) - { - throw new CultureNotFoundException(nameof(culture), culture, SR.Argument_CultureNotSupported); - } - return retval; - } - - // Gets a cached copy of the specified culture from an internal hashtable (or creates it - // if not found). (Named version) - public static CultureInfo GetCultureInfo(string name) - { - // Make sure we have a valid, non-zero length string as name - if (name == null) - { - throw new ArgumentNullException(nameof(name)); - } - - CultureInfo retval = GetCultureInfoHelper(0, name, null); - if (retval == null) - { - throw new CultureNotFoundException( - nameof(name), name, SR.Argument_CultureNotSupported); - } - return retval; - } - - // Gets a cached copy of the specified culture from an internal hashtable (or creates it - // if not found). - public static CultureInfo GetCultureInfo(string name, string altName) - { - // Make sure we have a valid, non-zero length string as name - if (name == null) - { - throw new ArgumentNullException(nameof(name)); - } - - if (altName == null) - { - throw new ArgumentNullException(nameof(altName)); - } - - Contract.Ensures(Contract.Result() != null); - Contract.EndContractBlock(); - - CultureInfo retval = GetCultureInfoHelper(-1, name, altName); - if (retval == null) - { - throw new CultureNotFoundException("name or altName", - SR.Format(SR.Argument_OneOfCulturesNotSupported, name, altName)); - } - return retval; - } - - // This function is deprecated, we don't like it - public static CultureInfo GetCultureInfoByIetfLanguageTag(string name) - { - Contract.Ensures(Contract.Result() != null); - - // Disallow old zh-CHT/zh-CHS names - if (name == "zh-CHT" || name == "zh-CHS") - { - throw new CultureNotFoundException(nameof(name), SR.Format(SR.Argument_CultureIetfNotSupported, name)); - } - - CultureInfo ci = GetCultureInfo(name); - - // Disallow alt sorts and es-es_TS - if (ci.LCID > 0xffff || ci.LCID == 0x040a) - { - throw new CultureNotFoundException(nameof(name), SR.Format(SR.Argument_CultureIetfNotSupported, name)); - } - - return ci; - } - } -} - diff --git a/src/mscorlib/corefx/System/Globalization/CultureNotFoundException.cs b/src/mscorlib/corefx/System/Globalization/CultureNotFoundException.cs deleted file mode 100644 index d296ad8..0000000 --- a/src/mscorlib/corefx/System/Globalization/CultureNotFoundException.cs +++ /dev/null @@ -1,122 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.Runtime.Serialization; -using System.Threading; - -namespace System.Globalization -{ - [Serializable] - public class CultureNotFoundException : ArgumentException, ISerializable - { - private string _invalidCultureName; // unrecognized culture name - private int? _invalidCultureId; // unrecognized culture Lcid - - public CultureNotFoundException() - : base(DefaultMessage) - { - } - - public CultureNotFoundException(String message) - : base(message) - { - } - - public CultureNotFoundException(String paramName, String message) - : base(message, paramName) - { - } - - public CultureNotFoundException(String message, Exception innerException) - : base(message, innerException) - { - } - - public CultureNotFoundException(String paramName, string invalidCultureName, String message) - : base(message, paramName) - { - _invalidCultureName = invalidCultureName; - } - - public CultureNotFoundException(String message, string invalidCultureName, Exception innerException) - : base(message, innerException) - { - _invalidCultureName = invalidCultureName; - } - - public CultureNotFoundException(string message, int invalidCultureId, Exception innerException) - : base(message, innerException) - { - _invalidCultureId = invalidCultureId; - } - - public CultureNotFoundException(string paramName, int invalidCultureId, string message) - : base(message, paramName) - { - _invalidCultureId = invalidCultureId; - } - - protected CultureNotFoundException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - _invalidCultureId = (int?)info.GetValue("InvalidCultureId", typeof(int?)); - _invalidCultureName = (string)info.GetValue("InvalidCultureName", typeof(string)); - } - - public override void GetObjectData(SerializationInfo info, StreamingContext context) - { - base.GetObjectData(info, context); - info.AddValue("InvalidCultureId", _invalidCultureId, typeof(int?)); - info.AddValue("InvalidCultureName", _invalidCultureName, typeof(string)); - } - - public virtual Nullable InvalidCultureId - { - get { return _invalidCultureId; } - } - - public virtual string InvalidCultureName - { - get { return _invalidCultureName; } - } - - private static String DefaultMessage - { - get - { - return SR.Argument_CultureNotSupported; - } - } - - private String FormatedInvalidCultureId - { - get - { - return InvalidCultureId != null ? - String.Format(CultureInfo.InvariantCulture, "{0} (0x{0:x4})", (int)InvalidCultureId) : - InvalidCultureName; - } - } - - public override String Message - { - get - { - String s = base.Message; - if (_invalidCultureId != null || _invalidCultureName != null) - { - String valueMessage = SR.Format(SR.Argument_CultureInvalidIdentifier, FormatedInvalidCultureId); - if (s == null) - { - return valueMessage; - } - - return s + Environment.NewLine + valueMessage; - } - return s; - } - } - } -} diff --git a/src/mscorlib/corefx/System/Globalization/CultureTypes.cs b/src/mscorlib/corefx/System/Globalization/CultureTypes.cs deleted file mode 100644 index 35ddff6..0000000 --- a/src/mscorlib/corefx/System/Globalization/CultureTypes.cs +++ /dev/null @@ -1,28 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -// The enumeration constants used in CultureInfo.GetCultures(). -// On Linux platforms, the only enum values used there is NeutralCultures and SpecificCultures -// the rest are obsolete or not valid on Linux - -namespace System.Globalization -{ - [Serializable] - [Flags] - public enum CultureTypes - { - NeutralCultures = 0x0001, // Neutral cultures are cultures like "en", "de", "zh", etc, for enumeration this includes ALL neutrals regardless of other flags - SpecificCultures = 0x0002, // Non-netural cultuers. Examples are "en-us", "zh-tw", etc., for enumeration this includes ALL specifics regardless of other flags - InstalledWin32Cultures = 0x0004, // Win32 installed cultures in the system and exists in the framework too., this is effectively all cultures - - AllCultures = NeutralCultures | SpecificCultures | InstalledWin32Cultures, - - UserCustomCulture = 0x0008, // User defined custom culture - ReplacementCultures = 0x0010, // User defined replacement custom culture. - [Obsolete("This value has been deprecated. Please use other values in CultureTypes.")] - WindowsOnlyCultures = 0x0020, // this will always return empty list. - [Obsolete("This value has been deprecated. Please use other values in CultureTypes.")] - FrameworkCultures = 0x0040, // will return only the v2 cultures marked as Framework culture. - } -} diff --git a/src/mscorlib/corefx/System/Globalization/DateTimeFormatInfo.cs b/src/mscorlib/corefx/System/Globalization/DateTimeFormatInfo.cs deleted file mode 100644 index bcfd6b1..0000000 --- a/src/mscorlib/corefx/System/Globalization/DateTimeFormatInfo.cs +++ /dev/null @@ -1,3087 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System.Collections.Generic; -using System.Diagnostics; -using System.Diagnostics.Contracts; -using System.Runtime.Serialization; - -namespace System.Globalization -{ - // - // Flags used to indicate different styles of month names. - // This is an internal flag used by internalGetMonthName(). - // Use flag here in case that we need to provide a combination of these styles - // (such as month name of a leap year in genitive form. Not likely for now, - // but would like to keep the option open). - // - - [Flags] - internal enum MonthNameStyles - { - Regular = 0x00000000, - Genitive = 0x00000001, - LeapYear = 0x00000002, - } - - // - // Flags used to indicate special rule used in parsing/formatting - // for a specific DateTimeFormatInfo instance. - // This is an internal flag. - // - // This flag is different from MonthNameStyles because this flag - // can be expanded to accomodate parsing behaviors like CJK month names - // or alternative month names, etc. - - [Flags] - internal enum DateTimeFormatFlags - { - None = 0x00000000, - UseGenitiveMonth = 0x00000001, - UseLeapYearMonth = 0x00000002, - UseSpacesInMonthNames = 0x00000004, // Has spaces or non-breaking space in the month names. - UseHebrewRule = 0x00000008, // Format/Parse using the Hebrew calendar rule. - UseSpacesInDayNames = 0x00000010, // Has spaces or non-breaking space in the day names. - UseDigitPrefixInTokens = 0x00000020, // Has token starting with numbers. - - NotInitialized = -1, - } - - - [Serializable] - public sealed class DateTimeFormatInfo : IFormatProvider, ICloneable - { - // cache for the invariant culture. - // invariantInfo is constant irrespective of your current culture. - private static volatile DateTimeFormatInfo s_invariantInfo; - - // an index which points to a record in Culture Data Table. - [NonSerialized] - private CultureData _cultureData; - - // The culture name used to create this DTFI. - - [OptionalField(VersionAdded = 2)] - private String _name = null; - - // The language name of the culture used to create this DTFI. - [NonSerialized] - private String _langName = null; - - // CompareInfo usually used by the parser. - [NonSerialized] - private CompareInfo _compareInfo = null; - - // Culture matches current DTFI. mainly used for string comparisons during parsing. - [NonSerialized] - private CultureInfo _cultureInfo = null; - - // - // Caches for various properties. - // - - private String amDesignator = null; - private String pmDesignator = null; - - private String dateSeparator = null; // derived from short date (whidbey expects, arrowhead doesn't) - - private String generalShortTimePattern = null; // short date + short time (whidbey expects, arrowhead doesn't) - - private String generalLongTimePattern = null; // short date + long time (whidbey expects, arrowhead doesn't) - - private String timeSeparator = null; // derived from long time (whidbey expects, arrowhead doesn't) - private String monthDayPattern = null; - // added in .NET Framework Release {2.0SP1/3.0SP1/3.5RTM} - private String dateTimeOffsetPattern = null; - - // - // The following are constant values. - // - private const String rfc1123Pattern = "ddd, dd MMM yyyy HH':'mm':'ss 'GMT'"; - - // The sortable pattern is based on ISO 8601. - private const String sortableDateTimePattern = "yyyy'-'MM'-'dd'T'HH':'mm':'ss"; - private const String universalSortableDateTimePattern = "yyyy'-'MM'-'dd HH':'mm':'ss'Z'"; - - // - // The following are affected by calendar settings. - // - private Calendar calendar = null; - - private int firstDayOfWeek = -1; - private int calendarWeekRule = -1; - - - private String fullDateTimePattern = null; // long date + long time (whidbey expects, arrowhead doesn't) - - private String[] abbreviatedDayNames = null; - - - private String[] m_superShortDayNames = null; - - private String[] dayNames = null; - private String[] abbreviatedMonthNames = null; - private String[] monthNames = null; - // Cache the genitive month names that we retrieve from the data table. - - private String[] genitiveMonthNames = null; - - // Cache the abbreviated genitive month names that we retrieve from the data table. - - private String[] m_genitiveAbbreviatedMonthNames = null; - - // Cache the month names of a leap year that we retrieve from the data table. - - private String[] leapYearMonthNames = null; - - // For our "patterns" arrays we have 2 variables, a string and a string[] - // - // The string[] contains the list of patterns, EXCEPT the default may not be included. - // The string contains the default pattern. - // When we initially construct our string[], we set the string to string[0] - - // The "default" Date/time patterns - private String longDatePattern = null; - private String shortDatePattern = null; - private String yearMonthPattern = null; - private String longTimePattern = null; - private String shortTimePattern = null; - - [OptionalField(VersionAdded = 3)] - private String[] allYearMonthPatterns = null; - - private String[] allShortDatePatterns = null; - private String[] allLongDatePatterns = null; - private String[] allShortTimePatterns = null; - private String[] allLongTimePatterns = null; - - // Cache the era names for this DateTimeFormatInfo instance. - private String[] m_eraNames = null; - private String[] m_abbrevEraNames = null; - private String[] m_abbrevEnglishEraNames = null; - - private CalendarId[] optionalCalendars = null; - - private const int DEFAULT_ALL_DATETIMES_SIZE = 132; - - // CultureInfo updates this - internal bool _isReadOnly = false; - - // This flag gives hints about if formatting/parsing should perform special code path for things like - // genitive form or leap year month names. - - private DateTimeFormatFlags formatFlags = DateTimeFormatFlags.NotInitialized; - - private String CultureName - { - get - { - if (_name == null) - { - _name = _cultureData.CultureName; - } - return (_name); - } - } - - private CultureInfo Culture - { - get - { - if (_cultureInfo == null) - { - _cultureInfo = CultureInfo.GetCultureInfo(this.CultureName); - } - return _cultureInfo; - } - } - - // TODO: This ignores other cultures that might want to do something similar - private String LanguageName - { - get - { - if (_langName == null) - { - _langName = _cultureData.SISO639LANGNAME; - } - return (_langName); - } - } - - //////////////////////////////////////////////////////////////////////////// - // - // Create an array of string which contains the abbreviated day names. - // - //////////////////////////////////////////////////////////////////////////// - - private String[] internalGetAbbreviatedDayOfWeekNames() - { - if (this.abbreviatedDayNames == null) - { - // Get the abbreviated day names for our current calendar - this.abbreviatedDayNames = _cultureData.AbbreviatedDayNames(Calendar.ID); - Debug.Assert(this.abbreviatedDayNames.Length == 7, "[DateTimeFormatInfo.GetAbbreviatedDayOfWeekNames] Expected 7 day names in a week"); - } - return (this.abbreviatedDayNames); - } - - - //////////////////////////////////////////////////////////////////////// - // - // Action: Returns the string array of the one-letter day of week names. - // Returns: - // an array of one-letter day of week names - // Arguments: - // None - // Exceptions: - // None - // - //////////////////////////////////////////////////////////////////////// - - private String[] internalGetSuperShortDayNames() - { - if (this.m_superShortDayNames == null) - { - // Get the super short day names for our current calendar - this.m_superShortDayNames = _cultureData.SuperShortDayNames(Calendar.ID); - Debug.Assert(this.m_superShortDayNames.Length == 7, "[DateTimeFormatInfo.internalGetSuperShortDayNames] Expected 7 day names in a week"); - } - return (this.m_superShortDayNames); - } - - //////////////////////////////////////////////////////////////////////////// - // - // Create an array of string which contains the day names. - // - //////////////////////////////////////////////////////////////////////////// - - private String[] internalGetDayOfWeekNames() - { - if (this.dayNames == null) - { - // Get the day names for our current calendar - this.dayNames = _cultureData.DayNames(Calendar.ID); - Debug.Assert(this.dayNames.Length == 7, "[DateTimeFormatInfo.GetDayOfWeekNames] Expected 7 day names in a week"); - } - return (this.dayNames); - } - - //////////////////////////////////////////////////////////////////////////// - // - // Create an array of string which contains the abbreviated month names. - // - //////////////////////////////////////////////////////////////////////////// - - private String[] internalGetAbbreviatedMonthNames() - { - if (this.abbreviatedMonthNames == null) - { - // Get the month names for our current calendar - this.abbreviatedMonthNames = _cultureData.AbbreviatedMonthNames(Calendar.ID); - Debug.Assert(this.abbreviatedMonthNames.Length == 12 || this.abbreviatedMonthNames.Length == 13, - "[DateTimeFormatInfo.GetAbbreviatedMonthNames] Expected 12 or 13 month names in a year"); - } - return (this.abbreviatedMonthNames); - } - - - //////////////////////////////////////////////////////////////////////////// - // - // Create an array of string which contains the month names. - // - //////////////////////////////////////////////////////////////////////////// - - private String[] internalGetMonthNames() - { - if (this.monthNames == null) - { - // Get the month names for our current calendar - this.monthNames = _cultureData.MonthNames(Calendar.ID); - Debug.Assert(this.monthNames.Length == 12 || this.monthNames.Length == 13, - "[DateTimeFormatInfo.GetMonthNames] Expected 12 or 13 month names in a year"); - } - - return (this.monthNames); - } - - - // - // Invariant DateTimeFormatInfo doesn't have user-overriden values - // Default calendar is gregorian - public DateTimeFormatInfo() - : this(CultureInfo.InvariantCulture.m_cultureData, - GregorianCalendar.GetDefaultInstance()) - { - } - - internal DateTimeFormatInfo(CultureData cultureData, Calendar cal) - { - Debug.Assert(cultureData != null); - Debug.Assert(cal != null); - - // Remember our culture - _cultureData = cultureData; - - this.Calendar = cal; - } - - private void InitializeOverridableProperties(CultureData cultureData, CalendarId calendarId) - { - Debug.Assert(cultureData != null); - Debug.Assert(calendarId != CalendarId.UNINITIALIZED_VALUE, "[DateTimeFormatInfo.Populate] Expected initalized calendarId"); - - if (this.firstDayOfWeek == -1) { this.firstDayOfWeek = cultureData.IFIRSTDAYOFWEEK; } - if (this.calendarWeekRule == -1) { this.calendarWeekRule = cultureData.IFIRSTWEEKOFYEAR; } - - if (this.amDesignator == null) { this.amDesignator = cultureData.SAM1159; } - if (this.pmDesignator == null) { this.pmDesignator = cultureData.SPM2359; } - if (this.timeSeparator == null) { this.timeSeparator = cultureData.TimeSeparator; } - if (this.dateSeparator == null) { this.dateSeparator = cultureData.DateSeparator(calendarId); } - - this.allLongTimePatterns = _cultureData.LongTimes; - Debug.Assert(this.allLongTimePatterns.Length > 0, "[DateTimeFormatInfo.Populate] Expected some long time patterns"); - - this.allShortTimePatterns = _cultureData.ShortTimes; - Debug.Assert(this.allShortTimePatterns.Length > 0, "[DateTimeFormatInfo.Populate] Expected some short time patterns"); - - this.allLongDatePatterns = cultureData.LongDates(calendarId); - Debug.Assert(this.allLongDatePatterns.Length > 0, "[DateTimeFormatInfo.Populate] Expected some long date patterns"); - - this.allShortDatePatterns = cultureData.ShortDates(calendarId); - Debug.Assert(this.allShortDatePatterns.Length > 0, "[DateTimeFormatInfo.Populate] Expected some short date patterns"); - - this.allYearMonthPatterns = cultureData.YearMonths(calendarId); - Debug.Assert(this.allYearMonthPatterns.Length > 0, "[DateTimeFormatInfo.Populate] Expected some year month patterns"); - } - - [OptionalField(VersionAdded = 1)] - private bool _useUserOverride; - - // This was synthesized by Whidbey so we knew what words might appear in the middle of a date string - // Now we always synthesize so its not helpful - - internal String[] m_dateWords = null; - - [OnSerializing] - private void OnSerializing(StreamingContext ctx) - { - _name = this.CultureName; // make sure the _name is initialized. - _useUserOverride = _cultureData.UseUserOverride; - - // Important to initialize these fields otherwise we may run into exception when deserializing on Whidbey - // because Whidbey try to initialize some of these fields using calendar data which could be null values - // and then we get exceptions. So we call the accessors to force the caches to get loaded. - Object o; - o = this.LongTimePattern; - o = this.LongDatePattern; - o = this.ShortTimePattern; - o = this.ShortDatePattern; - o = this.YearMonthPattern; - o = this.AllLongTimePatterns; - o = this.AllLongDatePatterns; - o = this.AllShortTimePatterns; - o = this.AllShortDatePatterns; - o = this.AllYearMonthPatterns; - } - - [OnDeserialized] - private void OnDeserialized(StreamingContext ctx) - { - if (_name != null) - { - _cultureData = CultureData.GetCultureData(_name, _useUserOverride); - if (_cultureData == null) - { - throw new CultureNotFoundException("_name", _name, SR.Argument_CultureNotSupported); - } - } - - if (calendar == null) - { - calendar = (Calendar)GregorianCalendar.GetDefaultInstance().Clone(); - calendar.SetReadOnlyState(_isReadOnly); - } - - InitializeOverridableProperties(_cultureData, calendar.ID); - - // - // turn off read only state till we finish initializing all fields and then store read only state after we are done. - // - bool isReadOnly = _isReadOnly; - _isReadOnly = false; - - // If we deserialized defaults ala Whidbey, make sure they're still defaults - // Whidbey's arrays could get a bit mixed up. - if (longDatePattern != null) this.LongDatePattern = longDatePattern; - if (shortDatePattern != null) this.ShortDatePattern = shortDatePattern; - if (yearMonthPattern != null) this.YearMonthPattern = yearMonthPattern; - if (longTimePattern != null) this.LongTimePattern = longTimePattern; - if (shortTimePattern != null) this.ShortTimePattern = shortTimePattern; - - _isReadOnly = isReadOnly; - } - - // Returns a default DateTimeFormatInfo that will be universally - // supported and constant irrespective of the current culture. - // Used by FromString methods. - // - - public static DateTimeFormatInfo InvariantInfo - { - get - { - Contract.Ensures(Contract.Result() != null); - if (s_invariantInfo == null) - { - DateTimeFormatInfo info = new DateTimeFormatInfo(); - info.Calendar.SetReadOnlyState(true); - info._isReadOnly = true; - s_invariantInfo = info; - } - return (s_invariantInfo); - } - } - - // Returns the current culture's DateTimeFormatInfo. Used by Parse methods. - // - - public static DateTimeFormatInfo CurrentInfo - { - get - { - Contract.Ensures(Contract.Result() != null); - System.Globalization.CultureInfo culture = System.Globalization.CultureInfo.CurrentCulture; - if (!culture.m_isInherited) - { - DateTimeFormatInfo info = culture.dateTimeInfo; - if (info != null) - { - return info; - } - } - return (DateTimeFormatInfo)culture.GetFormat(typeof(DateTimeFormatInfo)); - } - } - - - public static DateTimeFormatInfo GetInstance(IFormatProvider provider) - { - // Fast case for a regular CultureInfo - DateTimeFormatInfo info; - CultureInfo cultureProvider = provider as CultureInfo; - if (cultureProvider != null && !cultureProvider.m_isInherited) - { - return cultureProvider.DateTimeFormat; - } - // Fast case for a DTFI; - info = provider as DateTimeFormatInfo; - if (info != null) - { - return info; - } - // Wasn't cultureInfo or DTFI, do it the slower way - if (provider != null) - { - info = provider.GetFormat(typeof(DateTimeFormatInfo)) as DateTimeFormatInfo; - if (info != null) - { - return info; - } - } - // Couldn't get anything, just use currentInfo as fallback - return CurrentInfo; - } - - - public Object GetFormat(Type formatType) - { - return (formatType == typeof(DateTimeFormatInfo) ? this : null); - } - - - public Object Clone() - { - DateTimeFormatInfo n = (DateTimeFormatInfo)MemberwiseClone(); - // We can use the data member calendar in the setter, instead of the property Calendar, - // since the cloned copy should have the same state as the original copy. - n.calendar = (Calendar)this.Calendar.Clone(); - n._isReadOnly = false; - return n; - } - - - public String AMDesignator - { - get - { - if (this.amDesignator == null) - { - this.amDesignator = _cultureData.SAM1159; - } - Debug.Assert(this.amDesignator != null, "DateTimeFormatInfo.AMDesignator, amDesignator != null"); - return (this.amDesignator); - } - - set - { - if (IsReadOnly) - throw new InvalidOperationException(SR.InvalidOperation_ReadOnly); - if (value == null) - { - throw new ArgumentNullException(nameof(value), - SR.ArgumentNull_String); - } - Contract.EndContractBlock(); - ClearTokenHashTable(); - amDesignator = value; - } - } - - - public Calendar Calendar - { - get - { - Contract.Ensures(Contract.Result() != null); - - Debug.Assert(this.calendar != null, "DateTimeFormatInfo.Calendar: calendar != null"); - return (this.calendar); - } - - set - { - if (IsReadOnly) - throw new InvalidOperationException(SR.InvalidOperation_ReadOnly); - if (value == null) - { - throw new ArgumentNullException(nameof(value), SR.ArgumentNull_Obj); - } - Contract.EndContractBlock(); - if (value == calendar) - { - return; - } - - for (int i = 0; i < this.OptionalCalendars.Length; i++) - { - if (this.OptionalCalendars[i] == value.ID) - { - // We can use this one, so do so. - - // Clean related properties if we already had a calendar set - if (calendar != null) - { - // clean related properties which are affected by the calendar setting, - // so that they will be refreshed when they are accessed next time. - // - - // These properites are in the order as appearing in calendar.xml. - m_eraNames = null; - m_abbrevEraNames = null; - m_abbrevEnglishEraNames = null; - - monthDayPattern = null; - - dayNames = null; - abbreviatedDayNames = null; - m_superShortDayNames = null; - monthNames = null; - abbreviatedMonthNames = null; - genitiveMonthNames = null; - m_genitiveAbbreviatedMonthNames = null; - leapYearMonthNames = null; - formatFlags = DateTimeFormatFlags.NotInitialized; - - allShortDatePatterns = null; - allLongDatePatterns = null; - allYearMonthPatterns = null; - dateTimeOffsetPattern = null; - - // The defaults need reset as well: - longDatePattern = null; - shortDatePattern = null; - yearMonthPattern = null; - - // These properies are not in the OS data, but they are dependent on the values like shortDatePattern. - fullDateTimePattern = null; // Long date + long time - generalShortTimePattern = null; // short date + short time - generalLongTimePattern = null; // short date + long time - - // Derived item that changes - dateSeparator = null; - - // We don't need to do these because they are not changed by changing calendar - // amDesignator - // pmDesignator - // timeSeparator - // longTimePattern - // firstDayOfWeek - // calendarWeekRule - - // remember to reload tokens - ClearTokenHashTable(); - } - - // Remember the new calendar - calendar = value; - InitializeOverridableProperties(_cultureData, calendar.ID); - - // We succeeded, return - return; - } - } - - // The assigned calendar is not a valid calendar for this culture, throw - throw new ArgumentOutOfRangeException(nameof(value), SR.Argument_InvalidCalendar); - } - } - - private CalendarId[] OptionalCalendars - { - get - { - if (this.optionalCalendars == null) - { - this.optionalCalendars = _cultureData.CalendarIds; - } - return (this.optionalCalendars); - } - } - - /*=================================GetEra========================== - **Action: Get the era value by parsing the name of the era. - **Returns: The era value for the specified era name. - ** -1 if the name of the era is not valid or not supported. - **Arguments: eraName the name of the era. - **Exceptions: None. - ============================================================================*/ - - - public int GetEra(String eraName) - { - if (eraName == null) - { - throw new ArgumentNullException(nameof(eraName), - SR.ArgumentNull_String); - } - Contract.EndContractBlock(); - - // The Era Name and Abbreviated Era Name - // for Taiwan Calendar on non-Taiwan SKU returns empty string (which - // would be matched below) but we don't want the empty string to give - // us an Era number - // confer 85900 DTFI.GetEra("") should fail on all cultures - if (eraName.Length == 0) - { - return (-1); - } - - // The following is based on the assumption that the era value is starting from 1, and has a - // serial values. - // If that ever changes, the code has to be changed. - - // The calls to String.Compare should use the current culture for the string comparisons, but the - // invariant culture when comparing against the english names. - for (int i = 0; i < EraNames.Length; i++) - { - // Compare the era name in a case-insensitive way for the appropriate culture. - if (m_eraNames[i].Length > 0) - { - if (this.Culture.CompareInfo.Compare(eraName, m_eraNames[i], CompareOptions.IgnoreCase) == 0) - { - return (i + 1); - } - } - } - for (int i = 0; i < AbbreviatedEraNames.Length; i++) - { - // Compare the abbreviated era name in a case-insensitive way for the appropriate culture. - if (this.Culture.CompareInfo.Compare(eraName, m_abbrevEraNames[i], CompareOptions.IgnoreCase) == 0) - { - return (i + 1); - } - } - for (int i = 0; i < AbbreviatedEnglishEraNames.Length; i++) - { - // this comparison should use the InvariantCulture. The English name could have linguistically - // interesting characters. - if (CultureInfo.InvariantCulture.CompareInfo.Compare(eraName, m_abbrevEnglishEraNames[i], CompareOptions.IgnoreCase) == 0) - { - return (i + 1); - } - } - return (-1); - } - - - internal String[] EraNames - { - get - { - if (this.m_eraNames == null) - { - this.m_eraNames = _cultureData.EraNames(Calendar.ID); ; - } - return (this.m_eraNames); - } - } - - /*=================================GetEraName========================== - **Action: Get the name of the era for the specified era value. - **Returns: The name of the specified era. - **Arguments: - ** era the era value. - **Exceptions: - ** ArguementException if the era valie is invalid. - ============================================================================*/ - - // Era names are 1 indexed - public String GetEraName(int era) - { - if (era == Calendar.CurrentEra) - { - era = Calendar.CurrentEraValue; - } - - // The following is based on the assumption that the era value is starting from 1, and has a - // serial values. - // If that ever changes, the code has to be changed. - if ((--era) < EraNames.Length && (era >= 0)) - { - return (m_eraNames[era]); - } - throw new ArgumentOutOfRangeException(nameof(era), SR.ArgumentOutOfRange_InvalidEraValue); - } - - internal String[] AbbreviatedEraNames - { - get - { - if (this.m_abbrevEraNames == null) - { - this.m_abbrevEraNames = _cultureData.AbbrevEraNames(Calendar.ID); - } - return (this.m_abbrevEraNames); - } - } - - // Era names are 1 indexed - public String GetAbbreviatedEraName(int era) - { - if (AbbreviatedEraNames.Length == 0) - { - // If abbreviation era name is not used in this culture, - // return the full era name. - return (GetEraName(era)); - } - if (era == Calendar.CurrentEra) - { - era = Calendar.CurrentEraValue; - } - if ((--era) < m_abbrevEraNames.Length && (era >= 0)) - { - return (m_abbrevEraNames[era]); - } - throw new ArgumentOutOfRangeException(nameof(era), SR.ArgumentOutOfRange_InvalidEraValue); - } - - internal String[] AbbreviatedEnglishEraNames - { - get - { - if (this.m_abbrevEnglishEraNames == null) - { - Debug.Assert(Calendar.ID > 0, "[DateTimeFormatInfo.AbbreviatedEnglishEraNames] Expected Calendar.ID > 0"); - this.m_abbrevEnglishEraNames = _cultureData.AbbreviatedEnglishEraNames(Calendar.ID); - } - return (this.m_abbrevEnglishEraNames); - } - } - - // Note that cultureData derives this from the short date format (unless someone's set this previously) - // Note that this property is quite undesirable. - public string DateSeparator - { - get - { - if (dateSeparator == null) - { - dateSeparator = _cultureData.DateSeparator(Calendar.ID); - } - Debug.Assert(this.dateSeparator != null, "DateTimeFormatInfo.DateSeparator, dateSeparator != null"); - return dateSeparator; - } - set - { - if (IsReadOnly) - throw new InvalidOperationException(SR.InvalidOperation_ReadOnly); - - if (value == null) - { - throw new ArgumentNullException(nameof(value), SR.ArgumentNull_String); - } - Contract.EndContractBlock(); - ClearTokenHashTable(); - dateSeparator = value; - } - } - - public DayOfWeek FirstDayOfWeek - { - get - { - if (this.firstDayOfWeek == -1) - { - this.firstDayOfWeek = _cultureData.IFIRSTDAYOFWEEK; - } - Debug.Assert(this.firstDayOfWeek != -1, "DateTimeFormatInfo.FirstDayOfWeek, firstDayOfWeek != -1"); - - return ((DayOfWeek)this.firstDayOfWeek); - } - - set - { - if (IsReadOnly) - throw new InvalidOperationException(SR.InvalidOperation_ReadOnly); - if (value >= DayOfWeek.Sunday && value <= DayOfWeek.Saturday) - { - firstDayOfWeek = (int)value; - } - else - { - throw new ArgumentOutOfRangeException( - nameof(value), SR.Format(SR.ArgumentOutOfRange_Range, - DayOfWeek.Sunday, DayOfWeek.Saturday)); - } - } - } - - public CalendarWeekRule CalendarWeekRule - { - get - { - if (this.calendarWeekRule == -1) - { - this.calendarWeekRule = _cultureData.IFIRSTWEEKOFYEAR; - } - Debug.Assert(this.calendarWeekRule != -1, "DateTimeFormatInfo.CalendarWeekRule, calendarWeekRule != -1"); - return ((CalendarWeekRule)this.calendarWeekRule); - } - - set - { - if (IsReadOnly) - throw new InvalidOperationException(SR.InvalidOperation_ReadOnly); - if (value >= CalendarWeekRule.FirstDay && value <= CalendarWeekRule.FirstFourDayWeek) - { - calendarWeekRule = (int)value; - } - else - { - throw new ArgumentOutOfRangeException( - nameof(value), SR.Format(SR.ArgumentOutOfRange_Range, - CalendarWeekRule.FirstDay, CalendarWeekRule.FirstFourDayWeek)); - } - } - } - - public String FullDateTimePattern - { - get - { - if (fullDateTimePattern == null) - { - fullDateTimePattern = LongDatePattern + " " + LongTimePattern; - } - return (fullDateTimePattern); - } - - set - { - if (IsReadOnly) - throw new InvalidOperationException(SR.InvalidOperation_ReadOnly); - if (value == null) - { - throw new ArgumentNullException(nameof(value), - SR.ArgumentNull_String); - } - Contract.EndContractBlock(); - fullDateTimePattern = value; - } - } - - - // For our "patterns" arrays we have 2 variables, a string and a string[] - // - // The string[] contains the list of patterns, EXCEPT the default may not be included. - // The string contains the default pattern. - // When we initially construct our string[], we set the string to string[0] - public String LongDatePattern - { - get - { - // Initialize our long date pattern from the 1st array value if not set - if (this.longDatePattern == null) - { - // Initialize our data - this.longDatePattern = this.UnclonedLongDatePatterns[0]; - } - - return this.longDatePattern; - } - - set - { - if (IsReadOnly) - throw new InvalidOperationException(SR.InvalidOperation_ReadOnly); - if (value == null) - { - throw new ArgumentNullException(nameof(value), - SR.ArgumentNull_String); - } - Contract.EndContractBlock(); - - // Remember the new string - this.longDatePattern = value; - - // Clear the token hash table - ClearTokenHashTable(); - - // Clean up cached values that will be affected by this property. - this.fullDateTimePattern = null; - } - } - - // For our "patterns" arrays we have 2 variables, a string and a string[] - // - // The string[] contains the list of patterns, EXCEPT the default may not be included. - // The string contains the default pattern. - // When we initially construct our string[], we set the string to string[0] - public String LongTimePattern - { - get - { - // Initialize our long time pattern from the 1st array value if not set - if (this.longTimePattern == null) - { - // Initialize our data - this.longTimePattern = this.UnclonedLongTimePatterns[0]; - } - - return this.longTimePattern; - } - - set - { - if (IsReadOnly) - throw new InvalidOperationException(SR.InvalidOperation_ReadOnly); - if (value == null) - { - throw new ArgumentNullException(nameof(value), - SR.ArgumentNull_String); - } - Contract.EndContractBlock(); - - // Remember the new string - this.longTimePattern = value; - - // Clear the token hash table - ClearTokenHashTable(); - - // Clean up cached values that will be affected by this property. - this.fullDateTimePattern = null; // Full date = long date + long Time - this.generalLongTimePattern = null; // General long date = short date + long Time - this.dateTimeOffsetPattern = null; - } - } - - - // Note: just to be confusing there's only 1 month day pattern, not a whole list - public String MonthDayPattern - { - get - { - if (this.monthDayPattern == null) - { - Debug.Assert(Calendar.ID > 0, "[DateTimeFormatInfo.MonthDayPattern] Expected calID > 0"); - this.monthDayPattern = _cultureData.MonthDay(Calendar.ID); - } - Debug.Assert(this.monthDayPattern != null, "DateTimeFormatInfo.MonthDayPattern, monthDayPattern != null"); - return (this.monthDayPattern); - } - - set - { - if (IsReadOnly) - throw new InvalidOperationException(SR.InvalidOperation_ReadOnly); - if (value == null) - { - throw new ArgumentNullException(nameof(value), - SR.ArgumentNull_String); - } - Contract.EndContractBlock(); - - this.monthDayPattern = value; - } - } - - - public String PMDesignator - { - get - { - if (this.pmDesignator == null) - { - this.pmDesignator = _cultureData.SPM2359; - } - Debug.Assert(this.pmDesignator != null, "DateTimeFormatInfo.PMDesignator, pmDesignator != null"); - return (this.pmDesignator); - } - - set - { - if (IsReadOnly) - throw new InvalidOperationException(SR.InvalidOperation_ReadOnly); - if (value == null) - { - throw new ArgumentNullException(nameof(value), - SR.ArgumentNull_String); - } - Contract.EndContractBlock(); - ClearTokenHashTable(); - - pmDesignator = value; - } - } - - - public String RFC1123Pattern - { - get - { - return (rfc1123Pattern); - } - } - - // For our "patterns" arrays we have 2 variables, a string and a string[] - // - // The string[] contains the list of patterns, EXCEPT the default may not be included. - // The string contains the default pattern. - // When we initially construct our string[], we set the string to string[0] - public String ShortDatePattern - { - get - { - // Initialize our short date pattern from the 1st array value if not set - if (this.shortDatePattern == null) - { - // Initialize our data - this.shortDatePattern = this.UnclonedShortDatePatterns[0]; - } - - return this.shortDatePattern; - } - - set - { - if (IsReadOnly) - throw new InvalidOperationException(SR.InvalidOperation_ReadOnly); - if (value == null) - throw new ArgumentNullException(nameof(value), - SR.ArgumentNull_String); - Contract.EndContractBlock(); - - // Remember the new string - this.shortDatePattern = value; - - // Clear the token hash table, note that even short dates could require this - ClearTokenHashTable(); - - // Clean up cached values that will be affected by this property. - generalLongTimePattern = null; // General long time = short date + long time - generalShortTimePattern = null; // General short time = short date + short Time - dateTimeOffsetPattern = null; - } - } - - - // For our "patterns" arrays we have 2 variables, a string and a string[] - // - // The string[] contains the list of patterns, EXCEPT the default may not be included. - // The string contains the default pattern. - // When we initially construct our string[], we set the string to string[0] - public String ShortTimePattern - { - get - { - // Initialize our short time pattern from the 1st array value if not set - if (this.shortTimePattern == null) - { - // Initialize our data - this.shortTimePattern = this.UnclonedShortTimePatterns[0]; - } - return this.shortTimePattern; - } - - set - { - if (IsReadOnly) - throw new InvalidOperationException(SR.InvalidOperation_ReadOnly); - if (value == null) - { - throw new ArgumentNullException(nameof(value), - SR.ArgumentNull_String); - } - Contract.EndContractBlock(); - - // Remember the new string - this.shortTimePattern = value; - - // Clear the token hash table, note that even short times could require this - ClearTokenHashTable(); - - // Clean up cached values that will be affected by this property. - generalShortTimePattern = null; // General short date = short date + short time. - } - } - - - public String SortableDateTimePattern - { - get - { - return (sortableDateTimePattern); - } - } - - /*=================================GeneralShortTimePattern===================== - **Property: Return the pattern for 'g' general format: shortDate + short time - **Note: This is used by DateTimeFormat.cs to get the pattern for 'g' - ** We put this internal property here so that we can avoid doing the - ** concatation every time somebody asks for the general format. - ==============================================================================*/ - - internal String GeneralShortTimePattern - { - get - { - if (generalShortTimePattern == null) - { - generalShortTimePattern = ShortDatePattern + " " + ShortTimePattern; - } - return (generalShortTimePattern); - } - } - - /*=================================GeneralLongTimePattern===================== - **Property: Return the pattern for 'g' general format: shortDate + Long time - **Note: This is used by DateTimeFormat.cs to get the pattern for 'g' - ** We put this internal property here so that we can avoid doing the - ** concatation every time somebody asks for the general format. - ==============================================================================*/ - - internal String GeneralLongTimePattern - { - get - { - if (generalLongTimePattern == null) - { - generalLongTimePattern = ShortDatePattern + " " + LongTimePattern; - } - return (generalLongTimePattern); - } - } - - /*=================================DateTimeOffsetPattern========================== - **Property: Return the default pattern DateTimeOffset : shortDate + long time + time zone offset - **Note: This is used by DateTimeFormat.cs to get the pattern for short Date + long time + time zone offset - ** We put this internal property here so that we can avoid doing the - ** concatation every time somebody uses this form - ==============================================================================*/ - - /*=================================DateTimeOffsetPattern========================== - **Property: Return the default pattern DateTimeOffset : shortDate + long time + time zone offset - **Note: This is used by DateTimeFormat.cs to get the pattern for short Date + long time + time zone offset - ** We put this internal property here so that we can avoid doing the - ** concatation every time somebody uses this form - ==============================================================================*/ - - internal String DateTimeOffsetPattern - { - get - { - if (dateTimeOffsetPattern == null) - { - string dateTimePattern = ShortDatePattern + " " + LongTimePattern; - - /* LongTimePattern might contain a "z" as part of the format string in which case we don't want to append a time zone offset */ - - bool foundZ = false; - bool inQuote = false; - char quote = '\''; - for (int i = 0; !foundZ && i < LongTimePattern.Length; i++) - { - switch (LongTimePattern[i]) - { - case 'z': - /* if we aren't in a quote, we've found a z */ - foundZ = !inQuote; - /* we'll fall out of the loop now because the test includes !foundZ */ - break; - case '\'': - case '\"': - if (inQuote && (quote == LongTimePattern[i])) - { - /* we were in a quote and found a matching exit quote, so we are outside a quote now */ - inQuote = false; - } - else if (!inQuote) - { - quote = LongTimePattern[i]; - inQuote = true; - } - else - { - /* we were in a quote and saw the other type of quote character, so we are still in a quote */ - } - break; - case '%': - case '\\': - i++; /* skip next character that is escaped by this backslash */ - break; - default: - break; - } - } - - if (!foundZ) - { - dateTimePattern = dateTimePattern + " zzz"; - } - - dateTimeOffsetPattern = dateTimePattern; - } - return (dateTimeOffsetPattern); - } - } - - // Note that cultureData derives this from the long time format (unless someone's set this previously) - // Note that this property is quite undesirable. - public string TimeSeparator - { - get - { - if (timeSeparator == null) - { - timeSeparator = _cultureData.TimeSeparator; - } - Debug.Assert(this.timeSeparator != null, "DateTimeFormatInfo.TimeSeparator, timeSeparator != null"); - return (timeSeparator); - } - - set - { - if (IsReadOnly) - throw new InvalidOperationException(SR.InvalidOperation_ReadOnly); - - if (value == null) - { - throw new ArgumentNullException(nameof(value), SR.ArgumentNull_String); - } - - Contract.EndContractBlock(); - ClearTokenHashTable(); - - timeSeparator = value; - } - } - - public String UniversalSortableDateTimePattern - { - get - { - return (universalSortableDateTimePattern); - } - } - - // For our "patterns" arrays we have 2 variables, a string and a string[] - // - // The string[] contains the list of patterns, EXCEPT the default may not be included. - // The string contains the default pattern. - // When we initially construct our string[], we set the string to string[0] - public String YearMonthPattern - { - get - { - // Initialize our year/month pattern from the 1st array value if not set - if (this.yearMonthPattern == null) - { - // Initialize our data - this.yearMonthPattern = this.UnclonedYearMonthPatterns[0]; - } - return this.yearMonthPattern; - } - - set - { - if (IsReadOnly) - throw new InvalidOperationException(SR.InvalidOperation_ReadOnly); - if (value == null) - { - throw new ArgumentNullException(nameof(value), - SR.ArgumentNull_String); - } - Contract.EndContractBlock(); - - // Remember the new string - this.yearMonthPattern = value; - - // Clear the token hash table, note that even short times could require this - ClearTokenHashTable(); - } - } - - // - // Check if a string array contains a null value, and throw ArgumentNullException with parameter name "value" - // - private static void CheckNullValue(String[] values, int length) - { - Debug.Assert(values != null, "value != null"); - Debug.Assert(values.Length >= length); - for (int i = 0; i < length; i++) - { - if (values[i] == null) - { - throw new ArgumentNullException("value", - SR.ArgumentNull_ArrayValue); - } - } - } - - - public String[] AbbreviatedDayNames - { - get - { - return ((String[])internalGetAbbreviatedDayOfWeekNames().Clone()); - } - - set - { - if (IsReadOnly) - throw new InvalidOperationException(SR.InvalidOperation_ReadOnly); - if (value == null) - { - throw new ArgumentNullException(nameof(value), - SR.ArgumentNull_Array); - } - if (value.Length != 7) - { - throw new ArgumentException(SR.Format(SR.Argument_InvalidArrayLength, 7), nameof(value)); - } - Contract.EndContractBlock(); - CheckNullValue(value, value.Length); - ClearTokenHashTable(); - - abbreviatedDayNames = value; - } - } - - // Returns the string array of the one-letter day of week names. - public String[] ShortestDayNames - { - get - { - return ((String[])internalGetSuperShortDayNames().Clone()); - } - - set - { - if (IsReadOnly) - throw new InvalidOperationException(SR.InvalidOperation_ReadOnly); - if (value == null) - { - throw new ArgumentNullException(nameof(value), - SR.ArgumentNull_Array); - } - if (value.Length != 7) - { - throw new ArgumentException(SR.Format(SR.Argument_InvalidArrayLength, 7), nameof(value)); - } - Contract.EndContractBlock(); - CheckNullValue(value, value.Length); - this.m_superShortDayNames = value; - } - } - - - public String[] DayNames - { - get - { - return ((String[])internalGetDayOfWeekNames().Clone()); - } - - set - { - if (IsReadOnly) - throw new InvalidOperationException(SR.InvalidOperation_ReadOnly); - if (value == null) - { - throw new ArgumentNullException(nameof(value), - SR.ArgumentNull_Array); - } - if (value.Length != 7) - { - throw new ArgumentException(SR.Format(SR.Argument_InvalidArrayLength, 7), nameof(value)); - } - Contract.EndContractBlock(); - CheckNullValue(value, value.Length); - ClearTokenHashTable(); - - dayNames = value; - } - } - - - public String[] AbbreviatedMonthNames - { - get - { - return ((String[])internalGetAbbreviatedMonthNames().Clone()); - } - - set - { - if (IsReadOnly) - throw new InvalidOperationException(SR.InvalidOperation_ReadOnly); - if (value == null) - { - throw new ArgumentNullException(nameof(value), - SR.ArgumentNull_Array); - } - if (value.Length != 13) - { - throw new ArgumentException(SR.Format(SR.Argument_InvalidArrayLength, 13), nameof(value)); - } - Contract.EndContractBlock(); - CheckNullValue(value, value.Length - 1); - ClearTokenHashTable(); - abbreviatedMonthNames = value; - } - } - - - public String[] MonthNames - { - get - { - return ((String[])internalGetMonthNames().Clone()); - } - - set - { - if (IsReadOnly) - throw new InvalidOperationException(SR.InvalidOperation_ReadOnly); - if (value == null) - { - throw new ArgumentNullException(nameof(value), - SR.ArgumentNull_Array); - } - if (value.Length != 13) - { - throw new ArgumentException(SR.Format(SR.Argument_InvalidArrayLength, 13), nameof(value)); - } - Contract.EndContractBlock(); - CheckNullValue(value, value.Length - 1); - monthNames = value; - ClearTokenHashTable(); - } - } - - // Whitespaces that we allow in the month names. - // U+00a0 is non-breaking space. - private static readonly char[] s_monthSpaces = { ' ', '\u00a0' }; - - internal bool HasSpacesInMonthNames - { - get - { - return (FormatFlags & DateTimeFormatFlags.UseSpacesInMonthNames) != 0; - } - } - - internal bool HasSpacesInDayNames - { - get - { - return (FormatFlags & DateTimeFormatFlags.UseSpacesInDayNames) != 0; - } - } - - - // - // internalGetMonthName - // - // Actions: Return the month name using the specified MonthNameStyles in either abbreviated form - // or full form. - // Arguments: - // month - // style To indicate a form like regular/genitive/month name in a leap year. - // abbreviated When true, return abbreviated form. Otherwise, return a full form. - // Exceptions: - // ArgumentOutOfRangeException When month name is invalid. - // - internal String internalGetMonthName(int month, MonthNameStyles style, bool abbreviated) - { - // - // Right now, style is mutual exclusive, but I make the style to be flag so that - // maybe we can combine flag if there is such a need. - // - String[] monthNamesArray = null; - switch (style) - { - case MonthNameStyles.Genitive: - monthNamesArray = internalGetGenitiveMonthNames(abbreviated); - break; - case MonthNameStyles.LeapYear: - monthNamesArray = internalGetLeapYearMonthNames(/*abbreviated*/); - break; - default: - monthNamesArray = (abbreviated ? internalGetAbbreviatedMonthNames() : internalGetMonthNames()); - break; - } - // The month range is from 1 ~ this.m_monthNames.Length - // (actually is 13 right now for all cases) - if ((month < 1) || (month > monthNamesArray.Length)) - { - throw new ArgumentOutOfRangeException( - nameof(month), SR.Format(SR.ArgumentOutOfRange_Range, - 1, monthNamesArray.Length)); - } - return (monthNamesArray[month - 1]); - } - - // - // internalGetGenitiveMonthNames - // - // Action: Retrieve the array which contains the month names in genitive form. - // If this culture does not use the gentive form, the normal month name is returned. - // Arguments: - // abbreviated When true, return abbreviated form. Otherwise, return a full form. - // - private String[] internalGetGenitiveMonthNames(bool abbreviated) - { - if (abbreviated) - { - if (this.m_genitiveAbbreviatedMonthNames == null) - { - this.m_genitiveAbbreviatedMonthNames = _cultureData.AbbreviatedGenitiveMonthNames(this.Calendar.ID); - Debug.Assert(this.m_genitiveAbbreviatedMonthNames.Length == 13, - "[DateTimeFormatInfo.GetGenitiveMonthNames] Expected 13 abbreviated genitive month names in a year"); - } - return (this.m_genitiveAbbreviatedMonthNames); - } - - if (this.genitiveMonthNames == null) - { - this.genitiveMonthNames = _cultureData.GenitiveMonthNames(this.Calendar.ID); - Debug.Assert(this.genitiveMonthNames.Length == 13, - "[DateTimeFormatInfo.GetGenitiveMonthNames] Expected 13 genitive month names in a year"); - } - return (this.genitiveMonthNames); - } - - // - // internalGetLeapYearMonthNames - // - // Actions: Retrieve the month names used in a leap year. - // If this culture does not have different month names in a leap year, the normal month name is returned. - // Agruments: None. (can use abbreviated later if needed) - // - internal String[] internalGetLeapYearMonthNames(/*bool abbreviated*/) - { - if (this.leapYearMonthNames == null) - { - Debug.Assert(Calendar.ID > 0, "[DateTimeFormatInfo.internalGetLeapYearMonthNames] Expected Calendar.ID > 0"); - this.leapYearMonthNames = _cultureData.LeapYearMonthNames(Calendar.ID); - Debug.Assert(this.leapYearMonthNames.Length == 13, - "[DateTimeFormatInfo.internalGetLeapYearMonthNames] Expepcted 13 leap year month names"); - } - return (leapYearMonthNames); - } - - - public String GetAbbreviatedDayName(DayOfWeek dayofweek) - { - if ((int)dayofweek < 0 || (int)dayofweek > 6) - { - throw new ArgumentOutOfRangeException( - nameof(dayofweek), SR.Format(SR.ArgumentOutOfRange_Range, - DayOfWeek.Sunday, DayOfWeek.Saturday)); - } - Contract.EndContractBlock(); - // - // Don't call the public property AbbreviatedDayNames here since a clone is needed in that - // property, so it will be slower. Instead, use GetAbbreviatedDayOfWeekNames() directly. - // - return (internalGetAbbreviatedDayOfWeekNames()[(int)dayofweek]); - } - - // Returns the super short day of week names for the specified day of week. - public string GetShortestDayName(DayOfWeek dayOfWeek) - { - if ((int)dayOfWeek < 0 || (int)dayOfWeek > 6) - { - throw new ArgumentOutOfRangeException( - nameof(dayOfWeek), SR.Format(SR.ArgumentOutOfRange_Range, - DayOfWeek.Sunday, DayOfWeek.Saturday)); - } - Contract.EndContractBlock(); - // - // Don't call the public property SuperShortDayNames here since a clone is needed in that - // property, so it will be slower. Instead, use internalGetSuperShortDayNames() directly. - // - return (internalGetSuperShortDayNames()[(int)dayOfWeek]); - } - - // Get all possible combination of inputs - private static String[] GetCombinedPatterns(String[] patterns1, String[] patterns2, String connectString) - { - Debug.Assert(patterns1 != null); - Debug.Assert(patterns2 != null); - - // Get array size - String[] result = new String[patterns1.Length * patterns2.Length]; - - // Counter of actual results - int k = 0; - for (int i = 0; i < patterns1.Length; i++) - { - for (int j = 0; j < patterns2.Length; j++) - { - // Can't combine if null or empty - result[k++] = patterns1[i] + connectString + patterns2[j]; - } - } - - // Return the combinations - return (result); - } - - public string[] GetAllDateTimePatterns() - { - List results = new List(DEFAULT_ALL_DATETIMES_SIZE); - - for (int i = 0; i < DateTimeFormat.allStandardFormats.Length; i++) - { - String[] strings = GetAllDateTimePatterns(DateTimeFormat.allStandardFormats[i]); - for (int j = 0; j < strings.Length; j++) - { - results.Add(strings[j]); - } - } - return results.ToArray(); - } - - public string[] GetAllDateTimePatterns(char format) - { - Contract.Ensures(Contract.Result() != null); - String[] result = null; - - switch (format) - { - case 'd': - result = this.AllShortDatePatterns; - break; - case 'D': - result = this.AllLongDatePatterns; - break; - case 'f': - result = GetCombinedPatterns(AllLongDatePatterns, AllShortTimePatterns, " "); - break; - case 'F': - case 'U': - result = GetCombinedPatterns(AllLongDatePatterns, AllLongTimePatterns, " "); - break; - case 'g': - result = GetCombinedPatterns(AllShortDatePatterns, AllShortTimePatterns, " "); - break; - case 'G': - result = GetCombinedPatterns(AllShortDatePatterns, AllLongTimePatterns, " "); - break; - case 'm': - case 'M': - result = new String[] { MonthDayPattern }; - break; - case 'o': - case 'O': - result = new String[] { RoundtripFormat }; - break; - case 'r': - case 'R': - result = new String[] { rfc1123Pattern }; - break; - case 's': - result = new String[] { sortableDateTimePattern }; - break; - case 't': - result = this.AllShortTimePatterns; - break; - case 'T': - result = this.AllLongTimePatterns; - break; - case 'u': - result = new String[] { UniversalSortableDateTimePattern }; - break; - case 'y': - case 'Y': - result = this.AllYearMonthPatterns; - break; - default: - throw new ArgumentException(SR.Format_BadFormatSpecifier, nameof(format)); - } - return (result); - } - - - public String GetDayName(DayOfWeek dayofweek) - { - if ((int)dayofweek < 0 || (int)dayofweek > 6) - { - throw new ArgumentOutOfRangeException( - nameof(dayofweek), SR.Format(SR.ArgumentOutOfRange_Range, - DayOfWeek.Sunday, DayOfWeek.Saturday)); - } - Contract.EndContractBlock(); - - // Use the internal one so that we don't clone the array unnecessarily - return (internalGetDayOfWeekNames()[(int)dayofweek]); - } - - - - public String GetAbbreviatedMonthName(int month) - { - if (month < 1 || month > 13) - { - throw new ArgumentOutOfRangeException( - nameof(month), SR.Format(SR.ArgumentOutOfRange_Range, - 1, 13)); - } - Contract.EndContractBlock(); - // Use the internal one so we don't clone the array unnecessarily - return (internalGetAbbreviatedMonthNames()[month - 1]); - } - - - public String GetMonthName(int month) - { - if (month < 1 || month > 13) - { - throw new ArgumentOutOfRangeException( - nameof(month), SR.Format(SR.ArgumentOutOfRange_Range, - 1, 13)); - } - Contract.EndContractBlock(); - // Use the internal one so we don't clone the array unnecessarily - return (internalGetMonthNames()[month - 1]); - } - - // For our "patterns" arrays we have 2 variables, a string and a string[] - // - // The string[] contains the list of patterns, EXCEPT the default may not be included. - // The string contains the default pattern. - // When we initially construct our string[], we set the string to string[0] - // - // The resulting [] can get returned to the calling app, so clone it. - private static string[] GetMergedPatterns(string[] patterns, string defaultPattern) - { - Debug.Assert(patterns != null && patterns.Length > 0, - "[DateTimeFormatInfo.GetMergedPatterns]Expected array of at least one pattern"); - Debug.Assert(defaultPattern != null, - "[DateTimeFormatInfo.GetMergedPatterns]Expected non null default string"); - - // If the default happens to be the first in the list just return (a cloned) copy - if (defaultPattern == patterns[0]) - { - return (string[])patterns.Clone(); - } - - // We either need a bigger list, or the pattern from the list. - int i; - for (i = 0; i < patterns.Length; i++) - { - // Stop if we found it - if (defaultPattern == patterns[i]) - break; - } - - // Either way we're going to need a new array - string[] newPatterns; - - // Did we find it - if (i < patterns.Length) - { - // Found it, output will be same size - newPatterns = (string[])patterns.Clone(); - - // Have to move [0] item to [i] so we can re-write default at [0] - // (remember defaultPattern == [i] so this is OK) - newPatterns[i] = newPatterns[0]; - } - else - { - // Not found, make room for it - newPatterns = new String[patterns.Length + 1]; - - // Copy existing array - Array.Copy(patterns, 0, newPatterns, 1, patterns.Length); - } - - // Remember the default - newPatterns[0] = defaultPattern; - - // Return the reconstructed list - return newPatterns; - } - - // Needed by DateTimeFormatInfo and DateTimeFormat - internal const String RoundtripFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss.fffffffK"; - internal const String RoundtripDateTimeUnfixed = "yyyy'-'MM'-'ddTHH':'mm':'ss zzz"; - - // Default string isn't necessarily in our string array, so get the - // merged patterns of both - private String[] AllYearMonthPatterns - { - get - { - return GetMergedPatterns(this.UnclonedYearMonthPatterns, this.YearMonthPattern); - } - } - - private String[] AllShortDatePatterns - { - get - { - return GetMergedPatterns(this.UnclonedShortDatePatterns, this.ShortDatePattern); - } - } - - private String[] AllShortTimePatterns - { - get - { - return GetMergedPatterns(this.UnclonedShortTimePatterns, this.ShortTimePattern); - } - } - - private String[] AllLongDatePatterns - { - get - { - return GetMergedPatterns(this.UnclonedLongDatePatterns, this.LongDatePattern); - } - } - - private String[] AllLongTimePatterns - { - get - { - return GetMergedPatterns(this.UnclonedLongTimePatterns, this.LongTimePattern); - } - } - - // NOTE: Clone this string array if you want to return it to user. Otherwise, you are returning a writable cache copy. - // This won't include default, call AllYearMonthPatterns - private String[] UnclonedYearMonthPatterns - { - get - { - if (this.allYearMonthPatterns == null) - { - Debug.Assert(Calendar.ID > 0, "[DateTimeFormatInfo.UnclonedYearMonthPatterns] Expected Calendar.ID > 0"); - this.allYearMonthPatterns = _cultureData.YearMonths(this.Calendar.ID); - Debug.Assert(this.allYearMonthPatterns.Length > 0, - "[DateTimeFormatInfo.UnclonedYearMonthPatterns] Expected some year month patterns"); - } - - return this.allYearMonthPatterns; - } - } - - - // NOTE: Clone this string array if you want to return it to user. Otherwise, you are returning a writable cache copy. - // This won't include default, call AllShortDatePatterns - private String[] UnclonedShortDatePatterns - { - get - { - if (allShortDatePatterns == null) - { - Debug.Assert(Calendar.ID > 0, "[DateTimeFormatInfo.UnclonedShortDatePatterns] Expected Calendar.ID > 0"); - this.allShortDatePatterns = _cultureData.ShortDates(this.Calendar.ID); - Debug.Assert(this.allShortDatePatterns.Length > 0, - "[DateTimeFormatInfo.UnclonedShortDatePatterns] Expected some short date patterns"); - } - - return this.allShortDatePatterns; - } - } - - // NOTE: Clone this string array if you want to return it to user. Otherwise, you are returning a writable cache copy. - // This won't include default, call AllLongDatePatterns - private String[] UnclonedLongDatePatterns - { - get - { - if (allLongDatePatterns == null) - { - Debug.Assert(Calendar.ID > 0, "[DateTimeFormatInfo.UnclonedLongDatePatterns] Expected Calendar.ID > 0"); - this.allLongDatePatterns = _cultureData.LongDates(this.Calendar.ID); - Debug.Assert(this.allLongDatePatterns.Length > 0, - "[DateTimeFormatInfo.UnclonedLongDatePatterns] Expected some long date patterns"); - } - - return this.allLongDatePatterns; - } - } - - // NOTE: Clone this string array if you want to return it to user. Otherwise, you are returning a writable cache copy. - // This won't include default, call AllShortTimePatterns - private String[] UnclonedShortTimePatterns - { - get - { - if (this.allShortTimePatterns == null) - { - this.allShortTimePatterns = _cultureData.ShortTimes; - Debug.Assert(this.allShortTimePatterns.Length > 0, - "[DateTimeFormatInfo.UnclonedShortTimePatterns] Expected some short time patterns"); - } - - return this.allShortTimePatterns; - } - } - - // NOTE: Clone this string array if you want to return it to user. Otherwise, you are returning a writable cache copy. - // This won't include default, call AllLongTimePatterns - private String[] UnclonedLongTimePatterns - { - get - { - if (this.allLongTimePatterns == null) - { - this.allLongTimePatterns = _cultureData.LongTimes; - Debug.Assert(this.allLongTimePatterns.Length > 0, - "[DateTimeFormatInfo.UnclonedLongTimePatterns] Expected some long time patterns"); - } - - return this.allLongTimePatterns; - } - } - - public static DateTimeFormatInfo ReadOnly(DateTimeFormatInfo dtfi) - { - if (dtfi == null) - { - throw new ArgumentNullException(nameof(dtfi), - SR.ArgumentNull_Obj); - } - Contract.EndContractBlock(); - if (dtfi.IsReadOnly) - { - return (dtfi); - } - DateTimeFormatInfo newInfo = (DateTimeFormatInfo)(dtfi.MemberwiseClone()); - // We can use the data member calendar in the setter, instead of the property Calendar, - // since the cloned copy should have the same state as the original copy. - newInfo.calendar = Calendar.ReadOnly(dtfi.Calendar); - newInfo._isReadOnly = true; - return (newInfo); - } - - public bool IsReadOnly - { - get - { - return (_isReadOnly); - } - } - - // Return the native name for the calendar in DTFI.Calendar. The native name is referred to - // the culture used to create the DTFI. E.g. in the following example, the native language is Japanese. - // DateTimeFormatInfo dtfi = new CultureInfo("ja-JP", false).DateTimeFormat.Calendar = new JapaneseCalendar(); - // String nativeName = dtfi.NativeCalendarName; // Get the Japanese name for the Japanese calendar. - // DateTimeFormatInfo dtfi = new CultureInfo("ja-JP", false).DateTimeFormat.Calendar = new GregorianCalendar(GregorianCalendarTypes.Localized); - // String nativeName = dtfi.NativeCalendarName; // Get the Japanese name for the Gregorian calendar. - public string NativeCalendarName - { - get - { - return _cultureData.CalendarName(Calendar.ID); - } - } - - // - // Used by custom cultures and others to set the list of available formats. Note that none of them are - // explicitly used unless someone calls GetAllDateTimePatterns and subsequently uses one of the items - // from the list. - // - // Most of the format characters that can be used in GetAllDateTimePatterns are - // not really needed since they are one of the following: - // - // r/R/s/u locale-independent constants -- cannot be changed! - // m/M/y/Y fields with a single string in them -- that can be set through props directly - // f/F/g/G/U derived fields based on combinations of various of the below formats - // - // NOTE: No special validation is done here beyond what is done when the actual respective fields - // are used (what would be the point of disallowing here what we allow in the appropriate property?) - // - // WARNING: If more validation is ever done in one place, it should be done in the other. - // - public void SetAllDateTimePatterns(String[] patterns, char format) - { - if (IsReadOnly) - throw new InvalidOperationException(SR.InvalidOperation_ReadOnly); - - if (patterns == null) - { - throw new ArgumentNullException(nameof(patterns), SR.ArgumentNull_Array); - } - - if (patterns.Length == 0) - { - throw new ArgumentException(SR.Arg_ArrayZeroError, nameof(patterns)); - } - - Contract.EndContractBlock(); - - for (int i=0; i Calendar.GetYear(Calendar.MaxSupportedDateTime)) - { - return false; - } - - // To handle leap months, the set of month names in the symbol table does not always correspond to the numbers. - // For non-leap years, month 7 (Adar Bet) is not present, so we need to make using this month invalid and - // shuffle the other months down. - if (parsedMonthName) - { - if (!Calendar.IsLeapYear(year)) - { - if (month >= 8) - { - month--; - } - else if (month == 7) - { - return false; - } - } - } - } - return true; - } - - // - // DateTimeFormatInfo tokenizer. This is used by DateTime.Parse() to break input string into tokens. - // - [NonSerialized] - private TokenHashValue[] _dtfiTokenHash; - - private const int TOKEN_HASH_SIZE = 199; - private const int SECOND_PRIME = 197; - private const String dateSeparatorOrTimeZoneOffset = "-"; - private const String invariantDateSeparator = "/"; - private const String invariantTimeSeparator = ":"; - - // - // Common Ignorable Symbols - // - internal const String IgnorablePeriod = "."; - internal const String IgnorableComma = ","; - - // - // Year/Month/Day suffixes - // - internal const String CJKYearSuff = "\u5e74"; - internal const String CJKMonthSuff = "\u6708"; - internal const String CJKDaySuff = "\u65e5"; - - internal const String KoreanYearSuff = "\ub144"; - internal const String KoreanMonthSuff = "\uc6d4"; - internal const String KoreanDaySuff = "\uc77c"; - - internal const String KoreanHourSuff = "\uc2dc"; - internal const String KoreanMinuteSuff = "\ubd84"; - internal const String KoreanSecondSuff = "\ucd08"; - - internal const String CJKHourSuff = "\u6642"; - internal const String ChineseHourSuff = "\u65f6"; - - internal const String CJKMinuteSuff = "\u5206"; - internal const String CJKSecondSuff = "\u79d2"; - - internal const String LocalTimeMark = "T"; - - internal const String GMTName = "GMT"; - internal const String ZuluName = "Z"; - - internal const String KoreanLangName = "ko"; - internal const String JapaneseLangName = "ja"; - internal const String EnglishLangName = "en"; - - private static volatile DateTimeFormatInfo s_jajpDTFI; - private static volatile DateTimeFormatInfo s_zhtwDTFI; - - // - // Create a Japanese DTFI which uses JapaneseCalendar. This is used to parse - // date string with Japanese era name correctly even when the supplied DTFI - // does not use Japanese calendar. - // The created instance is stored in global s_jajpDTFI. - // - internal static DateTimeFormatInfo GetJapaneseCalendarDTFI() - { - DateTimeFormatInfo temp = s_jajpDTFI; - if (temp == null) - { - temp = new CultureInfo("ja-JP", false).DateTimeFormat; - temp.Calendar = JapaneseCalendar.GetDefaultInstance(); - s_jajpDTFI = temp; - } - return (temp); - } - - // Create a Taiwan DTFI which uses TaiwanCalendar. This is used to parse - // date string with era name correctly even when the supplied DTFI - // does not use Taiwan calendar. - // The created instance is stored in global s_zhtwDTFI. - internal static DateTimeFormatInfo GetTaiwanCalendarDTFI() - { - DateTimeFormatInfo temp = s_zhtwDTFI; - if (temp == null) - { - temp = new CultureInfo("zh-TW", false).DateTimeFormat; - temp.Calendar = TaiwanCalendar.GetDefaultInstance(); - s_zhtwDTFI = temp; - } - return (temp); - } - - - // DTFI properties should call this when the setter are called. - private void ClearTokenHashTable() - { - _dtfiTokenHash = null; - formatFlags = DateTimeFormatFlags.NotInitialized; - } - - internal TokenHashValue[] CreateTokenHashTable() - { - TokenHashValue[] temp = _dtfiTokenHash; - if (temp == null) - { - temp = new TokenHashValue[TOKEN_HASH_SIZE]; - - bool koreanLanguage = LanguageName.Equals(KoreanLangName); - - string sep = this.TimeSeparator.Trim(); - if (IgnorableComma != sep) InsertHash(temp, IgnorableComma, TokenType.IgnorableSymbol, 0); - if (IgnorablePeriod != sep) InsertHash(temp, IgnorablePeriod, TokenType.IgnorableSymbol, 0); - - if (KoreanHourSuff != sep && CJKHourSuff != sep && ChineseHourSuff != sep) - { - // - // On the Macintosh, the default TimeSeparator is identical to the KoreanHourSuff, CJKHourSuff, or ChineseHourSuff for some cultures like - // ja-JP and ko-KR. In these cases having the same symbol inserted into the hash table with multiple TokenTypes causes undesirable - // DateTime.Parse behavior. For instance, the DateTimeFormatInfo.Tokenize() method might return SEP_DateOrOffset for KoreanHourSuff - // instead of SEP_HourSuff. - // - InsertHash(temp, this.TimeSeparator, TokenType.SEP_Time, 0); - } - - InsertHash(temp, this.AMDesignator, TokenType.SEP_Am | TokenType.Am, 0); - InsertHash(temp, this.PMDesignator, TokenType.SEP_Pm | TokenType.Pm, 1); - - // TODO: This ignores similar custom cultures - if (LanguageName.Equals("sq")) - { - // Albanian allows time formats like "12:00.PD" - InsertHash(temp, IgnorablePeriod + this.AMDesignator, TokenType.SEP_Am | TokenType.Am, 0); - InsertHash(temp, IgnorablePeriod + this.PMDesignator, TokenType.SEP_Pm | TokenType.Pm, 1); - } - - // CJK suffix - InsertHash(temp, CJKYearSuff, TokenType.SEP_YearSuff, 0); - InsertHash(temp, KoreanYearSuff, TokenType.SEP_YearSuff, 0); - InsertHash(temp, CJKMonthSuff, TokenType.SEP_MonthSuff, 0); - InsertHash(temp, KoreanMonthSuff, TokenType.SEP_MonthSuff, 0); - InsertHash(temp, CJKDaySuff, TokenType.SEP_DaySuff, 0); - InsertHash(temp, KoreanDaySuff, TokenType.SEP_DaySuff, 0); - - InsertHash(temp, CJKHourSuff, TokenType.SEP_HourSuff, 0); - InsertHash(temp, ChineseHourSuff, TokenType.SEP_HourSuff, 0); - InsertHash(temp, CJKMinuteSuff, TokenType.SEP_MinuteSuff, 0); - InsertHash(temp, CJKSecondSuff, TokenType.SEP_SecondSuff, 0); - - // TODO: This ignores other custom cultures that might want to do something similar - if (koreanLanguage) - { - // Korean suffix - InsertHash(temp, KoreanHourSuff, TokenType.SEP_HourSuff, 0); - InsertHash(temp, KoreanMinuteSuff, TokenType.SEP_MinuteSuff, 0); - InsertHash(temp, KoreanSecondSuff, TokenType.SEP_SecondSuff, 0); - } - - if (LanguageName.Equals("ky")) - { - // For some cultures, the date separator works more like a comma, being allowed before or after any date part - InsertHash(temp, dateSeparatorOrTimeZoneOffset, TokenType.IgnorableSymbol, 0); - } - else - { - InsertHash(temp, dateSeparatorOrTimeZoneOffset, TokenType.SEP_DateOrOffset, 0); - } - - String[] dateWords = null; - DateTimeFormatInfoScanner scanner = null; - - // We need to rescan the date words since we're always synthetic - scanner = new DateTimeFormatInfoScanner(); - m_dateWords = dateWords = scanner.GetDateWordsOfDTFI(this); - // Ensure the formatflags is initialized. - DateTimeFormatFlags flag = FormatFlags; - - // For some cultures, the date separator works more like a comma, being allowed before or after any date part. - // In these cultures, we do not use normal date separator since we disallow date separator after a date terminal state. - // This is determined in DateTimeFormatInfoScanner. Use this flag to determine if we should treat date separator as ignorable symbol. - bool useDateSepAsIgnorableSymbol = false; - - String monthPostfix = null; - if (dateWords != null) - { - // There are DateWords. It could be a real date word (such as "de"), or a monthPostfix. - // The monthPostfix starts with '\xfffe' (MonthPostfixChar), followed by the real monthPostfix. - for (int i = 0; i < dateWords.Length; i++) - { - switch (dateWords[i][0]) - { - // This is a month postfix - case DateTimeFormatInfoScanner.MonthPostfixChar: - // Get the real month postfix. - monthPostfix = dateWords[i].Substring(1); - // Add the month name + postfix into the token. - AddMonthNames(temp, monthPostfix); - break; - case DateTimeFormatInfoScanner.IgnorableSymbolChar: - String symbol = dateWords[i].Substring(1); - InsertHash(temp, symbol, TokenType.IgnorableSymbol, 0); - if (this.DateSeparator.Trim(null).Equals(symbol)) - { - // The date separator is the same as the ignorable symbol. - useDateSepAsIgnorableSymbol = true; - } - break; - default: - InsertHash(temp, dateWords[i], TokenType.DateWordToken, 0); - // TODO: This ignores similar custom cultures - if (LanguageName.Equals("eu")) - { - // Basque has date words with leading dots - InsertHash(temp, IgnorablePeriod + dateWords[i], TokenType.DateWordToken, 0); - } - break; - } - } - } - - if (!useDateSepAsIgnorableSymbol) - { - // Use the normal date separator. - InsertHash(temp, this.DateSeparator, TokenType.SEP_Date, 0); - } - // Add the regular month names. - AddMonthNames(temp, null); - - // Add the abbreviated month names. - for (int i = 1; i <= 13; i++) - { - InsertHash(temp, GetAbbreviatedMonthName(i), TokenType.MonthToken, i); - } - - - if ((FormatFlags & DateTimeFormatFlags.UseGenitiveMonth) != 0) - { - for (int i = 1; i <= 13; i++) - { - String str; - str = internalGetMonthName(i, MonthNameStyles.Genitive, false); - InsertHash(temp, str, TokenType.MonthToken, i); - } - } - - if ((FormatFlags & DateTimeFormatFlags.UseLeapYearMonth) != 0) - { - for (int i = 1; i <= 13; i++) - { - String str; - str = internalGetMonthName(i, MonthNameStyles.LeapYear, false); - InsertHash(temp, str, TokenType.MonthToken, i); - } - } - - for (int i = 0; i < 7; i++) - { - //String str = GetDayOfWeekNames()[i]; - // We have to call public methods here to work with inherited DTFI. - String str = GetDayName((DayOfWeek)i); - InsertHash(temp, str, TokenType.DayOfWeekToken, i); - - str = GetAbbreviatedDayName((DayOfWeek)i); - InsertHash(temp, str, TokenType.DayOfWeekToken, i); - } - - int[] eras = calendar.Eras; - for (int i = 1; i <= eras.Length; i++) - { - InsertHash(temp, GetEraName(i), TokenType.EraToken, i); - InsertHash(temp, GetAbbreviatedEraName(i), TokenType.EraToken, i); - } - - // TODO: This ignores other cultures that might want to do something similar - if (LanguageName.Equals(JapaneseLangName)) - { - // Japanese allows day of week forms like: "(Tue)" - for (int i = 0; i < 7; i++) - { - String specialDayOfWeek = "(" + GetAbbreviatedDayName((DayOfWeek)i) + ")"; - InsertHash(temp, specialDayOfWeek, TokenType.DayOfWeekToken, i); - } - if (this.Calendar.GetType() != typeof(JapaneseCalendar)) - { - // Special case for Japanese. If this is a Japanese DTFI, and the calendar is not Japanese calendar, - // we will check Japanese Era name as well when the calendar is Gregorian. - DateTimeFormatInfo jaDtfi = GetJapaneseCalendarDTFI(); - for (int i = 1; i <= jaDtfi.Calendar.Eras.Length; i++) - { - InsertHash(temp, jaDtfi.GetEraName(i), TokenType.JapaneseEraToken, i); - InsertHash(temp, jaDtfi.GetAbbreviatedEraName(i), TokenType.JapaneseEraToken, i); - // m_abbrevEnglishEraNames[0] contains the name for era 1, so the token value is i+1. - InsertHash(temp, jaDtfi.AbbreviatedEnglishEraNames[i - 1], TokenType.JapaneseEraToken, i); - } - } - } - // TODO: This prohibits similar custom cultures, but we hard coded the name - else if (CultureName.Equals("zh-TW")) - { - DateTimeFormatInfo twDtfi = GetTaiwanCalendarDTFI(); - for (int i = 1; i <= twDtfi.Calendar.Eras.Length; i++) - { - if (twDtfi.GetEraName(i).Length > 0) - { - InsertHash(temp, twDtfi.GetEraName(i), TokenType.TEraToken, i); - } - } - } - - InsertHash(temp, InvariantInfo.AMDesignator, TokenType.SEP_Am | TokenType.Am, 0); - InsertHash(temp, InvariantInfo.PMDesignator, TokenType.SEP_Pm | TokenType.Pm, 1); - - // Add invariant month names and day names. - for (int i = 1; i <= 12; i++) - { - String str; - // We have to call public methods here to work with inherited DTFI. - // Insert the month name first, so that they are at the front of abbrevaited - // month names. - str = InvariantInfo.GetMonthName(i); - InsertHash(temp, str, TokenType.MonthToken, i); - str = InvariantInfo.GetAbbreviatedMonthName(i); - InsertHash(temp, str, TokenType.MonthToken, i); - } - - for (int i = 0; i < 7; i++) - { - // We have to call public methods here to work with inherited DTFI. - String str = InvariantInfo.GetDayName((DayOfWeek)i); - InsertHash(temp, str, TokenType.DayOfWeekToken, i); - - str = InvariantInfo.GetAbbreviatedDayName((DayOfWeek)i); - InsertHash(temp, str, TokenType.DayOfWeekToken, i); - } - - for (int i = 0; i < AbbreviatedEnglishEraNames.Length; i++) - { - // m_abbrevEnglishEraNames[0] contains the name for era 1, so the token value is i+1. - InsertHash(temp, AbbreviatedEnglishEraNames[i], TokenType.EraToken, i + 1); - } - - InsertHash(temp, LocalTimeMark, TokenType.SEP_LocalTimeMark, 0); - InsertHash(temp, GMTName, TokenType.TimeZoneToken, 0); - InsertHash(temp, ZuluName, TokenType.TimeZoneToken, 0); - - InsertHash(temp, invariantDateSeparator, TokenType.SEP_Date, 0); - InsertHash(temp, invariantTimeSeparator, TokenType.SEP_Time, 0); - - _dtfiTokenHash = temp; - } - return (temp); - } - - private void AddMonthNames(TokenHashValue[] temp, String monthPostfix) - { - for (int i = 1; i <= 13; i++) - { - String str; - //str = internalGetMonthName(i, MonthNameStyles.Regular, false); - // We have to call public methods here to work with inherited DTFI. - // Insert the month name first, so that they are at the front of abbrevaited - // month names. - str = GetMonthName(i); - if (str.Length > 0) - { - if (monthPostfix != null) - { - // Insert the month name with the postfix first, so it can be matched first. - InsertHash(temp, str + monthPostfix, TokenType.MonthToken, i); - } - else - { - InsertHash(temp, str, TokenType.MonthToken, i); - } - } - str = GetAbbreviatedMonthName(i); - InsertHash(temp, str, TokenType.MonthToken, i); - } - } - - //////////////////////////////////////////////////////////////////////// - // - // Actions: - // Try to parse the current word to see if it is a Hebrew number. - // Tokens will be updated accordingly. - // This is called by the Lexer of DateTime.Parse(). - // - // Unlike most of the functions in this class, the return value indicates - // whether or not it started to parse. The badFormat parameter indicates - // if parsing began, but the format was bad. - // - //////////////////////////////////////////////////////////////////////// - - private static bool TryParseHebrewNumber( -#if CORECLR - ref __DTString str, -#else - ref FormatProvider.__DTString str, -#endif - out Boolean badFormat, - out int number) - { - number = -1; - badFormat = false; - - int i = str.Index; - if (!HebrewNumber.IsDigit(str.Value[i])) - { - // If the current character is not a Hebrew digit, just return false. - // There is no chance that we can parse a valid Hebrew number from here. - return (false); - } - // The current character is a Hebrew digit. Try to parse this word as a Hebrew number. - HebrewNumberParsingContext context = new HebrewNumberParsingContext(0); - HebrewNumberParsingState state; - - do - { - state = HebrewNumber.ParseByChar(str.Value[i++], ref context); - switch (state) - { - case HebrewNumberParsingState.InvalidHebrewNumber: // Not a valid Hebrew number. - case HebrewNumberParsingState.NotHebrewDigit: // The current character is not a Hebrew digit character. - // Break out so that we don't continue to try parse this as a Hebrew number. - return (false); - } - } while (i < str.Value.Length && (state != HebrewNumberParsingState.FoundEndOfHebrewNumber)); - - // When we are here, we are either at the end of the string, or we find a valid Hebrew number. - Debug.Assert(state == HebrewNumberParsingState.ContinueParsing || state == HebrewNumberParsingState.FoundEndOfHebrewNumber, - "Invalid returned state from HebrewNumber.ParseByChar()"); - - if (state != HebrewNumberParsingState.FoundEndOfHebrewNumber) - { - // We reach end of the string but we can't find a terminal state in parsing Hebrew number. - return (false); - } - - // We have found a valid Hebrew number. Update the index. - str.Advance(i - str.Index); - - // Get the final Hebrew number value from the HebrewNumberParsingContext. - number = context.result; - - return (true); - } - - private static bool IsHebrewChar(char ch) - { - return (ch >= '\x0590' && ch <= '\x05ff'); - } - - internal bool Tokenize(TokenType TokenMask, out TokenType tokenType, out int tokenValue, -#if CORECLR - ref __DTString str) -#else - ref FormatProvider.__DTString str) -#endif - - { - tokenType = TokenType.UnknownToken; - tokenValue = 0; - - TokenHashValue value; - Debug.Assert(str.Index < str.Value.Length, "DateTimeFormatInfo.Tokenize(): start < value.Length"); - - char ch = str.m_current; - bool isLetter = Char.IsLetter(ch); - if (isLetter) - { - ch = this.Culture.TextInfo.ToLower(ch); - if (IsHebrewChar(ch) && TokenMask == TokenType.RegularTokenMask) - { - bool badFormat; - if (TryParseHebrewNumber(ref str, out badFormat, out tokenValue)) - { - if (badFormat) - { - tokenType = TokenType.UnknownToken; - return (false); - } - // This is a Hebrew number. - // Do nothing here. TryParseHebrewNumber() will update token accordingly. - tokenType = TokenType.HebrewNumber; - return (true); - } - } - } - - - int hashcode = ch % TOKEN_HASH_SIZE; - int hashProbe = 1 + ch % SECOND_PRIME; - int remaining = str.len - str.Index; - int i = 0; - - TokenHashValue[] hashTable = _dtfiTokenHash; - if (hashTable == null) - { - hashTable = CreateTokenHashTable(); - } - do - { - value = hashTable[hashcode]; - if (value == null) - { - // Not found. - break; - } - // Check this value has the right category (regular token or separator token) that we are looking for. - if (((int)value.tokenType & (int)TokenMask) > 0 && value.tokenString.Length <= remaining) - { - bool compareStrings = true; - if (isLetter) - { - // If this token starts with a letter, make sure that we won't allow partial match. So you can't tokenize "MarchWed" separately. - // Also an optimization to avoid string comparison - int nextCharIndex = str.Index + value.tokenString.Length; - if (nextCharIndex > str.len) - { - compareStrings = false; - } - else if (nextCharIndex < str.len) - { - // Check word boundary. The next character should NOT be a letter. - char nextCh = str.Value[nextCharIndex]; - compareStrings = !(Char.IsLetter(nextCh)); - } - } - if (compareStrings && CompareStringIgnoreCaseOptimized(str.Value, str.Index, value.tokenString.Length, value.tokenString, 0, value.tokenString.Length)) - { - tokenType = value.tokenType & TokenMask; - tokenValue = value.tokenValue; - str.Advance(value.tokenString.Length); - return (true); - } - else if ((value.tokenType == TokenType.MonthToken && HasSpacesInMonthNames) || - (value.tokenType == TokenType.DayOfWeekToken && HasSpacesInDayNames)) - { - // For month or day token, we will match the names which have spaces. - int matchStrLen = 0; - if (str.MatchSpecifiedWords(value.tokenString, true, ref matchStrLen)) - { - tokenType = value.tokenType & TokenMask; - tokenValue = value.tokenValue; - str.Advance(matchStrLen); - return (true); - } - } - } - i++; - hashcode += hashProbe; - if (hashcode >= TOKEN_HASH_SIZE) hashcode -= TOKEN_HASH_SIZE; - } while (i < TOKEN_HASH_SIZE); - - return (false); - } - - private void InsertAtCurrentHashNode(TokenHashValue[] hashTable, String str, char ch, TokenType tokenType, int tokenValue, int pos, int hashcode, int hashProbe) - { - // Remember the current slot. - TokenHashValue previousNode = hashTable[hashcode]; - - //// Console.WriteLine(" Insert Key: {0} in {1}", str, slotToInsert); - // Insert the new node into the current slot. - hashTable[hashcode] = new TokenHashValue(str, tokenType, tokenValue); ; - - while (++pos < TOKEN_HASH_SIZE) - { - hashcode += hashProbe; - if (hashcode >= TOKEN_HASH_SIZE) hashcode -= TOKEN_HASH_SIZE; - // Remember this slot - TokenHashValue temp = hashTable[hashcode]; - - if (temp != null && this.Culture.TextInfo.ToLower(temp.tokenString[0]) != ch) - { - continue; - } - // Put the previous slot into this slot. - hashTable[hashcode] = previousNode; - //// Console.WriteLine(" Move {0} to slot {1}", previousNode.tokenString, hashcode); - if (temp == null) - { - // Done - return; - } - previousNode = temp; - }; - Debug.Assert(false, "The hashtable is full. This should not happen."); - } - - private void InsertHash(TokenHashValue[] hashTable, String str, TokenType tokenType, int tokenValue) - { - // The month of the 13th month is allowed to be null, so make sure that we ignore null value here. - if (str == null || str.Length == 0) - { - return; - } - TokenHashValue value; - int i = 0; - // If there is whitespace characters in the beginning and end of the string, trim them since whitespaces are skipped by - // DateTime.Parse(). - if (Char.IsWhiteSpace(str[0]) || Char.IsWhiteSpace(str[str.Length - 1])) - { - str = str.Trim(null); // Trim white space characters. - // Could have space for separators - if (str.Length == 0) - return; - } - char ch = this.Culture.TextInfo.ToLower(str[0]); - int hashcode = ch % TOKEN_HASH_SIZE; - int hashProbe = 1 + ch % SECOND_PRIME; - do - { - value = hashTable[hashcode]; - if (value == null) - { - //// Console.WriteLine(" Put Key: {0} in {1}", str, hashcode); - hashTable[hashcode] = new TokenHashValue(str, tokenType, tokenValue); - return; - } - else - { - // Collision happens. Find another slot. - if (str.Length >= value.tokenString.Length) - { - // If there are two tokens with the same prefix, we have to make sure that the longer token should be at the front of - // the shorter ones. - if (this.CompareStringIgnoreCaseOptimized(str, 0, value.tokenString.Length, value.tokenString, 0, value.tokenString.Length)) - { - if (str.Length > value.tokenString.Length) - { - // The str to be inserted has the same prefix as the current token, and str is longer. - // Insert str into this node, and shift every node behind it. - InsertAtCurrentHashNode(hashTable, str, ch, tokenType, tokenValue, i, hashcode, hashProbe); - return; - } - else - { - // Same token. If they have different types (regular token vs separator token). Add them. - // If we have the same regular token or separator token in the hash already, do NOT update the hash. - // Therefore, the order of inserting token is significant here regarding what tokenType will be kept in the hash. - - - // - // Check the current value of RegularToken (stored in the lower 8-bit of tokenType) , and insert the tokenType into the hash ONLY when we don't have a RegularToken yet. - // Also check the current value of SeparatorToken (stored in the upper 8-bit of token), and insert the tokenType into the hash ONLY when we don't have the SeparatorToken yet. - // - - int nTokenType = (int)tokenType; - int nCurrentTokenTypeInHash = (int)value.tokenType; - - // - // The folowing is the fix for the issue of throwing FormatException when "mar" is passed in string of the short date format dd/MMM/yyyy for es-MX - // - - if (((nCurrentTokenTypeInHash & (int)TokenType.RegularTokenMask) == 0) && ((nTokenType & (int)TokenType.RegularTokenMask) != 0) || - ((nCurrentTokenTypeInHash & (int)TokenType.SeparatorTokenMask) == 0) && ((nTokenType & (int)TokenType.SeparatorTokenMask) != 0)) - { - value.tokenType |= tokenType; - if (tokenValue != 0) - { - value.tokenValue = tokenValue; - } - } - // The token to be inserted is already in the table. Skip it. - return; - } - } - } - } - //// Console.WriteLine(" COLLISION. Old Key: {0}, New Key: {1}", hashTable[hashcode].tokenString, str); - i++; - hashcode += hashProbe; - if (hashcode >= TOKEN_HASH_SIZE) hashcode -= TOKEN_HASH_SIZE; - } while (i < TOKEN_HASH_SIZE); - Debug.Assert(false, "The hashtable is full. This should not happen."); - } - - private bool CompareStringIgnoreCaseOptimized(string string1, int offset1, int length1, string string2, int offset2, int length2) - { - // Optimize for one character cases which are common due to date and time separators (/ and :) - if (length1 == 1 && length2 == 1 && string1[offset1] == string2[offset2]) - { - return true; - } - - return (this.Culture.CompareInfo.Compare(string1, offset1, length1, string2, offset2, length2, CompareOptions.IgnoreCase) == 0); - } - - // class DateTimeFormatInfo - - internal class TokenHashValue - { - internal String tokenString; - internal TokenType tokenType; - internal int tokenValue; - - internal TokenHashValue(String tokenString, TokenType tokenType, int tokenValue) - { - this.tokenString = tokenString; - this.tokenType = tokenType; - this.tokenValue = tokenValue; - } - } - } - -#if !CORECLR - // - // The type of token that will be returned by DateTimeFormatInfo.Tokenize(). - // - internal enum TokenType - { - // The valid token should start from 1. - - // Regular tokens. The range is from 0x00 ~ 0xff. - NumberToken = 1, // The number. E.g. "12" - YearNumberToken = 2, // The number which is considered as year number, which has 3 or more digits. E.g. "2003" - Am = 3, // AM timemark. E.g. "AM" - Pm = 4, // PM timemark. E.g. "PM" - MonthToken = 5, // A word (or words) that represents a month name. E.g. "March" - EndOfString = 6, // End of string - DayOfWeekToken = 7, // A word (or words) that represents a day of week name. E.g. "Monday" or "Mon" - TimeZoneToken = 8, // A word that represents a timezone name. E.g. "GMT" - EraToken = 9, // A word that represents a era name. E.g. "A.D." - DateWordToken = 10, // A word that can appear in a DateTime string, but serves no parsing semantics. E.g. "de" in Spanish culture. - UnknownToken = 11, // An unknown word, which signals an error in parsing. - HebrewNumber = 12, // A number that is composed of Hebrew text. Hebrew calendar uses Hebrew digits for year values, month values, and day values. - JapaneseEraToken = 13, // Era name for JapaneseCalendar - TEraToken = 14, // Era name for TaiwanCalendar - IgnorableSymbol = 15, // A separator like "," that is equivalent to whitespace - - - // Separator tokens. - SEP_Unk = 0x100, // Unknown separator. - SEP_End = 0x200, // The end of the parsing string. - SEP_Space = 0x300, // Whitespace (including comma). - SEP_Am = 0x400, // AM timemark. E.g. "AM" - SEP_Pm = 0x500, // PM timemark. E.g. "PM" - SEP_Date = 0x600, // date separator. E.g. "/" - SEP_Time = 0x700, // time separator. E.g. ":" - SEP_YearSuff = 0x800, // Chinese/Japanese/Korean year suffix. - SEP_MonthSuff = 0x900, // Chinese/Japanese/Korean month suffix. - SEP_DaySuff = 0xa00, // Chinese/Japanese/Korean day suffix. - SEP_HourSuff = 0xb00, // Chinese/Japanese/Korean hour suffix. - SEP_MinuteSuff = 0xc00, // Chinese/Japanese/Korean minute suffix. - SEP_SecondSuff = 0xd00, // Chinese/Japanese/Korean second suffix. - SEP_LocalTimeMark = 0xe00, // 'T', used in ISO 8601 format. - SEP_DateOrOffset = 0xf00, // '-' which could be a date separator or start of a time zone offset - - RegularTokenMask = 0x00ff, - SeparatorTokenMask = 0xff00, - } -#endif - -} diff --git a/src/mscorlib/corefx/System/Globalization/DateTimeFormatInfoScanner.cs b/src/mscorlib/corefx/System/Globalization/DateTimeFormatInfoScanner.cs deleted file mode 100644 index ddf7d7e..0000000 --- a/src/mscorlib/corefx/System/Globalization/DateTimeFormatInfoScanner.cs +++ /dev/null @@ -1,742 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -//////////////////////////////////////////////////////////////////////////// -// -// DateTimeFormatInfoScanner -// -// Scan a specified DateTimeFormatInfo to search for data used in DateTime.Parse() -// -// The data includes: -// -// DateWords: such as "de" used in es-ES (Spanish) LongDatePattern. -// Postfix: such as "ta" used in fi-FI after the month name. -// -// This class is shared among mscorlib.dll and sysglobl.dll. -// Use conditional CULTURE_AND_REGIONINFO_BUILDER_ONLY to differentiate between -// methods for mscorlib.dll and sysglobl.dll. -// -//////////////////////////////////////////////////////////////////////////// - -using System; -using System.Globalization; -using System.Collections; -using System.Collections.Generic; -using System.Text; - -namespace System.Globalization -{ - -#if CORECLR - using StringStringDictionary = Dictionary; - using StringList = List; -#else - using StringStringDictionary = LowLevelDictionary; - using StringList = LowLevelList; -#endif - - // - // from LocaleEx.txt header - // - //; IFORMATFLAGS - //; Parsing/formatting flags. - internal enum FORMATFLAGS - { - None = 0x00000000, - UseGenitiveMonth = 0x00000001, - UseLeapYearMonth = 0x00000002, - UseSpacesInMonthNames = 0x00000004, - UseHebrewParsing = 0x00000008, - UseSpacesInDayNames = 0x00000010, // Has spaces or non-breaking space in the day names. - UseDigitPrefixInTokens = 0x00000020, // Has token starting with numbers. - } - - internal enum CalendarId : ushort - { - UNINITIALIZED_VALUE = 0, - GREGORIAN = 1, // Gregorian (localized) calendar - GREGORIAN_US = 2, // Gregorian (U.S.) calendar - JAPAN = 3, // Japanese Emperor Era calendar - /* SSS_WARNINGS_OFF */ - TAIWAN = 4, // Taiwan Era calendar /* SSS_WARNINGS_ON */ - KOREA = 5, // Korean Tangun Era calendar - HIJRI = 6, // Hijri (Arabic Lunar) calendar - THAI = 7, // Thai calendar - HEBREW = 8, // Hebrew (Lunar) calendar - GREGORIAN_ME_FRENCH = 9, // Gregorian Middle East French calendar - GREGORIAN_ARABIC = 10, // Gregorian Arabic calendar - GREGORIAN_XLIT_ENGLISH = 11, // Gregorian Transliterated English calendar - GREGORIAN_XLIT_FRENCH = 12, - // Note that all calendars after this point are MANAGED ONLY for now. - JULIAN = 13, - JAPANESELUNISOLAR = 14, - CHINESELUNISOLAR = 15, - SAKA = 16, // reserved to match Office but not implemented in our code - LUNAR_ETO_CHN = 17, // reserved to match Office but not implemented in our code - LUNAR_ETO_KOR = 18, // reserved to match Office but not implemented in our code - LUNAR_ETO_ROKUYOU = 19, // reserved to match Office but not implemented in our code - KOREANLUNISOLAR = 20, - TAIWANLUNISOLAR = 21, - PERSIAN = 22, - UMALQURA = 23, - LAST_CALENDAR = 23 // Last calendar ID - } - - internal class DateTimeFormatInfoScanner - { - // Special prefix-like flag char in DateWord array. - - // Use char in PUA area since we won't be using them in real data. - // The char used to tell a read date word or a month postfix. A month postfix - // is "ta" in the long date pattern like "d. MMMM'ta 'yyyy" for fi-FI. - // In this case, it will be stored as "\xfffeta" in the date word array. - internal const char MonthPostfixChar = '\xe000'; - - // Add ignorable symbol in a DateWord array. - - // hu-HU has: - // shrot date pattern: yyyy. MM. dd.;yyyy-MM-dd;yy-MM-dd - // long date pattern: yyyy. MMMM d. - // Here, "." is the date separator (derived from short date pattern). However, - // "." also appear at the end of long date pattern. In this case, we just - // "." as ignorable symbol so that the DateTime.Parse() state machine will not - // treat the additional date separator at the end of y,m,d pattern as an error - // condition. - internal const char IgnorableSymbolChar = '\xe001'; - - // Known CJK suffix - internal const String CJKYearSuff = "\u5e74"; - internal const String CJKMonthSuff = "\u6708"; - internal const String CJKDaySuff = "\u65e5"; - - internal const String KoreanYearSuff = "\ub144"; - internal const String KoreanMonthSuff = "\uc6d4"; - internal const String KoreanDaySuff = "\uc77c"; - - internal const String KoreanHourSuff = "\uc2dc"; - internal const String KoreanMinuteSuff = "\ubd84"; - internal const String KoreanSecondSuff = "\ucd08"; - - internal const String CJKHourSuff = "\u6642"; - internal const String ChineseHourSuff = "\u65f6"; - - internal const String CJKMinuteSuff = "\u5206"; - internal const String CJKSecondSuff = "\u79d2"; - - // The collection fo date words & postfix. - internal StringList m_dateWords = new StringList(); - // Hashtable for the known words. - private static volatile StringStringDictionary s_knownWords; - - static StringStringDictionary KnownWords - { - get - { - if (s_knownWords == null) - { - StringStringDictionary temp = new StringStringDictionary(); - // Add known words into the hash table. - - // Skip these special symbols. - temp.Add("/", String.Empty); - temp.Add("-", String.Empty); - temp.Add(".", String.Empty); - // Skip known CJK suffixes. - temp.Add(CJKYearSuff, String.Empty); - temp.Add(CJKMonthSuff, String.Empty); - temp.Add(CJKDaySuff, String.Empty); - temp.Add(KoreanYearSuff, String.Empty); - temp.Add(KoreanMonthSuff, String.Empty); - temp.Add(KoreanDaySuff, String.Empty); - temp.Add(KoreanHourSuff, String.Empty); - temp.Add(KoreanMinuteSuff, String.Empty); - temp.Add(KoreanSecondSuff, String.Empty); - temp.Add(CJKHourSuff, String.Empty); - temp.Add(ChineseHourSuff, String.Empty); - temp.Add(CJKMinuteSuff, String.Empty); - temp.Add(CJKSecondSuff, String.Empty); - - s_knownWords = temp; - } - return (s_knownWords); - } - } - - //////////////////////////////////////////////////////////////////////////// - // - // Parameters: - // pattern: The pattern to be scanned. - // currentIndex: the current index to start the scan. - // - // Returns: - // Return the index with the first character that is a letter, which will - // be the start of a date word. - // Note that the index can be pattern.Length if we reach the end of the string. - // - //////////////////////////////////////////////////////////////////////////// - internal static int SkipWhiteSpacesAndNonLetter(String pattern, int currentIndex) - { - while (currentIndex < pattern.Length) - { - char ch = pattern[currentIndex]; - if (ch == '\\') - { - // Escaped character. Look ahead one character. - currentIndex++; - if (currentIndex < pattern.Length) - { - ch = pattern[currentIndex]; - if (ch == '\'') - { - // Skip the leading single quote. We will - // stop at the first letter. - continue; - } - // Fall thru to check if this is a letter. - } - else - { - // End of string - break; - } - } - if (Char.IsLetter(ch) || ch == '\'' || ch == '.') - { - break; - } - // Skip the current char since it is not a letter. - currentIndex++; - } - return (currentIndex); - } - - //////////////////////////////////////////////////////////////////////////// - // - // A helper to add the found date word or month postfix into ArrayList for date words. - // - // Parameters: - // formatPostfix: What kind of postfix this is. - // Possible values: - // null: This is a regular date word - // "MMMM": month postfix - // word: The date word or postfix to be added. - // - //////////////////////////////////////////////////////////////////////////// - internal void AddDateWordOrPostfix(String formatPostfix, String str) - { - if (str.Length > 0) - { - // Some cultures use . like an abbreviation - if (str.Equals(".")) - { - AddIgnorableSymbols("."); - return; - } - String words; - if (KnownWords.TryGetValue(str, out words) == false) - { - if (m_dateWords == null) - { - m_dateWords = new StringList(); - } - if (formatPostfix == "MMMM") - { - // Add the word into the ArrayList as "\xfffe" + real month postfix. - String temp = MonthPostfixChar + str; - if (!m_dateWords.Contains(temp)) - { - m_dateWords.Add(temp); - } - } - else - { - if (!m_dateWords.Contains(str)) - { - m_dateWords.Add(str); - } - if (str[str.Length - 1] == '.') - { - // Old version ignore the trialing dot in the date words. Support this as well. - String strWithoutDot = str.Substring(0, str.Length - 1); - if (!m_dateWords.Contains(strWithoutDot)) - { - m_dateWords.Add(strWithoutDot); - } - } - } - } - } - } - - //////////////////////////////////////////////////////////////////////////// - // - // Scan the pattern from the specified index and add the date word/postfix - // when appropriate. - // - // Parameters: - // pattern: The pattern to be scanned. - // index: The starting index to be scanned. - // formatPostfix: The kind of postfix to be scanned. - // Possible values: - // null: This is a regular date word - // "MMMM": month postfix - // - // - //////////////////////////////////////////////////////////////////////////// - internal int AddDateWords(String pattern, int index, String formatPostfix) - { - // Skip any whitespaces so we will start from a letter. - int newIndex = SkipWhiteSpacesAndNonLetter(pattern, index); - if (newIndex != index && formatPostfix != null) - { - // There are whitespaces. This will not be a postfix. - formatPostfix = null; - } - index = newIndex; - - // This is the first char added into dateWord. - // Skip all non-letter character. We will add the first letter into DateWord. - StringBuilder dateWord = new StringBuilder(); - // We assume that date words should start with a letter. - // Skip anything until we see a letter. - - while (index < pattern.Length) - { - char ch = pattern[index]; - if (ch == '\'') - { - // We have seen the end of quote. Add the word if we do not see it before, - // and break the while loop. - AddDateWordOrPostfix(formatPostfix, dateWord.ToString()); - index++; - break; - } - else if (ch == '\\') - { - // - // Escaped character. Look ahead one character - // - - // Skip escaped backslash. - index++; - if (index < pattern.Length) - { - dateWord.Append(pattern[index]); - index++; - } - } - else if (Char.IsWhiteSpace(ch)) - { - // Found a whitespace. We have to add the current date word/postfix. - AddDateWordOrPostfix(formatPostfix, dateWord.ToString()); - if (formatPostfix != null) - { - // Done with postfix. The rest will be regular date word. - formatPostfix = null; - } - // Reset the dateWord. - dateWord.Length = 0; - index++; - } - else - { - dateWord.Append(ch); - index++; - } - } - return (index); - } - - //////////////////////////////////////////////////////////////////////////// - // - // A simple helper to find the repeat count for a specified char. - // - //////////////////////////////////////////////////////////////////////////// - internal static int ScanRepeatChar(String pattern, char ch, int index, out int count) - { - count = 1; - while (++index < pattern.Length && pattern[index] == ch) - { - count++; - } - // Return the updated position. - return (index); - } - - //////////////////////////////////////////////////////////////////////////// - // - // Add the text that is a date separator but is treated like ignroable symbol. - // E.g. - // hu-HU has: - // shrot date pattern: yyyy. MM. dd.;yyyy-MM-dd;yy-MM-dd - // long date pattern: yyyy. MMMM d. - // Here, "." is the date separator (derived from short date pattern). However, - // "." also appear at the end of long date pattern. In this case, we just - // "." as ignorable symbol so that the DateTime.Parse() state machine will not - // treat the additional date separator at the end of y,m,d pattern as an error - // condition. - // - //////////////////////////////////////////////////////////////////////////// - - internal void AddIgnorableSymbols(String text) - { - if (m_dateWords == null) - { - // Create the date word array. - m_dateWords = new StringList(); - } - // Add the ignorable symbol into the ArrayList. - String temp = IgnorableSymbolChar + text; - if (!m_dateWords.Contains(temp)) - { - m_dateWords.Add(temp); - } - } - - - // - // Flag used to trace the date patterns (yy/yyyyy/M/MM/MMM/MMM/d/dd) that we have seen. - // - private enum FoundDatePattern - { - None = 0x0000, - FoundYearPatternFlag = 0x0001, - FoundMonthPatternFlag = 0x0002, - FoundDayPatternFlag = 0x0004, - FoundYMDPatternFlag = 0x0007, // FoundYearPatternFlag | FoundMonthPatternFlag | FoundDayPatternFlag; - } - - // Check if we have found all of the year/month/day pattern. - private FoundDatePattern _ymdFlags = FoundDatePattern.None; - - - //////////////////////////////////////////////////////////////////////////// - // - // Given a date format pattern, scan for date word or postfix. - // - // A date word should be always put in a single quoted string. And it will - // start from a letter, so whitespace and symbols will be ignored before - // the first letter. - // - // Examples of date word: - // 'de' in es-SP: dddd, dd' de 'MMMM' de 'yyyy - // "\x0443." in bg-BG: dd.M.yyyy '\x0433.' - // - // Example of postfix: - // month postfix: - // "ta" in fi-FI: d. MMMM'ta 'yyyy - // Currently, only month postfix is supported. - // - // Usage: - // Always call this with Framework-style pattern, instead of Windows style pattern. - // Windows style pattern uses '' for single quote, while .NET uses \' - // - //////////////////////////////////////////////////////////////////////////// - internal void ScanDateWord(String pattern) - { - // Check if we have found all of the year/month/day pattern. - _ymdFlags = FoundDatePattern.None; - - int i = 0; - while (i < pattern.Length) - { - char ch = pattern[i]; - int chCount; - - switch (ch) - { - case '\'': - // Find a beginning quote. Search until the end quote. - i = AddDateWords(pattern, i + 1, null); - break; - case 'M': - i = ScanRepeatChar(pattern, 'M', i, out chCount); - if (chCount >= 4) - { - if (i < pattern.Length && pattern[i] == '\'') - { - i = AddDateWords(pattern, i + 1, "MMMM"); - } - } - _ymdFlags |= FoundDatePattern.FoundMonthPatternFlag; - break; - case 'y': - i = ScanRepeatChar(pattern, 'y', i, out chCount); - _ymdFlags |= FoundDatePattern.FoundYearPatternFlag; - break; - case 'd': - i = ScanRepeatChar(pattern, 'd', i, out chCount); - if (chCount <= 2) - { - // Only count "d" & "dd". - // ddd, dddd are day names. Do not count them. - _ymdFlags |= FoundDatePattern.FoundDayPatternFlag; - } - break; - case '\\': - // Found a escaped char not in a quoted string. Skip the current backslash - // and its next character. - i += 2; - break; - case '.': - if (_ymdFlags == FoundDatePattern.FoundYMDPatternFlag) - { - // If we find a dot immediately after the we have seen all of the y, m, d pattern. - // treat it as a ignroable symbol. Check for comments in AddIgnorableSymbols for - // more details. - AddIgnorableSymbols("."); - _ymdFlags = FoundDatePattern.None; - } - i++; - break; - default: - if (_ymdFlags == FoundDatePattern.FoundYMDPatternFlag && !Char.IsWhiteSpace(ch)) - { - // We are not seeing "." after YMD. Clear the flag. - _ymdFlags = FoundDatePattern.None; - } - // We are not in quote. Skip the current character. - i++; - break; - } - } - } - - //////////////////////////////////////////////////////////////////////////// - // - // Given a DTFI, get all of the date words from date patterns and time patterns. - // - //////////////////////////////////////////////////////////////////////////// - - internal String[] GetDateWordsOfDTFI(DateTimeFormatInfo dtfi) - { - // Enumarate all LongDatePatterns, and get the DateWords and scan for month postfix. - String[] datePatterns = dtfi.GetAllDateTimePatterns('D'); - int i; - - // Scan the long date patterns - for (i = 0; i < datePatterns.Length; i++) - { - ScanDateWord(datePatterns[i]); - } - - // Scan the short date patterns - datePatterns = dtfi.GetAllDateTimePatterns('d'); - for (i = 0; i < datePatterns.Length; i++) - { - ScanDateWord(datePatterns[i]); - } - // Scan the YearMonth patterns. - datePatterns = dtfi.GetAllDateTimePatterns('y'); - for (i = 0; i < datePatterns.Length; i++) - { - ScanDateWord(datePatterns[i]); - } - - // Scan the month/day pattern - ScanDateWord(dtfi.MonthDayPattern); - - // Scan the long time patterns. - datePatterns = dtfi.GetAllDateTimePatterns('T'); - for (i = 0; i < datePatterns.Length; i++) - { - ScanDateWord(datePatterns[i]); - } - - // Scan the short time patterns. - datePatterns = dtfi.GetAllDateTimePatterns('t'); - for (i = 0; i < datePatterns.Length; i++) - { - ScanDateWord(datePatterns[i]); - } - - String[] result = null; - if (m_dateWords != null && m_dateWords.Count > 0) - { - result = new String[m_dateWords.Count]; - for (i = 0; i < m_dateWords.Count; i++) - { - result[i] = m_dateWords[i]; - } - } - return (result); - } - - - //////////////////////////////////////////////////////////////////////////// - // - // Scan the month names to see if genitive month names are used, and return - // the format flag. - // - //////////////////////////////////////////////////////////////////////////// - internal static FORMATFLAGS GetFormatFlagGenitiveMonth(String[] monthNames, String[] genitveMonthNames, String[] abbrevMonthNames, String[] genetiveAbbrevMonthNames) - { - // If we have different names in regular and genitive month names, use genitive month flag. - return ((!EqualStringArrays(monthNames, genitveMonthNames) || !EqualStringArrays(abbrevMonthNames, genetiveAbbrevMonthNames)) - ? FORMATFLAGS.UseGenitiveMonth : 0); - } - - //////////////////////////////////////////////////////////////////////////// - // - // Scan the month names to see if spaces are used or start with a digit, and return the format flag - // - //////////////////////////////////////////////////////////////////////////// - internal static FORMATFLAGS GetFormatFlagUseSpaceInMonthNames(String[] monthNames, String[] genitveMonthNames, String[] abbrevMonthNames, String[] genetiveAbbrevMonthNames) - { - FORMATFLAGS formatFlags = 0; - formatFlags |= (ArrayElementsBeginWithDigit(monthNames) || - ArrayElementsBeginWithDigit(genitveMonthNames) || - ArrayElementsBeginWithDigit(abbrevMonthNames) || - ArrayElementsBeginWithDigit(genetiveAbbrevMonthNames) - ? FORMATFLAGS.UseDigitPrefixInTokens : 0); - - formatFlags |= (ArrayElementsHaveSpace(monthNames) || - ArrayElementsHaveSpace(genitveMonthNames) || - ArrayElementsHaveSpace(abbrevMonthNames) || - ArrayElementsHaveSpace(genetiveAbbrevMonthNames) - ? FORMATFLAGS.UseSpacesInMonthNames : 0); - return (formatFlags); - } - - //////////////////////////////////////////////////////////////////////////// - // - // Scan the day names and set the correct format flag. - // - //////////////////////////////////////////////////////////////////////////// - internal static FORMATFLAGS GetFormatFlagUseSpaceInDayNames(String[] dayNames, String[] abbrevDayNames) - { - return ((ArrayElementsHaveSpace(dayNames) || - ArrayElementsHaveSpace(abbrevDayNames)) - ? FORMATFLAGS.UseSpacesInDayNames : 0); - } - - //////////////////////////////////////////////////////////////////////////// - // - // Check the calendar to see if it is HebrewCalendar and set the Hebrew format flag if necessary. - // - //////////////////////////////////////////////////////////////////////////// - internal static FORMATFLAGS GetFormatFlagUseHebrewCalendar(int calID) - { - return (calID == (int)CalendarId.HEBREW ? - FORMATFLAGS.UseHebrewParsing | FORMATFLAGS.UseLeapYearMonth : 0); - } - - - //----------------------------------------------------------------------------- - // EqualStringArrays - // compares two string arrays and return true if all elements of the first - // array equals to all elmentsof the second array. - // otherwise it returns false. - //----------------------------------------------------------------------------- - - private static bool EqualStringArrays(string[] array1, string[] array2) - { - // Shortcut if they're the same array - if (array1 == array2) - { - return true; - } - - // This is effectively impossible - if (array1.Length != array2.Length) - { - return false; - } - - // Check each string - for (int i = 0; i < array1.Length; i++) - { - if (!array1[i].Equals(array2[i])) - { - return false; - } - } - - return true; - } - - //----------------------------------------------------------------------------- - // ArrayElementsHaveSpace - // It checks all input array elements if any of them has space character - // returns true if found space character in one of the array elements. - // otherwise returns false. - //----------------------------------------------------------------------------- - - private static bool ArrayElementsHaveSpace(string[] array) - { - for (int i = 0; i < array.Length; i++) - { - // it is faster to check for space character manually instead of calling IndexOf - // so we don't have to go to native code side. - for (int j = 0; j < array[i].Length; j++) - { - if (Char.IsWhiteSpace(array[i][j])) - { - return true; - } - } - } - - return false; - } - - - //////////////////////////////////////////////////////////////////////////// - // - // Check if any element of the array start with a digit. - // - //////////////////////////////////////////////////////////////////////////// - private static bool ArrayElementsBeginWithDigit(string[] array) - { - for (int i = 0; i < array.Length; i++) - { - // it is faster to check for space character manually instead of calling IndexOf - // so we don't have to go to native code side. - if (array[i].Length > 0 && - array[i][0] >= '0' && array[i][0] <= '9') - { - int index = 1; - while (index < array[i].Length && array[i][index] >= '0' && array[i][index] <= '9') - { - // Skip other digits. - index++; - } - if (index == array[i].Length) - { - return (false); - } - - if (index == array[i].Length - 1) - { - // Skip known CJK month suffix. - // CJK uses month name like "1\x6708", since \x6708 is a known month suffix, - // we don't need the UseDigitPrefixInTokens since it is slower. - switch (array[i][index]) - { - case '\x6708': // CJKMonthSuff - case '\xc6d4': // KoreanMonthSuff - return (false); - } - } - - if (index == array[i].Length - 4) - { - // Skip known CJK month suffix. - // Starting with Windows 8, the CJK months for some cultures looks like: "1' \x6708'" - // instead of just "1\x6708" - if (array[i][index] == '\'' && array[i][index + 1] == ' ' && - array[i][index + 2] == '\x6708' && array[i][index + 3] == '\'') - { - return (false); - } - } - return (true); - } - } - - return false; - } - } -} - diff --git a/src/mscorlib/corefx/System/Globalization/DayLightTime.cs b/src/mscorlib/corefx/System/Globalization/DayLightTime.cs deleted file mode 100644 index 6ec9d6a..0000000 --- a/src/mscorlib/corefx/System/Globalization/DayLightTime.cs +++ /dev/null @@ -1,53 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; - -namespace System.Globalization -{ - // This class represents a starting/ending time for a period of daylight saving time. - - [Serializable] - public class DaylightTime - { - private readonly DateTime _start; - private readonly DateTime _end; - private readonly TimeSpan _delta; - - private DaylightTime() - { - } - - public DaylightTime(DateTime start, DateTime end, TimeSpan delta) - { - _start = start; - _end = end; - _delta = delta; - } - - // The start date of a daylight saving period. - public DateTime Start => _start; - - // The end date of a daylight saving period. - public DateTime End => _end; - - // Delta to stardard offset in ticks. - public TimeSpan Delta => _delta; - } - - // Value type version of DaylightTime - internal struct DaylightTimeStruct - { - public DaylightTimeStruct(DateTime start, DateTime end, TimeSpan delta) - { - Start = start; - End = end; - Delta = delta; - } - - public readonly DateTime Start; - public readonly DateTime End; - public readonly TimeSpan Delta; - } -} diff --git a/src/mscorlib/corefx/System/Globalization/DigitShapes.cs b/src/mscorlib/corefx/System/Globalization/DigitShapes.cs deleted file mode 100644 index 0e4dcc8..0000000 --- a/src/mscorlib/corefx/System/Globalization/DigitShapes.cs +++ /dev/null @@ -1,18 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -// -// The enumeration constants used in NumberFormatInfo.DigitSubstitution. -// - -namespace System.Globalization -{ - [Serializable] - public enum DigitShapes : int - { - Context = 0x0000, // The shape depends on the previous text in the same output. - None = 0x0001, // Gives full Unicode compatibility. - NativeNational = 0x0002 // National shapes - } -} \ No newline at end of file diff --git a/src/mscorlib/corefx/System/Globalization/EastAsianLunisolarCalendar.cs b/src/mscorlib/corefx/System/Globalization/EastAsianLunisolarCalendar.cs deleted file mode 100644 index f82fad8..0000000 --- a/src/mscorlib/corefx/System/Globalization/EastAsianLunisolarCalendar.cs +++ /dev/null @@ -1,717 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.Diagnostics.Contracts; - -namespace System.Globalization -{ - //////////////////////////////////////////////////////////////////////////// - // - // Notes about EastAsianLunisolarCalendar - // - //////////////////////////////////////////////////////////////////////////// - - [Serializable] - public abstract class EastAsianLunisolarCalendar : Calendar - { - internal const int LeapMonth = 0; - internal const int Jan1Month = 1; - internal const int Jan1Date = 2; - internal const int nDaysPerMonth = 3; - - // # of days so far in the solar year - internal static readonly int[] DaysToMonth365 = - { - 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 - }; - - internal static readonly int[] DaysToMonth366 = - { - 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 - }; - - internal const int DatePartYear = 0; - internal const int DatePartDayOfYear = 1; - internal const int DatePartMonth = 2; - internal const int DatePartDay = 3; - - public override CalendarAlgorithmType AlgorithmType - { - get - { - return CalendarAlgorithmType.LunisolarCalendar; - } - } - - // Return the year number in the 60-year cycle. - // - - public virtual int GetSexagenaryYear(DateTime time) - { - CheckTicksRange(time.Ticks); - - int year = 0, month = 0, day = 0; - TimeToLunar(time, ref year, ref month, ref day); - - return ((year - 4) % 60) + 1; - } - - // Return the celestial year from the 60-year cycle. - // The returned value is from 1 ~ 10. - // - - public int GetCelestialStem(int sexagenaryYear) - { - if ((sexagenaryYear < 1) || (sexagenaryYear > 60)) - { - throw new ArgumentOutOfRangeException( - nameof(sexagenaryYear), - SR.Format(SR.ArgumentOutOfRange_Range, 1, 60)); - } - Contract.EndContractBlock(); - - return ((sexagenaryYear - 1) % 10) + 1; - } - - // Return the Terrestial Branch from the the 60-year cycle. - // The returned value is from 1 ~ 12. - // - - public int GetTerrestrialBranch(int sexagenaryYear) - { - if ((sexagenaryYear < 1) || (sexagenaryYear > 60)) - { - throw new ArgumentOutOfRangeException( - nameof(sexagenaryYear), - SR.Format(SR.ArgumentOutOfRange_Range, 1, 60)); - } - Contract.EndContractBlock(); - - return ((sexagenaryYear - 1) % 12) + 1; - } - - internal abstract int GetYearInfo(int LunarYear, int Index); - internal abstract int GetYear(int year, DateTime time); - internal abstract int GetGregorianYear(int year, int era); - - internal abstract int MinCalendarYear { get; } - internal abstract int MaxCalendarYear { get; } - internal abstract EraInfo[] CalEraInfo { get; } - internal abstract DateTime MinDate { get; } - internal abstract DateTime MaxDate { get; } - - internal const int MaxCalendarMonth = 13; - internal const int MaxCalendarDay = 30; - - internal int MinEraCalendarYear(int era) - { - EraInfo[] mEraInfo = CalEraInfo; - //ChineseLunisolarCalendar does not has m_EraInfo it is going to retuen null - if (mEraInfo == null) - { - return MinCalendarYear; - } - - if (era == Calendar.CurrentEra) - { - era = CurrentEraValue; - } - //era has to be in the supported range otherwise we will throw exception in CheckEraRange() - if (era == GetEra(MinDate)) - { - return (GetYear(MinCalendarYear, MinDate)); - } - - for (int i = 0; i < mEraInfo.Length; i++) - { - if (era == mEraInfo[i].era) - { - return (mEraInfo[i].minEraYear); - } - } - throw new ArgumentOutOfRangeException(nameof(era), SR.ArgumentOutOfRange_InvalidEraValue); - } - - internal int MaxEraCalendarYear(int era) - { - EraInfo[] mEraInfo = CalEraInfo; - //ChineseLunisolarCalendar does not has m_EraInfo it is going to retuen null - if (mEraInfo == null) - { - return MaxCalendarYear; - } - - if (era == Calendar.CurrentEra) - { - era = CurrentEraValue; - } - //era has to be in the supported range otherwise we will throw exception in CheckEraRange() - if (era == GetEra(MaxDate)) - { - return (GetYear(MaxCalendarYear, MaxDate)); - } - - for (int i = 0; i < mEraInfo.Length; i++) - { - if (era == mEraInfo[i].era) - { - return (mEraInfo[i].maxEraYear); - } - } - throw new ArgumentOutOfRangeException(nameof(era), SR.ArgumentOutOfRange_InvalidEraValue); - } - - internal EastAsianLunisolarCalendar() - { - } - - internal void CheckTicksRange(long ticks) - { - if (ticks < MinSupportedDateTime.Ticks || ticks > MaxSupportedDateTime.Ticks) - { - throw new ArgumentOutOfRangeException( - "time", - String.Format(CultureInfo.InvariantCulture, SR.ArgumentOutOfRange_CalendarRange, - MinSupportedDateTime, MaxSupportedDateTime)); - } - Contract.EndContractBlock(); - } - - internal void CheckEraRange(int era) - { - if (era == Calendar.CurrentEra) - { - era = CurrentEraValue; - } - - if ((era < GetEra(MinDate)) || (era > GetEra(MaxDate))) - { - throw new ArgumentOutOfRangeException(nameof(era), SR.ArgumentOutOfRange_InvalidEraValue); - } - } - - internal int CheckYearRange(int year, int era) - { - CheckEraRange(era); - year = GetGregorianYear(year, era); - - if ((year < MinCalendarYear) || (year > MaxCalendarYear)) - { - throw new ArgumentOutOfRangeException( - nameof(year), - SR.Format(SR.ArgumentOutOfRange_Range, MinEraCalendarYear(era), MaxEraCalendarYear(era))); - } - return year; - } - - internal int CheckYearMonthRange(int year, int month, int era) - { - year = CheckYearRange(year, era); - - if (month == 13) - { - //Reject if there is no leap month this year - if (GetYearInfo(year, LeapMonth) == 0) - throw new ArgumentOutOfRangeException(nameof(month), SR.ArgumentOutOfRange_Month); - } - - if (month < 1 || month > 13) - { - throw new ArgumentOutOfRangeException(nameof(month), SR.ArgumentOutOfRange_Month); - } - return year; - } - - internal int InternalGetDaysInMonth(int year, int month) - { - int nDays; - int mask; // mask for extracting bits - - mask = 0x8000; - // convert the lunar day into a lunar month/date - mask >>= (month - 1); - if ((GetYearInfo(year, nDaysPerMonth) & mask) == 0) - nDays = 29; - else - nDays = 30; - return nDays; - } - - // Returns the number of days in the month given by the year and - // month arguments. - // - - public override int GetDaysInMonth(int year, int month, int era) - { - year = CheckYearMonthRange(year, month, era); - return InternalGetDaysInMonth(year, month); - } - - private static int GregorianIsLeapYear(int y) - { - return ((((y) % 4) != 0) ? 0 : ((((y) % 100) != 0) ? 1 : ((((y) % 400) != 0) ? 0 : 1))); - } - - // Returns the date and time converted to a DateTime value. Throws an exception if the n-tuple is invalid. - // - - public override DateTime ToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era) - { - year = CheckYearMonthRange(year, month, era); - int daysInMonth = InternalGetDaysInMonth(year, month); - if (day < 1 || day > daysInMonth) - { - throw new ArgumentOutOfRangeException( - nameof(day), - SR.Format(SR.ArgumentOutOfRange_Day, daysInMonth, month)); - } - - int gy = 0; int gm = 0; int gd = 0; - - if (LunarToGregorian(year, month, day, ref gy, ref gm, ref gd)) - { - return new DateTime(gy, gm, gd, hour, minute, second, millisecond); - } - else - { - throw new ArgumentOutOfRangeException(null, SR.ArgumentOutOfRange_BadYearMonthDay); - } - } - - - // - // GregorianToLunar calculates lunar calendar info for the given gregorian year, month, date. - // The input date should be validated before calling this method. - // - internal void GregorianToLunar(int nSYear, int nSMonth, int nSDate, ref int nLYear, ref int nLMonth, ref int nLDate) - { - // unsigned int nLYear, nLMonth, nLDate; // lunar ymd - int nSolarDay; // day # in solar year - int nLunarDay; // day # in lunar year - int fLeap; // is it a solar leap year? - int LDpM; // lunar days/month bitfield - int mask; // mask for extracting bits - int nDays; // # days this lunar month - int nJan1Month, nJan1Date; - - // calc the solar day of year - fLeap = GregorianIsLeapYear(nSYear); - nSolarDay = (fLeap == 1) ? DaysToMonth366[nSMonth - 1] : DaysToMonth365[nSMonth - 1]; - nSolarDay += nSDate; - - // init lunar year info - nLunarDay = nSolarDay; - nLYear = nSYear; - if (nLYear == (MaxCalendarYear + 1)) - { - nLYear--; - nLunarDay += ((GregorianIsLeapYear(nLYear) == 1) ? 366 : 365); - nJan1Month = GetYearInfo(nLYear, Jan1Month); - nJan1Date = GetYearInfo(nLYear, Jan1Date); - } - else - { - nJan1Month = GetYearInfo(nLYear, Jan1Month); - nJan1Date = GetYearInfo(nLYear, Jan1Date); - - // check if this solar date is actually part of the previous - // lunar year - if ((nSMonth < nJan1Month) || - (nSMonth == nJan1Month && nSDate < nJan1Date)) - { - // the corresponding lunar day is actually part of the previous - // lunar year - nLYear--; - - // add a solar year to the lunar day # - nLunarDay += ((GregorianIsLeapYear(nLYear) == 1) ? 366 : 365); - - // update the new start of year - nJan1Month = GetYearInfo(nLYear, Jan1Month); - nJan1Date = GetYearInfo(nLYear, Jan1Date); - } - } - - // convert solar day into lunar day. - // subtract off the beginning part of the solar year which is not - // part of the lunar year. since this part is always in Jan or Feb, - // we don't need to handle Leap Year (LY only affects March - // and later). - nLunarDay -= DaysToMonth365[nJan1Month - 1]; - nLunarDay -= (nJan1Date - 1); - - // convert the lunar day into a lunar month/date - mask = 0x8000; - LDpM = GetYearInfo(nLYear, nDaysPerMonth); - nDays = ((LDpM & mask) != 0) ? 30 : 29; - nLMonth = 1; - while (nLunarDay > nDays) - { - nLunarDay -= nDays; - nLMonth++; - mask >>= 1; - nDays = ((LDpM & mask) != 0) ? 30 : 29; - } - nLDate = nLunarDay; - } - - /* - //Convert from Lunar to Gregorian - //Highly inefficient, but it works based on the forward conversion - */ - internal bool LunarToGregorian(int nLYear, int nLMonth, int nLDate, ref int nSolarYear, ref int nSolarMonth, ref int nSolarDay) - { - int numLunarDays; - - if (nLDate < 1 || nLDate > 30) - return false; - - numLunarDays = nLDate - 1; - - //Add previous months days to form the total num of days from the first of the month. - for (int i = 1; i < nLMonth; i++) - { - numLunarDays += InternalGetDaysInMonth(nLYear, i); - } - - //Get Gregorian First of year - int nJan1Month = GetYearInfo(nLYear, Jan1Month); - int nJan1Date = GetYearInfo(nLYear, Jan1Date); - - // calc the solar day of year of 1 Lunar day - int fLeap = GregorianIsLeapYear(nLYear); - int[] days = (fLeap == 1) ? DaysToMonth366 : DaysToMonth365; - - nSolarDay = nJan1Date; - - if (nJan1Month > 1) - nSolarDay += days[nJan1Month - 1]; - - // Add the actual lunar day to get the solar day we want - nSolarDay = nSolarDay + numLunarDays;// - 1; - - if (nSolarDay > (fLeap + 365)) - { - nSolarYear = nLYear + 1; - nSolarDay -= (fLeap + 365); - } - else - { - nSolarYear = nLYear; - } - - for (nSolarMonth = 1; nSolarMonth < 12; nSolarMonth++) - { - if (days[nSolarMonth] >= nSolarDay) - break; - } - - nSolarDay -= days[nSolarMonth - 1]; - return true; - } - - internal DateTime LunarToTime(DateTime time, int year, int month, int day) - { - int gy = 0; int gm = 0; int gd = 0; - LunarToGregorian(year, month, day, ref gy, ref gm, ref gd); - return (GregorianCalendar.GetDefaultInstance().ToDateTime(gy, gm, gd, time.Hour, time.Minute, time.Second, time.Millisecond)); - } - - internal void TimeToLunar(DateTime time, ref int year, ref int month, ref int day) - { - int gy = 0; int gm = 0; int gd = 0; - - Calendar Greg = GregorianCalendar.GetDefaultInstance(); - gy = Greg.GetYear(time); - gm = Greg.GetMonth(time); - gd = Greg.GetDayOfMonth(time); - - GregorianToLunar(gy, gm, gd, ref year, ref month, ref day); - } - - // Returns the DateTime resulting from adding the given number of - // months to the specified DateTime. The result is computed by incrementing - // (or decrementing) the year and month parts of the specified DateTime by - // value months, and, if required, adjusting the day part of the - // resulting date downwards to the last day of the resulting month in the - // resulting year. The time-of-day part of the result is the same as the - // time-of-day part of the specified DateTime. - // - - public override DateTime AddMonths(DateTime time, int months) - { - if (months < -120000 || months > 120000) - { - throw new ArgumentOutOfRangeException( - nameof(months), - SR.Format(SR.ArgumentOutOfRange_Range, -120000, 120000)); - } - Contract.EndContractBlock(); - - CheckTicksRange(time.Ticks); - - int y = 0; int m = 0; int d = 0; - TimeToLunar(time, ref y, ref m, ref d); - - int i = m + months; - if (i > 0) - { - int monthsInYear = InternalIsLeapYear(y) ? 13 : 12; - - while (i - monthsInYear > 0) - { - i -= monthsInYear; - y++; - monthsInYear = InternalIsLeapYear(y) ? 13 : 12; - } - m = i; - } - else - { - int monthsInYear; - while (i <= 0) - { - monthsInYear = InternalIsLeapYear(y - 1) ? 13 : 12; - i += monthsInYear; - y--; - } - m = i; - } - - int days = InternalGetDaysInMonth(y, m); - if (d > days) - { - d = days; - } - DateTime dt = LunarToTime(time, y, m, d); - - CheckAddResult(dt.Ticks, MinSupportedDateTime, MaxSupportedDateTime); - return (dt); - } - - - public override DateTime AddYears(DateTime time, int years) - { - CheckTicksRange(time.Ticks); - - int y = 0; int m = 0; int d = 0; - TimeToLunar(time, ref y, ref m, ref d); - - y += years; - - if (m == 13 && !InternalIsLeapYear(y)) - { - m = 12; - d = InternalGetDaysInMonth(y, m); - } - int DaysInMonths = InternalGetDaysInMonth(y, m); - if (d > DaysInMonths) - { - d = DaysInMonths; - } - - DateTime dt = LunarToTime(time, y, m, d); - CheckAddResult(dt.Ticks, MinSupportedDateTime, MaxSupportedDateTime); - return (dt); - } - - // Returns the day-of-year part of the specified DateTime. The returned value - // is an integer between 1 and [354|355 |383|384]. - // - - public override int GetDayOfYear(DateTime time) - { - CheckTicksRange(time.Ticks); - - int y = 0; int m = 0; int d = 0; - TimeToLunar(time, ref y, ref m, ref d); - - for (int i = 1; i < m; i++) - { - d = d + InternalGetDaysInMonth(y, i); - } - return d; - } - - // Returns the day-of-month part of the specified DateTime. The returned - // value is an integer between 1 and 29 or 30. - // - - public override int GetDayOfMonth(DateTime time) - { - CheckTicksRange(time.Ticks); - - int y = 0; int m = 0; int d = 0; - TimeToLunar(time, ref y, ref m, ref d); - - return d; - } - - // Returns the number of days in the year given by the year argument for the current era. - // - - public override int GetDaysInYear(int year, int era) - { - year = CheckYearRange(year, era); - - int Days = 0; - int monthsInYear = InternalIsLeapYear(year) ? 13 : 12; - - while (monthsInYear != 0) - Days += InternalGetDaysInMonth(year, monthsInYear--); - - return Days; - } - - // Returns the month part of the specified DateTime. The returned value is an - // integer between 1 and 13. - // - - public override int GetMonth(DateTime time) - { - CheckTicksRange(time.Ticks); - - int y = 0; int m = 0; int d = 0; - TimeToLunar(time, ref y, ref m, ref d); - - return m; - } - - // Returns the year part of the specified DateTime. The returned value is an - // integer between 1 and MaxCalendarYear. - // - - public override int GetYear(DateTime time) - { - CheckTicksRange(time.Ticks); - - int y = 0; int m = 0; int d = 0; - TimeToLunar(time, ref y, ref m, ref d); - - return GetYear(y, time); - } - - // Returns the day-of-week part of the specified DateTime. The returned value - // is an integer between 0 and 6, where 0 indicates Sunday, 1 indicates - // Monday, 2 indicates Tuesday, 3 indicates Wednesday, 4 indicates - // Thursday, 5 indicates Friday, and 6 indicates Saturday. - // - - public override DayOfWeek GetDayOfWeek(DateTime time) - { - CheckTicksRange(time.Ticks); - return ((DayOfWeek)((int)(time.Ticks / Calendar.TicksPerDay + 1) % 7)); - } - - // Returns the number of months in the specified year and era. - - public override int GetMonthsInYear(int year, int era) - { - year = CheckYearRange(year, era); - return (InternalIsLeapYear(year) ? 13 : 12); - } - - // Checks whether a given day in the specified era is a leap day. This method returns true if - // the date is a leap day, or false if not. - // - - public override bool IsLeapDay(int year, int month, int day, int era) - { - year = CheckYearMonthRange(year, month, era); - int daysInMonth = InternalGetDaysInMonth(year, month); - - if (day < 1 || day > daysInMonth) - { - throw new ArgumentOutOfRangeException( - nameof(day), - SR.Format(SR.ArgumentOutOfRange_Day, daysInMonth, month)); - } - int m = GetYearInfo(year, LeapMonth); - return ((m != 0) && (month == (m + 1))); - } - - // Checks whether a given month in the specified era is a leap month. This method returns true if - // month is a leap month, or false if not. - // - - public override bool IsLeapMonth(int year, int month, int era) - { - year = CheckYearMonthRange(year, month, era); - int m = GetYearInfo(year, LeapMonth); - return ((m != 0) && (month == (m + 1))); - } - - // Returns the leap month in a calendar year of the specified era. This method returns 0 - // if this this year is not a leap year. - // - - public override int GetLeapMonth(int year, int era) - { - year = CheckYearRange(year, era); - int month = GetYearInfo(year, LeapMonth); - if (month > 0) - { - return (month + 1); - } - return 0; - } - - internal bool InternalIsLeapYear(int year) - { - return (GetYearInfo(year, LeapMonth) != 0); - } - // Checks whether a given year in the specified era is a leap year. This method returns true if - // year is a leap year, or false if not. - // - - public override bool IsLeapYear(int year, int era) - { - year = CheckYearRange(year, era); - return InternalIsLeapYear(year); - } - - private const int DEFAULT_GREGORIAN_TWO_DIGIT_YEAR_MAX = 2029; - - - public override int TwoDigitYearMax - { - get - { - if (twoDigitYearMax == -1) - { - twoDigitYearMax = GetSystemTwoDigitYearSetting(BaseCalendarID, GetYear(new DateTime(DEFAULT_GREGORIAN_TWO_DIGIT_YEAR_MAX, 1, 1))); - } - return (twoDigitYearMax); - } - - set - { - VerifyWritable(); - if (value < 99 || value > MaxCalendarYear) - { - throw new ArgumentOutOfRangeException( - nameof(value), - SR.Format(SR.ArgumentOutOfRange_Range, 99, MaxCalendarYear)); - } - twoDigitYearMax = value; - } - } - - - public override int ToFourDigitYear(int year) - { - if (year < 0) - { - throw new ArgumentOutOfRangeException(nameof(year), - SR.ArgumentOutOfRange_NeedNonNegNum); - } - Contract.EndContractBlock(); - - year = base.ToFourDigitYear(year); - CheckYearRange(year, CurrentEra); - return (year); - } - } -} diff --git a/src/mscorlib/corefx/System/Globalization/GregorianCalendar.cs b/src/mscorlib/corefx/System/Globalization/GregorianCalendar.cs deleted file mode 100644 index be5b65b..0000000 --- a/src/mscorlib/corefx/System/Globalization/GregorianCalendar.cs +++ /dev/null @@ -1,666 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -// - -// - -using System; -using System.Globalization; -using System.Diagnostics.Contracts; -using System.Runtime.Serialization; -using System.Threading; - -namespace System.Globalization -{ - // This calendar recognizes two era values: - // 0 CurrentEra (AD) - // 1 BeforeCurrentEra (BC) - - [Serializable] - - public class GregorianCalendar : Calendar - { - /* - A.D. = anno Domini - */ - - public const int ADEra = 1; - - - internal const int DatePartYear = 0; - internal const int DatePartDayOfYear = 1; - internal const int DatePartMonth = 2; - internal const int DatePartDay = 3; - - // - // This is the max Gregorian year can be represented by DateTime class. The limitation - // is derived from DateTime class. - // - internal const int MaxYear = 9999; - - internal GregorianCalendarTypes m_type; - - internal static readonly int[] DaysToMonth365 = - { - 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 - }; - - internal static readonly int[] DaysToMonth366 = - { - 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 - }; - - private static volatile Calendar s_defaultInstance; - - [OnDeserialized] - private void OnDeserialized(StreamingContext ctx) - { - if (m_type < GregorianCalendarTypes.Localized || - m_type > GregorianCalendarTypes.TransliteratedFrench) - { - throw new SerializationException( - String.Format(CultureInfo.CurrentCulture, SR.Serialization_MemberOutOfRange, "type", "GregorianCalendar")); - } - } - - public override DateTime MinSupportedDateTime - { - get - { - return (DateTime.MinValue); - } - } - - public override DateTime MaxSupportedDateTime - { - get - { - return (DateTime.MaxValue); - } - } - - public override CalendarAlgorithmType AlgorithmType - { - get - { - return CalendarAlgorithmType.SolarCalendar; - } - } - - /*=================================GetDefaultInstance========================== - **Action: Internal method to provide a default intance of GregorianCalendar. Used by NLS+ implementation - ** and other calendars. - **Returns: - **Arguments: - **Exceptions: - ============================================================================*/ - - internal static Calendar GetDefaultInstance() - { - if (s_defaultInstance == null) - { - s_defaultInstance = new GregorianCalendar(); - } - return (s_defaultInstance); - } - - // Construct an instance of gregorian calendar. - - public GregorianCalendar() : - this(GregorianCalendarTypes.Localized) - { - } - - - public GregorianCalendar(GregorianCalendarTypes type) - { - if ((int)type < (int)GregorianCalendarTypes.Localized || (int)type > (int)GregorianCalendarTypes.TransliteratedFrench) - { - throw new ArgumentOutOfRangeException( - nameof(type), - SR.Format(SR.ArgumentOutOfRange_Range, - GregorianCalendarTypes.Localized, GregorianCalendarTypes.TransliteratedFrench)); - } - Contract.EndContractBlock(); - this.m_type = type; - } - - public virtual GregorianCalendarTypes CalendarType - { - get - { - return (m_type); - } - - set - { - VerifyWritable(); - - switch (value) - { - case GregorianCalendarTypes.Localized: - case GregorianCalendarTypes.USEnglish: - case GregorianCalendarTypes.MiddleEastFrench: - case GregorianCalendarTypes.Arabic: - case GregorianCalendarTypes.TransliteratedEnglish: - case GregorianCalendarTypes.TransliteratedFrench: - m_type = value; - break; - - default: - throw new ArgumentOutOfRangeException("m_type", SR.ArgumentOutOfRange_Enum); - } - } - } - - internal override CalendarId ID - { - get - { - // By returning different ID for different variations of GregorianCalendar, - // we can support the Transliterated Gregorian calendar. - // DateTimeFormatInfo will use this ID to get formatting information about - // the calendar. - return ((CalendarId)m_type); - } - } - - - // Returns a given date part of this DateTime. This method is used - // to compute the year, day-of-year, month, or day part. - internal virtual int GetDatePart(long ticks, int part) - { - // n = number of days since 1/1/0001 - int n = (int)(ticks / TicksPerDay); - // y400 = number of whole 400-year periods since 1/1/0001 - int y400 = n / DaysPer400Years; - // n = day number within 400-year period - n -= y400 * DaysPer400Years; - // y100 = number of whole 100-year periods within 400-year period - int y100 = n / DaysPer100Years; - // Last 100-year period has an extra day, so decrement result if 4 - if (y100 == 4) y100 = 3; - // n = day number within 100-year period - n -= y100 * DaysPer100Years; - // y4 = number of whole 4-year periods within 100-year period - int y4 = n / DaysPer4Years; - // n = day number within 4-year period - n -= y4 * DaysPer4Years; - // y1 = number of whole years within 4-year period - int y1 = n / DaysPerYear; - // Last year has an extra day, so decrement result if 4 - if (y1 == 4) y1 = 3; - // If year was requested, compute and return it - if (part == DatePartYear) - { - return (y400 * 400 + y100 * 100 + y4 * 4 + y1 + 1); - } - // n = day number within year - n -= y1 * DaysPerYear; - // If day-of-year was requested, return it - if (part == DatePartDayOfYear) - { - return (n + 1); - } - // Leap year calculation looks different from IsLeapYear since y1, y4, - // and y100 are relative to year 1, not year 0 - bool leapYear = (y1 == 3 && (y4 != 24 || y100 == 3)); - int[] days = leapYear ? DaysToMonth366 : DaysToMonth365; - // All months have less than 32 days, so n >> 5 is a good conservative - // estimate for the month - int m = (n >> 5) + 1; - // m = 1-based month number - while (n >= days[m]) m++; - // If month was requested, return it - if (part == DatePartMonth) return (m); - // Return 1-based day-of-month - return (n - days[m - 1] + 1); - } - - /*=================================GetAbsoluteDate========================== - **Action: Gets the absolute date for the given Gregorian date. The absolute date means - ** the number of days from January 1st, 1 A.D. - **Returns: the absolute date - **Arguments: - ** year the Gregorian year - ** month the Gregorian month - ** day the day - **Exceptions: - ** ArgumentOutOfRangException if year, month, day value is valid. - **Note: - ** This is an internal method used by DateToTicks() and the calculations of Hijri and Hebrew calendars. - ** Number of Days in Prior Years (both common and leap years) + - ** Number of Days in Prior Months of Current Year + - ** Number of Days in Current Month - ** - ============================================================================*/ - - internal static long GetAbsoluteDate(int year, int month, int day) - { - if (year >= 1 && year <= MaxYear && month >= 1 && month <= 12) - { - int[] days = ((year % 4 == 0 && (year % 100 != 0 || year % 400 == 0))) ? DaysToMonth366 : DaysToMonth365; - if (day >= 1 && (day <= days[month] - days[month - 1])) - { - int y = year - 1; - int absoluteDate = y * 365 + y / 4 - y / 100 + y / 400 + days[month - 1] + day - 1; - return (absoluteDate); - } - } - throw new ArgumentOutOfRangeException(null, SR.ArgumentOutOfRange_BadYearMonthDay); - } - - // Returns the tick count corresponding to the given year, month, and day. - // Will check the if the parameters are valid. - internal virtual long DateToTicks(int year, int month, int day) - { - return (GetAbsoluteDate(year, month, day) * TicksPerDay); - } - - // Returns the DateTime resulting from adding the given number of - // months to the specified DateTime. The result is computed by incrementing - // (or decrementing) the year and month parts of the specified DateTime by - // value months, and, if required, adjusting the day part of the - // resulting date downwards to the last day of the resulting month in the - // resulting year. The time-of-day part of the result is the same as the - // time-of-day part of the specified DateTime. - // - // In more precise terms, considering the specified DateTime to be of the - // form y / m / d + t, where y is the - // year, m is the month, d is the day, and t is the - // time-of-day, the result is y1 / m1 / d1 + t, - // where y1 and m1 are computed by adding value months - // to y and m, and d1 is the largest value less than - // or equal to d that denotes a valid day in month m1 of year - // y1. - // - - public override DateTime AddMonths(DateTime time, int months) - { - if (months < -120000 || months > 120000) - { - throw new ArgumentOutOfRangeException( - nameof(months), - String.Format( - CultureInfo.CurrentCulture, - SR.ArgumentOutOfRange_Range, - -120000, - 120000)); - } - Contract.EndContractBlock(); - int y = GetDatePart(time.Ticks, DatePartYear); - int m = GetDatePart(time.Ticks, DatePartMonth); - int d = GetDatePart(time.Ticks, DatePartDay); - int i = m - 1 + months; - if (i >= 0) - { - m = i % 12 + 1; - y = y + i / 12; - } - else - { - m = 12 + (i + 1) % 12; - y = y + (i - 11) / 12; - } - int[] daysArray = (y % 4 == 0 && (y % 100 != 0 || y % 400 == 0)) ? DaysToMonth366 : DaysToMonth365; - int days = (daysArray[m] - daysArray[m - 1]); - - if (d > days) - { - d = days; - } - long ticks = DateToTicks(y, m, d) + time.Ticks % TicksPerDay; - Calendar.CheckAddResult(ticks, MinSupportedDateTime, MaxSupportedDateTime); - - return (new DateTime(ticks)); - } - - - // Returns the DateTime resulting from adding the given number of - // years to the specified DateTime. The result is computed by incrementing - // (or decrementing) the year part of the specified DateTime by value - // years. If the month and day of the specified DateTime is 2/29, and if the - // resulting year is not a leap year, the month and day of the resulting - // DateTime becomes 2/28. Otherwise, the month, day, and time-of-day - // parts of the result are the same as those of the specified DateTime. - // - - public override DateTime AddYears(DateTime time, int years) - { - return (AddMonths(time, years * 12)); - } - - // Returns the day-of-month part of the specified DateTime. The returned - // value is an integer between 1 and 31. - // - - public override int GetDayOfMonth(DateTime time) - { - return (GetDatePart(time.Ticks, DatePartDay)); - } - - // Returns the day-of-week part of the specified DateTime. The returned value - // is an integer between 0 and 6, where 0 indicates Sunday, 1 indicates - // Monday, 2 indicates Tuesday, 3 indicates Wednesday, 4 indicates - // Thursday, 5 indicates Friday, and 6 indicates Saturday. - // - - public override DayOfWeek GetDayOfWeek(DateTime time) - { - return ((DayOfWeek)((int)(time.Ticks / TicksPerDay + 1) % 7)); - } - - // Returns the day-of-year part of the specified DateTime. The returned value - // is an integer between 1 and 366. - // - - public override int GetDayOfYear(DateTime time) - { - return (GetDatePart(time.Ticks, DatePartDayOfYear)); - } - - // Returns the number of days in the month given by the year and - // month arguments. - // - - public override int GetDaysInMonth(int year, int month, int era) - { - if (era == CurrentEra || era == ADEra) - { - if (year < 1 || year > MaxYear) - { - throw new ArgumentOutOfRangeException(nameof(year), SR.Format(SR.ArgumentOutOfRange_Range, - 1, MaxYear)); - } - if (month < 1 || month > 12) - { - throw new ArgumentOutOfRangeException(nameof(month), SR.ArgumentOutOfRange_Month); - } - int[] days = ((year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) ? DaysToMonth366 : DaysToMonth365); - return (days[month] - days[month - 1]); - } - throw new ArgumentOutOfRangeException(nameof(era), SR.ArgumentOutOfRange_InvalidEraValue); - } - - // Returns the number of days in the year given by the year argument for the current era. - // - - public override int GetDaysInYear(int year, int era) - { - if (era == CurrentEra || era == ADEra) - { - if (year >= 1 && year <= MaxYear) - { - return ((year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) ? 366 : 365); - } - throw new ArgumentOutOfRangeException( - nameof(year), - String.Format( - CultureInfo.CurrentCulture, - SR.ArgumentOutOfRange_Range, - 1, - MaxYear)); - } - throw new ArgumentOutOfRangeException(nameof(era), SR.ArgumentOutOfRange_InvalidEraValue); - } - - // Returns the era for the specified DateTime value. - - public override int GetEra(DateTime time) - { - return (ADEra); - } - - - public override int[] Eras - { - get - { - return (new int[] { ADEra }); - } - } - - - // Returns the month part of the specified DateTime. The returned value is an - // integer between 1 and 12. - // - - public override int GetMonth(DateTime time) - { - return (GetDatePart(time.Ticks, DatePartMonth)); - } - - // Returns the number of months in the specified year and era. - - public override int GetMonthsInYear(int year, int era) - { - if (era == CurrentEra || era == ADEra) - { - if (year >= 1 && year <= MaxYear) - { - return (12); - } - throw new ArgumentOutOfRangeException( - nameof(year), - String.Format( - CultureInfo.CurrentCulture, - SR.ArgumentOutOfRange_Range, - 1, - MaxYear)); - } - throw new ArgumentOutOfRangeException(nameof(era), SR.ArgumentOutOfRange_InvalidEraValue); - } - - // Returns the year part of the specified DateTime. The returned value is an - // integer between 1 and 9999. - // - - public override int GetYear(DateTime time) - { - return (GetDatePart(time.Ticks, DatePartYear)); - } - - // Checks whether a given day in the specified era is a leap day. This method returns true if - // the date is a leap day, or false if not. - // - - public override bool IsLeapDay(int year, int month, int day, int era) - { - if (month < 1 || month > 12) - { - throw new ArgumentOutOfRangeException(nameof(month), SR.Format(SR.ArgumentOutOfRange_Range, - 1, 12)); - } - Contract.EndContractBlock(); - - if (era != CurrentEra && era != ADEra) - { - throw new ArgumentOutOfRangeException(nameof(era), SR.ArgumentOutOfRange_InvalidEraValue); - } - if (year < 1 || year > MaxYear) - { - throw new ArgumentOutOfRangeException( - nameof(year), - SR.Format(SR.ArgumentOutOfRange_Range, 1, MaxYear)); - } - - if (day < 1 || day > GetDaysInMonth(year, month)) - { - throw new ArgumentOutOfRangeException(nameof(day), SR.Format(SR.ArgumentOutOfRange_Range, - 1, GetDaysInMonth(year, month))); - } - if (!IsLeapYear(year)) - { - return (false); - } - if (month == 2 && day == 29) - { - return (true); - } - return (false); - } - - // Returns the leap month in a calendar year of the specified era. This method returns 0 - // if this calendar does not have leap month, or this year is not a leap year. - // - - public override int GetLeapMonth(int year, int era) - { - if (era != CurrentEra && era != ADEra) - { - throw new ArgumentOutOfRangeException(nameof(era), SR.ArgumentOutOfRange_InvalidEraValue); - } - if (year < 1 || year > MaxYear) - { - throw new ArgumentOutOfRangeException( - nameof(year), - String.Format( - CultureInfo.CurrentCulture, - SR.ArgumentOutOfRange_Range, 1, MaxYear)); - } - Contract.EndContractBlock(); - return (0); - } - - // Checks whether a given month in the specified era is a leap month. This method returns true if - // month is a leap month, or false if not. - // - - public override bool IsLeapMonth(int year, int month, int era) - { - if (era != CurrentEra && era != ADEra) - { - throw new ArgumentOutOfRangeException(nameof(era), SR.ArgumentOutOfRange_InvalidEraValue); - } - - if (year < 1 || year > MaxYear) - { - throw new ArgumentOutOfRangeException( - nameof(year), - String.Format( - CultureInfo.CurrentCulture, - SR.ArgumentOutOfRange_Range, 1, MaxYear)); - } - - if (month < 1 || month > 12) - { - throw new ArgumentOutOfRangeException(nameof(month), SR.Format(SR.ArgumentOutOfRange_Range, - 1, 12)); - } - Contract.EndContractBlock(); - return (false); - } - - // Checks whether a given year in the specified era is a leap year. This method returns true if - // year is a leap year, or false if not. - // - - public override bool IsLeapYear(int year, int era) - { - if (era == CurrentEra || era == ADEra) - { - if (year >= 1 && year <= MaxYear) - { - return (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)); - } - - throw new ArgumentOutOfRangeException( - nameof(year), - String.Format( - CultureInfo.CurrentCulture, - SR.ArgumentOutOfRange_Range, 1, MaxYear)); - } - throw new ArgumentOutOfRangeException(nameof(era), SR.ArgumentOutOfRange_InvalidEraValue); - } - - // Returns the date and time converted to a DateTime value. Throws an exception if the n-tuple is invalid. - // - - public override DateTime ToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era) - { - if (era == CurrentEra || era == ADEra) - { - return new DateTime(year, month, day, hour, minute, second, millisecond); - } - throw new ArgumentOutOfRangeException(nameof(era), SR.ArgumentOutOfRange_InvalidEraValue); - } - - internal override Boolean TryToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era, out DateTime result) - { - if (era == CurrentEra || era == ADEra) - { - try - { - result = new DateTime(year, month, day, hour, minute, second, millisecond); - return true; - } - catch (ArgumentOutOfRangeException) - { - result = DateTime.Now; - return false; - } - catch (ArgumentException) - { - result = DateTime.Now; - return false; - } - } - result = DateTime.MinValue; - return false; - } - - private const int DEFAULT_TWO_DIGIT_YEAR_MAX = 2029; - - - public override int TwoDigitYearMax - { - get - { - if (twoDigitYearMax == -1) - { - twoDigitYearMax = GetSystemTwoDigitYearSetting(ID, DEFAULT_TWO_DIGIT_YEAR_MAX); - } - return (twoDigitYearMax); - } - - set - { - VerifyWritable(); - if (value < 99 || value > MaxYear) - { - throw new ArgumentOutOfRangeException( - "year", - String.Format( - CultureInfo.CurrentCulture, - SR.ArgumentOutOfRange_Range, - 99, - MaxYear)); - } - twoDigitYearMax = value; - } - } - - - public override int ToFourDigitYear(int year) - { - if (year < 0) - { - throw new ArgumentOutOfRangeException(nameof(year), - SR.ArgumentOutOfRange_NeedNonNegNum); - } - Contract.EndContractBlock(); - - if (year > MaxYear) - { - throw new ArgumentOutOfRangeException( - nameof(year), - String.Format( - CultureInfo.CurrentCulture, - SR.ArgumentOutOfRange_Range, 1, MaxYear)); - } - return (base.ToFourDigitYear(year)); - } - } -} diff --git a/src/mscorlib/corefx/System/Globalization/GregorianCalendarHelper.cs b/src/mscorlib/corefx/System/Globalization/GregorianCalendarHelper.cs deleted file mode 100644 index ee8ba13..0000000 --- a/src/mscorlib/corefx/System/Globalization/GregorianCalendarHelper.cs +++ /dev/null @@ -1,668 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.Diagnostics.Contracts; -using System.Runtime.Serialization; -using System.Threading; - -namespace System.Globalization -{ - // Gregorian Calendars use Era Info - [Serializable] - internal class EraInfo - { - internal int era; // The value of the era. - internal long ticks; // The time in ticks when the era starts - internal int yearOffset; // The offset to Gregorian year when the era starts. - // Gregorian Year = Era Year + yearOffset - // Era Year = Gregorian Year - yearOffset - internal int minEraYear; // Min year value in this era. Generally, this value is 1, but this may - // be affected by the DateTime.MinValue; - internal int maxEraYear; // Max year value in this era. (== the year length of the era + 1) - - [OptionalField(VersionAdded = 4)] - internal String eraName; // The era name - [OptionalField(VersionAdded = 4)] - internal String abbrevEraName; // Abbreviated Era Name - [OptionalField(VersionAdded = 4)] - internal String englishEraName; // English era name - - internal EraInfo(int era, int startYear, int startMonth, int startDay, int yearOffset, int minEraYear, int maxEraYear) - { - this.era = era; - this.yearOffset = yearOffset; - this.minEraYear = minEraYear; - this.maxEraYear = maxEraYear; - this.ticks = new DateTime(startYear, startMonth, startDay).Ticks; - } - - internal EraInfo(int era, int startYear, int startMonth, int startDay, int yearOffset, int minEraYear, int maxEraYear, - String eraName, String abbrevEraName, String englishEraName) - { - this.era = era; - this.yearOffset = yearOffset; - this.minEraYear = minEraYear; - this.maxEraYear = maxEraYear; - this.ticks = new DateTime(startYear, startMonth, startDay).Ticks; - this.eraName = eraName; - this.abbrevEraName = abbrevEraName; - this.englishEraName = englishEraName; - } - } - - // This calendar recognizes two era values: - // 0 CurrentEra (AD) - // 1 BeforeCurrentEra (BC) - [Serializable] - internal class GregorianCalendarHelper - { - // 1 tick = 100ns = 10E-7 second - // Number of ticks per time unit - internal const long TicksPerMillisecond = 10000; - internal const long TicksPerSecond = TicksPerMillisecond * 1000; - internal const long TicksPerMinute = TicksPerSecond * 60; - internal const long TicksPerHour = TicksPerMinute * 60; - internal const long TicksPerDay = TicksPerHour * 24; - - // Number of milliseconds per time unit - internal const int MillisPerSecond = 1000; - internal const int MillisPerMinute = MillisPerSecond * 60; - internal const int MillisPerHour = MillisPerMinute * 60; - internal const int MillisPerDay = MillisPerHour * 24; - - // Number of days in a non-leap year - internal const int DaysPerYear = 365; - // Number of days in 4 years - internal const int DaysPer4Years = DaysPerYear * 4 + 1; - // Number of days in 100 years - internal const int DaysPer100Years = DaysPer4Years * 25 - 1; - // Number of days in 400 years - internal const int DaysPer400Years = DaysPer100Years * 4 + 1; - - // Number of days from 1/1/0001 to 1/1/10000 - internal const int DaysTo10000 = DaysPer400Years * 25 - 366; - - internal const long MaxMillis = (long)DaysTo10000 * MillisPerDay; - - internal const int DatePartYear = 0; - internal const int DatePartDayOfYear = 1; - internal const int DatePartMonth = 2; - internal const int DatePartDay = 3; - - // - // This is the max Gregorian year can be represented by DateTime class. The limitation - // is derived from DateTime class. - // - internal int MaxYear - { - get - { - return (m_maxYear); - } - } - - internal static readonly int[] DaysToMonth365 = - { - 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 - }; - - internal static readonly int[] DaysToMonth366 = - { - 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 - }; - - [OptionalField(VersionAdded = 1)] - internal int m_maxYear = 9999; - [OptionalField(VersionAdded = 1)] - internal int m_minYear; - internal Calendar m_Cal; - - [OptionalField(VersionAdded = 1)] - internal EraInfo[] m_EraInfo; - [OptionalField(VersionAdded = 1)] - internal int[] m_eras = null; - - - // Construct an instance of gregorian calendar. - internal GregorianCalendarHelper(Calendar cal, EraInfo[] eraInfo) - { - m_Cal = cal; - m_EraInfo = eraInfo; - m_maxYear = m_EraInfo[0].maxEraYear; - m_minYear = m_EraInfo[0].minEraYear; ; - } - - /*=================================GetGregorianYear========================== - **Action: Get the Gregorian year value for the specified year in an era. - **Returns: The Gregorian year value. - **Arguments: - ** year the year value in Japanese calendar - ** era the Japanese emperor era value. - **Exceptions: - ** ArgumentOutOfRangeException if year value is invalid or era value is invalid. - ============================================================================*/ - - internal int GetGregorianYear(int year, int era) - { - if (year < 0) - { - throw new ArgumentOutOfRangeException(nameof(year), - SR.ArgumentOutOfRange_NeedNonNegNum); - } - Contract.EndContractBlock(); - - if (era == Calendar.CurrentEra) - { - era = m_Cal.CurrentEraValue; - } - - for (int i = 0; i < m_EraInfo.Length; i++) - { - if (era == m_EraInfo[i].era) - { - if (year < m_EraInfo[i].minEraYear || year > m_EraInfo[i].maxEraYear) - { - throw new ArgumentOutOfRangeException( - nameof(year), - String.Format( - CultureInfo.CurrentCulture, - SR.ArgumentOutOfRange_Range, - m_EraInfo[i].minEraYear, - m_EraInfo[i].maxEraYear)); - } - return (m_EraInfo[i].yearOffset + year); - } - } - throw new ArgumentOutOfRangeException(nameof(era), SR.ArgumentOutOfRange_InvalidEraValue); - } - - internal bool IsValidYear(int year, int era) - { - if (year < 0) - { - return false; - } - - if (era == Calendar.CurrentEra) - { - era = m_Cal.CurrentEraValue; - } - - for (int i = 0; i < m_EraInfo.Length; i++) - { - if (era == m_EraInfo[i].era) - { - if (year < m_EraInfo[i].minEraYear || year > m_EraInfo[i].maxEraYear) - { - return false; - } - return true; - } - } - return false; - } - - - // Returns a given date part of this DateTime. This method is used - // to compute the year, day-of-year, month, or day part. - internal virtual int GetDatePart(long ticks, int part) - { - CheckTicksRange(ticks); - // n = number of days since 1/1/0001 - int n = (int)(ticks / TicksPerDay); - // y400 = number of whole 400-year periods since 1/1/0001 - int y400 = n / DaysPer400Years; - // n = day number within 400-year period - n -= y400 * DaysPer400Years; - // y100 = number of whole 100-year periods within 400-year period - int y100 = n / DaysPer100Years; - // Last 100-year period has an extra day, so decrement result if 4 - if (y100 == 4) y100 = 3; - // n = day number within 100-year period - n -= y100 * DaysPer100Years; - // y4 = number of whole 4-year periods within 100-year period - int y4 = n / DaysPer4Years; - // n = day number within 4-year period - n -= y4 * DaysPer4Years; - // y1 = number of whole years within 4-year period - int y1 = n / DaysPerYear; - // Last year has an extra day, so decrement result if 4 - if (y1 == 4) y1 = 3; - // If year was requested, compute and return it - if (part == DatePartYear) - { - return (y400 * 400 + y100 * 100 + y4 * 4 + y1 + 1); - } - // n = day number within year - n -= y1 * DaysPerYear; - // If day-of-year was requested, return it - if (part == DatePartDayOfYear) - { - return (n + 1); - } - // Leap year calculation looks different from IsLeapYear since y1, y4, - // and y100 are relative to year 1, not year 0 - bool leapYear = (y1 == 3 && (y4 != 24 || y100 == 3)); - int[] days = leapYear ? DaysToMonth366 : DaysToMonth365; - // All months have less than 32 days, so n >> 5 is a good conservative - // estimate for the month - int m = (n >> 5) + 1; - // m = 1-based month number - while (n >= days[m]) m++; - // If month was requested, return it - if (part == DatePartMonth) return (m); - // Return 1-based day-of-month - return (n - days[m - 1] + 1); - } - - /*=================================GetAbsoluteDate========================== - **Action: Gets the absolute date for the given Gregorian date. The absolute date means - ** the number of days from January 1st, 1 A.D. - **Returns: the absolute date - **Arguments: - ** year the Gregorian year - ** month the Gregorian month - ** day the day - **Exceptions: - ** ArgumentOutOfRangException if year, month, day value is valid. - **Note: - ** This is an internal method used by DateToTicks() and the calculations of Hijri and Hebrew calendars. - ** Number of Days in Prior Years (both common and leap years) + - ** Number of Days in Prior Months of Current Year + - ** Number of Days in Current Month - ** - ============================================================================*/ - - internal static long GetAbsoluteDate(int year, int month, int day) - { - if (year >= 1 && year <= 9999 && month >= 1 && month <= 12) - { - int[] days = ((year % 4 == 0 && (year % 100 != 0 || year % 400 == 0))) ? DaysToMonth366 : DaysToMonth365; - if (day >= 1 && (day <= days[month] - days[month - 1])) - { - int y = year - 1; - int absoluteDate = y * 365 + y / 4 - y / 100 + y / 400 + days[month - 1] + day - 1; - return (absoluteDate); - } - } - throw new ArgumentOutOfRangeException(null, SR.ArgumentOutOfRange_BadYearMonthDay); - } - - // Returns the tick count corresponding to the given year, month, and day. - // Will check the if the parameters are valid. - internal static long DateToTicks(int year, int month, int day) - { - return (GetAbsoluteDate(year, month, day) * TicksPerDay); - } - - // Return the tick count corresponding to the given hour, minute, second. - // Will check the if the parameters are valid. - internal static long TimeToTicks(int hour, int minute, int second, int millisecond) - { - //TimeSpan.TimeToTicks is a family access function which does no error checking, so - //we need to put some error checking out here. - if (hour >= 0 && hour < 24 && minute >= 0 && minute < 60 && second >= 0 && second < 60) - { - if (millisecond < 0 || millisecond >= MillisPerSecond) - { - throw new ArgumentOutOfRangeException( - nameof(millisecond), - String.Format( - CultureInfo.CurrentCulture, - SR.ArgumentOutOfRange_Range, - 0, - MillisPerSecond - 1)); - } - return (InternalGloablizationHelper.TimeToTicks(hour, minute, second) + millisecond * TicksPerMillisecond); ; - } - throw new ArgumentOutOfRangeException(null, SR.ArgumentOutOfRange_BadHourMinuteSecond); - } - - - internal void CheckTicksRange(long ticks) - { - if (ticks < m_Cal.MinSupportedDateTime.Ticks || ticks > m_Cal.MaxSupportedDateTime.Ticks) - { - throw new ArgumentOutOfRangeException( - "time", - String.Format( - CultureInfo.InvariantCulture, - SR.ArgumentOutOfRange_CalendarRange, - m_Cal.MinSupportedDateTime, - m_Cal.MaxSupportedDateTime)); - } - Contract.EndContractBlock(); - } - - // Returns the DateTime resulting from adding the given number of - // months to the specified DateTime. The result is computed by incrementing - // (or decrementing) the year and month parts of the specified DateTime by - // value months, and, if required, adjusting the day part of the - // resulting date downwards to the last day of the resulting month in the - // resulting year. The time-of-day part of the result is the same as the - // time-of-day part of the specified DateTime. - // - // In more precise terms, considering the specified DateTime to be of the - // form y / m / d + t, where y is the - // year, m is the month, d is the day, and t is the - // time-of-day, the result is y1 / m1 / d1 + t, - // where y1 and m1 are computed by adding value months - // to y and m, and d1 is the largest value less than - // or equal to d that denotes a valid day in month m1 of year - // y1. - // - public DateTime AddMonths(DateTime time, int months) - { - if (months < -120000 || months > 120000) - { - throw new ArgumentOutOfRangeException( - nameof(months), - String.Format( - CultureInfo.CurrentCulture, - SR.ArgumentOutOfRange_Range, - -120000, - 120000)); - } - Contract.EndContractBlock(); - CheckTicksRange(time.Ticks); - - int y = GetDatePart(time.Ticks, DatePartYear); - int m = GetDatePart(time.Ticks, DatePartMonth); - int d = GetDatePart(time.Ticks, DatePartDay); - int i = m - 1 + months; - if (i >= 0) - { - m = i % 12 + 1; - y = y + i / 12; - } - else - { - m = 12 + (i + 1) % 12; - y = y + (i - 11) / 12; - } - int[] daysArray = (y % 4 == 0 && (y % 100 != 0 || y % 400 == 0)) ? DaysToMonth366 : DaysToMonth365; - int days = (daysArray[m] - daysArray[m - 1]); - - if (d > days) - { - d = days; - } - long ticks = DateToTicks(y, m, d) + (time.Ticks % TicksPerDay); - Calendar.CheckAddResult(ticks, m_Cal.MinSupportedDateTime, m_Cal.MaxSupportedDateTime); - return (new DateTime(ticks)); - } - - // Returns the DateTime resulting from adding the given number of - // years to the specified DateTime. The result is computed by incrementing - // (or decrementing) the year part of the specified DateTime by value - // years. If the month and day of the specified DateTime is 2/29, and if the - // resulting year is not a leap year, the month and day of the resulting - // DateTime becomes 2/28. Otherwise, the month, day, and time-of-day - // parts of the result are the same as those of the specified DateTime. - // - public DateTime AddYears(DateTime time, int years) - { - return (AddMonths(time, years * 12)); - } - - // Returns the day-of-month part of the specified DateTime. The returned - // value is an integer between 1 and 31. - // - public int GetDayOfMonth(DateTime time) - { - return (GetDatePart(time.Ticks, DatePartDay)); - } - - // Returns the day-of-week part of the specified DateTime. The returned value - // is an integer between 0 and 6, where 0 indicates Sunday, 1 indicates - // Monday, 2 indicates Tuesday, 3 indicates Wednesday, 4 indicates - // Thursday, 5 indicates Friday, and 6 indicates Saturday. - // - public DayOfWeek GetDayOfWeek(DateTime time) - { - CheckTicksRange(time.Ticks); - return ((DayOfWeek)((time.Ticks / TicksPerDay + 1) % 7)); - } - - // Returns the day-of-year part of the specified DateTime. The returned value - // is an integer between 1 and 366. - // - public int GetDayOfYear(DateTime time) - { - return (GetDatePart(time.Ticks, DatePartDayOfYear)); - } - - // Returns the number of days in the month given by the year and - // month arguments. - // - [Pure] - public int GetDaysInMonth(int year, int month, int era) - { - // - // Convert year/era value to Gregorain year value. - // - year = GetGregorianYear(year, era); - if (month < 1 || month > 12) - { - throw new ArgumentOutOfRangeException(nameof(month), SR.ArgumentOutOfRange_Month); - } - int[] days = ((year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) ? DaysToMonth366 : DaysToMonth365); - return (days[month] - days[month - 1]); - } - - // Returns the number of days in the year given by the year argument for the current era. - // - - public int GetDaysInYear(int year, int era) - { - // - // Convert year/era value to Gregorain year value. - // - year = GetGregorianYear(year, era); - return ((year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) ? 366 : 365); - } - - // Returns the era for the specified DateTime value. - public int GetEra(DateTime time) - { - long ticks = time.Ticks; - // The assumption here is that m_EraInfo is listed in reverse order. - for (int i = 0; i < m_EraInfo.Length; i++) - { - if (ticks >= m_EraInfo[i].ticks) - { - return (m_EraInfo[i].era); - } - } - throw new ArgumentOutOfRangeException(nameof(time), SR.ArgumentOutOfRange_Era); - } - - - public int[] Eras - { - get - { - if (m_eras == null) - { - m_eras = new int[m_EraInfo.Length]; - for (int i = 0; i < m_EraInfo.Length; i++) - { - m_eras[i] = m_EraInfo[i].era; - } - } - return ((int[])m_eras.Clone()); - } - } - - // Returns the month part of the specified DateTime. The returned value is an - // integer between 1 and 12. - // - public int GetMonth(DateTime time) - { - return (GetDatePart(time.Ticks, DatePartMonth)); - } - - // Returns the number of months in the specified year and era. - public int GetMonthsInYear(int year, int era) - { - year = GetGregorianYear(year, era); - return (12); - } - - // Returns the year part of the specified DateTime. The returned value is an - // integer between 1 and 9999. - // - public int GetYear(DateTime time) - { - long ticks = time.Ticks; - int year = GetDatePart(ticks, DatePartYear); - for (int i = 0; i < m_EraInfo.Length; i++) - { - if (ticks >= m_EraInfo[i].ticks) - { - return (year - m_EraInfo[i].yearOffset); - } - } - throw new ArgumentException(SR.Argument_NoEra); - } - - // Returns the year that match the specified Gregorian year. The returned value is an - // integer between 1 and 9999. - // - public int GetYear(int year, DateTime time) - { - long ticks = time.Ticks; - for (int i = 0; i < m_EraInfo.Length; i++) - { - // while calculating dates with JapaneseLuniSolarCalendar, we can run into cases right after the start of the era - // and still belong to the month which is started in previous era. Calculating equivalent calendar date will cause - // using the new era info which will have the year offset equal to the year we are calculating year = m_EraInfo[i].yearOffset - // which will end up with zero as calendar year. - // We should use the previous era info instead to get the right year number. Example of such date is Feb 2nd 1989 - if (ticks >= m_EraInfo[i].ticks && year > m_EraInfo[i].yearOffset) - { - return (year - m_EraInfo[i].yearOffset); - } - } - throw new ArgumentException(SR.Argument_NoEra); - } - - // Checks whether a given day in the specified era is a leap day. This method returns true if - // the date is a leap day, or false if not. - // - public bool IsLeapDay(int year, int month, int day, int era) - { - // year/month/era checking is done in GetDaysInMonth() - if (day < 1 || day > GetDaysInMonth(year, month, era)) - { - throw new ArgumentOutOfRangeException( - nameof(day), - String.Format( - CultureInfo.CurrentCulture, - SR.ArgumentOutOfRange_Range, - 1, - GetDaysInMonth(year, month, era))); - } - Contract.EndContractBlock(); - - if (!IsLeapYear(year, era)) - { - return (false); - } - - if (month == 2 && day == 29) - { - return (true); - } - - return (false); - } - - // Returns the leap month in a calendar year of the specified era. This method returns 0 - // if this calendar does not have leap month, or this year is not a leap year. - // - public int GetLeapMonth(int year, int era) - { - year = GetGregorianYear(year, era); - return (0); - } - - // Checks whether a given month in the specified era is a leap month. This method returns true if - // month is a leap month, or false if not. - // - public bool IsLeapMonth(int year, int month, int era) - { - year = GetGregorianYear(year, era); - if (month < 1 || month > 12) - { - throw new ArgumentOutOfRangeException( - nameof(month), - String.Format( - CultureInfo.CurrentCulture, - SR.ArgumentOutOfRange_Range, - 1, - 12)); - } - return (false); - } - - // Checks whether a given year in the specified era is a leap year. This method returns true if - // year is a leap year, or false if not. - // - public bool IsLeapYear(int year, int era) - { - year = GetGregorianYear(year, era); - return (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)); - } - - // Returns the date and time converted to a DateTime value. Throws an exception if the n-tuple is invalid. - // - public DateTime ToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era) - { - year = GetGregorianYear(year, era); - long ticks = DateToTicks(year, month, day) + TimeToTicks(hour, minute, second, millisecond); - CheckTicksRange(ticks); - return (new DateTime(ticks)); - } - - public virtual int GetWeekOfYear(DateTime time, CalendarWeekRule rule, DayOfWeek firstDayOfWeek) - { - CheckTicksRange(time.Ticks); - // Use GregorianCalendar to get around the problem that the implmentation in Calendar.GetWeekOfYear() - // can call GetYear() that exceeds the supported range of the Gregorian-based calendars. - return (GregorianCalendar.GetDefaultInstance().GetWeekOfYear(time, rule, firstDayOfWeek)); - } - - - public int ToFourDigitYear(int year, int twoDigitYearMax) - { - if (year < 0) - { - throw new ArgumentOutOfRangeException(nameof(year), - SR.ArgumentOutOfRange_NeedPosNum); - } - Contract.EndContractBlock(); - - if (year < 100) - { - int y = year % 100; - return ((twoDigitYearMax / 100 - (y > twoDigitYearMax % 100 ? 1 : 0)) * 100 + y); - } - - if (year < m_minYear || year > m_maxYear) - { - throw new ArgumentOutOfRangeException( - nameof(year), - String.Format( - CultureInfo.CurrentCulture, - SR.ArgumentOutOfRange_Range, m_minYear, m_maxYear)); - } - // If the year value is above 100, just return the year value. Don't have to do - // the TwoDigitYearMax comparison. - return (year); - } - } -} - diff --git a/src/mscorlib/corefx/System/Globalization/GregorianCalendarTypes.cs b/src/mscorlib/corefx/System/Globalization/GregorianCalendarTypes.cs deleted file mode 100644 index a14010f..0000000 --- a/src/mscorlib/corefx/System/Globalization/GregorianCalendarTypes.cs +++ /dev/null @@ -1,21 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; - -namespace System.Globalization -{ - // Note: The values of the members of this enum must match the coresponding values - // in the CalendarId enum (since we cast between GregorianCalendarTypes and CalendarId). - [Serializable] - public enum GregorianCalendarTypes - { - Localized = CalendarId.GREGORIAN, - USEnglish = CalendarId.GREGORIAN_US, - MiddleEastFrench = CalendarId.GREGORIAN_ME_FRENCH, - Arabic = CalendarId.GREGORIAN_ARABIC, - TransliteratedEnglish = CalendarId.GREGORIAN_XLIT_ENGLISH, - TransliteratedFrench = CalendarId.GREGORIAN_XLIT_FRENCH, - } -} diff --git a/src/mscorlib/corefx/System/Globalization/HebrewCalendar.cs b/src/mscorlib/corefx/System/Globalization/HebrewCalendar.cs deleted file mode 100644 index b4f54f8..0000000 --- a/src/mscorlib/corefx/System/Globalization/HebrewCalendar.cs +++ /dev/null @@ -1,1129 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System.Diagnostics; -using System.Diagnostics.Contracts; - -namespace System.Globalization -{ - //////////////////////////////////////////////////////////////////////////// - // - // Rules for the Hebrew calendar: - // - The Hebrew calendar is both a Lunar (months) and Solar (years) - // calendar, but allows for a week of seven days. - // - Days begin at sunset. - // - Leap Years occur in the 3, 6, 8, 11, 14, 17, & 19th years of a - // 19-year cycle. Year = leap iff ((7y+1) mod 19 < 7). - // - There are 12 months in a common year and 13 months in a leap year. - // - In a common year, the 6th month, Adar, has 29 days. In a leap - // year, the 6th month, Adar I, has 30 days and the leap month, - // Adar II, has 29 days. - // - Common years have 353-355 days. Leap years have 383-385 days. - // - The Hebrew new year (Rosh HaShanah) begins on the 1st of Tishri, - // the 7th month in the list below. - // - The new year may not begin on Sunday, Wednesday, or Friday. - // - If the new year would fall on a Tuesday and the conjunction of - // the following year were at midday or later, the new year is - // delayed until Thursday. - // - If the new year would fall on a Monday after a leap year, the - // new year is delayed until Tuesday. - // - The length of the 8th and 9th months vary from year to year, - // depending on the overall length of the year. - // - The length of a year is determined by the dates of the new - // years (Tishri 1) preceding and following the year in question. - // - The 2th month is long (30 days) if the year has 355 or 385 days. - // - The 3th month is short (29 days) if the year has 353 or 383 days. - // - The Hebrew months are: - // 1. Tishri (30 days) - // 2. Heshvan (29 or 30 days) - // 3. Kislev (29 or 30 days) - // 4. Teveth (29 days) - // 5. Shevat (30 days) - // 6. Adar I (30 days) - // 7. Adar {II} (29 days, this only exists if that year is a leap year) - // 8. Nisan (30 days) - // 9. Iyyar (29 days) - // 10. Sivan (30 days) - // 11. Tammuz (29 days) - // 12. Av (30 days) - // 13. Elul (29 days) - // - //////////////////////////////////////////////////////////////////////////// - /* - ** Calendar support range: - ** Calendar Minimum Maximum - ** ========== ========== ========== - ** Gregorian 1583/01/01 2239/09/29 - ** Hebrew 5343/04/07 5999/13/29 - */ - - // Includes CHebrew implemetation;i.e All the code necessary for converting - // Gregorian to Hebrew Lunar from 1583 to 2239. - - - [Serializable] - public class HebrewCalendar : Calendar - { - public static readonly int HebrewEra = 1; - - internal const int DatePartYear = 0; - internal const int DatePartDayOfYear = 1; - internal const int DatePartMonth = 2; - internal const int DatePartDay = 3; - internal const int DatePartDayOfWeek = 4; - - // - // Hebrew Translation Table. - // - // This table is used to get the following Hebrew calendar information for a - // given Gregorian year: - // 1. The day of the Hebrew month corresponding to Gregorian January 1st - // for a given Gregorian year. - // 2. The month of the Hebrew month corresponding to Gregorian January 1st - // for a given Gregorian year. - // The information is not directly in the table. Instead, the info is decoded - // by special values (numbers above 29 and below 1). - // 3. The type of the Hebrew year for a given Gregorian year. - // - - /* - More notes: - - This table includes 2 numbers for each year. - The offset into the table determines the year. (offset 0 is Gregorian year 1500) - 1st number determines the day of the Hebrew month coresponeds to January 1st. - 2nd number determines the type of the Hebrew year. (the type determines how - many days are there in the year.) - - normal years : 1 = 353 days 2 = 354 days 3 = 355 days. - Leap years : 4 = 383 5 384 6 = 385 days. - - A 99 means the year is not supported for translation. - for convenience the table was defined for 750 year, - but only 640 years are supported. (from 1583 to 2239) - the years before 1582 (starting of Georgian calander) - and after 2239, are filled with 99. - - Greogrian January 1st falls usually in Tevet (4th month). Tevet has always 29 days. - That's why, there no nead to specify the lunar month in the table. - There are exceptions, these are coded by giving numbers above 29 and below 1. - Actual decoding is takenig place whenever fetching information from the table. - The function for decoding is in GetLunarMonthDay(). - - Example: - The data for 2000 - 2005 A.D. is: - - 23,6,6,1,17,2,27,6,7,3, // 2000 - 2004 - - For year 2000, we know it has a Hebrew year type 6, which means it has 385 days. - And 1/1/2000 A.D. is Hebrew year 5760, 23rd day of 4th month. - */ - - // - // Jewish Era in use today is dated from the supposed year of the - // Creation with its beginning in 3761 B.C. - // - - // The Hebrew year of Gregorian 1st year AD. - // 0001/01/01 AD is Hebrew 3760/01/01 - private const int HebrewYearOf1AD = 3760; - - // The first Gregorian year in HebrewTable. - private const int FirstGregorianTableYear = 1583; // == Hebrew Year 5343 - // The last Gregorian year in HebrewTable. - private const int LastGregorianTableYear = 2239; // == Hebrew Year 5999 - private const int TABLESIZE = (LastGregorianTableYear - FirstGregorianTableYear); - - private const int MinHebrewYear = HebrewYearOf1AD + FirstGregorianTableYear; // == 5343 - private const int MaxHebrewYear = HebrewYearOf1AD + LastGregorianTableYear; // == 5999 - - private static readonly byte[] s_hebrewTable = { - 7,3,17,3, // 1583-1584 (Hebrew year: 5343 - 5344) - 0,4,11,2,21,6,1,3,13,2, // 1585-1589 - 25,4,5,3,16,2,27,6,9,1, // 1590-1594 - 20,2,0,6,11,3,23,4,4,2, // 1595-1599 - 14,3,27,4,8,2,18,3,28,6, // 1600 - 11,1,22,5,2,3,12,3,25,4, // 1605 - 6,2,16,3,26,6,8,2,20,1, // 1610 - 0,6,11,2,24,4,4,3,15,2, // 1615 - 25,6,8,1,19,2,29,6,9,3, // 1620 - 22,4,3,2,13,3,25,4,6,3, // 1625 - 17,2,27,6,7,3,19,2,31,4, // 1630 - 11,3,23,4,5,2,15,3,25,6, // 1635 - 6,2,19,1,29,6,10,2,22,4, // 1640 - 3,3,14,2,24,6,6,1,17,3, // 1645 - 28,5,8,3,20,1,32,5,12,3, // 1650 - 22,6,4,1,16,2,26,6,6,3, // 1655 - 17,2,0,4,10,3,22,4,3,2, // 1660 - 14,3,24,6,5,2,17,1,28,6, // 1665 - 9,2,19,3,31,4,13,2,23,6, // 1670 - 3,3,15,1,27,5,7,3,17,3, // 1675 - 29,4,11,2,21,6,3,1,14,2, // 1680 - 25,6,5,3,16,2,28,4,9,3, // 1685 - 20,2,0,6,12,1,23,6,4,2, // 1690 - 14,3,26,4,8,2,18,3,0,4, // 1695 - 10,3,21,5,1,3,13,1,24,5, // 1700 - 5,3,15,3,27,4,8,2,19,3, // 1705 - 29,6,10,2,22,4,3,3,14,2, // 1710 - 26,4,6,3,18,2,28,6,10,1, // 1715 - 20,6,2,2,12,3,24,4,5,2, // 1720 - 16,3,28,4,8,3,19,2,0,6, // 1725 - 12,1,23,5,3,3,14,3,26,4, // 1730 - 7,2,17,3,28,6,9,2,21,4, // 1735 - 1,3,13,2,25,4,5,3,16,2, // 1740 - 27,6,9,1,19,3,0,5,11,3, // 1745 - 23,4,4,2,14,3,25,6,7,1, // 1750 - 18,2,28,6,9,3,21,4,2,2, // 1755 - 12,3,25,4,6,2,16,3,26,6, // 1760 - 8,2,20,1,0,6,11,2,22,6, // 1765 - 4,1,15,2,25,6,6,3,18,1, // 1770 - 29,5,9,3,22,4,2,3,13,2, // 1775 - 23,6,4,3,15,2,27,4,7,3, // 1780 - 19,2,31,4,11,3,21,6,3,2, // 1785 - 15,1,25,6,6,2,17,3,29,4, // 1790 - 10,2,20,6,3,1,13,3,24,5, // 1795 - 4,3,16,1,27,5,7,3,17,3, // 1800 - 0,4,11,2,21,6,1,3,13,2, // 1805 - 25,4,5,3,16,2,29,4,9,3, // 1810 - 19,6,30,2,13,1,23,6,4,2, // 1815 - 14,3,27,4,8,2,18,3,0,4, // 1820 - 11,3,22,5,2,3,14,1,26,5, // 1825 - 6,3,16,3,28,4,10,2,20,6, // 1830 - 30,3,11,2,24,4,4,3,15,2, // 1835 - 25,6,8,1,19,2,29,6,9,3, // 1840 - 22,4,3,2,13,3,25,4,7,2, // 1845 - 17,3,27,6,9,1,21,5,1,3, // 1850 - 11,3,23,4,5,2,15,3,25,6, // 1855 - 6,2,19,1,29,6,10,2,22,4, // 1860 - 3,3,14,2,24,6,6,1,18,2, // 1865 - 28,6,8,3,20,4,2,2,12,3, // 1870 - 24,4,4,3,16,2,26,6,6,3, // 1875 - 17,2,0,4,10,3,22,4,3,2, // 1880 - 14,3,24,6,5,2,17,1,28,6, // 1885 - 9,2,21,4,1,3,13,2,23,6, // 1890 - 5,1,15,3,27,5,7,3,19,1, // 1895 - 0,5,10,3,22,4,2,3,13,2, // 1900 - 24,6,4,3,15,2,27,4,8,3, // 1905 - 20,4,1,2,11,3,22,6,3,2, // 1910 - 15,1,25,6,7,2,17,3,29,4, // 1915 - 10,2,21,6,1,3,13,1,24,5, // 1920 - 5,3,15,3,27,4,8,2,19,6, // 1925 - 1,1,12,2,22,6,3,3,14,2, // 1930 - 26,4,6,3,18,2,28,6,10,1, // 1935 - 20,6,2,2,12,3,24,4,5,2, // 1940 - 16,3,28,4,9,2,19,6,30,3, // 1945 - 12,1,23,5,3,3,14,3,26,4, // 1950 - 7,2,17,3,28,6,9,2,21,4, // 1955 - 1,3,13,2,25,4,5,3,16,2, // 1960 - 27,6,9,1,19,6,30,2,11,3, // 1965 - 23,4,4,2,14,3,27,4,7,3, // 1970 - 18,2,28,6,11,1,22,5,2,3, // 1975 - 12,3,25,4,6,2,16,3,26,6, // 1980 - 8,2,20,4,30,3,11,2,24,4, // 1985 - 4,3,15,2,25,6,8,1,18,3, // 1990 - 29,5,9,3,22,4,3,2,13,3, // 1995 - 23,6,6,1,17,2,27,6,7,3, // 2000 - 2004 - 20,4,1,2,11,3,23,4,5,2, // 2005 - 2009 - 15,3,25,6,6,2,19,1,29,6, // 2010 - 10,2,20,6,3,1,14,2,24,6, // 2015 - 4,3,17,1,28,5,8,3,20,4, // 2020 - 1,3,12,2,22,6,2,3,14,2, // 2025 - 26,4,6,3,17,2,0,4,10,3, // 2030 - 20,6,1,2,14,1,24,6,5,2, // 2035 - 15,3,28,4,9,2,19,6,1,1, // 2040 - 12,3,23,5,3,3,15,1,27,5, // 2045 - 7,3,17,3,29,4,11,2,21,6, // 2050 - 1,3,12,2,25,4,5,3,16,2, // 2055 - 28,4,9,3,19,6,30,2,12,1, // 2060 - 23,6,4,2,14,3,26,4,8,2, // 2065 - 18,3,0,4,10,3,22,5,2,3, // 2070 - 14,1,25,5,6,3,16,3,28,4, // 2075 - 9,2,20,6,30,3,11,2,23,4, // 2080 - 4,3,15,2,27,4,7,3,19,2, // 2085 - 29,6,11,1,21,6,3,2,13,3, // 2090 - 25,4,6,2,17,3,27,6,9,1, // 2095 - 20,5,30,3,10,3,22,4,3,2, // 2100 - 14,3,24,6,5,2,17,1,28,6, // 2105 - 9,2,21,4,1,3,13,2,23,6, // 2110 - 5,1,16,2,27,6,7,3,19,4, // 2115 - 30,2,11,3,23,4,3,3,14,2, // 2120 - 25,6,5,3,16,2,28,4,9,3, // 2125 - 21,4,2,2,12,3,23,6,4,2, // 2130 - 16,1,26,6,8,2,20,4,30,3, // 2135 - 11,2,22,6,4,1,14,3,25,5, // 2140 - 6,3,18,1,29,5,9,3,22,4, // 2145 - 2,3,13,2,23,6,4,3,15,2, // 2150 - 27,4,7,3,20,4,1,2,11,3, // 2155 - 21,6,3,2,15,1,25,6,6,2, // 2160 - 17,3,29,4,10,2,20,6,3,1, // 2165 - 13,3,24,5,4,3,17,1,28,5, // 2170 - 8,3,18,6,1,1,12,2,22,6, // 2175 - 2,3,14,2,26,4,6,3,17,2, // 2180 - 28,6,10,1,20,6,1,2,12,3, // 2185 - 24,4,5,2,15,3,28,4,9,2, // 2190 - 19,6,33,3,12,1,23,5,3,3, // 2195 - 13,3,25,4,6,2,16,3,26,6, // 2200 - 8,2,20,4,30,3,11,2,24,4, // 2205 - 4,3,15,2,25,6,8,1,18,6, // 2210 - 33,2,9,3,22,4,3,2,13,3, // 2215 - 25,4,6,3,17,2,27,6,9,1, // 2220 - 21,5,1,3,11,3,23,4,5,2, // 2225 - 15,3,25,6,6,2,19,4,33,3, // 2230 - 10,2,22,4,3,3,14,2,24,6, // 2235 - 6,1 // 2240 (Hebrew year: 6000) - }; - - private const int MaxMonthPlusOne = 14; - - // - // The lunar calendar has 6 different variations of month lengths - // within a year. - // - private static readonly byte[] s_lunarMonthLen = { - 0,00,00,00,00,00,00,00,00,00,00,00,00,0, - 0,30,29,29,29,30,29,30,29,30,29,30,29,0, // 3 common year variations - 0,30,29,30,29,30,29,30,29,30,29,30,29,0, - 0,30,30,30,29,30,29,30,29,30,29,30,29,0, - 0,30,29,29,29,30,30,29,30,29,30,29,30,29, // 3 leap year variations - 0,30,29,30,29,30,30,29,30,29,30,29,30,29, - 0,30,30,30,29,30,30,29,30,29,30,29,30,29 - }; - - internal static readonly DateTime calendarMinValue = new DateTime(1583, 1, 1); - // Gregorian 2239/9/29 = Hebrew 5999/13/29 (last day in Hebrew year 5999). - // We can only format/parse Hebrew numbers up to 999, so we limit the max range to Hebrew year 5999. - internal static readonly DateTime calendarMaxValue = new DateTime((new DateTime(2239, 9, 29, 23, 59, 59, 999)).Ticks + 9999); - - - - public override DateTime MinSupportedDateTime - { - get - { - return (calendarMinValue); - } - } - - - - public override DateTime MaxSupportedDateTime - { - get - { - return (calendarMaxValue); - } - } - - public override CalendarAlgorithmType AlgorithmType - { - get - { - return CalendarAlgorithmType.LunisolarCalendar; - } - } - - public HebrewCalendar() - { - } - - internal override CalendarId ID - { - get - { - return (CalendarId.HEBREW); - } - } - - - /*=================================CheckHebrewYearValue========================== - **Action: Check if the Hebrew year value is supported in this class. - **Returns: None. - **Arguments: y Hebrew year value - ** ear Hebrew era value - **Exceptions: ArgumentOutOfRange_Range if the year value is not supported. - **Note: - ** We use a table for the Hebrew calendar calculation, so the year supported is limited. - ============================================================================*/ - - private static void CheckHebrewYearValue(int y, int era, String varName) - { - CheckEraRange(era); - if (y > MaxHebrewYear || y < MinHebrewYear) - { - throw new ArgumentOutOfRangeException( - varName, - String.Format( - CultureInfo.CurrentCulture, - SR.ArgumentOutOfRange_Range, - MinHebrewYear, - MaxHebrewYear)); - } - } - - /*=================================CheckHebrewMonthValue========================== - **Action: Check if the Hebrew month value is valid. - **Returns: None. - **Arguments: year Hebrew year value - ** month Hebrew month value - **Exceptions: ArgumentOutOfRange_Range if the month value is not valid. - **Note: - ** Call CheckHebrewYearValue() before calling this to verify the year value is supported. - ============================================================================*/ - - private void CheckHebrewMonthValue(int year, int month, int era) - { - int monthsInYear = GetMonthsInYear(year, era); - if (month < 1 || month > monthsInYear) - { - throw new ArgumentOutOfRangeException( - nameof(month), - String.Format( - CultureInfo.CurrentCulture, - SR.ArgumentOutOfRange_Range, - 1, - monthsInYear)); - } - } - - /*=================================CheckHebrewDayValue========================== - **Action: Check if the Hebrew day value is valid. - **Returns: None. - **Arguments: year Hebrew year value - ** month Hebrew month value - ** day Hebrew day value. - **Exceptions: ArgumentOutOfRange_Range if the day value is not valid. - **Note: - ** Call CheckHebrewYearValue()/CheckHebrewMonthValue() before calling this to verify the year/month values are valid. - ============================================================================*/ - - private void CheckHebrewDayValue(int year, int month, int day, int era) - { - int daysInMonth = GetDaysInMonth(year, month, era); - if (day < 1 || day > daysInMonth) - { - throw new ArgumentOutOfRangeException( - nameof(day), - String.Format( - CultureInfo.CurrentCulture, - SR.ArgumentOutOfRange_Range, - 1, - daysInMonth)); - } - } - - internal static void CheckEraRange(int era) - { - if (era != CurrentEra && era != HebrewEra) - { - throw new ArgumentOutOfRangeException(nameof(era), SR.ArgumentOutOfRange_InvalidEraValue); - } - } - - private static void CheckTicksRange(long ticks) - { - if (ticks < calendarMinValue.Ticks || ticks > calendarMaxValue.Ticks) - { - throw new ArgumentOutOfRangeException( - "time", - // Print out the date in Gregorian using InvariantCulture since the DateTime is based on GreograinCalendar. - String.Format( - CultureInfo.InvariantCulture, - SR.ArgumentOutOfRange_CalendarRange, - calendarMinValue, - calendarMaxValue)); - } - } - - internal static int GetResult(__DateBuffer result, int part) - { - switch (part) - { - case DatePartYear: - return (result.year); - case DatePartMonth: - return (result.month); - case DatePartDay: - return (result.day); - } - - throw new InvalidOperationException(SR.InvalidOperation_DateTimeParsing); - } - - /*=================================GetLunarMonthDay========================== - **Action: Using the Hebrew table (HebrewTable) to get the Hebrew month/day value for Gregorian January 1st - ** in a given Gregorian year. - ** Greogrian January 1st falls usually in Tevet (4th month). Tevet has always 29 days. - ** That's why, there no nead to specify the lunar month in the table. There are exceptions, and these - ** are coded by giving numbers above 29 and below 1. - ** Actual decoding is takenig place in the switch statement below. - **Returns: - ** The Hebrew year type. The value is from 1 to 6. - ** normal years : 1 = 353 days 2 = 354 days 3 = 355 days. - ** Leap years : 4 = 383 5 384 6 = 385 days. - **Arguments: - ** gregorianYear The year value in Gregorian calendar. The value should be between 1500 and 2239. - ** lunarDate Object to take the result of the Hebrew year/month/day. - **Exceptions: - ============================================================================*/ - - internal static int GetLunarMonthDay(int gregorianYear, __DateBuffer lunarDate) - { - // - // Get the offset into the LunarMonthLen array and the lunar day - // for January 1st. - // - int index = gregorianYear - FirstGregorianTableYear; - if (index < 0 || index > TABLESIZE) - { - throw new ArgumentOutOfRangeException(nameof(gregorianYear)); - } - - index *= 2; - lunarDate.day = s_hebrewTable[index]; - - // Get the type of the year. The value is from 1 to 6 - int LunarYearType = s_hebrewTable[index + 1]; - - // - // Get the Lunar Month. - // - switch (lunarDate.day) - { - case (0): // 1/1 is on Shvat 1 - lunarDate.month = 5; - lunarDate.day = 1; - break; - case (30): // 1/1 is on Kislev 30 - lunarDate.month = 3; - break; - case (31): // 1/1 is on Shvat 2 - lunarDate.month = 5; - lunarDate.day = 2; - break; - case (32): // 1/1 is on Shvat 3 - lunarDate.month = 5; - lunarDate.day = 3; - break; - case (33): // 1/1 is on Kislev 29 - lunarDate.month = 3; - lunarDate.day = 29; - break; - default: // 1/1 is on Tevet (This is the general case) - lunarDate.month = 4; - break; - } - return (LunarYearType); - } - - // Returns a given date part of this DateTime. This method is used - // to compute the year, day-of-year, month, or day part. - - internal virtual int GetDatePart(long ticks, int part) - { - // The Gregorian year, month, day value for ticks. - int gregorianYear, gregorianMonth, gregorianDay; - int hebrewYearType; // lunar year type - long AbsoluteDate; // absolute date - absolute date 1/1/1600 - - // - // Make sure we have a valid Gregorian date that will fit into our - // Hebrew conversion limits. - // - CheckTicksRange(ticks); - - DateTime time = new DateTime(ticks); - - // - // Save the Gregorian date values. - // - gregorianYear = time.Year; - gregorianMonth = time.Month; - gregorianDay = time.Day; - - __DateBuffer lunarDate = new __DateBuffer(); // lunar month and day for Jan 1 - - // From the table looking-up value of HebrewTable[index] (stored in lunarDate.day), we get the the - // lunar month and lunar day where the Gregorian date 1/1 falls. - lunarDate.year = gregorianYear + HebrewYearOf1AD; - hebrewYearType = GetLunarMonthDay(gregorianYear, lunarDate); - - // This is the buffer used to store the result Hebrew date. - __DateBuffer result = new __DateBuffer(); - - // - // Store the values for the start of the new year - 1/1. - // - result.year = lunarDate.year; - result.month = lunarDate.month; - result.day = lunarDate.day; - - // - // Get the absolute date from 1/1/1600. - // - AbsoluteDate = GregorianCalendar.GetAbsoluteDate(gregorianYear, gregorianMonth, gregorianDay); - - // - // If the requested date was 1/1, then we're done. - // - if ((gregorianMonth == 1) && (gregorianDay == 1)) - { - return (GetResult(result, part)); - } - - // - // Calculate the number of days between 1/1 and the requested date. - // - long NumDays; // number of days since 1/1 - NumDays = AbsoluteDate - GregorianCalendar.GetAbsoluteDate(gregorianYear, 1, 1); - - // - // If the requested date is within the current lunar month, then - // we're done. - // - if ((NumDays + (long)lunarDate.day) <= (long)(s_lunarMonthLen[hebrewYearType * MaxMonthPlusOne + lunarDate.month])) - { - result.day += (int)NumDays; - return (GetResult(result, part)); - } - - // - // Adjust for the current partial month. - // - result.month++; - result.day = 1; - - // - // Adjust the Lunar Month and Year (if necessary) based on the number - // of days between 1/1 and the requested date. - // - // Assumes Jan 1 can never translate to the last Lunar month, which - // is true. - // - NumDays -= (long)(s_lunarMonthLen[hebrewYearType * MaxMonthPlusOne + lunarDate.month] - lunarDate.day); - Debug.Assert(NumDays >= 1, "NumDays >= 1"); - - // If NumDays is 1, then we are done. Otherwise, find the correct Hebrew month - // and day. - if (NumDays > 1) - { - // - // See if we're on the correct Lunar month. - // - while (NumDays > (long)(s_lunarMonthLen[hebrewYearType * MaxMonthPlusOne + result.month])) - { - // - // Adjust the number of days and move to the next month. - // - NumDays -= (long)(s_lunarMonthLen[hebrewYearType * MaxMonthPlusOne + result.month++]); - - // - // See if we need to adjust the Year. - // Must handle both 12 and 13 month years. - // - if ((result.month > 13) || (s_lunarMonthLen[hebrewYearType * MaxMonthPlusOne + result.month] == 0)) - { - // - // Adjust the Year. - // - result.year++; - hebrewYearType = s_hebrewTable[(gregorianYear + 1 - FirstGregorianTableYear) * 2 + 1]; - - // - // Adjust the Month. - // - result.month = 1; - } - } - // - // Found the right Lunar month. - // - result.day += (int)(NumDays - 1); - } - return (GetResult(result, part)); - } - - // Returns the DateTime resulting from adding the given number of - // months to the specified DateTime. The result is computed by incrementing - // (or decrementing) the year and month parts of the specified DateTime by - // value months, and, if required, adjusting the day part of the - // resulting date downwards to the last day of the resulting month in the - // resulting year. The time-of-day part of the result is the same as the - // time-of-day part of the specified DateTime. - // - // In more precise terms, considering the specified DateTime to be of the - // form y / m / d + t, where y is the - // year, m is the month, d is the day, and t is the - // time-of-day, the result is y1 / m1 / d1 + t, - // where y1 and m1 are computed by adding value months - // to y and m, and d1 is the largest value less than - // or equal to d that denotes a valid day in month m1 of year - // y1. - // - - public override DateTime AddMonths(DateTime time, int months) - { - try - { - int y = GetDatePart(time.Ticks, DatePartYear); - int m = GetDatePart(time.Ticks, DatePartMonth); - int d = GetDatePart(time.Ticks, DatePartDay); - - - int monthsInYear; - int i; - if (months >= 0) - { - i = m + months; - while (i > (monthsInYear = GetMonthsInYear(y, CurrentEra))) - { - y++; - i -= monthsInYear; - } - } - else - { - if ((i = m + months) <= 0) - { - months = -months; - months -= m; - y--; - - while (months > (monthsInYear = GetMonthsInYear(y, CurrentEra))) - { - y--; - months -= monthsInYear; - } - monthsInYear = GetMonthsInYear(y, CurrentEra); - i = monthsInYear - months; - } - } - - int days = GetDaysInMonth(y, i); - if (d > days) - { - d = days; - } - return (new DateTime(ToDateTime(y, i, d, 0, 0, 0, 0).Ticks + (time.Ticks % TicksPerDay))); - } - // We expect ArgumentException and ArgumentOutOfRangeException (which is subclass of ArgumentException) - // If exception is thrown in the calls above, we are out of the supported range of this calendar. - catch (ArgumentException) - { - throw new ArgumentOutOfRangeException( - nameof(months), - String.Format( - CultureInfo.CurrentCulture, - SR.ArgumentOutOfRange_AddValue)); - } - } - - // Returns the DateTime resulting from adding the given number of - // years to the specified DateTime. The result is computed by incrementing - // (or decrementing) the year part of the specified DateTime by value - // years. If the month and day of the specified DateTime is 2/29, and if the - // resulting year is not a leap year, the month and day of the resulting - // DateTime becomes 2/28. Otherwise, the month, day, and time-of-day - // parts of the result are the same as those of the specified DateTime. - // - - public override DateTime AddYears(DateTime time, int years) - { - int y = GetDatePart(time.Ticks, DatePartYear); - int m = GetDatePart(time.Ticks, DatePartMonth); - int d = GetDatePart(time.Ticks, DatePartDay); - - y += years; - CheckHebrewYearValue(y, Calendar.CurrentEra, nameof(years)); - - int months = GetMonthsInYear(y, CurrentEra); - if (m > months) - { - m = months; - } - - int days = GetDaysInMonth(y, m); - if (d > days) - { - d = days; - } - - long ticks = ToDateTime(y, m, d, 0, 0, 0, 0).Ticks + (time.Ticks % TicksPerDay); - Calendar.CheckAddResult(ticks, MinSupportedDateTime, MaxSupportedDateTime); - return (new DateTime(ticks)); - } - - // Returns the day-of-month part of the specified DateTime. The returned - // value is an integer between 1 and 31. - // - - public override int GetDayOfMonth(DateTime time) - { - return (GetDatePart(time.Ticks, DatePartDay)); - } - - // Returns the day-of-week part of the specified DateTime. The returned value - // is an integer between 0 and 6, where 0 indicates Sunday, 1 indicates - // Monday, 2 indicates Tuesday, 3 indicates Wednesday, 4 indicates - // Thursday, 5 indicates Friday, and 6 indicates Saturday. - // - - public override DayOfWeek GetDayOfWeek(DateTime time) - { - // If we calculate back, the Hebrew day of week for Gregorian 0001/1/1 is Monday (1). - // Therfore, the fomula is: - return ((DayOfWeek)((int)(time.Ticks / TicksPerDay + 1) % 7)); - } - - internal static int GetHebrewYearType(int year, int era) - { - CheckHebrewYearValue(year, era, nameof(year)); - // The HebrewTable is indexed by Gregorian year and starts from FirstGregorianYear. - // So we need to convert year (Hebrew year value) to Gregorian Year below. - return (s_hebrewTable[(year - HebrewYearOf1AD - FirstGregorianTableYear) * 2 + 1]); - } - - // Returns the day-of-year part of the specified DateTime. The returned value - // is an integer between 1 and 366. - // - - public override int GetDayOfYear(DateTime time) - { - // Get Hebrew year value of the specified time. - int year = GetYear(time); - DateTime beginOfYearDate; - if (year == 5343) - { - // Gregorian 1583/01/01 corresponds to Hebrew 5343/04/07 (MinSupportedDateTime) - // To figure out the Gregorian date associated with Hebrew 5343/01/01, we need to - // count the days from 5343/01/01 to 5343/04/07 and subtract that from Gregorian - // 1583/01/01. - // 1. Tishri (30 days) - // 2. Heshvan (30 days since 5343 has 355 days) - // 3. Kislev (30 days since 5343 has 355 days) - // 96 days to get from 5343/01/01 to 5343/04/07 - // Gregorian 1583/01/01 - 96 days = 1582/9/27 - - // the beginning of Hebrew year 5343 corresponds to Gregorian September 27, 1582. - beginOfYearDate = new DateTime(1582, 9, 27); - } - else - { - // following line will fail when year is 5343 (first supported year) - beginOfYearDate = ToDateTime(year, 1, 1, 0, 0, 0, 0, CurrentEra); - } - return ((int)((time.Ticks - beginOfYearDate.Ticks) / TicksPerDay) + 1); - } - - // Returns the number of days in the month given by the year and - // month arguments. - // - - public override int GetDaysInMonth(int year, int month, int era) - { - CheckEraRange(era); - int hebrewYearType = GetHebrewYearType(year, era); - CheckHebrewMonthValue(year, month, era); - - Debug.Assert(hebrewYearType >= 1 && hebrewYearType <= 6, - "hebrewYearType should be from 1 to 6, but now hebrewYearType = " + hebrewYearType + " for hebrew year " + year); - int monthDays = s_lunarMonthLen[hebrewYearType * MaxMonthPlusOne + month]; - if (monthDays == 0) - { - throw new ArgumentOutOfRangeException(nameof(month), SR.ArgumentOutOfRange_Month); - } - return (monthDays); - } - - // Returns the number of days in the year given by the year argument for the current era. - // - - public override int GetDaysInYear(int year, int era) - { - CheckEraRange(era); - // normal years : 1 = 353 days 2 = 354 days 3 = 355 days. - // Leap years : 4 = 383 5 384 6 = 385 days. - - // LunarYearType is from 1 to 6 - int LunarYearType = GetHebrewYearType(year, era); - if (LunarYearType < 4) - { - // common year: LunarYearType = 1, 2, 3 - return (352 + LunarYearType); - } - return (382 + (LunarYearType - 3)); - } - - // Returns the era for the specified DateTime value. - - public override int GetEra(DateTime time) - { - return (HebrewEra); - } - - - public override int[] Eras - { - get - { - return (new int[] { HebrewEra }); - } - } - - // Returns the month part of the specified DateTime. The returned value is an - // integer between 1 and 12. - // - - public override int GetMonth(DateTime time) - { - return (GetDatePart(time.Ticks, DatePartMonth)); - } - - // Returns the number of months in the specified year and era. - - public override int GetMonthsInYear(int year, int era) - { - return (IsLeapYear(year, era) ? 13 : 12); - } - - // Returns the year part of the specified DateTime. The returned value is an - // integer between 1 and 9999. - // - - public override int GetYear(DateTime time) - { - return (GetDatePart(time.Ticks, DatePartYear)); - } - - // Checks whether a given day in the specified era is a leap day. This method returns true if - // the date is a leap day, or false if not. - // - - public override bool IsLeapDay(int year, int month, int day, int era) - { - if (IsLeapMonth(year, month, era)) - { - // Every day in a leap month is a leap day. - CheckHebrewDayValue(year, month, day, era); - return (true); - } - else if (IsLeapYear(year, Calendar.CurrentEra)) - { - // There is an additional day in the 6th month in the leap year (the extra day is the 30th day in the 6th month), - // so we should return true for 6/30 if that's in a leap year. - if (month == 6 && day == 30) - { - return (true); - } - } - CheckHebrewDayValue(year, month, day, era); - return (false); - } - - // Returns the leap month in a calendar year of the specified era. This method returns 0 - // if this calendar does not have leap month, or this year is not a leap year. - // - - - public override int GetLeapMonth(int year, int era) - { - // Year/era values are checked in IsLeapYear(). - if (IsLeapYear(year, era)) - { - // The 7th month in a leap year is a leap month. - return (7); - } - return (0); - } - - // Checks whether a given month in the specified era is a leap month. This method returns true if - // month is a leap month, or false if not. - // - - public override bool IsLeapMonth(int year, int month, int era) - { - // Year/era values are checked in IsLeapYear(). - bool isLeapYear = IsLeapYear(year, era); - CheckHebrewMonthValue(year, month, era); - // The 7th month in a leap year is a leap month. - if (isLeapYear) - { - if (month == 7) - { - return (true); - } - } - return (false); - } - - // Checks whether a given year in the specified era is a leap year. This method returns true if - // year is a leap year, or false if not. - // - - public override bool IsLeapYear(int year, int era) - { - CheckHebrewYearValue(year, era, nameof(year)); - return (((7 * (long)year + 1) % 19) < 7); - } - - // (month1, day1) - (month2, day2) - private static int GetDayDifference(int lunarYearType, int month1, int day1, int month2, int day2) - { - if (month1 == month2) - { - return (day1 - day2); - } - - // Make sure that (month1, day1) < (month2, day2) - bool swap = (month1 > month2); - if (swap) - { - // (month1, day1) < (month2, day2). Swap the values. - // The result will be a negative number. - int tempMonth, tempDay; - tempMonth = month1; tempDay = day1; - month1 = month2; day1 = day2; - month2 = tempMonth; day2 = tempDay; - } - - // Get the number of days from (month1,day1) to (month1, end of month1) - int days = s_lunarMonthLen[lunarYearType * MaxMonthPlusOne + month1] - day1; - - // Move to next month. - month1++; - - // Add up the days. - while (month1 < month2) - { - days += s_lunarMonthLen[lunarYearType * MaxMonthPlusOne + month1++]; - } - days += day2; - - return (swap ? days : -days); - } - - /*=================================HebrewToGregorian========================== - **Action: Convert Hebrew date to Gregorian date. - **Returns: - **Arguments: - **Exceptions: - ** The algorithm is like this: - ** The hebrew year has an offset to the Gregorian year, so we can guess the Gregorian year for - ** the specified Hebrew year. That is, GreogrianYear = HebrewYear - FirstHebrewYearOf1AD. - ** - ** From the Gregorian year and HebrewTable, we can get the Hebrew month/day value - ** of the Gregorian date January 1st. Let's call this month/day value [hebrewDateForJan1] - ** - ** If the requested Hebrew month/day is less than [hebrewDateForJan1], we know the result - ** Gregorian date falls in previous year. So we decrease the Gregorian year value, and - ** retrieve the Hebrew month/day value of the Gregorian date january 1st again. - ** - ** Now, we get the answer of the Gregorian year. - ** - ** The next step is to get the number of days between the requested Hebrew month/day - ** and [hebrewDateForJan1]. When we get that, we can create the DateTime by adding/subtracting - ** the ticks value of the number of days. - ** - ============================================================================*/ - - - private static DateTime HebrewToGregorian(int hebrewYear, int hebrewMonth, int hebrewDay, int hour, int minute, int second, int millisecond) - { - // Get the rough Gregorian year for the specified hebrewYear. - // - int gregorianYear = hebrewYear - HebrewYearOf1AD; - - __DateBuffer hebrewDateOfJan1 = new __DateBuffer(); // year value is unused. - int lunarYearType = GetLunarMonthDay(gregorianYear, hebrewDateOfJan1); - - if ((hebrewMonth == hebrewDateOfJan1.month) && (hebrewDay == hebrewDateOfJan1.day)) - { - return (new DateTime(gregorianYear, 1, 1, hour, minute, second, millisecond)); - } - - int days = GetDayDifference(lunarYearType, hebrewMonth, hebrewDay, hebrewDateOfJan1.month, hebrewDateOfJan1.day); - - DateTime gregorianNewYear = new DateTime(gregorianYear, 1, 1); - return (new DateTime(gregorianNewYear.Ticks + days * TicksPerDay - + TimeToTicks(hour, minute, second, millisecond))); - } - - // Returns the date and time converted to a DateTime value. Throws an exception if the n-tuple is invalid. - // - - public override DateTime ToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era) - { - CheckHebrewYearValue(year, era, nameof(year)); - CheckHebrewMonthValue(year, month, era); - CheckHebrewDayValue(year, month, day, era); - DateTime dt = HebrewToGregorian(year, month, day, hour, minute, second, millisecond); - CheckTicksRange(dt.Ticks); - return (dt); - } - - private const int DEFAULT_TWO_DIGIT_YEAR_MAX = 5790; - - - public override int TwoDigitYearMax - { - get - { - if (twoDigitYearMax == -1) - { - twoDigitYearMax = GetSystemTwoDigitYearSetting(ID, DEFAULT_TWO_DIGIT_YEAR_MAX); - } - return (twoDigitYearMax); - } - - set - { - VerifyWritable(); - if (value == 99) - { - // Do nothing here. Year 99 is allowed so that TwoDitYearMax is disabled. - } - else - { - CheckHebrewYearValue(value, HebrewEra, nameof(value)); - } - twoDigitYearMax = value; - } - } - - - public override int ToFourDigitYear(int year) - { - if (year < 0) - { - throw new ArgumentOutOfRangeException(nameof(year), - SR.ArgumentOutOfRange_NeedNonNegNum); - } - Contract.EndContractBlock(); - - if (year < 100) - { - return (base.ToFourDigitYear(year)); - } - - if (year > MaxHebrewYear || year < MinHebrewYear) - { - throw new ArgumentOutOfRangeException( - nameof(year), - String.Format( - CultureInfo.CurrentCulture, - SR.ArgumentOutOfRange_Range, - MinHebrewYear, - MaxHebrewYear)); - } - return (year); - } - - internal class __DateBuffer - { - internal int year; - internal int month; - internal int day; - } - } -} - diff --git a/src/mscorlib/corefx/System/Globalization/HebrewNumber.cs b/src/mscorlib/corefx/System/Globalization/HebrewNumber.cs deleted file mode 100644 index 01e251d..0000000 --- a/src/mscorlib/corefx/System/Globalization/HebrewNumber.cs +++ /dev/null @@ -1,458 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System.Text; -using System.Diagnostics; - -namespace System.Globalization -{ - //////////////////////////////////////////////////////////////////////////// - // - // Used in HebrewNumber.ParseByChar to maintain the context information ( - // the state in the state machine and current Hebrew number values, etc.) - // when parsing Hebrew number character by character. - // - //////////////////////////////////////////////////////////////////////////// - - internal struct HebrewNumberParsingContext - { - // The current state of the state machine for parsing Hebrew numbers. - internal HebrewNumber.HS state; - // The current value of the Hebrew number. - // The final value is determined when state is FoundEndOfHebrewNumber. - internal int result; - - public HebrewNumberParsingContext(int result) - { - // Set the start state of the state machine for parsing Hebrew numbers. - state = HebrewNumber.HS.Start; - this.result = result; - } - } - - //////////////////////////////////////////////////////////////////////////// - // - // Please see ParseByChar() for comments about different states defined here. - // - //////////////////////////////////////////////////////////////////////////// - - internal enum HebrewNumberParsingState - { - InvalidHebrewNumber, - NotHebrewDigit, - FoundEndOfHebrewNumber, - ContinueParsing, - } - - //////////////////////////////////////////////////////////////////////////// - // - // class HebrewNumber - // - // Provides static methods for formatting integer values into - // Hebrew text and parsing Hebrew number text. - // - // Limitations: - // Parse can only handles value 1 ~ 999. - // ToString() can only handles 1 ~ 999. If value is greater than 5000, - // 5000 will be subtracted from the value. - // - //////////////////////////////////////////////////////////////////////////// - - internal class HebrewNumber - { - // This class contains only static methods. Add a private ctor so that - // compiler won't generate a default one for us. - private HebrewNumber() - { - } - - //////////////////////////////////////////////////////////////////////////// - // - // ToString - // - // Converts the given number to Hebrew letters according to the numeric - // value of each Hebrew letter. Basically, this converts the lunar year - // and the lunar month to letters. - // - // The character of a year is described by three letters of the Hebrew - // alphabet, the first and third giving, respectively, the days of the - // weeks on which the New Year occurs and Passover begins, while the - // second is the initial of the Hebrew word for defective, normal, or - // complete. - // - // Defective Year : Both Heshvan and Kislev are defective (353 or 383 days) - // Normal Year : Heshvan is defective, Kislev is full (354 or 384 days) - // Complete Year : Both Heshvan and Kislev are full (355 or 385 days) - // - //////////////////////////////////////////////////////////////////////////// - - internal static String ToString(int Number) - { - char cTens = '\x0'; - char cUnits; // tens and units chars - int Hundreds, Tens; // hundreds and tens values - StringBuilder szHebrew = new StringBuilder(); - - - // - // Adjust the number if greater than 5000. - // - if (Number > 5000) - { - Number -= 5000; - } - - Debug.Assert(Number > 0 && Number <= 999, "Number is out of range."); ; - - // - // Get the Hundreds. - // - Hundreds = Number / 100; - - if (Hundreds > 0) - { - Number -= Hundreds * 100; - // \x05e7 = 100 - // \x05e8 = 200 - // \x05e9 = 300 - // \x05ea = 400 - // If the number is greater than 400, use the multiples of 400. - for (int i = 0; i < (Hundreds / 4); i++) - { - szHebrew.Append('\x05ea'); - } - - int remains = Hundreds % 4; - if (remains > 0) - { - szHebrew.Append((char)((int)'\x05e6' + remains)); - } - } - - // - // Get the Tens. - // - Tens = Number / 10; - Number %= 10; - - switch (Tens) - { - case (0): - cTens = '\x0'; - break; - case (1): - cTens = '\x05d9'; // Hebrew Letter Yod - break; - case (2): - cTens = '\x05db'; // Hebrew Letter Kaf - break; - case (3): - cTens = '\x05dc'; // Hebrew Letter Lamed - break; - case (4): - cTens = '\x05de'; // Hebrew Letter Mem - break; - case (5): - cTens = '\x05e0'; // Hebrew Letter Nun - break; - case (6): - cTens = '\x05e1'; // Hebrew Letter Samekh - break; - case (7): - cTens = '\x05e2'; // Hebrew Letter Ayin - break; - case (8): - cTens = '\x05e4'; // Hebrew Letter Pe - break; - case (9): - cTens = '\x05e6'; // Hebrew Letter Tsadi - break; - } - - // - // Get the Units. - // - cUnits = (char)(Number > 0 ? ((int)'\x05d0' + Number - 1) : 0); - - if ((cUnits == '\x05d4') && // Hebrew Letter He (5) - (cTens == '\x05d9')) - { // Hebrew Letter Yod (10) - cUnits = '\x05d5'; // Hebrew Letter Vav (6) - cTens = '\x05d8'; // Hebrew Letter Tet (9) - } - - if ((cUnits == '\x05d5') && // Hebrew Letter Vav (6) - (cTens == '\x05d9')) - { // Hebrew Letter Yod (10) - cUnits = '\x05d6'; // Hebrew Letter Zayin (7) - cTens = '\x05d8'; // Hebrew Letter Tet (9) - } - - // - // Copy the appropriate info to the given buffer. - // - - if (cTens != '\x0') - { - szHebrew.Append(cTens); - } - - if (cUnits != '\x0') - { - szHebrew.Append(cUnits); - } - - if (szHebrew.Length > 1) - { - szHebrew.Insert(szHebrew.Length - 1, '"'); - } - else - { - szHebrew.Append('\''); - } - - // - // Return success. - // - return (szHebrew.ToString()); - } - - //////////////////////////////////////////////////////////////////////////// - // - // Token used to tokenize a Hebrew word into tokens so that we can use in the - // state machine. - // - //////////////////////////////////////////////////////////////////////////// - - private enum HebrewToken : short - { - Invalid = -1, - Digit400 = 0, - Digit200_300 = 1, - Digit100 = 2, - Digit10 = 3, // 10 ~ 90 - Digit1 = 4, // 1, 2, 3, 4, 5, 8, - Digit6_7 = 5, - Digit7 = 6, - Digit9 = 7, - SingleQuote = 8, - DoubleQuote = 9, - }; - - //////////////////////////////////////////////////////////////////////////// - // - // This class is used to map a token into its Hebrew digit value. - // - //////////////////////////////////////////////////////////////////////////// - - private struct HebrewValue - { - internal HebrewToken token; - internal short value; - internal HebrewValue(HebrewToken token, short value) - { - this.token = token; - this.value = value; - } - } - - // - // Map a Hebrew character from U+05D0 ~ U+05EA to its digit value. - // The value is -1 if the Hebrew character does not have a associated value. - // - private static readonly HebrewValue[] s_hebrewValues = { - new HebrewValue(HebrewToken.Digit1, 1) , // '\x05d0 - new HebrewValue(HebrewToken.Digit1, 2) , // '\x05d1 - new HebrewValue(HebrewToken.Digit1, 3) , // '\x05d2 - new HebrewValue(HebrewToken.Digit1, 4) , // '\x05d3 - new HebrewValue(HebrewToken.Digit1, 5) , // '\x05d4 - new HebrewValue(HebrewToken.Digit6_7,6) , // '\x05d5 - new HebrewValue(HebrewToken.Digit6_7,7) , // '\x05d6 - new HebrewValue(HebrewToken.Digit1, 8) , // '\x05d7 - new HebrewValue(HebrewToken.Digit9, 9) , // '\x05d8 - new HebrewValue(HebrewToken.Digit10, 10) , // '\x05d9; // Hebrew Letter Yod - new HebrewValue(HebrewToken.Invalid, -1) , // '\x05da; - new HebrewValue(HebrewToken.Digit10, 20) , // '\x05db; // Hebrew Letter Kaf - new HebrewValue(HebrewToken.Digit10, 30) , // '\x05dc; // Hebrew Letter Lamed - new HebrewValue(HebrewToken.Invalid, -1) , // '\x05dd; - new HebrewValue(HebrewToken.Digit10, 40) , // '\x05de; // Hebrew Letter Mem - new HebrewValue(HebrewToken.Invalid, -1) , // '\x05df; - new HebrewValue(HebrewToken.Digit10, 50) , // '\x05e0; // Hebrew Letter Nun - new HebrewValue(HebrewToken.Digit10, 60) , // '\x05e1; // Hebrew Letter Samekh - new HebrewValue(HebrewToken.Digit10, 70) , // '\x05e2; // Hebrew Letter Ayin - new HebrewValue(HebrewToken.Invalid, -1) , // '\x05e3; - new HebrewValue(HebrewToken.Digit10, 80) , // '\x05e4; // Hebrew Letter Pe - new HebrewValue(HebrewToken.Invalid, -1) , // '\x05e5; - new HebrewValue(HebrewToken.Digit10, 90) , // '\x05e6; // Hebrew Letter Tsadi - new HebrewValue(HebrewToken.Digit100, 100) , // '\x05e7; - new HebrewValue(HebrewToken.Digit200_300, 200) , // '\x05e8; - new HebrewValue(HebrewToken.Digit200_300, 300) , // '\x05e9; - new HebrewValue(HebrewToken.Digit400, 400) , // '\x05ea; - }; - - private const int minHebrewNumberCh = 0x05d0; - private static char s_maxHebrewNumberCh = (char)(minHebrewNumberCh + s_hebrewValues.Length - 1); - - //////////////////////////////////////////////////////////////////////////// - // - // Hebrew number parsing State - // The current state and the next token will lead to the next state in the state machine. - // DQ = Double Quote - // - //////////////////////////////////////////////////////////////////////////// - - internal enum HS : sbyte - { - _err = -1, // an error state - Start = 0, - S400 = 1, // a Hebrew digit 400 - S400_400 = 2, // Two Hebrew digit 400 - S400_X00 = 3, // Two Hebrew digit 400 and followed by 100 - S400_X0 = 4, // Hebrew digit 400 and followed by 10 ~ 90 - X00_DQ = 5, // A hundred number and followed by a double quote. - S400_X00_X0 = 6, - X0_DQ = 7, // A two-digit number and followed by a double quote. - X = 8, // A single digit Hebrew number. - X0 = 9, // A two-digit Hebrew number - X00 = 10, // A three-digit Hebrew number - S400_DQ = 11, // A Hebrew digit 400 and followed by a double quote. - S400_400_DQ = 12, - S400_400_100 = 13, - S9 = 14, // Hebrew digit 9 - X00_S9 = 15, // A hundered number and followed by a digit 9 - S9_DQ = 16, // Hebrew digit 9 and followed by a double quote - END = 100, // A terminial state is reached. - } - - // - // The state machine for Hebrew number pasing. - // - private static readonly HS[] s_numberPasingState = - { - // 400 300/200 100 90~10 8~1 6, 7, 9, ' " - /* 0 */ - HS.S400, HS.X00, HS.X00, HS.X0, HS.X, HS.X, HS.X, HS.S9, HS._err, HS._err, - /* 1: S400 */ - HS.S400_400, HS.S400_X00, HS.S400_X00, HS.S400_X0, HS._err, HS._err, HS._err, HS.X00_S9 ,HS.END, HS.S400_DQ, - /* 2: S400_400 */ - HS._err, HS._err, HS.S400_400_100,HS.S400_X0, HS._err, HS._err, HS._err, HS.X00_S9 ,HS._err, HS.S400_400_DQ, - /* 3: S400_X00 */ - HS._err, HS._err, HS._err, HS.S400_X00_X0, HS._err, HS._err, HS._err, HS.X00_S9 ,HS._err, HS.X00_DQ, - /* 4: S400_X0 */ - HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS.X0_DQ, - /* 5: X00_DQ */ - HS._err, HS._err, HS._err, HS.END, HS.END, HS.END, HS.END, HS.END, HS._err, HS._err, - /* 6: S400_X00_X0 */ - HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS.X0_DQ, - /* 7: X0_DQ */ - HS._err, HS._err, HS._err, HS._err, HS.END, HS.END, HS.END, HS.END, HS._err, HS._err, - /* 8: X */ - HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS.END, HS._err, - /* 9: X0 */ - HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS.END, HS.X0_DQ, - /* 10: X00 */ - HS._err, HS._err, HS._err, HS.S400_X0, HS._err, HS._err, HS._err, HS.X00_S9, HS.END, HS.X00_DQ, - /* 11: S400_DQ */ - HS.END, HS.END, HS.END, HS.END, HS.END, HS.END, HS.END, HS.END, HS._err, HS._err, - /* 12: S400_400_DQ*/ - HS._err, HS._err, HS.END, HS.END, HS.END, HS.END, HS.END, HS.END, HS._err, HS._err, - /* 13: S400_400_100*/ - HS._err, HS._err, HS._err, HS.S400_X00_X0, HS._err, HS._err, HS._err, HS.X00_S9, HS._err, HS.X00_DQ, - /* 14: S9 */ - HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS.END, HS.S9_DQ, - /* 15: X00_S9 */ - HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS.S9_DQ, - /* 16: S9_DQ */ - HS._err, HS._err, HS._err, HS._err, HS._err, HS.END, HS.END, HS._err, HS._err, HS._err - }; - - // Count of valid HebrewToken, column count in the NumberPasingState array - private const int HebrewTokenCount = 10; - - - //////////////////////////////////////////////////////////////////////// - // - // Actions: - // Parse the Hebrew number by passing one character at a time. - // The state between characters are maintained at HebrewNumberPasingContext. - // Returns: - // Return a enum of HebrewNumberParsingState. - // NotHebrewDigit: The specified ch is not a valid Hebrew digit. - // InvalidHebrewNumber: After parsing the specified ch, it will lead into - // an invalid Hebrew number text. - // FoundEndOfHebrewNumber: A terminal state is reached. This means that - // we find a valid Hebrew number text after the specified ch is parsed. - // ContinueParsing: The specified ch is a valid Hebrew digit, and - // it will lead into a valid state in the state machine, we should - // continue to parse incoming characters. - // - //////////////////////////////////////////////////////////////////////// - - internal static HebrewNumberParsingState ParseByChar(char ch, ref HebrewNumberParsingContext context) - { - Debug.Assert(s_numberPasingState.Length == HebrewTokenCount * ((int)HS.S9_DQ + 1)); - - HebrewToken token; - if (ch == '\'') - { - token = HebrewToken.SingleQuote; - } - else if (ch == '\"') - { - token = HebrewToken.DoubleQuote; - } - else - { - int index = (int)ch - minHebrewNumberCh; - if (index >= 0 && index < s_hebrewValues.Length) - { - token = s_hebrewValues[index].token; - if (token == HebrewToken.Invalid) - { - return (HebrewNumberParsingState.NotHebrewDigit); - } - context.result += s_hebrewValues[index].value; - } - else - { - // Not in valid Hebrew digit range. - return (HebrewNumberParsingState.NotHebrewDigit); - } - } - context.state = s_numberPasingState[(int)context.state * (int)HebrewTokenCount + (int)token]; - if (context.state == HS._err) - { - // Invalid Hebrew state. This indicates an incorrect Hebrew number. - return (HebrewNumberParsingState.InvalidHebrewNumber); - } - if (context.state == HS.END) - { - // Reach a terminal state. - return (HebrewNumberParsingState.FoundEndOfHebrewNumber); - } - // We should continue to parse. - return (HebrewNumberParsingState.ContinueParsing); - } - - //////////////////////////////////////////////////////////////////////// - // - // Actions: - // Check if the ch is a valid Hebrew number digit. - // This function will return true if the specified char is a legal Hebrew - // digit character, single quote, or double quote. - // Returns: - // true if the specified character is a valid Hebrew number character. - // - //////////////////////////////////////////////////////////////////////// - - internal static bool IsDigit(char ch) - { - if (ch >= minHebrewNumberCh && ch <= s_maxHebrewNumberCh) - { - return (s_hebrewValues[ch - minHebrewNumberCh].value >= 0); - } - return (ch == '\'' || ch == '\"'); - } - } -} diff --git a/src/mscorlib/corefx/System/Globalization/HijriCalendar.cs b/src/mscorlib/corefx/System/Globalization/HijriCalendar.cs deleted file mode 100644 index 0c72d9e..0000000 --- a/src/mscorlib/corefx/System/Globalization/HijriCalendar.cs +++ /dev/null @@ -1,679 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.Runtime.Versioning; -using System.Diagnostics.Contracts; - -namespace System.Globalization -{ - //////////////////////////////////////////////////////////////////////////// - // - // Rules for the Hijri calendar: - // - The Hijri calendar is a strictly Lunar calendar. - // - Days begin at sunset. - // - Islamic Year 1 (Muharram 1, 1 A.H.) is equivalent to absolute date - // 227015 (Friday, July 16, 622 C.E. - Julian). - // - Leap Years occur in the 2, 5, 7, 10, 13, 16, 18, 21, 24, 26, & 29th - // years of a 30-year cycle. Year = leap iff ((11y+14) mod 30 < 11). - // - There are 12 months which contain alternately 30 and 29 days. - // - The 12th month, Dhu al-Hijjah, contains 30 days instead of 29 days - // in a leap year. - // - Common years have 354 days. Leap years have 355 days. - // - There are 10,631 days in a 30-year cycle. - // - The Islamic months are: - // 1. Muharram (30 days) 7. Rajab (30 days) - // 2. Safar (29 days) 8. Sha'ban (29 days) - // 3. Rabi I (30 days) 9. Ramadan (30 days) - // 4. Rabi II (29 days) 10. Shawwal (29 days) - // 5. Jumada I (30 days) 11. Dhu al-Qada (30 days) - // 6. Jumada II (29 days) 12. Dhu al-Hijjah (29 days) {30} - // - // NOTENOTE - // The calculation of the HijriCalendar is based on the absolute date. And the - // absolute date means the number of days from January 1st, 1 A.D. - // Therefore, we do not support the days before the January 1st, 1 A.D. - // - //////////////////////////////////////////////////////////////////////////// - /* - ** Calendar support range: - ** Calendar Minimum Maximum - ** ========== ========== ========== - ** Gregorian 0622/07/18 9999/12/31 - ** Hijri 0001/01/01 9666/04/03 - */ - - [Serializable] - public partial class HijriCalendar : Calendar - { - public static readonly int HijriEra = 1; - - internal const int DatePartYear = 0; - internal const int DatePartDayOfYear = 1; - internal const int DatePartMonth = 2; - internal const int DatePartDay = 3; - - internal const int MinAdvancedHijri = -2; - internal const int MaxAdvancedHijri = 2; - - internal static readonly int[] HijriMonthDays = { 0, 30, 59, 89, 118, 148, 177, 207, 236, 266, 295, 325, 355 }; - - private int _hijriAdvance = Int32.MinValue; - - // DateTime.MaxValue = Hijri calendar (year:9666, month: 4, day: 3). - internal const int MaxCalendarYear = 9666; - internal const int MaxCalendarMonth = 4; - internal const int MaxCalendarDay = 3; - // Hijri calendar (year: 1, month: 1, day:1 ) = Gregorian (year: 622, month: 7, day: 18) - // This is the minimal Gregorian date that we support in the HijriCalendar. - internal static readonly DateTime calendarMinValue = new DateTime(622, 7, 18); - internal static readonly DateTime calendarMaxValue = DateTime.MaxValue; - - - public override DateTime MinSupportedDateTime - { - get - { - return (calendarMinValue); - } - } - - - public override DateTime MaxSupportedDateTime - { - get - { - return (calendarMaxValue); - } - } - - public override CalendarAlgorithmType AlgorithmType - { - get - { - return CalendarAlgorithmType.LunarCalendar; - } - } - - public HijriCalendar() - { - } - - internal override CalendarId ID - { - get - { - return CalendarId.HIJRI; - } - } - - protected override int DaysInYearBeforeMinSupportedYear - { - get - { - // the year before the 1st year of the cycle would have been the 30th year - // of the previous cycle which is not a leap year. Common years have 354 days. - return 354; - } - } - - - - /*=================================GetAbsoluteDateHijri========================== - **Action: Gets the Absolute date for the given Hijri date. The absolute date means - ** the number of days from January 1st, 1 A.D. - **Returns: - **Arguments: - **Exceptions: - ============================================================================*/ - - private long GetAbsoluteDateHijri(int y, int m, int d) - { - return (long)(DaysUpToHijriYear(y) + HijriMonthDays[m - 1] + d - 1 - HijriAdjustment); - } - - /*=================================DaysUpToHijriYear========================== - **Action: Gets the total number of days (absolute date) up to the given Hijri Year. - ** The absolute date means the number of days from January 1st, 1 A.D. - **Returns: Gets the total number of days (absolute date) up to the given Hijri Year. - **Arguments: HijriYear year value in Hijri calendar. - **Exceptions: None - **Notes: - ============================================================================*/ - - private long DaysUpToHijriYear(int HijriYear) - { - long NumDays; // number of absolute days - int NumYear30; // number of years up to current 30 year cycle - int NumYearsLeft; // number of years into 30 year cycle - - // - // Compute the number of years up to the current 30 year cycle. - // - NumYear30 = ((HijriYear - 1) / 30) * 30; - - // - // Compute the number of years left. This is the number of years - // into the 30 year cycle for the given year. - // - NumYearsLeft = HijriYear - NumYear30 - 1; - - // - // Compute the number of absolute days up to the given year. - // - NumDays = ((NumYear30 * 10631L) / 30L) + 227013L; - while (NumYearsLeft > 0) - { - // Common year is 354 days, and leap year is 355 days. - NumDays += 354 + (IsLeapYear(NumYearsLeft, CurrentEra) ? 1 : 0); - NumYearsLeft--; - } - - // - // Return the number of absolute days. - // - return (NumDays); - } - - public int HijriAdjustment - { - get - { - if (_hijriAdvance == Int32.MinValue) - { - // Never been set before. Use the system value from registry. - _hijriAdvance = GetHijriDateAdjustment(); - } - return (_hijriAdvance); - } - - set - { - // NOTE: Check the value of Min/MaxAdavncedHijri with Arabic speakers to see if the assumption is good. - if (value < MinAdvancedHijri || value > MaxAdvancedHijri) - { - throw new ArgumentOutOfRangeException( - "HijriAdjustment", - String.Format( - CultureInfo.CurrentCulture, - SR.ArgumentOutOfRange_Bounds_Lower_Upper, - MinAdvancedHijri, - MaxAdvancedHijri)); - } - Contract.EndContractBlock(); - VerifyWritable(); - - _hijriAdvance = value; - } - } - - internal static void CheckTicksRange(long ticks) - { - if (ticks < calendarMinValue.Ticks || ticks > calendarMaxValue.Ticks) - { - throw new ArgumentOutOfRangeException( - "time", - String.Format( - CultureInfo.InvariantCulture, - SR.ArgumentOutOfRange_CalendarRange, - calendarMinValue, - calendarMaxValue)); - } - } - - internal static void CheckEraRange(int era) - { - if (era != CurrentEra && era != HijriEra) - { - throw new ArgumentOutOfRangeException(nameof(era), SR.ArgumentOutOfRange_InvalidEraValue); - } - } - - internal static void CheckYearRange(int year, int era) - { - CheckEraRange(era); - if (year < 1 || year > MaxCalendarYear) - { - throw new ArgumentOutOfRangeException( - nameof(year), - String.Format( - CultureInfo.CurrentCulture, - SR.ArgumentOutOfRange_Range, - 1, - MaxCalendarYear)); - } - } - - internal static void CheckYearMonthRange(int year, int month, int era) - { - CheckYearRange(year, era); - if (year == MaxCalendarYear) - { - if (month > MaxCalendarMonth) - { - throw new ArgumentOutOfRangeException( - nameof(month), - String.Format( - CultureInfo.CurrentCulture, - SR.ArgumentOutOfRange_Range, - 1, - MaxCalendarMonth)); - } - } - - if (month < 1 || month > 12) - { - throw new ArgumentOutOfRangeException(nameof(month), SR.ArgumentOutOfRange_Month); - } - } - - /*=================================GetDatePart========================== - **Action: Returns a given date part of this DateTime. This method is used - ** to compute the year, day-of-year, month, or day part. - **Returns: - **Arguments: - **Exceptions: ArgumentException if part is incorrect. - **Notes: - ** First, we get the absolute date (the number of days from January 1st, 1 A.C) for the given ticks. - ** Use the formula (((AbsoluteDate - 227013) * 30) / 10631) + 1, we can a rough value for the Hijri year. - ** In order to get the exact Hijri year, we compare the exact absolute date for HijriYear and (HijriYear + 1). - ** From here, we can get the correct Hijri year. - ============================================================================*/ - - internal virtual int GetDatePart(long ticks, int part) - { - int HijriYear; // Hijri year - int HijriMonth; // Hijri month - int HijriDay; // Hijri day - long NumDays; // The calculation buffer in number of days. - - CheckTicksRange(ticks); - - // - // Get the absolute date. The absolute date is the number of days from January 1st, 1 A.D. - // 1/1/0001 is absolute date 1. - // - NumDays = ticks / GregorianCalendar.TicksPerDay + 1; - - // - // See how much we need to backup or advance - // - NumDays += HijriAdjustment; - - // - // Calculate the appromixate Hijri Year from this magic formula. - // - HijriYear = (int)(((NumDays - 227013) * 30) / 10631) + 1; - - long daysToHijriYear = DaysUpToHijriYear(HijriYear); // The absoulte date for HijriYear - long daysOfHijriYear = GetDaysInYear(HijriYear, CurrentEra); // The number of days for (HijriYear+1) year. - - if (NumDays < daysToHijriYear) - { - daysToHijriYear -= daysOfHijriYear; - HijriYear--; - } - else if (NumDays == daysToHijriYear) - { - HijriYear--; - daysToHijriYear -= GetDaysInYear(HijriYear, CurrentEra); - } - else - { - if (NumDays > daysToHijriYear + daysOfHijriYear) - { - daysToHijriYear += daysOfHijriYear; - HijriYear++; - } - } - if (part == DatePartYear) - { - return (HijriYear); - } - - // - // Calculate the Hijri Month. - // - - HijriMonth = 1; - NumDays -= daysToHijriYear; - - if (part == DatePartDayOfYear) - { - return ((int)NumDays); - } - - while ((HijriMonth <= 12) && (NumDays > HijriMonthDays[HijriMonth - 1])) - { - HijriMonth++; - } - HijriMonth--; - - if (part == DatePartMonth) - { - return (HijriMonth); - } - - // - // Calculate the Hijri Day. - // - HijriDay = (int)(NumDays - HijriMonthDays[HijriMonth - 1]); - - if (part == DatePartDay) - { - return (HijriDay); - } - // Incorrect part value. - throw new InvalidOperationException(SR.InvalidOperation_DateTimeParsing); - } - - // Returns the DateTime resulting from adding the given number of - // months to the specified DateTime. The result is computed by incrementing - // (or decrementing) the year and month parts of the specified DateTime by - // value months, and, if required, adjusting the day part of the - // resulting date downwards to the last day of the resulting month in the - // resulting year. The time-of-day part of the result is the same as the - // time-of-day part of the specified DateTime. - // - // In more precise terms, considering the specified DateTime to be of the - // form y / m / d + t, where y is the - // year, m is the month, d is the day, and t is the - // time-of-day, the result is y1 / m1 / d1 + t, - // where y1 and m1 are computed by adding value months - // to y and m, and d1 is the largest value less than - // or equal to d that denotes a valid day in month m1 of year - // y1. - // - - public override DateTime AddMonths(DateTime time, int months) - { - if (months < -120000 || months > 120000) - { - throw new ArgumentOutOfRangeException( - nameof(months), - String.Format( - CultureInfo.CurrentCulture, - SR.ArgumentOutOfRange_Range, - -120000, - 120000)); - } - Contract.EndContractBlock(); - // Get the date in Hijri calendar. - int y = GetDatePart(time.Ticks, DatePartYear); - int m = GetDatePart(time.Ticks, DatePartMonth); - int d = GetDatePart(time.Ticks, DatePartDay); - int i = m - 1 + months; - if (i >= 0) - { - m = i % 12 + 1; - y = y + i / 12; - } - else - { - m = 12 + (i + 1) % 12; - y = y + (i - 11) / 12; - } - int days = GetDaysInMonth(y, m); - if (d > days) - { - d = days; - } - long ticks = GetAbsoluteDateHijri(y, m, d) * TicksPerDay + (time.Ticks % TicksPerDay); - Calendar.CheckAddResult(ticks, MinSupportedDateTime, MaxSupportedDateTime); - return (new DateTime(ticks)); - } - - // Returns the DateTime resulting from adding the given number of - // years to the specified DateTime. The result is computed by incrementing - // (or decrementing) the year part of the specified DateTime by value - // years. If the month and day of the specified DateTime is 2/29, and if the - // resulting year is not a leap year, the month and day of the resulting - // DateTime becomes 2/28. Otherwise, the month, day, and time-of-day - // parts of the result are the same as those of the specified DateTime. - // - - public override DateTime AddYears(DateTime time, int years) - { - return (AddMonths(time, years * 12)); - } - - // Returns the day-of-month part of the specified DateTime. The returned - // value is an integer between 1 and 31. - // - - public override int GetDayOfMonth(DateTime time) - { - return (GetDatePart(time.Ticks, DatePartDay)); - } - - // Returns the day-of-week part of the specified DateTime. The returned value - // is an integer between 0 and 6, where 0 indicates Sunday, 1 indicates - // Monday, 2 indicates Tuesday, 3 indicates Wednesday, 4 indicates - // Thursday, 5 indicates Friday, and 6 indicates Saturday. - // - - public override DayOfWeek GetDayOfWeek(DateTime time) - { - return ((DayOfWeek)((int)(time.Ticks / TicksPerDay + 1) % 7)); - } - - // Returns the day-of-year part of the specified DateTime. The returned value - // is an integer between 1 and 366. - // - - public override int GetDayOfYear(DateTime time) - { - return (GetDatePart(time.Ticks, DatePartDayOfYear)); - } - - // Returns the number of days in the month given by the year and - // month arguments. - // - [Pure] - public override int GetDaysInMonth(int year, int month, int era) - { - CheckYearMonthRange(year, month, era); - if (month == 12) - { - // For the 12th month, leap year has 30 days, and common year has 29 days. - return (IsLeapYear(year, CurrentEra) ? 30 : 29); - } - // Other months contain 30 and 29 days alternatively. The 1st month has 30 days. - return (((month % 2) == 1) ? 30 : 29); - } - - // Returns the number of days in the year given by the year argument for the current era. - // - - public override int GetDaysInYear(int year, int era) - { - CheckYearRange(year, era); - // Common years have 354 days. Leap years have 355 days. - return (IsLeapYear(year, CurrentEra) ? 355 : 354); - } - - // Returns the era for the specified DateTime value. - - public override int GetEra(DateTime time) - { - CheckTicksRange(time.Ticks); - return (HijriEra); - } - - - public override int[] Eras - { - get - { - return (new int[] { HijriEra }); - } - } - - // Returns the month part of the specified DateTime. The returned value is an - // integer between 1 and 12. - // - - public override int GetMonth(DateTime time) - { - return (GetDatePart(time.Ticks, DatePartMonth)); - } - - // Returns the number of months in the specified year and era. - - public override int GetMonthsInYear(int year, int era) - { - CheckYearRange(year, era); - return (12); - } - - // Returns the year part of the specified DateTime. The returned value is an - // integer between 1 and MaxCalendarYear. - // - - public override int GetYear(DateTime time) - { - return (GetDatePart(time.Ticks, DatePartYear)); - } - - // Checks whether a given day in the specified era is a leap day. This method returns true if - // the date is a leap day, or false if not. - // - - public override bool IsLeapDay(int year, int month, int day, int era) - { - // The year/month/era value checking is done in GetDaysInMonth(). - int daysInMonth = GetDaysInMonth(year, month, era); - if (day < 1 || day > daysInMonth) - { - throw new ArgumentOutOfRangeException( - nameof(day), - String.Format( - CultureInfo.CurrentCulture, - SR.ArgumentOutOfRange_Day, - daysInMonth, - month)); - } - return (IsLeapYear(year, era) && month == 12 && day == 30); - } - - // Returns the leap month in a calendar year of the specified era. This method returns 0 - // if this calendar does not have leap month, or this year is not a leap year. - // - - public override int GetLeapMonth(int year, int era) - { - CheckYearRange(year, era); - return (0); - } - - // Checks whether a given month in the specified era is a leap month. This method returns true if - // month is a leap month, or false if not. - // - - public override bool IsLeapMonth(int year, int month, int era) - { - CheckYearMonthRange(year, month, era); - return (false); - } - - // Checks whether a given year in the specified era is a leap year. This method returns true if - // year is a leap year, or false if not. - // - - public override bool IsLeapYear(int year, int era) - { - CheckYearRange(year, era); - return ((((year * 11) + 14) % 30) < 11); - } - - // Returns the date and time converted to a DateTime value. Throws an exception if the n-tuple is invalid. - // - - public override DateTime ToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era) - { - // The year/month/era checking is done in GetDaysInMonth(). - int daysInMonth = GetDaysInMonth(year, month, era); - if (day < 1 || day > daysInMonth) - { - throw new ArgumentOutOfRangeException( - nameof(day), - String.Format( - CultureInfo.CurrentCulture, - SR.ArgumentOutOfRange_Day, - daysInMonth, - month)); - } - - long lDate = GetAbsoluteDateHijri(year, month, day); - - if (lDate >= 0) - { - return (new DateTime(lDate * GregorianCalendar.TicksPerDay + TimeToTicks(hour, minute, second, millisecond))); - } - else - { - throw new ArgumentOutOfRangeException(null, SR.ArgumentOutOfRange_BadYearMonthDay); - } - } - - private const int DEFAULT_TWO_DIGIT_YEAR_MAX = 1451; - - - public override int TwoDigitYearMax - { - get - { - if (twoDigitYearMax == -1) - { - twoDigitYearMax = GetSystemTwoDigitYearSetting(ID, DEFAULT_TWO_DIGIT_YEAR_MAX); - } - return (twoDigitYearMax); - } - - set - { - VerifyWritable(); - if (value < 99 || value > MaxCalendarYear) - { - throw new ArgumentOutOfRangeException( - nameof(value), - String.Format( - CultureInfo.CurrentCulture, - SR.ArgumentOutOfRange_Range, - 99, - MaxCalendarYear)); - } - twoDigitYearMax = value; - } - } - - - public override int ToFourDigitYear(int year) - { - if (year < 0) - { - throw new ArgumentOutOfRangeException(nameof(year), - SR.ArgumentOutOfRange_NeedNonNegNum); - } - Contract.EndContractBlock(); - - if (year < 100) - { - return (base.ToFourDigitYear(year)); - } - - if (year > MaxCalendarYear) - { - throw new ArgumentOutOfRangeException( - nameof(year), - String.Format( - CultureInfo.CurrentCulture, - SR.ArgumentOutOfRange_Range, - 1, - MaxCalendarYear)); - } - return (year); - } - } -} diff --git a/src/mscorlib/corefx/System/Globalization/IdnMapping.cs b/src/mscorlib/corefx/System/Globalization/IdnMapping.cs deleted file mode 100644 index 8424472..0000000 --- a/src/mscorlib/corefx/System/Globalization/IdnMapping.cs +++ /dev/null @@ -1,152 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -// This file contains the IDN functions and implementation. -// -// This allows encoding of non-ASCII domain names in a "punycode" form, -// for example: -// -// \u5B89\u5BA4\u5948\u7F8E\u6075-with-SUPER-MONKEYS -// -// is encoded as: -// -// xn---with-SUPER-MONKEYS-pc58ag80a8qai00g7n9n -// -// Additional options are provided to allow unassigned IDN characters and -// to validate according to the Std3ASCII Rules (like DNS names). -// -// There are also rules regarding bidirectionality of text and the length -// of segments. -// -// For additional rules see also: -// RFC 3490 - Internationalizing Domain Names in Applications (IDNA) -// RFC 3491 - Nameprep: A Stringprep Profile for Internationalized Domain Names (IDN) -// RFC 3492 - Punycode: A Bootstring encoding of Unicode for Internationalized Domain Names in Applications (IDNA) - -using System.Diagnostics.Contracts; - -namespace System.Globalization -{ - // IdnMapping class used to map names to Punycode - public sealed partial class IdnMapping - { - private bool _allowUnassigned; - private bool _useStd3AsciiRules; - - public IdnMapping() - { - } - - public bool AllowUnassigned - { - get { return _allowUnassigned; } - set { _allowUnassigned = value; } - } - - public bool UseStd3AsciiRules - { - get { return _useStd3AsciiRules; } - set { _useStd3AsciiRules = value; } - } - - // Gets ASCII (Punycode) version of the string - public string GetAscii(string unicode) - { - return GetAscii(unicode, 0); - } - - public string GetAscii(string unicode, int index) - { - if (unicode == null) - throw new ArgumentNullException(nameof(unicode)); - Contract.EndContractBlock(); - return GetAscii(unicode, index, unicode.Length - index); - } - - public string GetAscii(string unicode, int index, int count) - { - if (unicode == null) - throw new ArgumentNullException(nameof(unicode)); - if (index < 0 || count < 0) - throw new ArgumentOutOfRangeException((index < 0) ? nameof(index) : nameof(count), SR.ArgumentOutOfRange_NeedNonNegNum); - if (index > unicode.Length) - throw new ArgumentOutOfRangeException(nameof(index), SR.ArgumentOutOfRange_Index); - if (index > unicode.Length - count) - throw new ArgumentOutOfRangeException(nameof(unicode), SR.ArgumentOutOfRange_IndexCountBuffer); - Contract.EndContractBlock(); - - if (count == 0) - { - throw new ArgumentException(SR.Argument_IdnBadLabelSize, nameof(unicode)); - } - if (unicode[index + count - 1] == 0) - { - throw new ArgumentException(SR.Format(SR.Argument_InvalidCharSequence, index + count - 1), nameof(unicode)); - } - - unsafe - { - fixed (char* pUnicode = unicode) - { - return GetAsciiCore(pUnicode + index, count); - } - } - } - - // Gets Unicode version of the string. Normalized and limited to IDNA characters. - public string GetUnicode(string ascii) - { - return GetUnicode(ascii, 0); - } - - public string GetUnicode(string ascii, int index) - { - if (ascii == null) - throw new ArgumentNullException(nameof(ascii)); - Contract.EndContractBlock(); - return GetUnicode(ascii, index, ascii.Length - index); - } - - public string GetUnicode(string ascii, int index, int count) - { - if (ascii == null) - throw new ArgumentNullException(nameof(ascii)); - if (index < 0 || count < 0) - throw new ArgumentOutOfRangeException((index < 0) ? nameof(index) : nameof(count), SR.ArgumentOutOfRange_NeedNonNegNum); - if (index > ascii.Length) - throw new ArgumentOutOfRangeException(nameof(index), SR.ArgumentOutOfRange_Index); - if (index > ascii.Length - count) - throw new ArgumentOutOfRangeException(nameof(ascii), SR.ArgumentOutOfRange_IndexCountBuffer); - - // This is a case (i.e. explicitly null-terminated input) where behavior in .NET and Win32 intentionally differ. - // The .NET APIs should (and did in v4.0 and earlier) throw an ArgumentException on input that includes a terminating null. - // The Win32 APIs fail on an embedded null, but not on a terminating null. - if (count > 0 && ascii[index + count - 1] == (char)0) - throw new ArgumentException(SR.Argument_IdnBadPunycode, nameof(ascii)); - Contract.EndContractBlock(); - - unsafe - { - fixed (char* pAscii = ascii) - { - return GetUnicodeCore(pAscii + index, count); - } - } - } - - public override bool Equals(object obj) - { - IdnMapping that = obj as IdnMapping; - return - that != null && - _allowUnassigned == that._allowUnassigned && - _useStd3AsciiRules == that._useStd3AsciiRules; - } - - public override int GetHashCode() - { - return (_allowUnassigned ? 100 : 200) + (_useStd3AsciiRules ? 1000 : 2000); - } - } -} diff --git a/src/mscorlib/corefx/System/Globalization/JapaneseCalendar.cs b/src/mscorlib/corefx/System/Globalization/JapaneseCalendar.cs deleted file mode 100644 index f0216c8..0000000 --- a/src/mscorlib/corefx/System/Globalization/JapaneseCalendar.cs +++ /dev/null @@ -1,411 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; -using System.Diagnostics.Contracts; - -namespace System.Globalization -{ - /*=================================JapaneseCalendar========================== - ** - ** JapaneseCalendar is based on Gregorian calendar. The month and day values are the same as - ** Gregorian calendar. However, the year value is an offset to the Gregorian - ** year based on the era. - ** - ** This system is adopted by Emperor Meiji in 1868. The year value is counted based on the reign of an emperor, - ** and the era begins on the day an emperor ascends the throne and continues until his death. - ** The era changes at 12:00AM. - ** - ** For example, the current era is Heisei. It started on 1989/1/8 A.D. Therefore, Gregorian year 1989 is also Heisei 1st. - ** 1989/1/8 A.D. is also Heisei 1st 1/8. - ** - ** Any date in the year during which era is changed can be reckoned in either era. For example, - ** 1989/1/1 can be 1/1 Heisei 1st year or 1/1 Showa 64th year. - ** - ** Note: - ** The DateTime can be represented by the JapaneseCalendar are limited to two factors: - ** 1. The min value and max value of DateTime class. - ** 2. The available era information. - ** - ** Calendar support range: - ** Calendar Minimum Maximum - ** ========== ========== ========== - ** Gregorian 1868/09/08 9999/12/31 - ** Japanese Meiji 01/01 Heisei 8011/12/31 - ============================================================================*/ - - - [Serializable] - public partial class JapaneseCalendar : Calendar - { - internal static readonly DateTime calendarMinValue = new DateTime(1868, 9, 8); - - - public override DateTime MinSupportedDateTime - { - get - { - return (calendarMinValue); - } - } - - public override DateTime MaxSupportedDateTime - { - get - { - return (DateTime.MaxValue); - } - } - - public override CalendarAlgorithmType AlgorithmType - { - get - { - return CalendarAlgorithmType.SolarCalendar; - } - } - - // - // Using a field initializer rather than a static constructor so that the whole class can be lazy - // init. - internal static volatile EraInfo[] japaneseEraInfo; - - // - // Read our era info - // - // m_EraInfo must be listed in reverse chronological order. The most recent era - // should be the first element. - // That is, m_EraInfo[0] contains the most recent era. - // - // We know about 4 built-in eras, however users may add additional era(s) from the - // registry, by adding values to HKLM\SYSTEM\CurrentControlSet\Control\Nls\Calendars\Japanese\Eras - // we don't read the registry and instead we call WinRT to get the needed informatio - // - // Registry values look like: - // yyyy.mm.dd=era_abbrev_english_englishabbrev - // - // Where yyyy.mm.dd is the registry value name, and also the date of the era start. - // yyyy, mm, and dd are the year, month & day the era begins (4, 2 & 2 digits long) - // era is the Japanese Era name - // abbrev is the Abbreviated Japanese Era Name - // english is the English name for the Era (unused) - // englishabbrev is the Abbreviated English name for the era. - // . is a delimiter, but the value of . doesn't matter. - // '_' marks the space between the japanese era name, japanese abbreviated era name - // english name, and abbreviated english names. - // - internal static EraInfo[] GetEraInfo() - { - // See if we need to build it - if (japaneseEraInfo == null) - { - japaneseEraInfo = GetJapaneseEras(); - // See if we have to use the built-in eras - if (japaneseEraInfo == null) - { - // We know about some built-in ranges - EraInfo[] defaultEraRanges = new EraInfo[4]; - defaultEraRanges[0] = new EraInfo(4, 1989, 1, 8, 1988, 1, GregorianCalendar.MaxYear - 1988, - "\x5e73\x6210", "\x5e73", "H"); // era #4 start year/month/day, yearOffset, minEraYear - defaultEraRanges[1] = new EraInfo(3, 1926, 12, 25, 1925, 1, 1989 - 1925, - "\x662d\x548c", "\x662d", "S"); // era #3,start year/month/day, yearOffset, minEraYear - defaultEraRanges[2] = new EraInfo(2, 1912, 7, 30, 1911, 1, 1926 - 1911, - "\x5927\x6b63", "\x5927", "T"); // era #2,start year/month/day, yearOffset, minEraYear - defaultEraRanges[3] = new EraInfo(1, 1868, 1, 1, 1867, 1, 1912 - 1867, - "\x660e\x6cbb", "\x660e", "M"); // era #1,start year/month/day, yearOffset, minEraYear - - // Remember the ranges we built - japaneseEraInfo = defaultEraRanges; - } - } - - // return the era we found/made - return japaneseEraInfo; - } - - internal static volatile Calendar s_defaultInstance; - internal GregorianCalendarHelper helper; - - /*=================================GetDefaultInstance========================== - **Action: Internal method to provide a default intance of JapaneseCalendar. Used by NLS+ implementation - ** and other calendars. - **Returns: - **Arguments: - **Exceptions: - ============================================================================*/ - - internal static Calendar GetDefaultInstance() - { - if (s_defaultInstance == null) - { - s_defaultInstance = new JapaneseCalendar(); - } - return (s_defaultInstance); - } - - - public JapaneseCalendar() - { - try - { - new CultureInfo("ja-JP"); - } - catch (ArgumentException e) - { - throw new TypeInitializationException(this.GetType().ToString(), e); - } - helper = new GregorianCalendarHelper(this, GetEraInfo()); - } - - internal override CalendarId ID - { - get - { - return CalendarId.JAPAN; - } - } - - - public override DateTime AddMonths(DateTime time, int months) - { - return (helper.AddMonths(time, months)); - } - - - public override DateTime AddYears(DateTime time, int years) - { - return (helper.AddYears(time, years)); - } - - /*=================================GetDaysInMonth========================== - **Action: Returns the number of days in the month given by the year and month arguments. - **Returns: The number of days in the given month. - **Arguments: - ** year The year in Japanese calendar. - ** month The month - ** era The Japanese era value. - **Exceptions - ** ArgumentException If month is less than 1 or greater * than 12. - ============================================================================*/ - - - public override int GetDaysInMonth(int year, int month, int era) - { - return (helper.GetDaysInMonth(year, month, era)); - } - - - public override int GetDaysInYear(int year, int era) - { - return (helper.GetDaysInYear(year, era)); - } - - - public override int GetDayOfMonth(DateTime time) - { - return (helper.GetDayOfMonth(time)); - } - - - public override DayOfWeek GetDayOfWeek(DateTime time) - { - return (helper.GetDayOfWeek(time)); - } - - - public override int GetDayOfYear(DateTime time) - { - return (helper.GetDayOfYear(time)); - } - - - public override int GetMonthsInYear(int year, int era) - { - return (helper.GetMonthsInYear(year, era)); - } - - - [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems. - public override int GetWeekOfYear(DateTime time, CalendarWeekRule rule, DayOfWeek firstDayOfWeek) - { - return (helper.GetWeekOfYear(time, rule, firstDayOfWeek)); - } - - /*=================================GetEra========================== - **Action: Get the era value of the specified time. - **Returns: The era value for the specified time. - **Arguments: - ** time the specified date time. - **Exceptions: ArgumentOutOfRangeException if time is out of the valid era ranges. - ============================================================================*/ - - - public override int GetEra(DateTime time) - { - return (helper.GetEra(time)); - } - - - public override int GetMonth(DateTime time) - { - return (helper.GetMonth(time)); - } - - - public override int GetYear(DateTime time) - { - return (helper.GetYear(time)); - } - - - public override bool IsLeapDay(int year, int month, int day, int era) - { - return (helper.IsLeapDay(year, month, day, era)); - } - - - public override bool IsLeapYear(int year, int era) - { - return (helper.IsLeapYear(year, era)); - } - - // Returns the leap month in a calendar year of the specified era. This method returns 0 - // if this calendar does not have leap month, or this year is not a leap year. - // - - public override int GetLeapMonth(int year, int era) - { - return (helper.GetLeapMonth(year, era)); - } - - - public override bool IsLeapMonth(int year, int month, int era) - { - return (helper.IsLeapMonth(year, month, era)); - } - - - public override DateTime ToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era) - { - return (helper.ToDateTime(year, month, day, hour, minute, second, millisecond, era)); - } - - // For Japanese calendar, four digit year is not used. Few emperors will live for more than one hundred years. - // Therefore, for any two digit number, we just return the original number. - - public override int ToFourDigitYear(int year) - { - if (year <= 0) - { - throw new ArgumentOutOfRangeException(nameof(year), - SR.ArgumentOutOfRange_NeedPosNum); - } - Contract.EndContractBlock(); - - if (year > helper.MaxYear) - { - throw new ArgumentOutOfRangeException( - nameof(year), - String.Format( - CultureInfo.CurrentCulture, - SR.ArgumentOutOfRange_Range, - 1, - helper.MaxYear)); - } - return (year); - } - - - public override int[] Eras - { - get - { - return (helper.Eras); - } - } - - // - // Return the various era strings - // Note: The arrays are backwards of the eras - // - internal static String[] EraNames() - { - EraInfo[] eras = GetEraInfo(); - String[] eraNames = new String[eras.Length]; - - for (int i = 0; i < eras.Length; i++) - { - // Strings are in chronological order, eras are backwards order. - eraNames[i] = eras[eras.Length - i - 1].eraName; - } - - return eraNames; - } - - internal static String[] AbbrevEraNames() - { - EraInfo[] eras = GetEraInfo(); - String[] erasAbbrev = new String[eras.Length]; - - for (int i = 0; i < eras.Length; i++) - { - // Strings are in chronological order, eras are backwards order. - erasAbbrev[i] = eras[eras.Length - i - 1].abbrevEraName; - } - - return erasAbbrev; - } - - internal static String[] EnglishEraNames() - { - EraInfo[] eras = GetEraInfo(); - String[] erasEnglish = new String[eras.Length]; - - for (int i = 0; i < eras.Length; i++) - { - // Strings are in chronological order, eras are backwards order. - erasEnglish[i] = eras[eras.Length - i - 1].englishEraName; - } - - return erasEnglish; - } - - private const int DEFAULT_TWO_DIGIT_YEAR_MAX = 99; - - internal override bool IsValidYear(int year, int era) - { - return helper.IsValidYear(year, era); - } - - public override int TwoDigitYearMax - { - get - { - if (twoDigitYearMax == -1) - { - twoDigitYearMax = GetSystemTwoDigitYearSetting(ID, DEFAULT_TWO_DIGIT_YEAR_MAX); - } - return (twoDigitYearMax); - } - - set - { - VerifyWritable(); - if (value < 99 || value > helper.MaxYear) - { - throw new ArgumentOutOfRangeException( - "year", - String.Format( - CultureInfo.CurrentCulture, - SR.ArgumentOutOfRange_Range, - 99, - helper.MaxYear)); - } - twoDigitYearMax = value; - } - } - } -} diff --git a/src/mscorlib/corefx/System/Globalization/JapaneseLunisolarCalendar.cs b/src/mscorlib/corefx/System/Globalization/JapaneseLunisolarCalendar.cs deleted file mode 100644 index cc3d349..0000000 --- a/src/mscorlib/corefx/System/Globalization/JapaneseLunisolarCalendar.cs +++ /dev/null @@ -1,311 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.Diagnostics.Contracts; - -namespace System.Globalization -{ - //////////////////////////////////////////////////////////////////////////// - // - // Notes about JapaneseLunisolarCalendar - // - //////////////////////////////////////////////////////////////////////////// - /* - ** Calendar support range: - ** Calendar Minimum Maximum - ** ========== ========== ========== - ** Gregorian 1960/01/28 2050/01/22 - ** JapaneseLunisolar 1960/01/01 2049/12/29 - */ - - [Serializable] - public class JapaneseLunisolarCalendar : EastAsianLunisolarCalendar - { - // - // The era value for the current era. - // - - public const int JapaneseEra = 1; - - internal GregorianCalendarHelper helper; - - internal const int MIN_LUNISOLAR_YEAR = 1960; - internal const int MAX_LUNISOLAR_YEAR = 2049; - - internal const int MIN_GREGORIAN_YEAR = 1960; - internal const int MIN_GREGORIAN_MONTH = 1; - internal const int MIN_GREGORIAN_DAY = 28; - - internal const int MAX_GREGORIAN_YEAR = 2050; - internal const int MAX_GREGORIAN_MONTH = 1; - internal const int MAX_GREGORIAN_DAY = 22; - - internal static DateTime minDate = new DateTime(MIN_GREGORIAN_YEAR, MIN_GREGORIAN_MONTH, MIN_GREGORIAN_DAY); - internal static DateTime maxDate = new DateTime((new DateTime(MAX_GREGORIAN_YEAR, MAX_GREGORIAN_MONTH, MAX_GREGORIAN_DAY, 23, 59, 59, 999)).Ticks + 9999); - - public override DateTime MinSupportedDateTime - { - get - { - return (minDate); - } - } - - - public override DateTime MaxSupportedDateTime - { - get - { - return (maxDate); - } - } - protected override int DaysInYearBeforeMinSupportedYear - { - get - { - // 1959 from ChineseLunisolarCalendar - return 354; - } - } - - private static readonly int[,] s_yinfo = - { - /*Y LM Lmon Lday DaysPerMonth D1 D2 D3 D4 D5 D6 D7 D8 D9 D10 D11 D12 D13 #Days - 1960 */ - { 6 , 1 , 28 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 29 384 -1961 */{ 0 , 2 , 15 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 0 355 -1962 */{ 0 , 2 , 5 , 19808 },/* 29 30 29 29 30 30 29 30 29 30 30 29 0 354 -1963 */{ 4 , 1 , 25 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 29 384 -1964 */{ 0 , 2 , 13 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355 -1965 */{ 0 , 2 , 2 , 21104 },/* 29 30 29 30 29 29 30 29 29 30 30 30 0 354 -1966 */{ 3 , 1 , 22 , 26928 },/* 29 30 30 29 30 29 29 30 29 29 30 30 29 383 -1967 */{ 0 , 2 , 9 , 55632 },/* 30 30 29 30 30 29 29 30 29 30 29 30 0 355 -1968 */{ 7 , 1 , 30 , 27304 },/* 29 30 30 29 30 29 30 29 30 29 30 29 30 384 -1969 */{ 0 , 2 , 17 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354 -1970 */{ 0 , 2 , 6 , 39632 },/* 30 29 29 30 30 29 30 29 30 30 29 30 0 355 -1971 */{ 5 , 1 , 27 , 19176 },/* 29 30 29 29 30 29 30 29 30 30 30 29 30 384 -1972 */{ 0 , 2 , 15 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354 -1973 */{ 0 , 2 , 3 , 42208 },/* 30 29 30 29 29 30 29 29 30 30 30 29 0 354 -1974 */{ 4 , 1 , 23 , 53864 },/* 30 30 29 30 29 29 30 29 29 30 30 29 30 384 -1975 */{ 0 , 2 , 11 , 53840 },/* 30 30 29 30 29 29 30 29 29 30 29 30 0 354 -1976 */{ 8 , 1 , 31 , 54600 },/* 30 30 29 30 29 30 29 30 29 30 29 29 30 384 -1977 */{ 0 , 2 , 18 , 46400 },/* 30 29 30 30 29 30 29 30 29 30 29 29 0 354 -1978 */{ 0 , 2 , 7 , 54944 },/* 30 30 29 30 29 30 30 29 30 29 30 29 0 355 -1979 */{ 6 , 1 , 28 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 29 384 -1980 */{ 0 , 2 , 16 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355 -1981 */{ 0 , 2 , 5 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354 -1982 */{ 4 , 1 , 25 , 42200 },/* 30 29 30 29 29 30 29 29 30 30 29 30 30 384 -1983 */{ 0 , 2 , 13 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354 -1984 */{ 10 , 2 , 2 , 45656 },/* 30 29 30 30 29 29 30 29 29 30 29 30 30 384 -1985 */{ 0 , 2 , 20 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 0 354 -1986 */{ 0 , 2 , 9 , 27968 },/* 29 30 30 29 30 30 29 30 29 30 29 29 0 354 -1987 */{ 6 , 1 , 29 , 46504 },/* 30 29 30 30 29 30 29 30 30 29 30 29 30 385 -1988 */{ 0 , 2 , 18 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354 -1989 */{ 0 , 2 , 6 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355 -1990 */{ 5 , 1 , 27 , 18872 },/* 29 30 29 29 30 29 29 30 30 29 30 30 30 384 -1991 */{ 0 , 2 , 15 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354 -1992 */{ 0 , 2 , 4 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 0 354 -1993 */{ 3 , 1 , 23 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 29 383 -1994 */{ 0 , 2 , 10 , 59984 },/* 30 30 30 29 30 29 30 29 29 30 29 30 0 355 -1995 */{ 8 , 1 , 31 , 27976 },/* 29 30 30 29 30 30 29 30 29 30 29 29 30 384 -1996 */{ 0 , 2 , 19 , 23248 },/* 29 30 29 30 30 29 30 29 30 30 29 30 0 355 -1997 */{ 0 , 2 , 8 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354 -1998 */{ 5 , 1 , 28 , 37744 },/* 30 29 29 30 29 29 30 30 29 30 30 30 29 384 -1999 */{ 0 , 2 , 16 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354 -2000 */{ 0 , 2 , 5 , 51552 },/* 30 30 29 29 30 29 29 30 29 30 30 29 0 354 -2001 */{ 4 , 1 , 24 , 58536 },/* 30 30 30 29 29 30 29 29 30 29 30 29 30 384 -2002 */{ 0 , 2 , 12 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354 -2003 */{ 0 , 2 , 1 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 0 355 -2004 */{ 2 , 1 , 22 , 23208 },/* 29 30 29 30 30 29 30 29 30 29 30 29 30 384 -2005 */{ 0 , 2 , 9 , 22208 },/* 29 30 29 30 29 30 30 29 30 30 29 29 0 354 -2006 */{ 7 , 1 , 29 , 43736 },/* 30 29 30 29 30 29 30 29 30 30 29 30 30 385 -2007 */{ 0 , 2 , 18 , 9680 },/* 29 29 30 29 29 30 29 30 30 30 29 30 0 354 -2008 */{ 0 , 2 , 7 , 37584 },/* 30 29 29 30 29 29 30 29 30 30 29 30 0 354 -2009 */{ 5 , 1 , 26 , 51544 },/* 30 30 29 29 30 29 29 30 29 30 29 30 30 384 -2010 */{ 0 , 2 , 14 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354 -2011 */{ 0 , 2 , 3 , 46240 },/* 30 29 30 30 29 30 29 29 30 29 30 29 0 354 -2012 */{ 3 , 1 , 23 , 47696 },/* 30 29 30 30 30 29 30 29 29 30 29 30 29 384 -2013 */{ 0 , 2 , 10 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355 -2014 */{ 9 , 1 , 31 , 21928 },/* 29 30 29 30 29 30 29 30 30 29 30 29 30 384 -2015 */{ 0 , 2 , 19 , 19360 },/* 29 30 29 29 30 29 30 30 30 29 30 29 0 354 -2016 */{ 0 , 2 , 8 , 42416 },/* 30 29 30 29 29 30 29 30 30 29 30 30 0 355 -2017 */{ 5 , 1 , 28 , 21176 },/* 29 30 29 30 29 29 30 29 30 29 30 30 30 384 -2018 */{ 0 , 2 , 16 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354 -2019 */{ 0 , 2 , 5 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354 -2020 */{ 4 , 1 , 25 , 46248 },/* 30 29 30 30 29 30 29 29 30 29 30 29 30 384 -2021 */{ 0 , 2 , 12 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354 -2022 */{ 0 , 2 , 1 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355 -2023 */{ 2 , 1 , 22 , 21928 },/* 29 30 29 30 29 30 29 30 30 29 30 29 30 384 -2024 */{ 0 , 2 , 10 , 19296 },/* 29 30 29 29 30 29 30 30 29 30 30 29 0 354 -2025 */{ 6 , 1 , 29 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 29 384 -2026 */{ 0 , 2 , 17 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355 -2027 */{ 0 , 2 , 7 , 21104 },/* 29 30 29 30 29 29 30 29 29 30 30 30 0 354 -2028 */{ 5 , 1 , 27 , 26928 },/* 29 30 30 29 30 29 29 30 29 29 30 30 29 383 -2029 */{ 0 , 2 , 13 , 55600 },/* 30 30 29 30 30 29 29 30 29 29 30 30 0 355 -2030 */{ 0 , 2 , 3 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354 -2031 */{ 3 , 1 , 23 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 29 384 -2032 */{ 0 , 2 , 11 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 0 355 -2033 */{ 11 , 1 , 31 , 19176 },/* 29 30 29 29 30 29 30 29 30 30 30 29 30 384 -2034 */{ 0 , 2 , 19 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354 -2035 */{ 0 , 2 , 8 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354 -2036 */{ 6 , 1 , 28 , 53864 },/* 30 30 29 30 29 29 30 29 29 30 30 29 30 384 -2037 */{ 0 , 2 , 15 , 53840 },/* 30 30 29 30 29 29 30 29 29 30 29 30 0 354 -2038 */{ 0 , 2 , 4 , 54560 },/* 30 30 29 30 29 30 29 30 29 29 30 29 0 354 -2039 */{ 5 , 1 , 24 , 55968 },/* 30 30 29 30 30 29 30 29 30 29 30 29 29 384 -2040 */{ 0 , 2 , 12 , 46752 },/* 30 29 30 30 29 30 30 29 30 29 30 29 0 355 -2041 */{ 0 , 2 , 1 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 0 355 -2042 */{ 2 , 1 , 22 , 19160 },/* 29 30 29 29 30 29 30 29 30 30 29 30 30 384 -2043 */{ 0 , 2 , 10 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354 -2044 */{ 7 , 1 , 30 , 42168 },/* 30 29 30 29 29 30 29 29 30 29 30 30 30 384 -2045 */{ 0 , 2 , 17 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354 -2046 */{ 0 , 2 , 6 , 45648 },/* 30 29 30 30 29 29 30 29 29 30 29 30 0 354 -2047 */{ 5 , 1 , 26 , 46376 },/* 30 29 30 30 29 30 29 30 29 29 30 29 30 384 -2048 */{ 0 , 2 , 14 , 27968 },/* 29 30 30 29 30 30 29 30 29 30 29 29 0 354 -2049 */{ 0 , 2 , 2 , 44448 },/* 30 29 30 29 30 30 29 30 30 29 30 29 0 355 - */ }; - - internal override int MinCalendarYear - { - get - { - return (MIN_LUNISOLAR_YEAR); - } - } - - internal override int MaxCalendarYear - { - get - { - return (MAX_LUNISOLAR_YEAR); - } - } - - internal override DateTime MinDate - { - get - { - return (minDate); - } - } - - internal override DateTime MaxDate - { - get - { - return (maxDate); - } - } - - internal override EraInfo[] CalEraInfo - { - get - { - return (JapaneseCalendar.GetEraInfo()); - } - } - - internal override int GetYearInfo(int lunarYear, int index) - { - if ((lunarYear < MIN_LUNISOLAR_YEAR) || (lunarYear > MAX_LUNISOLAR_YEAR)) - { - throw new ArgumentOutOfRangeException( - "year", - String.Format( - CultureInfo.CurrentCulture, - SR.ArgumentOutOfRange_Range, - MIN_LUNISOLAR_YEAR, - MAX_LUNISOLAR_YEAR)); - } - Contract.EndContractBlock(); - - return s_yinfo[lunarYear - MIN_LUNISOLAR_YEAR, index]; - } - - internal override int GetYear(int year, DateTime time) - { - return helper.GetYear(year, time); - } - - internal override int GetGregorianYear(int year, int era) - { - return helper.GetGregorianYear(year, era); - } - - // Trim off the eras that are before our date range - private static EraInfo[] TrimEras(EraInfo[] baseEras) - { - EraInfo[] newEras = new EraInfo[baseEras.Length]; - int newIndex = 0; - - // Eras have most recent first, so start with that - for (int i = 0; i < baseEras.Length; i++) - { - // If this one's minimum year is bigger than our maximum year - // then we can't use it. - if (baseEras[i].yearOffset + baseEras[i].minEraYear >= MAX_LUNISOLAR_YEAR) - { - // skip this one. - continue; - } - - // If this one's maximum era is less than our minimum era - // then we've gotten too low in the era #s, so we're done - if (baseEras[i].yearOffset + baseEras[i].maxEraYear < MIN_LUNISOLAR_YEAR) - { - break; - } - - // Wasn't too large or too small, can use this one - newEras[newIndex] = baseEras[i]; - newIndex++; - } - - // If we didn't copy any then something was wrong, just return base - if (newIndex == 0) return baseEras; - - // Resize the output array - Array.Resize(ref newEras, newIndex); - return newEras; - } - - - // Construct an instance of JapaneseLunisolar calendar. - public JapaneseLunisolarCalendar() - { - helper = new GregorianCalendarHelper(this, TrimEras(JapaneseCalendar.GetEraInfo())); - } - - - public override int GetEra(DateTime time) - { - return (helper.GetEra(time)); - } - - internal override CalendarId BaseCalendarID - { - get - { - return (CalendarId.JAPAN); - } - } - - internal override CalendarId ID - { - get - { - return (CalendarId.JAPANESELUNISOLAR); - } - } - - - public override int[] Eras - { - get - { - return (helper.Eras); - } - } - } -} diff --git a/src/mscorlib/corefx/System/Globalization/JulianCalendar.cs b/src/mscorlib/corefx/System/Globalization/JulianCalendar.cs deleted file mode 100644 index 43e6ad0..0000000 --- a/src/mscorlib/corefx/System/Globalization/JulianCalendar.cs +++ /dev/null @@ -1,444 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.Diagnostics.Contracts; - -namespace System.Globalization -{ - // - // This class implements the Julian calendar. In 48 B.C. Julius Caesar ordered a calendar reform, and this calendar - // is called Julian calendar. It consisted of a solar year of twelve months and of 365 days with an extra day - // every fourth year. - //* - //* Calendar support range: - //* Calendar Minimum Maximum - //* ========== ========== ========== - //* Gregorian 0001/01/01 9999/12/31 - //* Julia 0001/01/03 9999/10/19 - - [Serializable] - public class JulianCalendar : Calendar - { - public static readonly int JulianEra = 1; - - private const int DatePartYear = 0; - private const int DatePartDayOfYear = 1; - private const int DatePartMonth = 2; - private const int DatePartDay = 3; - - // Number of days in a non-leap year - private const int JulianDaysPerYear = 365; - // Number of days in 4 years - private const int JulianDaysPer4Years = JulianDaysPerYear * 4 + 1; - - private static readonly int[] s_daysToMonth365 = - { - 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 - }; - - private static readonly int[] s_daysToMonth366 = - { - 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 - }; - - // Gregorian Calendar 9999/12/31 = Julian Calendar 9999/10/19 - // keep it as variable field for serialization compat. - internal int MaxYear = 9999; - - - public override DateTime MinSupportedDateTime - { - get - { - return (DateTime.MinValue); - } - } - - public override DateTime MaxSupportedDateTime - { - get - { - return (DateTime.MaxValue); - } - } - - public override CalendarAlgorithmType AlgorithmType - { - get - { - return CalendarAlgorithmType.SolarCalendar; - } - } - - public JulianCalendar() - { - // There is no system setting of TwoDigitYear max, so set the value here. - twoDigitYearMax = 2029; - } - - internal override CalendarId ID - { - get - { - return CalendarId.JULIAN; - } - } - - internal static void CheckEraRange(int era) - { - if (era != CurrentEra && era != JulianEra) - { - throw new ArgumentOutOfRangeException(nameof(era), SR.ArgumentOutOfRange_InvalidEraValue); - } - } - - internal void CheckYearEraRange(int year, int era) - { - CheckEraRange(era); - if (year <= 0 || year > MaxYear) - { - throw new ArgumentOutOfRangeException( - nameof(year), - String.Format( - CultureInfo.CurrentCulture, - SR.ArgumentOutOfRange_Range, - 1, - MaxYear)); - } - } - - internal static void CheckMonthRange(int month) - { - if (month < 1 || month > 12) - { - throw new ArgumentOutOfRangeException(nameof(month), SR.ArgumentOutOfRange_Month); - } - } - - /*===================================CheckDayRange============================ - **Action: Check for if the day value is valid. - **Returns: - **Arguments: - **Exceptions: - **Notes: - ** Before calling this method, call CheckYearEraRange()/CheckMonthRange() to make - ** sure year/month values are correct. - ============================================================================*/ - - internal static void CheckDayRange(int year, int month, int day) - { - if (year == 1 && month == 1) - { - // The mimimum supported Julia date is Julian 0001/01/03. - if (day < 3) - { - throw new ArgumentOutOfRangeException(null, - SR.ArgumentOutOfRange_BadYearMonthDay); - } - } - bool isLeapYear = (year % 4) == 0; - int[] days = isLeapYear ? s_daysToMonth366 : s_daysToMonth365; - int monthDays = days[month] - days[month - 1]; - if (day < 1 || day > monthDays) - { - throw new ArgumentOutOfRangeException( - nameof(day), - String.Format( - CultureInfo.CurrentCulture, - SR.ArgumentOutOfRange_Range, - 1, - monthDays)); - } - } - - - // Returns a given date part of this DateTime. This method is used - // to compute the year, day-of-year, month, or day part. - internal static int GetDatePart(long ticks, int part) - { - // Gregorian 1/1/0001 is Julian 1/3/0001. Remember DateTime(0) is refered to Gregorian 1/1/0001. - // The following line convert Gregorian ticks to Julian ticks. - long julianTicks = ticks + TicksPerDay * 2; - // n = number of days since 1/1/0001 - int n = (int)(julianTicks / TicksPerDay); - // y4 = number of whole 4-year periods within 100-year period - int y4 = n / JulianDaysPer4Years; - // n = day number within 4-year period - n -= y4 * JulianDaysPer4Years; - // y1 = number of whole years within 4-year period - int y1 = n / JulianDaysPerYear; - // Last year has an extra day, so decrement result if 4 - if (y1 == 4) y1 = 3; - // If year was requested, compute and return it - if (part == DatePartYear) - { - return (y4 * 4 + y1 + 1); - } - // n = day number within year - n -= y1 * JulianDaysPerYear; - // If day-of-year was requested, return it - if (part == DatePartDayOfYear) - { - return (n + 1); - } - // Leap year calculation looks different from IsLeapYear since y1, y4, - // and y100 are relative to year 1, not year 0 - bool leapYear = (y1 == 3); - int[] days = leapYear ? s_daysToMonth366 : s_daysToMonth365; - // All months have less than 32 days, so n >> 5 is a good conservative - // estimate for the month - int m = (n >> 5) + 1; - // m = 1-based month number - while (n >= days[m]) m++; - // If month was requested, return it - if (part == DatePartMonth) return (m); - // Return 1-based day-of-month - return (n - days[m - 1] + 1); - } - - // Returns the tick count corresponding to the given year, month, and day. - internal static long DateToTicks(int year, int month, int day) - { - int[] days = (year % 4 == 0) ? s_daysToMonth366 : s_daysToMonth365; - int y = year - 1; - int n = y * 365 + y / 4 + days[month - 1] + day - 1; - // Gregorian 1/1/0001 is Julian 1/3/0001. n * TicksPerDay is the ticks in JulianCalendar. - // Therefore, we subtract two days in the following to convert the ticks in JulianCalendar - // to ticks in Gregorian calendar. - return ((n - 2) * TicksPerDay); - } - - - public override DateTime AddMonths(DateTime time, int months) - { - if (months < -120000 || months > 120000) - { - throw new ArgumentOutOfRangeException( - nameof(months), - String.Format( - CultureInfo.CurrentCulture, - SR.ArgumentOutOfRange_Range, - -120000, - 120000)); - } - Contract.EndContractBlock(); - int y = GetDatePart(time.Ticks, DatePartYear); - int m = GetDatePart(time.Ticks, DatePartMonth); - int d = GetDatePart(time.Ticks, DatePartDay); - int i = m - 1 + months; - if (i >= 0) - { - m = i % 12 + 1; - y = y + i / 12; - } - else - { - m = 12 + (i + 1) % 12; - y = y + (i - 11) / 12; - } - int[] daysArray = (y % 4 == 0 && (y % 100 != 0 || y % 400 == 0)) ? s_daysToMonth366 : s_daysToMonth365; - int days = (daysArray[m] - daysArray[m - 1]); - - if (d > days) - { - d = days; - } - long ticks = DateToTicks(y, m, d) + time.Ticks % TicksPerDay; - Calendar.CheckAddResult(ticks, MinSupportedDateTime, MaxSupportedDateTime); - return (new DateTime(ticks)); - } - - - public override DateTime AddYears(DateTime time, int years) - { - return (AddMonths(time, years * 12)); - } - - - public override int GetDayOfMonth(DateTime time) - { - return (GetDatePart(time.Ticks, DatePartDay)); - } - - - public override DayOfWeek GetDayOfWeek(DateTime time) - { - return ((DayOfWeek)((int)(time.Ticks / TicksPerDay + 1) % 7)); - } - - - public override int GetDayOfYear(DateTime time) - { - return (GetDatePart(time.Ticks, DatePartDayOfYear)); - } - - - public override int GetDaysInMonth(int year, int month, int era) - { - CheckYearEraRange(year, era); - CheckMonthRange(month); - int[] days = (year % 4 == 0) ? s_daysToMonth366 : s_daysToMonth365; - return (days[month] - days[month - 1]); - } - - - public override int GetDaysInYear(int year, int era) - { - // Year/Era range is done in IsLeapYear(). - return (IsLeapYear(year, era) ? 366 : 365); - } - - - public override int GetEra(DateTime time) - { - return (JulianEra); - } - - - public override int GetMonth(DateTime time) - { - return (GetDatePart(time.Ticks, DatePartMonth)); - } - - - public override int[] Eras - { - get - { - return (new int[] { JulianEra }); - } - } - - - public override int GetMonthsInYear(int year, int era) - { - CheckYearEraRange(year, era); - return (12); - } - - - public override int GetYear(DateTime time) - { - return (GetDatePart(time.Ticks, DatePartYear)); - } - - - public override bool IsLeapDay(int year, int month, int day, int era) - { - CheckMonthRange(month); - // Year/Era range check is done in IsLeapYear(). - if (IsLeapYear(year, era)) - { - CheckDayRange(year, month, day); - return (month == 2 && day == 29); - } - CheckDayRange(year, month, day); - return (false); - } - - // Returns the leap month in a calendar year of the specified era. This method returns 0 - // if this calendar does not have leap month, or this year is not a leap year. - // - - public override int GetLeapMonth(int year, int era) - { - CheckYearEraRange(year, era); - return (0); - } - - - public override bool IsLeapMonth(int year, int month, int era) - { - CheckYearEraRange(year, era); - CheckMonthRange(month); - return (false); - } - - // Checks whether a given year in the specified era is a leap year. This method returns true if - // year is a leap year, or false if not. - // - - public override bool IsLeapYear(int year, int era) - { - CheckYearEraRange(year, era); - return (year % 4 == 0); - } - - - public override DateTime ToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era) - { - CheckYearEraRange(year, era); - CheckMonthRange(month); - CheckDayRange(year, month, day); - if (millisecond < 0 || millisecond >= MillisPerSecond) - { - throw new ArgumentOutOfRangeException( - nameof(millisecond), - String.Format( - CultureInfo.CurrentCulture, - SR.ArgumentOutOfRange_Range, - 0, - MillisPerSecond - 1)); - } - - if (hour >= 0 && hour < 24 && minute >= 0 && minute < 60 && second >= 0 && second < 60) - { - return new DateTime(DateToTicks(year, month, day) + (new TimeSpan(0, hour, minute, second, millisecond)).Ticks); - } - else - { - throw new ArgumentOutOfRangeException(null, SR.ArgumentOutOfRange_BadHourMinuteSecond); - } - } - - - public override int TwoDigitYearMax - { - get - { - return (twoDigitYearMax); - } - - set - { - VerifyWritable(); - if (value < 99 || value > MaxYear) - { - throw new ArgumentOutOfRangeException( - "year", - String.Format( - CultureInfo.CurrentCulture, - SR.ArgumentOutOfRange_Range, - 99, - MaxYear)); - } - twoDigitYearMax = value; - } - } - - - public override int ToFourDigitYear(int year) - { - if (year < 0) - { - throw new ArgumentOutOfRangeException(nameof(year), - SR.ArgumentOutOfRange_NeedNonNegNum); - } - Contract.EndContractBlock(); - - if (year > MaxYear) - { - throw new ArgumentOutOfRangeException( - nameof(year), - String.Format( - CultureInfo.CurrentCulture, - SR.ArgumentOutOfRange_Bounds_Lower_Upper, - 1, - MaxYear)); - } - return (base.ToFourDigitYear(year)); - } - } -} diff --git a/src/mscorlib/corefx/System/Globalization/KoreanCalendar.cs b/src/mscorlib/corefx/System/Globalization/KoreanCalendar.cs deleted file mode 100644 index b015aa0..0000000 --- a/src/mscorlib/corefx/System/Globalization/KoreanCalendar.cs +++ /dev/null @@ -1,267 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.Diagnostics.CodeAnalysis; -using System.Diagnostics.Contracts; - -namespace System.Globalization -{ - /*=================================KoreanCalendar========================== - ** - ** Korean calendar is based on the Gregorian calendar. And the year is an offset to Gregorian calendar. - ** That is, - ** Korean year = Gregorian year + 2333. So 2000/01/01 A.D. is Korean 4333/01/01 - ** - ** 0001/1/1 A.D. is Korean year 2334. - ** - ** Calendar support range: - ** Calendar Minimum Maximum - ** ========== ========== ========== - ** Gregorian 0001/01/01 9999/12/31 - ** Korean 2334/01/01 12332/12/31 - ============================================================================*/ - - - [Serializable] - public class KoreanCalendar : Calendar - { - // - // The era value for the current era. - // - - public const int KoreanEra = 1; - - // Since - // Gregorian Year = Era Year + yearOffset - // Gregorian Year 1 is Korean year 2334, so that - // 1 = 2334 + yearOffset - // So yearOffset = -2333 - // Gregorian year 2001 is Korean year 4334. - - //m_EraInfo[0] = new EraInfo(1, new DateTime(1, 1, 1).Ticks, -2333, 2334, GregorianCalendar.MaxYear + 2333); - - // Initialize our era info. - internal static EraInfo[] koreanEraInfo = new EraInfo[] { - new EraInfo( 1, 1, 1, 1, -2333, 2334, GregorianCalendar.MaxYear + 2333) // era #, start year/month/day, yearOffset, minEraYear - }; - - internal GregorianCalendarHelper helper; - - - public override DateTime MinSupportedDateTime - { - get - { - return (DateTime.MinValue); - } - } - - public override DateTime MaxSupportedDateTime - { - get - { - return (DateTime.MaxValue); - } - } - - public override CalendarAlgorithmType AlgorithmType - { - get - { - return CalendarAlgorithmType.SolarCalendar; - } - } - - public KoreanCalendar() - { - try - { - new CultureInfo("ko-KR"); - } - catch (ArgumentException e) - { - throw new TypeInitializationException(this.GetType().ToString(), e); - } - helper = new GregorianCalendarHelper(this, koreanEraInfo); - } - - internal override CalendarId ID - { - get - { - return CalendarId.KOREA; - } - } - - - public override DateTime AddMonths(DateTime time, int months) - { - return (helper.AddMonths(time, months)); - } - - - public override DateTime AddYears(DateTime time, int years) - { - return (helper.AddYears(time, years)); - } - - /*=================================GetDaysInMonth========================== - **Action: Returns the number of days in the month given by the year and month arguments. - **Returns: The number of days in the given month. - **Arguments: - ** year The year in Korean calendar. - ** month The month - ** era The Japanese era value. - **Exceptions - ** ArgumentException If month is less than 1 or greater * than 12. - ============================================================================*/ - - - public override int GetDaysInMonth(int year, int month, int era) - { - return (helper.GetDaysInMonth(year, month, era)); - } - - - public override int GetDaysInYear(int year, int era) - { - return (helper.GetDaysInYear(year, era)); - } - - - public override int GetDayOfMonth(DateTime time) - { - return (helper.GetDayOfMonth(time)); - } - - - public override DayOfWeek GetDayOfWeek(DateTime time) - { - return (helper.GetDayOfWeek(time)); - } - - - public override int GetDayOfYear(DateTime time) - { - return (helper.GetDayOfYear(time)); - } - - - public override int GetMonthsInYear(int year, int era) - { - return (helper.GetMonthsInYear(year, era)); - } - - - [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems. - public override int GetWeekOfYear(DateTime time, CalendarWeekRule rule, DayOfWeek firstDayOfWeek) - { - return (helper.GetWeekOfYear(time, rule, firstDayOfWeek)); - } - - - public override int GetEra(DateTime time) - { - return (helper.GetEra(time)); - } - - public override int GetMonth(DateTime time) - { - return (helper.GetMonth(time)); - } - - - public override int GetYear(DateTime time) - { - return (helper.GetYear(time)); - } - - - public override bool IsLeapDay(int year, int month, int day, int era) - { - return (helper.IsLeapDay(year, month, day, era)); - } - - - public override bool IsLeapYear(int year, int era) - { - return (helper.IsLeapYear(year, era)); - } - - // Returns the leap month in a calendar year of the specified era. This method returns 0 - // if this calendar does not have leap month, or this year is not a leap year. - // - - public override int GetLeapMonth(int year, int era) - { - return (helper.GetLeapMonth(year, era)); - } - - - public override bool IsLeapMonth(int year, int month, int era) - { - return (helper.IsLeapMonth(year, month, era)); - } - - - public override DateTime ToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era) - { - return (helper.ToDateTime(year, month, day, hour, minute, second, millisecond, era)); - } - - - public override int[] Eras - { - get - { - return (helper.Eras); - } - } - - private const int DEFAULT_TWO_DIGIT_YEAR_MAX = 4362; - - - public override int TwoDigitYearMax - { - get - { - if (twoDigitYearMax == -1) - { - twoDigitYearMax = GetSystemTwoDigitYearSetting(ID, DEFAULT_TWO_DIGIT_YEAR_MAX); - } - return (twoDigitYearMax); - } - - set - { - VerifyWritable(); - if (value < 99 || value > helper.MaxYear) - { - throw new ArgumentOutOfRangeException( - "year", - String.Format( - CultureInfo.CurrentCulture, - SR.ArgumentOutOfRange_Range, - 99, - helper.MaxYear)); - } - twoDigitYearMax = value; - } - } - - - public override int ToFourDigitYear(int year) - { - if (year < 0) - { - throw new ArgumentOutOfRangeException(nameof(year), - SR.ArgumentOutOfRange_NeedNonNegNum); - } - Contract.EndContractBlock(); - - return (helper.ToFourDigitYear(year, this.TwoDigitYearMax)); - } - } -} diff --git a/src/mscorlib/corefx/System/Globalization/KoreanLunisolarCalendar.cs b/src/mscorlib/corefx/System/Globalization/KoreanLunisolarCalendar.cs deleted file mode 100644 index 6d09128..0000000 --- a/src/mscorlib/corefx/System/Globalization/KoreanLunisolarCalendar.cs +++ /dev/null @@ -1,1329 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.Diagnostics.Contracts; - -namespace System.Globalization -{ - //////////////////////////////////////////////////////////////////////////// - // - // Notes about KoreanLunisolarCalendar - // - //////////////////////////////////////////////////////////////////////////// - /* - ** Calendar support range: - ** Calendar Minimum Maximum - ** ========== ========== ========== - ** Gregorian 918/02/14 2051/02/10 - ** KoreanLunisolar 918/01/01 2050/13/29 - */ - - [Serializable] - public class KoreanLunisolarCalendar : EastAsianLunisolarCalendar - { - // - // The era value for the current era. - // - - public const int GregorianEra = 1; - - internal const int MIN_LUNISOLAR_YEAR = 918; - internal const int MAX_LUNISOLAR_YEAR = 2050; - - internal const int MIN_GREGORIAN_YEAR = 918; - internal const int MIN_GREGORIAN_MONTH = 2; - internal const int MIN_GREGORIAN_DAY = 14; - - internal const int MAX_GREGORIAN_YEAR = 2051; - internal const int MAX_GREGORIAN_MONTH = 2; - internal const int MAX_GREGORIAN_DAY = 10; - - internal static DateTime minDate = new DateTime(MIN_GREGORIAN_YEAR, MIN_GREGORIAN_MONTH, MIN_GREGORIAN_DAY); - internal static DateTime maxDate = new DateTime((new DateTime(MAX_GREGORIAN_YEAR, MAX_GREGORIAN_MONTH, MAX_GREGORIAN_DAY, 23, 59, 59, 999)).Ticks + 9999); - - public override DateTime MinSupportedDateTime - { - get - { - return (minDate); - } - } - - - - public override DateTime MaxSupportedDateTime - { - get - { - return (maxDate); - } - } - - protected override int DaysInYearBeforeMinSupportedYear - { - get - { - // 917 -- From http://emr.cs.iit.edu/home/reingold/calendar-book/Calendrica.html - // using ChineseLunisolar - return 384; - } - } - - private static readonly int[,] s_yinfo = - { - /*Y LM Lmon Lday DaysPerMonth D1 D2 D3 D4 D5 D6 D7 D8 D9 D10 D11 D12 D13 #Days - 918 */ - { 0 , 2 , 14 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 0 355 -919 */{ 0 , 2 , 4 , 17872 },/* 29 30 29 29 29 30 29 30 30 30 29 30 0 354 -920 */{ 6 , 1 , 24 , 41688 },/* 30 29 30 29 29 29 30 29 30 30 29 30 30 384 -921 */{ 0 , 2 , 11 , 41648 },/* 30 29 30 29 29 29 30 29 30 29 30 30 0 354 -922 */{ 0 , 1 , 31 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354 -923 */{ 4 , 1 , 20 , 46248 },/* 30 29 30 30 29 30 29 29 30 29 30 29 30 384 -924 */{ 0 , 2 , 8 , 27936 },/* 29 30 30 29 30 30 29 30 29 29 30 29 0 354 -925 */{ 12 , 1 , 27 , 44384 },/* 30 29 30 29 30 30 29 30 29 30 30 29 29 384 -926 */{ 0 , 2 , 15 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 0 355 -927 */{ 0 , 2 , 5 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 0 355 -928 */{ 8 , 1 , 26 , 17848 },/* 29 30 29 29 29 30 29 30 30 29 30 30 30 384 -929 */{ 0 , 2 , 13 , 17776 },/* 29 30 29 29 29 30 29 30 29 30 30 30 0 354 -930 */{ 0 , 2 , 2 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354 -931 */{ 5 , 1 , 22 , 26960 },/* 29 30 30 29 30 29 29 30 29 30 29 30 29 383 -932 */{ 0 , 2 , 9 , 59728 },/* 30 30 30 29 30 29 29 30 29 30 29 30 0 355 -933 */{ 0 , 1 , 29 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354 -934 */{ 1 , 1 , 18 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 29 384 -935 */{ 0 , 2 , 6 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 0 355 -936 */{ 11 , 1 , 27 , 21344 },/* 29 30 29 30 29 29 30 30 29 30 30 29 29 383 -937 */{ 0 , 2 , 13 , 51904 },/* 30 30 29 29 30 29 30 29 30 30 29 29 0 354 -938 */{ 0 , 2 , 2 , 58720 },/* 30 30 30 29 29 30 29 30 29 30 30 29 0 355 -939 */{ 7 , 1 , 23 , 53928 },/* 30 30 29 30 29 29 30 29 30 29 30 29 30 384 -940 */{ 0 , 2 , 11 , 53920 },/* 30 30 29 30 29 29 30 29 30 29 30 29 0 354 -941 */{ 0 , 1 , 30 , 55632 },/* 30 30 29 30 30 29 29 30 29 30 29 30 0 355 -942 */{ 3 , 1 , 20 , 23208 },/* 29 30 29 30 30 29 30 29 30 29 30 29 30 384 -943 */{ 0 , 2 , 8 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354 -944 */{ 12 , 1 , 28 , 42704 },/* 30 29 30 29 29 30 30 29 30 30 29 30 29 384 -945 */{ 0 , 2 , 15 , 38352 },/* 30 29 29 30 29 30 29 30 30 30 29 30 0 355 -946 */{ 0 , 2 , 5 , 19152 },/* 29 30 29 29 30 29 30 29 30 30 29 30 0 354 -947 */{ 7 , 1 , 25 , 42200 },/* 30 29 30 29 29 30 29 29 30 30 29 30 30 384 -948 */{ 0 , 2 , 13 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354 -949 */{ 0 , 2 , 1 , 45664 },/* 30 29 30 30 29 29 30 29 29 30 30 29 0 354 -950 */{ 5 , 1 , 21 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 29 384 -951 */{ 0 , 2 , 9 , 45936 },/* 30 29 30 30 29 30 29 30 29 30 29 0 0 325 -952 */{ 0 , 12 , 31 , 43728 },/* 30 29 30 29 30 29 30 29 30 30 29 30 29 384 -953 */{ 1 , 1 , 18 , 38352 },/* 30 29 29 30 29 30 29 30 30 30 29 30 29 384 -954 */{ 0 , 2 , 6 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355 -955 */{ 9 , 1 , 27 , 19128 },/* 29 30 29 29 30 29 30 29 30 29 30 30 30 384 -956 */{ 0 , 2 , 15 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354 -957 */{ 0 , 2 , 3 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354 -958 */{ 7 , 1 , 23 , 43672 },/* 30 29 30 29 30 29 30 29 30 29 29 30 30 384 -959 */{ 0 , 2 , 11 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354 -960 */{ 0 , 1 , 31 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355 -961 */{ 3 , 1 , 20 , 19880 },/* 29 30 29 29 30 30 29 30 30 29 30 29 30 384 -962 */{ 0 , 2 , 8 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354 -963 */{ 12 , 1 , 28 , 38256 },/* 30 29 29 30 29 30 29 30 29 30 30 30 29 384 -964 */{ 0 , 2 , 16 , 41840 },/* 30 29 30 29 29 29 30 30 29 30 30 30 0 355 -965 */{ 0 , 2 , 5 , 20848 },/* 29 30 29 30 29 29 29 30 29 30 30 30 0 354 -966 */{ 8 , 1 , 25 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 29 383 -967 */{ 0 , 2 , 12 , 54448 },/* 30 30 29 30 29 30 29 29 30 29 30 30 0 355 -968 */{ 0 , 2 , 2 , 23184 },/* 29 30 29 30 30 29 30 29 30 29 29 30 0 354 -969 */{ 5 , 1 , 21 , 27472 },/* 29 30 30 29 30 29 30 30 29 30 29 30 29 384 -970 */{ 0 , 2 , 9 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 0 355 -971 */{ 0 , 1 , 30 , 10976 },/* 29 29 30 29 30 29 30 29 30 30 30 29 0 354 -972 */{ 2 , 1 , 19 , 37744 },/* 30 29 29 30 29 29 30 30 29 30 30 30 29 384 -973 */{ 0 , 2 , 6 , 41696 },/* 30 29 30 29 29 29 30 29 30 30 30 29 0 354 -974 */{ 10 , 1 , 26 , 51560 },/* 30 30 29 29 30 29 29 30 29 30 30 29 30 384 -975 */{ 0 , 2 , 14 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354 -976 */{ 0 , 2 , 3 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354 -977 */{ 7 , 1 , 22 , 55952 },/* 30 30 29 30 30 29 30 29 30 29 29 30 29 384 -978 */{ 0 , 2 , 10 , 46496 },/* 30 29 30 30 29 30 29 30 30 29 30 29 0 355 -979 */{ 0 , 1 , 31 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 0 355 -980 */{ 3 , 1 , 21 , 10968 },/* 29 29 30 29 30 29 30 29 30 30 29 30 30 384 -981 */{ 0 , 2 , 8 , 9680 },/* 29 29 30 29 29 30 29 30 30 30 29 30 0 354 -982 */{ 12 , 1 , 28 , 37592 },/* 30 29 29 30 29 29 30 29 30 30 29 30 30 384 -983 */{ 0 , 2 , 16 , 37552 },/* 30 29 29 30 29 29 30 29 30 29 30 30 0 354 -984 */{ 0 , 2 , 5 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354 -985 */{ 9 , 1 , 24 , 46248 },/* 30 29 30 30 29 30 29 29 30 29 30 29 30 384 -986 */{ 0 , 2 , 12 , 44192 },/* 30 29 30 29 30 30 29 29 30 29 30 29 0 354 -987 */{ 0 , 2 , 1 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355 -988 */{ 5 , 1 , 22 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 29 384 -989 */{ 0 , 2 , 9 , 19376 },/* 29 30 29 29 30 29 30 30 30 29 30 30 0 355 -990 */{ 0 , 1 , 30 , 9648 },/* 29 29 30 29 29 30 29 30 30 29 30 30 0 354 -991 */{ 2 , 1 , 19 , 37560 },/* 30 29 29 30 29 29 30 29 30 29 30 30 30 384 -992 */{ 0 , 2 , 7 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354 -993 */{ 10 , 1 , 26 , 26968 },/* 29 30 30 29 30 29 29 30 29 30 29 30 30 384 -994 */{ 0 , 2 , 14 , 22864 },/* 29 30 29 30 30 29 29 30 29 30 29 30 0 354 -995 */{ 0 , 2 , 3 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354 -996 */{ 7 , 1 , 23 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 29 384 -997 */{ 0 , 2 , 10 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 0 355 -998 */{ 0 , 1 , 31 , 19296 },/* 29 30 29 29 30 29 30 30 29 30 30 29 0 354 -999 */{ 3 , 1 , 20 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 29 384 -1000 */{ 0 , 2 , 8 , 9584 },/* 29 29 30 29 29 30 29 30 29 30 30 30 0 354 -1001 */{ 12 , 1 , 28 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 29 383 -1002 */{ 0 , 2 , 15 , 53920 },/* 30 30 29 30 29 29 30 29 30 29 30 29 0 354 -1003 */{ 0 , 2 , 4 , 54608 },/* 30 30 29 30 29 30 29 30 29 30 29 30 0 355 -1004 */{ 9 , 1 , 25 , 23208 },/* 29 30 29 30 30 29 30 29 30 29 30 29 30 384 -1005 */{ 0 , 2 , 12 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354 -1006 */{ 0 , 2 , 1 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 0 355 -1007 */{ 5 , 1 , 22 , 19176 },/* 29 30 29 29 30 29 30 29 30 30 30 29 30 384 -1008 */{ 0 , 2 , 10 , 19152 },/* 29 30 29 29 30 29 30 29 30 30 29 30 0 354 -1009 */{ 0 , 1 , 29 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354 -1010 */{ 2 , 1 , 18 , 53864 },/* 30 30 29 30 29 29 30 29 29 30 30 29 30 384 -1011 */{ 0 , 2 , 6 , 45664 },/* 30 29 30 30 29 29 30 29 29 30 30 29 0 354 -1012 */{ 10 , 1 , 26 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 29 384 -1013 */{ 0 , 2 , 13 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355 -1014 */{ 0 , 2 , 3 , 13728 },/* 29 29 30 30 29 30 29 30 30 29 30 29 0 354 -1015 */{ 6 , 1 , 23 , 38352 },/* 30 29 29 30 29 30 29 30 30 30 29 30 29 384 -1016 */{ 0 , 2 , 11 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355 -1017 */{ 0 , 1 , 31 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354 -1018 */{ 4 , 1 , 20 , 42200 },/* 30 29 30 29 29 30 29 29 30 30 29 30 30 384 -1019 */{ 0 , 2 , 8 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354 -1020 */{ 12 , 1 , 28 , 43608 },/* 30 29 30 29 30 29 30 29 29 30 29 30 30 384 -1021 */{ 0 , 2 , 15 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354 -1022 */{ 0 , 2 , 4 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355 -1023 */{ 9 , 1 , 25 , 11688 },/* 29 29 30 29 30 30 29 30 30 29 30 29 30 384 -1024 */{ 0 , 2 , 13 , 11088 },/* 29 29 30 29 30 29 30 30 29 30 29 30 0 354 -1025 */{ 0 , 2 , 1 , 38256 },/* 30 29 29 30 29 30 29 30 29 30 30 30 0 355 -1026 */{ 5 , 1 , 22 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 29 383 -1027 */{ 0 , 2 , 9 , 51568 },/* 30 30 29 29 30 29 29 30 29 30 30 30 0 355 -1028 */{ 0 , 1 , 30 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 0 354 -1029 */{ 2 , 1 , 18 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 29 383 -1030 */{ 0 , 2 , 5 , 55952 },/* 30 30 29 30 30 29 30 29 30 29 29 30 0 355 -1031 */{ 10 , 1 , 26 , 27472 },/* 29 30 30 29 30 29 30 30 29 30 29 30 29 384 -1032 */{ 0 , 2 , 14 , 26320 },/* 29 30 30 29 29 30 30 29 30 30 29 30 0 355 -1033 */{ 0 , 2 , 3 , 9952 },/* 29 29 30 29 29 30 30 29 30 30 30 29 0 354 -1034 */{ 6 , 1 , 23 , 37744 },/* 30 29 29 30 29 29 30 30 29 30 30 30 29 384 -1035 */{ 0 , 2 , 11 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354 -1036 */{ 0 , 1 , 31 , 51552 },/* 30 30 29 29 30 29 29 30 29 30 30 29 0 354 -1037 */{ 4 , 1 , 19 , 54440 },/* 30 30 29 30 29 30 29 29 30 29 30 29 30 384 -1038 */{ 0 , 2 , 7 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354 -1039 */{ 12 , 1 , 27 , 54928 },/* 30 30 29 30 29 30 30 29 30 29 29 30 29 384 -1040 */{ 0 , 2 , 15 , 46464 },/* 30 29 30 30 29 30 29 30 30 29 29 29 0 354 -1041 */{ 0 , 2 , 3 , 54960 },/* 30 30 29 30 29 30 30 29 30 29 30 30 0 356 -1042 */{ 9 , 1 , 25 , 9944 },/* 29 29 30 29 29 30 30 29 30 30 29 30 30 384 -1043 */{ 0 , 2 , 13 , 9680 },/* 29 29 30 29 29 30 29 30 30 30 29 30 0 354 -1044 */{ 0 , 2 , 2 , 37552 },/* 30 29 29 30 29 29 30 29 30 29 30 30 0 354 -1045 */{ 5 , 1 , 21 , 43352 },/* 30 29 30 29 30 29 29 30 29 30 29 30 30 384 -1046 */{ 0 , 2 , 9 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354 -1047 */{ 0 , 1 , 29 , 46240 },/* 30 29 30 30 29 30 29 29 30 29 30 29 0 354 -1048 */{ 1 , 1 , 18 , 46424 },/* 30 29 30 30 29 30 29 30 29 30 29 30 30 385 -1049 */{ 0 , 2 , 6 , 11600 },/* 29 29 30 29 30 30 29 30 29 30 29 30 0 354 -1050 */{ 11 , 1 , 26 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 29 384 -1051 */{ 0 , 2 , 14 , 19376 },/* 29 30 29 29 30 29 30 30 30 29 30 30 0 355 -1052 */{ 0 , 2 , 4 , 9648 },/* 29 29 30 29 29 30 29 30 30 29 30 30 0 354 -1053 */{ 7 , 1 , 23 , 21176 },/* 29 30 29 30 29 29 30 29 30 29 30 30 30 384 -1054 */{ 0 , 2 , 11 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354 -1055 */{ 0 , 1 , 31 , 26960 },/* 29 30 30 29 30 29 29 30 29 30 29 30 0 354 -1056 */{ 3 , 1 , 20 , 27304 },/* 29 30 30 29 30 29 30 29 30 29 30 29 30 384 -1057 */{ 0 , 2 , 7 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354 -1058 */{ 12 , 1 , 27 , 43864 },/* 30 29 30 29 30 29 30 30 29 30 29 30 30 385 -1059 */{ 0 , 2 , 16 , 10064 },/* 29 29 30 29 29 30 30 30 29 30 29 30 0 354 -1060 */{ 0 , 2 , 5 , 19296 },/* 29 30 29 29 30 29 30 30 29 30 30 29 0 354 -1061 */{ 8 , 1 , 24 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 29 384 -1062 */{ 0 , 2 , 12 , 42336 },/* 30 29 30 29 29 30 29 30 29 30 30 29 0 354 -1063 */{ 0 , 2 , 1 , 53856 },/* 30 30 29 30 29 29 30 29 29 30 30 29 0 354 -1064 */{ 5 , 1 , 21 , 59696 },/* 30 30 30 29 30 29 29 30 29 29 30 30 29 384 -1065 */{ 0 , 2 , 8 , 54608 },/* 30 30 29 30 29 30 29 30 29 30 29 30 0 355 -1066 */{ 0 , 1 , 29 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354 -1067 */{ 1 , 1 , 18 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 29 384 -1068 */{ 0 , 2 , 6 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 0 355 -1069 */{ 11 , 1 , 26 , 19176 },/* 29 30 29 29 30 29 30 29 30 30 30 29 30 384 -1070 */{ 0 , 2 , 14 , 18896 },/* 29 30 29 29 30 29 29 30 30 30 29 30 0 354 -1071 */{ 0 , 2 , 3 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354 -1072 */{ 7 , 1 , 23 , 53864 },/* 30 30 29 30 29 29 30 29 29 30 30 29 30 384 -1073 */{ 0 , 2 , 10 , 43616 },/* 30 29 30 29 30 29 30 29 29 30 30 29 0 354 -1074 */{ 0 , 1 , 30 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355 -1075 */{ 4 , 1 , 20 , 22184 },/* 29 30 29 30 29 30 30 29 30 29 30 29 30 384 -1076 */{ 0 , 2 , 8 , 13728 },/* 29 29 30 30 29 30 29 30 30 29 30 29 0 354 -1077 */{ 0 , 1 , 27 , 38352 },/* 30 29 29 30 29 30 29 30 30 30 29 30 0 355 -1078 */{ 1 , 1 , 17 , 19352 },/* 29 30 29 29 30 29 30 30 30 29 29 30 30 384 -1079 */{ 0 , 2 , 5 , 17840 },/* 29 30 29 29 29 30 29 30 30 29 30 30 0 354 -1080 */{ 9 , 1 , 25 , 42168 },/* 30 29 30 29 29 30 29 29 30 29 30 30 30 384 -1081 */{ 0 , 2 , 12 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 0 354 -1082 */{ 0 , 2 , 1 , 43600 },/* 30 29 30 29 30 29 30 29 29 30 29 30 0 354 -1083 */{ 6 , 1 , 21 , 46408 },/* 30 29 30 30 29 30 29 30 29 30 29 29 30 384 -1084 */{ 0 , 2 , 9 , 27472 },/* 29 30 30 29 30 29 30 30 29 30 29 30 0 355 -1085 */{ 0 , 1 , 29 , 11680 },/* 29 29 30 29 30 30 29 30 30 29 30 29 0 354 -1086 */{ 2 , 1 , 18 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 29 384 -1087 */{ 0 , 2 , 6 , 37744 },/* 30 29 29 30 29 29 30 30 29 30 30 30 0 355 -1088 */{ 12 , 1 , 27 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 29 383 -1089 */{ 0 , 2 , 13 , 51568 },/* 30 30 29 29 30 29 29 30 29 30 30 30 0 355 -1090 */{ 0 , 2 , 3 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 0 354 -1091 */{ 8 , 1 , 23 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 29 383 -1092 */{ 0 , 2 , 10 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 0 355 -1093 */{ 0 , 1 , 30 , 23360 },/* 29 30 29 30 30 29 30 30 29 30 29 29 0 354 -1094 */{ 4 , 1 , 19 , 43880 },/* 30 29 30 29 30 29 30 30 29 30 30 29 30 385 -1095 */{ 0 , 2 , 8 , 10976 },/* 29 29 30 29 30 29 30 29 30 30 30 29 0 354 -1096 */{ 0 , 1 , 28 , 58896 },/* 30 30 30 29 29 30 30 29 29 29 29 30 0 354 -1097 */{ 2 , 1 , 16 , 51568 },/* 30 30 29 29 30 29 29 30 29 30 30 30 29 384 -1098 */{ 0 , 2 , 4 , 51552 },/* 30 30 29 29 30 29 29 30 29 30 30 29 0 354 -1099 */{ 9 , 1 , 24 , 54440 },/* 30 30 29 30 29 30 29 29 30 29 30 29 30 384 -1100 */{ 0 , 2 , 12 , 21664 },/* 29 30 29 30 29 30 29 29 30 29 30 29 0 353 -1101 */{ 0 , 1 , 31 , 54864 },/* 30 30 29 30 29 30 30 29 29 30 29 30 0 355 -1102 */{ 6 , 1 , 21 , 23208 },/* 29 30 29 30 30 29 30 29 30 29 30 29 30 384 -1103 */{ 0 , 2 , 9 , 21968 },/* 29 30 29 30 29 30 29 30 30 30 29 30 0 355 -1104 */{ 0 , 1 , 30 , 9936 },/* 29 29 30 29 29 30 30 29 30 30 29 30 0 354 -1105 */{ 2 , 1 , 18 , 37608 },/* 30 29 29 30 29 29 30 29 30 30 30 29 30 384 -1106 */{ 0 , 2 , 6 , 37552 },/* 30 29 29 30 29 29 30 29 30 29 30 30 0 354 -1107 */{ 10 , 1 , 26 , 43352 },/* 30 29 30 29 30 29 29 30 29 30 29 30 30 384 -1108 */{ 0 , 2 , 14 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354 -1109 */{ 0 , 2 , 2 , 46240 },/* 30 29 30 30 29 30 29 29 30 29 30 29 0 354 -1110 */{ 8 , 1 , 22 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 29 384 -1111 */{ 0 , 2 , 10 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355 -1112 */{ 0 , 1 , 31 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 0 355 -1113 */{ 4 , 1 , 20 , 9656 },/* 29 29 30 29 29 30 29 30 30 29 30 30 30 384 -1114 */{ 0 , 2 , 8 , 17776 },/* 29 30 29 29 29 30 29 30 29 30 30 30 0 354 -1115 */{ 0 , 1 , 28 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354 -1116 */{ 1 , 1 , 17 , 43352 },/* 30 29 30 29 30 29 29 30 29 30 29 30 30 384 -1117 */{ 0 , 2 , 4 , 26960 },/* 29 30 30 29 30 29 29 30 29 30 29 30 0 354 -1118 */{ 9 , 1 , 24 , 29352 },/* 29 30 30 30 29 29 30 29 30 29 30 29 30 384 -1119 */{ 0 , 2 , 12 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354 -1120 */{ 0 , 2 , 1 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 0 355 -1121 */{ 5 , 1 , 21 , 19304 },/* 29 30 29 29 30 29 30 30 29 30 30 29 30 384 -1122 */{ 0 , 2 , 9 , 19296 },/* 29 30 29 29 30 29 30 30 29 30 30 29 0 354 -1123 */{ 0 , 1 , 29 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355 -1124 */{ 3 , 1 , 19 , 21104 },/* 29 30 29 30 29 29 30 29 29 30 30 30 29 383 -1125 */{ 0 , 2 , 5 , 53856 },/* 30 30 29 30 29 29 30 29 29 30 30 29 0 354 -1126 */{ 11 , 1 , 25 , 59696 },/* 30 30 30 29 30 29 29 30 29 29 30 30 29 384 -1127 */{ 0 , 2 , 13 , 54608 },/* 30 30 29 30 29 30 29 30 29 30 29 30 0 355 -1128 */{ 0 , 2 , 3 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354 -1129 */{ 8 , 1 , 22 , 39824 },/* 30 29 29 30 30 29 30 30 30 29 29 30 29 384 -1130 */{ 0 , 2 , 10 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 0 355 -1131 */{ 0 , 1 , 31 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354 -1132 */{ 4 , 1 , 20 , 42216 },/* 30 29 30 29 29 30 29 29 30 30 30 29 30 384 -1133 */{ 0 , 2 , 7 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354 -1134 */{ 0 , 1 , 27 , 53840 },/* 30 30 29 30 29 29 30 29 29 30 29 30 0 354 -1135 */{ 2 , 1 , 16 , 55592 },/* 30 30 29 30 30 29 29 30 29 29 30 29 30 384 -1136 */{ 0 , 2 , 4 , 46400 },/* 30 29 30 30 29 30 29 30 29 30 29 29 0 354 -1137 */{ 10 , 1 , 23 , 54952 },/* 30 30 29 30 29 30 30 29 30 29 30 29 30 385 -1138 */{ 0 , 2 , 12 , 11680 },/* 29 29 30 29 30 30 29 30 30 29 30 29 0 354 -1139 */{ 0 , 2 , 1 , 38352 },/* 30 29 29 30 29 30 29 30 30 30 29 30 0 355 -1140 */{ 6 , 1 , 22 , 19160 },/* 29 30 29 29 30 29 30 29 30 30 29 30 30 384 -1141 */{ 0 , 2 , 9 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354 -1142 */{ 0 , 1 , 29 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354 -1143 */{ 4 , 1 , 18 , 45656 },/* 30 29 30 30 29 29 30 29 29 30 29 30 30 384 -1144 */{ 0 , 2 , 6 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 0 354 -1145 */{ 11 , 1 , 25 , 46376 },/* 30 29 30 30 29 30 29 30 29 29 30 29 30 384 -1146 */{ 0 , 2 , 13 , 27456 },/* 29 30 30 29 30 29 30 30 29 30 29 29 0 354 -1147 */{ 0 , 2 , 2 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 0 355 -1148 */{ 8 , 1 , 23 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 29 384 -1149 */{ 0 , 2 , 10 , 39280 },/* 30 29 29 30 30 29 29 30 29 30 30 30 0 355 -1150 */{ 0 , 1 , 31 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354 -1151 */{ 4 , 1 , 20 , 25784 },/* 29 30 30 29 29 30 29 29 30 29 30 30 30 384 -1152 */{ 0 , 2 , 8 , 21680 },/* 29 30 29 30 29 30 29 29 30 29 30 30 0 354 -1153 */{ 12 , 1 , 27 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 29 383 -1154 */{ 0 , 2 , 14 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 0 355 -1155 */{ 0 , 2 , 4 , 23232 },/* 29 30 29 30 30 29 30 29 30 30 29 29 0 354 -1156 */{ 10 , 1 , 24 , 43880 },/* 30 29 30 29 30 29 30 30 29 30 30 29 30 385 -1157 */{ 0 , 2 , 12 , 9952 },/* 29 29 30 29 29 30 30 29 30 30 30 29 0 354 -1158 */{ 0 , 2 , 1 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354 -1159 */{ 6 , 1 , 21 , 51568 },/* 30 30 29 29 30 29 29 30 29 30 30 30 29 384 -1160 */{ 0 , 2 , 9 , 51552 },/* 30 30 29 29 30 29 29 30 29 30 30 29 0 354 -1161 */{ 0 , 1 , 28 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354 -1162 */{ 2 , 1 , 17 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 29 384 -1163 */{ 0 , 2 , 5 , 54608 },/* 30 30 29 30 29 30 29 30 29 30 29 30 0 355 -1164 */{ 11 , 1 , 26 , 22184 },/* 29 30 29 30 29 30 30 29 30 29 30 29 30 384 -1165 */{ 0 , 2 , 13 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 0 355 -1166 */{ 0 , 2 , 3 , 9680 },/* 29 29 30 29 29 30 29 30 30 30 29 30 0 354 -1167 */{ 7 , 1 , 23 , 37608 },/* 30 29 29 30 29 29 30 29 30 30 30 29 30 384 -1168 */{ 0 , 2 , 11 , 37488 },/* 30 29 29 30 29 29 30 29 29 30 30 30 0 354 -1169 */{ 0 , 1 , 30 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354 -1170 */{ 5 , 1 , 19 , 54440 },/* 30 30 29 30 29 30 29 29 30 29 30 29 30 384 -1171 */{ 0 , 2 , 7 , 46240 },/* 30 29 30 30 29 30 29 29 30 29 30 29 0 354 -1172 */{ 0 , 1 , 27 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355 -1173 */{ 1 , 1 , 16 , 22184 },/* 29 30 29 30 29 30 30 29 30 29 30 29 30 384 -1174 */{ 0 , 2 , 4 , 19888 },/* 29 30 29 29 30 30 29 30 30 29 30 30 0 355 -1175 */{ 9 , 1 , 25 , 9648 },/* 29 29 30 29 29 30 29 30 30 29 30 30 29 383 -1176 */{ 0 , 2 , 12 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355 -1177 */{ 0 , 2 , 1 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354 -1178 */{ 6 , 1 , 21 , 43352 },/* 30 29 30 29 30 29 29 30 29 30 29 30 30 384 -1179 */{ 0 , 2 , 9 , 26960 },/* 29 30 30 29 30 29 29 30 29 30 29 30 0 354 -1180 */{ 0 , 1 , 29 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354 -1181 */{ 3 , 1 , 17 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 29 384 -1182 */{ 0 , 2 , 5 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 0 355 -1183 */{ 11 , 1 , 26 , 19304 },/* 29 30 29 29 30 29 30 30 29 30 30 29 30 384 -1184 */{ 0 , 2 , 14 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354 -1185 */{ 0 , 2 , 2 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355 -1186 */{ 7 , 1 , 23 , 21104 },/* 29 30 29 30 29 29 30 29 29 30 30 30 29 383 -1187 */{ 0 , 2 , 10 , 53392 },/* 30 30 29 30 29 29 30 29 29 30 30 0 0 325 -1188 */{ 0 , 1 , 1 , 29848 },/* 29 30 30 30 29 30 29 29 30 29 29 30 30 384 -1189 */{ 5 , 1 , 19 , 27304 },/* 29 30 30 29 30 29 30 29 30 29 30 29 30 384 -1190 */{ 0 , 2 , 7 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354 -1191 */{ 0 , 1 , 27 , 39760 },/* 30 29 29 30 30 29 30 30 29 30 29 30 0 355 -1192 */{ 2 , 1 , 17 , 19304 },/* 29 30 29 29 30 29 30 30 29 30 30 29 30 384 -1193 */{ 0 , 2 , 4 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354 -1194 */{ 10 , 1 , 24 , 42216 },/* 30 29 30 29 29 30 29 29 30 30 30 29 30 384 -1195 */{ 0 , 2 , 12 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354 -1196 */{ 0 , 2 , 1 , 53856 },/* 30 30 29 30 29 29 30 29 29 30 30 29 0 354 -1197 */{ 6 , 1 , 20 , 54568 },/* 30 30 29 30 29 30 29 30 29 29 30 29 30 384 -1198 */{ 0 , 2 , 8 , 46368 },/* 30 29 30 30 29 30 29 30 29 29 30 29 0 354 -1199 */{ 0 , 1 , 28 , 54944 },/* 30 30 29 30 29 30 30 29 30 29 30 29 0 355 -1200 */{ 2 , 1 , 18 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 29 384 -1201 */{ 0 , 2 , 5 , 38352 },/* 30 29 29 30 29 30 29 30 30 30 29 30 0 355 -1202 */{ 12 , 1 , 26 , 18904 },/* 29 30 29 29 30 29 29 30 30 30 29 30 30 384 -1203 */{ 0 , 2 , 14 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354 -1204 */{ 0 , 2 , 3 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354 -1205 */{ 8 , 1 , 22 , 43608 },/* 30 29 30 29 30 29 30 29 29 30 29 30 30 384 -1206 */{ 0 , 2 , 10 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 0 354 -1207 */{ 0 , 1 , 30 , 46400 },/* 30 29 30 30 29 30 29 30 29 30 29 29 0 354 -1208 */{ 4 , 1 , 19 , 46496 },/* 30 29 30 30 29 30 29 30 30 29 30 29 29 384 -1209 */{ 0 , 2 , 6 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 0 355 -1210 */{ 0 , 1 , 27 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355 -1211 */{ 2 , 1 , 17 , 18872 },/* 29 30 29 29 30 29 29 30 30 29 30 30 30 384 -1212 */{ 0 , 2 , 5 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354 -1213 */{ 9 , 1 , 24 , 25784 },/* 29 30 30 29 29 30 29 29 30 29 30 30 30 384 -1214 */{ 0 , 2 , 12 , 21680 },/* 29 30 29 30 29 30 29 29 30 29 30 30 0 354 -1215 */{ 0 , 2 , 1 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 0 354 -1216 */{ 7 , 1 , 21 , 27944 },/* 29 30 30 29 30 30 29 30 29 29 30 29 30 384 -1217 */{ 0 , 2 , 8 , 23232 },/* 29 30 29 30 30 29 30 29 30 30 29 29 0 354 -1218 */{ 0 , 1 , 28 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 0 355 -1219 */{ 3 , 1 , 18 , 37744 },/* 30 29 29 30 29 29 30 30 29 30 30 30 29 384 -1220 */{ 0 , 2 , 6 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354 -1221 */{ 12 , 1 , 25 , 51568 },/* 30 30 29 29 30 29 29 30 29 30 30 30 29 384 -1222 */{ 0 , 2 , 13 , 51552 },/* 30 30 29 29 30 29 29 30 29 30 30 29 0 354 -1223 */{ 0 , 2 , 2 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354 -1224 */{ 8 , 1 , 22 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 29 384 -1225 */{ 0 , 2 , 9 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355 -1226 */{ 0 , 1 , 30 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354 -1227 */{ 5 , 1 , 19 , 43736 },/* 30 29 30 29 30 29 30 29 30 30 29 30 30 385 -1228 */{ 0 , 2 , 8 , 9680 },/* 29 29 30 29 29 30 29 30 30 30 29 30 0 354 -1229 */{ 0 , 1 , 27 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354 -1230 */{ 2 , 1 , 16 , 51544 },/* 30 30 29 29 30 29 29 30 29 30 29 30 30 384 -1231 */{ 0 , 2 , 4 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354 -1232 */{ 9 , 1 , 24 , 54440 },/* 30 30 29 30 29 30 29 29 30 29 30 29 30 384 -1233 */{ 0 , 2 , 11 , 45728 },/* 30 29 30 30 29 29 30 29 30 29 30 29 0 354 -1234 */{ 0 , 1 , 31 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355 -1235 */{ 7 , 1 , 21 , 22184 },/* 29 30 29 30 29 30 30 29 30 29 30 29 30 384 -1236 */{ 0 , 2 , 9 , 19872 },/* 29 30 29 29 30 30 29 30 30 29 30 29 0 354 -1237 */{ 0 , 1 , 28 , 42416 },/* 30 29 30 29 29 30 29 30 30 29 30 30 0 355 -1238 */{ 4 , 1 , 18 , 21176 },/* 29 30 29 30 29 29 30 29 30 29 30 30 30 384 -1239 */{ 0 , 2 , 6 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354 -1240 */{ 12 , 1 , 26 , 43320 },/* 30 29 30 29 30 29 29 30 29 29 30 30 30 384 -1241 */{ 0 , 2 , 13 , 26928 },/* 29 30 30 29 30 29 29 30 29 29 30 30 0 354 -1242 */{ 0 , 2 , 2 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354 -1243 */{ 8 , 1 , 22 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 29 384 -1244 */{ 0 , 2 , 10 , 44624 },/* 30 29 30 29 30 30 30 29 29 30 29 30 0 355 -1245 */{ 0 , 1 , 30 , 19296 },/* 29 30 29 29 30 29 30 30 29 30 30 29 0 354 -1246 */{ 4 , 1 , 19 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 29 384 -1247 */{ 0 , 2 , 7 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355 -1248 */{ 0 , 1 , 28 , 21104 },/* 29 30 29 30 29 29 30 29 29 30 30 30 0 354 -1249 */{ 2 , 1 , 16 , 26928 },/* 29 30 30 29 30 29 29 30 29 29 30 30 29 383 -1250 */{ 0 , 2 , 3 , 58672 },/* 30 30 30 29 29 30 29 30 29 29 30 30 0 355 -1251 */{ 10 , 1 , 24 , 27800 },/* 29 30 30 29 30 30 29 29 30 29 29 30 30 384 -1252 */{ 0 , 2 , 12 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354 -1253 */{ 0 , 1 , 31 , 23248 },/* 29 30 29 30 30 29 30 29 30 30 29 30 0 355 -1254 */{ 6 , 1 , 21 , 19304 },/* 29 30 29 29 30 29 30 30 29 30 30 29 30 384 -1255 */{ 0 , 2 , 9 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354 -1256 */{ 0 , 1 , 29 , 42208 },/* 30 29 30 29 29 30 29 29 30 30 30 29 0 354 -1257 */{ 4 , 1 , 17 , 53864 },/* 30 30 29 30 29 29 30 29 29 30 30 29 30 384 -1258 */{ 0 , 2 , 5 , 53856 },/* 30 30 29 30 29 29 30 29 29 30 30 29 0 354 -1259 */{ 11 , 1 , 25 , 54568 },/* 30 30 29 30 29 30 29 30 29 29 30 29 30 384 -1260 */{ 0 , 2 , 13 , 46368 },/* 30 29 30 30 29 30 29 30 29 29 30 29 0 354 -1261 */{ 0 , 2 , 1 , 46752 },/* 30 29 30 30 29 30 30 29 30 29 30 29 0 355 -1262 */{ 9 , 1 , 22 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 29 384 -1263 */{ 0 , 2 , 10 , 21872 },/* 29 30 29 30 29 30 29 30 29 30 30 30 0 355 -1264 */{ 0 , 1 , 31 , 18896 },/* 29 30 29 29 30 29 29 30 30 30 29 30 0 354 -1265 */{ 5 , 1 , 19 , 42200 },/* 30 29 30 29 29 30 29 29 30 30 29 30 30 384 -1266 */{ 0 , 2 , 7 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354 -1267 */{ 0 , 1 , 27 , 43600 },/* 30 29 30 29 30 29 30 29 29 30 29 30 0 354 -1268 */{ 1 , 1 , 16 , 46376 },/* 30 29 30 30 29 30 29 30 29 29 30 29 30 384 -1269 */{ 0 , 2 , 3 , 46368 },/* 30 29 30 30 29 30 29 30 29 29 30 29 0 354 -1270 */{ 11 , 1 , 23 , 46528 },/* 30 29 30 30 29 30 29 30 30 30 29 29 29 384 -1271 */{ 0 , 2 , 11 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 0 355 -1272 */{ 0 , 2 , 1 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355 -1273 */{ 6 , 1 , 21 , 18872 },/* 29 30 29 29 30 29 29 30 30 29 30 30 30 384 -1274 */{ 0 , 2 , 9 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354 -1275 */{ 0 , 1 , 29 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 0 354 -1276 */{ 3 , 1 , 18 , 27224 },/* 29 30 30 29 30 29 30 29 29 30 29 30 30 384 -1277 */{ 0 , 2 , 5 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 0 354 -1278 */{ 11 , 1 , 25 , 27432 },/* 29 30 30 29 30 29 30 30 29 29 30 29 30 384 -1279 */{ 0 , 2 , 13 , 23232 },/* 29 30 29 30 30 29 30 29 30 30 29 29 0 354 -1280 */{ 0 , 2 , 2 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 0 355 -1281 */{ 8 , 1 , 22 , 10984 },/* 29 29 30 29 30 29 30 29 30 30 30 29 30 384 -1282 */{ 0 , 2 , 10 , 18912 },/* 29 30 29 29 30 29 29 30 30 30 30 29 0 354 -1283 */{ 0 , 1 , 30 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354 -1284 */{ 5 , 1 , 19 , 53848 },/* 30 30 29 30 29 29 30 29 29 30 29 30 30 384 -1285 */{ 0 , 2 , 6 , 45648 },/* 30 29 30 30 29 29 30 29 29 30 29 30 0 354 -1286 */{ 0 , 1 , 26 , 46368 },/* 30 29 30 30 29 30 29 30 29 29 30 29 0 354 -1287 */{ 2 , 1 , 15 , 62096 },/* 30 30 30 30 29 29 30 29 30 29 29 30 29 384 -1288 */{ 0 , 2 , 3 , 46496 },/* 30 29 30 30 29 30 29 30 30 29 30 29 0 355 -1289 */{ 10 , 1 , 23 , 38352 },/* 30 29 29 30 29 30 29 30 30 30 29 30 29 384 -1290 */{ 0 , 2 , 11 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355 -1291 */{ 0 , 2 , 1 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354 -1292 */{ 6 , 1 , 21 , 42168 },/* 30 29 30 29 29 30 29 29 30 29 30 30 30 384 -1293 */{ 0 , 2 , 8 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354 -1294 */{ 0 , 1 , 28 , 43600 },/* 30 29 30 29 30 29 30 29 29 30 29 30 0 354 -1295 */{ 4 , 1 , 17 , 46376 },/* 30 29 30 30 29 30 29 30 29 29 30 29 30 384 -1296 */{ 0 , 2 , 5 , 27968 },/* 29 30 30 29 30 30 29 30 29 30 29 29 0 354 -1297 */{ 12 , 1 , 24 , 44384 },/* 30 29 30 29 30 30 29 30 29 30 30 29 29 384 -1298 */{ 0 , 2 , 12 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 0 355 -1299 */{ 0 , 2 , 2 , 37744 },/* 30 29 29 30 29 29 30 30 29 30 30 30 0 355 -1300 */{ 8 , 1 , 23 , 2424 },/* 29 29 29 29 30 29 29 30 29 30 30 30 30 383 -1301 */{ 0 , 2 , 10 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354 -1302 */{ 0 , 1 , 30 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 0 354 -1303 */{ 5 , 1 , 19 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 29 383 -1304 */{ 0 , 2 , 6 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 0 355 -1305 */{ 0 , 1 , 26 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354 -1306 */{ 1 , 1 , 15 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 29 384 -1307 */{ 0 , 2 , 3 , 42720 },/* 30 29 30 29 29 30 30 29 30 30 30 29 0 355 -1308 */{ 11 , 1 , 24 , 37608 },/* 30 29 29 30 29 29 30 29 30 30 30 29 30 384 -1309 */{ 0 , 2 , 11 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354 -1310 */{ 0 , 1 , 31 , 51552 },/* 30 30 29 29 30 29 29 30 29 30 30 29 0 354 -1311 */{ 7 , 1 , 20 , 54440 },/* 30 30 29 30 29 30 29 29 30 29 30 29 30 384 -1312 */{ 0 , 2 , 8 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354 -1313 */{ 0 , 1 , 27 , 54608 },/* 30 30 29 30 29 30 29 30 29 30 29 30 0 355 -1314 */{ 3 , 1 , 17 , 23208 },/* 29 30 29 30 30 29 30 29 30 29 30 29 30 384 -1315 */{ 0 , 2 , 5 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354 -1316 */{ 0 , 1 , 25 , 42704 },/* 30 29 30 29 29 30 30 29 30 30 29 30 0 355 -1317 */{ 1 , 1 , 14 , 37608 },/* 30 29 29 30 29 29 30 29 30 30 30 29 30 384 -1318 */{ 0 , 2 , 2 , 37552 },/* 30 29 29 30 29 29 30 29 30 29 30 30 0 354 -1319 */{ 8 , 1 , 22 , 42328 },/* 30 29 30 29 29 30 29 30 29 30 29 30 30 384 -1320 */{ 0 , 2 , 10 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354 -1321 */{ 0 , 1 , 29 , 45728 },/* 30 29 30 30 29 29 30 29 30 29 30 29 0 354 -1322 */{ 5 , 1 , 18 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 29 384 -1323 */{ 0 , 2 , 6 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355 -1324 */{ 0 , 1 , 27 , 19872 },/* 29 30 29 29 30 30 29 30 30 29 30 29 0 354 -1325 */{ 1 , 1 , 15 , 42448 },/* 30 29 30 29 29 30 29 30 30 30 29 30 29 384 -1326 */{ 0 , 2 , 3 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355 -1327 */{ 9 , 1 , 24 , 21176 },/* 29 30 29 30 29 29 30 29 30 29 30 30 30 384 -1328 */{ 0 , 2 , 12 , 21104 },/* 29 30 29 30 29 29 30 29 29 30 30 30 0 354 -1329 */{ 0 , 1 , 31 , 26928 },/* 29 30 30 29 30 29 29 30 29 29 30 30 0 354 -1330 */{ 7 , 1 , 20 , 27288 },/* 29 30 30 29 30 29 30 29 30 29 29 30 30 384 -1331 */{ 0 , 2 , 8 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354 -1332 */{ 0 , 1 , 28 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 0 355 -1333 */{ 3 , 1 , 17 , 19368 },/* 29 30 29 29 30 29 30 30 30 29 30 29 30 384 -1334 */{ 0 , 2 , 5 , 19296 },/* 29 30 29 29 30 29 30 30 29 30 30 29 0 354 -1335 */{ 12 , 1 , 25 , 42608 },/* 30 29 30 29 29 30 30 29 29 30 30 30 29 384 -1336 */{ 0 , 2 , 13 , 41696 },/* 30 29 30 29 29 29 30 29 30 30 30 29 0 354 -1337 */{ 0 , 2 , 1 , 53600 },/* 30 30 29 30 29 29 29 30 29 30 30 29 0 354 -1338 */{ 8 , 1 , 21 , 59696 },/* 30 30 30 29 30 29 29 30 29 29 30 30 29 384 -1339 */{ 0 , 2 , 9 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354 -1340 */{ 0 , 1 , 29 , 55968 },/* 30 30 29 30 30 29 30 29 30 29 30 29 0 355 -1341 */{ 5 , 1 , 18 , 23376 },/* 29 30 29 30 30 29 30 30 29 30 29 30 29 384 -1342 */{ 0 , 2 , 6 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 0 355 -1343 */{ 0 , 1 , 27 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354 -1344 */{ 2 , 1 , 16 , 41704 },/* 30 29 30 29 29 29 30 29 30 30 30 29 30 384 -1345 */{ 0 , 2 , 3 , 41680 },/* 30 29 30 29 29 29 30 29 30 30 29 30 0 354 -1346 */{ 10 , 1 , 23 , 53592 },/* 30 30 29 30 29 29 29 30 29 30 29 30 30 384 -1347 */{ 0 , 2 , 11 , 43600 },/* 30 29 30 29 30 29 30 29 29 30 29 30 0 354 -1348 */{ 0 , 1 , 31 , 46368 },/* 30 29 30 30 29 30 29 30 29 29 30 29 0 354 -1349 */{ 7 , 1 , 19 , 54944 },/* 30 30 29 30 29 30 30 29 30 29 30 29 29 384 -1350 */{ 0 , 2 , 7 , 44448 },/* 30 29 30 29 30 30 29 30 30 29 30 29 0 355 -1351 */{ 0 , 1 , 28 , 21968 },/* 29 30 29 30 29 30 29 30 30 30 29 30 0 355 -1352 */{ 3 , 1 , 18 , 18904 },/* 29 30 29 29 30 29 29 30 30 30 29 30 30 384 -1353 */{ 0 , 2 , 5 , 17840 },/* 29 30 29 29 29 30 29 30 30 29 30 30 0 354 -1354 */{ 0 , 1 , 25 , 41648 },/* 30 29 30 29 29 29 30 29 30 29 30 30 0 354 -1355 */{ 1 , 1 , 14 , 53592 },/* 30 30 29 30 29 29 29 30 29 30 29 30 30 384 -1356 */{ 0 , 2 , 2 , 43600 },/* 30 29 30 29 30 29 30 29 29 30 29 30 0 354 -1357 */{ 9 , 1 , 21 , 46376 },/* 30 29 30 30 29 30 29 30 29 29 30 29 30 384 -1358 */{ 0 , 2 , 9 , 27424 },/* 29 30 30 29 30 29 30 30 29 29 30 29 0 354 -1359 */{ 0 , 1 , 29 , 44384 },/* 30 29 30 29 30 30 29 30 29 30 30 29 0 355 -1360 */{ 5 , 1 , 19 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 29 384 -1361 */{ 0 , 2 , 6 , 37744 },/* 30 29 29 30 29 29 30 30 29 30 30 30 0 355 -1362 */{ 0 , 1 , 27 , 17776 },/* 29 30 29 29 29 30 29 30 29 30 30 30 0 354 -1363 */{ 3 , 1 , 16 , 41656 },/* 30 29 30 29 29 29 30 29 30 29 30 30 30 384 -1364 */{ 0 , 2 , 4 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354 -1365 */{ 10 , 1 , 23 , 43600 },/* 30 29 30 29 30 29 30 29 29 30 29 30 29 383 -1366 */{ 0 , 2 , 10 , 55632 },/* 30 30 29 30 30 29 29 30 29 30 29 30 0 355 -1367 */{ 0 , 1 , 31 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354 -1368 */{ 7 , 1 , 20 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 29 384 -1369 */{ 0 , 2 , 7 , 42720 },/* 30 29 30 29 29 30 30 29 30 30 30 29 0 355 -1370 */{ 0 , 1 , 28 , 21216 },/* 29 30 29 30 29 29 30 29 30 30 30 29 0 354 -1371 */{ 3 , 1 , 17 , 50544 },/* 30 30 29 29 29 30 29 30 29 30 30 30 29 384 -1372 */{ 0 , 2 , 5 , 42336 },/* 30 29 30 29 29 30 29 30 29 30 30 29 0 354 -1373 */{ 11 , 1 , 24 , 53928 },/* 30 30 29 30 29 29 30 29 30 29 30 29 30 384 -1374 */{ 0 , 2 , 12 , 53920 },/* 30 30 29 30 29 29 30 29 30 29 30 29 0 354 -1375 */{ 0 , 2 , 1 , 54608 },/* 30 30 29 30 29 30 29 30 29 30 29 30 0 355 -1376 */{ 9 , 1 , 22 , 23208 },/* 29 30 29 30 30 29 30 29 30 29 30 29 30 384 -1377 */{ 0 , 2 , 9 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354 -1378 */{ 0 , 1 , 29 , 42704 },/* 30 29 30 29 29 30 30 29 30 30 29 30 0 355 -1379 */{ 5 , 1 , 19 , 21224 },/* 29 30 29 30 29 29 30 29 30 30 30 29 30 384 -1380 */{ 0 , 2 , 7 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354 -1381 */{ 0 , 1 , 26 , 43216 },/* 30 29 30 29 30 29 29 29 30 30 29 30 0 354 -1382 */{ 2 , 1 , 15 , 53928 },/* 30 30 29 30 29 29 30 29 30 29 30 29 30 384 -1383 */{ 0 , 2 , 3 , 45728 },/* 30 29 30 30 29 29 30 29 30 29 30 29 0 354 -1384 */{ 10 , 1 , 23 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 29 384 -1385 */{ 0 , 2 , 10 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355 -1386 */{ 0 , 1 , 31 , 19872 },/* 29 30 29 29 30 30 29 30 30 29 30 29 0 354 -1387 */{ 6 , 1 , 20 , 42448 },/* 30 29 30 29 29 30 29 30 30 30 29 30 29 384 -1388 */{ 0 , 2 , 8 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355 -1389 */{ 0 , 1 , 28 , 20912 },/* 29 30 29 30 29 29 29 30 30 29 30 30 0 354 -1390 */{ 4 , 1 , 17 , 43192 },/* 30 29 30 29 30 29 29 29 30 29 30 30 30 384 -1391 */{ 0 , 2 , 5 , 25904 },/* 29 30 30 29 29 30 29 30 29 29 30 30 0 354 -1392 */{ 12 , 1 , 25 , 27288 },/* 29 30 30 29 30 29 30 29 30 29 29 30 30 384 -1393 */{ 0 , 2 , 12 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354 -1394 */{ 0 , 2 , 1 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 0 355 -1395 */{ 9 , 1 , 22 , 11176 },/* 29 29 30 29 30 29 30 30 30 29 30 29 30 384 -1396 */{ 0 , 2 , 10 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354 -1397 */{ 0 , 1 , 29 , 50032 },/* 30 30 29 29 29 29 30 30 29 30 30 30 0 355 -1398 */{ 5 , 1 , 19 , 20848 },/* 29 30 29 30 29 29 29 30 29 30 30 30 29 383 -1399 */{ 0 , 2 , 6 , 51552 },/* 30 30 29 29 30 29 29 30 29 30 30 29 0 354 -1400 */{ 0 , 1 , 26 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354 -1401 */{ 3 , 1 , 15 , 27280 },/* 29 30 30 29 30 29 30 29 30 29 29 30 29 383 -1402 */{ 0 , 2 , 2 , 55968 },/* 30 30 29 30 30 29 30 29 30 29 30 29 0 355 -1403 */{ 11 , 1 , 23 , 23376 },/* 29 30 29 30 30 29 30 30 29 30 29 30 29 384 -1404 */{ 0 , 2 , 11 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 0 355 -1405 */{ 0 , 1 , 31 , 10976 },/* 29 29 30 29 30 29 30 29 30 30 30 29 0 354 -1406 */{ 7 , 1 , 20 , 41704 },/* 30 29 30 29 29 29 30 29 30 30 30 29 30 384 -1407 */{ 0 , 2 , 8 , 41680 },/* 30 29 30 29 29 29 30 29 30 30 29 30 0 354 -1408 */{ 0 , 1 , 28 , 53584 },/* 30 30 29 30 29 29 29 30 29 30 29 30 0 354 -1409 */{ 4 , 1 , 16 , 54440 },/* 30 30 29 30 29 30 29 29 30 29 30 29 30 384 -1410 */{ 0 , 2 , 4 , 46368 },/* 30 29 30 30 29 30 29 30 29 29 30 29 0 354 -1411 */{ 12 , 1 , 24 , 46736 },/* 30 29 30 30 29 30 30 29 30 29 29 30 29 384 -1412 */{ 0 , 2 , 12 , 44448 },/* 30 29 30 29 30 30 29 30 30 29 30 29 0 355 -1413 */{ 0 , 2 , 1 , 21968 },/* 29 30 29 30 29 30 29 30 30 30 29 30 0 355 -1414 */{ 9 , 1 , 22 , 9688 },/* 29 29 30 29 29 30 29 30 30 30 29 30 30 384 -1415 */{ 0 , 2 , 10 , 17840 },/* 29 30 29 29 29 30 29 30 30 29 30 30 0 354 -1416 */{ 0 , 1 , 30 , 41648 },/* 30 29 30 29 29 29 30 29 30 29 30 30 0 354 -1417 */{ 5 , 1 , 18 , 43352 },/* 30 29 30 29 30 29 29 30 29 30 29 30 30 384 -1418 */{ 0 , 2 , 6 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354 -1419 */{ 0 , 1 , 26 , 46368 },/* 30 29 30 30 29 30 29 30 29 29 30 29 0 354 -1420 */{ 1 , 1 , 15 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 29 384 -1421 */{ 0 , 2 , 2 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 0 355 -1422 */{ 12 , 1 , 23 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 29 384 -1423 */{ 0 , 2 , 11 , 19312 },/* 29 30 29 29 30 29 30 30 29 30 30 30 0 355 -1424 */{ 0 , 2 , 1 , 17776 },/* 29 30 29 29 29 30 29 30 29 30 30 30 0 354 -1425 */{ 7 , 1 , 20 , 21176 },/* 29 30 29 30 29 29 30 29 30 29 30 30 30 384 -1426 */{ 0 , 2 , 8 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354 -1427 */{ 0 , 1 , 28 , 26960 },/* 29 30 30 29 30 29 29 30 29 30 29 30 0 354 -1428 */{ 4 , 1 , 17 , 27816 },/* 29 30 30 29 30 30 29 29 30 29 30 29 30 384 -1429 */{ 0 , 2 , 4 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354 -1430 */{ 12 , 1 , 24 , 39760 },/* 30 29 29 30 30 29 30 30 29 30 29 30 29 384 -1431 */{ 0 , 2 , 12 , 42720 },/* 30 29 30 29 29 30 30 29 30 30 30 29 0 355 -1432 */{ 0 , 2 , 2 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354 -1433 */{ 8 , 1 , 21 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 29 384 -1434 */{ 0 , 2 , 9 , 42336 },/* 30 29 30 29 29 30 29 30 29 30 30 29 0 354 -1435 */{ 0 , 1 , 29 , 53920 },/* 30 30 29 30 29 29 30 29 30 29 30 29 0 354 -1436 */{ 6 , 1 , 18 , 59728 },/* 30 30 30 29 30 29 29 30 29 30 29 30 29 384 -1437 */{ 0 , 2 , 5 , 54608 },/* 30 30 29 30 29 30 29 30 29 30 29 30 0 355 -1438 */{ 0 , 1 , 26 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354 -1439 */{ 2 , 1 , 15 , 43728 },/* 30 29 30 29 30 29 30 29 30 30 29 30 29 384 -1440 */{ 0 , 2 , 3 , 38368 },/* 30 29 29 30 29 30 29 30 30 30 30 29 0 355 -1441 */{ 11 , 1 , 23 , 19176 },/* 29 30 29 29 30 29 30 29 30 30 30 29 30 384 -1442 */{ 0 , 2 , 11 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354 -1443 */{ 0 , 1 , 31 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354 -1444 */{ 7 , 1 , 20 , 53872 },/* 30 30 29 30 29 29 30 29 29 30 30 30 29 384 -1445 */{ 0 , 2 , 7 , 45728 },/* 30 29 30 30 29 29 30 29 30 29 30 29 0 354 -1446 */{ 0 , 1 , 27 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355 -1447 */{ 4 , 1 , 17 , 22184 },/* 29 30 29 30 29 30 30 29 30 29 30 29 30 384 -1448 */{ 0 , 2 , 5 , 11680 },/* 29 29 30 29 30 30 29 30 30 29 30 29 0 354 -1449 */{ 0 , 1 , 24 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355 -1450 */{ 1 , 1 , 14 , 19128 },/* 29 30 29 29 30 29 30 29 30 29 30 30 30 384 -1451 */{ 0 , 2 , 2 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354 -1452 */{ 9 , 1 , 22 , 42168 },/* 30 29 30 29 29 30 29 29 30 29 30 30 30 384 -1453 */{ 0 , 2 , 9 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 0 354 -1454 */{ 0 , 1 , 29 , 27280 },/* 29 30 30 29 30 29 30 29 30 29 29 30 0 354 -1455 */{ 6 , 1 , 18 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 29 384 -1456 */{ 0 , 2 , 6 , 27472 },/* 29 30 30 29 30 29 30 30 29 30 29 30 0 355 -1457 */{ 0 , 1 , 26 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354 -1458 */{ 2 , 1 , 15 , 38256 },/* 30 29 29 30 29 30 29 30 29 30 30 30 29 384 -1459 */{ 0 , 2 , 3 , 37744 },/* 30 29 29 30 29 29 30 30 29 30 30 30 0 355 -1460 */{ 11 , 1 , 24 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 29 383 -1461 */{ 0 , 2 , 10 , 51552 },/* 30 30 29 29 30 29 29 30 29 30 30 29 0 354 -1462 */{ 0 , 1 , 30 , 58544 },/* 30 30 30 29 29 30 29 29 30 29 30 30 0 355 -1463 */{ 7 , 1 , 20 , 27280 },/* 29 30 30 29 30 29 30 29 30 29 29 30 29 383 -1464 */{ 0 , 2 , 7 , 55968 },/* 30 30 29 30 30 29 30 29 30 29 30 29 0 355 -1465 */{ 0 , 1 , 27 , 23248 },/* 29 30 29 30 30 29 30 29 30 30 29 30 0 355 -1466 */{ 3 , 1 , 17 , 11112 },/* 29 29 30 29 30 29 30 30 29 30 30 29 30 384 -1467 */{ 0 , 2 , 5 , 9952 },/* 29 29 30 29 29 30 30 29 30 30 30 29 0 354 -1468 */{ 0 , 1 , 25 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354 -1469 */{ 2 , 1 , 13 , 51560 },/* 30 30 29 29 30 29 29 30 29 30 30 29 30 384 -1470 */{ 0 , 2 , 1 , 51536 },/* 30 30 29 29 30 29 29 30 29 30 29 30 0 354 -1471 */{ 9 , 1 , 21 , 54440 },/* 30 30 29 30 29 30 29 29 30 29 30 29 30 384 -1472 */{ 0 , 2 , 9 , 46240 },/* 30 29 30 30 29 30 29 29 30 29 30 29 0 354 -1473 */{ 0 , 1 , 28 , 46736 },/* 30 29 30 30 29 30 30 29 30 29 29 30 0 355 -1474 */{ 6 , 1 , 18 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 29 384 -1475 */{ 0 , 2 , 6 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 0 355 -1476 */{ 0 , 1 , 27 , 9680 },/* 29 29 30 29 29 30 29 30 30 30 29 30 0 354 -1477 */{ 2 , 1 , 15 , 37592 },/* 30 29 29 30 29 29 30 29 30 30 29 30 30 384 -1478 */{ 0 , 2 , 3 , 37552 },/* 30 29 29 30 29 29 30 29 30 29 30 30 0 354 -1479 */{ 10 , 1 , 23 , 43352 },/* 30 29 30 29 30 29 29 30 29 30 29 30 30 384 -1480 */{ 0 , 2 , 11 , 26960 },/* 29 30 30 29 30 29 29 30 29 30 29 30 0 354 -1481 */{ 0 , 1 , 30 , 29856 },/* 29 30 30 30 29 30 29 29 30 29 30 29 0 354 -1482 */{ 8 , 1 , 19 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 29 384 -1483 */{ 0 , 2 , 7 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 0 355 -1484 */{ 0 , 1 , 28 , 21424 },/* 29 30 29 30 29 29 30 30 30 29 30 30 0 355 -1485 */{ 4 , 1 , 17 , 9656 },/* 29 29 30 29 29 30 29 30 30 29 30 30 30 384 -1486 */{ 0 , 2 , 5 , 9584 },/* 29 29 30 29 29 30 29 30 29 30 30 30 0 354 -1487 */{ 0 , 1 , 25 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354 -1488 */{ 1 , 1 , 14 , 43352 },/* 30 29 30 29 30 29 29 30 29 30 29 30 30 384 -1489 */{ 0 , 2 , 1 , 26960 },/* 29 30 30 29 30 29 29 30 29 30 29 30 0 354 -1490 */{ 9 , 1 , 21 , 27304 },/* 29 30 30 29 30 29 30 29 30 29 30 29 30 384 -1491 */{ 0 , 2 , 9 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354 -1492 */{ 0 , 1 , 29 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 0 355 -1493 */{ 5 , 1 , 18 , 19304 },/* 29 30 29 29 30 29 30 30 29 30 30 29 30 384 -1494 */{ 0 , 2 , 6 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354 -1495 */{ 0 , 1 , 26 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355 -1496 */{ 3 , 1 , 16 , 21104 },/* 29 30 29 30 29 29 30 29 29 30 30 30 29 383 -1497 */{ 0 , 2 , 2 , 53920 },/* 30 30 29 30 29 29 30 29 30 29 30 29 0 354 -1498 */{ 11 , 1 , 22 , 55632 },/* 30 30 29 30 30 29 29 30 29 30 29 30 29 384 -1499 */{ 0 , 2 , 10 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355 -1500 */{ 0 , 1 , 31 , 5792 },/* 29 29 29 30 29 30 30 29 30 29 30 29 0 353 -1501 */{ 7 , 1 , 19 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 29 384 -1502 */{ 0 , 2 , 7 , 38352 },/* 30 29 29 30 29 30 29 30 30 30 29 30 0 355 -1503 */{ 0 , 1 , 28 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354 -1504 */{ 4 , 1 , 17 , 42200 },/* 30 29 30 29 29 30 29 29 30 30 29 30 30 384 -1505 */{ 0 , 2 , 4 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354 -1506 */{ 0 , 1 , 24 , 53840 },/* 30 30 29 30 29 29 30 29 29 30 29 30 0 354 -1507 */{ 1 , 1 , 13 , 54608 },/* 30 30 29 30 29 30 29 30 29 30 29 30 29 384 -1508 */{ 0 , 2 , 1 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355 -1509 */{ 9 , 1 , 21 , 22184 },/* 29 30 29 30 29 30 30 29 30 29 30 29 30 384 -1510 */{ 0 , 2 , 9 , 11680 },/* 29 29 30 29 30 30 29 30 30 29 30 29 0 354 -1511 */{ 0 , 1 , 29 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355 -1512 */{ 5 , 1 , 19 , 18872 },/* 29 30 29 29 30 29 29 30 30 29 30 30 30 384 -1513 */{ 0 , 2 , 6 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354 -1514 */{ 0 , 1 , 26 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354 -1515 */{ 4 , 1 , 15 , 45656 },/* 30 29 30 30 29 29 30 29 29 30 29 30 30 384 -1516 */{ 0 , 2 , 3 , 27280 },/* 29 30 30 29 30 29 30 29 30 29 29 30 0 354 -1517 */{ 12 , 1 , 22 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 29 384 -1518 */{ 0 , 2 , 10 , 23376 },/* 29 30 29 30 30 29 30 30 29 30 29 30 0 355 -1519 */{ 0 , 1 , 31 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354 -1520 */{ 8 , 1 , 20 , 38256 },/* 30 29 29 30 29 30 29 30 29 30 30 30 29 384 -1521 */{ 0 , 2 , 7 , 37616 },/* 30 29 29 30 29 29 30 29 30 30 30 30 0 355 -1522 */{ 0 , 1 , 28 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354 -1523 */{ 4 , 1 , 17 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 29 383 -1524 */{ 0 , 2 , 4 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354 -1525 */{ 12 , 1 , 23 , 59984 },/* 30 30 30 29 30 29 30 29 29 30 29 30 29 384 -1526 */{ 0 , 2 , 11 , 54928 },/* 30 30 29 30 29 30 30 29 30 29 29 30 0 355 -1527 */{ 0 , 2 , 1 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 0 355 -1528 */{ 10 , 1 , 22 , 11112 },/* 29 29 30 29 30 29 30 30 29 30 30 29 30 384 -1529 */{ 0 , 2 , 9 , 9952 },/* 29 29 30 29 29 30 30 29 30 30 30 29 0 354 -1530 */{ 0 , 1 , 29 , 21216 },/* 29 30 29 30 29 29 30 29 30 30 30 29 0 354 -1531 */{ 6 , 1 , 18 , 51560 },/* 30 30 29 29 30 29 29 30 29 30 30 29 30 384 -1532 */{ 0 , 2 , 6 , 51536 },/* 30 30 29 29 30 29 29 30 29 30 29 30 0 354 -1533 */{ 0 , 1 , 25 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354 -1534 */{ 2 , 1 , 14 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 29 384 -1535 */{ 0 , 2 , 2 , 46480 },/* 30 29 30 30 29 30 29 30 30 29 29 30 0 355 -1536 */{ 12 , 1 , 23 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 29 384 -1537 */{ 0 , 2 , 10 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 0 355 -1538 */{ 0 , 1 , 31 , 9680 },/* 29 29 30 29 29 30 29 30 30 30 29 30 0 354 -1539 */{ 7 , 1 , 20 , 37592 },/* 30 29 29 30 29 29 30 29 30 30 29 30 30 384 -1540 */{ 0 , 2 , 8 , 37552 },/* 30 29 29 30 29 29 30 29 30 29 30 30 0 354 -1541 */{ 0 , 1 , 27 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354 -1542 */{ 5 , 1 , 16 , 46248 },/* 30 29 30 30 29 30 29 29 30 29 30 29 30 384 -1543 */{ 0 , 2 , 4 , 27808 },/* 29 30 30 29 30 30 29 29 30 29 30 29 0 354 -1544 */{ 0 , 1 , 24 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355 -1545 */{ 1 , 1 , 13 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 29 384 -1546 */{ 0 , 2 , 1 , 19376 },/* 29 30 29 29 30 29 30 30 30 29 30 30 0 355 -1547 */{ 9 , 1 , 22 , 9656 },/* 29 29 30 29 29 30 29 30 30 29 30 30 30 384 -1548 */{ 0 , 2 , 10 , 9584 },/* 29 29 30 29 29 30 29 30 29 30 30 30 0 354 -1549 */{ 0 , 1 , 29 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354 -1550 */{ 6 , 1 , 18 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 29 383 -1551 */{ 0 , 2 , 5 , 59728 },/* 30 30 30 29 30 29 29 30 29 30 29 30 0 355 -1552 */{ 0 , 1 , 26 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354 -1553 */{ 3 , 1 , 14 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 29 384 -1554 */{ 0 , 2 , 2 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 0 355 -1555 */{ 11 , 1 , 23 , 19304 },/* 29 30 29 29 30 29 30 30 29 30 30 29 30 384 -1556 */{ 0 , 2 , 11 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354 -1557 */{ 0 , 1 , 30 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355 -1558 */{ 7 , 1 , 20 , 21096 },/* 29 30 29 30 29 29 30 29 29 30 30 29 30 383 -1559 */{ 0 , 2 , 7 , 53856 },/* 30 30 29 30 29 29 30 29 29 30 30 29 0 354 -1560 */{ 0 , 1 , 27 , 55632 },/* 30 30 29 30 30 29 29 30 29 30 29 30 0 355 -1561 */{ 5 , 1 , 16 , 23208 },/* 29 30 29 30 30 29 30 29 30 29 30 29 30 384 -1562 */{ 0 , 2 , 4 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354 -1563 */{ 0 , 1 , 24 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 0 355 -1564 */{ 2 , 1 , 14 , 19176 },/* 29 30 29 29 30 29 30 29 30 30 30 29 30 384 -1565 */{ 0 , 2 , 1 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354 -1566 */{ 10 , 1 , 21 , 42200 },/* 30 29 30 29 29 30 29 29 30 30 29 30 30 384 -1567 */{ 0 , 2 , 9 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354 -1568 */{ 0 , 1 , 29 , 53840 },/* 30 30 29 30 29 29 30 29 29 30 29 30 0 354 -1569 */{ 6 , 1 , 17 , 54600 },/* 30 30 29 30 29 30 29 30 29 30 29 29 30 384 -1570 */{ 0 , 2 , 5 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355 -1571 */{ 0 , 1 , 26 , 13728 },/* 29 29 30 30 29 30 29 30 30 29 30 29 0 354 -1572 */{ 2 , 1 , 15 , 38352 },/* 30 29 29 30 29 30 29 30 30 30 29 30 29 384 -1573 */{ 0 , 2 , 2 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355 -1574 */{ 12 , 1 , 23 , 18872 },/* 29 30 29 29 30 29 29 30 30 29 30 30 30 384 -1575 */{ 0 , 2 , 11 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354 -1576 */{ 0 , 1 , 31 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354 -1577 */{ 8 , 1 , 19 , 45656 },/* 30 29 30 30 29 29 30 29 29 30 29 30 30 384 -1578 */{ 0 , 2 , 7 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 0 354 -1579 */{ 0 , 1 , 27 , 27968 },/* 29 30 30 29 30 30 29 30 29 30 29 29 0 354 -1580 */{ 4 , 1 , 16 , 44456 },/* 30 29 30 29 30 30 29 30 30 29 30 29 30 385 -1581 */{ 0 , 2 , 4 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354 -1582 */{ 0 , 1 , 24 , 39024 },/* 30 29 29 30 29 29 30 30 39 30 30 30 0 365 -1583 */{ 2 , 1 , 24 , 18808 },/* 29 30 29 29 30 29 29 30 29 30 30 30 30 384 -1584 */{ 0 , 2 , 12 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354 -1585 */{ 9 , 1 , 31 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 29 383 -1586 */{ 0 , 2 , 18 , 54440 },/* 30 30 29 30 29 30 29 29 30 29 30 29 30 384 -1587 */{ 0 , 3 , 9 , 53968 },/* 30 30 29 30 29 30 29 29 30 29 30 0 0 325 -1588 */{ 6 , 1 , 28 , 27464 },/* 29 30 30 29 30 29 30 30 29 30 29 29 30 384 -1589 */{ 0 , 2 , 15 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 0 355 -1590 */{ 0 , 2 , 5 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354 -1591 */{ 3 , 1 , 25 , 37616 },/* 30 29 29 30 29 29 30 29 30 30 30 30 29 384 -1592 */{ 0 , 2 , 13 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354 -1593 */{ 11 , 2 , 1 , 51560 },/* 30 30 29 29 30 29 29 30 29 30 30 29 30 384 -1594 */{ 0 , 2 , 20 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354 -1595 */{ 0 , 2 , 9 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354 -1596 */{ 8 , 1 , 29 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 29 384 -1597 */{ 0 , 2 , 16 , 46288 },/* 30 29 30 30 29 30 29 29 30 30 29 30 0 355 -1598 */{ 0 , 2 , 6 , 22192 },/* 29 30 29 30 29 30 30 29 30 29 30 30 0 355 -1599 */{ 4 , 1 , 27 , 9944 },/* 29 29 30 29 29 30 30 29 30 30 29 30 30 384 -1600 */{ 0 , 2 , 15 , 9680 },/* 29 29 30 29 29 30 29 30 30 30 29 30 0 354 -1601 */{ 0 , 2 , 3 , 37584 },/* 30 29 29 30 29 29 30 29 30 30 29 30 0 354 -1602 */{ 2 , 1 , 23 , 51608 },/* 30 30 29 29 30 29 29 30 30 29 29 30 30 384 -1603 */{ 0 , 2 , 11 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354 -1604 */{ 9 , 1 , 31 , 46248 },/* 30 29 30 30 29 30 29 29 30 29 30 29 30 384 -1605 */{ 0 , 2 , 18 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354 -1606 */{ 0 , 2 , 7 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355 -1607 */{ 6 , 1 , 28 , 21928 },/* 29 30 29 30 29 30 29 30 30 29 30 29 30 384 -1608 */{ 0 , 2 , 16 , 19376 },/* 29 30 29 29 30 29 30 30 30 29 30 30 0 355 -1609 */{ 0 , 2 , 5 , 9648 },/* 29 29 30 29 29 30 29 30 30 29 30 30 0 354 -1610 */{ 3 , 1 , 25 , 21176 },/* 29 30 29 30 29 29 30 29 30 29 30 30 30 384 -1611 */{ 0 , 2 , 13 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354 -1612 */{ 11 , 2 , 2 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 29 383 -1613 */{ 0 , 2 , 19 , 59728 },/* 30 30 30 29 30 29 29 30 29 30 29 30 0 355 -1614 */{ 0 , 2 , 9 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354 -1615 */{ 8 , 1 , 29 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 29 384 -1616 */{ 0 , 2 , 17 , 39760 },/* 30 29 29 30 30 29 30 30 29 30 29 30 0 355 -1617 */{ 0 , 2 , 6 , 19296 },/* 29 30 29 29 30 29 30 30 29 30 30 29 0 354 -1618 */{ 4 , 1 , 26 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 29 384 -1619 */{ 0 , 2 , 14 , 42224 },/* 30 29 30 29 29 30 29 29 30 30 30 30 0 355 -1620 */{ 0 , 2 , 4 , 21088 },/* 29 30 29 30 29 29 30 29 29 30 30 29 0 353 -1621 */{ 2 , 1 , 22 , 59696 },/* 30 30 30 29 30 29 29 30 29 29 30 30 29 384 -1622 */{ 0 , 2 , 10 , 54608 },/* 30 30 29 30 29 30 29 30 29 30 29 30 0 355 -1623 */{ 10 , 1 , 31 , 23208 },/* 29 30 29 30 30 29 30 29 30 29 30 29 30 384 -1624 */{ 0 , 2 , 19 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354 -1625 */{ 0 , 2 , 7 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 0 355 -1626 */{ 6 , 1 , 28 , 19176 },/* 29 30 29 29 30 29 30 29 30 30 30 29 30 384 -1627 */{ 0 , 2 , 16 , 18912 },/* 29 30 29 29 30 29 29 30 30 30 30 29 0 354 -1628 */{ 0 , 2 , 5 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354 -1629 */{ 4 , 1 , 24 , 53864 },/* 30 30 29 30 29 29 30 29 29 30 30 29 30 384 -1630 */{ 0 , 2 , 12 , 53840 },/* 30 30 29 30 29 29 30 29 29 30 29 30 0 354 -1631 */{ 11 , 2 , 1 , 54568 },/* 30 30 29 30 29 30 29 30 29 29 30 29 30 384 -1632 */{ 0 , 2 , 20 , 46400 },/* 30 29 30 30 29 30 29 30 29 30 29 29 0 354 -1633 */{ 0 , 2 , 8 , 46496 },/* 30 29 30 30 29 30 29 30 30 29 30 29 0 355 -1634 */{ 8 , 1 , 29 , 38352 },/* 30 29 29 30 29 30 29 30 30 30 29 30 29 384 -1635 */{ 0 , 2 , 17 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355 -1636 */{ 0 , 2 , 7 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354 -1637 */{ 4 , 1 , 26 , 42168 },/* 30 29 30 29 29 30 29 29 30 29 30 30 30 384 -1638 */{ 0 , 2 , 14 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354 -1639 */{ 0 , 2 , 3 , 43600 },/* 30 29 30 29 30 29 30 29 29 30 29 30 0 354 -1640 */{ 1 , 1 , 23 , 46376 },/* 30 29 30 30 29 30 29 30 29 29 30 29 30 384 -1641 */{ 0 , 2 , 10 , 27968 },/* 29 30 30 29 30 30 29 30 29 30 29 29 0 354 -1642 */{ 11 , 1 , 30 , 44456 },/* 30 29 30 29 30 30 29 30 30 29 30 29 30 385 -1643 */{ 0 , 2 , 19 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354 -1644 */{ 0 , 2 , 8 , 37744 },/* 30 29 29 30 29 29 30 30 29 30 30 30 0 355 -1645 */{ 6 , 1 , 28 , 18808 },/* 29 30 29 29 30 29 29 30 29 30 30 30 30 384 -1646 */{ 0 , 2 , 16 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354 -1647 */{ 0 , 2 , 5 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 0 354 -1648 */{ 3 , 1 , 24 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 29 383 -1649 */{ 0 , 2 , 11 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 0 355 -1650 */{ 11 , 2 , 1 , 27464 },/* 29 30 30 29 30 29 30 30 29 30 29 29 30 384 -1651 */{ 0 , 2 , 20 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 0 355 -1652 */{ 0 , 2 , 10 , 11168 },/* 29 29 30 29 30 29 30 30 30 29 30 29 0 354 -1653 */{ 7 , 1 , 29 , 37616 },/* 30 29 29 30 29 29 30 29 30 30 30 30 29 384 -1654 */{ 0 , 2 , 17 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354 -1655 */{ 0 , 2 , 6 , 51552 },/* 30 30 29 29 30 29 29 30 29 30 30 29 0 354 -1656 */{ 5 , 1 , 26 , 54440 },/* 30 30 29 30 29 30 29 29 30 29 30 29 30 384 -1657 */{ 0 , 2 , 13 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354 -1658 */{ 0 , 2 , 2 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 0 355 -1659 */{ 3 , 1 , 23 , 39592 },/* 30 29 29 30 30 29 30 29 30 29 30 29 30 384 -1660 */{ 0 , 2 , 11 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354 -1661 */{ 7 , 1 , 30 , 42704 },/* 30 29 30 29 29 30 30 29 30 30 29 30 29 384 -1662 */{ 0 , 2 , 18 , 42448 },/* 30 29 30 29 29 30 29 30 30 30 29 30 0 355 -1663 */{ 0 , 2 , 8 , 37584 },/* 30 29 29 30 29 29 30 29 30 30 29 30 0 354 -1664 */{ 6 , 1 , 28 , 43352 },/* 30 29 30 29 30 29 29 30 29 30 29 30 30 384 -1665 */{ 0 , 2 , 15 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354 -1666 */{ 0 , 2 , 4 , 46240 },/* 30 29 30 30 29 30 29 29 30 29 30 29 0 354 -1667 */{ 4 , 1 , 24 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 29 384 -1668 */{ 0 , 2 , 12 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355 -1669 */{ 0 , 2 , 1 , 21920 },/* 29 30 29 30 29 30 29 30 30 29 30 29 0 354 -1670 */{ 2 , 1 , 21 , 42448 },/* 30 29 30 29 29 30 29 30 30 30 29 30 29 384 -1671 */{ 0 , 2 , 9 , 42416 },/* 30 29 30 29 29 30 29 30 30 29 30 30 0 355 -1672 */{ 7 , 1 , 30 , 21176 },/* 29 30 29 30 29 29 30 29 30 29 30 30 30 384 -1673 */{ 0 , 2 , 17 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354 -1674 */{ 0 , 2 , 6 , 26928 },/* 29 30 30 29 30 29 29 30 29 29 30 30 0 354 -1675 */{ 5 , 1 , 26 , 29864 },/* 29 30 30 30 29 30 29 29 30 29 30 29 30 384 -1676 */{ 0 , 2 , 14 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354 -1677 */{ 0 , 2 , 2 , 44432 },/* 30 29 30 29 30 30 29 30 30 29 29 30 0 355 -1678 */{ 3 , 1 , 23 , 19880 },/* 29 30 29 29 30 30 29 30 30 29 30 29 30 384 -1679 */{ 0 , 2 , 11 , 19296 },/* 29 30 29 29 30 29 30 30 29 30 30 29 0 354 -1680 */{ 8 , 1 , 31 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 29 384 -1681 */{ 0 , 2 , 18 , 42208 },/* 30 29 30 29 29 30 29 29 30 30 30 29 0 354 -1682 */{ 0 , 2 , 7 , 53856 },/* 30 30 29 30 29 29 30 29 29 30 30 29 0 354 -1683 */{ 6 , 1 , 27 , 59696 },/* 30 30 30 29 30 29 29 30 29 29 30 30 29 384 -1684 */{ 0 , 2 , 15 , 54560 },/* 30 30 29 30 29 30 29 30 29 29 30 29 0 354 -1685 */{ 0 , 2 , 3 , 55968 },/* 30 30 29 30 30 29 30 29 30 29 30 29 0 355 -1686 */{ 4 , 1 , 24 , 27472 },/* 29 30 30 29 30 29 30 30 29 30 29 30 29 384 -1687 */{ 0 , 2 , 12 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 0 355 -1688 */{ 0 , 2 , 2 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354 -1689 */{ 3 , 1 , 21 , 42216 },/* 30 29 30 29 29 30 29 29 30 30 30 29 30 384 -1690 */{ 0 , 2 , 9 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354 -1691 */{ 7 , 1 , 29 , 53848 },/* 30 30 29 30 29 29 30 29 29 30 29 30 30 384 -1692 */{ 0 , 2 , 17 , 45136 },/* 30 29 29 32 29 29 29 29 29 30 29 30 0 354 -1693 */{ 0 , 2 , 5 , 54560 },/* 30 30 29 30 29 30 29 30 29 29 30 29 0 354 -1694 */{ 5 , 1 , 25 , 54944 },/* 30 30 29 30 29 30 30 29 30 29 30 29 29 384 -1695 */{ 0 , 2 , 13 , 46496 },/* 30 29 30 30 29 30 29 30 30 29 30 29 0 355 -1696 */{ 0 , 2 , 3 , 21968 },/* 29 30 29 30 29 30 29 30 30 30 29 30 0 355 -1697 */{ 3 , 1 , 23 , 19160 },/* 29 30 29 29 30 29 30 29 30 30 29 30 30 384 -1698 */{ 0 , 2 , 11 , 18896 },/* 29 30 29 29 30 29 29 30 30 30 29 30 0 354 -1699 */{ 7 , 1 , 31 , 42168 },/* 30 29 30 29 29 30 29 29 30 29 30 30 30 384 -1700 */{ 0 , 2 , 19 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354 -1701 */{ 0 , 2 , 8 , 43600 },/* 30 29 30 29 30 29 30 29 29 30 29 30 0 354 -1702 */{ 6 , 1 , 28 , 46376 },/* 30 29 30 30 29 30 29 30 29 29 30 29 30 384 -1703 */{ 0 , 2 , 16 , 27936 },/* 29 30 30 29 30 30 29 30 29 29 30 29 0 354 -1704 */{ 0 , 2 , 5 , 44448 },/* 30 29 30 29 30 30 29 30 30 29 30 29 0 355 -1705 */{ 4 , 1 , 25 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 29 384 -1706 */{ 0 , 2 , 13 , 37744 },/* 30 29 29 30 29 29 30 30 29 30 30 30 0 355 -1707 */{ 0 , 2 , 3 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354 -1708 */{ 3 , 1 , 23 , 25784 },/* 29 30 30 29 29 30 29 29 30 29 30 30 30 384 -1709 */{ 0 , 2 , 10 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354 -1710 */{ 7 , 1 , 30 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 29 383 -1711 */{ 0 , 2 , 17 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 0 355 -1712 */{ 0 , 2 , 7 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354 -1713 */{ 5 , 1 , 26 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 29 384 -1714 */{ 0 , 2 , 14 , 43744 },/* 30 29 30 29 30 29 30 29 30 30 30 29 0 355 -1715 */{ 0 , 2 , 4 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354 -1716 */{ 3 , 1 , 24 , 51568 },/* 30 30 29 29 30 29 29 30 29 30 30 30 29 384 -1717 */{ 0 , 2 , 11 , 51552 },/* 30 30 29 29 30 29 29 30 29 30 30 29 0 354 -1718 */{ 8 , 1 , 31 , 54440 },/* 30 30 29 30 29 30 29 29 30 29 30 29 30 384 -1719 */{ 0 , 2 , 19 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354 -1720 */{ 0 , 2 , 8 , 54608 },/* 30 30 29 30 29 30 29 30 29 30 29 30 0 355 -1721 */{ 6 , 1 , 28 , 23208 },/* 29 30 29 30 30 29 30 29 30 29 30 29 30 384 -1722 */{ 0 , 2 , 16 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354 -1723 */{ 0 , 2 , 5 , 42704 },/* 30 29 30 29 29 30 30 29 30 30 29 30 0 355 -1724 */{ 4 , 1 , 26 , 21224 },/* 29 30 29 30 29 29 30 29 30 30 30 29 30 384 -1725 */{ 0 , 2 , 13 , 21200 },/* 29 30 29 30 29 29 30 29 30 30 29 30 0 354 -1726 */{ 0 , 2 , 2 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354 -1727 */{ 3 , 1 , 22 , 58536 },/* 30 30 30 29 29 30 29 29 30 29 30 29 30 384 -1728 */{ 0 , 2 , 10 , 46240 },/* 30 29 30 30 29 30 29 29 30 29 30 29 0 354 -1729 */{ 7 , 1 , 29 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 29 384 -1730 */{ 0 , 2 , 17 , 40272 },/* 30 29 29 30 30 30 29 30 29 30 29 30 0 355 -1731 */{ 0 , 2 , 7 , 21920 },/* 29 30 29 30 29 30 29 30 30 29 30 29 0 354 -1732 */{ 5 , 1 , 27 , 42448 },/* 30 29 30 29 29 30 29 30 30 30 29 30 29 384 -1733 */{ 0 , 2 , 14 , 42416 },/* 30 29 30 29 29 30 29 30 30 29 30 30 0 355 -1734 */{ 0 , 2 , 4 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354 -1735 */{ 4 , 1 , 24 , 43192 },/* 30 29 30 29 30 29 29 29 30 29 30 30 30 384 -1736 */{ 0 , 2 , 12 , 26928 },/* 29 30 30 29 30 29 29 30 29 29 30 30 0 354 -1737 */{ 9 , 1 , 31 , 27288 },/* 29 30 30 29 30 29 30 29 30 29 29 30 30 384 -1738 */{ 0 , 2 , 19 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354 -1739 */{ 0 , 2 , 8 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 0 355 -1740 */{ 6 , 1 , 29 , 19880 },/* 29 30 29 29 30 30 29 30 30 29 30 29 30 384 -1741 */{ 0 , 2 , 16 , 19296 },/* 29 30 29 29 30 29 30 30 29 30 30 29 0 354 -1742 */{ 0 , 2 , 5 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355 -1743 */{ 4 , 1 , 26 , 20848 },/* 29 30 29 30 29 29 29 30 29 30 30 30 29 383 -1744 */{ 0 , 2 , 13 , 53600 },/* 30 30 29 30 29 29 29 30 29 30 30 29 0 354 -1745 */{ 0 , 2 , 1 , 59696 },/* 30 30 30 29 30 29 29 30 29 29 30 30 0 355 -1746 */{ 3 , 1 , 22 , 27280 },/* 29 30 30 29 30 29 30 29 30 29 29 30 29 383 -1747 */{ 0 , 2 , 9 , 55968 },/* 30 30 29 30 30 29 30 29 30 29 30 29 0 355 -1748 */{ 7 , 1 , 30 , 23376 },/* 29 30 29 30 30 29 30 30 29 30 29 30 29 384 -1749 */{ 0 , 2 , 17 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 0 355 -1750 */{ 0 , 2 , 7 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354 -1751 */{ 5 , 1 , 27 , 42200 },/* 30 29 30 29 29 30 29 29 30 30 29 30 30 384 -1752 */{ 0 , 2 , 15 , 41680 },/* 30 29 30 29 29 29 30 29 30 30 29 30 0 354 -1753 */{ 0 , 2 , 3 , 53592 },/* 30 30 29 30 29 29 29 30 29 30 29 30 30 384 -1754 */{ 4 , 2 , 22 , 43600 },/* 30 29 30 29 30 29 30 29 29 30 29 30 0 354 -1755 */{ 0 , 2 , 11 , 46368 },/* 30 29 30 30 29 30 29 30 29 29 30 29 0 354 -1756 */{ 9 , 1 , 31 , 54928 },/* 30 30 29 30 29 30 30 29 30 29 29 30 29 384 -1757 */{ 0 , 2 , 18 , 44448 },/* 30 29 30 29 30 30 29 30 30 29 30 29 0 355 -1758 */{ 0 , 2 , 8 , 21968 },/* 29 30 29 30 29 30 29 30 30 30 29 30 0 355 -1759 */{ 6 , 1 , 29 , 10968 },/* 29 29 30 29 30 29 30 29 30 30 29 30 30 384 -1760 */{ 0 , 2 , 17 , 17840 },/* 29 30 29 29 29 30 29 30 30 29 30 30 0 354 -1761 */{ 0 , 2 , 5 , 41648 },/* 30 29 30 29 29 29 30 29 30 29 30 30 0 354 -1762 */{ 5 , 1 , 25 , 45400 },/* 30 29 30 30 29 29 29 30 29 30 29 30 30 384 -1763 */{ 0 , 2 , 13 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354 -1764 */{ 0 , 2 , 2 , 46368 },/* 30 29 30 30 29 30 29 30 29 29 30 29 0 354 -1765 */{ 2 , 1 , 21 , 46480 },/* 30 29 30 30 29 30 29 30 30 29 29 30 29 384 -1766 */{ 0 , 2 , 9 , 44384 },/* 30 29 30 29 30 30 29 30 29 30 30 29 0 355 -1767 */{ 7 , 1 , 30 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 29 384 -1768 */{ 0 , 2 , 18 , 21360 },/* 29 30 29 30 29 29 30 30 29 30 30 30 0 355 -1769 */{ 0 , 2 , 7 , 17776 },/* 29 30 29 29 29 30 29 30 29 30 30 30 0 354 -1770 */{ 5 , 1 , 27 , 25272 },/* 29 30 30 29 29 29 30 29 30 29 30 30 30 384 -1771 */{ 0 , 2 , 15 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354 -1772 */{ 0 , 2 , 4 , 26960 },/* 29 30 30 29 30 29 29 30 29 30 29 30 0 354 -1773 */{ 3 , 1 , 23 , 27816 },/* 29 30 30 29 30 30 29 29 30 29 30 29 30 384 -1774 */{ 0 , 2 , 11 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354 -1775 */{ 10 , 1 , 31 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 29 384 -1776 */{ 0 , 2 , 19 , 42704 },/* 30 29 30 29 29 30 30 29 30 30 29 30 0 355 -1777 */{ 0 , 2 , 8 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354 -1778 */{ 6 , 1 , 28 , 38256 },/* 30 29 29 30 29 30 29 30 29 30 30 30 29 384 -1779 */{ 0 , 2 , 16 , 42336 },/* 30 29 30 29 29 30 29 30 29 30 30 29 0 354 -1780 */{ 0 , 2 , 5 , 53920 },/* 30 30 29 30 29 29 30 29 30 29 30 29 0 354 -1781 */{ 5 , 1 , 24 , 59728 },/* 30 30 30 29 30 29 29 30 29 30 29 30 29 384 -1782 */{ 0 , 2 , 12 , 54608 },/* 30 30 29 30 29 30 29 30 29 30 29 30 0 355 -1783 */{ 0 , 2 , 2 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354 -1784 */{ 3 , 1 , 22 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 29 384 -1785 */{ 0 , 2 , 9 , 42704 },/* 30 29 30 29 29 30 30 29 30 30 29 30 0 355 -1786 */{ 7 , 1 , 30 , 19176 },/* 29 30 29 29 30 29 30 29 30 30 30 29 30 384 -1787 */{ 0 , 2 , 18 , 19120 },/* 29 30 29 29 30 29 30 29 30 29 30 30 0 354 -1788 */{ 0 , 2 , 7 , 43216 },/* 30 29 30 29 30 29 29 29 30 30 29 30 0 354 -1789 */{ 5 , 1 , 26 , 53928 },/* 30 30 29 30 29 29 30 29 30 29 30 29 30 384 -1790 */{ 0 , 2 , 14 , 45728 },/* 30 29 30 30 29 29 30 29 30 29 30 29 0 354 -1791 */{ 0 , 2 , 3 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355 -1792 */{ 4 , 1 , 24 , 22184 },/* 29 30 29 30 29 30 30 29 30 29 30 29 30 384 -1793 */{ 0 , 2 , 11 , 19872 },/* 29 30 29 29 30 30 29 30 30 29 30 29 0 354 -1794 */{ 0 , 1 , 31 , 38352 },/* 30 29 29 30 29 30 29 30 30 30 29 30 0 355 -1795 */{ 2 , 1 , 21 , 19128 },/* 29 30 29 29 30 29 30 29 30 29 30 30 30 384 -1796 */{ 0 , 2 , 9 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354 -1797 */{ 6 , 1 , 28 , 43192 },/* 30 29 30 29 30 29 29 29 30 29 30 30 30 384 -1798 */{ 0 , 2 , 16 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 0 354 -1799 */{ 0 , 2 , 5 , 27280 },/* 29 30 30 29 30 29 30 29 30 29 29 30 0 354 -1800 */{ 4 , 1 , 25 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 29 384 -1801 */{ 0 , 2 , 13 , 27472 },/* 29 30 30 29 30 29 30 30 29 30 29 30 0 355 -1802 */{ 0 , 2 , 3 , 11168 },/* 29 29 30 29 30 29 30 30 30 29 30 29 0 354 -1803 */{ 2 , 1 , 23 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 29 384 -1804 */{ 0 , 2 , 11 , 37744 },/* 30 29 29 30 29 29 30 30 29 30 30 30 0 355 -1805 */{ 6 , 1 , 31 , 20848 },/* 29 30 29 30 29 29 29 30 29 30 30 30 29 383 -1806 */{ 0 , 2 , 18 , 53600 },/* 30 30 29 30 29 29 29 30 29 30 30 29 0 354 -1807 */{ 0 , 2 , 7 , 58544 },/* 30 30 30 29 29 30 29 29 30 29 30 30 0 355 -1808 */{ 5 , 1 , 28 , 27280 },/* 29 30 30 29 30 29 30 29 30 29 29 30 29 383 -1809 */{ 0 , 2 , 14 , 55952 },/* 30 30 29 30 30 29 30 29 30 29 29 30 0 355 -1810 */{ 0 , 2 , 4 , 23376 },/* 29 30 29 30 30 29 30 30 29 30 29 30 0 355 -1811 */{ 3 , 1 , 25 , 11112 },/* 29 29 30 29 30 29 30 30 29 30 30 29 30 384 -1812 */{ 0 , 2 , 13 , 10976 },/* 29 29 30 29 30 29 30 29 30 30 30 29 0 354 -1813 */{ 0 , 2 , 1 , 41696 },/* 30 29 30 29 29 29 30 29 30 30 30 29 0 354 -1814 */{ 2 , 1 , 21 , 53608 },/* 30 30 29 30 29 29 29 30 29 30 30 29 30 384 -1815 */{ 0 , 2 , 9 , 51536 },/* 30 30 29 29 30 29 29 30 29 30 29 30 0 354 -1816 */{ 6 , 1 , 29 , 54440 },/* 30 30 29 30 29 30 29 29 30 29 30 29 30 384 -1817 */{ 0 , 2 , 16 , 46368 },/* 30 29 30 30 29 30 29 30 29 29 30 29 0 354 -1818 */{ 0 , 2 , 5 , 46736 },/* 30 29 30 30 29 30 30 29 30 29 29 30 0 355 -1819 */{ 4 , 1 , 26 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 29 384 -1820 */{ 0 , 2 , 14 , 21968 },/* 29 30 29 30 29 30 29 30 30 30 29 30 0 355 -1821 */{ 0 , 2 , 3 , 9680 },/* 29 29 30 29 29 30 29 30 30 30 29 30 0 354 -1822 */{ 3 , 1 , 23 , 41688 },/* 30 29 30 29 29 29 30 29 30 30 29 30 30 384 -1823 */{ 0 , 2 , 11 , 41648 },/* 30 29 30 29 29 29 30 29 30 29 30 30 0 354 -1824 */{ 7 , 1 , 31 , 43352 },/* 30 29 30 29 30 29 29 30 29 30 29 30 30 384 -1825 */{ 0 , 2 , 18 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354 -1826 */{ 0 , 2 , 7 , 46240 },/* 30 29 30 30 29 30 29 29 30 29 30 29 0 354 -1827 */{ 5 , 1 , 27 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 29 384 -1828 */{ 0 , 2 , 15 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355 -1829 */{ 0 , 2 , 4 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 0 355 -1830 */{ 4 , 1 , 25 , 9656 },/* 29 29 30 29 29 30 29 30 30 29 30 30 30 384 -1831 */{ 0 , 2 , 13 , 9584 },/* 29 29 30 29 29 30 29 30 29 30 30 30 0 354 -1832 */{ 9 , 2 , 2 , 21176 },/* 29 30 29 30 29 29 30 29 30 29 30 30 30 384 -1833 */{ 0 , 2 , 20 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354 -1834 */{ 0 , 2 , 9 , 26960 },/* 29 30 30 29 30 29 29 30 29 30 29 30 0 354 -1835 */{ 6 , 1 , 29 , 27816 },/* 29 30 30 29 30 30 29 29 30 29 30 29 30 384 -1836 */{ 0 , 2 , 17 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354 -1837 */{ 0 , 2 , 5 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 0 355 -1838 */{ 4 , 1 , 26 , 21352 },/* 29 30 29 30 29 29 30 30 29 30 30 29 30 384 -1839 */{ 0 , 2 , 14 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354 -1840 */{ 0 , 2 , 3 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355 -1841 */{ 3 , 1 , 23 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 29 383 -1842 */{ 0 , 2 , 10 , 53920 },/* 30 30 29 30 29 29 30 29 30 29 30 29 0 354 -1843 */{ 7 , 1 , 30 , 59728 },/* 30 30 30 29 30 29 29 30 29 30 29 30 29 384 -1844 */{ 0 , 2 , 18 , 54608 },/* 30 30 29 30 29 30 29 30 29 30 29 30 0 355 -1845 */{ 0 , 2 , 7 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354 -1846 */{ 5 , 1 , 27 , 43728 },/* 30 29 30 29 30 29 30 29 30 30 29 30 29 384 -1847 */{ 0 , 2 , 15 , 38352 },/* 30 29 29 30 29 30 29 30 30 30 29 30 0 355 -1848 */{ 0 , 2 , 5 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354 -1849 */{ 4 , 1 , 24 , 42328 },/* 30 29 30 29 29 30 29 30 29 30 29 30 30 384 -1850 */{ 0 , 2 , 12 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354 -1851 */{ 8 , 2 , 1 , 53848 },/* 30 30 29 30 29 29 30 29 29 30 29 30 30 384 -1852 */{ 0 , 2 , 20 , 45712 },/* 30 29 30 30 29 29 30 29 30 29 29 30 0 354 -1853 */{ 0 , 2 , 8 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355 -1854 */{ 7 , 1 , 29 , 22184 },/* 29 30 29 30 29 30 30 29 30 29 30 29 30 384 -1855 */{ 0 , 2 , 17 , 11680 },/* 29 29 30 29 30 30 29 30 30 29 30 29 0 354 -1856 */{ 0 , 2 , 6 , 38352 },/* 30 29 29 30 29 30 29 30 30 30 29 30 0 355 -1857 */{ 5 , 1 , 26 , 19128 },/* 29 30 29 29 30 29 30 29 30 29 30 30 30 384 -1858 */{ 0 , 2 , 14 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354 -1859 */{ 0 , 2 , 3 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354 -1860 */{ 3 , 1 , 23 , 45656 },/* 30 29 30 30 29 29 30 29 29 30 29 30 30 384 -1861 */{ 0 , 2 , 10 , 27280 },/* 29 30 30 29 30 29 30 29 30 29 29 30 0 354 -1862 */{ 8 , 1 , 30 , 44360 },/* 30 29 30 29 30 30 29 30 29 30 29 29 30 384 -1863 */{ 0 , 2 , 18 , 27472 },/* 29 30 30 29 30 29 30 30 29 30 29 30 0 355 -1864 */{ 0 , 2 , 8 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354 -1865 */{ 5 , 1 , 27 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 29 384 -1866 */{ 0 , 2 , 15 , 37744 },/* 30 29 29 30 29 29 30 30 29 30 30 30 0 355 -1867 */{ 0 , 2 , 5 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354 -1868 */{ 4 , 1 , 25 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 29 383 -1869 */{ 0 , 2 , 11 , 58528 },/* 30 30 30 29 29 30 29 29 30 29 30 29 0 354 -1870 */{ 10 , 1 , 31 , 59984 },/* 30 30 30 29 30 29 30 29 29 30 29 30 29 384 -1871 */{ 0 , 2 , 19 , 55952 },/* 30 30 29 30 30 29 30 29 30 29 29 30 0 355 -1872 */{ 0 , 2 , 9 , 23248 },/* 29 30 29 30 30 29 30 29 30 30 29 30 0 355 -1873 */{ 6 , 1 , 29 , 11112 },/* 29 29 30 29 30 29 30 30 29 30 30 29 30 384 -1874 */{ 0 , 2 , 17 , 10976 },/* 29 29 30 29 30 29 30 29 30 30 30 29 0 354 -1875 */{ 0 , 2 , 6 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354 -1876 */{ 5 , 1 , 26 , 51560 },/* 30 30 29 29 30 29 29 30 29 30 30 29 30 384 -1877 */{ 0 , 2 , 13 , 51536 },/* 30 30 29 29 30 29 29 30 29 30 29 30 0 354 -1878 */{ 0 , 2 , 2 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354 -1879 */{ 3 , 1 , 22 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 29 384 -1880 */{ 0 , 2 , 10 , 46736 },/* 30 29 30 30 29 30 30 29 30 29 29 30 0 355 -1881 */{ 7 , 1 , 30 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 29 384 -1882 */{ 0 , 2 , 18 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 0 355 -1883 */{ 0 , 2 , 8 , 9680 },/* 29 29 30 29 29 30 29 30 30 30 29 30 0 354 -1884 */{ 5 , 1 , 28 , 37592 },/* 30 29 29 30 29 29 30 29 30 30 29 30 30 384 -1885 */{ 0 , 2 , 15 , 37552 },/* 30 29 29 30 29 29 30 29 30 29 30 30 0 354 -1886 */{ 0 , 2 , 4 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354 -1887 */{ 4 , 1 , 24 , 54440 },/* 30 30 29 30 29 30 29 29 30 29 30 29 30 384 -1888 */{ 0 , 2 , 12 , 46240 },/* 30 29 30 30 29 30 29 29 30 29 30 29 0 354 -1889 */{ 0 , 1 , 31 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355 -1890 */{ 2 , 1 , 21 , 22184 },/* 29 30 29 30 29 30 30 29 30 29 30 29 30 384 -1891 */{ 0 , 2 , 9 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 0 355 -1892 */{ 6 , 1 , 30 , 9656 },/* 29 29 30 29 29 30 29 30 30 29 30 30 30 384 -1893 */{ 0 , 2 , 17 , 9584 },/* 29 29 30 29 29 30 29 30 29 30 30 30 0 354 -1894 */{ 0 , 2 , 6 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354 -1895 */{ 5 , 1 , 26 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 29 383 -1896 */{ 0 , 2 , 13 , 59728 },/* 30 30 30 29 30 29 29 30 29 30 29 30 0 355 -1897 */{ 0 , 2 , 2 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354 -1898 */{ 3 , 1 , 22 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 29 384 -1899 */{ 0 , 2 , 10 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 0 355 -1900 */{ 8 , 1 , 31 , 19304 },/* 29 30 29 29 30 29 30 30 29 30 30 29 30 384 -1901 */{ 0 , 2 , 19 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354 -1902 */{ 0 , 2 , 8 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355 -1903 */{ 5 , 1 , 29 , 21096 },/* 29 30 29 30 29 29 30 29 29 30 30 29 30 383 -1904 */{ 0 , 2 , 16 , 53856 },/* 30 30 29 30 29 29 30 29 29 30 30 29 0 354 -1905 */{ 0 , 2 , 4 , 55632 },/* 30 30 29 30 30 29 29 30 29 30 29 30 0 355 -1906 */{ 4 , 1 , 25 , 27304 },/* 29 30 30 29 30 29 30 29 30 29 30 29 30 384 -1907 */{ 0 , 2 , 13 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354 -1908 */{ 0 , 2 , 2 , 39632 },/* 30 29 29 30 30 29 30 29 30 30 29 30 0 355 -1909 */{ 2 , 1 , 22 , 19176 },/* 29 30 29 29 30 29 30 29 30 30 30 29 30 384 -1910 */{ 0 , 2 , 10 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354 -1911 */{ 6 , 1 , 30 , 42200 },/* 30 29 30 29 29 30 29 29 30 30 29 30 30 384 -1912 */{ 0 , 2 , 18 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354 -1913 */{ 0 , 2 , 6 , 53840 },/* 30 30 29 30 29 29 30 29 29 30 29 30 0 354 -1914 */{ 5 , 1 , 26 , 55624 },/* 30 30 29 30 30 29 29 30 29 30 29 29 30 384 -1915 */{ 0 , 2 , 14 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355 -1916 */{ 0 , 2 , 4 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354 -1917 */{ 2 , 1 , 23 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 29 384 -1918 */{ 0 , 2 , 11 , 38352 },/* 30 29 29 30 29 30 29 30 30 30 29 30 0 355 -1919 */{ 7 , 2 , 1 , 19160 },/* 29 30 29 29 30 29 30 29 30 30 29 30 30 384 -1920 */{ 0 , 2 , 20 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354 -1921 */{ 0 , 2 , 8 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354 -1922 */{ 5 , 1 , 28 , 45656 },/* 30 29 30 30 29 29 30 29 29 30 29 30 30 384 -1923 */{ 0 , 2 , 16 , 27280 },/* 29 30 30 29 30 29 30 29 30 29 29 30 0 354 -1924 */{ 0 , 2 , 5 , 44352 },/* 30 29 30 29 30 30 29 30 29 30 29 29 0 354 -1925 */{ 4 , 1 , 24 , 46504 },/* 30 29 30 30 29 30 29 30 30 29 30 29 30 385 -1926 */{ 0 , 2 , 13 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354 -1927 */{ 0 , 2 , 2 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355 -1928 */{ 2 , 1 , 23 , 18872 },/* 29 30 29 29 30 29 29 30 30 29 30 30 30 384 -1929 */{ 0 , 2 , 10 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354 -1930 */{ 6 , 1 , 30 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 29 383 -1931 */{ 0 , 2 , 17 , 58528 },/* 30 30 30 29 29 30 29 29 30 29 30 29 0 354 -1932 */{ 0 , 2 , 6 , 59984 },/* 30 30 30 29 30 29 30 29 29 30 29 30 0 355 -1933 */{ 5 , 1 , 26 , 27976 },/* 29 30 30 29 30 30 29 30 29 30 29 29 30 384 -1934 */{ 0 , 2 , 14 , 23376 },/* 29 30 29 30 30 29 30 30 29 30 29 30 0 355 -1935 */{ 0 , 2 , 4 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354 -1936 */{ 3 , 1 , 24 , 38256 },/* 30 29 29 30 29 30 29 30 29 30 30 30 29 384 -1937 */{ 0 , 2 , 11 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354 -1938 */{ 7 , 1 , 31 , 51560 },/* 30 30 29 29 30 29 29 30 29 30 30 29 30 384 -1939 */{ 0 , 2 , 19 , 51536 },/* 30 30 29 29 30 29 29 30 29 30 29 30 0 354 -1940 */{ 0 , 2 , 8 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354 -1941 */{ 6 , 1 , 27 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 29 384 -1942 */{ 0 , 2 , 15 , 46736 },/* 30 29 30 30 29 30 30 29 30 29 29 30 0 355 -1943 */{ 0 , 2 , 5 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 0 355 -1944 */{ 4 , 1 , 26 , 10968 },/* 29 29 30 29 30 29 30 29 30 30 29 30 30 384 -1945 */{ 0 , 2 , 13 , 9680 },/* 29 29 30 29 29 30 29 30 30 30 29 30 0 354 -1946 */{ 0 , 2 , 2 , 37584 },/* 30 29 29 30 29 29 30 29 30 30 29 30 0 354 -1947 */{ 2 , 1 , 22 , 51544 },/* 30 30 29 29 30 29 29 30 29 30 29 30 30 384 -1948 */{ 0 , 2 , 10 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354 -1949 */{ 7 , 1 , 29 , 54440 },/* 30 30 29 30 29 30 29 29 30 29 30 29 30 384 -1950 */{ 0 , 2 , 17 , 46240 },/* 30 29 30 30 29 30 29 29 30 29 30 29 0 354 -1951 */{ 0 , 2 , 6 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355 -1952 */{ 5 , 1 , 27 , 22184 },/* 29 30 29 30 29 30 30 29 30 29 30 29 30 384 -1953 */{ 0 , 2 , 14 , 19888 },/* 29 30 29 29 30 30 29 30 30 29 30 30 0 355 -1954 */{ 0 , 2 , 4 , 9648 },/* 29 29 30 29 29 30 29 30 30 29 30 30 0 354 -1955 */{ 3 , 1 , 24 , 37560 },/* 30 29 29 30 29 29 30 29 30 29 30 30 30 384 -1956 */{ 0 , 2 , 12 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354 -1957 */{ 8 , 1 , 31 , 43352 },/* 30 29 30 29 30 29 29 30 29 30 29 30 30 384 -1958 */{ 0 , 2 , 19 , 26960 },/* 29 30 30 29 30 29 29 30 29 30 29 30 0 354 -1959 */{ 0 , 2 , 8 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354 -1960 */{ 6 , 1 , 28 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 29 384 -1961 */{ 0 , 2 , 15 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 0 355 -1962 */{ 0 , 2 , 5 , 19296 },/* 29 30 29 29 30 29 30 30 29 30 30 29 0 354 -1963 */{ 4 , 1 , 25 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 29 384 -1964 */{ 0 , 2 , 13 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355 -1965 */{ 0 , 2 , 2 , 21104 },/* 29 30 29 30 29 29 30 29 29 30 30 30 0 354 -1966 */{ 3 , 1 , 22 , 26928 },/* 29 30 30 29 30 29 29 30 29 29 30 30 29 383 -1967 */{ 0 , 2 , 9 , 55632 },/* 30 30 29 30 30 29 29 30 29 30 29 30 0 355 -1968 */{ 7 , 1 , 30 , 27304 },/* 29 30 30 29 30 29 30 29 30 29 30 29 30 384 -1969 */{ 0 , 2 , 17 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354 -1970 */{ 0 , 2 , 6 , 39632 },/* 30 29 29 30 30 29 30 29 30 30 29 30 0 355 -1971 */{ 5 , 1 , 27 , 19176 },/* 29 30 29 29 30 29 30 29 30 30 30 29 30 384 -1972 */{ 0 , 2 , 15 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354 -1973 */{ 0 , 2 , 3 , 42208 },/* 30 29 30 29 29 30 29 29 30 30 30 29 0 354 -1974 */{ 4 , 1 , 23 , 53864 },/* 30 30 29 30 29 29 30 29 29 30 30 29 30 384 -1975 */{ 0 , 2 , 11 , 53840 },/* 30 30 29 30 29 29 30 29 29 30 29 30 0 354 -1976 */{ 8 , 1 , 31 , 54600 },/* 30 30 29 30 29 30 29 30 29 30 29 29 30 384 -1977 */{ 0 , 2 , 18 , 46400 },/* 30 29 30 30 29 30 29 30 29 30 29 29 0 354 -1978 */{ 0 , 2 , 7 , 54944 },/* 30 30 29 30 29 30 30 29 30 29 30 29 0 355 -1979 */{ 6 , 1 , 28 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 29 384 -1980 */{ 0 , 2 , 16 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355 -1981 */{ 0 , 2 , 5 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354 -1982 */{ 4 , 1 , 25 , 42200 },/* 30 29 30 29 29 30 29 29 30 30 29 30 30 384 -1983 */{ 0 , 2 , 13 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354 -1984 */{ 10 , 2 , 2 , 45656 },/* 30 29 30 30 29 29 30 29 29 30 29 30 30 384 -1985 */{ 0 , 2 , 20 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 0 354 -1986 */{ 0 , 2 , 9 , 27968 },/* 29 30 30 29 30 30 29 30 29 30 29 29 0 354 -1987 */{ 6 , 1 , 29 , 46504 },/* 30 29 30 30 29 30 29 30 30 29 30 29 30 385 -1988 */{ 0 , 2 , 18 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354 -1989 */{ 0 , 2 , 6 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355 -1990 */{ 5 , 1 , 27 , 18872 },/* 29 30 29 29 30 29 29 30 30 29 30 30 30 384 -1991 */{ 0 , 2 , 15 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354 -1992 */{ 0 , 2 , 4 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 0 354 -1993 */{ 3 , 1 , 23 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 29 383 -1994 */{ 0 , 2 , 10 , 59984 },/* 30 30 30 29 30 29 30 29 29 30 29 30 0 355 -1995 */{ 8 , 1 , 31 , 27976 },/* 29 30 30 29 30 30 29 30 29 30 29 29 30 384 -1996 */{ 0 , 2 , 19 , 23248 },/* 29 30 29 30 30 29 30 29 30 30 29 30 0 355 -1997 */{ 0 , 2 , 8 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354 -1998 */{ 5 , 1 , 28 , 37744 },/* 30 29 29 30 29 29 30 30 29 30 30 30 29 384 -1999 */{ 0 , 2 , 16 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354 -2000 */{ 0 , 2 , 5 , 51552 },/* 30 30 29 29 30 29 29 30 29 30 30 29 0 354 -2001 */{ 4 , 1 , 24 , 58536 },/* 30 30 30 29 29 30 29 29 30 29 30 29 30 384 -2002 */{ 0 , 2 , 12 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354 -2003 */{ 0 , 2 , 1 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 0 355 -2004 */{ 2 , 1 , 22 , 23208 },/* 29 30 29 30 30 29 30 29 30 29 30 29 30 384 -2005 */{ 0 , 2 , 9 , 22208 },/* 29 30 29 30 29 30 30 29 30 30 29 29 0 354 -2006 */{ 7 , 1 , 29 , 43736 },/* 30 29 30 29 30 29 30 29 30 30 29 30 30 385 -2007 */{ 0 , 2 , 18 , 9680 },/* 29 29 30 29 29 30 29 30 30 30 29 30 0 354 -2008 */{ 0 , 2 , 7 , 37584 },/* 30 29 29 30 29 29 30 29 30 30 29 30 0 354 -2009 */{ 5 , 1 , 26 , 51544 },/* 30 30 29 29 30 29 29 30 29 30 29 30 30 384 -2010 */{ 0 , 2 , 14 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354 -2011 */{ 0 , 2 , 3 , 46240 },/* 30 29 30 30 29 30 29 29 30 29 30 29 0 354 -2012 */{ 3 , 1 , 23 , 47696 },/* 30 29 30 30 30 29 30 29 29 30 29 30 29 384 -2013 */{ 0 , 2 , 10 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355 -2014 */{ 9 , 1 , 31 , 21928 },/* 29 30 29 30 29 30 29 30 30 29 30 29 30 384 -2015 */{ 0 , 2 , 19 , 19360 },/* 29 30 29 29 30 29 30 30 30 29 30 29 0 354 -2016 */{ 0 , 2 , 8 , 42416 },/* 30 29 30 29 29 30 29 30 30 29 30 30 0 355 -2017 */{ 5 , 1 , 28 , 21176 },/* 29 30 29 30 29 29 30 29 30 29 30 30 30 384 -2018 */{ 0 , 2 , 16 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354 -2019 */{ 0 , 2 , 5 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354 -2020 */{ 4 , 1 , 25 , 46248 },/* 30 29 30 30 29 30 29 29 30 29 30 29 30 384 -2021 */{ 0 , 2 , 12 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354 -2022 */{ 0 , 2 , 1 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355 -2023 */{ 2 , 1 , 22 , 21928 },/* 29 30 29 30 29 30 29 30 30 29 30 29 30 384 -2024 */{ 0 , 2 , 10 , 19296 },/* 29 30 29 29 30 29 30 30 29 30 30 29 0 354 -2025 */{ 6 , 1 , 29 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 29 384 -2026 */{ 0 , 2 , 17 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355 -2027 */{ 0 , 2 , 7 , 21104 },/* 29 30 29 30 29 29 30 29 29 30 30 30 0 354 -2028 */{ 5 , 1 , 27 , 26928 },/* 29 30 30 29 30 29 29 30 29 29 30 30 29 383 -2029 */{ 0 , 2 , 13 , 55600 },/* 30 30 29 30 30 29 29 30 29 29 30 30 0 355 -2030 */{ 0 , 2 , 3 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354 -2031 */{ 3 , 1 , 23 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 29 384 -2032 */{ 0 , 2 , 11 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 0 355 -2033 */{ 11 , 1 , 31 , 19176 },/* 29 30 29 29 30 29 30 29 30 30 30 29 30 384 -2034 */{ 0 , 2 , 19 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354 -2035 */{ 0 , 2 , 8 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354 -2036 */{ 6 , 1 , 28 , 53864 },/* 30 30 29 30 29 29 30 29 29 30 30 29 30 384 -2037 */{ 0 , 2 , 15 , 53840 },/* 30 30 29 30 29 29 30 29 29 30 29 30 0 354 -2038 */{ 0 , 2 , 4 , 54560 },/* 30 30 29 30 29 30 29 30 29 29 30 29 0 354 -2039 */{ 5 , 1 , 24 , 55968 },/* 30 30 29 30 30 29 30 29 30 29 30 29 29 384 -2040 */{ 0 , 2 , 12 , 46752 },/* 30 29 30 30 29 30 30 29 30 29 30 29 0 355 -2041 */{ 0 , 2 , 1 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 0 355 -2042 */{ 2 , 1 , 22 , 19160 },/* 29 30 29 29 30 29 30 29 30 30 29 30 30 384 -2043 */{ 0 , 2 , 10 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354 -2044 */{ 7 , 1 , 30 , 42168 },/* 30 29 30 29 29 30 29 29 30 29 30 30 30 384 -2045 */{ 0 , 2 , 17 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354 -2046 */{ 0 , 2 , 6 , 45648 },/* 30 29 30 30 29 29 30 29 29 30 29 30 0 354 -2047 */{ 5 , 1 , 26 , 46376 },/* 30 29 30 30 29 30 29 30 29 29 30 29 30 384 -2048 */{ 0 , 2 , 14 , 27968 },/* 29 30 30 29 30 30 29 30 29 30 29 29 0 354 -2049 */{ 0 , 2 , 2 , 44448 },/* 30 29 30 29 30 30 29 30 30 29 30 29 0 355 -2050 */{ 3 , 1 , 23 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 29 384 - */}; - - - internal override int MinCalendarYear - { - get - { - return (MIN_LUNISOLAR_YEAR); - } - } - - internal override int MaxCalendarYear - { - get - { - return (MAX_LUNISOLAR_YEAR); - } - } - - internal override DateTime MinDate - { - get - { - return (minDate); - } - } - - internal override DateTime MaxDate - { - get - { - return (maxDate); - } - } - - internal override EraInfo[] CalEraInfo - { - get - { - return null; - } - } - - internal override int GetYearInfo(int lunarYear, int index) - { - if ((lunarYear < MIN_LUNISOLAR_YEAR) || (lunarYear > MAX_LUNISOLAR_YEAR)) - { - throw new ArgumentOutOfRangeException( - "year", - String.Format( - CultureInfo.CurrentCulture, - SR.ArgumentOutOfRange_Range, - MIN_LUNISOLAR_YEAR, - MAX_LUNISOLAR_YEAR)); - } - Contract.EndContractBlock(); - return s_yinfo[lunarYear - MIN_LUNISOLAR_YEAR, index]; - } - - internal override int GetYear(int year, DateTime time) - { - return year; - } - - internal override int GetGregorianYear(int year, int era) - { - if (era != CurrentEra && era != GregorianEra) - throw new ArgumentOutOfRangeException(nameof(era), SR.ArgumentOutOfRange_InvalidEraValue); - - if (year < MIN_LUNISOLAR_YEAR || year > MAX_LUNISOLAR_YEAR) - { - throw new ArgumentOutOfRangeException( - nameof(year), - String.Format( - CultureInfo.CurrentCulture, - SR.ArgumentOutOfRange_Range, MIN_LUNISOLAR_YEAR, MAX_LUNISOLAR_YEAR)); - } - Contract.EndContractBlock(); - - return year; - } - - public KoreanLunisolarCalendar() - { - } - - public override int GetEra(DateTime time) - { - CheckTicksRange(time.Ticks); - return (GregorianEra); - } - - internal override CalendarId BaseCalendarID - { - get - { - return (CalendarId.KOREA); - } - } - - internal override CalendarId ID - { - get - { - return (CalendarId.KOREANLUNISOLAR); - } - } - - - - public override int[] Eras - { - get - { - return (new int[] { GregorianEra }); - } - } - } -} diff --git a/src/mscorlib/corefx/System/Globalization/NumberFormatInfo.cs b/src/mscorlib/corefx/System/Globalization/NumberFormatInfo.cs deleted file mode 100644 index 54cf492..0000000 --- a/src/mscorlib/corefx/System/Globalization/NumberFormatInfo.cs +++ /dev/null @@ -1,900 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.Diagnostics.Contracts; -using System.Runtime.Serialization; -using System.Text; - -namespace System.Globalization -{ - // - // Property Default Description - // PositiveSign '+' Character used to indicate positive values. - // NegativeSign '-' Character used to indicate negative values. - // NumberDecimalSeparator '.' The character used as the decimal separator. - // NumberGroupSeparator ',' The character used to separate groups of - // digits to the left of the decimal point. - // NumberDecimalDigits 2 The default number of decimal places. - // NumberGroupSizes 3 The number of digits in each group to the - // left of the decimal point. - // NaNSymbol "NaN" The string used to represent NaN values. - // PositiveInfinitySymbol"Infinity" The string used to represent positive - // infinities. - // NegativeInfinitySymbol"-Infinity" The string used to represent negative - // infinities. - // - // - // - // Property Default Description - // CurrencyDecimalSeparator '.' The character used as the decimal - // separator. - // CurrencyGroupSeparator ',' The character used to separate groups - // of digits to the left of the decimal - // point. - // CurrencyDecimalDigits 2 The default number of decimal places. - // CurrencyGroupSizes 3 The number of digits in each group to - // the left of the decimal point. - // CurrencyPositivePattern 0 The format of positive values. - // CurrencyNegativePattern 0 The format of negative values. - // CurrencySymbol "$" String used as local monetary symbol. - // - - [Serializable] - sealed public class NumberFormatInfo : IFormatProvider, ICloneable - { - // invariantInfo is constant irrespective of your current culture. - private static volatile NumberFormatInfo s_invariantInfo; - - // READTHIS READTHIS READTHIS - // This class has an exact mapping onto a native structure defined in COMNumber.cpp - // DO NOT UPDATE THIS WITHOUT UPDATING THAT STRUCTURE. IF YOU ADD BOOL, ADD THEM AT THE END. - // ALSO MAKE SURE TO UPDATE mscorlib.h in the VM directory to check field offsets. - // READTHIS READTHIS READTHIS - internal int[] numberGroupSizes = new int[] { 3 }; - internal int[] currencyGroupSizes = new int[] { 3 }; - internal int[] percentGroupSizes = new int[] { 3 }; - internal String positiveSign = "+"; - internal String negativeSign = "-"; - internal String numberDecimalSeparator = "."; - internal String numberGroupSeparator = ","; - internal String currencyGroupSeparator = ","; - internal String currencyDecimalSeparator = "."; - internal String currencySymbol = "$"; // TODO: CoreFX #846 Restore to the original value "\x00a4"; // U+00a4 is the symbol for International Monetary Fund. - internal String nanSymbol = "NaN"; - internal String positiveInfinitySymbol = "Infinity"; - internal String negativeInfinitySymbol = "-Infinity"; - internal String percentDecimalSeparator = "."; - internal String percentGroupSeparator = ","; - internal String percentSymbol = "%"; - internal String perMilleSymbol = "\u2030"; - - - [OptionalField(VersionAdded = 2)] - internal String[] nativeDigits = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" }; - - internal int numberDecimalDigits = 2; - internal int currencyDecimalDigits = 2; - internal int currencyPositivePattern = 0; - internal int currencyNegativePattern = 0; - internal int numberNegativePattern = 1; - internal int percentPositivePattern = 0; - internal int percentNegativePattern = 0; - internal int percentDecimalDigits = 2; - - [OptionalField(VersionAdded = 2)] - internal int digitSubstitution = (int) DigitShapes.None; - - internal bool isReadOnly = false; - - // Is this NumberFormatInfo for invariant culture? - - [OptionalField(VersionAdded = 2)] - internal bool m_isInvariant = false; - - public NumberFormatInfo() : this(null) - { - } - - [OnSerializing] - private void OnSerializing(StreamingContext ctx) { } - - [OnDeserializing] - private void OnDeserializing(StreamingContext ctx) { } - - [OnDeserialized] - private void OnDeserialized(StreamingContext ctx) { } - - private static void VerifyDecimalSeparator(String decSep, String propertyName) - { - if (decSep == null) - { - throw new ArgumentNullException(propertyName, - SR.ArgumentNull_String); - } - - if (decSep.Length == 0) - { - throw new ArgumentException(SR.Argument_EmptyDecString); - } - Contract.EndContractBlock(); - } - - private static void VerifyGroupSeparator(String groupSep, String propertyName) - { - if (groupSep == null) - { - throw new ArgumentNullException(propertyName, - SR.ArgumentNull_String); - } - Contract.EndContractBlock(); - } - - private static void VerifyNativeDigits(string [] nativeDig, string propertyName) - { - if (nativeDig == null) - { - throw new ArgumentNullException(propertyName, SR.ArgumentNull_Array); - } - - if (nativeDig.Length != 10) - { - throw new ArgumentException(SR.Argument_InvalidNativeDigitCount, propertyName); - } - Contract.EndContractBlock(); - - for (int i = 0; i < nativeDig.Length; i++) - { - if (nativeDig[i] == null) - { - throw new ArgumentNullException(propertyName, SR.ArgumentNull_ArrayValue); - } - - if (nativeDig[i].Length != 1) - { - if (nativeDig[i].Length != 2) - { - // Not 1 or 2 UTF-16 code points - throw new ArgumentException(SR.Argument_InvalidNativeDigitValue, propertyName); - } - else if (!char.IsSurrogatePair(nativeDig[i][0], nativeDig[i][1])) - { - // 2 UTF-6 code points, but not a surrogate pair - throw new ArgumentException(SR.Argument_InvalidNativeDigitValue, propertyName); - } - } - - if (CharUnicodeInfo.GetDecimalDigitValue(nativeDig[i], 0) != i && - CharUnicodeInfo.GetUnicodeCategory(nativeDig[i], 0) != UnicodeCategory.PrivateUse) - { - // Not the appropriate digit according to the Unicode data properties - // (Digit 0 must be a 0, etc.). - throw new ArgumentException(SR.Argument_InvalidNativeDigitValue, propertyName); - } - } - } - - private static void VerifyDigitSubstitution(DigitShapes digitSub, string propertyName) - { - switch (digitSub) - { - case DigitShapes.Context: - case DigitShapes.None: - case DigitShapes.NativeNational: - // Success. - break; - - default: - throw new ArgumentException(SR.Argument_InvalidDigitSubstitution, propertyName); - } - } - - internal NumberFormatInfo(CultureData cultureData) - { - if (cultureData != null) - { - // We directly use fields here since these data is coming from data table or Win32, so we - // don't need to verify their values (except for invalid parsing situations). - cultureData.GetNFIValues(this); - - if (cultureData.IsInvariantCulture) - { - // For invariant culture - this.m_isInvariant = true; - } - } - } - - [Pure] - private void VerifyWritable() - { - if (isReadOnly) - { - throw new InvalidOperationException(SR.InvalidOperation_ReadOnly); - } - Contract.EndContractBlock(); - } - - // Returns a default NumberFormatInfo that will be universally - // supported and constant irrespective of the current culture. - // Used by FromString methods. - // - - public static NumberFormatInfo InvariantInfo - { - get - { - if (s_invariantInfo == null) - { - // Lazy create the invariant info. This cannot be done in a .cctor because exceptions can - // be thrown out of a .cctor stack that will need this. - NumberFormatInfo nfi = new NumberFormatInfo(); - nfi.m_isInvariant = true; - s_invariantInfo = ReadOnly(nfi); - } - return s_invariantInfo; - } - } - - public static NumberFormatInfo GetInstance(IFormatProvider formatProvider) - { - // Fast case for a regular CultureInfo - NumberFormatInfo info; - CultureInfo cultureProvider = formatProvider as CultureInfo; - if (cultureProvider != null && !cultureProvider.m_isInherited) - { - info = cultureProvider.numInfo; - if (info != null) - { - return info; - } - else - { - return cultureProvider.NumberFormat; - } - } - // Fast case for an NFI; - info = formatProvider as NumberFormatInfo; - if (info != null) - { - return info; - } - if (formatProvider != null) - { - info = formatProvider.GetFormat(typeof(NumberFormatInfo)) as NumberFormatInfo; - if (info != null) - { - return info; - } - } - return CurrentInfo; - } - - - - public Object Clone() - { - NumberFormatInfo n = (NumberFormatInfo)MemberwiseClone(); - n.isReadOnly = false; - return n; - } - - - public int CurrencyDecimalDigits - { - get { return currencyDecimalDigits; } - set - { - if (value < 0 || value > 99) - { - throw new ArgumentOutOfRangeException( - nameof(CurrencyDecimalDigits), - String.Format( - CultureInfo.CurrentCulture, - SR.ArgumentOutOfRange_Range, - 0, - 99)); - } - Contract.EndContractBlock(); - VerifyWritable(); - currencyDecimalDigits = value; - } - } - - - public String CurrencyDecimalSeparator - { - get { return currencyDecimalSeparator; } - set - { - VerifyWritable(); - VerifyDecimalSeparator(value, "CurrencyDecimalSeparator"); - currencyDecimalSeparator = value; - } - } - - - public bool IsReadOnly - { - get - { - return isReadOnly; - } - } - - // - // Check the values of the groupSize array. - // - // Every element in the groupSize array should be between 1 and 9 - // excpet the last element could be zero. - // - internal static void CheckGroupSize(String propName, int[] groupSize) - { - for (int i = 0; i < groupSize.Length; i++) - { - if (groupSize[i] < 1) - { - if (i == groupSize.Length - 1 && groupSize[i] == 0) - return; - throw new ArgumentException(SR.Argument_InvalidGroupSize, propName); - } - else if (groupSize[i] > 9) - { - throw new ArgumentException(SR.Argument_InvalidGroupSize, propName); - } - } - } - - - public int[] CurrencyGroupSizes - { - get - { - return ((int[])currencyGroupSizes.Clone()); - } - set - { - if (value == null) - { - throw new ArgumentNullException(nameof(CurrencyGroupSizes), - SR.ArgumentNull_Obj); - } - Contract.EndContractBlock(); - VerifyWritable(); - - Int32[] inputSizes = (Int32[])value.Clone(); - CheckGroupSize(nameof(CurrencyGroupSizes), inputSizes); - currencyGroupSizes = inputSizes; - } - } - - - - public int[] NumberGroupSizes - { - get - { - return ((int[])numberGroupSizes.Clone()); - } - set - { - if (value == null) - { - throw new ArgumentNullException(nameof(NumberGroupSizes), - SR.ArgumentNull_Obj); - } - Contract.EndContractBlock(); - VerifyWritable(); - - Int32[] inputSizes = (Int32[])value.Clone(); - CheckGroupSize(nameof(NumberGroupSizes), inputSizes); - numberGroupSizes = inputSizes; - } - } - - - public int[] PercentGroupSizes - { - get - { - return ((int[])percentGroupSizes.Clone()); - } - set - { - if (value == null) - { - throw new ArgumentNullException("PercentGroupSizes", - SR.ArgumentNull_Obj); - } - Contract.EndContractBlock(); - VerifyWritable(); - Int32[] inputSizes = (Int32[])value.Clone(); - CheckGroupSize("PercentGroupSizes", inputSizes); - percentGroupSizes = inputSizes; - } - } - - - public String CurrencyGroupSeparator - { - get { return currencyGroupSeparator; } - set - { - VerifyWritable(); - VerifyGroupSeparator(value, nameof(CurrencyGroupSeparator)); - currencyGroupSeparator = value; - } - } - - - public String CurrencySymbol - { - get { return currencySymbol; } - set - { - if (value == null) - { - throw new ArgumentNullException(nameof(CurrencySymbol), - SR.ArgumentNull_String); - } - Contract.EndContractBlock(); - VerifyWritable(); - currencySymbol = value; - } - } - - // Returns the current culture's NumberFormatInfo. Used by Parse methods. - // - - public static NumberFormatInfo CurrentInfo - { - get - { - System.Globalization.CultureInfo culture = CultureInfo.CurrentCulture; - if (!culture.m_isInherited) - { - NumberFormatInfo info = culture.numInfo; - if (info != null) - { - return info; - } - } - return ((NumberFormatInfo)culture.GetFormat(typeof(NumberFormatInfo))); - } - } - - - public String NaNSymbol - { - get - { - return nanSymbol; - } - set - { - if (value == null) - { - throw new ArgumentNullException(nameof(NaNSymbol), - SR.ArgumentNull_String); - } - Contract.EndContractBlock(); - VerifyWritable(); - nanSymbol = value; - } - } - - - - public int CurrencyNegativePattern - { - get { return currencyNegativePattern; } - set - { - if (value < 0 || value > 15) - { - throw new ArgumentOutOfRangeException( - nameof(CurrencyNegativePattern), - String.Format( - CultureInfo.CurrentCulture, - SR.ArgumentOutOfRange_Range, - 0, - 15)); - } - Contract.EndContractBlock(); - VerifyWritable(); - currencyNegativePattern = value; - } - } - - - public int NumberNegativePattern - { - get { return numberNegativePattern; } - set - { - // - // NOTENOTE: the range of value should correspond to negNumberFormats[] in vm\COMNumber.cpp. - // - if (value < 0 || value > 4) - { - throw new ArgumentOutOfRangeException( - nameof(NumberNegativePattern), - String.Format( - CultureInfo.CurrentCulture, - SR.ArgumentOutOfRange_Range, - 0, - 4)); - } - Contract.EndContractBlock(); - VerifyWritable(); - numberNegativePattern = value; - } - } - - - public int PercentPositivePattern - { - get { return percentPositivePattern; } - set - { - // - // NOTENOTE: the range of value should correspond to posPercentFormats[] in vm\COMNumber.cpp. - // - if (value < 0 || value > 3) - { - throw new ArgumentOutOfRangeException( - nameof(PercentPositivePattern), - String.Format( - CultureInfo.CurrentCulture, - SR.ArgumentOutOfRange_Range, - 0, - 3)); - } - Contract.EndContractBlock(); - VerifyWritable(); - percentPositivePattern = value; - } - } - - - public int PercentNegativePattern - { - get { return percentNegativePattern; } - set - { - // - // NOTENOTE: the range of value should correspond to posPercentFormats[] in vm\COMNumber.cpp. - // - if (value < 0 || value > 11) - { - throw new ArgumentOutOfRangeException( - nameof(PercentNegativePattern), - String.Format( - CultureInfo.CurrentCulture, - SR.ArgumentOutOfRange_Range, - 0, - 11)); - } - Contract.EndContractBlock(); - VerifyWritable(); - percentNegativePattern = value; - } - } - - - public String NegativeInfinitySymbol - { - get - { - return negativeInfinitySymbol; - } - set - { - if (value == null) - { - throw new ArgumentNullException(nameof(NegativeInfinitySymbol), - SR.ArgumentNull_String); - } - Contract.EndContractBlock(); - VerifyWritable(); - negativeInfinitySymbol = value; - } - } - - - public String NegativeSign - { - get { return negativeSign; } - set - { - if (value == null) - { - throw new ArgumentNullException(nameof(NegativeSign), - SR.ArgumentNull_String); - } - Contract.EndContractBlock(); - VerifyWritable(); - negativeSign = value; - } - } - - - public int NumberDecimalDigits - { - get { return numberDecimalDigits; } - set - { - if (value < 0 || value > 99) - { - throw new ArgumentOutOfRangeException( - nameof(NumberDecimalDigits), - String.Format( - CultureInfo.CurrentCulture, - SR.ArgumentOutOfRange_Range, - 0, - 99)); - } - Contract.EndContractBlock(); - VerifyWritable(); - numberDecimalDigits = value; - } - } - - - public String NumberDecimalSeparator - { - get { return numberDecimalSeparator; } - set - { - VerifyWritable(); - VerifyDecimalSeparator(value, nameof(NumberDecimalSeparator)); - numberDecimalSeparator = value; - } - } - - - public String NumberGroupSeparator - { - get { return numberGroupSeparator; } - set - { - VerifyWritable(); - VerifyGroupSeparator(value, nameof(NumberGroupSeparator)); - numberGroupSeparator = value; - } - } - - - public int CurrencyPositivePattern - { - get { return currencyPositivePattern; } - set - { - if (value < 0 || value > 3) - { - throw new ArgumentOutOfRangeException( - nameof(CurrencyPositivePattern), - String.Format( - CultureInfo.CurrentCulture, - SR.ArgumentOutOfRange_Range, - 0, - 3)); - } - Contract.EndContractBlock(); - VerifyWritable(); - currencyPositivePattern = value; - } - } - - - public String PositiveInfinitySymbol - { - get - { - return positiveInfinitySymbol; - } - set - { - if (value == null) - { - throw new ArgumentNullException(nameof(PositiveInfinitySymbol), - SR.ArgumentNull_String); - } - Contract.EndContractBlock(); - VerifyWritable(); - positiveInfinitySymbol = value; - } - } - - - public String PositiveSign - { - get { return positiveSign; } - set - { - if (value == null) - { - throw new ArgumentNullException(nameof(PositiveSign), - SR.ArgumentNull_String); - } - Contract.EndContractBlock(); - VerifyWritable(); - positiveSign = value; - } - } - - - public int PercentDecimalDigits - { - get { return percentDecimalDigits; } - set - { - if (value < 0 || value > 99) - { - throw new ArgumentOutOfRangeException( - nameof(PercentDecimalDigits), - String.Format( - CultureInfo.CurrentCulture, - SR.ArgumentOutOfRange_Range, - 0, - 99)); - } - Contract.EndContractBlock(); - VerifyWritable(); - percentDecimalDigits = value; - } - } - - - public String PercentDecimalSeparator - { - get { return percentDecimalSeparator; } - set - { - VerifyWritable(); - VerifyDecimalSeparator(value, nameof(PercentDecimalSeparator)); - percentDecimalSeparator = value; - } - } - - - public String PercentGroupSeparator - { - get { return percentGroupSeparator; } - set - { - VerifyWritable(); - VerifyGroupSeparator(value, nameof(PercentGroupSeparator)); - percentGroupSeparator = value; - } - } - - - public String PercentSymbol - { - get - { - return percentSymbol; - } - set - { - if (value == null) - { - throw new ArgumentNullException(nameof(PercentSymbol), - SR.ArgumentNull_String); - } - Contract.EndContractBlock(); - VerifyWritable(); - percentSymbol = value; - } - } - - - public String PerMilleSymbol - { - get { return perMilleSymbol; } - set - { - if (value == null) - { - throw new ArgumentNullException(nameof(PerMilleSymbol), - SR.ArgumentNull_String); - } - Contract.EndContractBlock(); - VerifyWritable(); - perMilleSymbol = value; - } - } - - public string [] NativeDigits - { - get { return (String[]) nativeDigits.Clone(); } - set - { - VerifyWritable(); - VerifyNativeDigits(value, nameof(NativeDigits)); - nativeDigits = value; - } - } - - public DigitShapes DigitSubstitution - { - get { return (DigitShapes) digitSubstitution; } - set - { - VerifyWritable(); - VerifyDigitSubstitution(value, nameof(DigitSubstitution)); - digitSubstitution = (int) value; - } - } - - public Object GetFormat(Type formatType) - { - return formatType == typeof(NumberFormatInfo) ? this : null; - } - - public static NumberFormatInfo ReadOnly(NumberFormatInfo nfi) - { - if (nfi == null) - { - throw new ArgumentNullException(nameof(nfi)); - } - Contract.EndContractBlock(); - if (nfi.IsReadOnly) - { - return (nfi); - } - NumberFormatInfo info = (NumberFormatInfo)(nfi.MemberwiseClone()); - info.isReadOnly = true; - return info; - } - - // private const NumberStyles InvalidNumberStyles = unchecked((NumberStyles) 0xFFFFFC00); - private const NumberStyles InvalidNumberStyles = ~(NumberStyles.AllowLeadingWhite | NumberStyles.AllowTrailingWhite - | NumberStyles.AllowLeadingSign | NumberStyles.AllowTrailingSign - | NumberStyles.AllowParentheses | NumberStyles.AllowDecimalPoint - | NumberStyles.AllowThousands | NumberStyles.AllowExponent - | NumberStyles.AllowCurrencySymbol | NumberStyles.AllowHexSpecifier); - - internal static void ValidateParseStyleInteger(NumberStyles style) - { - // Check for undefined flags - if ((style & InvalidNumberStyles) != 0) - { - throw new ArgumentException(SR.Argument_InvalidNumberStyles, nameof(style)); - } - Contract.EndContractBlock(); - if ((style & NumberStyles.AllowHexSpecifier) != 0) - { // Check for hex number - if ((style & ~NumberStyles.HexNumber) != 0) - { - throw new ArgumentException(SR.Arg_InvalidHexStyle); - } - } - } - - internal static void ValidateParseStyleFloatingPoint(NumberStyles style) - { - // Check for undefined flags - if ((style & InvalidNumberStyles) != 0) - { - throw new ArgumentException(SR.Argument_InvalidNumberStyles, nameof(style)); - } - Contract.EndContractBlock(); - if ((style & NumberStyles.AllowHexSpecifier) != 0) - { // Check for hex number - throw new ArgumentException(SR.Arg_HexStyleNotSupported); - } - } - } // NumberFormatInfo -} - - - - - - - - - diff --git a/src/mscorlib/corefx/System/Globalization/PersianCalendar.cs b/src/mscorlib/corefx/System/Globalization/PersianCalendar.cs deleted file mode 100644 index b8b3da6..0000000 --- a/src/mscorlib/corefx/System/Globalization/PersianCalendar.cs +++ /dev/null @@ -1,611 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System.Diagnostics; -using System.Diagnostics.Contracts; - -namespace System.Globalization -{ - //////////////////////////////////////////////////////////////////////////// - // - // Notes about PersianCalendar - // - //////////////////////////////////////////////////////////////////////////// - // Modern Persian calendar is a solar observation based calendar. Each new year begins on the day when the vernal equinox occurs before noon. - // The epoch is the date of the vernal equinox prior to the epoch of the Islamic calendar (March 19, 622 Julian or March 22, 622 Gregorian) - - // There is no Persian year 0. Ordinary years have 365 days. Leap years have 366 days with the last month (Esfand) gaining the extra day. - /* - ** Calendar support range: - ** Calendar Minimum Maximum - ** ========== ========== ========== - ** Gregorian 0622/03/22 9999/12/31 - ** Persian 0001/01/01 9378/10/13 - */ - - [Serializable] - public class PersianCalendar : Calendar - { - public static readonly int PersianEra = 1; - - internal static long PersianEpoch = new DateTime(622, 3, 22).Ticks / GregorianCalendar.TicksPerDay; - private const int ApproximateHalfYear = 180; - - internal const int DatePartYear = 0; - internal const int DatePartDayOfYear = 1; - internal const int DatePartMonth = 2; - internal const int DatePartDay = 3; - internal const int MonthsPerYear = 12; - - internal static int[] DaysToMonth = { 0, 31, 62, 93, 124, 155, 186, 216, 246, 276, 306, 336, 366 }; - - internal const int MaxCalendarYear = 9378; - internal const int MaxCalendarMonth = 10; - internal const int MaxCalendarDay = 13; - - // Persian calendar (year: 1, month: 1, day:1 ) = Gregorian (year: 622, month: 3, day: 22) - // This is the minimal Gregorian date that we support in the PersianCalendar. - internal static DateTime minDate = new DateTime(622, 3, 22); - internal static DateTime maxDate = DateTime.MaxValue; - - public override DateTime MinSupportedDateTime - { - get - { - return (minDate); - } - } - - public override DateTime MaxSupportedDateTime - { - get - { - return (maxDate); - } - } - - public override CalendarAlgorithmType AlgorithmType - { - get - { - return CalendarAlgorithmType.SolarCalendar; - } - } - - // Construct an instance of Persian calendar. - - public PersianCalendar() - { - } - - - internal override CalendarId BaseCalendarID - { - get - { - return CalendarId.GREGORIAN; - } - } - - internal override CalendarId ID - { - get - { - return CalendarId.PERSIAN; - } - } - - - /*=================================GetAbsoluteDatePersian========================== - **Action: Gets the Absolute date for the given Persian date. The absolute date means - ** the number of days from January 1st, 1 A.D. - **Returns: - **Arguments: - **Exceptions: - ============================================================================*/ - - private long GetAbsoluteDatePersian(int year, int month, int day) - { - if (year >= 1 && year <= MaxCalendarYear && month >= 1 && month <= 12) - { - int ordinalDay = DaysInPreviousMonths(month) + day - 1; // day is one based, make 0 based since this will be the number of days we add to beginning of year below - int approximateDaysFromEpochForYearStart = (int)(CalendricalCalculationsHelper.MeanTropicalYearInDays * (year - 1)); - long yearStart = CalendricalCalculationsHelper.PersianNewYearOnOrBefore(PersianEpoch + approximateDaysFromEpochForYearStart + ApproximateHalfYear); - yearStart += ordinalDay; - return yearStart; - } - throw new ArgumentOutOfRangeException(null, SR.ArgumentOutOfRange_BadYearMonthDay); - } - - internal static void CheckTicksRange(long ticks) - { - if (ticks < minDate.Ticks || ticks > maxDate.Ticks) - { - throw new ArgumentOutOfRangeException( - "time", - String.Format( - CultureInfo.InvariantCulture, - SR.ArgumentOutOfRange_CalendarRange, - minDate, - maxDate)); - } - } - - internal static void CheckEraRange(int era) - { - if (era != CurrentEra && era != PersianEra) - { - throw new ArgumentOutOfRangeException(nameof(era), SR.ArgumentOutOfRange_InvalidEraValue); - } - } - - internal static void CheckYearRange(int year, int era) - { - CheckEraRange(era); - if (year < 1 || year > MaxCalendarYear) - { - throw new ArgumentOutOfRangeException( - nameof(year), - String.Format( - CultureInfo.CurrentCulture, - SR.ArgumentOutOfRange_Range, - 1, - MaxCalendarYear)); - } - } - - internal static void CheckYearMonthRange(int year, int month, int era) - { - CheckYearRange(year, era); - if (year == MaxCalendarYear) - { - if (month > MaxCalendarMonth) - { - throw new ArgumentOutOfRangeException( - nameof(month), - String.Format( - CultureInfo.CurrentCulture, - SR.ArgumentOutOfRange_Range, - 1, - MaxCalendarMonth)); - } - } - - if (month < 1 || month > 12) - { - throw new ArgumentOutOfRangeException(nameof(month), SR.ArgumentOutOfRange_Month); - } - } - - private static int MonthFromOrdinalDay(int ordinalDay) - { - Debug.Assert(ordinalDay <= 366); - int index = 0; - while (ordinalDay > DaysToMonth[index]) - index++; - - return index; - } - - private static int DaysInPreviousMonths(int month) - { - Debug.Assert(1 <= month && month <= 12); - --month; // months are one based but for calculations use 0 based - return DaysToMonth[month]; - } - - /*=================================GetDatePart========================== - **Action: Returns a given date part of this DateTime. This method is used - ** to compute the year, day-of-year, month, or day part. - **Returns: - **Arguments: - **Exceptions: ArgumentException if part is incorrect. - ============================================================================*/ - - internal int GetDatePart(long ticks, int part) - { - long NumDays; // The calculation buffer in number of days. - - CheckTicksRange(ticks); - - // - // Get the absolute date. The absolute date is the number of days from January 1st, 1 A.D. - // 1/1/0001 is absolute date 1. - // - NumDays = ticks / GregorianCalendar.TicksPerDay + 1; - - // - // Calculate the appromixate Persian Year. - // - - long yearStart = CalendricalCalculationsHelper.PersianNewYearOnOrBefore(NumDays); - int y = (int)(Math.Floor(((yearStart - PersianEpoch) / CalendricalCalculationsHelper.MeanTropicalYearInDays) + 0.5)) + 1; - Debug.Assert(y >= 1); - - if (part == DatePartYear) - { - return y; - } - - // - // Calculate the Persian Month. - // - - int ordinalDay = (int)(NumDays - CalendricalCalculationsHelper.GetNumberOfDays(this.ToDateTime(y, 1, 1, 0, 0, 0, 0, 1))); - - if (part == DatePartDayOfYear) - { - return ordinalDay; - } - - int m = MonthFromOrdinalDay(ordinalDay); - Debug.Assert(ordinalDay >= 1); - Debug.Assert(m >= 1 && m <= 12); - if (part == DatePartMonth) - { - return m; - } - - int d = ordinalDay - DaysInPreviousMonths(m); - Debug.Assert(1 <= d); - Debug.Assert(d <= 31); - - // - // Calculate the Persian Day. - // - - if (part == DatePartDay) - { - return (d); - } - - // Incorrect part value. - throw new InvalidOperationException(SR.InvalidOperation_DateTimeParsing); - } - - // Returns the DateTime resulting from adding the given number of - // months to the specified DateTime. The result is computed by incrementing - // (or decrementing) the year and month parts of the specified DateTime by - // value months, and, if required, adjusting the day part of the - // resulting date downwards to the last day of the resulting month in the - // resulting year. The time-of-day part of the result is the same as the - // time-of-day part of the specified DateTime. - // - // In more precise terms, considering the specified DateTime to be of the - // form y / m / d + t, where y is the - // year, m is the month, d is the day, and t is the - // time-of-day, the result is y1 / m1 / d1 + t, - // where y1 and m1 are computed by adding value months - // to y and m, and d1 is the largest value less than - // or equal to d that denotes a valid day in month m1 of year - // y1. - // - - - public override DateTime AddMonths(DateTime time, int months) - { - if (months < -120000 || months > 120000) - { - throw new ArgumentOutOfRangeException( - nameof(months), - String.Format( - CultureInfo.CurrentCulture, - SR.ArgumentOutOfRange_Range, - -120000, - 120000)); - } - Contract.EndContractBlock(); - // Get the date in Persian calendar. - int y = GetDatePart(time.Ticks, DatePartYear); - int m = GetDatePart(time.Ticks, DatePartMonth); - int d = GetDatePart(time.Ticks, DatePartDay); - int i = m - 1 + months; - if (i >= 0) - { - m = i % 12 + 1; - y = y + i / 12; - } - else - { - m = 12 + (i + 1) % 12; - y = y + (i - 11) / 12; - } - int days = GetDaysInMonth(y, m); - if (d > days) - { - d = days; - } - long ticks = GetAbsoluteDatePersian(y, m, d) * TicksPerDay + time.Ticks % TicksPerDay; - Calendar.CheckAddResult(ticks, MinSupportedDateTime, MaxSupportedDateTime); - return (new DateTime(ticks)); - } - - // Returns the DateTime resulting from adding the given number of - // years to the specified DateTime. The result is computed by incrementing - // (or decrementing) the year part of the specified DateTime by value - // years. If the month and day of the specified DateTime is 2/29, and if the - // resulting year is not a leap year, the month and day of the resulting - // DateTime becomes 2/28. Otherwise, the month, day, and time-of-day - // parts of the result are the same as those of the specified DateTime. - // - - - public override DateTime AddYears(DateTime time, int years) - { - return (AddMonths(time, years * 12)); - } - - // Returns the day-of-month part of the specified DateTime. The returned - // value is an integer between 1 and 31. - // - - - public override int GetDayOfMonth(DateTime time) - { - return (GetDatePart(time.Ticks, DatePartDay)); - } - - // Returns the day-of-week part of the specified DateTime. The returned value - // is an integer between 0 and 6, where 0 indicates Sunday, 1 indicates - // Monday, 2 indicates Tuesday, 3 indicates Wednesday, 4 indicates - // Thursday, 5 indicates Friday, and 6 indicates Saturday. - // - - - public override DayOfWeek GetDayOfWeek(DateTime time) - { - return ((DayOfWeek)((int)(time.Ticks / TicksPerDay + 1) % 7)); - } - - // Returns the day-of-year part of the specified DateTime. The returned value - // is an integer between 1 and 366. - // - - - public override int GetDayOfYear(DateTime time) - { - return (GetDatePart(time.Ticks, DatePartDayOfYear)); - } - - // Returns the number of days in the month given by the year and - // month arguments. - // - - - public override int GetDaysInMonth(int year, int month, int era) - { - CheckYearMonthRange(year, month, era); - - if ((month == MaxCalendarMonth) && (year == MaxCalendarYear)) - { - return MaxCalendarDay; - } - - int daysInMonth = DaysToMonth[month] - DaysToMonth[month - 1]; - if ((month == MonthsPerYear) && !IsLeapYear(year)) - { - Debug.Assert(daysInMonth == 30); - --daysInMonth; - } - return daysInMonth; - } - - // Returns the number of days in the year given by the year argument for the current era. - // - - public override int GetDaysInYear(int year, int era) - { - CheckYearRange(year, era); - if (year == MaxCalendarYear) - { - return DaysToMonth[MaxCalendarMonth - 1] + MaxCalendarDay; - } - // Common years have 365 days. Leap years have 366 days. - return (IsLeapYear(year, CurrentEra) ? 366 : 365); - } - - // Returns the era for the specified DateTime value. - - - public override int GetEra(DateTime time) - { - CheckTicksRange(time.Ticks); - return (PersianEra); - } - - - - public override int[] Eras - { - get - { - return (new int[] { PersianEra }); - } - } - - // Returns the month part of the specified DateTime. The returned value is an - // integer between 1 and 12. - // - - - public override int GetMonth(DateTime time) - { - return (GetDatePart(time.Ticks, DatePartMonth)); - } - - // Returns the number of months in the specified year and era. - - - public override int GetMonthsInYear(int year, int era) - { - CheckYearRange(year, era); - if (year == MaxCalendarYear) - { - return MaxCalendarMonth; - } - return (12); - } - - // Returns the year part of the specified DateTime. The returned value is an - // integer between 1 and MaxCalendarYear. - // - - - public override int GetYear(DateTime time) - { - return (GetDatePart(time.Ticks, DatePartYear)); - } - - // Checks whether a given day in the specified era is a leap day. This method returns true if - // the date is a leap day, or false if not. - // - - - public override bool IsLeapDay(int year, int month, int day, int era) - { - // The year/month/era value checking is done in GetDaysInMonth(). - int daysInMonth = GetDaysInMonth(year, month, era); - if (day < 1 || day > daysInMonth) - { - throw new ArgumentOutOfRangeException( - nameof(day), - String.Format( - CultureInfo.CurrentCulture, - SR.ArgumentOutOfRange_Day, - daysInMonth, - month)); - } - return (IsLeapYear(year, era) && month == 12 && day == 30); - } - - // Returns the leap month in a calendar year of the specified era. This method returns 0 - // if this calendar does not have leap month, or this year is not a leap year. - // - - - public override int GetLeapMonth(int year, int era) - { - CheckYearRange(year, era); - return (0); - } - - // Checks whether a given month in the specified era is a leap month. This method returns true if - // month is a leap month, or false if not. - // - - - public override bool IsLeapMonth(int year, int month, int era) - { - CheckYearMonthRange(year, month, era); - return (false); - } - - // Checks whether a given year in the specified era is a leap year. This method returns true if - // year is a leap year, or false if not. - // - - public override bool IsLeapYear(int year, int era) - { - CheckYearRange(year, era); - - if (year == MaxCalendarYear) - { - return false; - } - - return (GetAbsoluteDatePersian(year + 1, 1, 1) - GetAbsoluteDatePersian(year, 1, 1)) == 366; - } - - // Returns the date and time converted to a DateTime value. Throws an exception if the n-tuple is invalid. - // - - - public override DateTime ToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era) - { - // The year/month/era checking is done in GetDaysInMonth(). - int daysInMonth = GetDaysInMonth(year, month, era); - if (day < 1 || day > daysInMonth) - { - // BCLDebug.Log("year = " + year + ", month = " + month + ", day = " + day); - throw new ArgumentOutOfRangeException( - nameof(day), - String.Format( - CultureInfo.CurrentCulture, - SR.ArgumentOutOfRange_Day, - daysInMonth, - month)); - } - - long lDate = GetAbsoluteDatePersian(year, month, day); - - if (lDate >= 0) - { - return (new DateTime(lDate * GregorianCalendar.TicksPerDay + TimeToTicks(hour, minute, second, millisecond))); - } - else - { - throw new ArgumentOutOfRangeException(null, SR.ArgumentOutOfRange_BadYearMonthDay); - } - } - - private const int DEFAULT_TWO_DIGIT_YEAR_MAX = 1410; - - public override int TwoDigitYearMax - { - get - { - if (twoDigitYearMax == -1) - { - twoDigitYearMax = GetSystemTwoDigitYearSetting(ID, DEFAULT_TWO_DIGIT_YEAR_MAX); - } - return (twoDigitYearMax); - } - - set - { - VerifyWritable(); - if (value < 99 || value > MaxCalendarYear) - { - throw new ArgumentOutOfRangeException( - nameof(value), - String.Format( - CultureInfo.CurrentCulture, - SR.ArgumentOutOfRange_Range, - 99, - MaxCalendarYear)); - } - twoDigitYearMax = value; - } - } - - - - public override int ToFourDigitYear(int year) - { - if (year < 0) - { - throw new ArgumentOutOfRangeException(nameof(year), - SR.ArgumentOutOfRange_NeedNonNegNum); - } - Contract.EndContractBlock(); - - if (year < 100) - { - return (base.ToFourDigitYear(year)); - } - - if (year > MaxCalendarYear) - { - throw new ArgumentOutOfRangeException( - nameof(year), - String.Format( - CultureInfo.CurrentCulture, - SR.ArgumentOutOfRange_Range, - 1, - MaxCalendarYear)); - } - return (year); - } - } -} diff --git a/src/mscorlib/corefx/System/Globalization/RegionInfo.cs b/src/mscorlib/corefx/System/Globalization/RegionInfo.cs deleted file mode 100644 index 15679d2..0000000 --- a/src/mscorlib/corefx/System/Globalization/RegionInfo.cs +++ /dev/null @@ -1,421 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -//////////////////////////////////////////////////////////////////////////// -// -// -// Purpose: This class represents settings specified by de jure or -// de facto standards for a particular country/region. In -// contrast to CultureInfo, the RegionInfo does not represent -// preferences of the user and does not depend on the user's -// language or culture. -// -// -//////////////////////////////////////////////////////////////////////////// - -using System.Diagnostics; -using System.Diagnostics.Contracts; -using System.Runtime.Serialization; - -namespace System.Globalization -{ - [Serializable] - public class RegionInfo - { - //--------------------------------------------------------------------// - // Internal Information // - //--------------------------------------------------------------------// - - // - // Variables. - // - - // - // Name of this region (ie: es-US): serialized, the field used for deserialization - // - internal String _name; - - // - // The CultureData instance that we are going to read data from. - // - internal CultureData _cultureData; - - // - // The RegionInfo for our current region - // - internal static volatile RegionInfo s_currentRegionInfo; - - - //////////////////////////////////////////////////////////////////////// - // - // RegionInfo Constructors - // - // Note: We prefer that a region be created with a full culture name (ie: en-US) - // because otherwise the native strings won't be right. - // - // In Silverlight we enforce that RegionInfos must be created with a full culture name - // - //////////////////////////////////////////////////////////////////////// - public RegionInfo(String name) - { - if (name == null) - throw new ArgumentNullException(nameof(name)); - - if (name.Length == 0) //The InvariantCulture has no matching region - { - throw new ArgumentException(SR.Argument_NoRegionInvariantCulture, nameof(name)); - } - - Contract.EndContractBlock(); - - // - // For CoreCLR we only want the region names that are full culture names - // - _cultureData = CultureData.GetCultureDataForRegion(name, true); - if (_cultureData == null) - throw new ArgumentException( - String.Format( - CultureInfo.CurrentCulture, - SR.Argument_InvalidCultureName, name), nameof(name)); - - - // Not supposed to be neutral - if (_cultureData.IsNeutralCulture) - throw new ArgumentException(SR.Format(SR.Argument_InvalidNeutralRegionName, name), nameof(name)); - - SetName(name); - } - - public RegionInfo(int culture) - { - if (culture == CultureInfo.LOCALE_INVARIANT) //The InvariantCulture has no matching region - { - throw new ArgumentException(SR.Argument_NoRegionInvariantCulture); - } - - if (culture == CultureInfo.LOCALE_NEUTRAL) - { - // Not supposed to be neutral - throw new ArgumentException(SR.Format(SR.Argument_CultureIsNeutral, culture), nameof(culture)); - } - - if (culture == CultureInfo.LOCALE_CUSTOM_DEFAULT) - { - // Not supposed to be neutral - throw new ArgumentException(SR.Format(SR.Argument_CustomCultureCannotBePassedByNumber, culture), nameof(culture)); - } - - _cultureData = CultureData.GetCultureData(culture, true); - _name = _cultureData.SREGIONNAME; - - if (_cultureData.IsNeutralCulture) - { - // Not supposed to be neutral - throw new ArgumentException(SR.Format(SR.Argument_CultureIsNeutral, culture), nameof(culture)); - } - } - - internal RegionInfo(CultureData cultureData) - { - _cultureData = cultureData; - _name = _cultureData.SREGIONNAME; - } - - private void SetName(string name) - { - // Use the name of the region we found - _name = _cultureData.SREGIONNAME; - } - - [OnSerializing] - private void OnSerializing(StreamingContext ctx) { } - - [OnDeserialized] - private void OnDeserialized(StreamingContext ctx) - { - _cultureData = CultureData.GetCultureData(_name, true); - - if (_cultureData == null) - { - throw new ArgumentException( - String.Format(CultureInfo.CurrentCulture, SR.Argument_InvalidCultureName, _name), - "_name"); - } - - _name = _cultureData.SREGIONNAME; - } - - //////////////////////////////////////////////////////////////////////// - // - // GetCurrentRegion - // - // This instance provides methods based on the current user settings. - // These settings are volatile and may change over the lifetime of the - // thread. - // - //////////////////////////////////////////////////////////////////////// - public static RegionInfo CurrentRegion - { - get - { - RegionInfo temp = s_currentRegionInfo; - if (temp == null) - { - temp = new RegionInfo(CultureInfo.CurrentCulture.m_cultureData); - - // Need full name for custom cultures - temp._name = temp._cultureData.SREGIONNAME; - s_currentRegionInfo = temp; - } - return temp; - } - } - - //////////////////////////////////////////////////////////////////////// - // - // GetName - // - // Returns the name of the region (ie: en-US) - // - //////////////////////////////////////////////////////////////////////// - public virtual String Name - { - get - { - Debug.Assert(_name != null, "Expected RegionInfo._name to be populated already"); - return (_name); - } - } - - //////////////////////////////////////////////////////////////////////// - // - // GetEnglishName - // - // Returns the name of the region in English. (ie: United States) - // - //////////////////////////////////////////////////////////////////////// - public virtual String EnglishName - { - get - { - return (_cultureData.SENGCOUNTRY); - } - } - - - //////////////////////////////////////////////////////////////////////// - // - // GetDisplayName - // - // Returns the display name (localized) of the region. (ie: United States - // if the current UI language is en-US) - // - //////////////////////////////////////////////////////////////////////// - public virtual String DisplayName - { - get - { - return (_cultureData.SLOCALIZEDCOUNTRY); - } - } - - - //////////////////////////////////////////////////////////////////////// - // - // GetNativeName - // - // Returns the native name of the region. (ie: Deutschland) - // WARNING: You need a full locale name for this to make sense. - // - //////////////////////////////////////////////////////////////////////// - public virtual String NativeName - { - get - { - return (_cultureData.SNATIVECOUNTRY); - } - } - - //////////////////////////////////////////////////////////////////////// - // - // TwoLetterISORegionName - // - // Returns the two letter ISO region name (ie: US) - // - //////////////////////////////////////////////////////////////////////// - public virtual String TwoLetterISORegionName - { - get - { - return (_cultureData.SISO3166CTRYNAME); - } - } - - //////////////////////////////////////////////////////////////////////// - // - // ThreeLetterISORegionName - // - // Returns the three letter ISO region name (ie: USA) - // - //////////////////////////////////////////////////////////////////////// - public virtual String ThreeLetterISORegionName - { - get - { - return (_cultureData.SISO3166CTRYNAME2); - } - } - - //////////////////////////////////////////////////////////////////////// - // - // ThreeLetterWindowsRegionName - // - // Returns the three letter windows region name (ie: USA) - // - //////////////////////////////////////////////////////////////////////// - public virtual String ThreeLetterWindowsRegionName - { - get - { - // ThreeLetterWindowsRegionName is really same as ThreeLetterISORegionName - return ThreeLetterISORegionName; - } - } - - - //////////////////////////////////////////////////////////////////////// - // - // IsMetric - // - // Returns true if this region uses the metric measurement system - // - //////////////////////////////////////////////////////////////////////// - public virtual bool IsMetric - { - get - { - int value = _cultureData.IMEASURE; - return (value == 0); - } - } - - public virtual int GeoId - { - get - { - return (_cultureData.IGEOID); - } - } - - //////////////////////////////////////////////////////////////////////// - // - // CurrencyEnglishName - // - // English name for this region's currency, ie: Swiss Franc - // - //////////////////////////////////////////////////////////////////////// - public virtual string CurrencyEnglishName - { - get - { - return (_cultureData.SENGLISHCURRENCY); - } - } - - //////////////////////////////////////////////////////////////////////// - // - // CurrencyNativeName - // - // Native name for this region's currency, ie: Schweizer Franken - // WARNING: You need a full locale name for this to make sense. - // - //////////////////////////////////////////////////////////////////////// - public virtual string CurrencyNativeName - { - get - { - return (_cultureData.SNATIVECURRENCY); - } - } - - //////////////////////////////////////////////////////////////////////// - // - // CurrencySymbol - // - // Currency Symbol for this locale, ie: Fr. or $ - // - //////////////////////////////////////////////////////////////////////// - public virtual String CurrencySymbol - { - get - { - return (_cultureData.SCURRENCY); - } - } - - //////////////////////////////////////////////////////////////////////// - // - // ISOCurrencySymbol - // - // ISO Currency Symbol for this locale, ie: CHF - // - //////////////////////////////////////////////////////////////////////// - public virtual String ISOCurrencySymbol - { - get - { - return (_cultureData.SINTLSYMBOL); - } - } - - //////////////////////////////////////////////////////////////////////// - // - // Equals - // - // Implements Object.Equals(). Returns a boolean indicating whether - // or not object refers to the same RegionInfo as the current instance. - // - // RegionInfos are considered equal if and only if they have the same name - // (ie: en-US) - // - //////////////////////////////////////////////////////////////////////// - public override bool Equals(Object value) - { - RegionInfo that = value as RegionInfo; - if (that != null) - { - return this.Name.Equals(that.Name); - } - - return (false); - } - - //////////////////////////////////////////////////////////////////////// - // - // GetHashCode - // - // Implements Object.GetHashCode(). Returns the hash code for the - // CultureInfo. The hash code is guaranteed to be the same for RegionInfo - // A and B where A.Equals(B) is true. - // - //////////////////////////////////////////////////////////////////////// - public override int GetHashCode() - { - return (this.Name.GetHashCode()); - } - - - //////////////////////////////////////////////////////////////////////// - // - // ToString - // - // Implements Object.ToString(). Returns the name of the Region, ie: es-US - // - //////////////////////////////////////////////////////////////////////// - public override String ToString() - { - return (Name); - } - } -} diff --git a/src/mscorlib/corefx/System/Globalization/SortKey.cs b/src/mscorlib/corefx/System/Globalization/SortKey.cs deleted file mode 100644 index 9e22a6f..0000000 --- a/src/mscorlib/corefx/System/Globalization/SortKey.cs +++ /dev/null @@ -1,208 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -//////////////////////////////////////////////////////////////////////////// -// -// -// Purpose: This class implements a set of methods for retrieving -// sort key information. -// -// -//////////////////////////////////////////////////////////////////////////// - -namespace System.Globalization { - - using System; - using System.Runtime.CompilerServices; - using System.Runtime.Serialization; - using System.Diagnostics; - using System.Diagnostics.Contracts; - - [Serializable] - public partial class SortKey - { - //--------------------------------------------------------------------// - // Internal Information // - //--------------------------------------------------------------------// - - // - // Variables. - // - - [OptionalField(VersionAdded = 3)] - internal string _localeName; // locale identifier - - [OptionalField(VersionAdded = 1)] // LCID field so serialization is Whidbey compatible though we don't officially support it - internal int _win32LCID; - // Whidbey serialization - - internal CompareOptions _options; // options - internal string _string; // original string - internal byte[] _keyData; // sortkey data - - // - // The following constructor is designed to be called from CompareInfo to get the - // the sort key of specific string for synthetic culture - // - internal SortKey(String localeName, String str, CompareOptions options, byte[] keyData) - { - _keyData = keyData; - _localeName = localeName; - _options = options; - _string = str; - } - - [OnSerializing] - private void OnSerializing(StreamingContext context) - { - //set LCID to proper value for Whidbey serialization (no other use) - if (_win32LCID == 0) - { - _win32LCID = CultureInfo.GetCultureInfo(_localeName).LCID; - } - } - - [OnDeserialized] - private void OnDeserialized(StreamingContext context) - { - //set locale name to proper value after Whidbey deserialization - if (String.IsNullOrEmpty(_localeName) && _win32LCID != 0) - { - _localeName = CultureInfo.GetCultureInfo(_win32LCID).Name; - } - } - - //////////////////////////////////////////////////////////////////////// - // - // GetOriginalString - // - // Returns the original string used to create the current instance - // of SortKey. - // - //////////////////////////////////////////////////////////////////////// - public virtual String OriginalString - { - get - { - return (_string); - } - } - - //////////////////////////////////////////////////////////////////////// - // - // GetKeyData - // - // Returns a byte array representing the current instance of the - // sort key. - // - //////////////////////////////////////////////////////////////////////// - public virtual byte[] KeyData - { - get - { - return (byte[])(_keyData.Clone()); - } - } - - //////////////////////////////////////////////////////////////////////// - // - // Compare - // - // Compares the two sort keys. Returns 0 if the two sort keys are - // equal, a number less than 0 if sortkey1 is less than sortkey2, - // and a number greater than 0 if sortkey1 is greater than sortkey2. - // - //////////////////////////////////////////////////////////////////////// - public static int Compare(SortKey sortkey1, SortKey sortkey2) - { - if (sortkey1==null || sortkey2==null) - { - throw new ArgumentNullException((sortkey1 == null ? nameof(sortkey1) : nameof(sortkey2))); - } - Contract.EndContractBlock(); - - byte[] key1Data = sortkey1._keyData; - byte[] key2Data = sortkey2._keyData; - - Debug.Assert(key1Data != null, "key1Data != null"); - Debug.Assert(key2Data != null, "key2Data != null"); - - if (key1Data.Length == 0) - { - if (key2Data.Length == 0) - { - return (0); - } - return (-1); - } - if (key2Data.Length == 0) - { - return (1); - } - - int compLen = (key1Data.Lengthkey2Data[i]) - { - return (1); - } - if (key1Data[i] - { - private int _nlsVersion; - private Guid _sortId; - - public int FullVersion - { - get - { - return _nlsVersion; - } - } - - public Guid SortId - { - get - { - return _sortId; - } - } - - public SortVersion(int fullVersion, Guid sortId) - { - _sortId = sortId; - _nlsVersion = fullVersion; - } - - internal SortVersion(int nlsVersion, int effectiveId, Guid customVersion) - { - _nlsVersion = nlsVersion; - - if (customVersion == Guid.Empty) - { - byte b1 = (byte)(effectiveId >> 24); - byte b2 = (byte)((effectiveId & 0x00FF0000) >> 16); - byte b3 = (byte)((effectiveId & 0x0000FF00) >> 8); - byte b4 = (byte)(effectiveId & 0xFF); - customVersion = new Guid(0, 0, 0, 0, 0, 0, 0, b1, b2, b3, b4); - } - - _sortId = customVersion; - } - - public override bool Equals(object obj) - { - SortVersion n = obj as SortVersion; - if (n != null) - { - return this.Equals(n); - } - - return false; - } - - public bool Equals(SortVersion other) - { - if (other == null) - { - return false; - } - - return _nlsVersion == other._nlsVersion && _sortId == other._sortId; - } - - public override int GetHashCode() - { - return _nlsVersion * 7 | _sortId.GetHashCode(); - } - - public static bool operator ==(SortVersion left, SortVersion right) - { - if (((object)left) != null) - { - return left.Equals(right); - } - - if (((object)right) != null) - { - return right.Equals(left); - } - - // Both null. - return true; - } - - public static bool operator !=(SortVersion left, SortVersion right) - { - return !(left == right); - } - } -} \ No newline at end of file diff --git a/src/mscorlib/corefx/System/Globalization/StringInfo.cs b/src/mscorlib/corefx/System/Globalization/StringInfo.cs deleted file mode 100644 index f1dd305..0000000 --- a/src/mscorlib/corefx/System/Globalization/StringInfo.cs +++ /dev/null @@ -1,374 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -//////////////////////////////////////////////////////////////////////////// -// -// -// Purpose: This class defines behaviors specific to a writing system. -// A writing system is the collection of scripts and -// orthographic rules required to represent a language as text. -// -// -//////////////////////////////////////////////////////////////////////////// - -using System; -using System.Diagnostics; -using System.Diagnostics.Contracts; -using System.Runtime.Serialization; - -namespace System.Globalization -{ - [Serializable] - public class StringInfo - { - [OptionalField(VersionAdded = 2)] - private string _str; - - [NonSerialized] - private int[] _indexes; - - // Legacy constructor - public StringInfo() : this("") { } - - // Primary, useful constructor - public StringInfo(string value) - { - this.String = value; - } - - [OnDeserializing] - private void OnDeserializing(StreamingContext ctx) - { - _str = String.Empty; - } - - [OnDeserialized] - private void OnDeserialized(StreamingContext ctx) - { - if (_str.Length == 0) - { - _indexes = null; - } - } - - public override bool Equals(Object value) - { - StringInfo that = value as StringInfo; - if (that != null) - { - return (_str.Equals(that._str)); - } - return (false); - } - - public override int GetHashCode() - { - return _str.GetHashCode(); - } - - - // Our zero-based array of index values into the string. Initialize if - // our private array is not yet, in fact, initialized. - private int[] Indexes - { - get - { - if ((null == _indexes) && (0 < this.String.Length)) - { - _indexes = StringInfo.ParseCombiningCharacters(this.String); - } - - return (_indexes); - } - } - - public string String - { - get - { - return (_str); - } - set - { - if (null == value) - { - throw new ArgumentNullException("String", - SR.ArgumentNull_String); - } - Contract.EndContractBlock(); - - _str = value; - _indexes = null; - } - } - - public int LengthInTextElements - { - get - { - if (null == this.Indexes) - { - // Indexes not initialized, so assume length zero - return (0); - } - - return (this.Indexes.Length); - } - } - - public string SubstringByTextElements(int startingTextElement) - { - // If the string is empty, no sense going further. - if (null == this.Indexes) - { - // Just decide which error to give depending on the param they gave us.... - if (startingTextElement < 0) - { - throw new ArgumentOutOfRangeException(nameof(startingTextElement), SR.ArgumentOutOfRange_NeedPosNum); - } - else - { - throw new ArgumentOutOfRangeException(nameof(startingTextElement), SR.Arg_ArgumentOutOfRangeException); - } - } - return (SubstringByTextElements(startingTextElement, Indexes.Length - startingTextElement)); - } - - public string SubstringByTextElements(int startingTextElement, int lengthInTextElements) - { - if (startingTextElement < 0) - { - throw new ArgumentOutOfRangeException(nameof(startingTextElement), SR.ArgumentOutOfRange_NeedPosNum); - } - - if (this.String.Length == 0 || startingTextElement >= Indexes.Length) - { - throw new ArgumentOutOfRangeException(nameof(startingTextElement), SR.Arg_ArgumentOutOfRangeException); - } - - if (lengthInTextElements < 0) - { - throw new ArgumentOutOfRangeException(nameof(lengthInTextElements), SR.ArgumentOutOfRange_NeedPosNum); - } - - if (startingTextElement > Indexes.Length - lengthInTextElements) - { - throw new ArgumentOutOfRangeException(nameof(lengthInTextElements), SR.Arg_ArgumentOutOfRangeException); - } - - int start = Indexes[startingTextElement]; - - if (startingTextElement + lengthInTextElements == Indexes.Length) - { - // We are at the last text element in the string and because of that - // must handle the call differently. - return (this.String.Substring(start)); - } - else - { - return (this.String.Substring(start, (Indexes[lengthInTextElements + startingTextElement] - start))); - } - } - - public static string GetNextTextElement(string str) - { - return (GetNextTextElement(str, 0)); - } - - - //////////////////////////////////////////////////////////////////////// - // - // Get the code point count of the current text element. - // - // A combining class is defined as: - // A character/surrogate that has the following Unicode category: - // * NonSpacingMark (e.g. U+0300 COMBINING GRAVE ACCENT) - // * SpacingCombiningMark (e.g. U+ 0903 DEVANGARI SIGN VISARGA) - // * EnclosingMark (e.g. U+20DD COMBINING ENCLOSING CIRCLE) - // - // In the context of GetNextTextElement() and ParseCombiningCharacters(), a text element is defined as: - // - // 1. If a character/surrogate is in the following category, it is a text element. - // It can NOT further combine with characters in the combinging class to form a text element. - // * one of the Unicode category in the combinging class - // * UnicodeCategory.Format - // * UnicodeCateogry.Control - // * UnicodeCategory.OtherNotAssigned - // 2. Otherwise, the character/surrogate can be combined with characters in the combinging class to form a text element. - // - // Return: - // The length of the current text element - // - // Parameters: - // String str - // index The starting index - // len The total length of str (to define the upper boundary) - // ucCurrent The Unicode category pointed by Index. It will be updated to the uc of next character if this is not the last text element. - // currentCharCount The char count of an abstract char pointed by Index. It will be updated to the char count of next abstract character if this is not the last text element. - // - //////////////////////////////////////////////////////////////////////// - - internal static int GetCurrentTextElementLen(string str, int index, int len, ref UnicodeCategory ucCurrent, ref int currentCharCount) - { - Debug.Assert(index >= 0 && len >= 0, "StringInfo.GetCurrentTextElementLen() : index = " + index + ", len = " + len); - Debug.Assert(index < len, "StringInfo.GetCurrentTextElementLen() : index = " + index + ", len = " + len); - if (index + currentCharCount == len) - { - // This is the last character/surrogate in the string. - return (currentCharCount); - } - - // Call an internal GetUnicodeCategory, which will tell us both the unicode category, and also tell us if it is a surrogate pair or not. - int nextCharCount; - UnicodeCategory ucNext = CharUnicodeInfo.InternalGetUnicodeCategory(str, index + currentCharCount, out nextCharCount); - if (CharUnicodeInfo.IsCombiningCategory(ucNext)) - { - // The next element is a combining class. - // Check if the current text element to see if it is a valid base category (i.e. it should not be a combining category, - // not a format character, and not a control character). - - if (CharUnicodeInfo.IsCombiningCategory(ucCurrent) - || (ucCurrent == UnicodeCategory.Format) - || (ucCurrent == UnicodeCategory.Control) - || (ucCurrent == UnicodeCategory.OtherNotAssigned) - || (ucCurrent == UnicodeCategory.Surrogate)) // An unpair high surrogate or low surrogate - { - // Will fall thru and return the currentCharCount - } - else - { - int startIndex = index; // Remember the current index. - - // We have a valid base characters, and we have a character (or surrogate) that is combining. - // Check if there are more combining characters to follow. - // Check if the next character is a nonspacing character. - index += currentCharCount + nextCharCount; - - while (index < len) - { - ucNext = CharUnicodeInfo.InternalGetUnicodeCategory(str, index, out nextCharCount); - if (!CharUnicodeInfo.IsCombiningCategory(ucNext)) - { - ucCurrent = ucNext; - currentCharCount = nextCharCount; - break; - } - index += nextCharCount; - } - return (index - startIndex); - } - } - // The return value will be the currentCharCount. - int ret = currentCharCount; - ucCurrent = ucNext; - // Update currentCharCount. - currentCharCount = nextCharCount; - return (ret); - } - - // Returns the str containing the next text element in str starting at - // index index. If index is not supplied, then it will start at the beginning - // of str. It recognizes a base character plus one or more combining - // characters or a properly formed surrogate pair as a text element. See also - // the ParseCombiningCharacters() and the ParseSurrogates() methods. - public static string GetNextTextElement(string str, int index) - { - // - // Validate parameters. - // - if (str == null) - { - throw new ArgumentNullException(nameof(str)); - } - Contract.EndContractBlock(); - - int len = str.Length; - if (index < 0 || index >= len) - { - if (index == len) - { - return (String.Empty); - } - throw new ArgumentOutOfRangeException(nameof(index), SR.ArgumentOutOfRange_Index); - } - - int charLen; - UnicodeCategory uc = CharUnicodeInfo.InternalGetUnicodeCategory(str, index, out charLen); - return (str.Substring(index, GetCurrentTextElementLen(str, index, len, ref uc, ref charLen))); - } - - public static TextElementEnumerator GetTextElementEnumerator(string str) - { - return (GetTextElementEnumerator(str, 0)); - } - - public static TextElementEnumerator GetTextElementEnumerator(string str, int index) - { - // - // Validate parameters. - // - if (str == null) - { - throw new ArgumentNullException(nameof(str)); - } - Contract.EndContractBlock(); - - int len = str.Length; - if (index < 0 || (index > len)) - { - throw new ArgumentOutOfRangeException(nameof(index), SR.ArgumentOutOfRange_Index); - } - - return (new TextElementEnumerator(str, index, len)); - } - - /* - * Returns the indices of each base character or properly formed surrogate pair - * within the str. It recognizes a base character plus one or more combining - * characters or a properly formed surrogate pair as a text element and returns - * the index of the base character or high surrogate. Each index is the - * beginning of a text element within a str. The length of each element is - * easily computed as the difference between successive indices. The length of - * the array will always be less than or equal to the length of the str. For - * example, given the str \u4f00\u302a\ud800\udc00\u4f01, this method would - * return the indices: 0, 2, 4. - */ - - public static int[] ParseCombiningCharacters(string str) - { - if (str == null) - { - throw new ArgumentNullException(nameof(str)); - } - Contract.EndContractBlock(); - - int len = str.Length; - int[] result = new int[len]; - if (len == 0) - { - return (result); - } - - int resultCount = 0; - - int i = 0; - int currentCharLen; - UnicodeCategory currentCategory = CharUnicodeInfo.InternalGetUnicodeCategory(str, 0, out currentCharLen); - - while (i < len) - { - result[resultCount++] = i; - i += GetCurrentTextElementLen(str, i, len, ref currentCategory, ref currentCharLen); - } - - if (resultCount < len) - { - int[] returnArray = new int[resultCount]; - Array.Copy(result, returnArray, resultCount); - return (returnArray); - } - return (result); - } - } -} diff --git a/src/mscorlib/corefx/System/Globalization/TaiwanCalendar.cs b/src/mscorlib/corefx/System/Globalization/TaiwanCalendar.cs deleted file mode 100644 index 2e735e0..0000000 --- a/src/mscorlib/corefx/System/Globalization/TaiwanCalendar.cs +++ /dev/null @@ -1,285 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.Diagnostics.CodeAnalysis; -using System.Diagnostics.Contracts; - -namespace System.Globalization -{ - /*=================================TaiwanCalendar========================== - ** - ** Taiwan calendar is based on the Gregorian calendar. And the year is an offset to Gregorian calendar. - ** That is, - ** Taiwan year = Gregorian year - 1911. So 1912/01/01 A.D. is Taiwan 1/01/01 - ** - ** Calendar support range: - ** Calendar Minimum Maximum - ** ========== ========== ========== - ** Gregorian 1912/01/01 9999/12/31 - ** Taiwan 01/01/01 8088/12/31 - ============================================================================*/ - - [Serializable] - public class TaiwanCalendar : Calendar - { - // - // The era value for the current era. - // - - // Since - // Gregorian Year = Era Year + yearOffset - // When Gregorian Year 1912 is year 1, so that - // 1912 = 1 + yearOffset - // So yearOffset = 1911 - //m_EraInfo[0] = new EraInfo(1, new DateTime(1912, 1, 1).Ticks, 1911, 1, GregorianCalendar.MaxYear - 1911); - - // Initialize our era info. - internal static EraInfo[] taiwanEraInfo = new EraInfo[] { - new EraInfo( 1, 1912, 1, 1, 1911, 1, GregorianCalendar.MaxYear - 1911) // era #, start year/month/day, yearOffset, minEraYear - }; - - internal static volatile Calendar s_defaultInstance; - - internal GregorianCalendarHelper helper; - - /*=================================GetDefaultInstance========================== - **Action: Internal method to provide a default intance of TaiwanCalendar. Used by NLS+ implementation - ** and other calendars. - **Returns: - **Arguments: - **Exceptions: - ============================================================================*/ - - internal static Calendar GetDefaultInstance() - { - if (s_defaultInstance == null) - { - s_defaultInstance = new TaiwanCalendar(); - } - return (s_defaultInstance); - } - - internal static readonly DateTime calendarMinValue = new DateTime(1912, 1, 1); - - - public override DateTime MinSupportedDateTime - { - get - { - return (calendarMinValue); - } - } - - public override DateTime MaxSupportedDateTime - { - get - { - return (DateTime.MaxValue); - } - } - - public override CalendarAlgorithmType AlgorithmType - { - get - { - return CalendarAlgorithmType.SolarCalendar; - } - } - - // Return the type of the Taiwan calendar. - // - - public TaiwanCalendar() - { - try - { - new CultureInfo("zh-TW"); - } - catch (ArgumentException e) - { - throw new TypeInitializationException(this.GetType().ToString(), e); - } - helper = new GregorianCalendarHelper(this, taiwanEraInfo); - } - - internal override CalendarId ID - { - get - { - return CalendarId.TAIWAN; - } - } - - - public override DateTime AddMonths(DateTime time, int months) - { - return (helper.AddMonths(time, months)); - } - - - public override DateTime AddYears(DateTime time, int years) - { - return (helper.AddYears(time, years)); - } - - - public override int GetDaysInMonth(int year, int month, int era) - { - return (helper.GetDaysInMonth(year, month, era)); - } - - - public override int GetDaysInYear(int year, int era) - { - return (helper.GetDaysInYear(year, era)); - } - - - public override int GetDayOfMonth(DateTime time) - { - return (helper.GetDayOfMonth(time)); - } - - - public override DayOfWeek GetDayOfWeek(DateTime time) - { - return (helper.GetDayOfWeek(time)); - } - - - public override int GetDayOfYear(DateTime time) - { - return (helper.GetDayOfYear(time)); - } - - - public override int GetMonthsInYear(int year, int era) - { - return (helper.GetMonthsInYear(year, era)); - } - - - [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems. - public override int GetWeekOfYear(DateTime time, CalendarWeekRule rule, DayOfWeek firstDayOfWeek) - { - return (helper.GetWeekOfYear(time, rule, firstDayOfWeek)); - } - - - public override int GetEra(DateTime time) - { - return (helper.GetEra(time)); - } - - public override int GetMonth(DateTime time) - { - return (helper.GetMonth(time)); - } - - - public override int GetYear(DateTime time) - { - return (helper.GetYear(time)); - } - - - public override bool IsLeapDay(int year, int month, int day, int era) - { - return (helper.IsLeapDay(year, month, day, era)); - } - - - public override bool IsLeapYear(int year, int era) - { - return (helper.IsLeapYear(year, era)); - } - - // Returns the leap month in a calendar year of the specified era. This method returns 0 - // if this calendar does not have leap month, or this year is not a leap year. - // - - public override int GetLeapMonth(int year, int era) - { - return (helper.GetLeapMonth(year, era)); - } - - - public override bool IsLeapMonth(int year, int month, int era) - { - return (helper.IsLeapMonth(year, month, era)); - } - - - public override DateTime ToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era) - { - return (helper.ToDateTime(year, month, day, hour, minute, second, millisecond, era)); - } - - - public override int[] Eras - { - get - { - return (helper.Eras); - } - } - - private const int DEFAULT_TWO_DIGIT_YEAR_MAX = 99; - - public override int TwoDigitYearMax - { - get - { - if (twoDigitYearMax == -1) - { - twoDigitYearMax = GetSystemTwoDigitYearSetting(ID, DEFAULT_TWO_DIGIT_YEAR_MAX); - } - return (twoDigitYearMax); - } - - set - { - VerifyWritable(); - if (value < 99 || value > helper.MaxYear) - { - throw new ArgumentOutOfRangeException( - "year", - String.Format( - CultureInfo.CurrentCulture, - SR.ArgumentOutOfRange_Range, - 99, - helper.MaxYear)); - } - twoDigitYearMax = value; - } - } - - // For Taiwan calendar, four digit year is not used. - // Therefore, for any two digit number, we just return the original number. - - public override int ToFourDigitYear(int year) - { - if (year <= 0) - { - throw new ArgumentOutOfRangeException(nameof(year), - SR.ArgumentOutOfRange_NeedPosNum); - } - Contract.EndContractBlock(); - - if (year > helper.MaxYear) - { - throw new ArgumentOutOfRangeException( - nameof(year), - String.Format( - CultureInfo.CurrentCulture, - SR.ArgumentOutOfRange_Range, - 1, - helper.MaxYear)); - } - return (year); - } - } -} - diff --git a/src/mscorlib/corefx/System/Globalization/TaiwanLunisolarCalendar.cs b/src/mscorlib/corefx/System/Globalization/TaiwanLunisolarCalendar.cs deleted file mode 100644 index 1f75ac9..0000000 --- a/src/mscorlib/corefx/System/Globalization/TaiwanLunisolarCalendar.cs +++ /dev/null @@ -1,330 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.Diagnostics.Contracts; - -namespace System.Globalization -{ - //////////////////////////////////////////////////////////////////////////// - // - // Notes about TaiwanLunisolarCalendar - // - //////////////////////////////////////////////////////////////////////////// - /* - ** Calendar support range: - ** Calendar Minimum Maximum - ** ========== ========== ========== - ** Gregorian 1912/02/18 2051/02/10 - ** TaiwanLunisolar 1912/01/01 2050/13/29 - */ - - [Serializable] - public class TaiwanLunisolarCalendar : EastAsianLunisolarCalendar - { - // Since - // Gregorian Year = Era Year + yearOffset - // When Gregorian Year 1912 is year 1, so that - // 1912 = 1 + yearOffset - // So yearOffset = 1911 - //m_EraInfo[0] = new EraInfo(1, new DateTime(1912, 1, 1).Ticks, 1911, 1, GregorianCalendar.MaxYear - 1911); - - // Initialize our era info. - internal static EraInfo[] taiwanLunisolarEraInfo = new EraInfo[] { - new EraInfo( 1, 1912, 1, 1, 1911, 1, GregorianCalendar.MaxYear - 1911) // era #, start year/month/day, yearOffset, minEraYear - }; - - internal GregorianCalendarHelper helper; - - internal const int MIN_LUNISOLAR_YEAR = 1912; - internal const int MAX_LUNISOLAR_YEAR = 2050; - - internal const int MIN_GREGORIAN_YEAR = 1912; - internal const int MIN_GREGORIAN_MONTH = 2; - internal const int MIN_GREGORIAN_DAY = 18; - - internal const int MAX_GREGORIAN_YEAR = 2051; - internal const int MAX_GREGORIAN_MONTH = 2; - internal const int MAX_GREGORIAN_DAY = 10; - - internal static DateTime minDate = new DateTime(MIN_GREGORIAN_YEAR, MIN_GREGORIAN_MONTH, MIN_GREGORIAN_DAY); - internal static DateTime maxDate = new DateTime((new DateTime(MAX_GREGORIAN_YEAR, MAX_GREGORIAN_MONTH, MAX_GREGORIAN_DAY, 23, 59, 59, 999)).Ticks + 9999); - - public override DateTime MinSupportedDateTime - { - get - { - return (minDate); - } - } - - - - public override DateTime MaxSupportedDateTime - { - get - { - return (maxDate); - } - } - - protected override int DaysInYearBeforeMinSupportedYear - { - get - { - // 1911 from ChineseLunisolarCalendar - return 384; - } - } - - private static readonly int[,] s_yinfo = - { - /*Y LM Lmon Lday DaysPerMonth D1 D2 D3 D4 D5 D6 D7 D8 D9 D10 D11 D12 D13 #Days - 1912 */ - { 0 , 2 , 18 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354 -1913 */{ 0 , 2 , 6 , 53840 },/* 30 30 29 30 29 29 30 29 29 30 29 30 0 354 -1914 */{ 5 , 1 , 26 , 54568 },/* 30 30 29 30 29 30 29 30 29 29 30 29 30 384 -1915 */{ 0 , 2 , 14 , 46400 },/* 30 29 30 30 29 30 29 30 29 30 29 29 0 354 -1916 */{ 0 , 2 , 3 , 54944 },/* 30 30 29 30 29 30 30 29 30 29 30 29 0 355 -1917 */{ 2 , 1 , 23 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 29 384 -1918 */{ 0 , 2 , 11 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355 -1919 */{ 7 , 2 , 1 , 18872 },/* 29 30 29 29 30 29 29 30 30 29 30 30 30 384 -1920 */{ 0 , 2 , 20 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354 -1921 */{ 0 , 2 , 8 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354 -1922 */{ 5 , 1 , 28 , 45656 },/* 30 29 30 30 29 29 30 29 29 30 29 30 30 384 -1923 */{ 0 , 2 , 16 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 0 354 -1924 */{ 0 , 2 , 5 , 27968 },/* 29 30 30 29 30 30 29 30 29 30 29 29 0 354 -1925 */{ 4 , 1 , 24 , 44456 },/* 30 29 30 29 30 30 29 30 30 29 30 29 30 385 -1926 */{ 0 , 2 , 13 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354 -1927 */{ 0 , 2 , 2 , 38256 },/* 30 29 29 30 29 30 29 30 29 30 30 30 0 355 -1928 */{ 2 , 1 , 23 , 18808 },/* 29 30 29 29 30 29 29 30 29 30 30 30 30 384 -1929 */{ 0 , 2 , 10 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354 -1930 */{ 6 , 1 , 30 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 29 383 -1931 */{ 0 , 2 , 17 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354 -1932 */{ 0 , 2 , 6 , 59984 },/* 30 30 30 29 30 29 30 29 29 30 29 30 0 355 -1933 */{ 5 , 1 , 26 , 27976 },/* 29 30 30 29 30 30 29 30 29 30 29 29 30 384 -1934 */{ 0 , 2 , 14 , 23248 },/* 29 30 29 30 30 29 30 29 30 30 29 30 0 355 -1935 */{ 0 , 2 , 4 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354 -1936 */{ 3 , 1 , 24 , 37744 },/* 30 29 29 30 29 29 30 30 29 30 30 30 29 384 -1937 */{ 0 , 2 , 11 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354 -1938 */{ 7 , 1 , 31 , 51560 },/* 30 30 29 29 30 29 29 30 29 30 30 29 30 384 -1939 */{ 0 , 2 , 19 , 51536 },/* 30 30 29 29 30 29 29 30 29 30 29 30 0 354 -1940 */{ 0 , 2 , 8 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354 -1941 */{ 6 , 1 , 27 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 29 384 -1942 */{ 0 , 2 , 15 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355 -1943 */{ 0 , 2 , 5 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354 -1944 */{ 4 , 1 , 25 , 43736 },/* 30 29 30 29 30 29 30 29 30 30 29 30 30 385 -1945 */{ 0 , 2 , 13 , 9680 },/* 29 29 30 29 29 30 29 30 30 30 29 30 0 354 -1946 */{ 0 , 2 , 2 , 37584 },/* 30 29 29 30 29 29 30 29 30 30 29 30 0 354 -1947 */{ 2 , 1 , 22 , 51544 },/* 30 30 29 29 30 29 29 30 29 30 29 30 30 384 -1948 */{ 0 , 2 , 10 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354 -1949 */{ 7 , 1 , 29 , 46248 },/* 30 29 30 30 29 30 29 29 30 29 30 29 30 384 -1950 */{ 0 , 2 , 17 , 27808 },/* 29 30 30 29 30 30 29 29 30 29 30 29 0 354 -1951 */{ 0 , 2 , 6 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355 -1952 */{ 5 , 1 , 27 , 21928 },/* 29 30 29 30 29 30 29 30 30 29 30 29 30 384 -1953 */{ 0 , 2 , 14 , 19872 },/* 29 30 29 29 30 30 29 30 30 29 30 29 0 354 -1954 */{ 0 , 2 , 3 , 42416 },/* 30 29 30 29 29 30 29 30 30 29 30 30 0 355 -1955 */{ 3 , 1 , 24 , 21176 },/* 29 30 29 30 29 29 30 29 30 29 30 30 30 384 -1956 */{ 0 , 2 , 12 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354 -1957 */{ 8 , 1 , 31 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 29 383 -1958 */{ 0 , 2 , 18 , 59728 },/* 30 30 30 29 30 29 29 30 29 30 29 30 0 355 -1959 */{ 0 , 2 , 8 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354 -1960 */{ 6 , 1 , 28 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 29 384 -1961 */{ 0 , 2 , 15 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 0 355 -1962 */{ 0 , 2 , 5 , 19296 },/* 29 30 29 29 30 29 30 30 29 30 30 29 0 354 -1963 */{ 4 , 1 , 25 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 29 384 -1964 */{ 0 , 2 , 13 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355 -1965 */{ 0 , 2 , 2 , 21088 },/* 29 30 29 30 29 29 30 29 29 30 30 29 0 353 -1966 */{ 3 , 1 , 21 , 59696 },/* 30 30 30 29 30 29 29 30 29 29 30 30 29 384 -1967 */{ 0 , 2 , 9 , 55632 },/* 30 30 29 30 30 29 29 30 29 30 29 30 0 355 -1968 */{ 7 , 1 , 30 , 23208 },/* 29 30 29 30 30 29 30 29 30 29 30 29 30 384 -1969 */{ 0 , 2 , 17 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354 -1970 */{ 0 , 2 , 6 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 0 355 -1971 */{ 5 , 1 , 27 , 19176 },/* 29 30 29 29 30 29 30 29 30 30 30 29 30 384 -1972 */{ 0 , 2 , 15 , 19152 },/* 29 30 29 29 30 29 30 29 30 30 29 30 0 354 -1973 */{ 0 , 2 , 3 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354 -1974 */{ 4 , 1 , 23 , 53864 },/* 30 30 29 30 29 29 30 29 29 30 30 29 30 384 -1975 */{ 0 , 2 , 11 , 53840 },/* 30 30 29 30 29 29 30 29 29 30 29 30 0 354 -1976 */{ 8 , 1 , 31 , 54568 },/* 30 30 29 30 29 30 29 30 29 29 30 29 30 384 -1977 */{ 0 , 2 , 18 , 46400 },/* 30 29 30 30 29 30 29 30 29 30 29 29 0 354 -1978 */{ 0 , 2 , 7 , 46752 },/* 30 29 30 30 29 30 30 29 30 29 30 29 0 355 -1979 */{ 6 , 1 , 28 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 29 384 -1980 */{ 0 , 2 , 16 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355 -1981 */{ 0 , 2 , 5 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354 -1982 */{ 4 , 1 , 25 , 42168 },/* 30 29 30 29 29 30 29 29 30 29 30 30 30 384 -1983 */{ 0 , 2 , 13 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354 -1984 */{ 10 , 2 , 2 , 45656 },/* 30 29 30 30 29 29 30 29 29 30 29 30 30 384 -1985 */{ 0 , 2 , 20 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 0 354 -1986 */{ 0 , 2 , 9 , 27968 },/* 29 30 30 29 30 30 29 30 29 30 29 29 0 354 -1987 */{ 6 , 1 , 29 , 44448 },/* 30 29 30 29 30 30 29 30 30 29 30 29 29 384 -1988 */{ 0 , 2 , 17 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 0 355 -1989 */{ 0 , 2 , 6 , 38256 },/* 30 29 29 30 29 30 29 30 29 30 30 30 0 355 -1990 */{ 5 , 1 , 27 , 18808 },/* 29 30 29 29 30 29 29 30 29 30 30 30 30 384 -1991 */{ 0 , 2 , 15 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354 -1992 */{ 0 , 2 , 4 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 0 354 -1993 */{ 3 , 1 , 23 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 29 383 -1994 */{ 0 , 2 , 10 , 59984 },/* 30 30 30 29 30 29 30 29 29 30 29 30 0 355 -1995 */{ 8 , 1 , 31 , 27432 },/* 29 30 30 29 30 29 30 30 29 29 30 29 30 384 -1996 */{ 0 , 2 , 19 , 23232 },/* 29 30 29 30 30 29 30 29 30 30 29 29 0 354 -1997 */{ 0 , 2 , 7 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 0 355 -1998 */{ 5 , 1 , 28 , 37736 },/* 30 29 29 30 29 29 30 30 29 30 30 29 30 384 -1999 */{ 0 , 2 , 16 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354 -2000 */{ 0 , 2 , 5 , 51552 },/* 30 30 29 29 30 29 29 30 29 30 30 29 0 354 -2001 */{ 4 , 1 , 24 , 54440 },/* 30 30 29 30 29 30 29 29 30 29 30 29 30 384 -2002 */{ 0 , 2 , 12 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354 -2003 */{ 0 , 2 , 1 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 0 355 -2004 */{ 2 , 1 , 22 , 23208 },/* 29 30 29 30 30 29 30 29 30 29 30 29 30 384 -2005 */{ 0 , 2 , 9 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354 -2006 */{ 7 , 1 , 29 , 43736 },/* 30 29 30 29 30 29 30 29 30 30 29 30 30 385 -2007 */{ 0 , 2 , 18 , 9680 },/* 29 29 30 29 29 30 29 30 30 30 29 30 0 354 -2008 */{ 0 , 2 , 7 , 37584 },/* 30 29 29 30 29 29 30 29 30 30 29 30 0 354 -2009 */{ 5 , 1 , 26 , 51544 },/* 30 30 29 29 30 29 29 30 29 30 29 30 30 384 -2010 */{ 0 , 2 , 14 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354 -2011 */{ 0 , 2 , 3 , 46240 },/* 30 29 30 30 29 30 29 29 30 29 30 29 0 354 -2012 */{ 4 , 1 , 23 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 29 384 -2013 */{ 0 , 2 , 10 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355 -2014 */{ 9 , 1 , 31 , 21928 },/* 29 30 29 30 29 30 29 30 30 29 30 29 30 384 -2015 */{ 0 , 2 , 19 , 19360 },/* 29 30 29 29 30 29 30 30 30 29 30 29 0 354 -2016 */{ 0 , 2 , 8 , 42416 },/* 30 29 30 29 29 30 29 30 30 29 30 30 0 355 -2017 */{ 6 , 1 , 28 , 21176 },/* 29 30 29 30 29 29 30 29 30 29 30 30 30 384 -2018 */{ 0 , 2 , 16 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354 -2019 */{ 0 , 2 , 5 , 43312 },/* 30 29 30 29 30 29 29 30 29 29 30 30 0 354 -2020 */{ 4 , 1 , 25 , 29864 },/* 29 30 30 30 29 30 29 29 30 29 30 29 30 384 -2021 */{ 0 , 2 , 12 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354 -2022 */{ 0 , 2 , 1 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355 -2023 */{ 2 , 1 , 22 , 19880 },/* 29 30 29 29 30 30 29 30 30 29 30 29 30 384 -2024 */{ 0 , 2 , 10 , 19296 },/* 29 30 29 29 30 29 30 30 29 30 30 29 0 354 -2025 */{ 6 , 1 , 29 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 29 384 -2026 */{ 0 , 2 , 17 , 42208 },/* 30 29 30 29 29 30 29 29 30 30 30 29 0 354 -2027 */{ 0 , 2 , 6 , 53856 },/* 30 30 29 30 29 29 30 29 29 30 30 29 0 354 -2028 */{ 5 , 1 , 26 , 59696 },/* 30 30 30 29 30 29 29 30 29 29 30 30 29 384 -2029 */{ 0 , 2 , 13 , 54576 },/* 30 30 29 30 29 30 29 30 29 29 30 30 0 355 -2030 */{ 0 , 2 , 3 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354 -2031 */{ 3 , 1 , 23 , 27472 },/* 29 30 30 29 30 29 30 30 29 30 29 30 29 384 -2032 */{ 0 , 2 , 11 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 0 355 -2033 */{ 11 , 1 , 31 , 19176 },/* 29 30 29 29 30 29 30 29 30 30 30 29 30 384 -2034 */{ 0 , 2 , 19 , 19152 },/* 29 30 29 29 30 29 30 29 30 30 29 30 0 354 -2035 */{ 0 , 2 , 8 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354 -2036 */{ 6 , 1 , 28 , 53848 },/* 30 30 29 30 29 29 30 29 29 30 29 30 30 384 -2037 */{ 0 , 2 , 15 , 53840 },/* 30 30 29 30 29 29 30 29 29 30 29 30 0 354 -2038 */{ 0 , 2 , 4 , 54560 },/* 30 30 29 30 29 30 29 30 29 29 30 29 0 354 -2039 */{ 5 , 1 , 24 , 55968 },/* 30 30 29 30 30 29 30 29 30 29 30 29 29 384 -2040 */{ 0 , 2 , 12 , 46496 },/* 30 29 30 30 29 30 29 30 30 29 30 29 0 355 -2041 */{ 0 , 2 , 1 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 0 355 -2042 */{ 2 , 1 , 22 , 19160 },/* 29 30 29 29 30 29 30 29 30 30 29 30 30 384 -2043 */{ 0 , 2 , 10 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354 -2044 */{ 7 , 1 , 30 , 42168 },/* 30 29 30 29 29 30 29 29 30 29 30 30 30 384 -2045 */{ 0 , 2 , 17 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354 -2046 */{ 0 , 2 , 6 , 43600 },/* 30 29 30 29 30 29 30 29 29 30 29 30 0 354 -2047 */{ 5 , 1 , 26 , 46376 },/* 30 29 30 30 29 30 29 30 29 29 30 29 30 384 -2048 */{ 0 , 2 , 14 , 27936 },/* 29 30 30 29 30 30 29 30 29 29 30 29 0 354 -2049 */{ 0 , 2 , 2 , 44448 },/* 30 29 30 29 30 30 29 30 30 29 30 29 0 355 -2050 */{ 3 , 1 , 23 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 29 384 - */}; - - - internal override int MinCalendarYear - { - get - { - return (MIN_LUNISOLAR_YEAR); - } - } - - internal override int MaxCalendarYear - { - get - { - return (MAX_LUNISOLAR_YEAR); - } - } - - internal override DateTime MinDate - { - get - { - return (minDate); - } - } - - internal override DateTime MaxDate - { - get - { - return (maxDate); - } - } - - internal override EraInfo[] CalEraInfo - { - get - { - return (taiwanLunisolarEraInfo); - } - } - - internal override int GetYearInfo(int lunarYear, int index) - { - if ((lunarYear < MIN_LUNISOLAR_YEAR) || (lunarYear > MAX_LUNISOLAR_YEAR)) - { - throw new ArgumentOutOfRangeException( - "year", - String.Format( - CultureInfo.CurrentCulture, - SR.ArgumentOutOfRange_Range, - MIN_LUNISOLAR_YEAR, - MAX_LUNISOLAR_YEAR)); - } - Contract.EndContractBlock(); - - return s_yinfo[lunarYear - MIN_LUNISOLAR_YEAR, index]; - } - - internal override int GetYear(int year, DateTime time) - { - return helper.GetYear(year, time); - } - - internal override int GetGregorianYear(int year, int era) - { - return helper.GetGregorianYear(year, era); - } - - public TaiwanLunisolarCalendar() - { - helper = new GregorianCalendarHelper(this, taiwanLunisolarEraInfo); - } - - public override int GetEra(DateTime time) - { - return (helper.GetEra(time)); - } - - internal override CalendarId BaseCalendarID - { - get - { - return (CalendarId.TAIWAN); - } - } - - internal override CalendarId ID - { - get - { - return (CalendarId.TAIWANLUNISOLAR); - } - } - - - - public override int[] Eras - { - get - { - return (helper.Eras); - } - } - } -} diff --git a/src/mscorlib/corefx/System/Globalization/TextElementEnumerator.cs b/src/mscorlib/corefx/System/Globalization/TextElementEnumerator.cs deleted file mode 100644 index 464897b..0000000 --- a/src/mscorlib/corefx/System/Globalization/TextElementEnumerator.cs +++ /dev/null @@ -1,153 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -//////////////////////////////////////////////////////////////////////////// -// -// -// Purpose: -// -// -//////////////////////////////////////////////////////////////////////////// - -using System.Collections; -using System.Diagnostics; -using System.Runtime.Serialization; - -namespace System.Globalization -{ - // - // This is public because GetTextElement() is public. - // - - [Serializable] - public class TextElementEnumerator : IEnumerator - { - private String _str; - private int _index; - private int _startIndex; - - [NonSerialized] - private int _strLen; // This is the length of the total string, counting from the beginning of string. - - [NonSerialized] - private int _currTextElementLen; // The current text element lenght after MoveNext() is called. - - [OptionalField(VersionAdded = 2)] - private UnicodeCategory _uc; - - [OptionalField(VersionAdded = 2)] - private int _charLen; // The next abstract char to look at after MoveNext() is called. It could be 1 or 2, depending on if it is a surrogate or not. - - internal TextElementEnumerator(String str, int startIndex, int strLen) - { - Debug.Assert(str != null, "TextElementEnumerator(): str != null"); - Debug.Assert(startIndex >= 0 && strLen >= 0, "TextElementEnumerator(): startIndex >= 0 && strLen >= 0"); - Debug.Assert(strLen >= startIndex, "TextElementEnumerator(): strLen >= startIndex"); - _str = str; - _startIndex = startIndex; - _strLen = strLen; - Reset(); - } - - // the following fields is defined to keep the compatibility with Everett. - // don't change/remove the names/types of these fields. - private int _endIndex; - private int _nextTextElementLen; - - [OnDeserializing] - private void OnDeserializing(StreamingContext ctx) - { - _charLen = -1; - } - - [OnDeserialized] - private void OnDeserialized(StreamingContext ctx) - { - _strLen = _endIndex + 1; - _currTextElementLen = _nextTextElementLen; - - if (_charLen == -1) - { - _uc = CharUnicodeInfo.InternalGetUnicodeCategory(_str, _index, out _charLen); - } - } - - [OnSerializing] - private void OnSerializing(StreamingContext ctx) - { - _endIndex = _strLen - 1; - _nextTextElementLen = _currTextElementLen; - } - - public bool MoveNext() - { - if (_index >= _strLen) - { - // Make the _index to be greater than _strLen so that we can throw exception if GetTextElement() is called. - _index = _strLen + 1; - return (false); - } - _currTextElementLen = StringInfo.GetCurrentTextElementLen(_str, _index, _strLen, ref _uc, ref _charLen); - _index += _currTextElementLen; - return (true); - } - - // - // Get the current text element. - // - - public Object Current - { - get - { - return (GetTextElement()); - } - } - - // - // Get the current text element. - // - - public String GetTextElement() - { - if (_index == _startIndex) - { - throw new InvalidOperationException(SR.InvalidOperation_EnumNotStarted); - } - if (_index > _strLen) - { - throw new InvalidOperationException(SR.InvalidOperation_EnumEnded); - } - - return (_str.Substring(_index - _currTextElementLen, _currTextElementLen)); - } - - // - // Get the starting index of the current text element. - // - - public int ElementIndex - { - get - { - if (_index == _startIndex) - { - throw new InvalidOperationException(SR.InvalidOperation_EnumNotStarted); - } - return (_index - _currTextElementLen); - } - } - - - public void Reset() - { - _index = _startIndex; - if (_index < _strLen) - { - // If we have more than 1 character, get the category of the current char. - _uc = CharUnicodeInfo.InternalGetUnicodeCategory(_str, _index, out _charLen); - } - } - } -} diff --git a/src/mscorlib/corefx/System/Globalization/TextInfo.cs b/src/mscorlib/corefx/System/Globalization/TextInfo.cs deleted file mode 100644 index 172bbd2..0000000 --- a/src/mscorlib/corefx/System/Globalization/TextInfo.cs +++ /dev/null @@ -1,746 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -//////////////////////////////////////////////////////////////////////////// -// -// -// Purpose: This Class defines behaviors specific to a writing system. -// A writing system is the collection of scripts and -// orthographic rules required to represent a language as text. -// -// -//////////////////////////////////////////////////////////////////////////// - -using System.Diagnostics; -using System.Diagnostics.Contracts; -using System.Runtime.Serialization; -using System.Text; - -namespace System.Globalization -{ - [Serializable] - public partial class TextInfo : ICloneable, IDeserializationCallback - { - ////--------------------------------------------------------------------// - //// Internal Information // - ////--------------------------------------------------------------------// - - private enum Tristate : byte - { - NotInitialized, - True, - False, - } - - //// - //// Variables. - //// - - [OptionalField(VersionAdded = 2)] - private String _listSeparator; - [OptionalField(VersionAdded = 2)] - private bool _isReadOnly = false; - - //// _cultureName is the name of the creating culture. Note that we consider this authoratative, - //// if the culture's textinfo changes when deserializing, then behavior may change. - //// (ala Whidbey behavior). This is the only string Arrowhead needs to serialize. - //// _cultureData is the data that backs this class. - //// _textInfoName is the actual name of the textInfo (from cultureData.STEXTINFO) - //// this can be the same as _cultureName on Silverlight since the OS knows - //// how to do the sorting. However in the desktop, when we call the sorting dll, it doesn't - //// know how to resolve custom locle names to sort ids so we have to have alredy resolved this. - //// - - [OptionalField(VersionAdded = 3)] - private String _cultureName; // Name of the culture that created this text info - [NonSerialized] - private CultureData _cultureData; // Data record for the culture that made us, not for this textinfo - [NonSerialized] - private String _textInfoName; // Name of the text info we're using (ie: _cultureData.STEXTINFO) - [NonSerialized] - private Tristate _isAsciiCasingSameAsInvariant = Tristate.NotInitialized; - - // Invariant text info - internal static TextInfo Invariant - { - get - { - if (s_Invariant == null) - s_Invariant = new TextInfo(CultureData.Invariant); - return s_Invariant; - } - } - internal volatile static TextInfo s_Invariant; - - [OnSerializing] - private void OnSerializing(StreamingContext ctx) { } - - [OnDeserializing] - private void OnDeserializing(StreamingContext ctx) - { - // Clear these so we can check if we've fixed them yet - _cultureData = null; - _cultureName = null; - } - - [OnDeserialized] - private void OnDeserialized(StreamingContext ctx) - { - OnDeserialized(); - } - - void IDeserializationCallback.OnDeserialization(Object sender) - { - OnDeserialized(); - } - - private void OnDeserialized() - { - // this method will be called twice because of the support of IDeserializationCallback - if (_cultureData == null) - { - // Get the text info name belonging to that culture - _cultureData = CultureInfo.GetCultureInfo(_cultureName).m_cultureData; - _textInfoName = _cultureData.STEXTINFO; - FinishInitialization(_textInfoName); - } - } - - // - // Internal ordinal comparison functions - // - - internal static int GetHashCodeOrdinalIgnoreCase(String s) - { - // This is the same as an case insensitive hash for Invariant - // (not necessarily true for sorting, but OK for casing & then we apply normal hash code rules) - return (Invariant.GetCaseInsensitiveHashCode(s)); - } - - // Currently we don't have native functions to do this, so we do it the hard way - internal static int IndexOfStringOrdinalIgnoreCase(String source, String value, int startIndex, int count) - { - if (count > source.Length || count < 0 || startIndex < 0 || startIndex >= source.Length || startIndex + count > source.Length) - { - return -1; - } - - return CompareInfo.IndexOfOrdinal(source, value, startIndex, count, ignoreCase: true); - } - - // Currently we don't have native functions to do this, so we do it the hard way - internal static int LastIndexOfStringOrdinalIgnoreCase(String source, String value, int startIndex, int count) - { - if (count > source.Length || count < 0 || startIndex < 0 || startIndex > source.Length - 1 || (startIndex - count + 1 < 0)) - { - return -1; - } - - return CompareInfo.LastIndexOfOrdinal(source, value, startIndex, count, ignoreCase: true); - } - - //////////////////////////////////////////////////////////////////////// - // - // CodePage - // - // Returns the number of the code page used by this writing system. - // The type parameter can be any of the following values: - // ANSICodePage - // OEMCodePage - // MACCodePage - // - //////////////////////////////////////////////////////////////////////// - - - public virtual int ANSICodePage - { - get - { - return (_cultureData.IDEFAULTANSICODEPAGE); - } - } - - - public virtual int OEMCodePage - { - get - { - return (_cultureData.IDEFAULTOEMCODEPAGE); - } - } - - - public virtual int MacCodePage - { - get - { - return (_cultureData.IDEFAULTMACCODEPAGE); - } - } - - - public virtual int EBCDICCodePage - { - get - { - return (_cultureData.IDEFAULTEBCDICCODEPAGE); - } - } - - public int LCID - { - get - { - // Just use the LCID from our text info name - return CultureInfo.GetCultureInfo(_textInfoName).LCID; - } - } - - ////////////////////////////////////////////////////////////////////////// - //// - //// CultureName - //// - //// The name of the culture associated with the current TextInfo. - //// - ////////////////////////////////////////////////////////////////////////// - public string CultureName - { - get - { - return _textInfoName; - } - } - - //////////////////////////////////////////////////////////////////////// - // - // IsReadOnly - // - // Detect if the object is readonly. - // - //////////////////////////////////////////////////////////////////////// - public bool IsReadOnly - { - get { return (_isReadOnly); } - } - - ////////////////////////////////////////////////////////////////////////// - //// - //// Clone - //// - //// Is the implementation of ICloneable. - //// - ////////////////////////////////////////////////////////////////////////// - public virtual object Clone() - { - object o = MemberwiseClone(); - ((TextInfo)o).SetReadOnlyState(false); - return (o); - } - - //////////////////////////////////////////////////////////////////////// - // - // ReadOnly - // - // Create a cloned readonly instance or return the input one if it is - // readonly. - // - //////////////////////////////////////////////////////////////////////// - public static TextInfo ReadOnly(TextInfo textInfo) - { - if (textInfo == null) { throw new ArgumentNullException(nameof(textInfo)); } - Contract.EndContractBlock(); - if (textInfo.IsReadOnly) { return (textInfo); } - - TextInfo clonedTextInfo = (TextInfo)(textInfo.MemberwiseClone()); - clonedTextInfo.SetReadOnlyState(true); - - return (clonedTextInfo); - } - - private void VerifyWritable() - { - if (_isReadOnly) - { - throw new InvalidOperationException(SR.InvalidOperation_ReadOnly); - } - } - - internal void SetReadOnlyState(bool readOnly) - { - _isReadOnly = readOnly; - } - - - //////////////////////////////////////////////////////////////////////// - // - // ListSeparator - // - // Returns the string used to separate items in a list. - // - //////////////////////////////////////////////////////////////////////// - public virtual String ListSeparator - { - get - { - if (_listSeparator == null) - { - _listSeparator = _cultureData.SLIST; - } - return (_listSeparator); - } - - set - { - if (value == null) - { - throw new ArgumentNullException(nameof(value), SR.ArgumentNull_String); - } - VerifyWritable(); - _listSeparator = value; - } - } - - //////////////////////////////////////////////////////////////////////// - // - // ToLower - // - // Converts the character or string to lower case. Certain locales - // have different casing semantics from the file systems in Win32. - // - //////////////////////////////////////////////////////////////////////// - public unsafe virtual char ToLower(char c) - { - if (IsAscii(c) && IsAsciiCasingSameAsInvariant) - { - return ToLowerAsciiInvariant(c); - } - return (ChangeCase(c, toUpper: false)); - } - - public unsafe virtual String ToLower(String str) - { - if (str == null) { throw new ArgumentNullException(nameof(str)); } - - return ChangeCase(str, toUpper: false); - } - - private static Char ToLowerAsciiInvariant(Char c) - { - if ((uint)(c - 'A') <= (uint)('Z' - 'A')) - { - c = (Char)(c | 0x20); - } - return c; - } - - //////////////////////////////////////////////////////////////////////// - // - // ToUpper - // - // Converts the character or string to upper case. Certain locales - // have different casing semantics from the file systems in Win32. - // - //////////////////////////////////////////////////////////////////////// - public unsafe virtual char ToUpper(char c) - { - if (IsAscii(c) && IsAsciiCasingSameAsInvariant) - { - return ToUpperAsciiInvariant(c); - } - return (ChangeCase(c, toUpper: true)); - } - - public unsafe virtual String ToUpper(String str) - { - if (str == null) { throw new ArgumentNullException(nameof(str)); } - - return ChangeCase(str, toUpper: true); - } - - private static Char ToUpperAsciiInvariant(Char c) - { - if ((uint)(c - 'a') <= (uint)('z' - 'a')) - { - c = (Char)(c & ~0x20); - } - return c; - } - - private static bool IsAscii(Char c) - { - return c < 0x80; - } - - private bool IsAsciiCasingSameAsInvariant - { - get - { - if (_isAsciiCasingSameAsInvariant == Tristate.NotInitialized) - { - _isAsciiCasingSameAsInvariant = CultureInfo.GetCultureInfo(_textInfoName).CompareInfo.Compare("abcdefghijklmnopqrstuvwxyz", - "ABCDEFGHIJKLMNOPQRSTUVWXYZ", - CompareOptions.IgnoreCase) == 0 ? Tristate.True : Tristate.False; - } - return _isAsciiCasingSameAsInvariant == Tristate.True; - } - } - - // IsRightToLeft - // - // Returns true if the dominant direction of text and UI such as the relative position of buttons and scroll bars - // - public bool IsRightToLeft - { - get - { - return _cultureData.IsRightToLeft; - } - } - - //////////////////////////////////////////////////////////////////////// - // - // Equals - // - // Implements Object.Equals(). Returns a boolean indicating whether - // or not object refers to the same CultureInfo as the current instance. - // - //////////////////////////////////////////////////////////////////////// - public override bool Equals(Object obj) - { - TextInfo that = obj as TextInfo; - - if (that != null) - { - return this.CultureName.Equals(that.CultureName); - } - - return (false); - } - - //////////////////////////////////////////////////////////////////////// - // - // GetHashCode - // - // Implements Object.GetHashCode(). Returns the hash code for the - // CultureInfo. The hash code is guaranteed to be the same for CultureInfo A - // and B where A.Equals(B) is true. - // - //////////////////////////////////////////////////////////////////////// - public override int GetHashCode() - { - return (this.CultureName.GetHashCode()); - } - - //////////////////////////////////////////////////////////////////////// - // - // ToString - // - // Implements Object.ToString(). Returns a string describing the - // TextInfo. - // - //////////////////////////////////////////////////////////////////////// - public override String ToString() - { - return ("TextInfo - " + _cultureData.CultureName); - } - - // - // Titlecasing: - // ----------- - // Titlecasing refers to a casing practice wherein the first letter of a word is an uppercase letter - // and the rest of the letters are lowercase. The choice of which words to titlecase in headings - // and titles is dependent on language and local conventions. For example, "The Merry Wives of Windor" - // is the appropriate titlecasing of that play's name in English, with the word "of" not titlecased. - // In German, however, the title is "Die lustigen Weiber von Windsor," and both "lustigen" and "von" - // are not titlecased. In French even fewer words are titlecased: "Les joyeuses commeres de Windsor." - // - // Moreover, the determination of what actually constitutes a word is language dependent, and this can - // influence which letter or letters of a "word" are uppercased when titlecasing strings. For example - // "l'arbre" is considered two words in French, whereas "can't" is considered one word in English. - // - public unsafe String ToTitleCase(String str) - { - if (str == null) - { - throw new ArgumentNullException(nameof(str)); - } - Contract.EndContractBlock(); - if (str.Length == 0) - { - return (str); - } - - StringBuilder result = new StringBuilder(); - string lowercaseData = null; - - for (int i = 0; i < str.Length; i++) - { - UnicodeCategory charType; - int charLen; - - charType = CharUnicodeInfo.InternalGetUnicodeCategory(str, i, out charLen); - if (Char.CheckLetter(charType)) - { - // Do the titlecasing for the first character of the word. - i = AddTitlecaseLetter(ref result, ref str, i, charLen) + 1; - - // - // Convert the characters until the end of the this word - // to lowercase. - // - int lowercaseStart = i; - - // - // Use hasLowerCase flag to prevent from lowercasing acronyms (like "URT", "USA", etc) - // This is in line with Word 2000 behavior of titlecasing. - // - bool hasLowerCase = (charType == UnicodeCategory.LowercaseLetter); - // Use a loop to find all of the other letters following this letter. - while (i < str.Length) - { - charType = CharUnicodeInfo.InternalGetUnicodeCategory(str, i, out charLen); - if (IsLetterCategory(charType)) - { - if (charType == UnicodeCategory.LowercaseLetter) - { - hasLowerCase = true; - } - i += charLen; - } - else if (str[i] == '\'') - { - i++; - if (hasLowerCase) - { - if (lowercaseData == null) - { - lowercaseData = this.ToLower(str); - } - result.Append(lowercaseData, lowercaseStart, i - lowercaseStart); - } - else - { - result.Append(str, lowercaseStart, i - lowercaseStart); - } - lowercaseStart = i; - hasLowerCase = true; - } - else if (!IsWordSeparator(charType)) - { - // This category is considered to be part of the word. - // This is any category that is marked as false in wordSeprator array. - i+= charLen; - } - else - { - // A word separator. Break out of the loop. - break; - } - } - - int count = i - lowercaseStart; - - if (count > 0) - { - if (hasLowerCase) - { - if (lowercaseData == null) - { - lowercaseData = this.ToLower(str); - } - result.Append(lowercaseData, lowercaseStart, count); - } - else - { - result.Append(str, lowercaseStart, count); - } - } - - if (i < str.Length) - { - // not a letter, just append it - i = AddNonLetter(ref result, ref str, i, charLen); - } - } - else - { - // not a letter, just append it - i = AddNonLetter(ref result, ref str, i, charLen); - } - } - return (result.ToString()); - } - - private static int AddNonLetter(ref StringBuilder result, ref String input, int inputIndex, int charLen) - { - Debug.Assert(charLen == 1 || charLen == 2, "[TextInfo.AddNonLetter] CharUnicodeInfo.InternalGetUnicodeCategory returned an unexpected charLen!"); - if (charLen == 2) - { - // Surrogate pair - result.Append(input[inputIndex++]); - result.Append(input[inputIndex]); - } - else - { - result.Append(input[inputIndex]); - } - return inputIndex; - } - - private int AddTitlecaseLetter(ref StringBuilder result, ref String input, int inputIndex, int charLen) - { - Debug.Assert(charLen == 1 || charLen == 2, "[TextInfo.AddTitlecaseLetter] CharUnicodeInfo.InternalGetUnicodeCategory returned an unexpected charLen!"); - - // for surrogate pairs do a simple ToUpper operation on the substring - if (charLen == 2) - { - // Surrogate pair - result.Append(ToUpper(input.Substring(inputIndex, charLen))); - inputIndex++; - } - else - { - switch (input[inputIndex]) - { - // - // For AppCompat, the Titlecase Case Mapping data from NDP 2.0 is used below. - case (char) 0x01C4: // DZ with Caron -> Dz with Caron - case (char) 0x01C5: // Dz with Caron -> Dz with Caron - case (char) 0x01C6: // dz with Caron -> Dz with Caron - result.Append((char) 0x01C5); - break; - case (char) 0x01C7: // LJ -> Lj - case (char) 0x01C8: // Lj -> Lj - case (char) 0x01C9: // lj -> Lj - result.Append((char) 0x01C8); - break; - case (char) 0x01CA: // NJ -> Nj - case (char) 0x01CB: // Nj -> Nj - case (char) 0x01CC: // nj -> Nj - result.Append((char) 0x01CB); - break; - case (char) 0x01F1: // DZ -> Dz - case (char) 0x01F2: // Dz -> Dz - case (char) 0x01F3: // dz -> Dz - result.Append((char) 0x01F2); - break; - default: - result.Append(ToUpper(input[inputIndex])); - break; - } - } - return inputIndex; - } - - // - // Used in ToTitleCase(): - // When we find a starting letter, the following array decides if a category should be - // considered as word seprator or not. - // - private const int c_wordSeparatorMask = - /* false */ (0 << 0) | // UppercaseLetter = 0, - /* false */ (0 << 1) | // LowercaseLetter = 1, - /* false */ (0 << 2) | // TitlecaseLetter = 2, - /* false */ (0 << 3) | // ModifierLetter = 3, - /* false */ (0 << 4) | // OtherLetter = 4, - /* false */ (0 << 5) | // NonSpacingMark = 5, - /* false */ (0 << 6) | // SpacingCombiningMark = 6, - /* false */ (0 << 7) | // EnclosingMark = 7, - /* false */ (0 << 8) | // DecimalDigitNumber = 8, - /* false */ (0 << 9) | // LetterNumber = 9, - /* false */ (0 << 10) | // OtherNumber = 10, - /* true */ (1 << 11) | // SpaceSeparator = 11, - /* true */ (1 << 12) | // LineSeparator = 12, - /* true */ (1 << 13) | // ParagraphSeparator = 13, - /* true */ (1 << 14) | // Control = 14, - /* true */ (1 << 15) | // Format = 15, - /* false */ (0 << 16) | // Surrogate = 16, - /* false */ (0 << 17) | // PrivateUse = 17, - /* true */ (1 << 18) | // ConnectorPunctuation = 18, - /* true */ (1 << 19) | // DashPunctuation = 19, - /* true */ (1 << 20) | // OpenPunctuation = 20, - /* true */ (1 << 21) | // ClosePunctuation = 21, - /* true */ (1 << 22) | // InitialQuotePunctuation = 22, - /* true */ (1 << 23) | // FinalQuotePunctuation = 23, - /* true */ (1 << 24) | // OtherPunctuation = 24, - /* true */ (1 << 25) | // MathSymbol = 25, - /* true */ (1 << 26) | // CurrencySymbol = 26, - /* true */ (1 << 27) | // ModifierSymbol = 27, - /* true */ (1 << 28) | // OtherSymbol = 28, - /* false */ (0 << 29); // OtherNotAssigned = 29; - - private static bool IsWordSeparator(UnicodeCategory category) - { - return (c_wordSeparatorMask & (1 << (int) category)) != 0; - } - - private static bool IsLetterCategory(UnicodeCategory uc) - { - return (uc == UnicodeCategory.UppercaseLetter - || uc == UnicodeCategory.LowercaseLetter - || uc == UnicodeCategory.TitlecaseLetter - || uc == UnicodeCategory.ModifierLetter - || uc == UnicodeCategory.OtherLetter); - } - - // - // Get case-insensitive hash code for the specified string. - // - internal unsafe int GetCaseInsensitiveHashCode(String str) - { - // Validate inputs - if (str == null) - { - throw new ArgumentNullException(nameof(str)); - } - - // This code assumes that ASCII casing is safe for whatever context is passed in. - // this is true today, because we only ever call these methods on Invariant. It would be ideal to refactor - // these methods so they were correct by construction and we could only ever use Invariant. - - uint hash = 5381; - uint c; - - // Note: We assume that str contains only ASCII characters until - // we hit a non-ASCII character to optimize the common case. - for (int i = 0; i < str.Length; i++) - { - c = str[i]; - if (c >= 0x80) - { - return GetCaseInsensitiveHashCodeSlow(str); - } - - // If we have a lowercase character, ANDing off 0x20 - // will make it an uppercase character. - if ((c - 'a') <= ('z' - 'a')) - { - c = (uint)((int)c & ~0x20); - } - - hash = ((hash << 5) + hash) ^ c; - } - - return (int)hash; - } - - private unsafe int GetCaseInsensitiveHashCodeSlow(String str) - { - Debug.Assert(str != null); - - string upper = ToUpper(str); - - uint hash = 5381; - uint c; - - for (int i = 0; i < upper.Length; i++) - { - c = upper[i]; - hash = ((hash << 5) + hash) ^ c; - } - - return (int)hash; - } - } -} diff --git a/src/mscorlib/corefx/System/Globalization/ThaiBuddhistCalendar.cs b/src/mscorlib/corefx/System/Globalization/ThaiBuddhistCalendar.cs deleted file mode 100644 index 9e6e304..0000000 --- a/src/mscorlib/corefx/System/Globalization/ThaiBuddhistCalendar.cs +++ /dev/null @@ -1,236 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.Diagnostics.CodeAnalysis; -using System.Diagnostics.Contracts; - -namespace System.Globalization -{ - /*=================================ThaiBuddhistCalendar========================== - ** - ** ThaiBuddhistCalendar is based on Gregorian calendar. Its year value has - ** an offset to the Gregorain calendar. - ** - ** Calendar support range: - ** Calendar Minimum Maximum - ** ========== ========== ========== - ** Gregorian 0001/01/01 9999/12/31 - ** Thai 0544/01/01 10542/12/31 - ============================================================================*/ - - [Serializable] - public class ThaiBuddhistCalendar : Calendar - { - // Initialize our era info. - internal static EraInfo[] thaiBuddhistEraInfo = new EraInfo[] { - new EraInfo( 1, 1, 1, 1, -543, 544, GregorianCalendar.MaxYear + 543) // era #, start year/month/day, yearOffset, minEraYear - }; - - // - // The era value for the current era. - // - - public const int ThaiBuddhistEra = 1; - - internal GregorianCalendarHelper helper; - - - public override DateTime MinSupportedDateTime - { - get - { - return (DateTime.MinValue); - } - } - - public override DateTime MaxSupportedDateTime - { - get - { - return (DateTime.MaxValue); - } - } - - public override CalendarAlgorithmType AlgorithmType - { - get - { - return CalendarAlgorithmType.SolarCalendar; - } - } - - public ThaiBuddhistCalendar() - { - helper = new GregorianCalendarHelper(this, thaiBuddhistEraInfo); - } - - internal override CalendarId ID - { - get - { - return (CalendarId.THAI); - } - } - - - public override DateTime AddMonths(DateTime time, int months) - { - return (helper.AddMonths(time, months)); - } - - - public override DateTime AddYears(DateTime time, int years) - { - return (helper.AddYears(time, years)); - } - - - public override int GetDaysInMonth(int year, int month, int era) - { - return (helper.GetDaysInMonth(year, month, era)); - } - - - public override int GetDaysInYear(int year, int era) - { - return (helper.GetDaysInYear(year, era)); - } - - - public override int GetDayOfMonth(DateTime time) - { - return (helper.GetDayOfMonth(time)); - } - - - public override DayOfWeek GetDayOfWeek(DateTime time) - { - return (helper.GetDayOfWeek(time)); - } - - - public override int GetDayOfYear(DateTime time) - { - return (helper.GetDayOfYear(time)); - } - - - public override int GetMonthsInYear(int year, int era) - { - return (helper.GetMonthsInYear(year, era)); - } - - - [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems. - public override int GetWeekOfYear(DateTime time, CalendarWeekRule rule, DayOfWeek firstDayOfWeek) - { - return (helper.GetWeekOfYear(time, rule, firstDayOfWeek)); - } - - - public override int GetEra(DateTime time) - { - return (helper.GetEra(time)); - } - - public override int GetMonth(DateTime time) - { - return (helper.GetMonth(time)); - } - - - public override int GetYear(DateTime time) - { - return (helper.GetYear(time)); - } - - - public override bool IsLeapDay(int year, int month, int day, int era) - { - return (helper.IsLeapDay(year, month, day, era)); - } - - - public override bool IsLeapYear(int year, int era) - { - return (helper.IsLeapYear(year, era)); - } - - // Returns the leap month in a calendar year of the specified era. This method returns 0 - // if this calendar does not have leap month, or this year is not a leap year. - // - - public override int GetLeapMonth(int year, int era) - { - return (helper.GetLeapMonth(year, era)); - } - - - public override bool IsLeapMonth(int year, int month, int era) - { - return (helper.IsLeapMonth(year, month, era)); - } - - - public override DateTime ToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era) - { - return (helper.ToDateTime(year, month, day, hour, minute, second, millisecond, era)); - } - - - public override int[] Eras - { - get - { - return (helper.Eras); - } - } - - private const int DEFAULT_TWO_DIGIT_YEAR_MAX = 2572; - - - public override int TwoDigitYearMax - { - get - { - if (twoDigitYearMax == -1) - { - twoDigitYearMax = GetSystemTwoDigitYearSetting(ID, DEFAULT_TWO_DIGIT_YEAR_MAX); - } - return (twoDigitYearMax); - } - - set - { - VerifyWritable(); - if (value < 99 || value > helper.MaxYear) - { - throw new ArgumentOutOfRangeException( - "year", - String.Format( - CultureInfo.CurrentCulture, - SR.ArgumentOutOfRange_Range, - 99, - helper.MaxYear)); - } - twoDigitYearMax = value; - } - } - - - public override int ToFourDigitYear(int year) - { - if (year < 0) - { - throw new ArgumentOutOfRangeException(nameof(year), - SR.ArgumentOutOfRange_NeedNonNegNum); - } - Contract.EndContractBlock(); - - return (helper.ToFourDigitYear(year, this.TwoDigitYearMax)); - } - } -} - diff --git a/src/mscorlib/corefx/System/Globalization/TimeSpanStyles.cs b/src/mscorlib/corefx/System/Globalization/TimeSpanStyles.cs deleted file mode 100644 index 68a47bc..0000000 --- a/src/mscorlib/corefx/System/Globalization/TimeSpanStyles.cs +++ /dev/null @@ -1,13 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -namespace System.Globalization -{ - [Flags] - public enum TimeSpanStyles - { - None = 0x00000000, - AssumeNegative = 0x00000001, - } -} diff --git a/src/mscorlib/corefx/System/Globalization/UmAlQuraCalendar.cs b/src/mscorlib/corefx/System/Globalization/UmAlQuraCalendar.cs deleted file mode 100644 index 7b47d9c..0000000 --- a/src/mscorlib/corefx/System/Globalization/UmAlQuraCalendar.cs +++ /dev/null @@ -1,870 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System.Diagnostics; -using System.Diagnostics.Contracts; - -namespace System.Globalization -{ - //////////////////////////////////////////////////////////////////////////// - // - // Notes about UmAlQuraCalendar - // - //////////////////////////////////////////////////////////////////////////// - /* - ** Calendar support range: - ** Calendar Minimum Maximum - ** ========== ========== ========== - ** Gregorian 1900/04/30 2077/05/13 - ** UmAlQura 1318/01/01 1500/12/30 - */ - - [Serializable] - public partial class UmAlQuraCalendar : Calendar - { - internal const int MinCalendarYear = 1318; - internal const int MaxCalendarYear = 1500; - - internal struct DateMapping - { - internal DateMapping(int MonthsLengthFlags, int GYear, int GMonth, int GDay) - { - HijriMonthsLengthFlags = MonthsLengthFlags; - GregorianDate = new DateTime(GYear, GMonth, GDay); - } - internal int HijriMonthsLengthFlags; - internal DateTime GregorianDate; - } - - private static readonly DateMapping[] s_hijriYearInfo = InitDateMapping(); - - private static DateMapping[] InitDateMapping() - { - short[] rawData = new short[] - { - //These data is taken from Tables/Excel/UmAlQura.xls please make sure that the two places are in sync - /* DaysPerM GY GM GD D1 D2 D3 D4 D5 D6 D7 D8 D9 D10 D11 D12 - 1318*/0x02EA, 1900, 4, 30,/* 0 1 0 1 0 1 1 1 0 1 0 0 4/30/1900 - 1319*/0x06E9, 1901, 4, 19,/* 1 0 0 1 0 1 1 1 0 1 1 0 4/19/1901 - 1320*/0x0ED2, 1902, 4, 9,/* 0 1 0 0 1 0 1 1 0 1 1 1 4/9/1902 - 1321*/0x0EA4, 1903, 3, 30,/* 0 0 1 0 0 1 0 1 0 1 1 1 3/30/1903 - 1322*/0x0D4A, 1904, 3, 18,/* 0 1 0 1 0 0 1 0 1 0 1 1 3/18/1904 - 1323*/0x0A96, 1905, 3, 7,/* 0 1 1 0 1 0 0 1 0 1 0 1 3/7/1905 - 1324*/0x0536, 1906, 2, 24,/* 0 1 1 0 1 1 0 0 1 0 1 0 2/24/1906 - 1325*/0x0AB5, 1907, 2, 13,/* 1 0 1 0 1 1 0 1 0 1 0 1 2/13/1907 - 1326*/0x0DAA, 1908, 2, 3,/* 0 1 0 1 0 1 0 1 1 0 1 1 2/3/1908 - 1327*/0x0BA4, 1909, 1, 23,/* 0 0 1 0 0 1 0 1 1 1 0 1 1/23/1909 - 1328*/0x0B49, 1910, 1, 12,/* 1 0 0 1 0 0 1 0 1 1 0 1 1/12/1910 - 1329*/0x0A93, 1911, 1, 1,/* 1 1 0 0 1 0 0 1 0 1 0 1 1/1/1911 - 1330*/0x052B, 1911, 12, 21,/* 1 1 0 1 0 1 0 0 1 0 1 0 12/21/1911 - 1331*/0x0A57, 1912, 12, 9,/* 1 1 1 0 1 0 1 0 0 1 0 1 12/9/1912 - 1332*/0x04B6, 1913, 11, 29,/* 0 1 1 0 1 1 0 1 0 0 1 0 11/29/1913 - 1333*/0x0AB5, 1914, 11, 18,/* 1 0 1 0 1 1 0 1 0 1 0 1 11/18/1914 - 1334*/0x05AA, 1915, 11, 8,/* 0 1 0 1 0 1 0 1 1 0 1 0 11/8/1915 - 1335*/0x0D55, 1916, 10, 27,/* 1 0 1 0 1 0 1 0 1 0 1 1 10/27/1916 - 1336*/0x0D2A, 1917, 10, 17,/* 0 1 0 1 0 1 0 0 1 0 1 1 10/17/1917 - 1337*/0x0A56, 1918, 10, 6,/* 0 1 1 0 1 0 1 0 0 1 0 1 10/6/1918 - 1338*/0x04AE, 1919, 9, 25,/* 0 1 1 1 0 1 0 1 0 0 1 0 9/25/1919 - 1339*/0x095D, 1920, 9, 13,/* 1 0 1 1 1 0 1 0 1 0 0 1 9/13/1920 - 1340*/0x02EC, 1921, 9, 3,/* 0 0 1 1 0 1 1 1 0 1 0 0 9/3/1921 - 1341*/0x06D5, 1922, 8, 23,/* 1 0 1 0 1 0 1 1 0 1 1 0 8/23/1922 - 1342*/0x06AA, 1923, 8, 13,/* 0 1 0 1 0 1 0 1 0 1 1 0 8/13/1923 - 1343*/0x0555, 1924, 8, 1,/* 1 0 1 0 1 0 1 0 1 0 1 0 8/1/1924 - 1344*/0x04AB, 1925, 7, 21,/* 1 1 0 1 0 1 0 1 0 0 1 0 7/21/1925 - 1345*/0x095B, 1926, 7, 10,/* 1 1 0 1 1 0 1 0 1 0 0 1 7/10/1926 - 1346*/0x02BA, 1927, 6, 30,/* 0 1 0 1 1 1 0 1 0 1 0 0 6/30/1927 - 1347*/0x0575, 1928, 6, 18,/* 1 0 1 0 1 1 1 0 1 0 1 0 6/18/1928 - 1348*/0x0BB2, 1929, 6, 8,/* 0 1 0 0 1 1 0 1 1 1 0 1 6/8/1929 - 1349*/0x0764, 1930, 5, 29,/* 0 0 1 0 0 1 1 0 1 1 1 0 5/29/1930 - 1350*/0x0749, 1931, 5, 18,/* 1 0 0 1 0 0 1 0 1 1 1 0 5/18/1931 - 1351*/0x0655, 1932, 5, 6,/* 1 0 1 0 1 0 1 0 0 1 1 0 5/6/1932 - 1352*/0x02AB, 1933, 4, 25,/* 1 1 0 1 0 1 0 1 0 1 0 0 4/25/1933 - 1353*/0x055B, 1934, 4, 14,/* 1 1 0 1 1 0 1 0 1 0 1 0 4/14/1934 - 1354*/0x0ADA, 1935, 4, 4,/* 0 1 0 1 1 0 1 1 0 1 0 1 4/4/1935 - 1355*/0x06D4, 1936, 3, 24,/* 0 0 1 0 1 0 1 1 0 1 1 0 3/24/1936 - 1356*/0x0EC9, 1937, 3, 13,/* 1 0 0 1 0 0 1 1 0 1 1 1 3/13/1937 - 1357*/0x0D92, 1938, 3, 3,/* 0 1 0 0 1 0 0 1 1 0 1 1 3/3/1938 - 1358*/0x0D25, 1939, 2, 20,/* 1 0 1 0 0 1 0 0 1 0 1 1 2/20/1939 - 1359*/0x0A4D, 1940, 2, 9,/* 1 0 1 1 0 0 1 0 0 1 0 1 2/9/1940 - 1360*/0x02AD, 1941, 1, 28,/* 1 0 1 1 0 1 0 1 0 1 0 0 1/28/1941 - 1361*/0x056D, 1942, 1, 17,/* 1 0 1 1 0 1 1 0 1 0 1 0 1/17/1942 - 1362*/0x0B6A, 1943, 1, 7,/* 0 1 0 1 0 1 1 0 1 1 0 1 1/7/1943 - 1363*/0x0B52, 1943, 12, 28,/* 0 1 0 0 1 0 1 0 1 1 0 1 12/28/1943 - 1364*/0x0AA5, 1944, 12, 16,/* 1 0 1 0 0 1 0 1 0 1 0 1 12/16/1944 - 1365*/0x0A4B, 1945, 12, 5,/* 1 1 0 1 0 0 1 0 0 1 0 1 12/5/1945 - 1366*/0x0497, 1946, 11, 24,/* 1 1 1 0 1 0 0 1 0 0 1 0 11/24/1946 - 1367*/0x0937, 1947, 11, 13,/* 1 1 1 0 1 1 0 0 1 0 0 1 11/13/1947 - 1368*/0x02B6, 1948, 11, 2,/* 0 1 1 0 1 1 0 1 0 1 0 0 11/2/1948 - 1369*/0x0575, 1949, 10, 22,/* 1 0 1 0 1 1 1 0 1 0 1 0 10/22/1949 - 1370*/0x0D6A, 1950, 10, 12,/* 0 1 0 1 0 1 1 0 1 0 1 1 10/12/1950 - 1371*/0x0D52, 1951, 10, 2,/* 0 1 0 0 1 0 1 0 1 0 1 1 10/2/1951 - 1372*/0x0A96, 1952, 9, 20,/* 0 1 1 0 1 0 0 1 0 1 0 1 9/20/1952 - 1373*/0x092D, 1953, 9, 9,/* 1 0 1 1 0 1 0 0 1 0 0 1 9/9/1953 - 1374*/0x025D, 1954, 8, 29,/* 1 0 1 1 1 0 1 0 0 1 0 0 8/29/1954 - 1375*/0x04DD, 1955, 8, 18,/* 1 0 1 1 1 0 1 1 0 0 1 0 8/18/1955 - 1376*/0x0ADA, 1956, 8, 7,/* 0 1 0 1 1 0 1 1 0 1 0 1 8/7/1956 - 1377*/0x05D4, 1957, 7, 28,/* 0 0 1 0 1 0 1 1 1 0 1 0 7/28/1957 - 1378*/0x0DA9, 1958, 7, 17,/* 1 0 0 1 0 1 0 1 1 0 1 1 7/17/1958 - 1379*/0x0D52, 1959, 7, 7,/* 0 1 0 0 1 0 1 0 1 0 1 1 7/7/1959 - 1380*/0x0AAA, 1960, 6, 25,/* 0 1 0 1 0 1 0 1 0 1 0 1 6/25/1960 - 1381*/0x04D6, 1961, 6, 14,/* 0 1 1 0 1 0 1 1 0 0 1 0 6/14/1961 - 1382*/0x09B6, 1962, 6, 3,/* 0 1 1 0 1 1 0 1 1 0 0 1 6/3/1962 - 1383*/0x0374, 1963, 5, 24,/* 0 0 1 0 1 1 1 0 1 1 0 0 5/24/1963 - 1384*/0x0769, 1964, 5, 12,/* 1 0 0 1 0 1 1 0 1 1 1 0 5/12/1964 - 1385*/0x0752, 1965, 5, 2,/* 0 1 0 0 1 0 1 0 1 1 1 0 5/2/1965 - 1386*/0x06A5, 1966, 4, 21,/* 1 0 1 0 0 1 0 1 0 1 1 0 4/21/1966 - 1387*/0x054B, 1967, 4, 10,/* 1 1 0 1 0 0 1 0 1 0 1 0 4/10/1967 - 1388*/0x0AAB, 1968, 3, 29,/* 1 1 0 1 0 1 0 1 0 1 0 1 3/29/1968 - 1389*/0x055A, 1969, 3, 19,/* 0 1 0 1 1 0 1 0 1 0 1 0 3/19/1969 - 1390*/0x0AD5, 1970, 3, 8,/* 1 0 1 0 1 0 1 1 0 1 0 1 3/8/1970 - 1391*/0x0DD2, 1971, 2, 26,/* 0 1 0 0 1 0 1 1 1 0 1 1 2/26/1971 - 1392*/0x0DA4, 1972, 2, 16,/* 0 0 1 0 0 1 0 1 1 0 1 1 2/16/1972 - 1393*/0x0D49, 1973, 2, 4,/* 1 0 0 1 0 0 1 0 1 0 1 1 2/4/1973 - 1394*/0x0A95, 1974, 1, 24,/* 1 0 1 0 1 0 0 1 0 1 0 1 1/24/1974 - 1395*/0x052D, 1975, 1, 13,/* 1 0 1 1 0 1 0 0 1 0 1 0 1/13/1975 - 1396*/0x0A5D, 1976, 1, 2,/* 1 0 1 1 1 0 1 0 0 1 0 1 1/2/1976 - 1397*/0x055A, 1976, 12, 22,/* 0 1 0 1 1 0 1 0 1 0 1 0 12/22/1976 - 1398*/0x0AD5, 1977, 12, 11,/* 1 0 1 0 1 0 1 1 0 1 0 1 12/11/1977 - 1399*/0x06AA, 1978, 12, 1,/* 0 1 0 1 0 1 0 1 0 1 1 0 12/1/1978 - 1400*/0x0695, 1979, 11, 20,/* 1 0 1 0 1 0 0 1 0 1 1 0 11/20/1979 - 1401*/0x052B, 1980, 11, 8,/* 1 1 0 1 0 1 0 0 1 0 1 0 11/8/1980 - 1402*/0x0A57, 1981, 10, 28,/* 1 1 1 0 1 0 1 0 0 1 0 1 10/28/1981 - 1403*/0x04AE, 1982, 10, 18,/* 0 1 1 1 0 1 0 1 0 0 1 0 10/18/1982 - 1404*/0x0976, 1983, 10, 7,/* 0 1 1 0 1 1 1 0 1 0 0 1 10/7/1983 - 1405*/0x056C, 1984, 9, 26,/* 0 0 1 1 0 1 1 0 1 0 1 0 9/26/1984 - 1406*/0x0B55, 1985, 9, 15,/* 1 0 1 0 1 0 1 0 1 1 0 1 9/15/1985 - 1407*/0x0AAA, 1986, 9, 5,/* 0 1 0 1 0 1 0 1 0 1 0 1 9/5/1986 - 1408*/0x0A55, 1987, 8, 25,/* 1 0 1 0 1 0 1 0 0 1 0 1 8/25/1987 - 1409*/0x04AD, 1988, 8, 13,/* 1 0 1 1 0 1 0 1 0 0 1 0 8/13/1988 - 1410*/0x095D, 1989, 8, 2,/* 1 0 1 1 1 0 1 0 1 0 0 1 8/2/1989 - 1411*/0x02DA, 1990, 7, 23,/* 0 1 0 1 1 0 1 1 0 1 0 0 7/23/1990 - 1412*/0x05D9, 1991, 7, 12,/* 1 0 0 1 1 0 1 1 1 0 1 0 7/12/1991 - 1413*/0x0DB2, 1992, 7, 1,/* 0 1 0 0 1 1 0 1 1 0 1 1 7/1/1992 - 1414*/0x0BA4, 1993, 6, 21,/* 0 0 1 0 0 1 0 1 1 1 0 1 6/21/1993 - 1415*/0x0B4A, 1994, 6, 10,/* 0 1 0 1 0 0 1 0 1 1 0 1 6/10/1994 - 1416*/0x0A55, 1995, 5, 30,/* 1 0 1 0 1 0 1 0 0 1 0 1 5/30/1995 - 1417*/0x02B5, 1996, 5, 18,/* 1 0 1 0 1 1 0 1 0 1 0 0 5/18/1996 - 1418*/0x0575, 1997, 5, 7,/* 1 0 1 0 1 1 1 0 1 0 1 0 5/7/1997 - 1419*/0x0B6A, 1998, 4, 27,/* 0 1 0 1 0 1 1 0 1 1 0 1 4/27/1998 - 1420*/0x0BD2, 1999, 4, 17,/* 0 1 0 0 1 0 1 1 1 1 0 1 4/17/1999 - 1421*/0x0BC4, 2000, 4, 6,/* 0 0 1 0 0 0 1 1 1 1 0 1 4/6/2000 - 1422*/0x0B89, 2001, 3, 26,/* 1 0 0 1 0 0 0 1 1 1 0 1 3/26/2001 - 1423*/0x0A95, 2002, 3, 15,/* 1 0 1 0 1 0 0 1 0 1 0 1 3/15/2002 - 1424*/0x052D, 2003, 3, 4,/* 1 0 1 1 0 1 0 0 1 0 1 0 3/4/2003 - 1425*/0x05AD, 2004, 2, 21,/* 1 0 1 1 0 1 0 1 1 0 1 0 2/21/2004 - 1426*/0x0B6A, 2005, 2, 10,/* 0 1 0 1 0 1 1 0 1 1 0 1 2/10/2005 - 1427*/0x06D4, 2006, 1, 31,/* 0 0 1 0 1 0 1 1 0 1 1 0 1/31/2006 - 1428*/0x0DC9, 2007, 1, 20,/* 1 0 0 1 0 0 1 1 1 0 1 1 1/20/2007 - 1429*/0x0D92, 2008, 1, 10,/* 0 1 0 0 1 0 0 1 1 0 1 1 1/10/2008 - 1430*/0x0AA6, 2008, 12, 29,/* 0 1 1 0 0 1 0 1 0 1 0 1 12/29/2008 - 1431*/0x0956, 2009, 12, 18,/* 0 1 1 0 1 0 1 0 1 0 0 1 12/18/2009 - 1432*/0x02AE, 2010, 12, 7,/* 0 1 1 1 0 1 0 1 0 1 0 0 12/7/2010 - 1433*/0x056D, 2011, 11, 26,/* 1 0 1 1 0 1 1 0 1 0 1 0 11/26/2011 - 1434*/0x036A, 2012, 11, 15,/* 0 1 0 1 0 1 1 0 1 1 0 0 11/15/2012 - 1435*/0x0B55, 2013, 11, 4,/* 1 0 1 0 1 0 1 0 1 1 0 1 11/4/2013 - 1436*/0x0AAA, 2014, 10, 25,/* 0 1 0 1 0 1 0 1 0 1 0 1 10/25/2014 - 1437*/0x094D, 2015, 10, 14,/* 1 0 1 1 0 0 1 0 1 0 0 1 10/14/2015 - 1438*/0x049D, 2016, 10, 2,/* 1 0 1 1 1 0 0 1 0 0 1 0 10/2/2016 - 1439*/0x095D, 2017, 9, 21,/* 1 0 1 1 1 0 1 0 1 0 0 1 9/21/2017 - 1440*/0x02BA, 2018, 9, 11,/* 0 1 0 1 1 1 0 1 0 1 0 0 9/11/2018 - 1441*/0x05B5, 2019, 8, 31,/* 1 0 1 0 1 1 0 1 1 0 1 0 8/31/2019 - 1442*/0x05AA, 2020, 8, 20,/* 0 1 0 1 0 1 0 1 1 0 1 0 8/20/2020 - 1443*/0x0D55, 2021, 8, 9,/* 1 0 1 0 1 0 1 0 1 0 1 1 8/9/2021 - 1444*/0x0A9A, 2022, 7, 30,/* 0 1 0 1 1 0 0 1 0 1 0 1 7/30/2022 - 1445*/0x092E, 2023, 7, 19,/* 0 1 1 1 0 1 0 0 1 0 0 1 7/19/2023 - 1446*/0x026E, 2024, 7, 7,/* 0 1 1 1 0 1 1 0 0 1 0 0 7/7/2024 - 1447*/0x055D, 2025, 6, 26,/* 1 0 1 1 1 0 1 0 1 0 1 0 6/26/2025 - 1448*/0x0ADA, 2026, 6, 16,/* 0 1 0 1 1 0 1 1 0 1 0 1 6/16/2026 - 1449*/0x06D4, 2027, 6, 6,/* 0 0 1 0 1 0 1 1 0 1 1 0 6/6/2027 - 1450*/0x06A5, 2028, 5, 25,/* 1 0 1 0 0 1 0 1 0 1 1 0 5/25/2028 - 1451*/0x054B, 2029, 5, 14,/* 1 1 0 1 0 0 1 0 1 0 1 0 5/14/2029 - 1452*/0x0A97, 2030, 5, 3,/* 1 1 1 0 1 0 0 1 0 1 0 1 5/3/2030 - 1453*/0x054E, 2031, 4, 23,/* 0 1 1 1 0 0 1 0 1 0 1 0 4/23/2031 - 1454*/0x0AAE, 2032, 4, 11,/* 0 1 1 1 0 1 0 1 0 1 0 1 4/11/2032 - 1455*/0x05AC, 2033, 4, 1,/* 0 0 1 1 0 1 0 1 1 0 1 0 4/1/2033 - 1456*/0x0BA9, 2034, 3, 21,/* 1 0 0 1 0 1 0 1 1 1 0 1 3/21/2034 - 1457*/0x0D92, 2035, 3, 11,/* 0 1 0 0 1 0 0 1 1 0 1 1 3/11/2035 - 1458*/0x0B25, 2036, 2, 28,/* 1 0 1 0 0 1 0 0 1 1 0 1 2/28/2036 - 1459*/0x064B, 2037, 2, 16,/* 1 1 0 1 0 0 1 0 0 1 1 0 2/16/2037 - 1460*/0x0CAB, 2038, 2, 5,/* 1 1 0 1 0 1 0 1 0 0 1 1 2/5/2038 - 1461*/0x055A, 2039, 1, 26,/* 0 1 0 1 1 0 1 0 1 0 1 0 1/26/2039 - 1462*/0x0B55, 2040, 1, 15,/* 1 0 1 0 1 0 1 0 1 1 0 1 1/15/2040 - 1463*/0x06D2, 2041, 1, 4,/* 0 1 0 0 1 0 1 1 0 1 1 0 1/4/2041 - 1464*/0x0EA5, 2041, 12, 24,/* 1 0 1 0 0 1 0 1 0 1 1 1 12/24/2041 - 1465*/0x0E4A, 2042, 12, 14,/* 0 1 0 1 0 0 1 0 0 1 1 1 12/14/2042 - 1466*/0x0A95, 2043, 12, 3,/* 1 0 1 0 1 0 0 1 0 1 0 1 12/3/2043 - 1467*/0x052D, 2044, 11, 21,/* 1 0 1 1 0 1 0 0 1 0 1 0 11/21/2044 - 1468*/0x0AAD, 2045, 11, 10,/* 1 0 1 1 0 1 0 1 0 1 0 1 11/10/2045 - 1469*/0x036C, 2046, 10, 31,/* 0 0 1 1 0 1 1 0 1 1 0 0 10/31/2046 - 1470*/0x0759, 2047, 10, 20,/* 1 0 0 1 1 0 1 0 1 1 1 0 10/20/2047 - 1471*/0x06D2, 2048, 10, 9,/* 0 1 0 0 1 0 1 1 0 1 1 0 10/9/2048 - 1472*/0x0695, 2049, 9, 28,/* 1 0 1 0 1 0 0 1 0 1 1 0 9/28/2049 - 1473*/0x052D, 2050, 9, 17,/* 1 0 1 1 0 1 0 0 1 0 1 0 9/17/2050 - 1474*/0x0A5B, 2051, 9, 6,/* 1 1 0 1 1 0 1 0 0 1 0 1 9/6/2051 - 1475*/0x04BA, 2052, 8, 26,/* 0 1 0 1 1 1 0 1 0 0 1 0 8/26/2052 - 1476*/0x09BA, 2053, 8, 15,/* 0 1 0 1 1 1 0 1 1 0 0 1 8/15/2053 - 1477*/0x03B4, 2054, 8, 5,/* 0 0 1 0 1 1 0 1 1 1 0 0 8/5/2054 - 1478*/0x0B69, 2055, 7, 25,/* 1 0 0 1 0 1 1 0 1 1 0 1 7/25/2055 - 1479*/0x0B52, 2056, 7, 14,/* 0 1 0 0 1 0 1 0 1 1 0 1 7/14/2056 - 1480*/0x0AA6, 2057, 7, 3,/* 0 1 1 0 0 1 0 1 0 1 0 1 7/3/2057 - 1481*/0x04B6, 2058, 6, 22,/* 0 1 1 0 1 1 0 1 0 0 1 0 6/22/2058 - 1482*/0x096D, 2059, 6, 11,/* 1 0 1 1 0 1 1 0 1 0 0 1 6/11/2059 - 1483*/0x02EC, 2060, 5, 31,/* 0 0 1 1 0 1 1 1 0 1 0 0 5/31/2060 - 1484*/0x06D9, 2061, 5, 20,/* 1 0 0 1 1 0 1 1 0 1 1 0 5/20/2061 - 1485*/0x0EB2, 2062, 5, 10,/* 0 1 0 0 1 1 0 1 0 1 1 1 5/10/2062 - 1486*/0x0D54, 2063, 4, 30,/* 0 0 1 0 1 0 1 0 1 0 1 1 4/30/2063 - 1487*/0x0D2A, 2064, 4, 18,/* 0 1 0 1 0 1 0 0 1 0 1 1 4/18/2064 - 1488*/0x0A56, 2065, 4, 7,/* 0 1 1 0 1 0 1 0 0 1 0 1 4/7/2065 - 1489*/0x04AE, 2066, 3, 27,/* 0 1 1 1 0 1 0 1 0 0 1 0 3/27/2066 - 1490*/0x096D, 2067, 3, 16,/* 1 0 1 1 0 1 1 0 1 0 0 1 3/16/2067 - 1491*/0x0D6A, 2068, 3, 5,/* 0 1 0 1 0 1 1 0 1 0 1 1 3/5/2068 - 1492*/0x0B54, 2069, 2, 23,/* 0 0 1 0 1 0 1 0 1 1 0 1 2/23/2069 - 1493*/0x0B29, 2070, 2, 12,/* 1 0 0 1 0 1 0 0 1 1 0 1 2/12/2070 - 1494*/0x0A93, 2071, 2, 1,/* 1 1 0 0 1 0 0 1 0 1 0 1 2/1/2071 - 1495*/0x052B, 2072, 1, 21,/* 1 1 0 1 0 1 0 0 1 0 1 0 1/21/2072 - 1496*/0x0A57, 2073, 1, 9,/* 1 1 1 0 1 0 1 0 0 1 0 1 1/9/2073 - 1497*/0x0536, 2073, 12, 30,/* 0 1 1 0 1 1 0 0 1 0 1 0 12/30/2073 - 1498*/0x0AB5, 2074, 12, 19,/* 1 0 1 0 1 1 0 1 0 1 0 1 12/19/2074 - 1499*/0x06AA, 2075, 12, 9,/* 0 1 0 1 0 1 0 1 0 1 1 0 12/9/2075 - 1500*/0x0E93, 2076, 11, 27,/* 1 1 0 0 1 0 0 1 0 1 1 1 11/27/2076 - 1501*/ 0, 2077, 11, 17,/* 0 0 0 0 0 0 0 0 0 0 0 0 11/17/2077 - */ }; - // Direct inline initialization of DateMapping array would produce a lot of code bloat. - - // We take advantage of C# compiler compiles inline initialization of primitive type array into very compact code. - // So we start with raw data stored in primitive type array, and initialize the DateMapping out of it - - DateMapping[] mapping = new DateMapping[rawData.Length / 4]; - for (int i = 0; i < mapping.Length; i++) - mapping[i] = new DateMapping(rawData[i * 4], rawData[i * 4 + 1], rawData[i * 4 + 2], rawData[i * 4 + 3]); - return mapping; - } - - public const int UmAlQuraEra = 1; - - internal const int DateCycle = 30; - internal const int DatePartYear = 0; - internal const int DatePartDayOfYear = 1; - internal const int DatePartMonth = 2; - internal const int DatePartDay = 3; - - - // This is the minimal Gregorian date that we support in the UmAlQuraCalendar. - internal static DateTime minDate = new DateTime(1900, 4, 30); - internal static DateTime maxDate = new DateTime((new DateTime(2077, 11, 16, 23, 59, 59, 999)).Ticks + 9999); - - public override DateTime MinSupportedDateTime - { - get - { - return (minDate); - } - } - - public override DateTime MaxSupportedDateTime - { - get - { - return (maxDate); - } - } - - public override CalendarAlgorithmType AlgorithmType - { - get - { - return CalendarAlgorithmType.LunarCalendar; - } - } - - public UmAlQuraCalendar() - { - } - - internal override CalendarId BaseCalendarID - { - get - { - return (CalendarId.HIJRI); - } - } - - internal override CalendarId ID - { - get - { - return (CalendarId.UMALQURA); - } - } - - protected override int DaysInYearBeforeMinSupportedYear - { - get - { - // HijriCalendar has same number of days as UmAlQuraCalendar for any given year - // HijriCalendar says year 1317 has 355 days. - return 355; - } - } - - /*==========================ConvertHijriToGregorian========================== - ** Purpose: convert Hdate(year,month,day) to Gdate(year,month,day) - ** Arguments: - ** Input/Ouput: Hijrah date: year:yh, month:mh, day:dh - ** Output: Gregorian date: year:yg, month:mg, day:dg , day of week:dayweek - ** and returns flag found:1 not found:0 - =========================ConvertHijriToGregorian============================*/ - private static void ConvertHijriToGregorian(int HijriYear, int HijriMonth, int HijriDay, ref int yg, ref int mg, ref int dg) - { - Debug.Assert((HijriYear >= MinCalendarYear) && (HijriYear <= MaxCalendarYear), "Hijri year is out of range."); - Debug.Assert(HijriMonth >= 1, "Hijri month is out of range."); - Debug.Assert(HijriDay >= 1, "Hijri day is out of range."); - int index, b, nDays = HijriDay - 1; - DateTime dt; - - - index = HijriYear - MinCalendarYear; - dt = s_hijriYearInfo[index].GregorianDate; - - - b = s_hijriYearInfo[index].HijriMonthsLengthFlags; - - for (int m = 1; m < HijriMonth; m++) - { - nDays = nDays + 29 + (b & 1); /* Add the months lengths before mh */ - b = b >> 1; - } - - dt = dt.AddDays(nDays); - yg = dt.Year; - mg = dt.Month; - dg = dt.Day; - } - - /*=================================GetAbsoluteDateUmAlQura========================== - **Action: Gets the Absolute date for the given UmAlQura date. The absolute date means - ** the number of days from January 1st, 1 A.D. - **Returns: - **Arguments: - **Exceptions: - ============================================================================*/ - private static long GetAbsoluteDateUmAlQura(int year, int month, int day) - { - //Caller should check the validaty of year, month and day. - - int yg = 0, mg = 0, dg = 0; - ConvertHijriToGregorian(year, month, day, ref yg, ref mg, ref dg); - return GregorianCalendar.GetAbsoluteDate(yg, mg, dg); - } - - internal static void CheckTicksRange(long ticks) - { - if (ticks < minDate.Ticks || ticks > maxDate.Ticks) - { - throw new ArgumentOutOfRangeException( - "time", - String.Format( - CultureInfo.InvariantCulture, - SR.ArgumentOutOfRange_CalendarRange, - minDate, - maxDate)); - } - } - - internal static void CheckEraRange(int era) - { - if (era != CurrentEra && era != UmAlQuraEra) - { - throw new ArgumentOutOfRangeException(nameof(era), SR.ArgumentOutOfRange_InvalidEraValue); - } - } - - internal static void CheckYearRange(int year, int era) - { - CheckEraRange(era); - if (year < MinCalendarYear || year > MaxCalendarYear) - { - throw new ArgumentOutOfRangeException( - nameof(year), - String.Format( - CultureInfo.CurrentCulture, - SR.ArgumentOutOfRange_Range, - MinCalendarYear, - MaxCalendarYear)); - } - } - - internal static void CheckYearMonthRange(int year, int month, int era) - { - CheckYearRange(year, era); - if (month < 1 || month > 12) - { - throw new ArgumentOutOfRangeException(nameof(month), SR.ArgumentOutOfRange_Month); - } - } - - /*========================ConvertGregorianToHijri============================ - ** Purpose: convert DateTime to Hdate(year,month,day) - ** Arguments: - ** Input: DateTime - ** Output: Hijrah date: year:yh, month:mh, day:dh - ============================================================================*/ - private static void ConvertGregorianToHijri(DateTime time, ref int HijriYear, ref int HijriMonth, ref int HijriDay) - { - int index, b, DaysPerThisMonth; - double nDays; - TimeSpan ts; - int yh1 = 0, mh1 = 0, dh1 = 0; - - Debug.Assert((time.Ticks >= minDate.Ticks) && (time.Ticks <= maxDate.Ticks), "Gregorian date is out of range."); - - // Find the index where we should start our search by quessing the Hijri year that we will be in HijriYearInfo. - // A Hijri year is 354 or 355 days. Use 355 days so that we will search from a lower index. - - index = (int)((time.Ticks - minDate.Ticks) / Calendar.TicksPerDay) / 355; - do - { - } while (time.CompareTo(s_hijriYearInfo[++index].GregorianDate) > 0); //while greater - - if (time.CompareTo(s_hijriYearInfo[index].GregorianDate) != 0) - { - index--; - } - - ts = time.Subtract(s_hijriYearInfo[index].GregorianDate); - yh1 = index + MinCalendarYear; - - mh1 = 1; - dh1 = 1; - nDays = ts.TotalDays; - b = s_hijriYearInfo[index].HijriMonthsLengthFlags; - DaysPerThisMonth = 29 + (b & 1); - - while (nDays >= DaysPerThisMonth) - { - nDays -= DaysPerThisMonth; - b = b >> 1; - DaysPerThisMonth = 29 + (b & 1); - mh1++; - } - dh1 += (int)nDays; - - HijriDay = dh1; - HijriMonth = mh1; - HijriYear = yh1; - } - - /*=================================GetDatePart========================== - **Action: Returns a given date part of this DateTime. This method is used - ** to compute the year, day-of-year, month, or day part. - **Returns: - **Arguments: - **Exceptions: ArgumentException if part is incorrect. - **Notes: - ** First, we get the absolute date (the number of days from January 1st, 1 A.C) for the given ticks. - ** Use the formula (((AbsoluteDate - 226894) * 33) / (33 * 365 + 8)) + 1, we can a rough value for the UmAlQura year. - ** In order to get the exact UmAlQura year, we compare the exact absolute date for UmAlQuraYear and (UmAlQuraYear + 1). - ** From here, we can get the correct UmAlQura year. - ============================================================================*/ - - internal virtual int GetDatePart(DateTime time, int part) - { - int UmAlQuraYear = 0; // UmAlQura year - int UmAlQuraMonth = 0; // UmAlQura month - int UmAlQuraDay = 0; // UmAlQura day - long ticks = time.Ticks; - CheckTicksRange(ticks); - - ConvertGregorianToHijri(time, ref UmAlQuraYear, ref UmAlQuraMonth, ref UmAlQuraDay); - - if (part == DatePartYear) - return (UmAlQuraYear); - - if (part == DatePartMonth) - return (UmAlQuraMonth); - - if (part == DatePartDay) - return (UmAlQuraDay); - - if (part == DatePartDayOfYear) - return (int)(GetAbsoluteDateUmAlQura(UmAlQuraYear, UmAlQuraMonth, UmAlQuraDay) - GetAbsoluteDateUmAlQura(UmAlQuraYear, 1, 1) + 1); - - // Incorrect part value. - throw new InvalidOperationException(SR.InvalidOperation_DateTimeParsing); - } - - // Returns the DateTime resulting from adding the given number of - // months to the specified DateTime. The result is computed by incrementing - // (or decrementing) the year and month parts of the specified DateTime by - // value months, and, if required, adjusting the day part of the - // resulting date downwards to the last day of the resulting month in the - // resulting year. The time-of-day part of the result is the same as the - // time-of-day part of the specified DateTime. - // - // In more precise terms, considering the specified DateTime to be of the - // form y / m / d + t, where y is the - // year, m is the month, d is the day, and t is the - // time-of-day, the result is y1 / m1 / d1 + t, - // where y1 and m1 are computed by adding value months - // to y and m, and d1 is the largest value less than - // or equal to d that denotes a valid day in month m1 of year - // y1. - // - - - public override DateTime AddMonths(DateTime time, int months) - { - if (months < -120000 || months > 120000) - { - throw new ArgumentOutOfRangeException( - nameof(months), - String.Format( - CultureInfo.CurrentCulture, - SR.ArgumentOutOfRange_Range, - -120000, - 120000)); - } - Contract.EndContractBlock(); - // Get the date in UmAlQura calendar. - int y = GetDatePart(time, DatePartYear); - int m = GetDatePart(time, DatePartMonth); - int d = GetDatePart(time, DatePartDay); - int i = m - 1 + months; - - if (i >= 0) - { - m = i % 12 + 1; - y = y + i / 12; - } - else - { - m = 12 + (i + 1) % 12; - y = y + (i - 11) / 12; - } - - if (d > 29) - { - int days = GetDaysInMonth(y, m); - if (d > days) - { - d = days; - } - } - CheckYearRange(y, UmAlQuraEra); - DateTime dt = new DateTime(GetAbsoluteDateUmAlQura(y, m, d) * TicksPerDay + time.Ticks % TicksPerDay); - Calendar.CheckAddResult(dt.Ticks, MinSupportedDateTime, MaxSupportedDateTime); - return (dt); - } - - // Returns the DateTime resulting from adding the given number of - // years to the specified DateTime. The result is computed by incrementing - // (or decrementing) the year part of the specified DateTime by value - // years. If the month and day of the specified DateTime is 2/29, and if the - // resulting year is not a leap year, the month and day of the resulting - // DateTime becomes 2/28. Otherwise, the month, day, and time-of-day - // parts of the result are the same as those of the specified DateTime. - // - - - public override DateTime AddYears(DateTime time, int years) - { - return (AddMonths(time, years * 12)); - } - - // Returns the day-of-month part of the specified DateTime. The returned - // value is an integer between 1 and 31. - // - - - public override int GetDayOfMonth(DateTime time) - { - return (GetDatePart(time, DatePartDay)); - } - - // Returns the day-of-week part of the specified DateTime. The returned value - // is an integer between 0 and 6, where 0 indicates Sunday, 1 indicates - // Monday, 2 indicates Tuesday, 3 indicates Wednesday, 4 indicates - // Thursday, 5 indicates Friday, and 6 indicates Saturday. - // - - - public override DayOfWeek GetDayOfWeek(DateTime time) - { - return ((DayOfWeek)((int)(time.Ticks / TicksPerDay + 1) % 7)); - } - - // Returns the day-of-year part of the specified DateTime. The returned value - // is an integer between 1 and 354 or 355. - // - - - public override int GetDayOfYear(DateTime time) - { - return (GetDatePart(time, DatePartDayOfYear)); - } - - /* - internal bool CouldBeLeapYear(int year) - { - return ((((year * 11) + 14) % 30) < 11); - } - */ - - // Returns the number of days in the month given by the year and - // month arguments. - // - - - public override int GetDaysInMonth(int year, int month, int era) - { - CheckYearMonthRange(year, month, era); - - if ((s_hijriYearInfo[year - MinCalendarYear].HijriMonthsLengthFlags & (1 << month - 1)) == 0) - return 29; - else - return 30; - } - - internal static int RealGetDaysInYear(int year) - { - int days = 0, b; - - Debug.Assert((year >= MinCalendarYear) && (year <= MaxCalendarYear), "Hijri year is out of range."); - - b = s_hijriYearInfo[year - MinCalendarYear].HijriMonthsLengthFlags; - - for (int m = 1; m <= 12; m++) - { - days = days + 29 + (b & 1); /* Add the months lengths before mh */ - b = b >> 1; - } - Debug.Assert((days == 354) || (days == 355), "Hijri year has to be 354 or 355 days."); - return days; - } - - // Returns the number of days in the year given by the year argument for the current era. - // - - - public override int GetDaysInYear(int year, int era) - { - CheckYearRange(year, era); - return (RealGetDaysInYear(year)); - } - - // Returns the era for the specified DateTime value. - - - public override int GetEra(DateTime time) - { - CheckTicksRange(time.Ticks); - return (UmAlQuraEra); - } - - - - public override int[] Eras - { - get - { - return (new int[] { UmAlQuraEra }); - } - } - - // Returns the month part of the specified DateTime. The returned value is an - // integer between 1 and 12. - // - - - public override int GetMonth(DateTime time) - { - return (GetDatePart(time, DatePartMonth)); - } - - // Returns the number of months in the specified year and era. - - - public override int GetMonthsInYear(int year, int era) - { - CheckYearRange(year, era); - return (12); - } - - // Returns the year part of the specified DateTime. The returned value is an - // integer between MinCalendarYear and MaxCalendarYear. - // - - - public override int GetYear(DateTime time) - { - return (GetDatePart(time, DatePartYear)); - } - - // Checks whether a given day in the specified era is a leap day. This method returns true if - // the date is a leap day, or false if not. - // - - - public override bool IsLeapDay(int year, int month, int day, int era) - { - if (day >= 1 && day <= 29) - { - CheckYearMonthRange(year, month, era); - return (false); - } - - // The year/month/era value checking is done in GetDaysInMonth(). - int daysInMonth = GetDaysInMonth(year, month, era); - if (day < 1 || day > daysInMonth) - { - throw new ArgumentOutOfRangeException( - nameof(day), - String.Format( - CultureInfo.CurrentCulture, - SR.ArgumentOutOfRange_Day, - daysInMonth, - month)); - } - return (false); - } - - // Returns the leap month in a calendar year of the specified era. This method returns 0 - // if this calendar does not have leap month, or this year is not a leap year. - // - - - public override int GetLeapMonth(int year, int era) - { - CheckYearRange(year, era); - return (0); - } - - // Checks whether a given month in the specified era is a leap month. This method returns true if - // month is a leap month, or false if not. - // - - - public override bool IsLeapMonth(int year, int month, int era) - { - CheckYearMonthRange(year, month, era); - return (false); - } - - // Checks whether a given year in the specified era is a leap year. This method returns true if - // year is a leap year, or false if not. - // - - - public override bool IsLeapYear(int year, int era) - { - CheckYearRange(year, era); - if (RealGetDaysInYear(year) == 355) - return true; - else - return false; - } - - // Returns the date and time converted to a DateTime value. Throws an exception if the n-tuple is invalid. - // - - - public override DateTime ToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era) - { - if (day >= 1 && day <= 29) - { - CheckYearMonthRange(year, month, era); - goto DayInRang; - } - - // The year/month/era value checking is done in GetDaysInMonth(). - int daysInMonth = GetDaysInMonth(year, month, era); - - if (day < 1 || day > daysInMonth) - { - throw new ArgumentOutOfRangeException( - nameof(day), - String.Format( - CultureInfo.CurrentCulture, - SR.ArgumentOutOfRange_Day, - daysInMonth, - month)); - } - DayInRang: - long lDate = GetAbsoluteDateUmAlQura(year, month, day); - - if (lDate >= 0) - { - return (new DateTime(lDate * GregorianCalendar.TicksPerDay + TimeToTicks(hour, minute, second, millisecond))); - } - else - { - throw new ArgumentOutOfRangeException(null, SR.ArgumentOutOfRange_BadYearMonthDay); - } - } - - private const int DEFAULT_TWO_DIGIT_YEAR_MAX = 1451; - - - - public override int TwoDigitYearMax - { - get - { - if (twoDigitYearMax == -1) - { - twoDigitYearMax = GetSystemTwoDigitYearSetting(ID, DEFAULT_TWO_DIGIT_YEAR_MAX); - } - return (twoDigitYearMax); - } - - set - { - if (value != 99 && (value < MinCalendarYear || value > MaxCalendarYear)) - { - throw new ArgumentOutOfRangeException( - nameof(value), - String.Format( - CultureInfo.CurrentCulture, - SR.ArgumentOutOfRange_Range, - MinCalendarYear, - MaxCalendarYear)); - } - Contract.EndContractBlock(); - VerifyWritable(); - // We allow year 99 to be set so that one can make ToFourDigitYearMax a no-op by setting TwoDigitYearMax to 99. - twoDigitYearMax = value; - } - } - - - - public override int ToFourDigitYear(int year) - { - if (year < 0) - { - throw new ArgumentOutOfRangeException(nameof(year), - SR.ArgumentOutOfRange_NeedNonNegNum); - } - Contract.EndContractBlock(); - - if (year < 100) - { - return (base.ToFourDigitYear(year)); - } - - if ((year < MinCalendarYear) || (year > MaxCalendarYear)) - { - throw new ArgumentOutOfRangeException( - nameof(year), - String.Format( - CultureInfo.CurrentCulture, - SR.ArgumentOutOfRange_Range, - MinCalendarYear, - MaxCalendarYear)); - } - return (year); - } - } -} - diff --git a/src/mscorlib/corefx/System/Globalization/UnicodeCategory.cs b/src/mscorlib/corefx/System/Globalization/UnicodeCategory.cs deleted file mode 100644 index 1c5e6bc..0000000 --- a/src/mscorlib/corefx/System/Globalization/UnicodeCategory.cs +++ /dev/null @@ -1,70 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -namespace System.Globalization -{ - [Serializable] - public enum UnicodeCategory - { - UppercaseLetter = 0, - - LowercaseLetter = 1, - - TitlecaseLetter = 2, - - ModifierLetter = 3, - - OtherLetter = 4, - - NonSpacingMark = 5, - - SpacingCombiningMark = 6, - - EnclosingMark = 7, - - DecimalDigitNumber = 8, - - LetterNumber = 9, - - OtherNumber = 10, - - SpaceSeparator = 11, - - LineSeparator = 12, - - ParagraphSeparator = 13, - - Control = 14, - - Format = 15, - - Surrogate = 16, - - PrivateUse = 17, - - ConnectorPunctuation = 18, - - DashPunctuation = 19, - - OpenPunctuation = 20, - - ClosePunctuation = 21, - - InitialQuotePunctuation = 22, - - FinalQuotePunctuation = 23, - - OtherPunctuation = 24, - - MathSymbol = 25, - - CurrencySymbol = 26, - - ModifierSymbol = 27, - - OtherSymbol = 28, - - OtherNotAssigned = 29, - } -} diff --git a/src/mscorlib/src/System/Globalization/Calendar.cs b/src/mscorlib/src/System/Globalization/Calendar.cs index 9a3d8c4..8d10353 100644 --- a/src/mscorlib/src/System/Globalization/Calendar.cs +++ b/src/mscorlib/src/System/Globalization/Calendar.cs @@ -2,12 +2,9 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System; -using System.Runtime.CompilerServices; -using System.Globalization; -using System.Runtime.Versioning; using System.Diagnostics; using System.Diagnostics.Contracts; +using System.Runtime.Serialization; namespace System.Globalization { @@ -32,7 +29,7 @@ namespace System.Globalization // since most of the calendars (or all?) have the same way of calcuating hour/minute/second. [Serializable] - public abstract class Calendar : ICloneable + public abstract partial class Calendar : ICloneable { // Number of 100ns (10E-7 second) ticks per time unit internal const long TicksPerMillisecond = 10000; @@ -61,39 +58,20 @@ namespace System.Globalization internal const long MaxMillis = (long)DaysTo10000 * MillisPerDay; - // - // Calendar ID Values. This is used to get data from calendar.nlp. - // The order of calendar ID means the order of data items in the table. - // - - internal const int CAL_GREGORIAN = 1; // Gregorian (localized) calendar - internal const int CAL_GREGORIAN_US = 2; // Gregorian (U.S.) calendar - internal const int CAL_JAPAN = 3; // Japanese Emperor Era calendar - internal const int CAL_TAIWAN = 4; // Taiwan Era calendar - internal const int CAL_KOREA = 5; // Korean Tangun Era calendar - internal const int CAL_HIJRI = 6; // Hijri (Arabic Lunar) calendar - internal const int CAL_THAI = 7; // Thai calendar - internal const int CAL_HEBREW = 8; // Hebrew (Lunar) calendar - internal const int CAL_GREGORIAN_ME_FRENCH = 9; // Gregorian Middle East French calendar - internal const int CAL_GREGORIAN_ARABIC = 10; // Gregorian Arabic calendar - internal const int CAL_GREGORIAN_XLIT_ENGLISH = 11; // Gregorian Transliterated English calendar - internal const int CAL_GREGORIAN_XLIT_FRENCH = 12; - internal const int CAL_JULIAN = 13; - internal const int CAL_JAPANESELUNISOLAR = 14; - internal const int CAL_CHINESELUNISOLAR = 15; - internal const int CAL_SAKA = 16; // reserved to match Office but not implemented in our code - internal const int CAL_LUNAR_ETO_CHN = 17; // reserved to match Office but not implemented in our code - internal const int CAL_LUNAR_ETO_KOR = 18; // reserved to match Office but not implemented in our code - internal const int CAL_LUNAR_ETO_ROKUYOU = 19; // reserved to match Office but not implemented in our code - internal const int CAL_KOREANLUNISOLAR = 20; - internal const int CAL_TAIWANLUNISOLAR = 21; - internal const int CAL_PERSIAN = 22; - internal const int CAL_UMALQURA = 23; - - internal int m_currentEraValue = -1; - - [System.Runtime.Serialization.OptionalField(VersionAdded = 2)] - private bool m_isReadOnly = false; + private int _currentEraValue = -1; + + [OptionalField(VersionAdded = 2)] + private bool _isReadOnly = false; + +#if CORECLR + internal const CalendarId CAL_HEBREW = CalendarId.HEBREW; + internal const CalendarId CAL_HIJRI = CalendarId.HIJRI; + internal const CalendarId CAL_JAPAN = CalendarId.JAPAN; + internal const CalendarId CAL_JULIAN = CalendarId.JULIAN; + internal const CalendarId CAL_TAIWAN = CalendarId.TAIWAN; + internal const CalendarId CAL_UMALQURA = CalendarId.UMALQURA; + internal const CalendarId CAL_PERSIAN = CalendarId.PERSIAN; +#endif // The minimum supported DateTime range for the calendar. @@ -115,8 +93,13 @@ namespace System.Globalization } } - - + public virtual CalendarAlgorithmType AlgorithmType + { + get + { + return CalendarAlgorithmType.Unknown; + } + } protected Calendar() { @@ -126,11 +109,11 @@ namespace System.Globalization /// // This can not be abstract, otherwise no one can create a subclass of Calendar. // - internal virtual int ID + internal virtual CalendarId ID { get { - return (-1); + return CalendarId.UNINITIALIZED_VALUE; } } @@ -138,21 +121,11 @@ namespace System.Globalization // Return the Base calendar ID for calendars that didn't have defined data in calendarData // - internal virtual int BaseCalendarID + internal virtual CalendarId BaseCalendarID { get { return ID; } } - // Returns the type of the calendar. - // - public virtual CalendarAlgorithmType AlgorithmType - { - get - { - return CalendarAlgorithmType.Unknown; - } - } - //////////////////////////////////////////////////////////////////////// // // IsReadOnly @@ -162,7 +135,7 @@ namespace System.Globalization //////////////////////////////////////////////////////////////////////// public bool IsReadOnly { - get { return (m_isReadOnly); } + get { return (_isReadOnly); } } //////////////////////////////////////////////////////////////////////// @@ -172,7 +145,7 @@ namespace System.Globalization // Is the implementation of ICloneable. // //////////////////////////////////////////////////////////////////////// - public virtual Object Clone() + public virtual object Clone() { object o = MemberwiseClone(); ((Calendar)o).SetReadOnlyState(false); @@ -201,15 +174,15 @@ namespace System.Globalization internal void VerifyWritable() { - if (m_isReadOnly) + if (_isReadOnly) { - throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly")); + throw new InvalidOperationException(SR.InvalidOperation_ReadOnly); } } internal void SetReadOnlyState(bool readOnly) { - m_isReadOnly = readOnly; + _isReadOnly = readOnly; } @@ -227,12 +200,12 @@ namespace System.Globalization get { // The following code assumes that the current era value can not be -1. - if (m_currentEraValue == -1) + if (_currentEraValue == -1) { - Debug.Assert(BaseCalendarID > 0, "[Calendar.CurrentEraValue] Expected ID > 0"); - m_currentEraValue = CalendarData.GetCalendarData(BaseCalendarID).iCurrentEra; + Debug.Assert(BaseCalendarID != CalendarId.UNINITIALIZED_VALUE, "[Calendar.CurrentEraValue] Expected a real calendar ID"); + _currentEraValue = CalendarData.GetCalendarData(BaseCalendarID).iCurrentEra; } - return (m_currentEraValue); + return (_currentEraValue); } } @@ -247,8 +220,8 @@ namespace System.Globalization if (ticks < minValue.Ticks || ticks > maxValue.Ticks) { throw new ArgumentException( - String.Format(CultureInfo.InvariantCulture, Environment.GetResourceString("Argument_ResultCalendarRange"), - minValue, maxValue)); + String.Format(CultureInfo.InvariantCulture, SR.Format(SR.Argument_ResultCalendarRange, + minValue, maxValue))); } Contract.EndContractBlock(); } @@ -265,7 +238,7 @@ namespace System.Globalization double tempMillis = (value * scale + (value >= 0 ? 0.5 : -0.5)); if (!((tempMillis > -(double)MaxMillis) && (tempMillis < (double)MaxMillis))) { - throw new ArgumentOutOfRangeException(nameof(value), Environment.GetResourceString("ArgumentOutOfRange_AddValue")); + throw new ArgumentOutOfRangeException(nameof(value), SR.ArgumentOutOfRange_AddValue); } long millis = (long)tempMillis; @@ -669,7 +642,7 @@ namespace System.Globalization if ((int)firstDayOfWeek < 0 || (int)firstDayOfWeek > 6) { throw new ArgumentOutOfRangeException( - nameof(firstDayOfWeek), Environment.GetResourceString("ArgumentOutOfRange_Range", + nameof(firstDayOfWeek), SR.Format(SR.ArgumentOutOfRange_Range, DayOfWeek.Sunday, DayOfWeek.Saturday)); } Contract.EndContractBlock(); @@ -683,7 +656,7 @@ namespace System.Globalization return (GetWeekOfYearFullDays(time, (int)firstDayOfWeek, 4)); } throw new ArgumentOutOfRangeException( - nameof(rule), Environment.GetResourceString("ArgumentOutOfRange_Range", + nameof(rule), SR.Format(SR.ArgumentOutOfRange_Range, CalendarWeekRule.FirstDay, CalendarWeekRule.FirstFourDayWeek)); } @@ -840,7 +813,7 @@ namespace System.Globalization if (year < 0) { throw new ArgumentOutOfRangeException(nameof(year), - Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + SR.ArgumentOutOfRange_NeedNonNegNum); } Contract.EndContractBlock(); if (year < 100) @@ -864,17 +837,17 @@ namespace System.Globalization nameof(millisecond), String.Format( CultureInfo.InvariantCulture, - Environment.GetResourceString("ArgumentOutOfRange_Range"), 0, MillisPerSecond - 1)); + SR.Format(SR.ArgumentOutOfRange_Range, 0, MillisPerSecond - 1))); } - return TimeSpan.TimeToTicks(hour, minute, second) + millisecond * TicksPerMillisecond; + return InternalGloablizationHelper.TimeToTicks(hour, minute, second) + millisecond * TicksPerMillisecond; } - throw new ArgumentOutOfRangeException(null, Environment.GetResourceString("ArgumentOutOfRange_BadHourMinuteSecond")); + throw new ArgumentOutOfRangeException(null, SR.ArgumentOutOfRange_BadHourMinuteSecond); } - internal static int GetSystemTwoDigitYearSetting(int CalID, int defaultYearValue) + internal static int GetSystemTwoDigitYearSetting(CalendarId CalID, int defaultYearValue) { // Call nativeGetTwoDigitYearMax - int twoDigitYearMax = CalendarData.nativeGetTwoDigitYearMax(CalID); + int twoDigitYearMax = CalendarData.GetTwoDigitYearMax(CalID); if (twoDigitYearMax < 0) { twoDigitYearMax = defaultYearValue; diff --git a/src/mscorlib/src/System/Globalization/CalendarAlgorithmType.cs b/src/mscorlib/src/System/Globalization/CalendarAlgorithmType.cs index 9c09c58..159b0e6 100644 --- a/src/mscorlib/src/System/Globalization/CalendarAlgorithmType.cs +++ b/src/mscorlib/src/System/Globalization/CalendarAlgorithmType.cs @@ -16,6 +16,5 @@ namespace System.Globalization LunisolarCalendar = 3 // Lunisolar-based calendar which use leap month rule, such as HebrewCalendar and Asian Lunisolar calendars. // Lunisolar calendars are based on the cycle of the moon, but consider the seasons as a secondary consideration, // so they align with the seasons as well as lunar events. - } } diff --git a/src/mscorlib/corefx/System/Globalization/CalendarData.Unix.cs b/src/mscorlib/src/System/Globalization/CalendarData.Unix.cs similarity index 100% rename from src/mscorlib/corefx/System/Globalization/CalendarData.Unix.cs rename to src/mscorlib/src/System/Globalization/CalendarData.Unix.cs diff --git a/src/mscorlib/corefx/System/Globalization/CalendarData.Windows.cs b/src/mscorlib/src/System/Globalization/CalendarData.Windows.cs similarity index 91% rename from src/mscorlib/corefx/System/Globalization/CalendarData.Windows.cs rename to src/mscorlib/src/System/Globalization/CalendarData.Windows.cs index bdf3ff1..4565dff 100644 --- a/src/mscorlib/corefx/System/Globalization/CalendarData.Windows.cs +++ b/src/mscorlib/src/System/Globalization/CalendarData.Windows.cs @@ -10,6 +10,14 @@ using System.Collections.Generic; namespace System.Globalization { +#if CORECLR + using IntList = List; + using StringList = List; +#else + using IntList = LowLevelList; + using StringList = LowLevelList; +#endif + internal partial class CalendarData { private bool LoadCalendarDataFromSystem(String localeName, CalendarId calendarId) @@ -123,13 +131,13 @@ namespace System.Globalization { EnumCalendarsData data = new EnumCalendarsData(); data.userOverride = 0; - data.calendars = new LowLevelList(); + data.calendars = new IntList(); // First call GetLocaleInfo if necessary if (useUserOverride) { // They want user overrides, see if the user calendar matches the input calendar - int userCalendar = Interop.mincore.GetLocaleInfoExInt(localeName, LOCALE_ICALENDARTYPE); + int userCalendar = CultureData.GetLocaleInfoExInt(localeName, LOCALE_ICALENDARTYPE); // If we got a default, then use it as the first calendar if (userCalendar != 0) @@ -143,8 +151,12 @@ namespace System.Globalization try { // Now call the enumeration API. Work is done by our callback function +#if CORECLR + Interop.Kernel32.EnumCalendarInfoExEx(EnumCalendarsCallback, localeName, ENUM_ALL_CALENDARS, null, CAL_ICALINTVALUE, (IntPtr)contextHandle); +#else IntPtr callback = AddrofIntrinsics.AddrOf>(EnumCalendarsCallback); - Interop.mincore.EnumCalendarInfoExEx(callback, localeName, ENUM_ALL_CALENDARS, null, CAL_ICALINTVALUE, (IntPtr)contextHandle); + Interop.Kernel32.EnumCalendarInfoExEx(callback, localeName, ENUM_ALL_CALENDARS, null, CAL_ICALINTVALUE, (IntPtr)contextHandle); +#endif } finally { @@ -244,7 +256,7 @@ namespace System.Globalization private static bool CallGetCalendarInfoEx(string localeName, CalendarId calendar, uint calType, out int data) { - return (Interop.mincore.GetCalendarInfoEx(localeName, (uint)calendar, IntPtr.Zero, calType | CAL_RETURN_NUMBER, IntPtr.Zero, 0, out data) != 0); + return (Interop.Kernel32.GetCalendarInfoEx(localeName, (uint)calendar, IntPtr.Zero, calType | CAL_RETURN_NUMBER, IntPtr.Zero, 0, out data) != 0); } private static unsafe bool CallGetCalendarInfoEx(string localeName, CalendarId calendar, uint calType, out string data) @@ -254,7 +266,7 @@ namespace System.Globalization // The maximum size for values returned from GetCalendarInfoEx is 80 characters. char* buffer = stackalloc char[BUFFER_LENGTH]; - int ret = Interop.mincore.GetCalendarInfoEx(localeName, (uint)calendar, IntPtr.Zero, calType, (IntPtr)buffer, BUFFER_LENGTH, IntPtr.Zero); + int ret = Interop.Kernel32.GetCalendarInfoEx(localeName, (uint)calendar, IntPtr.Zero, calType, (IntPtr)buffer, BUFFER_LENGTH, IntPtr.Zero); if (ret > 0) { if (buffer[ret - 1] == '\0') @@ -272,11 +284,13 @@ namespace System.Globalization private class EnumData { public string userOverride; - public LowLevelList strings; + public StringList strings; } // EnumCalendarInfoExEx callback itself. +#if !CORECLR [NativeCallable(CallingConvention = CallingConvention.StdCall)] +#endif private static unsafe Interop.BOOL EnumCalendarInfoCallback(IntPtr lpCalendarInfoString, uint calendar, IntPtr pReserved, IntPtr lParam) { EnumData context = (EnumData)((GCHandle)lParam).Target; @@ -300,8 +314,7 @@ namespace System.Globalization { EnumData context = new EnumData(); context.userOverride = null; - context.strings = new LowLevelList(); - + context.strings = new StringList(); // First call GetLocaleInfo if necessary if (((lcType != 0) && ((lcType & CAL_NOUSEROVERRIDE) == 0)) && // Get user locale, see if it matches localeName. @@ -309,13 +322,13 @@ namespace System.Globalization GetUserDefaultLocaleName() == localeName) { // They want user overrides, see if the user calendar matches the input calendar - CalendarId userCalendar = (CalendarId)Interop.mincore.GetLocaleInfoExInt(localeName, LOCALE_ICALENDARTYPE); + CalendarId userCalendar = (CalendarId)CultureData.GetLocaleInfoExInt(localeName, LOCALE_ICALENDARTYPE); // If the calendars were the same, see if the locales were the same if (userCalendar == calendar) { // They matched, get the user override since locale & calendar match - string res = Interop.mincore.GetLocaleInfoEx(localeName, lcType); + string res = CultureData.GetLocaleInfoEx(localeName, lcType); // if it succeeded remember the override for the later callers if (res != "") @@ -332,9 +345,13 @@ namespace System.Globalization GCHandle contextHandle = GCHandle.Alloc(context); try { +#if CORECLR + Interop.Kernel32.EnumCalendarInfoExEx(EnumCalendarInfoCallback, localeName, (uint)calendar, null, calType, (IntPtr)contextHandle); +#else // Now call the enumeration API. Work is done by our callback function IntPtr callback = AddrofIntrinsics.AddrOf>(EnumCalendarInfoCallback); - Interop.mincore.EnumCalendarInfoExEx(callback, localeName, (uint)calendar, null, calType, (IntPtr)contextHandle); + Interop.Kernel32.EnumCalendarInfoExEx(callback, localeName, (uint)calendar, null, calType, (IntPtr)contextHandle); +#endif // CORECLR } finally { @@ -432,10 +449,12 @@ namespace System.Globalization private class EnumCalendarsData { public int userOverride; // user override value (if found) - public LowLevelList calendars; // list of calendars found so far + public IntList calendars; // list of calendars found so far } +#if !CORECLR [NativeCallable(CallingConvention = CallingConvention.StdCall)] +#endif private static Interop.BOOL EnumCalendarsCallback(IntPtr lpCalendarInfoString, uint calendar, IntPtr reserved, IntPtr lParam) { EnumCalendarsData context = (EnumCalendarsData)((GCHandle)lParam).Target; @@ -461,7 +480,7 @@ namespace System.Globalization int result; char* localeName = stackalloc char[LOCALE_NAME_MAX_LENGTH]; - result = Interop.mincore.GetLocaleInfoEx(LOCALE_NAME_USER_DEFAULT, LOCALE_SNAME, localeName, LOCALE_NAME_MAX_LENGTH); + result = CultureData.GetLocaleInfoEx(LOCALE_NAME_USER_DEFAULT, LOCALE_SNAME, localeName, LOCALE_NAME_MAX_LENGTH); return result <= 0 ? "" : new String(localeName, 0, result - 1); // exclude the null termination } diff --git a/src/mscorlib/src/System/Globalization/CalendarData.cs b/src/mscorlib/src/System/Globalization/CalendarData.cs index b683db1..3a1e827 100644 --- a/src/mscorlib/src/System/Globalization/CalendarData.cs +++ b/src/mscorlib/src/System/Globalization/CalendarData.cs @@ -2,34 +2,18 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. - -using System; -using System.Runtime.InteropServices; -using System.Runtime.CompilerServices; -using System.Runtime.Versioning; using System.Diagnostics; -using System.Diagnostics.Contracts; namespace System.Globalization { - // // List of calendar data // Note the we cache overrides. // Note that localized names (resource names) aren't available from here. // // NOTE: Calendars depend on the locale name that creates it. Only a few - // properties are available without locales using CalendarData.GetCalendar(int) + // properties are available without locales using CalendarData.GetCalendar(CalendarData) - // StructLayout is needed here otherwise compiler can re-arrange the fields. - // We have to keep this in-sync with the definition in calendardata.h - // - // WARNING WARNING WARNING - // - // WARNING: Anything changed here also needs to be updated on the native side (object.h see type CalendarDataBaseObject) - // WARNING: The type loader will rearrange class member offsets so the mscorwks!CalendarDataBaseObject - // WARNING: must be manually structured to match the true loaded class layout - // - internal class CalendarData + internal partial class CalendarData { // Max calendars internal const int MAX_CALENDARS = 23; @@ -110,18 +94,16 @@ namespace System.Globalization return invariant; } - - // // Get a bunch of data for a calendar // - internal CalendarData(String localeName, int calendarId, bool bUseUserOverrides) + internal CalendarData(String localeName, CalendarId calendarId, bool bUseUserOverrides) { - // Call nativeGetCalendarData to populate the data this.bUseUserOverrides = bUseUserOverrides; - if (!nativeGetCalendarData(this, localeName, calendarId)) + + if (!LoadCalendarDataFromSystem(localeName, calendarId)) { - Debug.Assert(false, "[CalendarData] nativeGetCalendarData call isn't expected to fail for calendar " + calendarId + " locale " + localeName); + Debug.Assert(false, "[CalendarData] LoadCalendarDataFromSystem call isn't expected to fail for calendar " + calendarId + " locale " + localeName); // Something failed, try invariant for missing parts // This is really not good, but we don't want the callers to crash. @@ -145,15 +127,9 @@ namespace System.Globalization // Genitive and Leap names can follow the fallback below } - // Clean up the escaping of the formats - this.saShortDates = CultureData.ReescapeWin32Strings(this.saShortDates); - this.saLongDates = CultureData.ReescapeWin32Strings(this.saLongDates); - this.saYearMonths = CultureData.ReescapeWin32Strings(this.saYearMonths); - this.sMonthDay = CultureData.ReescapeWin32String(this.sMonthDay); - - if ((CalendarId)calendarId == CalendarId.TAIWAN) + if (calendarId == CalendarId.TAIWAN) { - if (CultureInfo.IsTaiwanSku) + if (SystemSupportsTaiwaneseCalendar()) { // We got the month/day names from the OS (same as gregorian), but the native name is wrong this.sNativeName = "\x4e2d\x83ef\x6c11\x570b\x66c6"; @@ -165,11 +141,11 @@ namespace System.Globalization } // Check for null genitive names (in case unmanaged side skips it for non-gregorian calendars, etc) - if (this.saMonthGenitiveNames == null || String.IsNullOrEmpty(this.saMonthGenitiveNames[0])) + if (this.saMonthGenitiveNames == null || this.saMonthGenitiveNames.Length == 0 || String.IsNullOrEmpty(this.saMonthGenitiveNames[0])) this.saMonthGenitiveNames = this.saMonthNames; // Genitive month names (same as month names for invariant) - if (this.saAbbrevMonthGenitiveNames == null || String.IsNullOrEmpty(this.saAbbrevMonthGenitiveNames[0])) + if (this.saAbbrevMonthGenitiveNames == null || this.saAbbrevMonthGenitiveNames.Length == 0 || String.IsNullOrEmpty(this.saAbbrevMonthGenitiveNames[0])) this.saAbbrevMonthGenitiveNames = this.saAbbrevMonthNames; // Abbreviated genitive month names (same as abbrev month names for invariant) - if (this.saLeapYearMonthNames == null || String.IsNullOrEmpty(this.saLeapYearMonthNames[0])) + if (this.saLeapYearMonthNames == null || this.saLeapYearMonthNames.Length == 0 || String.IsNullOrEmpty(this.saLeapYearMonthNames[0])) this.saLeapYearMonthNames = this.saMonthNames; InitializeEraNames(localeName, calendarId); @@ -177,7 +153,7 @@ namespace System.Globalization InitializeAbbreviatedEraNames(localeName, calendarId); // Abbreviated English Era Names are only used for the Japanese calendar. - if (calendarId == (int)CalendarId.JAPAN) + if (calendarId == CalendarId.JAPAN) { this.saAbbrevEnglishEraNames = JapaneseCalendar.EnglishEraNames(); } @@ -192,10 +168,10 @@ namespace System.Globalization this.iCurrentEra = this.saEraNames.Length; } - private void InitializeEraNames(string localeName, int calendarId) + private void InitializeEraNames(string localeName, CalendarId calendarId) { // Note that the saEraNames only include "A.D." We don't have localized names for other calendars available from windows - switch ((CalendarId)calendarId) + switch (calendarId) { // For Localized Gregorian we really expect the data from the OS. case CalendarId.GREGORIAN: @@ -238,7 +214,7 @@ namespace System.Globalization break; case CalendarId.TAIWAN: - if (CultureInfo.IsTaiwanSku) + if (SystemSupportsTaiwaneseCalendar()) { this.saEraNames = new String[] { "\x4e2d\x83ef\x6c11\x570b" }; } @@ -275,14 +251,14 @@ namespace System.Globalization } } - private void InitializeAbbreviatedEraNames(string localeName, int calendarId) + private void InitializeAbbreviatedEraNames(string localeName, CalendarId calendarId) { // Note that the saAbbrevEraNames only include "AD" We don't have localized names for other calendars available from windows - switch ((CalendarId)calendarId) + switch (calendarId) { // For Localized Gregorian we really expect the data from the OS. case CalendarId.GREGORIAN: - // Fallback for culture.dll missing + // Fallback for CoreCLR < Win7 or culture.dll missing if (this.saAbbrevEraNames == null || this.saAbbrevEraNames.Length == 0 || String.IsNullOrEmpty(this.saAbbrevEraNames[0])) { this.saAbbrevEraNames = new String[] { "AD" }; @@ -337,7 +313,7 @@ namespace System.Globalization } } - internal static CalendarData GetCalendarData(int calendarId) + internal static CalendarData GetCalendarData(CalendarId calendarId) { // // Get a calendar. @@ -347,48 +323,45 @@ namespace System.Globalization // // Get a culture name + // TODO: Note that this doesn't handle the new calendars (lunisolar, etc) String culture = CalendarIdToCultureName(calendarId); // Return our calendar - return CultureInfo.GetCultureInfo(culture).m_cultureData.GetCalendar(calendarId); + return CultureInfo.GetCultureInfo(culture)._cultureData.GetCalendar(calendarId); } - // - // Helper methods - // - private static String CalendarIdToCultureName(int calendarId) + private static String CalendarIdToCultureName(CalendarId calendarId) { - // note that this doesn't handle the new calendars (lunisolar, etc) switch (calendarId) { - case Calendar.CAL_GREGORIAN_US: + case CalendarId.GREGORIAN_US: return "fa-IR"; // "fa-IR" Iran - case Calendar.CAL_JAPAN: + case CalendarId.JAPAN: return "ja-JP"; // "ja-JP" Japan - case Calendar.CAL_TAIWAN: // zh-TW Taiwan - return "zh-TW"; + case CalendarId.TAIWAN: + return "zh-TW"; // zh-TW Taiwan - case Calendar.CAL_KOREA: + case CalendarId.KOREA: return "ko-KR"; // "ko-KR" Korea - case Calendar.CAL_HIJRI: - case Calendar.CAL_GREGORIAN_ARABIC: - case Calendar.CAL_UMALQURA: + case CalendarId.HIJRI: + case CalendarId.GREGORIAN_ARABIC: + case CalendarId.UMALQURA: return "ar-SA"; // "ar-SA" Saudi Arabia - case Calendar.CAL_THAI: + case CalendarId.THAI: return "th-TH"; // "th-TH" Thailand - case Calendar.CAL_HEBREW: + case CalendarId.HEBREW: return "he-IL"; // "he-IL" Israel - case Calendar.CAL_GREGORIAN_ME_FRENCH: + case CalendarId.GREGORIAN_ME_FRENCH: return "ar-DZ"; // "ar-DZ" Algeria - case Calendar.CAL_GREGORIAN_XLIT_ENGLISH: - case Calendar.CAL_GREGORIAN_XLIT_FRENCH: + case CalendarId.GREGORIAN_XLIT_ENGLISH: + case CalendarId.GREGORIAN_XLIT_FRENCH: return "ar-IQ"; // "ar-IQ"; Iraq default: @@ -398,19 +371,6 @@ namespace System.Globalization return "en-US"; } - - - // Get native two digit year max - [MethodImplAttribute(MethodImplOptions.InternalCall)] - internal static extern int nativeGetTwoDigitYearMax(int calID); - - // Call native side to load our calendar data - [MethodImplAttribute(MethodImplOptions.InternalCall)] - private static extern bool nativeGetCalendarData(CalendarData data, String localeName, int calendar); - - // Call native side to figure out which calendars are allowed - [MethodImplAttribute(MethodImplOptions.InternalCall)] - internal static extern int nativeGetCalendars(String localeName, bool useUserOverride, [In, Out] int[] calendars); } } diff --git a/src/mscorlib/src/System/Globalization/CalendricalCalculationsHelper.cs b/src/mscorlib/src/System/Globalization/CalendricalCalculationsHelper.cs index 9f1c086..7de75d6 100644 --- a/src/mscorlib/src/System/Globalization/CalendricalCalculationsHelper.cs +++ b/src/mscorlib/src/System/Globalization/CalendricalCalculationsHelper.cs @@ -2,9 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System; using System.Diagnostics; -using System.Diagnostics.Contracts; namespace System.Globalization { @@ -24,19 +22,19 @@ namespace System.Globalization private const int SecondsPerMinute = 60; private const int MinutesPerDegree = 60; - private static long StartOf1810 = GetNumberOfDays(new DateTime(1810, 1, 1)); - private static long StartOf1900Century = GetNumberOfDays(new DateTime(1900, 1, 1)); + private static readonly long s_startOf1810 = GetNumberOfDays(new DateTime(1810, 1, 1)); + private static readonly long s_startOf1900Century = GetNumberOfDays(new DateTime(1900, 1, 1)); - private static double[] Coefficients1900to1987 = new double[] { -0.00002, 0.000297, 0.025184, -0.181133, 0.553040, -0.861938, 0.677066, -0.212591 }; - private static double[] Coefficients1800to1899 = new double[] { -0.000009, 0.003844, 0.083563, 0.865736, 4.867575, 15.845535, 31.332267, 38.291999, 28.316289, 11.636204, 2.043794 }; - private static double[] Coefficients1700to1799 = new double[] { 8.118780842, -0.005092142, 0.003336121, -0.0000266484 }; - private static double[] Coefficients1620to1699 = new double[] { 196.58333, -4.0675, 0.0219167 }; - private static double[] LambdaCoefficients = new double[] { 280.46645, 36000.76983, 0.0003032 }; - private static double[] AnomalyCoefficients = new double[] { 357.52910, 35999.05030, -0.0001559, -0.00000048 }; - private static double[] EccentricityCoefficients = new double[] { 0.016708617, -0.000042037, -0.0000001236 }; - private static double[] Coefficients = new double[] { Angle(23, 26, 21.448), Angle(0, 0, -46.8150), Angle(0, 0, -0.00059), Angle(0, 0, 0.001813) }; - private static double[] CoefficientsA = new double[] { 124.90, -1934.134, 0.002063 }; - private static double[] CoefficientsB = new double[] { 201.11, 72001.5377, 0.00057 }; + private static readonly double[] s_coefficients1900to1987 = new double[] { -0.00002, 0.000297, 0.025184, -0.181133, 0.553040, -0.861938, 0.677066, -0.212591 }; + private static readonly double[] s_coefficients1800to1899 = new double[] { -0.000009, 0.003844, 0.083563, 0.865736, 4.867575, 15.845535, 31.332267, 38.291999, 28.316289, 11.636204, 2.043794 }; + private static readonly double[] s_coefficients1700to1799 = new double[] { 8.118780842, -0.005092142, 0.003336121, -0.0000266484 }; + private static readonly double[] s_coefficients1620to1699 = new double[] { 196.58333, -4.0675, 0.0219167 }; + private static readonly double[] s_lambdaCoefficients = new double[] { 280.46645, 36000.76983, 0.0003032 }; + private static readonly double[] s_anomalyCoefficients = new double[] { 357.52910, 35999.05030, -0.0001559, -0.00000048 }; + private static readonly double[] s_eccentricityCoefficients = new double[] { 0.016708617, -0.000042037, -0.0000001236 }; + private static readonly double[] s_coefficients = new double[] { Angle(23, 26, 21.448), Angle(0, 0, -46.8150), Angle(0, 0, -0.00059), Angle(0, 0, 0.001813) }; + private static readonly double[] s_coefficientsA = new double[] { 124.90, -1934.134, 0.002063 }; + private static readonly double[] s_coefficientsB = new double[] { 201.11, 72001.5377, 0.00057 }; private static double RadiansFromDegrees(double degree) { @@ -64,7 +62,7 @@ namespace System.Globalization private static double Obliquity(double julianCenturies) { - return PolynomialSum(Coefficients, julianCenturies); + return PolynomialSum(s_coefficients, julianCenturies); } internal static long GetNumberOfDays(DateTime date) @@ -99,7 +97,7 @@ namespace System.Globalization internal CorrectionAlgorithm _algorithm; }; - private static EphemerisCorrectionAlgorithmMap[] EphemerisCorrectionTable = new EphemerisCorrectionAlgorithmMap[] + private static readonly EphemerisCorrectionAlgorithmMap[] s_ephemerisCorrectionTable = new EphemerisCorrectionAlgorithmMap[] { // lowest year that starts algorithm, algorithm to use new EphemerisCorrectionAlgorithmMap(2020, CorrectionAlgorithm.Default), @@ -127,7 +125,7 @@ namespace System.Globalization return longitude; } - static public double AsDayFraction(double longitude) + public static double AsDayFraction(double longitude) { return longitude / FullCircleOfArc; } @@ -148,7 +146,7 @@ namespace System.Globalization private static double CenturiesFrom1900(int gregorianYear) { long july1stOfYear = GetNumberOfDays(new DateTime(gregorianYear, 7, 1)); - return (double)(july1stOfYear - StartOf1900Century) / DaysInUniformLengthCentury; + return (double)(july1stOfYear - s_startOf1900Century) / DaysInUniformLengthCentury; } // the following formulas defines a polynomial function which gives us the amount that the earth is slowing down for specific year ranges @@ -156,7 +154,7 @@ namespace System.Globalization { Debug.Assert(gregorianYear < 1620 || 2020 <= gregorianYear); long january1stOfYear = GetNumberOfDays(new DateTime(gregorianYear, 1, 1)); - double daysSinceStartOf1810 = january1stOfYear - StartOf1810; + double daysSinceStartOf1810 = january1stOfYear - s_startOf1810; double x = TwelveHours + daysSinceStartOf1810; return ((Math.Pow(x, 2) / 41048480) - 15) / SecondsPerDay; } @@ -171,35 +169,35 @@ namespace System.Globalization { Debug.Assert(1900 <= gregorianYear && gregorianYear <= 1987); double centuriesFrom1900 = CenturiesFrom1900(gregorianYear); - return PolynomialSum(Coefficients1900to1987, centuriesFrom1900); + return PolynomialSum(s_coefficients1900to1987, centuriesFrom1900); } private static double EphemerisCorrection1800to1899(int gregorianYear) { Debug.Assert(1800 <= gregorianYear && gregorianYear <= 1899); double centuriesFrom1900 = CenturiesFrom1900(gregorianYear); - return PolynomialSum(Coefficients1800to1899, centuriesFrom1900); + return PolynomialSum(s_coefficients1800to1899, centuriesFrom1900); } private static double EphemerisCorrection1700to1799(int gregorianYear) { Debug.Assert(1700 <= gregorianYear && gregorianYear <= 1799); double yearsSince1700 = gregorianYear - 1700; - return PolynomialSum(Coefficients1700to1799, yearsSince1700) / SecondsPerDay; + return PolynomialSum(s_coefficients1700to1799, yearsSince1700) / SecondsPerDay; } private static double EphemerisCorrection1620to1699(int gregorianYear) { Debug.Assert(1620 <= gregorianYear && gregorianYear <= 1699); double yearsSince1600 = gregorianYear - 1600; - return PolynomialSum(Coefficients1620to1699, yearsSince1600) / SecondsPerDay; + return PolynomialSum(s_coefficients1620to1699, yearsSince1600) / SecondsPerDay; } // ephemeris-correction: correction to account for the slowing down of the rotation of the earth private static double EphemerisCorrection(double time) { int year = GetGregorianYear(time); - foreach (EphemerisCorrectionAlgorithmMap map in EphemerisCorrectionTable) + foreach (EphemerisCorrectionAlgorithmMap map in s_ephemerisCorrectionTable) { if (map._lowestYear <= year) { @@ -221,7 +219,7 @@ namespace System.Globalization return DefaultEphemerisCorrection(year); } - static public double JulianCenturies(double moment) + public static double JulianCenturies(double moment) { double dynamicalMoment = moment + EphemerisCorrection(moment); return (dynamicalMoment - Noon2000Jan01) / DaysInUniformLengthCentury; @@ -246,9 +244,9 @@ namespace System.Globalization private static double EquationOfTime(double time) { double julianCenturies = JulianCenturies(time); - double lambda = PolynomialSum(LambdaCoefficients, julianCenturies); - double anomaly = PolynomialSum(AnomalyCoefficients, julianCenturies); - double eccentricity = PolynomialSum(EccentricityCoefficients, julianCenturies); + double lambda = PolynomialSum(s_lambdaCoefficients, julianCenturies); + double anomaly = PolynomialSum(s_anomalyCoefficients, julianCenturies); + double eccentricity = PolynomialSum(s_eccentricityCoefficients, julianCenturies); double epsilon = Obliquity(julianCenturies); double tanHalfEpsilon = TanOfDegree(epsilon / 2); @@ -275,7 +273,7 @@ namespace System.Globalization } // midday - static public double Midday(double date, double longitude) + public static double Midday(double date, double longitude) { return AsLocalTime(date + TwelveHours, longitude) - AsDayFraction(longitude); } @@ -286,7 +284,7 @@ namespace System.Globalization } // midday-in-tehran - static public double MiddayAtPersianObservationSite(double date) + public static double MiddayAtPersianObservationSite(double date) { return Midday(date, InitLongitude(52.5)); // 52.5 degrees east - longitude of UTC+3:30 which defines Iranian Standard Time } @@ -358,12 +356,12 @@ namespace System.Globalization private static double Nutation(double julianCenturies) { - double a = PolynomialSum(CoefficientsA, julianCenturies); - double b = PolynomialSum(CoefficientsB, julianCenturies); + double a = PolynomialSum(s_coefficientsA, julianCenturies); + double b = PolynomialSum(s_coefficientsB, julianCenturies); return (-0.004778 * SinOfDegree(a)) - (0.0003667 * SinOfDegree(b)); } - static public double Compute(double time) + public static double Compute(double time) { double julianCenturies = JulianCenturies(time); double lambda = 282.7771834 @@ -374,7 +372,7 @@ namespace System.Globalization return InitLongitude(longitude); } - static public double AsSeason(double longitude) + public static double AsSeason(double longitude) { return (longitude < 0) ? (longitude + FullCircleOfArc) : longitude; } diff --git a/src/mscorlib/src/System/Globalization/CharUnicodeInfo.cs b/src/mscorlib/src/System/Globalization/CharUnicodeInfo.cs index 860b847..8e3bb47 100644 --- a/src/mscorlib/src/System/Globalization/CharUnicodeInfo.cs +++ b/src/mscorlib/src/System/Globalization/CharUnicodeInfo.cs @@ -12,22 +12,12 @@ // //////////////////////////////////////////////////////////////////////////// +using System.Diagnostics; +using System.Diagnostics.Contracts; + namespace System.Globalization { - //This class has only static members and therefore doesn't need to be serialized. - - using System; - using System.Threading; - using System.Runtime.InteropServices; - using System.Runtime.CompilerServices; - using System.Runtime.Versioning; - using System.Reflection; - using System.Security; - using System.Diagnostics; - using System.Diagnostics.Contracts; - - - public static class CharUnicodeInfo + public static partial class CharUnicodeInfo { //--------------------------------------------------------------------// // Internal Information // @@ -44,88 +34,10 @@ namespace System.Globalization internal const int UNICODE_CATEGORY_OFFSET = 0; internal const int BIDI_CATEGORY_OFFSET = 1; - private static bool s_initialized = InitTable(); - - // The native pointer to the 12:4:4 index table of the Unicode cateogry data. - private unsafe static ushort* s_pCategoryLevel1Index; - private unsafe static byte* s_pCategoriesValue; - - // The native pointer to the 12:4:4 index table of the Unicode numeric data. - // The value of this index table is an index into the real value table stored in s_pNumericValues. - private unsafe static ushort* s_pNumericLevel1Index; - - // The numeric value table, which is indexed by s_pNumericLevel1Index. - // Every item contains the value for numeric value. - // unsafe static double* s_pNumericValues; - // To get around the IA64 alignment issue. Our double data is aligned in 8-byte boundary, but loader loads the embeded table starting - // at 4-byte boundary. This cause a alignment issue since double is 8-byte. - private unsafe static byte* s_pNumericValues; - - // The digit value table, which is indexed by s_pNumericLevel1Index. It shares the same indice as s_pNumericValues. - // Every item contains the value for decimal digit/digit value. - private unsafe static DigitValues* s_pDigitValues; - - internal const String UNICODE_INFO_FILE_NAME = "charinfo.nlp"; // The starting codepoint for Unicode plane 1. Plane 1 contains 0x010000 ~ 0x01ffff. internal const int UNICODE_PLANE01_START = 0x10000; - // - // This is the header for the native data table that we load from UNICODE_INFO_FILE_NAME. - // - // Excplicit layout is used here since a syntax like char[16] can not be used in sequential layout. - [StructLayout(LayoutKind.Explicit)] - internal unsafe struct UnicodeDataHeader - { - [FieldOffset(0)] - internal char TableName; // WCHAR[16] - [FieldOffset(0x20)] - internal ushort version; // WORD[4] - [FieldOffset(0x28)] - internal uint OffsetToCategoriesIndex; // DWORD - [FieldOffset(0x2c)] - internal uint OffsetToCategoriesValue; // DWORD - [FieldOffset(0x30)] - internal uint OffsetToNumbericIndex; // DWORD - [FieldOffset(0x34)] - internal uint OffsetToDigitValue; // DWORD - [FieldOffset(0x38)] - internal uint OffsetToNumbericValue; // DWORD - } - - // NOTE: It's important to specify pack size here, since the size of the structure is 2 bytes. Otherwise, - // the default pack size will be 4. - - [StructLayout(LayoutKind.Sequential, Pack = 2)] - internal struct DigitValues - { - internal sbyte decimalDigit; - internal sbyte digit; - } - - - //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. - // - private 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 + mainHeader->OffsetToCategoriesIndex); - s_pCategoriesValue = (byte*)(pDataTable + mainHeader->OffsetToCategoriesValue); - s_pNumericLevel1Index = (ushort*)(pDataTable + mainHeader->OffsetToNumbericIndex); - s_pNumericValues = (byte*)(pDataTable + mainHeader->OffsetToNumbericValue); - s_pDigitValues = (DigitValues*)(pDataTable + mainHeader->OffsetToDigitValue); - - return true; - } - - //////////////////////////////////////////////////////////////////////// // // Actions: @@ -157,7 +69,6 @@ namespace System.Globalization } return ((int)s[index]); } - //////////////////////////////////////////////////////////////////////// // // Convert a character or a surrogate pair starting at index of string s @@ -246,12 +157,13 @@ namespace System.Globalization return (false); } + // // This is called by the public char and string, index versions // // Note that for ch in the range D800-DFFF we just treat it as any other non-numeric character // - internal unsafe static double InternalGetNumericValue(int ch) + internal static unsafe double InternalGetNumericValue(int ch) { Debug.Assert(ch >= 0 && ch <= 0x10ffff, "ch is not in valid Unicode range."); // Get the level 2 item from the highest 12 bit (8 - 19) of ch. @@ -260,56 +172,34 @@ namespace System.Globalization // The offset is referred to an float item in m_pNumericFloatData. // Note that & has the lower precedence than addition, so don't forget the parathesis. index = s_pNumericLevel1Index[index + ((ch >> 4) & 0x000f)]; - byte* pBytePtr = (byte*)&(s_pNumericLevel1Index[index]); - // Get the result from the 0 -3 bit of ch. -#if BIT64 - // To get around the IA64 alignment issue. Our double data is aligned in 8-byte boundary, but loader loads the embeded table starting - // at 4-byte boundary. This cause a alignment issue since double is 8-byte. - byte* pSourcePtr = &(s_pNumericValues[pBytePtr[(ch & 0x000f)] * sizeof(double)]); - if (((long)pSourcePtr % 8) != 0) + + fixed (ushort* pUshortPtr = &(s_pNumericLevel1Index[index])) { - // We are not aligned in 8-byte boundary. Do a copy. - double ret; - byte* retPtr = (byte*)&ret; - Buffer.Memcpy(retPtr, pSourcePtr, sizeof(double)); - return (ret); + byte* pBytePtr = (byte*)pUshortPtr; + fixed (byte* pByteNum = s_pNumericValues) + { + double* pDouble = (double*)pByteNum; + return pDouble[pBytePtr[(ch & 0x000f)]]; + } } - return (((double*)s_pNumericValues)[pBytePtr[(ch & 0x000f)]]); -#else - return (((double*)s_pNumericValues)[pBytePtr[(ch & 0x000f)]]); -#endif } - // - // This is called by the public char and string, index versions - // - // Note that for ch in the range D800-DFFF we just treat it as any other non-numeric character - // - internal unsafe static DigitValues* InternalGetDigitValues(int ch) + internal static unsafe ushort InternalGetDigitValues(int ch) { Debug.Assert(ch >= 0 && ch <= 0x10ffff, "ch is not in valid Unicode range."); // Get the level 2 item from the highest 12 bit (8 - 19) of ch. ushort index = s_pNumericLevel1Index[ch >> 8]; // Get the level 2 WORD offset from the 4 - 7 bit of ch. This provides the base offset of the level 3 table. - // The offset is referred to an float item in m_pNumericFloatData. // Note that & has the lower precedence than addition, so don't forget the parathesis. index = s_pNumericLevel1Index[index + ((ch >> 4) & 0x000f)]; - byte* pBytePtr = (byte*)&(s_pNumericLevel1Index[index]); - // Get the result from the 0 -3 bit of ch. - return &(s_pDigitValues[pBytePtr[(ch & 0x000f)]]); - } - internal unsafe static sbyte InternalGetDecimalDigitValue(int ch) - { - return (InternalGetDigitValues(ch)->decimalDigit); - } - - internal unsafe static sbyte InternalGetDigitValue(int ch) - { - return (InternalGetDigitValues(ch)->digit); + fixed (ushort* pUshortPtr = &(s_pNumericLevel1Index[index])) + { + byte* pBytePtr = (byte*)pUshortPtr; + return s_pDigitValues[pBytePtr[(ch & 0x000f)]]; + } } - //////////////////////////////////////////////////////////////////////// // //Returns the numeric value associated with the character c. If the character is a fraction, @@ -340,89 +230,52 @@ namespace System.Globalization } if (index < 0 || index >= s.Length) { - throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_Index")); + throw new ArgumentOutOfRangeException(nameof(index), SR.ArgumentOutOfRange_Index); } Contract.EndContractBlock(); return (InternalGetNumericValue(InternalConvertToUtf32(s, index))); } - //////////////////////////////////////////////////////////////////////// - // - //Returns the decimal digit value associated with the character c. - // - // The value should be from 0 ~ 9. - // If the character does not have a numeric value, the return value is -1. - // From Unicode.org: Decimal Digits. Digits that can be used to form decimal-radix numbers. - //Returns: - // the decimal digit value for the specified Unicode character. If the character does not have a decimal digit value, the return value is -1. - //Arguments: - // ch a Unicode character - //Exceptions: - // ArgumentNullException - // ArgumentOutOfRangeException - // - //////////////////////////////////////////////////////////////////////// - - public static int GetDecimalDigitValue(char ch) { - return (InternalGetDecimalDigitValue(ch)); + return (sbyte)(InternalGetDigitValues(ch) >> 8); } - public static int GetDecimalDigitValue(String s, int index) { if (s == null) { throw new ArgumentNullException(nameof(s)); } + if (index < 0 || index >= s.Length) { - throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_Index")); + throw new ArgumentOutOfRangeException(nameof(index), SR.ArgumentOutOfRange_Index); } Contract.EndContractBlock(); - return (InternalGetDecimalDigitValue(InternalConvertToUtf32(s, index))); + return (sbyte)(InternalGetDigitValues(InternalConvertToUtf32(s, index)) >> 8); } - //////////////////////////////////////////////////////////////////////// - // - //Action: Returns the digit value associated with the character c. - // If the character does not have a numeric value, the return value is -1. - // From Unicode.org: If the character represents a digit, not necessarily a decimal digit, - // the value is here. This covers digits which do not form decimal radix forms, such as the compatibility superscript digits. - // - // An example is: U+2460 IRCLED DIGIT ONE. This character has digit value 1, but does not have associcated decimal digit value. - // - //Returns: - // the digit value for the specified Unicode character. If the character does not have a digit value, the return value is -1. - //Arguments: - // ch a Unicode character - //Exceptions: - // ArgumentNullException - // ArgumentOutOfRangeException - // - //////////////////////////////////////////////////////////////////////// - - public static int GetDigitValue(char ch) { - return (InternalGetDigitValue(ch)); + return (sbyte)(InternalGetDigitValues(ch) & 0x00FF); } - public static int GetDigitValue(String s, int index) { if (s == null) { throw new ArgumentNullException(nameof(s)); } + if (index < 0 || index >= s.Length) { - throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_Index")); + throw new ArgumentOutOfRangeException(nameof(index), SR.ArgumentOutOfRange_Index); } + Contract.EndContractBlock(); - return (InternalGetDigitValue(InternalConvertToUtf32(s, index))); + return (sbyte)(InternalGetDigitValues(InternalConvertToUtf32(s, index)) & 0x00FF); } public static UnicodeCategory GetUnicodeCategory(char ch) @@ -442,11 +295,12 @@ namespace System.Globalization return InternalGetUnicodeCategory(s, index); } - internal unsafe static UnicodeCategory InternalGetUnicodeCategory(int ch) + internal static unsafe UnicodeCategory InternalGetUnicodeCategory(int ch) { return ((UnicodeCategory)InternalGetCategoryValue(ch, UNICODE_CATEGORY_OFFSET)); } + //////////////////////////////////////////////////////////////////////// // //Action: Returns the Unicode Category property for the character c. @@ -461,7 +315,7 @@ namespace System.Globalization // //////////////////////////////////////////////////////////////////////// - internal unsafe static byte InternalGetCategoryValue(int ch, int offset) + internal static unsafe byte InternalGetCategoryValue(int ch, int offset) { Debug.Assert(ch >= 0 && ch <= 0x10ffff, "ch is not in valid Unicode range."); // Get the level 2 item from the highest 12 bit (8 - 19) of ch. @@ -469,32 +323,20 @@ namespace System.Globalization // Get the level 2 WORD offset from the 4 - 7 bit of ch. This provides the base offset of the level 3 table. // Note that & has the lower precedence than addition, so don't forget the parathesis. index = s_pCategoryLevel1Index[index + ((ch >> 4) & 0x000f)]; - byte* pBytePtr = (byte*)&(s_pCategoryLevel1Index[index]); - // Get the result from the 0 -3 bit of ch. - byte valueIndex = pBytePtr[(ch & 0x000f)]; - byte uc = s_pCategoriesValue[valueIndex * 2 + offset]; - // - // Make sure that OtherNotAssigned is the last category in UnicodeCategory. - // If that changes, change the following assertion as well. - // - //Debug.Assert(uc >= 0 && uc <= UnicodeCategory.OtherNotAssigned, "Table returns incorrect Unicode category"); - return (uc); - } - - // internal static BidiCategory GetBidiCategory(char ch) { - // return ((BidiCategory)InternalGetCategoryValue(c, BIDI_CATEGORY_OFFSET)); - // } - internal static BidiCategory GetBidiCategory(String s, int index) - { - if (s == null) - throw new ArgumentNullException(nameof(s)); - if (((uint)index) >= ((uint)s.Length)) + fixed (ushort* pUshortPtr = &(s_pCategoryLevel1Index[index])) { - throw new ArgumentOutOfRangeException(nameof(index)); + byte* pBytePtr = (byte*)pUshortPtr; + // Get the result from the 0 -3 bit of ch. + byte valueIndex = pBytePtr[(ch & 0x000f)]; + byte uc = s_pCategoriesValue[valueIndex * 2 + offset]; + // + // Make sure that OtherNotAssigned is the last category in UnicodeCategory. + // If that changes, change the following assertion as well. + // + //Debug.Assert(uc >= 0 && uc <= UnicodeCategory.OtherNotAssigned, "Table returns incorrect Unicode category"); + return (uc); } - Contract.EndContractBlock(); - return ((BidiCategory)InternalGetCategoryValue(InternalConvertToUtf32(s, index), BIDI_CATEGORY_OFFSET)); } //////////////////////////////////////////////////////////////////////// @@ -518,6 +360,19 @@ namespace System.Globalization return (InternalGetUnicodeCategory(InternalConvertToUtf32(value, index))); } + internal static BidiCategory GetBidiCategory(String s, int index) + { + if (s == null) + throw new ArgumentNullException(nameof(s)); + + if (((uint)index) >= ((uint)s.Length)) + { + throw new ArgumentOutOfRangeException(nameof(index)); + } + + return ((BidiCategory) InternalGetCategoryValue(InternalConvertToUtf32(s, index), BIDI_CATEGORY_OFFSET)); + } + //////////////////////////////////////////////////////////////////////// // // Get the Unicode category of the character starting at index. If the character is in BMP, charLength will return 1. diff --git a/src/mscorlib/corefx/System/Globalization/CharUnicodeInfoData.cs b/src/mscorlib/src/System/Globalization/CharUnicodeInfoData.cs similarity index 100% rename from src/mscorlib/corefx/System/Globalization/CharUnicodeInfoData.cs rename to src/mscorlib/src/System/Globalization/CharUnicodeInfoData.cs diff --git a/src/mscorlib/src/System/Globalization/ChineseLunisolarCalendar.cs b/src/mscorlib/src/System/Globalization/ChineseLunisolarCalendar.cs index 260b435..dc9e5fd 100644 --- a/src/mscorlib/src/System/Globalization/ChineseLunisolarCalendar.cs +++ b/src/mscorlib/src/System/Globalization/ChineseLunisolarCalendar.cs @@ -28,7 +28,6 @@ namespace System.Globalization // public const int ChineseEra = 1; - //internal static Calendar m_defaultInstance; internal const int MIN_LUNISOLAR_YEAR = 1901; internal const int MAX_LUNISOLAR_YEAR = 2100; @@ -71,10 +70,11 @@ namespace System.Globalization } - private static readonly int[,] yinfo = + private static readonly int[,] s_yinfo = { - /*Y LM Lmon Lday DaysPerMonth D1 D2 D3 D4 D5 D6 D7 D8 D9 D10 D11 D12 D13 #Days -1901 */{ 0 , 2 , 19 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354 + /*Y LM Lmon Lday DaysPerMonth D1 D2 D3 D4 D5 D6 D7 D8 D9 D10 D11 D12 D13 #Days + 1901 */ + { 0 , 2 , 19 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354 1902 */{ 0 , 2 , 8 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355 1903 */{ 5 , 1 , 29 , 21096 },/* 29 30 29 30 29 29 30 29 29 30 30 29 30 383 1904 */{ 0 , 2 , 16 , 53856 },/* 30 30 29 30 29 29 30 29 29 30 30 29 0 354 @@ -317,19 +317,19 @@ namespace System.Globalization } } - internal override int GetYearInfo(int LunarYear, int Index) + internal override int GetYearInfo(int lunarYear, int index) { - if ((LunarYear < MIN_LUNISOLAR_YEAR) || (LunarYear > MAX_LUNISOLAR_YEAR)) + if ((lunarYear < MIN_LUNISOLAR_YEAR) || (lunarYear > MAX_LUNISOLAR_YEAR)) { throw new ArgumentOutOfRangeException( "year", String.Format( CultureInfo.CurrentCulture, - Environment.GetResourceString("ArgumentOutOfRange_Range"), MIN_LUNISOLAR_YEAR, MAX_LUNISOLAR_YEAR)); + SR.ArgumentOutOfRange_Range, MIN_LUNISOLAR_YEAR, MAX_LUNISOLAR_YEAR)); } Contract.EndContractBlock(); - return yinfo[LunarYear - MIN_LUNISOLAR_YEAR, Index]; + return s_yinfo[lunarYear - MIN_LUNISOLAR_YEAR, index]; } internal override int GetYear(int year, DateTime time) @@ -341,7 +341,7 @@ namespace System.Globalization { if (era != CurrentEra && era != ChineseEra) { - throw new ArgumentOutOfRangeException(nameof(era), Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue")); + throw new ArgumentOutOfRangeException(nameof(era), SR.ArgumentOutOfRange_InvalidEraValue); } if (year < MIN_LUNISOLAR_YEAR || year > MAX_LUNISOLAR_YEAR) @@ -350,59 +350,37 @@ namespace System.Globalization nameof(year), String.Format( CultureInfo.CurrentCulture, - Environment.GetResourceString("ArgumentOutOfRange_Range"), MIN_LUNISOLAR_YEAR, MAX_LUNISOLAR_YEAR)); + SR.ArgumentOutOfRange_Range, MIN_LUNISOLAR_YEAR, MAX_LUNISOLAR_YEAR)); } Contract.EndContractBlock(); return year; } - - /*=================================GetDefaultInstance========================== - **Action: Internal method to provide a default intance of ChineseLunisolarCalendar. Used by NLS+ implementation - ** and other calendars. - **Returns: - **Arguments: - **Exceptions: - ============================================================================*/ - - /* - internal static Calendar GetDefaultInstance() - { - if (m_defaultInstance == null) { - m_defaultInstance = new ChineseLunisolarCalendar(); - } - return (m_defaultInstance); - } - */ - - // Construct an instance of ChineseLunisolar calendar. - public ChineseLunisolarCalendar() { } - public override int GetEra(DateTime time) { CheckTicksRange(time.Ticks); return (ChineseEra); } - internal override int ID + internal override CalendarId ID { get { - return (CAL_CHINESELUNISOLAR); + return (CalendarId.CHINESELUNISOLAR); } } - internal override int BaseCalendarID + internal override CalendarId BaseCalendarID { get { //Use CAL_GREGORIAN just to get CurrentEraValue as 1 since we do not have data under the ID CAL_ChineseLunisolar yet - return (CAL_GREGORIAN); + return (CalendarId.GREGORIAN); } } diff --git a/src/mscorlib/corefx/System/Globalization/CompareInfo.Unix.cs b/src/mscorlib/src/System/Globalization/CompareInfo.Unix.cs similarity index 99% rename from src/mscorlib/corefx/System/Globalization/CompareInfo.Unix.cs rename to src/mscorlib/src/System/Globalization/CompareInfo.Unix.cs index a5232b8..4cb1d26 100644 --- a/src/mscorlib/corefx/System/Globalization/CompareInfo.Unix.cs +++ b/src/mscorlib/src/System/Globalization/CompareInfo.Unix.cs @@ -20,7 +20,7 @@ namespace System.Globalization internal CompareInfo(CultureInfo culture) { - _name = culture.m_name; + _name = culture._name; InitSort(culture); } @@ -357,7 +357,7 @@ namespace System.Globalization byte[] sortKey = new byte[sortKeyLength]; - fixed(byte* pSortKey = sortKey) + fixed (byte* pSortKey = sortKey) { Interop.GlobalizationInterop.GetSortKey(_sortHandle, source, source.Length, pSortKey, sortKeyLength, options); return InternalHashSortKey(pSortKey, sortKeyLength, false, additionalEntropy); diff --git a/src/mscorlib/corefx/System/Globalization/CompareInfo.Windows.cs b/src/mscorlib/src/System/Globalization/CompareInfo.Windows.cs similarity index 73% rename from src/mscorlib/corefx/System/Globalization/CompareInfo.Windows.cs rename to src/mscorlib/src/System/Globalization/CompareInfo.Windows.cs index d493652..0c87d9f 100644 --- a/src/mscorlib/corefx/System/Globalization/CompareInfo.Windows.cs +++ b/src/mscorlib/src/System/Globalization/CompareInfo.Windows.cs @@ -2,8 +2,11 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System.Security; using System.Diagnostics; using System.Diagnostics.Contracts; +using System.Runtime.InteropServices; +using System.Runtime.CompilerServices; namespace System.Globalization { @@ -15,7 +18,7 @@ namespace System.Globalization InitSort(culture); } - private void InitSort(CultureInfo culture) + private unsafe void InitSort(CultureInfo culture) { _sortName = culture.SortName; @@ -25,7 +28,7 @@ namespace System.Globalization _sortName = culture.SortName; IntPtr handle; - int ret = Interop.mincore.LCMapStringEx(_sortName, LCMAP_SORTHANDLE, null, 0, &handle, IntPtr.Size, null, null, IntPtr.Zero); + int ret = Interop.Kernel32.LCMapStringEx(_sortName, LCMAP_SORTHANDLE, null, 0, &handle, IntPtr.Size, null, null, IntPtr.Zero); _sortHandle = ret > 0 ? handle : IntPtr.Zero; } @@ -41,7 +44,7 @@ namespace System.Globalization fixed (char* pSource = stringSource) fixed (char* pValue = value) { - int ret = Interop.mincore.FindStringOrdinal( + int ret = Interop.Kernel32.FindStringOrdinal( dwFindStringOrdinalFlags, pSource + offset, cchSource, @@ -78,12 +81,15 @@ namespace System.Globalization return 0; } + int flags = GetNativeCompareFlags(options); int tmpHash = 0; - +#if CORECLR + tmpHash = InternalGetGlobalizedHashCode(_sortHandle, _sortName, source, source.Length, flags, 0); +#else fixed (char* pSource = source) { - if (Interop.mincore.LCMapStringEx(_sortHandle != IntPtr.Zero ? null : _sortName, - LCMAP_HASH | (uint)GetNativeCompareFlags(options), + if (Interop.Kernel32.LCMapStringEx(_sortHandle != IntPtr.Zero ? null : _sortName, + LCMAP_HASH | (uint)flags, pSource, source.Length, &tmpHash, sizeof(int), null, null, _sortHandle) == 0) @@ -91,14 +97,14 @@ namespace System.Globalization Environment.FailFast("LCMapStringEx failed!"); } } - +#endif return tmpHash; } private static unsafe int CompareStringOrdinalIgnoreCase(char* string1, int count1, char* string2, int count2) { // Use the OS to compare and then convert the result to expected value by subtracting 2 - return Interop.mincore.CompareStringOrdinal(string1, count1, string2, count2, true) - 2; + return Interop.Kernel32.CompareStringOrdinal(string1, count1, string2, count2, true) - 2; } private unsafe int CompareString(string string1, int offset1, int length1, string string2, int offset2, int length2, CompareOptions options) @@ -113,7 +119,7 @@ namespace System.Globalization fixed (char* pString1 = string1) fixed (char* pString2 = string2) { - int result = Interop.mincore.CompareStringEx( + int result = Interop.Kernel32.CompareStringEx( pLocaleName, (uint)GetNativeCompareFlags(options), pString1 + offset1, @@ -141,7 +147,8 @@ namespace System.Globalization int cchSource, string lpStringValue, int startValue, - int cchValue) + int cchValue, + int *pcchFound) { string localeName = _sortHandle != IntPtr.Zero ? null : _sortName; @@ -152,44 +159,52 @@ namespace System.Globalization char* pS = pSource + startSource; char* pV = pValue + startValue; - return Interop.mincore.FindNLSStringEx( + return Interop.Kernel32.FindNLSStringEx( pLocaleName, dwFindNLSStringFlags, pS, cchSource, pV, cchValue, - null, + pcchFound, null, null, _sortHandle); } } - private int IndexOfCore(string source, string target, int startIndex, int count, CompareOptions options) + internal unsafe int IndexOfCore(String source, String target, int startIndex, int count, CompareOptions options, int* matchLengthPtr) { - Debug.Assert(!string.IsNullOrEmpty(source)); + Debug.Assert(source != null); Debug.Assert(target != null); Debug.Assert((options & CompareOptions.OrdinalIgnoreCase) == 0); - // TODO: Consider moving this up to the relevent APIs we need to ensure this behavior for - // and add a precondition that target is not empty. if (target.Length == 0) - return startIndex; // keep Whidbey compatibility + { + if (matchLengthPtr != null) + *matchLengthPtr = 0; + return 0; + } + + if (source.Length == 0) + { + return -1; + } if ((options & CompareOptions.Ordinal) != 0) { - return FastIndexOfString(source, target, startIndex, count, target.Length, findLastIndex: false); + int retValue = FastIndexOfString(source, target, startIndex, count, target.Length, findLastIndex: false); + if (retValue >= 0) + { + if (matchLengthPtr != null) + *matchLengthPtr = target.Length; + } + return retValue; } else { - int retValue = FindString(FIND_FROMSTART | (uint)GetNativeCompareFlags(options), - source, - startIndex, - count, - target, - 0, - target.Length); + int retValue = FindString(FIND_FROMSTART | (uint)GetNativeCompareFlags(options), source, startIndex, count, + target, 0, target.Length, matchLengthPtr); if (retValue >= 0) { return retValue + startIndex; @@ -199,7 +214,7 @@ namespace System.Globalization return -1; } - private int LastIndexOfCore(string source, string target, int startIndex, int count, CompareOptions options) + private unsafe int LastIndexOfCore(string source, string target, int startIndex, int count, CompareOptions options) { Debug.Assert(!string.IsNullOrEmpty(source)); Debug.Assert(target != null); @@ -216,13 +231,8 @@ namespace System.Globalization } else { - int retValue = FindString(FIND_FROMEND | (uint)GetNativeCompareFlags(options), - source, - startIndex - count + 1, - count, - target, - 0, - target.Length); + int retValue = FindString(FIND_FROMEND | (uint) GetNativeCompareFlags(options), source, startIndex - count + 1, + count, target, 0, target.Length, null); if (retValue >= 0) { @@ -233,41 +243,32 @@ namespace System.Globalization return -1; } - private bool StartsWith(string source, string prefix, CompareOptions options) + private unsafe bool StartsWith(string source, string prefix, CompareOptions options) { Debug.Assert(!string.IsNullOrEmpty(source)); Debug.Assert(!string.IsNullOrEmpty(prefix)); Debug.Assert((options & (CompareOptions.Ordinal | CompareOptions.OrdinalIgnoreCase)) == 0); - return FindString(FIND_STARTSWITH | (uint)GetNativeCompareFlags(options), - source, - 0, - source.Length, - prefix, - 0, - prefix.Length) >= 0; + return FindString(FIND_STARTSWITH | (uint)GetNativeCompareFlags(options), source, 0, source.Length, + prefix, 0, prefix.Length, null) >= 0; } - private bool EndsWith(string source, string suffix, CompareOptions options) + private unsafe bool EndsWith(string source, string suffix, CompareOptions options) { Debug.Assert(!string.IsNullOrEmpty(source)); Debug.Assert(!string.IsNullOrEmpty(suffix)); Debug.Assert((options & (CompareOptions.Ordinal | CompareOptions.OrdinalIgnoreCase)) == 0); - return FindString(FIND_ENDSWITH | (uint)GetNativeCompareFlags(options), - source, - 0, - source.Length, - suffix, - 0, - suffix.Length) >= 0; + return FindString(FIND_ENDSWITH | (uint)GetNativeCompareFlags(options), source, 0, source.Length, + suffix, 0, suffix.Length, null) >= 0; } // PAL ends here [NonSerialized] - private readonly IntPtr _sortHandle; + private IntPtr _sortHandle; - private const uint LCMAP_HASH = 0x00040000; + private const uint LCMAP_SORTKEY = 0x00000400; + private const uint LCMAP_HASH = 0x00040000; private const int FIND_STARTSWITH = 0x00100000; private const int FIND_ENDSWITH = 0x00200000; @@ -359,14 +360,44 @@ namespace System.Globalization throw new ArgumentException(SR.Argument_InvalidFlag, nameof(options)); } - throw new NotImplementedException(); + byte [] keyData = null; + if (source.Length == 0) + { + keyData = Array.Empty(); + } + else + { + fixed (char *pSource = source) + { + int result = Interop.Kernel32.LCMapStringEx(_sortHandle != IntPtr.Zero ? null : _sortName, + LCMAP_SORTKEY | (uint) GetNativeCompareFlags(options), + pSource, source.Length, + null, 0, + null, null, _sortHandle); + if (result == 0) + { + throw new ArgumentException(SR.Argument_InvalidFlag, "source"); + } + + keyData = new byte[result]; + + fixed (byte* pBytes = keyData) + { + result = Interop.Kernel32.LCMapStringEx(_sortHandle != IntPtr.Zero ? null : _sortName, + LCMAP_SORTKEY | (uint) GetNativeCompareFlags(options), + pSource, source.Length, + pBytes, keyData.Length, + null, null, _sortHandle); + } + } + } + + return new SortKey(Name, source, options, keyData); } private static unsafe bool IsSortable(char* text, int length) { - // CompareInfo c = CultureInfo.InvariantCulture.CompareInfo; - // return (InternalIsSortable(c.m_dataHandle, c.m_handleOrigin, c.m_sortName, text, text.Length)); - throw new NotImplementedException(); + return Interop.Kernel32.IsNLSDefinedString(Interop.Kernel32.COMPARE_STRING, 0, IntPtr.Zero, text, length); } private const int COMPARE_OPTIONS_ORDINAL = 0x40000000; // Ordinal @@ -407,9 +438,21 @@ namespace System.Globalization return nativeCompareFlags; } - private SortVersion GetSortVersion() + private unsafe SortVersion GetSortVersion() { - throw new NotImplementedException(); + Interop.Kernel32.NlsVersionInfoEx nlsVersion = new Interop.Kernel32.NlsVersionInfoEx(); + Interop.Kernel32.GetNLSVersionEx(Interop.Kernel32.COMPARE_STRING, _sortName, &nlsVersion); + return new SortVersion( + nlsVersion.dwNLSVersion, + nlsVersion.dwEffectiveId == 0 ? LCID : nlsVersion.dwEffectiveId, + nlsVersion.guidCustomVersion); } + +#if CORECLR + // Get a locale sensitive sort hash code from native code -- COMNlsInfo::InternalGetGlobalizedHashCode + [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] + [SuppressUnmanagedCodeSecurity] + private static extern int InternalGetGlobalizedHashCode(IntPtr handle, string localeName, string source, int length, int dwFlags, long additionalEntropy); +#endif } } diff --git a/src/mscorlib/src/System/Globalization/CompareInfo.cs b/src/mscorlib/src/System/Globalization/CompareInfo.cs index 49ae7c2..94cfcad 100644 --- a/src/mscorlib/src/System/Globalization/CompareInfo.cs +++ b/src/mscorlib/src/System/Globalization/CompareInfo.cs @@ -12,38 +12,15 @@ // //////////////////////////////////////////////////////////////////////////// +using System.Reflection; +using System.Diagnostics; +using System.Diagnostics.Contracts; +using System.Runtime.Serialization; + namespace System.Globalization { - // - // We pass all of the sorting calls to the native side, preferrably to the OS to do - // the actual work. - // - - using System; - using System.Collections; - using System.Collections.Generic; - using System.Reflection; - using System.Runtime.Serialization; - using System.Runtime.CompilerServices; - using System.Runtime.ConstrainedExecution; - using System.Runtime.InteropServices; - using System.Runtime.Versioning; - using System.Threading; - using Microsoft.Win32; - using System.Security; - using System.Diagnostics; - using System.Diagnostics.Contracts; - - // - // Options can be used during string comparison. - // - // Native implementation (COMNlsInfo.cpp & SortingTable.cpp) relies on the values of these, - // If you change the values below, be sure to change the values in native part as well. - // - - - [Serializable] [Flags] + [Serializable] public enum CompareOptions { None = 0x00000000, @@ -55,14 +32,8 @@ namespace System.Globalization OrdinalIgnoreCase = 0x10000000, // This flag can not be used with other flags. StringSort = 0x20000000, // use string sort method Ordinal = 0x40000000, // This flag can not be used with other flags. - - // StopOnNull = 0x10000000, - - // StopOnNull is defined in SortingTable.h, but we didn't enable this option here. - // Do not use this value for other flags accidentally. } - [Serializable] public partial class CompareInfo : IDeserializationCallback { @@ -81,6 +52,11 @@ namespace System.Globalization ~(CompareOptions.IgnoreCase | CompareOptions.IgnoreSymbols | CompareOptions.IgnoreNonSpace | CompareOptions.IgnoreWidth | CompareOptions.IgnoreKanaType); + // Mask used to check if we have the right flags. + private const CompareOptions ValidSortkeyCtorMaskOffFlags = + ~(CompareOptions.IgnoreCase | CompareOptions.IgnoreSymbols | CompareOptions.IgnoreNonSpace | + CompareOptions.IgnoreWidth | CompareOptions.IgnoreKanaType | CompareOptions.StringSort); + // // CompareInfos have an interesting identity. They are attached to the locale that created them, // ie: en-US would have an en-US sort. For haw-US (custom), then we serialize it as haw-US. @@ -88,47 +64,24 @@ namespace System.Globalization // locale, which is what SCOMPAREINFO does. [OptionalField(VersionAdded = 2)] - private String m_name; // The name used to construct this CompareInfo - - [NonSerialized] - private String m_sortName; // The name that defines our behavior + private String _name; // The name used to construct this CompareInfo + [NonSerialized] + private String _sortName; // The name that defines our behavior - [NonSerialized] - private IntPtr m_dataHandle; - - [NonSerialized] - private IntPtr m_handleOrigin; - - //////////////////////////////////////////////////////////////////////// - // - // CompareInfo Constructor - // - // - //////////////////////////////////////////////////////////////////////// - // Constructs an instance that most closely corresponds to the NLS locale - // identifier. - internal CompareInfo(CultureInfo culture) - { - m_name = culture.m_name; - m_sortName = culture.SortName; - - IntPtr handleOrigin; - m_dataHandle = InternalInitSortHandle(m_sortName, out handleOrigin); - m_handleOrigin = handleOrigin; - } + [OptionalField(VersionAdded = 3)] + private SortVersion _sortVersion; /*=================================GetCompareInfo========================== **Action: Get the CompareInfo constructed from the data table in the specified assembly for the specified culture. ** Warning: The assembly versioning mechanism is dead! **Returns: The CompareInfo for the specified culture. **Arguments: - ** culture the ID of the culture + ** 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. ============================================================================*/ -#if FEATURE_USE_LCID // Assembly constructor should be deprecated, we don't act on the assembly information any more public static CompareInfo GetCompareInfo(int culture, Assembly assembly) { @@ -137,24 +90,22 @@ namespace System.Globalization { throw new ArgumentNullException(nameof(assembly)); } - if (assembly != typeof(Object).Module.Assembly) + if (assembly != typeof(Object).Module.Assembly) { - throw new ArgumentException(Environment.GetResourceString("Argument_OnlyMscorlib")); + throw new ArgumentException(SR.Argument_OnlyMscorlib); } Contract.EndContractBlock(); return GetCompareInfo(culture); } -#endif - /*=================================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. + ** 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. @@ -170,7 +121,7 @@ namespace System.Globalization if (assembly != typeof(Object).Module.Assembly) { - throw new ArgumentException(Environment.GetResourceString("Argument_OnlyMscorlib")); + throw new ArgumentException(SR.Argument_OnlyMscorlib); } return GetCompareInfo(name); @@ -185,20 +136,17 @@ namespace System.Globalization **Exceptions: ** ArgumentException if culture is invalid. ============================================================================*/ - -#if FEATURE_USE_LCID // People really shouldn't be calling LCID versions, no custom support public static CompareInfo GetCompareInfo(int culture) { if (CultureData.IsCustomCultureId(culture)) { // Customized culture cannot be created by the LCID. - throw new ArgumentException(Environment.GetResourceString("Argument_CustomCultureCannotBePassedByNumber", nameof(culture))); + throw new ArgumentException(SR.Argument_CustomCultureCannotBePassedByNumber, nameof(culture)); } return CultureInfo.GetCultureInfo(culture).CompareInfo; } -#endif /*=================================GetCompareInfo========================== **Action: Get the CompareInfo for the specified culture. @@ -220,14 +168,15 @@ namespace System.Globalization return CultureInfo.GetCultureInfo(name).CompareInfo; } - public static bool IsSortable(char ch) + public static unsafe bool IsSortable(char ch) { - return (IsSortable(ch.ToString())); + char *pChar = &ch; + return IsSortable(pChar, 1); } - public static bool IsSortable(String text) + public static unsafe bool IsSortable(string text) { - if (text == null) + if (text == null) { // A null param is invalid here. throw new ArgumentNullException(nameof(text)); @@ -238,49 +187,23 @@ namespace System.Globalization // A zero length string is not invalid, but it is also not sortable. return (false); } - - CompareInfo c = CultureInfo.InvariantCulture.CompareInfo; - - return (InternalIsSortable(c.m_dataHandle, c.m_handleOrigin, c.m_sortName, text, text.Length)); + + fixed (char *pChar = text) + { + return IsSortable(pChar, text.Length); + } } - #region Serialization - // the following fields are defined to keep the compatibility with Whidbey. - // don't change/remove the names/types of these fields. -#if FEATURE_USE_LCID - [OptionalField(VersionAdded = 1)] - private int win32LCID; // mapped sort culture id of this instance - private int culture; // the culture ID used to create this instance. -#endif [OnDeserializing] private void OnDeserializing(StreamingContext ctx) { - m_name = null; + _name = null; } - private void OnDeserialized() + void IDeserializationCallback.OnDeserialization(Object sender) { - CultureInfo ci; - // If we didn't have a name, use the LCID - if (m_name == null) - { -#if FEATURE_USE_LCID - // From whidbey, didn't have a name - ci = CultureInfo.GetCultureInfo(culture); - m_name = ci.m_name; - m_sortName = ci.SortName; -#endif - } - else - { - ci = CultureInfo.GetCultureInfo(m_name); - m_sortName = ci.SortName; - } - - IntPtr handleOrigin; - m_dataHandle = InternalInitSortHandle(m_sortName, out handleOrigin); - m_handleOrigin = handleOrigin; + OnDeserialized(); } [OnDeserialized] @@ -289,23 +212,16 @@ namespace System.Globalization OnDeserialized(); } - [OnSerializing] - private void OnSerializing(StreamingContext ctx) - { -#if FEATURE_USE_LCID - // This is merely for serialization compatibility with Whidbey/Orcas, it can go away when we don't want that compat any more. - culture = CultureInfo.GetCultureInfo(this.Name).LCID; // This is the lcid of the constructing culture (still have to dereference to get target sort) - Debug.Assert(m_name != null, "CompareInfo.OnSerializing - expected m_name to be set already"); -#endif - } - - void IDeserializationCallback.OnDeserialization(Object sender) + private void OnDeserialized() { - OnDeserialized(); + if (_name != null) + { + InitSort(CultureInfo.GetCultureInfo(_name)); + } } - #endregion Serialization - + [OnSerializing] + private void OnSerializing(StreamingContext ctx) { } ///////////////////////////----- Name -----///////////////////////////////// // @@ -324,61 +240,16 @@ namespace System.Globalization { get { - Debug.Assert(m_name != null, "CompareInfo.Name Expected m_name to be set"); - return (m_sortName); - } - } - - // These flags are used in the native Win32. so we need to map the managed options to those flags - private const int LINGUISTIC_IGNORECASE = 0x00000010; // linguistically appropriate 'ignore case' - private const int NORM_IGNORECASE = 0x00000001; // Ignores case. (use LINGUISTIC_IGNORECASE instead) - private const int NORM_IGNOREKANATYPE = 0x00010000; // Does not differentiate between Hiragana and Katakana characters. Corresponding Hiragana and Katakana will compare as equal. - private const int LINGUISTIC_IGNOREDIACRITIC = 0x00000020; // linguistically appropriate 'ignore nonspace' - private const int NORM_IGNORENONSPACE = 0x00000002; // Ignores nonspacing. This flag also removes Japanese accent characters. (use LINGUISTIC_IGNOREDIACRITIC instead) - private const int NORM_IGNORESYMBOLS = 0x00000004; // Ignores symbols. - private const int NORM_IGNOREWIDTH = 0x00020000; // Does not differentiate between a single-byte character and the same character as a double-byte character. - private const int SORT_STRINGSORT = 0x00001000; // Treats punctuation the same as symbols. - private const int COMPARE_OPTIONS_ORDINAL = 0x40000000; // Ordinal (handled by Comnlsinfo) - internal const int NORM_LINGUISTIC_CASING = 0x08000000; // use linguistic rules for casing - - - private const int RESERVED_FIND_ASCII_STRING = 0x20000000; // This flag used only to tell the sorting DLL can assume the string characters are in ASCII. + Debug.Assert(_name != null, "CompareInfo.Name Expected _name to be set"); + if (_name == "zh-CHT" || _name == "zh-CHS") + { + return _name; + } - [Pure] - internal static int GetNativeCompareFlags(CompareOptions options) - { - // some NLS VM functions can handle COMPARE_OPTIONS_ORDINAL - // in which case options should be simply cast to int instead of using this function - // Does not look like the best approach to me but for now I am going to leave it as it is - Debug.Assert(options != CompareOptions.OrdinalIgnoreCase, "[CompareInfo.GetNativeCompareFlags]CompareOptions.OrdinalIgnoreCase should be handled separately"); - - // Use "linguistic casing" by default (load the culture's casing exception tables) - int nativeCompareFlags = NORM_LINGUISTIC_CASING; - - if ((options & CompareOptions.IgnoreCase) != 0) { nativeCompareFlags |= NORM_IGNORECASE; } - if ((options & CompareOptions.IgnoreKanaType) != 0) { nativeCompareFlags |= NORM_IGNOREKANATYPE; } - if ((options & CompareOptions.IgnoreNonSpace) != 0) { nativeCompareFlags |= NORM_IGNORENONSPACE; } - if ((options & CompareOptions.IgnoreSymbols) != 0) { nativeCompareFlags |= NORM_IGNORESYMBOLS; } - if ((options & CompareOptions.IgnoreWidth) != 0) { nativeCompareFlags |= NORM_IGNOREWIDTH; } - if ((options & CompareOptions.StringSort) != 0) { nativeCompareFlags |= SORT_STRINGSORT; } - - // Suffix & Prefix shouldn't use this, make sure to turn off the NORM_LINGUISTIC_CASING flag - if (options == CompareOptions.Ordinal) { nativeCompareFlags = COMPARE_OPTIONS_ORDINAL; } - - Debug.Assert(((options & ~(CompareOptions.IgnoreCase | - CompareOptions.IgnoreKanaType | - CompareOptions.IgnoreNonSpace | - CompareOptions.IgnoreSymbols | - CompareOptions.IgnoreWidth | - CompareOptions.StringSort)) == 0) || - (options == CompareOptions.Ordinal), "[CompareInfo.GetNativeCompareFlags]Expected all flags to be handled"); - - Debug.Assert((nativeCompareFlags & RESERVED_FIND_ASCII_STRING) == 0, "[CompareInfo.GetNativeCompareFlags] RESERVED_FIND_ASCII_STRING shouldn't be set here"); - - return nativeCompareFlags; + return _sortName; + } } - //////////////////////////////////////////////////////////////////////// // // Compare @@ -390,7 +261,6 @@ namespace System.Globalization // //////////////////////////////////////////////////////////////////////// - public virtual int Compare(String string1, String string2) { return (Compare(string1, string2, CompareOptions.None)); @@ -408,14 +278,14 @@ namespace System.Globalization { if (options != CompareOptions.Ordinal) { - throw new ArgumentException(Environment.GetResourceString("Argument_CompareOptionOrdinal"), nameof(options)); + throw new ArgumentException(SR.Argument_CompareOptionOrdinal, nameof(options)); } return String.CompareOrdinal(string1, string2); } if ((options & ValidCompareMaskOffFlags) != 0) { - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidFlag"), nameof(options)); + throw new ArgumentException(SR.Argument_InvalidFlag, nameof(options)); } //Our paradigm is that null sorts less than any other string and @@ -433,7 +303,7 @@ namespace System.Globalization return (1); // non-null > null } - return InternalCompareString(m_dataHandle, m_handleOrigin, m_sortName, string1, 0, string1.Length, string2, 0, string2.Length, GetNativeCompareFlags(options)); + return CompareString(string1, 0, string1.Length, string2, 0, string2.Length, options); } @@ -482,31 +352,31 @@ namespace System.Globalization // Verify inputs if (length1 < 0 || length2 < 0) { - throw new ArgumentOutOfRangeException((length1 < 0) ? nameof(length1) : nameof(length2), Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum")); + throw new ArgumentOutOfRangeException((length1 < 0) ? nameof(length1) : nameof(length2), SR.ArgumentOutOfRange_NeedPosNum); } if (offset1 < 0 || offset2 < 0) { - throw new ArgumentOutOfRangeException((offset1 < 0) ? nameof(offset1) : nameof(offset2), Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum")); + throw new ArgumentOutOfRangeException((offset1 < 0) ? nameof(offset1) : nameof(offset2), SR.ArgumentOutOfRange_NeedPosNum); } if (offset1 > (string1 == null ? 0 : string1.Length) - length1) { - throw new ArgumentOutOfRangeException(nameof(string1), Environment.GetResourceString("ArgumentOutOfRange_OffsetLength")); + throw new ArgumentOutOfRangeException(nameof(string1), SR.ArgumentOutOfRange_OffsetLength); } if (offset2 > (string2 == null ? 0 : string2.Length) - length2) { - throw new ArgumentOutOfRangeException(nameof(string2), Environment.GetResourceString("ArgumentOutOfRange_OffsetLength")); + throw new ArgumentOutOfRangeException(nameof(string2), SR.ArgumentOutOfRange_OffsetLength); } if ((options & CompareOptions.Ordinal) != 0) { if (options != CompareOptions.Ordinal) { - throw new ArgumentException(Environment.GetResourceString("Argument_CompareOptionOrdinal"), + throw new ArgumentException(SR.Argument_CompareOptionOrdinal, nameof(options)); } } else if ((options & ValidCompareMaskOffFlags) != 0) { - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidFlag"), nameof(options)); + throw new ArgumentException(SR.Argument_InvalidFlag, nameof(options)); } // @@ -527,12 +397,75 @@ namespace System.Globalization if (options == CompareOptions.Ordinal) { - return string.CompareOrdinalHelper(string1, offset1, length1, string2, offset2, length2); + return CompareOrdinal(string1, offset1, length1, + string2, offset2, length2); + } + return CompareString(string1, offset1, length1, + string2, offset2, length2, + options); + } + + private static int CompareOrdinal(string string1, int offset1, int length1, string string2, int offset2, int length2) + { + int result = String.CompareOrdinal(string1, offset1, string2, offset2, + (length1 < length2 ? length1 : length2)); + if ((length1 != length2) && result == 0) + { + return (length1 > length2 ? 1 : -1); + } + return (result); + } + + // + // CompareOrdinalIgnoreCase compare two string oridnally with ignoring the case. + // it assumes the strings are Ascii string till we hit non Ascii character in strA or strB and then we continue the comparison by + // calling the OS. + // + internal static unsafe int CompareOrdinalIgnoreCase(string strA, int indexA, int lengthA, string strB, int indexB, int lengthB) + { + Debug.Assert(indexA + lengthA <= strA.Length); + Debug.Assert(indexB + lengthB <= strB.Length); + + int length = Math.Min(lengthA, lengthB); + int range = length; + + fixed (char* ap = strA) fixed (char* bp = strB) + { + char* a = ap + indexA; + char* b = bp + indexB; + + while (length != 0 && (*a <= 0x80) && (*b <= 0x80)) + { + int charA = *a; + int charB = *b; + + if (charA == charB) + { + a++; b++; + length--; + continue; + } + + // uppercase both chars - notice that we need just one compare per char + if ((uint)(charA - 'a') <= (uint)('z' - 'a')) charA -= 0x20; + if ((uint)(charB - 'a') <= (uint)('z' - 'a')) charB -= 0x20; + + //Return the (case-insensitive) difference between them. + if (charA != charB) + return charA - charB; + + // Next char + a++; b++; + length--; + } + + if (length == 0) + return lengthA - lengthB; + + range -= length; + + return CompareStringOrdinalIgnoreCase(a, lengthA - range, b, lengthB - range); } - return InternalCompareString(m_dataHandle, m_handleOrigin, m_sortName, - string1, offset1, length1, - string2, offset2, length2, - GetNativeCompareFlags(options)); } //////////////////////////////////////////////////////////////////////// @@ -543,23 +476,25 @@ namespace System.Globalization // String.Empty, true is returned. // //////////////////////////////////////////////////////////////////////// - - public unsafe virtual bool IsPrefix(String source, String prefix, CompareOptions options) { if (source == null || prefix == null) { throw new ArgumentNullException((source == null ? nameof(source) : nameof(prefix)), - Environment.GetResourceString("ArgumentNull_String")); + SR.ArgumentNull_String); } Contract.EndContractBlock(); - int prefixLen = prefix.Length; - if (prefixLen == 0) + if (prefix.Length == 0) { return (true); } + if (source.Length == 0) + { + return false; + } + if (options == CompareOptions.OrdinalIgnoreCase) { return source.StartsWith(prefix, StringComparison.OrdinalIgnoreCase); @@ -572,17 +507,10 @@ namespace System.Globalization if ((options & ValidIndexMaskOffFlags) != 0) { - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidFlag"), nameof(options)); + throw new ArgumentException(SR.Argument_InvalidFlag, nameof(options)); } - - // to let the sorting DLL do the call optimization in case of Ascii strings, we check if the strings are in Ascii and then send the flag RESERVED_FIND_ASCII_STRING to - // the sorting DLL API SortFindString so sorting DLL don't have to check if the string is Ascii with every call to SortFindString. - return (InternalFindNLSStringEx( - m_dataHandle, m_handleOrigin, m_sortName, - GetNativeCompareFlags(options) | Win32Native.FIND_STARTSWITH | ((source.IsAscii() && prefix.IsAscii()) ? RESERVED_FIND_ASCII_STRING : 0), - source, source.Length, 0, prefix, prefix.Length, - null) > -1); + return StartsWith(source, prefix, options); } public virtual bool IsPrefix(String source, String prefix) @@ -590,7 +518,6 @@ namespace System.Globalization return (IsPrefix(source, prefix, 0)); } - //////////////////////////////////////////////////////////////////////// // // IsSuffix @@ -599,23 +526,25 @@ namespace System.Globalization // String.Empty, true is returned. // //////////////////////////////////////////////////////////////////////// - - public unsafe virtual bool IsSuffix(String source, String suffix, CompareOptions options) { if (source == null || suffix == null) { throw new ArgumentNullException((source == null ? nameof(source) : nameof(suffix)), - Environment.GetResourceString("ArgumentNull_String")); + SR.ArgumentNull_String); } Contract.EndContractBlock(); - int suffixLen = suffix.Length; - if (suffixLen == 0) + if (suffix.Length == 0) { return (true); } + if (source.Length == 0) + { + return false; + } + if (options == CompareOptions.OrdinalIgnoreCase) { return source.EndsWith(suffix, StringComparison.OrdinalIgnoreCase); @@ -628,15 +557,10 @@ namespace System.Globalization if ((options & ValidIndexMaskOffFlags) != 0) { - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidFlag"), nameof(options)); + throw new ArgumentException(SR.Argument_InvalidFlag, nameof(options)); } - // to let the sorting DLL do the call optimization in case of Ascii strings, we check if the strings are in Ascii and then send the flag RESERVED_FIND_ASCII_STRING to - // the sorting DLL API SortFindString so sorting DLL don't have to check if the string is Ascii with every call to SortFindString. - return InternalFindNLSStringEx( - m_dataHandle, m_handleOrigin, m_sortName, - GetNativeCompareFlags(options) | Win32Native.FIND_ENDSWITH | ((source.IsAscii() && suffix.IsAscii()) ? RESERVED_FIND_ASCII_STRING : 0), - source, source.Length, source.Length - 1, suffix, suffix.Length, null) >= 0; + return EndsWith(source, suffix, options); } @@ -698,7 +622,6 @@ namespace System.Globalization return IndexOf(source, value, 0, source.Length, options); } - public unsafe virtual int IndexOf(String source, char value, int startIndex) { if (source == null) @@ -708,7 +631,6 @@ namespace System.Globalization return IndexOf(source, value, startIndex, source.Length - startIndex, CompareOptions.None); } - public unsafe virtual int IndexOf(String source, String value, int startIndex) { if (source == null) @@ -718,7 +640,6 @@ namespace System.Globalization return IndexOf(source, value, startIndex, source.Length - startIndex, CompareOptions.None); } - public unsafe virtual int IndexOf(String source, char value, int startIndex, CompareOptions options) { if (source == null) @@ -757,10 +678,10 @@ namespace System.Globalization throw new ArgumentNullException(nameof(source)); if (startIndex < 0 || startIndex > source.Length) - throw new ArgumentOutOfRangeException(nameof(startIndex), Environment.GetResourceString("ArgumentOutOfRange_Index")); + throw new ArgumentOutOfRangeException(nameof(startIndex), SR.ArgumentOutOfRange_Index); if (count < 0 || startIndex > source.Length - count) - throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_Count")); + throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_Count); Contract.EndContractBlock(); if (options == CompareOptions.OrdinalIgnoreCase) @@ -771,22 +692,13 @@ namespace System.Globalization // Validate CompareOptions // Ordinal can't be selected with other flags if ((options & ValidIndexMaskOffFlags) != 0 && (options != CompareOptions.Ordinal)) - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidFlag"), nameof(options)); - - // to let the sorting DLL do the call optimization in case of Ascii strings, we check if the strings are in Ascii and then send the flag RESERVED_FIND_ASCII_STRING to - // the sorting DLL API SortFindString so sorting DLL don't have to check if the string is Ascii with every call to SortFindString. - return InternalFindNLSStringEx( - m_dataHandle, m_handleOrigin, m_sortName, - GetNativeCompareFlags(options) | Win32Native.FIND_FROMSTART | ((source.IsAscii() && (value <= '\x007f')) ? RESERVED_FIND_ASCII_STRING : 0), - source, count, startIndex, new String(value, 1), 1, null); - } + throw new ArgumentException(SR.Argument_InvalidFlag, nameof(options)); - public unsafe virtual int IndexOf(String source, String value, int startIndex, int count, CompareOptions options) - { - return IndexOfCore(source, value, startIndex, count, options, null); + return IndexOfCore(source, new string(value, 1), startIndex, count, options, null); } - internal unsafe int IndexOfCore(String source, String value, int startIndex, int count, CompareOptions options, int* matchLengthPtr) + + public unsafe virtual int IndexOf(String source, String value, int startIndex, int count, CompareOptions options) { // Validate inputs if (source == null) @@ -796,7 +708,7 @@ namespace System.Globalization if (startIndex > source.Length) { - throw new ArgumentOutOfRangeException(nameof(startIndex), Environment.GetResourceString("ArgumentOutOfRange_Index")); + throw new ArgumentOutOfRangeException(nameof(startIndex), SR.ArgumentOutOfRange_Index); } Contract.EndContractBlock(); @@ -806,8 +718,6 @@ namespace System.Globalization { if (value.Length == 0) { - if (matchLengthPtr != null) - *matchLengthPtr = 0; return 0; } return -1; @@ -815,34 +725,23 @@ namespace System.Globalization if (startIndex < 0) { - throw new ArgumentOutOfRangeException(nameof(startIndex), Environment.GetResourceString("ArgumentOutOfRange_Index")); + throw new ArgumentOutOfRangeException(nameof(startIndex), SR.ArgumentOutOfRange_Index); } if (count < 0 || startIndex > source.Length - count) - throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_Count")); + throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_Count); if (options == CompareOptions.OrdinalIgnoreCase) { - int index = source.IndexOf(value, startIndex, count, StringComparison.OrdinalIgnoreCase); - if (index != -1) - { - if (matchLengthPtr != null) - *matchLengthPtr = value.Length; - } - return index; + return IndexOfOrdinal(source, value, startIndex, count, ignoreCase: true); } // Validate CompareOptions // Ordinal can't be selected with other flags if ((options & ValidIndexMaskOffFlags) != 0 && (options != CompareOptions.Ordinal)) - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidFlag"), nameof(options)); - - // to let the sorting DLL do the call optimization in case of Ascii strings, we check if the strings are in Ascii and then send the flag RESERVED_FIND_ASCII_STRING to - // the sorting DLL API SortFindString so sorting DLL don't have to check if the string is Ascii with every call to SortFindString. - return InternalFindNLSStringEx( - m_dataHandle, m_handleOrigin, m_sortName, - GetNativeCompareFlags(options) | Win32Native.FIND_FROMSTART | ((source.IsAscii() && value.IsAscii()) ? RESERVED_FIND_ASCII_STRING : 0), - source, count, startIndex, value, value.Length, matchLengthPtr); + throw new ArgumentException(SR.Argument_InvalidFlag, nameof(options)); + + return IndexOfCore(source, value, startIndex, count, options, null); } //////////////////////////////////////////////////////////////////////// @@ -905,7 +804,6 @@ namespace System.Globalization source.Length, options); } - public unsafe virtual int LastIndexOf(String source, char value, int startIndex) { return LastIndexOf(source, value, startIndex, startIndex + 1, CompareOptions.None); @@ -917,7 +815,6 @@ namespace System.Globalization return LastIndexOf(source, value, startIndex, startIndex + 1, CompareOptions.None); } - public unsafe virtual int LastIndexOf(String source, char value, int startIndex, CompareOptions options) { return LastIndexOf(source, value, startIndex, startIndex + 1, options); @@ -954,7 +851,7 @@ namespace System.Globalization if ((options & ValidIndexMaskOffFlags) != 0 && (options != CompareOptions.Ordinal) && (options != CompareOptions.OrdinalIgnoreCase)) - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidFlag"), nameof(options)); + throw new ArgumentException(SR.Argument_InvalidFlag, nameof(options)); // Special case for 0 length input strings if (source.Length == 0 && (startIndex == -1 || startIndex == 0)) @@ -962,7 +859,7 @@ namespace System.Globalization // Make sure we're not out of range if (startIndex < 0 || startIndex > source.Length) - throw new ArgumentOutOfRangeException(nameof(startIndex), Environment.GetResourceString("ArgumentOutOfRange_Index")); + throw new ArgumentOutOfRangeException(nameof(startIndex), SR.ArgumentOutOfRange_Index); // Make sure that we allow startIndex == source.Length if (startIndex == source.Length) @@ -974,19 +871,14 @@ namespace System.Globalization // 2nd have of this also catches when startIndex == MAXINT, so MAXINT - 0 + 1 == -1, which is < 0. if (count < 0 || startIndex - count + 1 < 0) - throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_Count")); + throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_Count); if (options == CompareOptions.OrdinalIgnoreCase) { return source.LastIndexOf(value.ToString(), startIndex, count, StringComparison.OrdinalIgnoreCase); } - // to let the sorting DLL do the call optimization in case of Ascii strings, we check if the strings are in Ascii and then send the flag RESERVED_FIND_ASCII_STRING to - // the sorting DLL API SortFindString so sorting DLL don't have to check if the string is Ascii with every call to SortFindString. - return InternalFindNLSStringEx( - m_dataHandle, m_handleOrigin, m_sortName, - GetNativeCompareFlags(options) | Win32Native.FIND_FROMEND | ((source.IsAscii() && (value <= '\x007f')) ? RESERVED_FIND_ASCII_STRING : 0), - source, count, startIndex, new String(value, 1), 1, null); + return LastIndexOfCore(source, value.ToString(), startIndex, count, options); } @@ -1004,7 +896,7 @@ namespace System.Globalization if ((options & ValidIndexMaskOffFlags) != 0 && (options != CompareOptions.Ordinal) && (options != CompareOptions.OrdinalIgnoreCase)) - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidFlag"), nameof(options)); + throw new ArgumentException(SR.Argument_InvalidFlag, nameof(options)); // Special case for 0 length input strings if (source.Length == 0 && (startIndex == -1 || startIndex == 0)) @@ -1012,7 +904,7 @@ namespace System.Globalization // Make sure we're not out of range if (startIndex < 0 || startIndex > source.Length) - throw new ArgumentOutOfRangeException(nameof(startIndex), Environment.GetResourceString("ArgumentOutOfRange_Index")); + throw new ArgumentOutOfRangeException(nameof(startIndex), SR.ArgumentOutOfRange_Index); // Make sure that we allow startIndex == source.Length if (startIndex == source.Length) @@ -1028,22 +920,16 @@ namespace System.Globalization // 2nd half of this also catches when startIndex == MAXINT, so MAXINT - 0 + 1 == -1, which is < 0. if (count < 0 || startIndex - count + 1 < 0) - throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_Count")); + throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_Count); if (options == CompareOptions.OrdinalIgnoreCase) { - return source.LastIndexOf(value, startIndex, count, StringComparison.OrdinalIgnoreCase); + return LastIndexOfOrdinal(source, value, startIndex, count, ignoreCase: true); } - // to let the sorting DLL do the call optimization in case of Ascii strings, we check if the strings are in Ascii and then send the flag RESERVED_FIND_ASCII_STRING to - // the sorting DLL API SortFindString so sorting DLL don't have to check if the string is Ascii with every call to SortFindString. - return InternalFindNLSStringEx( - m_dataHandle, m_handleOrigin, m_sortName, - GetNativeCompareFlags(options) | Win32Native.FIND_FROMEND | ((source.IsAscii() && value.IsAscii()) ? RESERVED_FIND_ASCII_STRING : 0), - source, count, startIndex, value, value.Length, null); + return LastIndexOfCore(source, value, startIndex, count, options); } - //////////////////////////////////////////////////////////////////////// // // GetSortKey @@ -1062,63 +948,6 @@ namespace System.Globalization return CreateSortKey(source, CompareOptions.None); } - private SortKey CreateSortKey(String source, CompareOptions options) - { - if (source == null) { throw new ArgumentNullException(nameof(source)); } - Contract.EndContractBlock(); - - // Mask used to check if we have the right flags. - const CompareOptions ValidSortkeyCtorMaskOffFlags = ~(CompareOptions.IgnoreCase | - CompareOptions.IgnoreSymbols | - CompareOptions.IgnoreNonSpace | - CompareOptions.IgnoreWidth | - CompareOptions.IgnoreKanaType | - CompareOptions.StringSort); - - if ((options & ValidSortkeyCtorMaskOffFlags) != 0) - { - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidFlag"), nameof(options)); - } - byte[] keyData = null; - // The OS doesn't have quite the same behavior so we have to test for empty inputs - if (String.IsNullOrEmpty(source)) - { - // Empty strings get an empty sort key - keyData = EmptyArray.Value; - // Fake value to test though so we can verify our flags - source = "\x0000"; - } - - int flags = GetNativeCompareFlags(options); - - // Go ahead and call the OS - // First get the count - int length = InternalGetSortKey(m_dataHandle, m_handleOrigin, m_sortName, flags, source, source.Length, null, 0); - - // If there was an error, return an error - if (length == 0) - { - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidFlag"), nameof(source)); - } - - // If input was empty, return the empty byte[] we made earlier and skip this - if (keyData == null) - { - // Make an appropriate byte array - keyData = new byte[length]; - - // Fill up the array - length = InternalGetSortKey(m_dataHandle, m_handleOrigin, m_sortName, flags, source, source.Length, keyData, keyData.Length); - } - else - { - source = String.Empty; // back to original - } - - return new SortKey(Name, source, options, keyData); - } - - //////////////////////////////////////////////////////////////////////// // // Equals @@ -1159,34 +988,6 @@ namespace System.Globalization return (this.Name.GetHashCode()); } - // - // return hash value for the string according to the input CompareOptions - // - - public virtual int GetHashCode(string source, CompareOptions options) - { - if (source == null) - { - throw new ArgumentNullException(nameof(source)); - } - - if (options == CompareOptions.Ordinal) - { - return source.GetHashCode(); - } - - if (options == CompareOptions.OrdinalIgnoreCase) - { - return TextInfo.GetHashCodeOrdinalIgnoreCase(source); - } - - // - // GetHashCodeOfString does more parameters validation. basically will throw when - // having Ordinal, OrdinalIgnoreCase and StringSort - // - - return GetHashCodeOfString(source, options, false, 0); - } //////////////////////////////////////////////////////////////////////// // @@ -1214,11 +1015,6 @@ namespace System.Globalization //////////////////////////////////////////////////////////////////////// internal int GetHashCodeOfString(string source, CompareOptions options) { - return GetHashCodeOfString(source, options, false, 0); - } - - internal int GetHashCodeOfString(string source, CompareOptions options, bool forceRandomizedHashing, long additionalEntropy) - { // // Parameter validation // @@ -1229,18 +1025,36 @@ namespace System.Globalization if ((options & ValidHashCodeOfStringMaskOffFlags) != 0) { - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidFlag"), nameof(options)); + throw new ArgumentException(SR.Argument_InvalidFlag, nameof(options)); } Contract.EndContractBlock(); - if (0 == source.Length) + return GetHashCodeOfStringCore(source, options); + } + + public virtual int GetHashCode(string source, CompareOptions options) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + if (options == CompareOptions.Ordinal) + { + return source.GetHashCode(); + } + + if (options == CompareOptions.OrdinalIgnoreCase) { - return (0); + return TextInfo.GetHashCodeOrdinalIgnoreCase(source); } // - //////////////////////////////////////////////////////////////////////// - return (InternalGetGlobalizedHashCode(m_dataHandle, m_handleOrigin, m_sortName, source, source.Length, GetNativeCompareFlags(options), forceRandomizedHashing, additionalEntropy)); + // GetHashCodeOfString does more parameters validation. basically will throw when + // having Ordinal, OrdinalIgnoreCase and StringSort + // + + return GetHashCodeOfString(source, options); } //////////////////////////////////////////////////////////////////////// @@ -1251,83 +1065,30 @@ namespace System.Globalization // CompareInfo. // //////////////////////////////////////////////////////////////////////// - - public override String ToString() { return ("CompareInfo - " + this.Name); } -#if FEATURE_USE_LCID - public int LCID + public SortVersion Version { get { - return CultureInfo.GetCultureInfo(this.Name).LCID; - } - } -#endif + if (_sortVersion == null) + { + _sortVersion = GetSortVersion(); + } - internal static IntPtr InternalInitSortHandle(String localeName, out IntPtr handleOrigin) - { - return NativeInternalInitSortHandle(localeName, out handleOrigin); + return _sortVersion; + } } - [OptionalField(VersionAdded = 3)] - private SortVersion m_SortVersion; - - public SortVersion Version + public int LCID { get { - if (m_SortVersion == null) - { - Win32Native.NlsVersionInfoEx v = new Win32Native.NlsVersionInfoEx(); - v.dwNLSVersionInfoSize = Marshal.SizeOf(typeof(Win32Native.NlsVersionInfoEx)); - InternalGetNlsVersionEx(m_dataHandle, m_handleOrigin, m_sortName, ref v); - m_SortVersion = new SortVersion(v.dwNLSVersion, (v.dwEffectiveId != 0) ? v.dwEffectiveId : LCID, v.guidCustomVersion); - } - - return m_SortVersion; + return CultureInfo.GetCultureInfo(Name).LCID; } } - - [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] - [SuppressUnmanagedCodeSecurity] - [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool InternalGetNlsVersionEx(IntPtr handle, IntPtr handleOrigin, String localeName, ref Win32Native.NlsVersionInfoEx lpNlsVersionInformation); - - [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] - [SuppressUnmanagedCodeSecurity] - private static extern IntPtr NativeInternalInitSortHandle(String localeName, out IntPtr handleOrigin); - - // Get a locale sensitive sort hash code from native code -- COMNlsInfo::InternalGetGlobalizedHashCode - [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] - [SuppressUnmanagedCodeSecurity] - private static extern int InternalGetGlobalizedHashCode(IntPtr handle, IntPtr handleOrigin, string localeName, string source, int length, int dwFlags, bool forceRandomizedHashing, long additionalEntropy); - - // Use native API calls to see if this string is entirely defined -- COMNlsInfo::InternalIsSortable - [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] - [SuppressUnmanagedCodeSecurity] - [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool InternalIsSortable(IntPtr handle, IntPtr handleOrigin, String localeName, String source, int length); - - // Compare a string using the native API calls -- COMNlsInfo::InternalCompareString - [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] - [SuppressUnmanagedCodeSecurity] - private static extern int InternalCompareString(IntPtr handle, IntPtr handleOrigin, String localeName, String string1, int offset1, int length1, - String string2, int offset2, int length2, int flags); - - // InternalFindNLSStringEx parameters is not exactly matching kernel32::FindNLSStringEx parameters. - // Call through to NewApis::FindNLSStringEx so we can get the right behavior - [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] - [SuppressUnmanagedCodeSecurity] - private unsafe static extern int InternalFindNLSStringEx(IntPtr handle, IntPtr handleOrigin, String localeName, int flags, String source, int sourceCount, int startIndex, string target, int targetCount, int* matchLengthPtr); - - - // Call through to NewAPis::LCMapStringEx so we can get appropriate behavior for all platforms - [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] - [SuppressUnmanagedCodeSecurity] - private static extern int InternalGetSortKey(IntPtr handle, IntPtr handleOrigin, String localeName, int flags, String source, int sourceCount, byte[] target, int targetCount); } } diff --git a/src/mscorlib/corefx/System/Globalization/CultureData.Unix.cs b/src/mscorlib/src/System/Globalization/CultureData.Unix.cs similarity index 99% rename from src/mscorlib/corefx/System/Globalization/CultureData.Unix.cs rename to src/mscorlib/src/System/Globalization/CultureData.Unix.cs index ba96189..210f772 100644 --- a/src/mscorlib/corefx/System/Globalization/CultureData.Unix.cs +++ b/src/mscorlib/src/System/Globalization/CultureData.Unix.cs @@ -242,7 +242,7 @@ namespace System.Globalization private static string GetLanguageDisplayName(string cultureName) { - return new CultureInfo(cultureName).m_cultureData.GetLocaleInfo(cultureName, LocaleStringData.LocalizedDisplayName); + return new CultureInfo(cultureName)._cultureData.GetLocaleInfo(cultureName, LocaleStringData.LocalizedDisplayName); } private static string GetRegionDisplayName(string isoCountryCode) diff --git a/src/mscorlib/corefx/System/Globalization/CultureData.Windows.cs b/src/mscorlib/src/System/Globalization/CultureData.Windows.cs similarity index 76% rename from src/mscorlib/corefx/System/Globalization/CultureData.Windows.cs rename to src/mscorlib/src/System/Globalization/CultureData.Windows.cs index 0c264e5..6ce5293 100644 --- a/src/mscorlib/corefx/System/Globalization/CultureData.Windows.cs +++ b/src/mscorlib/src/System/Globalization/CultureData.Windows.cs @@ -13,6 +13,12 @@ using Internal.Runtime.Augments; namespace System.Globalization { +#if CORECLR + using StringList = List; +#else + using StringList = LowLevelList; +#endif + internal partial class CultureData { private const uint LOCALE_NOUSEROVERRIDE = 0x80000000; @@ -66,7 +72,7 @@ namespace System.Globalization string realNameBuffer = _sRealName; char* pBuffer = stackalloc char[LOCALE_NAME_MAX_LENGTH]; - result = Interop.mincore.GetLocaleInfoEx(realNameBuffer, LOCALE_SNAME, pBuffer, LOCALE_NAME_MAX_LENGTH); + result = GetLocaleInfoEx(realNameBuffer, LOCALE_SNAME, pBuffer, LOCALE_NAME_MAX_LENGTH); // Did it fail? if (result == 0) @@ -83,7 +89,7 @@ namespace System.Globalization // Check for neutrality, don't expect to fail // (buffer has our name in it, so we don't have to do the gc. stuff) - result = Interop.mincore.GetLocaleInfoEx(realNameBuffer, LOCALE_INEUTRAL | LOCALE_RETURN_NUMBER, pBuffer, sizeof(int) / sizeof(char)); + result = GetLocaleInfoEx(realNameBuffer, LOCALE_INEUTRAL | LOCALE_RETURN_NUMBER, pBuffer, sizeof(int) / sizeof(char)); if (result == 0) { return false; @@ -94,8 +100,8 @@ namespace System.Globalization // Note: Parents will be set dynamically - // Start by assuming the windows name'll be the same as the specific name since windows knows - // about specifics on all versions. Only for downlevel Neutral locales does this have to change. + // Start by assuming the windows name will be the same as the specific name since windows knows + // about specifics on all versions. Only for downlevel Neutral locales does this have to change. _sWindowsName = realNameBuffer; // Neutrals and non-neutrals are slightly different @@ -108,7 +114,7 @@ namespace System.Globalization // Specific locale name is whatever ResolveLocaleName (win7+) returns. // (Buffer has our name in it, and we can recycle that because windows resolves it before writing to the buffer) - result = Interop.mincore.ResolveLocaleName(realNameBuffer, pBuffer, LOCALE_NAME_MAX_LENGTH); + result = Interop.Kernel32.ResolveLocaleName(realNameBuffer, pBuffer, LOCALE_NAME_MAX_LENGTH); // 0 is failure, 1 is invariant (""), which we expect if (result < 1) @@ -136,7 +142,7 @@ namespace System.Globalization // If we are an alt sort locale then this is the same as the part before the _ in the windows name // This is for like de-DE_phoneb and es-ES_tradnl that hsouldn't have the _ part - result = Interop.mincore.GetLocaleInfoEx(realNameBuffer, LOCALE_ILANGUAGE | LOCALE_RETURN_NUMBER, pBuffer, sizeof(int) / sizeof(char)); + result = GetLocaleInfoEx(realNameBuffer, LOCALE_ILANGUAGE | LOCALE_RETURN_NUMBER, pBuffer, sizeof(int) / sizeof(char)); if (result == 0) { return false; @@ -159,6 +165,37 @@ namespace System.Globalization return true; } + // Wrappers around the GetLocaleInfoEx APIs which handle marshalling the returned + // data as either and Int or String. + internal static unsafe String GetLocaleInfoEx(String localeName, uint field) + { + // REVIEW: Determine the maximum size for the buffer + const int BUFFER_SIZE = 530; + + char* pBuffer = stackalloc char[BUFFER_SIZE]; + int resultCode = GetLocaleInfoEx(localeName, field, pBuffer, BUFFER_SIZE); + if (resultCode > 0) + { + return new String(pBuffer); + } + + return ""; + } + + internal static unsafe int GetLocaleInfoExInt(String localeName, uint field) + { + const uint LOCALE_RETURN_NUMBER = 0x20000000; + field |= LOCALE_RETURN_NUMBER; + int value = 0; + GetLocaleInfoEx(localeName, field, (char*) &value, sizeof(int)); + return value; + } + + internal static unsafe int GetLocaleInfoEx(string lpLocaleName, uint lcType, char* lpLCData, int cchData) + { + return Interop.Kernel32.GetLocaleInfoEx(lpLocaleName, lcType, (IntPtr)lpLCData, cchData); + } + private string GetLocaleInfo(LocaleStringData type) { Debug.Assert(_sWindowsName != null, "[CultureData.DoGetLocaleInfo] Expected _sWindowsName to be populated by already"); @@ -187,9 +224,7 @@ namespace System.Globalization // Ask OS for data, note that we presume it returns success, so we have to know that // sWindowsName is valid before calling. Debug.Assert(_sWindowsName != null, "[CultureData.DoGetLocaleInfoInt] Expected _sWindowsName to be populated by already"); - int result = Interop.mincore.GetLocaleInfoExInt(_sWindowsName, lctype); - - return result; + return GetLocaleInfoExInt(_sWindowsName, lctype); } private int[] GetLocaleInfo(LocaleGroupingData type) @@ -210,7 +245,7 @@ namespace System.Globalization const uint LOCALE_IFIRSTDAYOFWEEK = 0x0000100C; - int result = Interop.mincore.GetLocaleInfoExInt(_sWindowsName, LOCALE_IFIRSTDAYOFWEEK | (!UseUserOverride ? LOCALE_NOUSEROVERRIDE : 0)); + int result = GetLocaleInfoExInt(_sWindowsName, LOCALE_IFIRSTDAYOFWEEK | (!UseUserOverride ? LOCALE_NOUSEROVERRIDE : 0)); // Win32 and .NET disagree on the numbering for days of the week, so we have to convert. return ConvertFirstDayOfWeekMonToSun(result); @@ -250,8 +285,12 @@ namespace System.Globalization GCHandle contextHandle = GCHandle.Alloc(context); try { +#if CORECLR + Interop.Kernel32.EnumSystemLocalesEx(EnumSystemLocalesProc, LOCALE_SPECIFICDATA | LOCALE_SUPPLEMENTAL, (IntPtr)contextHandle, IntPtr.Zero); +#else IntPtr callback = AddrofIntrinsics.AddrOf>(EnumSystemLocalesProc); - Interop.mincore.EnumSystemLocalesEx(callback, LOCALE_SPECIFICDATA | LOCALE_SUPPLEMENTAL, (IntPtr)contextHandle, IntPtr.Zero); + Interop.Kernel32.EnumSystemLocalesEx(callback, LOCALE_SPECIFICDATA | LOCALE_SUPPLEMENTAL, (IntPtr)contextHandle, IntPtr.Zero); +#endif } finally { @@ -333,7 +372,7 @@ namespace System.Globalization } // Ask OS for data - string result = Interop.mincore.GetLocaleInfoEx(localeName, lctype); + string result = GetLocaleInfoEx(localeName, lctype); if (result == null) { // Failed, just use empty string @@ -502,14 +541,16 @@ namespace System.Globalization } // EnumSystemLocaleEx callback. +#if !CORECLR [NativeCallable(CallingConvention = CallingConvention.StdCall)] +#endif private static unsafe Interop.BOOL EnumSystemLocalesProc(IntPtr lpLocaleString, uint flags, IntPtr contextHandle) { EnumLocaleData context = (EnumLocaleData)((GCHandle)contextHandle).Target; try { string cultureName = new string((char*)lpLocaleString); - string regionName = Interop.mincore.GetLocaleInfoEx(cultureName, LOCALE_SISO3166CTRYNAME); + string regionName = GetLocaleInfoEx(cultureName, LOCALE_SISO3166CTRYNAME); if (regionName != null && regionName.Equals(context.regionName, StringComparison.OrdinalIgnoreCase)) { context.cultureName = cultureName; @@ -524,14 +565,34 @@ namespace System.Globalization } } + // EnumSystemLocaleEx callback. +#if !CORECLR + [NativeCallable(CallingConvention = CallingConvention.StdCall)] +#endif + private static unsafe Interop.BOOL EnumAllSystemLocalesProc(IntPtr lpLocaleString, uint flags, IntPtr contextHandle) + { + EnumData context = (EnumData)((GCHandle)contextHandle).Target; + try + { + context.strings.Add(new string((char*)lpLocaleString)); + return Interop.BOOL.TRUE; + } + catch (Exception) + { + return Interop.BOOL.FALSE; + } + } + // Context for EnumTimeFormatsEx callback. private class EnumData { - public LowLevelList strings; + public StringList strings; } // EnumTimeFormatsEx callback itself. +#if !CORECLR [NativeCallable(CallingConvention = CallingConvention.StdCall)] +#endif private static unsafe Interop.BOOL EnumTimeCallback(IntPtr lpTimeFormatString, IntPtr lParam) { EnumData context = (EnumData)((GCHandle)lParam).Target; @@ -553,14 +614,17 @@ namespace System.Globalization const uint LOCALE_STIMEFORMAT = 0x00001003; EnumData data = new EnumData(); - data.strings = new LowLevelList(); - + data.strings = new StringList(); GCHandle dataHandle = GCHandle.Alloc(data); try { +#if CORECLR + Interop.Kernel32.EnumTimeFormatsEx(EnumTimeCallback, localeName, (uint)dwFlags, (IntPtr)dataHandle); +#else // Now call the enumeration API. Work is done by our callback function IntPtr callback = AddrofIntrinsics.AddrOf>(EnumTimeCallback); - Interop.mincore.EnumTimeFormatsEx(callback, localeName, (uint)dwFlags, (IntPtr)dataHandle); + Interop.Kernel32.EnumTimeFormatsEx(callback, localeName, (uint)dwFlags, (IntPtr)dataHandle); +#endif } finally { @@ -599,14 +663,22 @@ namespace System.Globalization return null; } - private int LocaleNameToLCID(string cultureName) + private static int LocaleNameToLCID(string cultureName) { - return GetLocaleInfo(LocaleNumberData.LanguageId); + return Interop.Kernel32.LocaleNameToLCID(cultureName, Interop.Kernel32.LOCALE_ALLOW_NEUTRAL_NAMES); } - private static string LCIDToLocaleName(int culture) + private static unsafe string LCIDToLocaleName(int culture) { - throw new NotImplementedException(); + char *pBuffer = stackalloc char[Interop.Kernel32.LOCALE_NAME_MAX_LENGTH + 1]; // +1 for the null termination + int length = Interop.Kernel32.LCIDToLocaleName(culture, pBuffer, Interop.Kernel32.LOCALE_NAME_MAX_LENGTH + 1, Interop.Kernel32.LOCALE_ALLOW_NEUTRAL_NAMES); + + if (length > 0) + { + return new String(pBuffer); + } + + return null; } private int GetAnsiCodePage(string cultureName) @@ -646,7 +718,59 @@ namespace System.Globalization private static CultureInfo[] EnumCultures(CultureTypes types) { - throw new NotImplementedException(); + uint flags = 0; + +#pragma warning disable 618 + if ((types & (CultureTypes.FrameworkCultures | CultureTypes.InstalledWin32Cultures | CultureTypes.ReplacementCultures)) != 0) + { + flags |= Interop.Kernel32.LOCALE_NEUTRALDATA | Interop.Kernel32.LOCALE_SPECIFICDATA; + } +#pragma warning restore 618 + + if ((types & CultureTypes.NeutralCultures) != 0) + { + flags |= Interop.Kernel32.LOCALE_NEUTRALDATA; + } + + if ((types & CultureTypes.SpecificCultures) != 0) + { + flags |= Interop.Kernel32.LOCALE_SPECIFICDATA; + } + + if ((types & CultureTypes.UserCustomCulture) != 0) + { + flags |= Interop.Kernel32.LOCALE_SUPPLEMENTAL; + } + + if ((types & CultureTypes.ReplacementCultures) != 0) + { + flags |= Interop.Kernel32.LOCALE_SUPPLEMENTAL; + } + + EnumData context = new EnumData(); + context.strings = new StringList(); + GCHandle contextHandle = GCHandle.Alloc(context); + try + { +#if CORECLR + Interop.Kernel32.EnumSystemLocalesEx(EnumAllSystemLocalesProc, flags, (IntPtr)contextHandle, IntPtr.Zero); +#else + IntPtr callback = AddrofIntrinsics.AddrOf>(EnumAllSystemLocalesProc); + Interop.Kernel32.EnumSystemLocalesEx(callback, flags, (IntPtr)contextHandle, IntPtr.Zero); +#endif + } + finally + { + contextHandle.Free(); + } + + CultureInfo [] cultures = new CultureInfo[context.strings.Count]; + for (int i = 0; i < cultures.Length; i++) + { + cultures[i] = new CultureInfo(context.strings[i]); + } + + return cultures; } private string GetConsoleFallbackName(string cultureName) @@ -656,17 +780,43 @@ namespace System.Globalization internal bool IsFramework { - get { throw new NotImplementedException(); } + get { return false; } } internal bool IsWin32Installed { - get { throw new NotImplementedException(); } + get { return true; } } internal bool IsReplacementCulture { - get { throw new NotImplementedException(); } + get + { + EnumData context = new EnumData(); + context.strings = new StringList(); + GCHandle contextHandle = GCHandle.Alloc(context); + try + { +#if CORECLR + Interop.Kernel32.EnumSystemLocalesEx(EnumAllSystemLocalesProc, Interop.Kernel32.LOCALE_REPLACEMENT, (IntPtr)contextHandle, IntPtr.Zero); +#else + IntPtr callback = AddrofIntrinsics.AddrOf>(EnumAllSystemLocalesProc); + Interop.Kernel32.EnumSystemLocalesEx(callback, Interop.Kernel32.LOCALE_REPLACEMENT, (IntPtr)contextHandle, IntPtr.Zero); +#endif + } + finally + { + contextHandle.Free(); + } + + for (int i=0; i; + using StringCultureDataDictionary = Dictionary; + using LcidToCultureNameDictionary = Dictionary; + using Lock = Object; +#else + using StringStringDictionary = LowLevelDictionary; + using StringCultureDataDictionary = LowLevelDictionary; + using LcidToCultureNameDictionary = LowLevelDictionary; +#endif // // List of culture data @@ -47,504 +51,262 @@ namespace System.Globalization // en if you pass in en // de-DE if you pass in de-DE_phoneb // - - // StructLayout is needed here otherwise compiler can re-arrange the fields. - // We have to keep this in-sync with the definition in comnlsinfo.h - // - // WARNING WARNING WARNING - // - // WARNING: Anything changed here also needs to be updated on the native side (object.h see type CultureDataBaseObject) - // WARNING: The type loader will rearrange class member offsets so the mscorwks!CultureDataBaseObject - // WARNING: must be manually structured to match the true loaded class layout - // - [FriendAccessAllowed] - internal class CultureData + internal partial class CultureData { private const int undef = -1; // Override flag - private String sRealName; // Name you passed in (ie: en-US, en, or de-DE_phoneb) - private String sWindowsName; // Name OS thinks the object is (ie: de-DE_phoneb, or en-US (even if en was passed in)) + private String _sRealName; // Name you passed in (ie: en-US, en, or de-DE_phoneb) + private String _sWindowsName; // Name OS thinks the object is (ie: de-DE_phoneb, or en-US (even if en was passed in)) // Identity - private String sName; // locale name (ie: en-us, NO sort info, but could be neutral) - private String sParent; // Parent name (which may be a custom locale/culture) - private String sLocalizedDisplayName; // Localized pretty name for this locale - private String sEnglishDisplayName; // English pretty name for this locale - private String sNativeDisplayName; // Native pretty name for this locale - private String sSpecificCulture; // The culture name to be used in CultureInfo.CreateSpecificCulture(), en-US form if neutral, sort name if sort + private String _sName; // locale name (ie: en-us, NO sort info, but could be neutral) + private String _sParent; // Parent name (which may be a custom locale/culture) + private String _sLocalizedDisplayName; // Localized pretty name for this locale + private String _sEnglishDisplayName; // English pretty name for this locale + private String _sNativeDisplayName; // Native pretty name for this locale + private String _sSpecificCulture; // The culture name to be used in CultureInfo.CreateSpecificCulture(), en-US form if neutral, sort name if sort // Language - private String sISO639Language; // ISO 639 Language Name - private String sLocalizedLanguage; // Localized name for this language - private String sEnglishLanguage; // English name for this language - private String sNativeLanguage; // Native name of this language + private String _sISO639Language; // ISO 639 Language Name + private String _sISO639Language2; // ISO 639 Language Name + private String _sLocalizedLanguage; // Localized name for this language + private String _sEnglishLanguage; // English name for this language + private String _sNativeLanguage; // Native name of this language + private String _sAbbrevLang; // abbreviated language name (Windows Language Name) ex: ENU + private string _sConsoleFallbackName; // The culture name for the console fallback UI culture + private int _iInputLanguageHandle=undef;// input language handle // Region - private String sRegionName; // (RegionInfo) - private int iGeoId = undef; // GeoId - private String sLocalizedCountry; // localized country name - private String sEnglishCountry; // english country name (RegionInfo) - private String sNativeCountry; // native country name - private String sISO3166CountryName; // ISO 3166 (RegionInfo), ie: US + private String _sRegionName; // (RegionInfo) + private String _sLocalizedCountry; // localized country name + private String _sEnglishCountry; // english country name (RegionInfo) + private String _sNativeCountry; // native country name + private String _sISO3166CountryName; // ISO 3166 (RegionInfo), ie: US + private String _sISO3166CountryName2; // 3 char ISO 3166 country name 2 2(RegionInfo) ex: USA (ISO) + private int _iGeoId = undef; // GeoId // Numbers - private String sPositiveSign; // (user can override) positive sign - private String sNegativeSign; // (user can override) negative sign - private String[] saNativeDigits; // (user can override) native characters for digits 0-9 + private String _sPositiveSign; // (user can override) positive sign + private String _sNegativeSign; // (user can override) negative sign // (nfi populates these 5, don't have to be = undef) - private int iDigitSubstitution; // (user can override) Digit substitution 0=context, 1=none/arabic, 2=Native/national (2 seems to be unused) - private int iLeadingZeros; // (user can override) leading zeros 0 = no leading zeros, 1 = leading zeros - private int iDigits; // (user can override) number of fractional digits - private int iNegativeNumber; // (user can override) negative number format - private int[] waGrouping; // (user can override) grouping of digits - private String sDecimalSeparator; // (user can override) decimal separator - private String sThousandSeparator; // (user can override) thousands separator - private String sNaN; // Not a Number - private String sPositiveInfinity; // + Infinity - private String sNegativeInfinity; // - Infinity + private int _iDigits; // (user can override) number of fractional digits + private int _iNegativeNumber; // (user can override) negative number format + private int[] _waGrouping; // (user can override) grouping of digits + private String _sDecimalSeparator; // (user can override) decimal separator + private String _sThousandSeparator; // (user can override) thousands separator + private String _sNaN; // Not a Number + private String _sPositiveInfinity; // + Infinity + private String _sNegativeInfinity; // - Infinity // Percent - private int iNegativePercent = undef; // Negative Percent (0-3) - private int iPositivePercent = undef; // Positive Percent (0-11) - private String sPercent; // Percent (%) symbol - private String sPerMille; // PerMille (‰) symbol + private int _iNegativePercent = undef; // Negative Percent (0-3) + private int _iPositivePercent = undef; // Positive Percent (0-11) + private String _sPercent; // Percent (%) symbol + private String _sPerMille; // PerMille symbol // Currency - private String sCurrency; // (user can override) local monetary symbol - private String sIntlMonetarySymbol; // international monetary symbol (RegionInfo) - private String sEnglishCurrency; // English name for this currency - private String sNativeCurrency; // Native name for this currency + private String _sCurrency; // (user can override) local monetary symbol + private String _sIntlMonetarySymbol; // international monetary symbol (RegionInfo) + private String _sEnglishCurrency; // English name for this currency + private String _sNativeCurrency; // Native name for this currency // (nfi populates these 4, don't have to be = undef) - private int iCurrencyDigits; // (user can override) # local monetary fractional digits - private int iCurrency; // (user can override) positive currency format - private int iNegativeCurrency; // (user can override) negative currency format - private int[] waMonetaryGrouping; // (user can override) monetary grouping of digits - private String sMonetaryDecimal; // (user can override) monetary decimal separator - private String sMonetaryThousand; // (user can override) monetary thousands separator + private int _iCurrencyDigits; // (user can override) # local monetary fractional digits + private int _iCurrency; // (user can override) positive currency format + private int _iNegativeCurrency; // (user can override) negative currency format + private int[] _waMonetaryGrouping; // (user can override) monetary grouping of digits + private String _sMonetaryDecimal; // (user can override) monetary decimal separator + private String _sMonetaryThousand; // (user can override) monetary thousands separator // Misc - private int iMeasure = undef; // (user can override) system of measurement 0=metric, 1=US (RegionInfo) - private String sListSeparator; // (user can override) list separator - // private int iPaperSize ; // default paper size (RegionInfo) + private int _iMeasure = undef; // (user can override) system of measurement 0=metric, 1=US (RegionInfo) + private String _sListSeparator; // (user can override) list separator // Time - private String sAM1159; // (user can override) AM designator - private String sPM2359; // (user can override) PM designator - private String sTimeSeparator; - private volatile String[] saLongTimes; // (user can override) time format - private volatile String[] saShortTimes; // short time format - private volatile String[] saDurationFormats; // time duration format + private String _sAM1159; // (user can override) AM designator + private String _sPM2359; // (user can override) PM designator + private String _sTimeSeparator; + private volatile String[] _saLongTimes; // (user can override) time format + private volatile String[] _saShortTimes; // short time format + private volatile String[] _saDurationFormats; // time duration format // Calendar specific data - private int iFirstDayOfWeek = undef; // (user can override) first day of week (gregorian really) - private int iFirstWeekOfYear = undef; // (user can override) first week of year (gregorian really) - private volatile int[] waCalendars; // all available calendar type(s). The first one is the default calendar + private int _iFirstDayOfWeek = undef; // (user can override) first day of week (gregorian really) + private int _iFirstWeekOfYear = undef; // (user can override) first week of year (gregorian really) + private volatile CalendarId[] _waCalendars; // all available calendar type(s). The first one is the default calendar // Store for specific data about each calendar - private CalendarData[] calendars; // Store for specific calendar data + private CalendarData[] _calendars; // Store for specific calendar data // Text information - private int iReadingLayout = undef; // Reading layout data + private int _iReadingLayout = undef; // Reading layout data // 0 - Left to right (eg en-US) // 1 - Right to left (eg arabic locales) // 2 - Vertical top to bottom with columns to the left and also left to right (ja-JP locales) // 3 - Vertical top to bottom with columns proceeding to the right - private String sTextInfo; // Text info name to use for custom - private String sCompareInfo; // Compare info name (including sorting key) to use if custom - private String sScripts; // Typical Scripts for this locale (latn;cyrl; etc) - - private int iDefaultAnsiCodePage = undef; // default ansi code page ID (ACP) - private int iDefaultOemCodePage = undef; // default oem code page ID (OCP or OEM) - private int iDefaultMacCodePage = undef; // default macintosh code page - private int iDefaultEbcdicCodePage = undef; // default EBCDIC code page - - // These are desktop only, not coreclr - private int iLanguage; // locale ID (0409) - NO sort information - private String sAbbrevLang; // abbreviated language name (Windows Language Name) ex: ENU - private String sAbbrevCountry; // abbreviated country name (RegionInfo) (Windows Region Name) ex: USA - private String sISO639Language2; // 3 char ISO 639 lang name 2 ex: eng - private String sISO3166CountryName2; // 3 char ISO 3166 country name 2 2(RegionInfo) ex: USA (ISO) - private int iInputLanguageHandle = undef;// input language handle - private String sConsoleFallbackName; // The culture name for the console fallback UI culture - private String sKeyboardsToInstall; // Keyboard installation string. - private String fontSignature; // Font signature (16 WORDS) - - // The bools all need to be in one spot - private bool bUseOverrides; // use user overrides? - private bool bNeutral; // Flags for the culture (ie: neutral or not right now) - private bool bWin32Installed; // Flags indicate if the culture is Win32 installed - private bool bFramework; // Flags for indicate if the culture is one of Whidbey cultures + // CoreCLR depends on this even though its not exposed publicly. + + private int _iDefaultAnsiCodePage = undef; // default ansi code page ID (ACP) + private int _iDefaultOemCodePage = undef; // default oem code page ID (OCP or OEM) + private int _iDefaultMacCodePage = undef; // default macintosh code page + private int _iDefaultEbcdicCodePage = undef; // default EBCDIC code page + + private int _iLanguage; // locale ID (0409) - NO sort information + private bool _bUseOverrides; // use user overrides? + private bool _bNeutral; // Flags for the culture (ie: neutral or not right now) // Region Name to Culture Name mapping table // (In future would be nice to be in registry or something) //Using a property so we avoid creating the dictionary untill we need it - private static Dictionary RegionNames + private static StringStringDictionary RegionNames { get { if (s_RegionNames == null) { - var regionNames = new Dictionary { - { "029", "en-029" }, - { "AE", "ar-AE" }, - { "AF", "prs-AF" }, - { "AL", "sq-AL" }, - { "AM", "hy-AM" }, - { "AR", "es-AR" }, - { "AT", "de-AT" }, - { "AU", "en-AU" }, - { "AZ", "az-Cyrl-AZ" }, - { "BA", "bs-Latn-BA" }, - { "BD", "bn-BD" }, - { "BE", "nl-BE" }, - { "BG", "bg-BG" }, - { "BH", "ar-BH" }, - { "BN", "ms-BN" }, - { "BO", "es-BO" }, - { "BR", "pt-BR" }, - { "BY", "be-BY" }, - { "BZ", "en-BZ" }, - { "CA", "en-CA" }, - { "CH", "it-CH" }, - { "CL", "es-CL" }, - { "CN", "zh-CN" }, - { "CO", "es-CO" }, - { "CR", "es-CR" }, - { "CS", "sr-Cyrl-CS" }, - { "CZ", "cs-CZ" }, - { "DE", "de-DE" }, - { "DK", "da-DK" }, - { "DO", "es-DO" }, - { "DZ", "ar-DZ" }, - { "EC", "es-EC" }, - { "EE", "et-EE" }, - { "EG", "ar-EG" }, - { "ES", "es-ES" }, - { "ET", "am-ET" }, - { "FI", "fi-FI" }, - { "FO", "fo-FO" }, - { "FR", "fr-FR" }, - { "GB", "en-GB" }, - { "GE", "ka-GE" }, - { "GL", "kl-GL" }, - { "GR", "el-GR" }, - { "GT", "es-GT" }, - { "HK", "zh-HK" }, - { "HN", "es-HN" }, - { "HR", "hr-HR" }, - { "HU", "hu-HU" }, - { "ID", "id-ID" }, - { "IE", "en-IE" }, - { "IL", "he-IL" }, - { "IN", "hi-IN" }, - { "IQ", "ar-IQ" }, - { "IR", "fa-IR" }, - { "IS", "is-IS" }, - { "IT", "it-IT" }, - { "IV", "" }, - { "JM", "en-JM" }, - { "JO", "ar-JO" }, - { "JP", "ja-JP" }, - { "KE", "sw-KE" }, - { "KG", "ky-KG" }, - { "KH", "km-KH" }, - { "KR", "ko-KR" }, - { "KW", "ar-KW" }, - { "KZ", "kk-KZ" }, - { "LA", "lo-LA" }, - { "LB", "ar-LB" }, - { "LI", "de-LI" }, - { "LK", "si-LK" }, - { "LT", "lt-LT" }, - { "LU", "lb-LU" }, - { "LV", "lv-LV" }, - { "LY", "ar-LY" }, - { "MA", "ar-MA" }, - { "MC", "fr-MC" }, - { "ME", "sr-Latn-ME" }, - { "MK", "mk-MK" }, - { "MN", "mn-MN" }, - { "MO", "zh-MO" }, - { "MT", "mt-MT" }, - { "MV", "dv-MV" }, - { "MX", "es-MX" }, - { "MY", "ms-MY" }, - { "NG", "ig-NG" }, - { "NI", "es-NI" }, - { "NL", "nl-NL" }, - { "NO", "nn-NO" }, - { "NP", "ne-NP" }, - { "NZ", "en-NZ" }, - { "OM", "ar-OM" }, - { "PA", "es-PA" }, - { "PE", "es-PE" }, - { "PH", "en-PH" }, - { "PK", "ur-PK" }, - { "PL", "pl-PL" }, - { "PR", "es-PR" }, - { "PT", "pt-PT" }, - { "PY", "es-PY" }, - { "QA", "ar-QA" }, - { "RO", "ro-RO" }, - { "RS", "sr-Latn-RS" }, - { "RU", "ru-RU" }, - { "RW", "rw-RW" }, - { "SA", "ar-SA" }, - { "SE", "sv-SE" }, - { "SG", "zh-SG" }, - { "SI", "sl-SI" }, - { "SK", "sk-SK" }, - { "SN", "wo-SN" }, - { "SV", "es-SV" }, - { "SY", "ar-SY" }, - { "TH", "th-TH" }, - { "TJ", "tg-Cyrl-TJ" }, - { "TM", "tk-TM" }, - { "TN", "ar-TN" }, - { "TR", "tr-TR" }, - { "TT", "en-TT" }, - { "TW", "zh-TW" }, - { "UA", "uk-UA" }, - { "US", "en-US" }, - { "UY", "es-UY" }, - { "UZ", "uz-Cyrl-UZ" }, - { "VE", "es-VE" }, - { "VN", "vi-VN" }, - { "YE", "ar-YE" }, - { "ZA", "af-ZA" }, - { "ZW", "en-ZW" } - }; - s_RegionNames = regionNames; - } - return s_RegionNames; - } - } - private volatile static Dictionary s_RegionNames; - - ///////////////////////////////////////////////////////////////////////// - // Build our invariant information - // - // We need an invariant instance, which we build hard-coded - ///////////////////////////////////////////////////////////////////////// - internal static CultureData Invariant - { - get - { - if (s_Invariant == null) - { - // Make a new culturedata - CultureData invariant = new CultureData(); - - // Call the native code to get the value of bWin32Installed. - // For versions <= Vista, we set this to false for compatibility with v2. - // For Windows 7, the flag is true. - invariant.bUseOverrides = false; - invariant.sRealName = ""; - - // Ask the native code to fill it out for us, we only need the field IsWin32Installed - nativeInitCultureData(invariant); - - // Basics - // Note that we override the resources since this IS NOT supposed to change (by definition) - invariant.bUseOverrides = false; - invariant.sRealName = ""; // Name you passed in (ie: en-US, en, or de-DE_phoneb) - invariant.sWindowsName = ""; // Name OS thinks the object is (ie: de-DE_phoneb, or en-US (even if en was passed in)) - - // Identity - invariant.sName = ""; // locale name (ie: en-us) - invariant.sParent = ""; // Parent name (which may be a custom locale/culture) - invariant.bNeutral = false; // Flags for the culture (ie: neutral or not right now) - // Don't set invariant.bWin32Installed, we used nativeInitCultureData for that. - invariant.bFramework = true; - - invariant.sEnglishDisplayName = "Invariant Language (Invariant Country)"; // English pretty name for this locale - invariant.sNativeDisplayName = "Invariant Language (Invariant Country)"; // Native pretty name for this locale - invariant.sSpecificCulture = ""; // The culture name to be used in CultureInfo.CreateSpecificCulture() - - // Language - invariant.sISO639Language = "iv"; // ISO 639 Language Name - invariant.sLocalizedLanguage = "Invariant Language"; // Display name for this Language - invariant.sEnglishLanguage = "Invariant Language"; // English name for this language - invariant.sNativeLanguage = "Invariant Language"; // Native name of this language - - // Region - invariant.sRegionName = "IV"; // (RegionInfo) - // Unused for now: - // invariant.iCountry =1; // country code (RegionInfo) - invariant.iGeoId = 244; // GeoId (Windows Only) - invariant.sEnglishCountry = "Invariant Country"; // english country name (RegionInfo) - invariant.sNativeCountry = "Invariant Country"; // native country name (Windows Only) - invariant.sISO3166CountryName = "IV"; // (RegionInfo), ie: US - - // Numbers - invariant.sPositiveSign = "+"; // positive sign - invariant.sNegativeSign = "-"; // negative sign - invariant.saNativeDigits = new String[] { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" }; // native characters for digits 0-9 - invariant.iDigitSubstitution = 1; // Digit substitution 0=context, 1=none/arabic, 2=Native/national (2 seems to be unused) (Windows Only) - invariant.iLeadingZeros = 1; // leading zeros 0=no leading zeros, 1=leading zeros - invariant.iDigits = 2; // number of fractional digits - invariant.iNegativeNumber = 1; // negative number format - invariant.waGrouping = new int[] { 3 }; // grouping of digits - invariant.sDecimalSeparator = "."; // decimal separator - invariant.sThousandSeparator = ","; // thousands separator - invariant.sNaN = "NaN"; // Not a Number - invariant.sPositiveInfinity = "Infinity"; // + Infinity - invariant.sNegativeInfinity = "-Infinity"; // - Infinity - - // Percent - invariant.iNegativePercent = 0; // Negative Percent (0-3) - invariant.iPositivePercent = 0; // Positive Percent (0-11) - invariant.sPercent = "%"; // Percent (%) symbol - invariant.sPerMille = "\x2030"; // PerMille(‰) symbol - - // Currency - invariant.sCurrency = "\x00a4"; // local monetary symbol "¤: for international monetary symbol - invariant.sIntlMonetarySymbol = "XDR"; // international monetary symbol (RegionInfo) - invariant.sEnglishCurrency = "International Monetary Fund"; // English name for this currency (Windows Only) - invariant.sNativeCurrency = "International Monetary Fund"; // Native name for this currency (Windows Only) - invariant.iCurrencyDigits = 2; // # local monetary fractional digits - invariant.iCurrency = 0; // positive currency format - invariant.iNegativeCurrency = 0; // negative currency format - invariant.waMonetaryGrouping = new int[] { 3 }; // monetary grouping of digits - invariant.sMonetaryDecimal = "."; // monetary decimal separator - invariant.sMonetaryThousand = ","; // monetary thousands separator - - // Misc - invariant.iMeasure = 0; // system of measurement 0=metric, 1=US (RegionInfo) - invariant.sListSeparator = ","; // list separator - // Unused for now: - // invariant.iPaperSize =9; // default paper size (RegionInfo) - // invariant.waFontSignature ="\x0002\x0000\x0000\x0000\x0000\x0000\x0000\x8000\x0001\x0000\x0000\x8000\x0001\x0000\x0000\x8000"; // Font signature (16 WORDS) (Windows Only) - - // Time - invariant.sAM1159 = "AM"; // AM designator - invariant.sPM2359 = "PM"; // PM designator - invariant.saLongTimes = new String[] { "HH:mm:ss" }; // time format - invariant.saShortTimes = new String[] { "HH:mm", "hh:mm tt", "H:mm", "h:mm tt" }; // short time format - invariant.saDurationFormats = new String[] { "HH:mm:ss" }; // time duration format - - // Calendar specific data - invariant.iFirstDayOfWeek = 0; // first day of week - invariant.iFirstWeekOfYear = 0; // first week of year - invariant.waCalendars = new int[] { (int)CalendarId.GREGORIAN }; // all available calendar type(s). The first one is the default calendar - - // Store for specific data about each calendar - invariant.calendars = new CalendarData[CalendarData.MAX_CALENDARS]; - invariant.calendars[0] = CalendarData.Invariant; - - // Text information - invariant.iReadingLayout = 0; // Reading Layout = RTL - - invariant.sTextInfo = ""; // Text info name to use for custom - invariant.sCompareInfo = ""; // Compare info name (including sorting key) to use if custom - invariant.sScripts = "Latn;"; // Typical Scripts for this locale (latn,cyrl, etc) - - invariant.iLanguage = 0x007f; // locale ID (0409) - NO sort information - invariant.iDefaultAnsiCodePage = 1252; // default ansi code page ID (ACP) - invariant.iDefaultOemCodePage = 437; // default oem code page ID (OCP or OEM) - invariant.iDefaultMacCodePage = 10000; // default macintosh code page - invariant.iDefaultEbcdicCodePage = 037; // default EBCDIC code page - invariant.sAbbrevLang = "IVL"; // abbreviated language name (Windows Language Name) - invariant.sAbbrevCountry = "IVC"; // abbreviated country name (RegionInfo) (Windows Region Name) - invariant.sISO639Language2 = "ivl"; // 3 char ISO 639 lang name 2 - invariant.sISO3166CountryName2 = "ivc"; // 3 char ISO 3166 country name 2 2(RegionInfo) - invariant.iInputLanguageHandle = 0x007f; // input language handle - invariant.sConsoleFallbackName = ""; // The culture name for the console fallback UI culture - invariant.sKeyboardsToInstall = "0409:00000409"; // Keyboard installation string. - // Remember it - s_Invariant = invariant; - } - return s_Invariant; - } - } - private volatile static CultureData s_Invariant; - - /////////////// - // Constructors // - /////////////// - // Cache of cultures we've already looked up - private static volatile Dictionary s_cachedCultures; + StringStringDictionary regionNames = new StringStringDictionary(211 /* prime */); + + regionNames.Add("029", "en-029"); + regionNames.Add("AE", "ar-AE"); + regionNames.Add("AF", "prs-AF"); + regionNames.Add("AL", "sq-AL"); + regionNames.Add("AM", "hy-AM"); + regionNames.Add("AR", "es-AR"); + regionNames.Add("AT", "de-AT"); + regionNames.Add("AU", "en-AU"); + regionNames.Add("AZ", "az-Cyrl-AZ"); + regionNames.Add("BA", "bs-Latn-BA"); + regionNames.Add("BD", "bn-BD"); + regionNames.Add("BE", "nl-BE"); + regionNames.Add("BG", "bg-BG"); + regionNames.Add("BH", "ar-BH"); + regionNames.Add("BN", "ms-BN"); + regionNames.Add("BO", "es-BO"); + regionNames.Add("BR", "pt-BR"); + regionNames.Add("BY", "be-BY"); + regionNames.Add("BZ", "en-BZ"); + regionNames.Add("CA", "en-CA"); + regionNames.Add("CH", "it-CH"); + regionNames.Add("CL", "es-CL"); + regionNames.Add("CN", "zh-CN"); + regionNames.Add("CO", "es-CO"); + regionNames.Add("CR", "es-CR"); + regionNames.Add("CS", "sr-Cyrl-CS"); + regionNames.Add("CZ", "cs-CZ"); + regionNames.Add("DE", "de-DE"); + regionNames.Add("DK", "da-DK"); + regionNames.Add("DO", "es-DO"); + regionNames.Add("DZ", "ar-DZ"); + regionNames.Add("EC", "es-EC"); + regionNames.Add("EE", "et-EE"); + regionNames.Add("EG", "ar-EG"); + regionNames.Add("ES", "es-ES"); + regionNames.Add("ET", "am-ET"); + regionNames.Add("FI", "fi-FI"); + regionNames.Add("FO", "fo-FO"); + regionNames.Add("FR", "fr-FR"); + regionNames.Add("GB", "en-GB"); + regionNames.Add("GE", "ka-GE"); + regionNames.Add("GL", "kl-GL"); + regionNames.Add("GR", "el-GR"); + regionNames.Add("GT", "es-GT"); + regionNames.Add("HK", "zh-HK"); + regionNames.Add("HN", "es-HN"); + regionNames.Add("HR", "hr-HR"); + regionNames.Add("HU", "hu-HU"); + regionNames.Add("ID", "id-ID"); + regionNames.Add("IE", "en-IE"); + regionNames.Add("IL", "he-IL"); + regionNames.Add("IN", "hi-IN"); + regionNames.Add("IQ", "ar-IQ"); + regionNames.Add("IR", "fa-IR"); + regionNames.Add("IS", "is-IS"); + regionNames.Add("IT", "it-IT"); + regionNames.Add("IV", ""); + regionNames.Add("JM", "en-JM"); + regionNames.Add("JO", "ar-JO"); + regionNames.Add("JP", "ja-JP"); + regionNames.Add("KE", "sw-KE"); + regionNames.Add("KG", "ky-KG"); + regionNames.Add("KH", "km-KH"); + regionNames.Add("KR", "ko-KR"); + regionNames.Add("KW", "ar-KW"); + regionNames.Add("KZ", "kk-KZ"); + regionNames.Add("LA", "lo-LA"); + regionNames.Add("LB", "ar-LB"); + regionNames.Add("LI", "de-LI"); + regionNames.Add("LK", "si-LK"); + regionNames.Add("LT", "lt-LT"); + regionNames.Add("LU", "lb-LU"); + regionNames.Add("LV", "lv-LV"); + regionNames.Add("LY", "ar-LY"); + regionNames.Add("MA", "ar-MA"); + regionNames.Add("MC", "fr-MC"); + regionNames.Add("ME", "sr-Latn-ME"); + regionNames.Add("MK", "mk-MK"); + regionNames.Add("MN", "mn-MN"); + regionNames.Add("MO", "zh-MO"); + regionNames.Add("MT", "mt-MT"); + regionNames.Add("MV", "dv-MV"); + regionNames.Add("MX", "es-MX"); + regionNames.Add("MY", "ms-MY"); + regionNames.Add("NG", "ig-NG"); + regionNames.Add("NI", "es-NI"); + regionNames.Add("NL", "nl-NL"); + regionNames.Add("NO", "nn-NO"); + regionNames.Add("NP", "ne-NP"); + regionNames.Add("NZ", "en-NZ"); + regionNames.Add("OM", "ar-OM"); + regionNames.Add("PA", "es-PA"); + regionNames.Add("PE", "es-PE"); + regionNames.Add("PH", "en-PH"); + regionNames.Add("PK", "ur-PK"); + regionNames.Add("PL", "pl-PL"); + regionNames.Add("PR", "es-PR"); + regionNames.Add("PT", "pt-PT"); + regionNames.Add("PY", "es-PY"); + regionNames.Add("QA", "ar-QA"); + regionNames.Add("RO", "ro-RO"); + regionNames.Add("RS", "sr-Latn-RS"); + regionNames.Add("RU", "ru-RU"); + regionNames.Add("RW", "rw-RW"); + regionNames.Add("SA", "ar-SA"); + regionNames.Add("SE", "sv-SE"); + regionNames.Add("SG", "zh-SG"); + regionNames.Add("SI", "sl-SI"); + regionNames.Add("SK", "sk-SK"); + regionNames.Add("SN", "wo-SN"); + regionNames.Add("SV", "es-SV"); + regionNames.Add("SY", "ar-SY"); + regionNames.Add("TH", "th-TH"); + regionNames.Add("TJ", "tg-Cyrl-TJ"); + regionNames.Add("TM", "tk-TM"); + regionNames.Add("TN", "ar-TN"); + regionNames.Add("TR", "tr-TR"); + regionNames.Add("TT", "en-TT"); + regionNames.Add("TW", "zh-TW"); + regionNames.Add("UA", "uk-UA"); + regionNames.Add("US", "en-US"); + regionNames.Add("UY", "es-UY"); + regionNames.Add("UZ", "uz-Cyrl-UZ"); + regionNames.Add("VE", "es-VE"); + regionNames.Add("VN", "vi-VN"); + regionNames.Add("YE", "ar-YE"); + regionNames.Add("ZA", "af-ZA"); + regionNames.Add("ZW", "en-ZW"); - [FriendAccessAllowed] - internal static CultureData GetCultureData(String cultureName, bool useUserOverride) - { - // First do a shortcut for Invariant - if (String.IsNullOrEmpty(cultureName)) - { - return CultureData.Invariant; - } - - // Try the hash table first - String hashName = AnsiToLower(useUserOverride ? cultureName : cultureName + '*'); - Dictionary tempHashTable = s_cachedCultures; - if (tempHashTable == null) - { - // No table yet, make a new one - tempHashTable = new Dictionary(); - } - else - { - // Check the hash table - CultureData retVal; - lock (((ICollection)tempHashTable).SyncRoot) - { - tempHashTable.TryGetValue(hashName, out retVal); - } - if (retVal != null) - { - return retVal; + s_RegionNames = regionNames; } - } - - // Not found in the hash table, need to see if we can build one that works for us - CultureData culture = CreateCultureData(cultureName, useUserOverride); - if (culture == null) - { - return null; - } - // Found one, add it to the cache - lock (((ICollection)tempHashTable).SyncRoot) - { - tempHashTable[hashName] = culture; - } - - // Copy the hashtable to the corresponding member variables. This will potentially overwrite - // new tables simultaneously created by a new thread, but maximizes thread safety. - s_cachedCultures = tempHashTable; - - return culture; - } - - private static CultureData CreateCultureData(string cultureName, bool useUserOverride) - { - CultureData culture = new CultureData(); - culture.bUseOverrides = useUserOverride; - culture.sRealName = cultureName; - - // Ask native code if that one's real - if (culture.InitCultureData() == false) - { - return null; - } - - return culture; - } - - private bool InitCultureData() - { - if (nativeInitCultureData(this) == false) - { - return false; + return s_RegionNames; } - return true; } // Cache of regions we've already looked up - private static volatile Dictionary s_cachedRegions; + private static volatile StringCultureDataDictionary s_cachedRegions; + private static volatile StringStringDictionary s_RegionNames; internal static CultureData GetCultureDataForRegion(String cultureName, bool useUserOverride) { @@ -570,16 +332,16 @@ namespace System.Globalization // Try the hash table next String hashName = AnsiToLower(useUserOverride ? cultureName : cultureName + '*'); - Dictionary tempHashTable = s_cachedRegions; + StringCultureDataDictionary tempHashTable = s_cachedRegions; if (tempHashTable == null) { // No table yet, make a new one - tempHashTable = new Dictionary(); + tempHashTable = new StringCultureDataDictionary(); } else { // Check the hash table - lock (((ICollection)tempHashTable).SyncRoot) + lock (s_lock) { tempHashTable.TryGetValue(hashName, out retVal); } @@ -597,36 +359,25 @@ namespace System.Globalization if (retVal == null || (retVal.IsNeutralCulture == true)) { // Not a valid mapping, try the hard coded table - if (RegionNames.ContainsKey(cultureName)) + string name; + if (RegionNames.TryGetValue(cultureName, out name)) { // Make sure we can get culture data for it - retVal = GetCultureData(RegionNames[cultureName], useUserOverride); + retVal = GetCultureData(name, useUserOverride); } } // If not found in the hard coded table we'll have to find a culture that works for us if (retVal == null || (retVal.IsNeutralCulture == true)) { - // Not found in the hard coded table, need to see if we can find a culture that works for us - // Not a real culture name, see if it matches a region name - // (we just return the first culture we match) - CultureInfo[] specifics = SpecificCultures; - for (int i = 0; i < specifics.Length; i++) - { - if (String.Compare(specifics[i].m_cultureData.SREGIONNAME, cultureName, StringComparison.OrdinalIgnoreCase) == 0) - { - // Matched, use this culture - retVal = specifics[i].m_cultureData; - break; - } - } + retVal = GetCultureDataFromRegionName(cultureName); } - // If we found one we can use, then cash it for next time + // If we found one we can use, then cache it for next time if (retVal != null && (retVal.IsNeutralCulture == false)) { // first add it to the cache - lock (((ICollection)tempHashTable).SyncRoot) + lock (s_lock) { tempHashTable[hashName] = retVal; } @@ -646,54 +397,11 @@ namespace System.Globalization return retVal; } -#if FEATURE_USE_LCID - // Obtain locale name from LCID - // NOTE: This will get neutral names, unlike the OS API - [MethodImplAttribute(MethodImplOptions.InternalCall)] - internal static extern String LCIDToLocaleName(int lcid); - - // We'd rather people use the named version since this doesn't allow custom locales - internal static CultureData GetCultureData(int culture, bool bUseUserOverride) - { - String localeName = null; - CultureData retVal = null; - - if (localeName == null) - { - // Convert the lcid to a name, then use that - // Note that this'll return neutral names (unlike Vista native API) - localeName = LCIDToLocaleName(culture); - } - - // If its not valid, then throw - if (String.IsNullOrEmpty(localeName)) - { - // Could be valid for Invariant - if (culture == 0x007f) - return Invariant; - } - else - { - // Valid name, use it - retVal = GetCultureData(localeName, bUseUserOverride); - } - - // If not successful, throw - if (retVal == null) - throw new CultureNotFoundException( - nameof(culture), culture, Environment.GetResourceString("Argument_CultureNotSupported")); - - // Return the one we found - return retVal; - } -#endif - // Clear our internal caches internal static void ClearCachedData() { s_cachedCultures = null; s_cachedRegions = null; - s_replacementCultureNames = null; } internal static CultureInfo[] GetCultures(CultureTypes types) @@ -702,23 +410,16 @@ namespace System.Globalization #pragma warning disable 618 // Validate flags if ((int)types <= 0 || ((int)types & (int)~(CultureTypes.NeutralCultures | CultureTypes.SpecificCultures | - CultureTypes.InstalledWin32Cultures | CultureTypes.UserCustomCulture | - CultureTypes.ReplacementCultures | CultureTypes.WindowsOnlyCultures | - CultureTypes.FrameworkCultures)) != 0) + CultureTypes.InstalledWin32Cultures | CultureTypes.UserCustomCulture | + CultureTypes.ReplacementCultures | CultureTypes.WindowsOnlyCultures | + CultureTypes.FrameworkCultures)) != 0) { - throw new ArgumentOutOfRangeException( - nameof(types), - String.Format( - CultureInfo.CurrentCulture, - Environment.GetResourceString("ArgumentOutOfRange_Range"), CultureTypes.NeutralCultures, CultureTypes.FrameworkCultures)); + throw new ArgumentOutOfRangeException(nameof(types), + SR.Format(SR.ArgumentOutOfRange_Range, CultureTypes.NeutralCultures, CultureTypes.FrameworkCultures)); } - // - // CHANGE FROM Whidbey - // // We have deprecated CultureTypes.FrameworkCultures. // When this enum is used, we will enumerate Whidbey framework cultures (for compatibility). - // // We have deprecated CultureTypes.WindowsOnlyCultures. // When this enum is used, we will return an empty array for this enum. @@ -727,85 +428,260 @@ namespace System.Globalization // Remove the enum as it is an no-op. types &= (~CultureTypes.WindowsOnlyCultures); } + +#pragma warning restore 618 + return EnumCultures(types); + } + + ///////////////////////////////////////////////////////////////////////// + // Build our invariant information + // + // We need an invariant instance, which we build hard-coded + ///////////////////////////////////////////////////////////////////////// + internal static CultureData Invariant + { + get + { + if (s_Invariant == null) + { + // Make a new culturedata + CultureData invariant = new CultureData(); - String[] cultureNames = null; + // Basics + // Note that we override the resources since this IS NOT supposed to change (by definition) + invariant._bUseOverrides = false; + invariant._sRealName = ""; // Name you passed in (ie: en-US, en, or de-DE_phoneb) + invariant._sWindowsName = ""; // Name OS thinks the object is (ie: de-DE_phoneb, or en-US (even if en was passed in)) - // - // Call nativeEnumCultureNames() to get a string array of culture names based on the specified - // enumeration type. - // - // nativeEnumCultureNames is a QCall. We need to use a reference to return the string array - // allocated from the QCall. That ref has to be wrapped as object handle. - // See vm\qcall.h for details in QCall. - // + // Identity + invariant._sName = ""; // locale name (ie: en-us) + invariant._sParent = ""; // Parent name (which may be a custom locale/culture) + invariant._bNeutral = false; // Flags for the culture (ie: neutral or not right now) + invariant._sEnglishDisplayName = "Invariant Language (Invariant Country)"; // English pretty name for this locale + invariant._sNativeDisplayName = "Invariant Language (Invariant Country)"; // Native pretty name for this locale + invariant._sSpecificCulture = ""; // The culture name to be used in CultureInfo.CreateSpecificCulture() + + // Language + invariant._sISO639Language = "iv"; // ISO 639 Language Name + invariant._sISO639Language2 = "ivl"; // 3 char ISO 639 lang name 2 + invariant._sLocalizedLanguage = "Invariant Language"; // Display name for this Language + invariant._sEnglishLanguage = "Invariant Language"; // English name for this language + invariant._sNativeLanguage = "Invariant Language"; // Native name of this language + invariant._sAbbrevLang = "IVL"; // abbreviated language name (Windows Language Name) + invariant._sConsoleFallbackName = ""; // The culture name for the console fallback UI culture + invariant._iInputLanguageHandle = 0x07F; // input language handle + + // Region + invariant._sRegionName = "IV"; // (RegionInfo) + invariant._sEnglishCountry = "Invariant Country"; // english country name (RegionInfo) + invariant._sNativeCountry = "Invariant Country"; // native country name (Windows Only) + invariant._sISO3166CountryName = "IV"; // (RegionInfo), ie: US + invariant._sISO3166CountryName2 = "ivc"; // 3 char ISO 3166 country name 2 2(RegionInfo) + invariant._iGeoId = 244; // GeoId (Windows Only) + + // Numbers + invariant._sPositiveSign = "+"; // positive sign + invariant._sNegativeSign = "-"; // negative sign + invariant._iDigits = 2; // number of fractional digits + invariant._iNegativeNumber = 1; // negative number format + invariant._waGrouping = new int[] { 3 }; // grouping of digits + invariant._sDecimalSeparator = "."; // decimal separator + invariant._sThousandSeparator = ","; // thousands separator + invariant._sNaN = "NaN"; // Not a Number + invariant._sPositiveInfinity = "Infinity"; // + Infinity + invariant._sNegativeInfinity = "-Infinity"; // - Infinity + + // Percent + invariant._iNegativePercent = 0; // Negative Percent (0-3) + invariant._iPositivePercent = 0; // Positive Percent (0-11) + invariant._sPercent = "%"; // Percent (%) symbol + invariant._sPerMille = "\x2030"; // PerMille symbol + + // Currency + invariant._sCurrency = "\x00a4"; // local monetary symbol: for international monetary symbol + invariant._sIntlMonetarySymbol = "XDR"; // international monetary symbol (RegionInfo) + invariant._sEnglishCurrency = "International Monetary Fund"; // English name for this currency (Windows Only) + invariant._sNativeCurrency = "International Monetary Fund"; // Native name for this currency (Windows Only) + invariant._iCurrencyDigits = 2; // # local monetary fractional digits + invariant._iCurrency = 0; // positive currency format + invariant._iNegativeCurrency = 0; // negative currency format + invariant._waMonetaryGrouping = new int[] { 3 }; // monetary grouping of digits + invariant._sMonetaryDecimal = "."; // monetary decimal separator + invariant._sMonetaryThousand = ","; // monetary thousands separator + + // Misc + invariant._iMeasure = 0; // system of measurement 0=metric, 1=US (RegionInfo) + invariant._sListSeparator = ","; // list separator + + // Time + invariant._sAM1159 = "AM"; // AM designator + invariant._sPM2359 = "PM"; // PM designator + invariant._saLongTimes = new String[] { "HH:mm:ss" }; // time format + invariant._saShortTimes = new String[] { "HH:mm", "hh:mm tt", "H:mm", "h:mm tt" }; // short time format + invariant._saDurationFormats = new String[] { "HH:mm:ss" }; // time duration format - if (nativeEnumCultureNames((int)types, JitHelpers.GetObjectHandleOnStack(ref cultureNames)) == 0) + + // Calendar specific data + invariant._iFirstDayOfWeek = 0; // first day of week + invariant._iFirstWeekOfYear = 0; // first week of year + invariant._waCalendars = new CalendarId[] { CalendarId.GREGORIAN }; // all available calendar type(s). The first one is the default calendar + + // Store for specific data about each calendar + invariant._calendars = new CalendarData[CalendarData.MAX_CALENDARS]; + invariant._calendars[0] = CalendarData.Invariant; + + // Text information + invariant._iReadingLayout = 0; + + // These are desktop only, not coreclr + + invariant._iLanguage = CultureInfo.LOCALE_INVARIANT; // locale ID (0409) - NO sort information + invariant._iDefaultAnsiCodePage = 1252; // default ansi code page ID (ACP) + invariant._iDefaultOemCodePage = 437; // default oem code page ID (OCP or OEM) + invariant._iDefaultMacCodePage = 10000; // default macintosh code page + invariant._iDefaultEbcdicCodePage = 037; // default EBCDIC code page + // Remember it + s_Invariant = invariant; + } + return s_Invariant; + } + } + private volatile static CultureData s_Invariant; + + /////////////// + // Constructors // + /////////////// + // Cache of cultures we've already looked up + private static volatile StringCultureDataDictionary s_cachedCultures; + private static readonly Lock s_lock = new Lock(); + + internal static CultureData GetCultureData(String cultureName, bool useUserOverride) + { + // First do a shortcut for Invariant + if (String.IsNullOrEmpty(cultureName)) + { + return CultureData.Invariant; + } + + // Try the hash table first + String hashName = AnsiToLower(useUserOverride ? cultureName : cultureName + '*'); + StringCultureDataDictionary tempHashTable = s_cachedCultures; + if (tempHashTable == null) + { + // No table yet, make a new one + tempHashTable = new StringCultureDataDictionary(); + } + else { - return new CultureInfo[0]; + // Check the hash table + bool ret; + CultureData retVal; + lock (s_lock) + { + ret = tempHashTable.TryGetValue(hashName, out retVal); + } + if (ret && retVal != null) + { + return retVal; + } } - int arrayLength = cultureNames.Length; + // Not found in the hash table, need to see if we can build one that works for us + CultureData culture = CreateCultureData(cultureName, useUserOverride); + if (culture == null) + { + return null; + } - CultureInfo[] cultures = new CultureInfo[arrayLength]; + // Found one, add it to the cache + lock (s_lock) + { + tempHashTable[hashName] = culture; + } + + // Copy the hashtable to the corresponding member variables. This will potentially overwrite + // new tables simultaneously created by a new thread, but maximizes thread safety. + s_cachedCultures = tempHashTable; + + return culture; + } + + private static CultureData CreateCultureData(string cultureName, bool useUserOverride) + { + CultureData culture = new CultureData(); + culture._bUseOverrides = useUserOverride; + culture._sRealName = cultureName; - for (int i = 0; i < cultureNames.Length; i++) + // Ask native code if that one's real + if (culture.InitCultureData() == false) { - cultures[i] = new CultureInfo(cultureNames[i]); + if (culture.InitCompatibilityCultureData() == false) + { + return null; + } } -#pragma warning restore 618 - return cultures; + return culture; } - internal static volatile CultureInfo[] specificCultures; - - private static CultureInfo[] SpecificCultures + private bool InitCompatibilityCultureData() { - get - { - if (specificCultures == null) - specificCultures = GetCultures(CultureTypes.SpecificCultures); + // for compatibility handle the deprecated ids: zh-chs, zh-cht + string cultureName = _sRealName; - return specificCultures; + string fallbackCultureName; + string realCultureName; + switch (AnsiToLower(cultureName)) + { + case "zh-chs": + fallbackCultureName = "zh-Hans"; + realCultureName = "zh-CHS"; + break; + case "zh-cht": + fallbackCultureName = "zh-Hant"; + realCultureName = "zh-CHT"; + break; + default: + return false; } - } - internal bool IsReplacementCulture - { - get + _sRealName = fallbackCultureName; + if (InitCultureData() == false) { - return IsReplacementCultureName(this.SNAME); + return false; } + // fixup our data + _sName = realCultureName; // the name that goes back to the user + _sParent = fallbackCultureName; + + return true; } - internal static volatile String[] s_replacementCultureNames; + // We'd rather people use the named version since this doesn't allow custom locales + internal static CultureData GetCultureData(int culture, bool bUseUserOverride) + { + string localeName = null; + CultureData retVal = null; - //////////////////////////////////////////////////////////////////////// - // - // Cache for the known replacement cultures. - // This is used by CultureInfo.CultureType to check if a culture is a - // replacement culture. - // - //////////////////////////////////////////////////////////////////////// + if (culture == CultureInfo.LOCALE_INVARIANT) + return Invariant; + // Convert the lcid to a name, then use that + // Note that this will return neutral names (unlike Vista native API) + localeName = LCIDToLocaleName(culture); - private static bool IsReplacementCultureName(String name) - { - Debug.Assert(name != null, "IsReplacementCultureName(): name should not be null"); - String[] replacementCultureNames = s_replacementCultureNames; - if (replacementCultureNames == null) + if (!String.IsNullOrEmpty(localeName)) { - if (nativeEnumCultureNames((int)CultureTypes.ReplacementCultures, JitHelpers.GetObjectHandleOnStack(ref replacementCultureNames)) == 0) - { - return false; - } - - // Even if we don't have any replacement cultures, the returned replacementCultureNames will still an empty string array, not null. - Debug.Assert(name != null, "IsReplacementCultureName(): replacementCultureNames should not be null"); - Array.Sort(replacementCultureNames); - s_replacementCultureNames = replacementCultureNames; + // Valid name, use it + retVal = GetCultureData(localeName, bUseUserOverride); } - return Array.BinarySearch(replacementCultureNames, name) >= 0; + + // If not successful, throw + if (retVal == null) + throw new CultureNotFoundException(nameof(culture), culture, SR.Argument_CultureNotSupported); + + // Return the one we found + return retVal; } //////////////////////////////////////////////////////////////////////// @@ -825,17 +701,17 @@ namespace System.Globalization { get { - Debug.Assert(sRealName != null, "[CultureData.CultureName] Expected this.sRealName to be populated by COMNlsInfo::nativeInitCultureData already"); + Debug.Assert(_sRealName != null, "[CultureData.CultureName] Expected _sRealName to be populated by already"); // since windows doesn't know about zh-CHS and zh-CHT, // we leave sRealName == zh-Hanx but we still need to // pretend that it was zh-CHX. - switch (sName) + switch (_sName) { case "zh-CHS": case "zh-CHT": - return sName; + return _sName; } - return sRealName; + return _sRealName; } } @@ -844,7 +720,7 @@ namespace System.Globalization { get { - return bUseOverrides; + return _bUseOverrides; } } @@ -853,13 +729,11 @@ namespace System.Globalization { get { - // Debug.Assert(this.sName != null, - // "[CultureData.SNAME] Expected this.sName to be populated by COMNlsInfo::nativeInitCultureData already"); - if (sName == null) + if (_sName == null) { - sName = String.Empty; + _sName = String.Empty; } - return sName; + return _sName; } } @@ -868,12 +742,12 @@ namespace System.Globalization { get { - if (sParent == null) + if (_sParent == null) { // Ask using the real name, so that we get parents of neutrals - sParent = DoGetLocaleInfo(sRealName, LOCALE_SPARENT); + _sParent = GetLocaleInfo(_sRealName, LocaleStringData.ParentName); } - return sParent; + return _sParent; } } @@ -882,31 +756,73 @@ namespace System.Globalization { get { - if (sLocalizedDisplayName == null) + if (_sLocalizedDisplayName == null) { + if (this.IsSupplementalCustomCulture) + { + if (this.IsNeutralCulture) + { + _sLocalizedDisplayName = this.SNATIVELANGUAGE; + } + else + { + _sLocalizedDisplayName = this.SNATIVEDISPLAYNAME; + } + } + else + { + try + { + const string ZH_CHT = "zh-CHT"; + const string ZH_CHS = "zh-CHS"; + + if (SNAME.Equals(ZH_CHT, StringComparison.OrdinalIgnoreCase)) + { + _sLocalizedDisplayName = GetLanguageDisplayName("zh-Hant"); + } + else if (SNAME.Equals(ZH_CHS, StringComparison.OrdinalIgnoreCase)) + { + _sLocalizedDisplayName = GetLanguageDisplayName("zh-Hans"); + } + else + { + _sLocalizedDisplayName = GetLanguageDisplayName(SNAME); + } + } + catch (Exception) + { + // do nothing + } + } // If it hasn't been found (Windows 8 and up), fallback to the system - if (String.IsNullOrEmpty(sLocalizedDisplayName)) + if (String.IsNullOrEmpty(_sLocalizedDisplayName)) { // If its neutral use the language name if (this.IsNeutralCulture) { - sLocalizedDisplayName = this.SLOCALIZEDLANGUAGE; + _sLocalizedDisplayName = this.SLOCALIZEDLANGUAGE; } else { - // We have to make the neutral distinction in case the OS returns a specific name - if (CultureInfo.UserDefaultUICulture.Name.Equals(Thread.CurrentThread.CurrentUICulture.Name)) + // Usually the UI culture shouldn't be different than what we got from WinRT except + // if DefaultThreadCurrentUICulture was set + CultureInfo ci; + + if (CultureInfo.DefaultThreadCurrentUICulture != null && + ((ci = GetUserDefaultCulture()) != null) && + !CultureInfo.DefaultThreadCurrentUICulture.Name.Equals(ci.Name)) { - sLocalizedDisplayName = DoGetLocaleInfo(LOCALE_SLOCALIZEDDISPLAYNAME); + _sLocalizedDisplayName = this.SNATIVEDISPLAYNAME; } - if (String.IsNullOrEmpty(sLocalizedDisplayName)) + else { - sLocalizedDisplayName = this.SNATIVEDISPLAYNAME; + _sLocalizedDisplayName = GetLocaleInfo(LocaleStringData.LocalizedDisplayName); } } } } - return sLocalizedDisplayName; + + return _sLocalizedDisplayName; } } @@ -915,39 +831,47 @@ namespace System.Globalization { get { - if (sEnglishDisplayName == null) + if (_sEnglishDisplayName == null) { // If its neutral use the language name if (this.IsNeutralCulture) { - sEnglishDisplayName = this.SENGLISHLANGUAGE; + _sEnglishDisplayName = this.SENGLISHLANGUAGE; + // differentiate the legacy display names + switch (_sName) + { + case "zh-CHS": + case "zh-CHT": + _sEnglishDisplayName += " Legacy"; + break; + } } else { - sEnglishDisplayName = DoGetLocaleInfo(LOCALE_SENGLISHDISPLAYNAME); + _sEnglishDisplayName = GetLocaleInfo(LocaleStringData.EnglishDisplayName); // if it isn't found build one: - if (String.IsNullOrEmpty(sEnglishDisplayName)) + if (String.IsNullOrEmpty(_sEnglishDisplayName)) { // Our existing names mostly look like: // "English" + "United States" -> "English (United States)" // "Azeri (Latin)" + "Azerbaijan" -> "Azeri (Latin, Azerbaijan)" - if (this.SENGLISHLANGUAGE.EndsWith(')')) + if (this.SENGLISHLANGUAGE[this.SENGLISHLANGUAGE.Length - 1] == ')') { // "Azeri (Latin)" + "Azerbaijan" -> "Azeri (Latin, Azerbaijan)" - sEnglishDisplayName = - this.SENGLISHLANGUAGE.Substring(0, sEnglishLanguage.Length - 1) + + _sEnglishDisplayName = + this.SENGLISHLANGUAGE.Substring(0, _sEnglishLanguage.Length - 1) + ", " + this.SENGCOUNTRY + ")"; } else { // "English" + "United States" -> "English (United States)" - sEnglishDisplayName = this.SENGLISHLANGUAGE + " (" + this.SENGCOUNTRY + ")"; + _sEnglishDisplayName = this.SENGLISHLANGUAGE + " (" + this.SENGCOUNTRY + ")"; } } } } - return sEnglishDisplayName; + return _sEnglishDisplayName; } } @@ -956,37 +880,47 @@ namespace System.Globalization { get { - if (sNativeDisplayName == null) + if (_sNativeDisplayName == null) { // If its neutral use the language name if (this.IsNeutralCulture) { - sNativeDisplayName = this.SNATIVELANGUAGE; + _sNativeDisplayName = this.SNATIVELANGUAGE; + // differentiate the legacy display names + switch (_sName) + { + case "zh-CHS": + _sNativeDisplayName += " \u65E7\u7248"; + break; + case "zh-CHT": + _sNativeDisplayName += " \u820A\u7248"; + break; + } } else { - sNativeDisplayName = DoGetLocaleInfo(LOCALE_SNATIVEDISPLAYNAME); + _sNativeDisplayName = GetLocaleInfo(LocaleStringData.NativeDisplayName); // if it isn't found build one: - if (String.IsNullOrEmpty(sNativeDisplayName)) + if (String.IsNullOrEmpty(_sNativeDisplayName)) { // These should primarily be "Deutsch (Deutschland)" type names - sNativeDisplayName = this.SNATIVELANGUAGE + " (" + this.SNATIVECOUNTRY + ")"; + _sNativeDisplayName = this.SNATIVELANGUAGE + " (" + this.SNATIVECOUNTRY + ")"; } } } - return sNativeDisplayName; + return _sNativeDisplayName; } } // The culture name to be used in CultureInfo.CreateSpecificCulture() - internal String SSPECIFICCULTURE + internal string SSPECIFICCULTURE { get { - // This got populated when ComNlsInfo::nativeInitCultureData told us we had a culture - Debug.Assert(sSpecificCulture != null, "[CultureData.SSPECIFICCULTURE] Expected this.sSpecificCulture to be populated by COMNlsInfo::nativeInitCultureData already"); - return sSpecificCulture; + // This got populated during the culture initialization + Debug.Assert(_sSpecificCulture != null, "[CultureData.SSPECIFICCULTURE] Expected this.sSpecificCulture to be populated by culture data initialization already"); + return _sSpecificCulture; } } @@ -999,37 +933,37 @@ namespace System.Globalization { get { - if (sISO639Language == null) + if (_sISO639Language == null) { - sISO639Language = DoGetLocaleInfo(LOCALE_SISO639LANGNAME); + _sISO639Language = GetLocaleInfo(LocaleStringData.Iso639LanguageTwoLetterName); } - return sISO639Language; + return _sISO639Language; } } // iso 639 language name, ie: eng - internal String SISO639LANGNAME2 + internal string SISO639LANGNAME2 { get { - if (sISO639Language2 == null) + if (_sISO639Language2 == null) { - sISO639Language2 = DoGetLocaleInfo(LOCALE_SISO639LANGNAME2); + _sISO639Language2 = GetLocaleInfo(LocaleStringData.Iso639LanguageThreeLetterName); } - return sISO639Language2; + return _sISO639Language2; } } // abbreviated windows language name (ie: enu) (non-standard, avoid this) - internal String SABBREVLANGNAME + internal string SABBREVLANGNAME { get { - if (sAbbrevLang == null) + if (_sAbbrevLang == null) { - sAbbrevLang = DoGetLocaleInfo(LOCALE_SABBREVLANGNAME); + _sAbbrevLang = GetThreeLetterWindowsLanguageName(_sRealName); } - return sAbbrevLang; + return _sAbbrevLang; } } @@ -1039,20 +973,25 @@ namespace System.Globalization { get { - if (sLocalizedLanguage == null) + if (_sLocalizedLanguage == null) { - if (CultureInfo.UserDefaultUICulture.Name.Equals(Thread.CurrentThread.CurrentUICulture.Name)) + // Usually the UI culture shouldn't be different than what we got from WinRT except + // if DefaultThreadCurrentUICulture was set + CultureInfo ci; + + if (CultureInfo.DefaultThreadCurrentUICulture != null && + ((ci = GetUserDefaultCulture()) != null) && + !CultureInfo.DefaultThreadCurrentUICulture.Name.Equals(ci.Name)) { - sLocalizedLanguage = DoGetLocaleInfo(LOCALE_SLOCALIZEDLANGUAGENAME); + _sLocalizedLanguage = SNATIVELANGUAGE; } - // Some OS's might not have this resource or LCTYPE - if (String.IsNullOrEmpty(sLocalizedLanguage)) + else { - sLocalizedLanguage = SNATIVELANGUAGE; + _sLocalizedLanguage = GetLocaleInfo(LocaleStringData.LocalizedLanguageName); } } - return sLocalizedLanguage; + return _sLocalizedLanguage; } } @@ -1061,11 +1000,11 @@ namespace System.Globalization { get { - if (sEnglishLanguage == null) + if (_sEnglishLanguage == null) { - sEnglishLanguage = DoGetLocaleInfo(LOCALE_SENGLISHLANGUAGENAME); + _sEnglishLanguage = GetLocaleInfo(LocaleStringData.EnglishLanguageName); } - return sEnglishLanguage; + return _sEnglishLanguage; } } @@ -1074,13 +1013,11 @@ namespace System.Globalization { get { - if (sNativeLanguage == null) + if (_sNativeLanguage == null) { - { - sNativeLanguage = DoGetLocaleInfo(LOCALE_SNATIVELANGUAGENAME); - } + _sNativeLanguage = GetLocaleInfo(LocaleStringData.NativeLanguageName); } - return sNativeLanguage; + return _sNativeLanguage; } } @@ -1093,24 +1030,23 @@ namespace System.Globalization { get { - if (sRegionName == null) + if (_sRegionName == null) { - sRegionName = DoGetLocaleInfo(LOCALE_SISO3166CTRYNAME); + _sRegionName = GetLocaleInfo(LocaleStringData.Iso3166CountryName); } - return sRegionName; + return _sRegionName; } } - // GeoId internal int IGEOID { get { - if (iGeoId == undef) + if (_iGeoId == undef) { - iGeoId = DoGetLocaleInfoInt(LOCALE_IGEOID); + _iGeoId = GetGeoId(_sRealName); } - return iGeoId; + return _iGeoId; } } @@ -1119,23 +1055,23 @@ namespace System.Globalization { get { - if (sLocalizedCountry == null) + if (_sLocalizedCountry == null) { - // If it hasn't been found (Windows 8 and up), fallback to the system - if (String.IsNullOrEmpty(sLocalizedCountry)) + try { - // We have to make the neutral distinction in case the OS returns a specific name - if (CultureInfo.UserDefaultUICulture.Name.Equals(Thread.CurrentThread.CurrentUICulture.Name)) - { - sLocalizedCountry = DoGetLocaleInfo(LOCALE_SLOCALIZEDCOUNTRYNAME); - } - if (String.IsNullOrEmpty(sLocalizedDisplayName)) - { - sLocalizedCountry = SNATIVECOUNTRY; - } + _sLocalizedCountry = GetRegionDisplayName(SISO3166CTRYNAME); + } + catch (Exception) + { + // do nothing. we'll fallback + } + + if (_sLocalizedCountry == null) + { + _sLocalizedCountry = SNATIVECOUNTRY; } } - return sLocalizedCountry; + return _sLocalizedCountry; } } @@ -1144,11 +1080,11 @@ namespace System.Globalization { get { - if (sEnglishCountry == null) + if (_sEnglishCountry == null) { - sEnglishCountry = DoGetLocaleInfo(LOCALE_SENGLISHCOUNTRYNAME); + _sEnglishCountry = GetLocaleInfo(LocaleStringData.EnglishCountryName); } - return sEnglishCountry; + return _sEnglishCountry; } } @@ -1157,11 +1093,11 @@ namespace System.Globalization { get { - if (sNativeCountry == null) + if (_sNativeCountry == null) { - sNativeCountry = DoGetLocaleInfo(LOCALE_SNATIVECOUNTRYNAME); + _sNativeCountry = GetLocaleInfo(LocaleStringData.NativeCountryName); } - return sNativeCountry; + return _sNativeCountry; } } @@ -1170,90 +1106,70 @@ namespace System.Globalization { get { - if (sISO3166CountryName == null) + if (_sISO3166CountryName == null) { - sISO3166CountryName = DoGetLocaleInfo(LOCALE_SISO3166CTRYNAME); + _sISO3166CountryName = GetLocaleInfo(LocaleStringData.Iso3166CountryName); } - return sISO3166CountryName; + return _sISO3166CountryName; } } - // ISO 3166 Country Name + // 3 letter ISO 3166 country code internal String SISO3166CTRYNAME2 { get { - if (sISO3166CountryName2 == null) + if (_sISO3166CountryName2 == null) { - sISO3166CountryName2 = DoGetLocaleInfo(LOCALE_SISO3166CTRYNAME2); + _sISO3166CountryName2 = GetLocaleInfo(LocaleStringData.Iso3166CountryName2); } - return sISO3166CountryName2; + return _sISO3166CountryName2; } } - // abbreviated Country Name (windows version, non-standard, avoid) - internal String SABBREVCTRYNAME - { - get - { - if (sAbbrevCountry == null) - { - sAbbrevCountry = DoGetLocaleInfo(LOCALE_SABBREVCTRYNAME); - } - return sAbbrevCountry; - } - } - - // Console fallback name (ie: locale to use for console apps for unicode-only locales) internal int IINPUTLANGUAGEHANDLE { get { - if (iInputLanguageHandle == undef) + if (_iInputLanguageHandle == undef) { if (IsSupplementalCustomCulture) { - iInputLanguageHandle = 0x0409; + _iInputLanguageHandle = 0x0409; } else { // Input Language is same as LCID for built-in cultures - iInputLanguageHandle = this.ILANGUAGE; + _iInputLanguageHandle = this.ILANGUAGE; } } - return iInputLanguageHandle; + return _iInputLanguageHandle; } } // Console fallback name (ie: locale to use for console apps for unicode-only locales) - internal String SCONSOLEFALLBACKNAME + internal string SCONSOLEFALLBACKNAME { get { - if (sConsoleFallbackName == null) + if (_sConsoleFallbackName == null) { - string consoleFallbackName = DoGetLocaleInfo(LOCALE_SCONSOLEFALLBACKNAME); - if (consoleFallbackName == "es-ES_tradnl") - { - consoleFallbackName = "es-ES"; - } - sConsoleFallbackName = consoleFallbackName; + _sConsoleFallbackName = GetConsoleFallbackName(_sRealName); } - return sConsoleFallbackName; + return _sConsoleFallbackName; } } - // (user can override) grouping of digits internal int[] WAGROUPING { get { - if (waGrouping == null || UseUserOverride) + if (_waGrouping == null) { - waGrouping = ConvertWin32GroupString(DoGetLocaleInfo(LOCALE_SGROUPING)); + _waGrouping = GetLocaleInfo(LocaleGroupingData.Digit); } - return waGrouping; + return _waGrouping; } } @@ -1266,11 +1182,11 @@ namespace System.Globalization { get { - if (sNaN == null) + if (_sNaN == null) { - sNaN = DoGetLocaleInfo(LOCALE_SNAN); + _sNaN = GetLocaleInfo(LocaleStringData.NaNSymbol); } - return sNaN; + return _sNaN; } } @@ -1279,11 +1195,11 @@ namespace System.Globalization { get { - if (sPositiveInfinity == null) + if (_sPositiveInfinity == null) { - sPositiveInfinity = DoGetLocaleInfo(LOCALE_SPOSINFINITY); + _sPositiveInfinity = GetLocaleInfo(LocaleStringData.PositiveInfinitySymbol); } - return sPositiveInfinity; + return _sPositiveInfinity; } } @@ -1292,11 +1208,11 @@ namespace System.Globalization { get { - if (sNegativeInfinity == null) + if (_sNegativeInfinity == null) { - sNegativeInfinity = DoGetLocaleInfo(LOCALE_SNEGINFINITY); + _sNegativeInfinity = GetLocaleInfo(LocaleStringData.NegativeInfinitySymbol); } - return sNegativeInfinity; + return _sNegativeInfinity; } } @@ -1310,12 +1226,12 @@ namespace System.Globalization { get { - if (iNegativePercent == undef) + if (_iNegativePercent == undef) { // Note that <= Windows Vista this is synthesized by native code - iNegativePercent = DoGetLocaleInfoInt(LOCALE_INEGATIVEPERCENT); + _iNegativePercent = GetLocaleInfo(LocaleNumberData.NegativePercentFormat); } - return iNegativePercent; + return _iNegativePercent; } } @@ -1324,12 +1240,12 @@ namespace System.Globalization { get { - if (iPositivePercent == undef) + if (_iPositivePercent == undef) { // Note that <= Windows Vista this is synthesized by native code - iPositivePercent = DoGetLocaleInfoInt(LOCALE_IPOSITIVEPERCENT); + _iPositivePercent = GetLocaleInfo(LocaleNumberData.PositivePercentFormat); } - return iPositivePercent; + return _iPositivePercent; } } @@ -1338,26 +1254,24 @@ namespace System.Globalization { get { - if (sPercent == null) + if (_sPercent == null) { - // Note that <= Windows Vista this is synthesized by native code - sPercent = DoGetLocaleInfo(LOCALE_SPERCENT); + _sPercent = GetLocaleInfo(LocaleStringData.PercentSymbol); } - return sPercent; + return _sPercent; } } - // PerMille (‰) symbol + // PerMille symbol internal String SPERMILLE { get { - if (sPerMille == null) + if (_sPerMille == null) { - // Note that <= Windows Vista this is synthesized by native code - sPerMille = DoGetLocaleInfo(LOCALE_SPERMILLE); + _sPerMille = GetLocaleInfo(LocaleStringData.PerMilleSymbol); } - return sPerMille; + return _sPerMille; } } @@ -1370,11 +1284,11 @@ namespace System.Globalization { get { - if (sCurrency == null || UseUserOverride) + if (_sCurrency == null) { - sCurrency = DoGetLocaleInfo(LOCALE_SCURRENCY); + _sCurrency = GetLocaleInfo(LocaleStringData.MonetarySymbol); } - return sCurrency; + return _sCurrency; } } @@ -1383,11 +1297,11 @@ namespace System.Globalization { get { - if (sIntlMonetarySymbol == null) + if (_sIntlMonetarySymbol == null) { - sIntlMonetarySymbol = DoGetLocaleInfo(LOCALE_SINTLSYMBOL); + _sIntlMonetarySymbol = GetLocaleInfo(LocaleStringData.Iso4217MonetarySymbol); } - return sIntlMonetarySymbol; + return _sIntlMonetarySymbol; } } @@ -1396,11 +1310,11 @@ namespace System.Globalization { get { - if (sEnglishCurrency == null) + if (_sEnglishCurrency == null) { - sEnglishCurrency = DoGetLocaleInfo(LOCALE_SENGCURRNAME); + _sEnglishCurrency = GetLocaleInfo(LocaleStringData.CurrencyEnglishName); } - return sEnglishCurrency; + return _sEnglishCurrency; } } @@ -1409,11 +1323,11 @@ namespace System.Globalization { get { - if (sNativeCurrency == null) + if (_sNativeCurrency == null) { - sNativeCurrency = DoGetLocaleInfo(LOCALE_SNATIVECURRNAME); + _sNativeCurrency = GetLocaleInfo(LocaleStringData.CurrencyNativeName); } - return sNativeCurrency; + return _sNativeCurrency; } } @@ -1426,31 +1340,24 @@ namespace System.Globalization { get { - if (waMonetaryGrouping == null || UseUserOverride) + if (_waMonetaryGrouping == null) { - waMonetaryGrouping = ConvertWin32GroupString(DoGetLocaleInfo(LOCALE_SMONGROUPING)); + _waMonetaryGrouping = GetLocaleInfo(LocaleGroupingData.Monetary); } - return waMonetaryGrouping; + return _waMonetaryGrouping; } } - // internal String sMonetaryDecimal ; // (user can override) monetary decimal separator - // internal String sMonetaryThousand ; // (user can override) monetary thousands separator - - ///////// - // Misc // - ///////// - // (user can override) system of measurement 0=metric, 1=US (RegionInfo) internal int IMEASURE { get { - if (iMeasure == undef || UseUserOverride) + if (_iMeasure == undef) { - iMeasure = DoGetLocaleInfoInt(LOCALE_IMEASURE); + _iMeasure = GetLocaleInfo(LocaleNumberData.MeasurementSystem); } - return iMeasure; + return _iMeasure; } } @@ -1459,14 +1366,15 @@ namespace System.Globalization { get { - if (sListSeparator == null || UseUserOverride) + if (_sListSeparator == null) { - sListSeparator = DoGetLocaleInfo(LOCALE_SLIST); + _sListSeparator = GetLocaleInfo(LocaleStringData.ListSeparator); } - return sListSeparator; + return _sListSeparator; } } + //////////////////////////// // Calendar/Time (Gregorian) // //////////////////////////// @@ -1476,11 +1384,11 @@ namespace System.Globalization { get { - if (sAM1159 == null || UseUserOverride) + if (_sAM1159 == null) { - sAM1159 = DoGetLocaleInfo(LOCALE_S1159); + _sAM1159 = GetLocaleInfo(LocaleStringData.AMDesignator); } - return sAM1159; + return _sAM1159; } } @@ -1489,11 +1397,11 @@ namespace System.Globalization { get { - if (sPM2359 == null || UseUserOverride) + if (_sPM2359 == null) { - sPM2359 = DoGetLocaleInfo(LOCALE_S2359); + _sPM2359 = GetLocaleInfo(LocaleStringData.PMDesignator); } - return sPM2359; + return _sPM2359; } } @@ -1502,32 +1410,34 @@ namespace System.Globalization { get { - if (saLongTimes == null || UseUserOverride) + if (_saLongTimes == null) { - String[] longTimes = DoEnumTimeFormats(); + String[] longTimes = GetTimeFormats(); if (longTimes == null || longTimes.Length == 0) { - saLongTimes = Invariant.saLongTimes; + _saLongTimes = Invariant._saLongTimes; } else { - saLongTimes = longTimes; + _saLongTimes = longTimes; } } - return saLongTimes; + return _saLongTimes; } } // short time format // Short times (derived from long times format) + // TODO: NLS Arrowhead - On Windows 7 we should have short times so this isn't necessary internal String[] ShortTimes { get { - if (saShortTimes == null || UseUserOverride) + if (_saShortTimes == null) { // Try to get the short times from the OS/culture.dll - String[] shortTimes = DoEnumShortTimeFormats(); + String[] shortTimes = null; + shortTimes = GetShortTimeFormats(); if (shortTimes == null || shortTimes.Length == 0) { @@ -1538,13 +1448,24 @@ namespace System.Globalization shortTimes = DeriveShortTimesFromLong(); } + /* The above logic doesn't make sense on Mac, since the OS can provide us a "short time pattern". + * currently this is the 4th element in the array returned by LongTimes. We'll add this to our array + * if it doesn't exist. + */ + shortTimes = AdjustShortTimesForMac(shortTimes); + // Found short times, use them - saShortTimes = shortTimes; + _saShortTimes = shortTimes; } - return saShortTimes; + return _saShortTimes; } } + private string[] AdjustShortTimesForMac(string[] shortTimes) + { + return shortTimes; + } + private string[] DeriveShortTimesFromLong() { // Our logic is to look for h,H,m,s,t. If we find an s, then we check the string @@ -1610,13 +1531,19 @@ namespace System.Globalization bool containsSpace; int endIndex = GetIndexOfNextTokenAfterSeconds(time, j, out containsSpace); - StringBuilder sb = new StringBuilder(time.Substring(0, j)); + + string sep; + if (containsSpace) { - sb.Append(' '); + sep = " "; } - sb.Append(time.Substring(endIndex)); - time = sb.ToString(); + else + { + sep = ""; + } + + time = time.Substring(0, j) + sep + time.Substring(endIndex); break; case 'm': case 'H': @@ -1669,12 +1596,11 @@ namespace System.Globalization { get { - if (iFirstDayOfWeek == undef || UseUserOverride) + if (_iFirstDayOfWeek == undef) { - // Have to convert it from windows to .Net formats - iFirstDayOfWeek = ConvertFirstDayOfWeekMonToSun(DoGetLocaleInfoInt(LOCALE_IFIRSTDAYOFWEEK)); + _iFirstDayOfWeek = GetFirstDayOfWeek(); } - return iFirstDayOfWeek; + return _iFirstDayOfWeek; } } @@ -1683,71 +1609,71 @@ namespace System.Globalization { get { - if (iFirstWeekOfYear == undef || UseUserOverride) + if (_iFirstWeekOfYear == undef) { - iFirstWeekOfYear = DoGetLocaleInfoInt(LOCALE_IFIRSTWEEKOFYEAR); + _iFirstWeekOfYear = GetLocaleInfo(LocaleNumberData.FirstWeekOfYear); } - return iFirstWeekOfYear; + return _iFirstWeekOfYear; } } // (user can override default only) short date format - internal String[] ShortDates(int calendarId) + internal String[] ShortDates(CalendarId calendarId) { return GetCalendar(calendarId).saShortDates; } // (user can override default only) long date format - internal String[] LongDates(int calendarId) + internal String[] LongDates(CalendarId calendarId) { return GetCalendar(calendarId).saLongDates; } // (user can override) date year/month format. - internal String[] YearMonths(int calendarId) + internal String[] YearMonths(CalendarId calendarId) { return GetCalendar(calendarId).saYearMonths; } // day names - internal string[] DayNames(int calendarId) + internal string[] DayNames(CalendarId calendarId) { return GetCalendar(calendarId).saDayNames; } // abbreviated day names - internal string[] AbbreviatedDayNames(int calendarId) + internal string[] AbbreviatedDayNames(CalendarId calendarId) { // Get abbreviated day names for this calendar from the OS if necessary return GetCalendar(calendarId).saAbbrevDayNames; } // The super short day names - internal string[] SuperShortDayNames(int calendarId) + internal string[] SuperShortDayNames(CalendarId calendarId) { return GetCalendar(calendarId).saSuperShortDayNames; } // month names - internal string[] MonthNames(int calendarId) + internal string[] MonthNames(CalendarId calendarId) { return GetCalendar(calendarId).saMonthNames; } // Genitive month names - internal string[] GenitiveMonthNames(int calendarId) + internal string[] GenitiveMonthNames(CalendarId calendarId) { return GetCalendar(calendarId).saMonthGenitiveNames; } // month names - internal string[] AbbreviatedMonthNames(int calendarId) + internal string[] AbbreviatedMonthNames(CalendarId calendarId) { return GetCalendar(calendarId).saAbbrevMonthNames; } // Genitive month names - internal string[] AbbreviatedGenitiveMonthNames(int calendarId) + internal string[] AbbreviatedGenitiveMonthNames(CalendarId calendarId) { return GetCalendar(calendarId).saAbbrevMonthGenitiveNames; } @@ -1755,13 +1681,13 @@ namespace System.Globalization // Leap year month names // Note: This only applies to Hebrew, and it basically adds a "1" to the 6th month name // the non-leap names skip the 7th name in the normal month name array - internal string[] LeapYearMonthNames(int calendarId) + internal string[] LeapYearMonthNames(CalendarId calendarId) { return GetCalendar(calendarId).saLeapYearMonthNames; } // month/day format (single string, no override) - internal String MonthDay(int calendarId) + internal String MonthDay(CalendarId calendarId) { return GetCalendar(calendarId).sMonthDay; } @@ -1773,29 +1699,30 @@ namespace System.Globalization ///////////// // all available calendar type(s), The first one is the default calendar. - internal int[] CalendarIds + internal CalendarId[] CalendarIds { get { - if (waCalendars == null) + if (_waCalendars == null) { // We pass in an array of ints, and native side fills it up with count calendars. // We then have to copy that list to a new array of the right size. // Default calendar should be first - int[] calendarInts = new int[23]; - Debug.Assert(sWindowsName != null, "[CultureData.CalendarIds] Expected this.sWindowsName to be populated by COMNlsInfo::nativeInitCultureData already"); - int count = CalendarData.nativeGetCalendars(sWindowsName, bUseOverrides, calendarInts); + CalendarId[] calendars = new CalendarId[23]; + Debug.Assert(_sWindowsName != null, "[CultureData.CalendarIds] Expected _sWindowsName to be populated by already"); + int count = CalendarData.GetCalendars(_sWindowsName, _bUseOverrides, calendars); // See if we had a calendar to add. if (count == 0) { // Failed for some reason, just grab Gregorian from Invariant - waCalendars = Invariant.waCalendars; + _waCalendars = Invariant._waCalendars; } else { // The OS may not return calendar 4 for zh-TW, but we've always allowed it. - if (sWindowsName == "zh-TW") + // TODO: Is this hack necessary long-term? + if (_sWindowsName == "zh-TW") { bool found = false; @@ -1803,7 +1730,7 @@ namespace System.Globalization for (int i = 0; i < count; i++) { // Stop if we found calendar four - if (calendarInts[i] == Calendar.CAL_TAIWAN) + if (calendars[i] == CalendarId.TAIWAN) { found = true; break; @@ -1816,21 +1743,20 @@ namespace System.Globalization // Insert it as the 2nd calendar count++; // Copy them from the 2nd position to the end, -1 for skipping 1st, -1 for one being added. - Array.Copy(calendarInts, 1, calendarInts, 2, 23 - 1 - 1); - calendarInts[1] = Calendar.CAL_TAIWAN; + Array.Copy(calendars, 1, calendars, 2, 23 - 1 - 1); + calendars[1] = CalendarId.TAIWAN; } } // It worked, remember the list - int[] temp = new int[count]; - Array.Copy(calendarInts, temp, count); + CalendarId[] temp = new CalendarId[count]; + Array.Copy(calendars, temp, count); // Want 1st calendar to be default // Prior to Vista the enumeration didn't have default calendar first - // Only a coreclr concern, culture.dll does the right thing. if (temp.Length > 1) { - int i = DoGetLocaleInfoInt(LOCALE_ICALENDARTYPE); + CalendarId i = (CalendarId)GetLocaleInfo(LocaleNumberData.CalendarType); if (temp[1] == i) { temp[1] = temp[0]; @@ -1838,45 +1764,45 @@ namespace System.Globalization } } - waCalendars = temp; + _waCalendars = temp; } } - return waCalendars; + return _waCalendars; } } // Native calendar names. index of optional calendar - 1, empty if no optional calendar at that number - internal String CalendarName(int calendarId) + internal string CalendarName(CalendarId calendarId) { // Get the calendar return GetCalendar(calendarId).sNativeName; } - internal CalendarData GetCalendar(int calendarId) + internal CalendarData GetCalendar(CalendarId calendarId) { - Debug.Assert(calendarId > 0 && calendarId <= CalendarData.MAX_CALENDARS, + Debug.Assert(calendarId > 0 && calendarId <= CalendarId.LAST_CALENDAR, "[CultureData.GetCalendar] Expect calendarId to be in a valid range"); // arrays are 0 based, calendarIds are 1 based - int calendarIndex = calendarId - 1; + int calendarIndex = (int)calendarId - 1; // Have to have calendars - if (calendars == null) + if (_calendars == null) { - calendars = new CalendarData[CalendarData.MAX_CALENDARS]; + _calendars = new CalendarData[CalendarData.MAX_CALENDARS]; } // we need the following local variable to avoid returning null // when another thread creates a new array of CalendarData (above) // right after we insert the newly created CalendarData (below) - CalendarData calendarData = calendars[calendarIndex]; + CalendarData calendarData = _calendars[calendarIndex]; // Make sure that calendar has data - if (calendarData == null || UseUserOverride) + if (calendarData == null) { - Debug.Assert(sWindowsName != null, "[CultureData.GetCalendar] Expected this.sWindowsName to be populated by COMNlsInfo::nativeInitCultureData already"); - calendarData = new CalendarData(sWindowsName, calendarId, this.UseUserOverride); - calendars[calendarIndex] = calendarData; + Debug.Assert(_sWindowsName != null, "[CultureData.GetCalendar] Expected _sWindowsName to be populated by already"); + calendarData = new CalendarData(_sWindowsName, calendarId, this.UseUserOverride); + _calendars[calendarIndex] = calendarData; } return calendarData; @@ -1912,13 +1838,13 @@ namespace System.Globalization { get { - if (iReadingLayout == undef) + if (_iReadingLayout == undef) { - Debug.Assert(sRealName != null, "[CultureData.IsRightToLeft] Expected this.sRealName to be populated by COMNlsInfo::nativeInitCultureData already"); - iReadingLayout = DoGetLocaleInfoInt(LOCALE_IREADINGLAYOUT); + Debug.Assert(_sRealName != null, "[CultureData.IsRightToLeft] Expected _sRealName to be populated by already"); + _iReadingLayout = GetLocaleInfo(LocaleNumberData.ReadingLayout); } - return (iReadingLayout); + return (_iReadingLayout); } } @@ -1933,23 +1859,10 @@ namespace System.Globalization { get { - if (sTextInfo == null) - { - // LOCALE_SSORTLOCALE is broken in Win7 for Alt sorts. - // It is also not supported downlevel without culture.dll. - if (IsNeutralCulture || IsSupplementalCustomCulture) - { - string sortLocale = DoGetLocaleInfo(LOCALE_SSORTLOCALE); - sTextInfo = GetCultureData(sortLocale, bUseOverrides).SNAME; - } - - if (sTextInfo == null) - { - sTextInfo = this.SNAME; // removes alternate sort - } - } - - return sTextInfo; + // Note: Custom cultures might point at another culture's textinfo, however windows knows how + // to redirect it to the desired textinfo culture, so this is OK. + Debug.Assert(_sRealName != null, "[CultureData.STEXTINFO] Expected _sRealName to be populated by already"); + return (_sRealName); } } @@ -1958,24 +1871,8 @@ namespace System.Globalization { get { - if (sCompareInfo == null) - { - // LOCALE_SSORTLOCALE is broken in Win7 for Alt sorts. - // It is also not supported downlevel without culture.dll. - // We really only need it for the custom locale case though - // since for all other cases, it is the same as sWindowsName - if (IsSupplementalCustomCulture) - { - sCompareInfo = DoGetLocaleInfo(LOCALE_SSORTLOCALE); - } - - if (sCompareInfo == null) - { - sCompareInfo = sWindowsName; - } - } - - return sCompareInfo; + Debug.Assert(_sRealName != null, "[CultureData.SCOMPAREINFO] Expected _sRealName to be populated by already"); + return (_sRealName); } } @@ -1987,16 +1884,15 @@ namespace System.Globalization } } - internal int IDEFAULTANSICODEPAGE // default ansi code page ID (ACP) { get { - if (iDefaultAnsiCodePage == undef) + if (_iDefaultAnsiCodePage == undef) { - iDefaultAnsiCodePage = DoGetLocaleInfoInt(LOCALE_IDEFAULTANSICODEPAGE); + _iDefaultAnsiCodePage = GetAnsiCodePage(_sRealName); } - return iDefaultAnsiCodePage; + return _iDefaultAnsiCodePage; } } @@ -2004,11 +1900,11 @@ namespace System.Globalization { get { - if (iDefaultOemCodePage == undef) + if (_iDefaultOemCodePage == undef) { - iDefaultOemCodePage = DoGetLocaleInfoInt(LOCALE_IDEFAULTCODEPAGE); + _iDefaultOemCodePage = GetOemCodePage(_sRealName); } - return iDefaultOemCodePage; + return _iDefaultOemCodePage; } } @@ -2016,11 +1912,11 @@ namespace System.Globalization { get { - if (iDefaultMacCodePage == undef) + if (_iDefaultMacCodePage == undef) { - iDefaultMacCodePage = DoGetLocaleInfoInt(LOCALE_IDEFAULTMACCODEPAGE); + _iDefaultMacCodePage = GetMacCodePage(_sRealName); } - return iDefaultMacCodePage; + return _iDefaultMacCodePage; } } @@ -2028,54 +1924,33 @@ namespace System.Globalization { get { - if (iDefaultEbcdicCodePage == undef) + if (_iDefaultEbcdicCodePage == undef) { - iDefaultEbcdicCodePage = DoGetLocaleInfoInt(LOCALE_IDEFAULTEBCDICCODEPAGE); + _iDefaultEbcdicCodePage = GetEbcdicCodePage(_sRealName); } - return iDefaultEbcdicCodePage; + return _iDefaultEbcdicCodePage; } } - // Obtain locale name from LCID - // NOTE: This will get neutral names, unlike the OS API - [MethodImplAttribute(MethodImplOptions.InternalCall)] - internal static extern int LocaleNameToLCID(String localeName); - - // These are desktop only, not coreclr - // locale ID (0409), including sort information internal int ILANGUAGE { get { - if (iLanguage == 0) + if (_iLanguage == 0) { - Debug.Assert(sRealName != null, "[CultureData.ILANGUAGE] Expected this.sRealName to be populated by COMNlsInfo::nativeInitCultureData already"); - iLanguage = LocaleNameToLCID(sRealName); + Debug.Assert(_sRealName != null, "[CultureData.ILANGUAGE] Expected this.sRealName to be populated already"); + _iLanguage = LocaleNameToLCID(_sRealName); } - return iLanguage; + return _iLanguage; } } - internal bool IsWin32Installed - { - get { return bWin32Installed; } - } - - internal bool IsFramework - { - get { return bFramework; } - } - - //////////////////// - // Derived properties // - //////////////////// - internal bool IsNeutralCulture { get { - // NlsInfo::nativeInitCultureData told us if we're neutral or not - return bNeutral; + // InitCultureData told us if we're neutral or not + return _bNeutral; } } @@ -2092,7 +1967,8 @@ namespace System.Globalization { get { - int defaultCalId = DoGetLocaleInfoInt(LOCALE_ICALENDARTYPE); + CalendarId defaultCalId = (CalendarId)GetLocaleInfo(LocaleNumberData.CalendarType); + if (defaultCalId == 0) { defaultCalId = this.CalendarIds[0]; @@ -2103,29 +1979,29 @@ namespace System.Globalization } // All of our era names - internal String[] EraNames(int calendarId) + internal String[] EraNames(CalendarId calendarId) { Debug.Assert(calendarId > 0, "[CultureData.saEraNames] Expected Calendar.ID > 0"); return this.GetCalendar(calendarId).saEraNames; } - internal String[] AbbrevEraNames(int calendarId) + internal String[] AbbrevEraNames(CalendarId calendarId) { Debug.Assert(calendarId > 0, "[CultureData.saAbbrevEraNames] Expected Calendar.ID > 0"); return this.GetCalendar(calendarId).saAbbrevEraNames; } - internal String[] AbbreviatedEnglishEraNames(int calendarId) + internal String[] AbbreviatedEnglishEraNames(CalendarId calendarId) { Debug.Assert(calendarId > 0, "[CultureData.saAbbrevEraNames] Expected Calendar.ID > 0"); return this.GetCalendar(calendarId).saAbbrevEnglishEraNames; } - // String array DEFAULTS - // Note: GetDTFIOverrideValues does the user overrides for these, so we don't have to. + //// String array DEFAULTS + //// Note: GetDTFIOverrideValues does the user overrides for these, so we don't have to. // Time separator (derived from time format) @@ -2133,23 +2009,23 @@ namespace System.Globalization { get { - if (sTimeSeparator == null || UseUserOverride) + if (_sTimeSeparator == null) { - string longTimeFormat = ReescapeWin32String(DoGetLocaleInfo(LOCALE_STIMEFORMAT)); + string longTimeFormat = GetTimeFormatString(); if (String.IsNullOrEmpty(longTimeFormat)) { longTimeFormat = LongTimes[0]; } // Compute STIME from time format - sTimeSeparator = GetTimeSeparator(longTimeFormat); + _sTimeSeparator = GetTimeSeparator(longTimeFormat); } - return sTimeSeparator; + return _sTimeSeparator; } } // Date separator (derived from short date format) - internal String DateSeparator(int calendarId) + internal String DateSeparator(CalendarId calendarId) { return GetDateSeparator(ShortDates(calendarId)[0]); } @@ -2177,11 +2053,11 @@ namespace System.Globalization // always build a stringbuilder because we need to remove the ' or \. // //////////////////////////////////////////////////////////////////////////// - static private String UnescapeNlsString(String str, int start, int end) + private static String UnescapeNlsString(String str, int start, int end) { - Contract.Requires(str != null); - Contract.Requires(start >= 0); - Contract.Requires(end >= 0); + Debug.Assert(str != null); + Debug.Assert(start >= 0); + Debug.Assert(end >= 0); StringBuilder result = null; for (int i = start; i < str.Length && i <= end; i++) @@ -2220,102 +2096,7 @@ namespace System.Globalization return (result.ToString()); } - //////////////////////////////////////////////////////////////////////////// - // - // Reescape a Win32 style quote string as a NLS+ style quoted string - // - // This is also the escaping style used by custom culture data files - // - // NLS+ uses \ to escape the next character, whether in a quoted string or - // not, so we always have to change \ to \\. - // - // NLS+ uses \' to escape a quote inside a quoted string so we have to change - // '' to \' (if inside a quoted string) - // - // We don't build the stringbuilder unless we find something to change - //////////////////////////////////////////////////////////////////////////// - static internal String ReescapeWin32String(String str) - { - // If we don't have data, then don't try anything - if (str == null) - return null; - - StringBuilder result = null; - - bool inQuote = false; - for (int i = 0; i < str.Length; i++) - { - // Look for quote - if (str[i] == '\'') - { - // Already in quote? - if (inQuote) - { - // See another single quote. Is this '' of 'fred''s' or '''', or is it an ending quote? - if (i + 1 < str.Length && str[i + 1] == '\'') - { - // Found another ', so we have ''. Need to add \' instead. - // 1st make sure we have our stringbuilder - if (result == null) - result = new StringBuilder(str, 0, i, str.Length * 2); - - // Append a \' and keep going (so we don't turn off quote mode) - result.Append("\\'"); - i++; - continue; - } - - // Turning off quote mode, fall through to add it - inQuote = false; - } - else - { - // Found beginning quote, fall through to add it - inQuote = true; - } - } - // Is there a single \ character? - else if (str[i] == '\\') - { - // Found a \, need to change it to \\ - // 1st make sure we have our stringbuilder - if (result == null) - result = new StringBuilder(str, 0, i, str.Length * 2); - - // Append our \\ to the string & continue - result.Append("\\\\"); - continue; - } - - // If we have a builder we need to add our character - if (result != null) - result.Append(str[i]); - } - - // Unchanged string? , just return input string - if (result == null) - return str; - - // String changed, need to use the builder - return result.ToString(); - } - - static internal String[] ReescapeWin32Strings(String[] array) - { - if (array != null) - { - for (int i = 0; i < array.Length; i++) - { - array[i] = ReescapeWin32String(array[i]); - } - } - - return array; - } - - // NOTE: this method is used through reflection by System.Globalization.CultureXmlParser.ReadDateElement() - // and breaking changes here will not show up at build time, only at run time. - static private String GetTimeSeparator(String format) + private static String GetTimeSeparator(String format) { // Time format separator (ie: : in 12:39:00) // @@ -2328,9 +2109,7 @@ namespace System.Globalization return GetSeparator(format, "Hhms"); } - // NOTE: this method is used through reflection by System.Globalization.CultureXmlParser.ReadDateElement() - // and breaking changes here will not show up at build time, only at run time. - static private String GetDateSeparator(String format) + private static String GetDateSeparator(String format) { // Date format separator (ie: / in 9/1/03) // @@ -2412,128 +2191,61 @@ namespace System.Globalization return -1; } - private string DoGetLocaleInfo(uint lctype) - { - Debug.Assert(sWindowsName != null, "[CultureData.DoGetLocaleInfo] Expected this.sWindowsName to be populated by COMNlsInfo::nativeInitCultureData already"); - return DoGetLocaleInfo(sWindowsName, lctype); - } - - // For LOCALE_SPARENT we need the option of using the "real" name (forcing neutral names) instead of the - // "windows" name, which can be specific for downlevel (< windows 7) os's. - private string DoGetLocaleInfo(string localeName, uint lctype) - { - // Fix lctype if we don't want overrides - if (!UseUserOverride) - { - lctype |= LOCALE_NOUSEROVERRIDE; - } - - // Ask OS for data - Debug.Assert(localeName != null, "[CultureData.DoGetLocaleInfo] Expected localeName to be not be null"); - string result = CultureInfo.nativeGetLocaleInfoEx(localeName, lctype); - if (result == null) - { - // Failed, just use empty string - result = String.Empty; - } - - return result; - } - - private int DoGetLocaleInfoInt(uint lctype) - { - // Fix lctype if we don't want overrides - if (!UseUserOverride) - { - lctype |= LOCALE_NOUSEROVERRIDE; - } - - // Ask OS for data, note that we presume it returns success, so we have to know that - // sWindowsName is valid before calling. - Debug.Assert(sWindowsName != null, "[CultureData.DoGetLocaleInfoInt] Expected this.sWindowsName to be populated by COMNlsInfo::nativeInitCultureData already"); - int result = CultureInfo.nativeGetLocaleInfoExInt(sWindowsName, lctype); - - return result; - } - - private String[] DoEnumTimeFormats() - { - // Note that this gets overrides for us all the time - Debug.Assert(sWindowsName != null, "[CultureData.DoEnumTimeFormats] Expected this.sWindowsName to be populated by COMNlsInfo::nativeInitCultureData already"); - String[] result = ReescapeWin32Strings(nativeEnumTimeFormats(sWindowsName, 0, UseUserOverride)); - - return result; - } - - private String[] DoEnumShortTimeFormats() - { - // Note that this gets overrides for us all the time - Debug.Assert(sWindowsName != null, "[CultureData.DoEnumShortTimeFormats] Expected this.sWindowsName to be populated by COMNlsInfo::nativeInitCultureData already"); - String[] result = ReescapeWin32Strings(nativeEnumTimeFormats(sWindowsName, TIME_NOSECONDS, UseUserOverride)); - - return result; - } - - ///////////////// - // Static Helpers // - //////////////// internal static bool IsCustomCultureId(int cultureId) { - if (cultureId == CultureInfo.LOCALE_CUSTOM_DEFAULT || cultureId == CultureInfo.LOCALE_CUSTOM_UNSPECIFIED) - return true; - - return false; + return (cultureId == CultureInfo.LOCALE_CUSTOM_DEFAULT || cultureId == CultureInfo.LOCALE_CUSTOM_UNSPECIFIED); } - //////////////////////////////////////////////////////////////////////////// - // - // Parameters: - // calendarValueOnly Retrieve the values which are affected by the calendar change of DTFI. - // This will cause values like longTimePattern not be retrieved since it is - // not affected by the Calendar property in DTFI. - // - //////////////////////////////////////////////////////////////////////////// internal void GetNFIValues(NumberFormatInfo nfi) { if (this.IsInvariantCulture) { - nfi.positiveSign = sPositiveSign; - nfi.negativeSign = sNegativeSign; + // FUTURE: NumberFormatInfo already has default values for many of these fields. Can we not do this? + nfi.positiveSign = _sPositiveSign; + nfi.negativeSign = _sNegativeSign; - nfi.nativeDigits = saNativeDigits; - nfi.digitSubstitution = iDigitSubstitution; + nfi.numberGroupSeparator = _sThousandSeparator; + nfi.numberDecimalSeparator = _sDecimalSeparator; + nfi.numberDecimalDigits = _iDigits; + nfi.numberNegativePattern = _iNegativeNumber; - nfi.numberGroupSeparator = sThousandSeparator; - nfi.numberDecimalSeparator = sDecimalSeparator; - nfi.numberDecimalDigits = iDigits; - nfi.numberNegativePattern = iNegativeNumber; - - nfi.currencySymbol = sCurrency; - nfi.currencyGroupSeparator = sMonetaryThousand; - nfi.currencyDecimalSeparator = sMonetaryDecimal; - nfi.currencyDecimalDigits = iCurrencyDigits; - nfi.currencyNegativePattern = iNegativeCurrency; - nfi.currencyPositivePattern = iCurrency; + nfi.currencySymbol = _sCurrency; + nfi.currencyGroupSeparator = _sMonetaryThousand; + nfi.currencyDecimalSeparator = _sMonetaryDecimal; + nfi.currencyDecimalDigits = _iCurrencyDigits; + nfi.currencyNegativePattern = _iNegativeCurrency; + nfi.currencyPositivePattern = _iCurrency; } else { - // - // We don't have information for the following four. All cultures use - // the same value of the number formatting values. - // - // PercentDecimalDigits - // PercentDecimalSeparator - // PercentGroupSize - // PercentGroupSeparator - // + Debug.Assert(_sWindowsName != null, "[CultureData.GetNFIValues] Expected _sWindowsName to be populated by already"); + // String values + nfi.positiveSign = GetLocaleInfo(LocaleStringData.PositiveSign); + nfi.negativeSign = GetLocaleInfo(LocaleStringData.NegativeSign); - // - // Ask native side for our data. - // - Debug.Assert(sWindowsName != null, "[CultureData.GetNFIValues] Expected this.sWindowsName to be populated by COMNlsInfo::nativeInitCultureData already"); - CultureData.nativeGetNumberFormatInfoValues(sWindowsName, nfi, UseUserOverride); - } + nfi.numberDecimalSeparator = GetLocaleInfo(LocaleStringData.DecimalSeparator); + nfi.numberGroupSeparator = GetLocaleInfo(LocaleStringData.ThousandSeparator); + nfi.currencyGroupSeparator = GetLocaleInfo(LocaleStringData.MonetaryThousandSeparator); + nfi.currencyDecimalSeparator = GetLocaleInfo(LocaleStringData.MonetaryDecimalSeparator); + nfi.currencySymbol = GetLocaleInfo(LocaleStringData.MonetarySymbol); + + // Numeric values + nfi.numberDecimalDigits = GetLocaleInfo(LocaleNumberData.FractionalDigitsCount); + nfi.currencyDecimalDigits = GetLocaleInfo(LocaleNumberData.MonetaryFractionalDigitsCount); + nfi.currencyPositivePattern = GetLocaleInfo(LocaleNumberData.PositiveMonetaryNumberFormat); + nfi.currencyNegativePattern = GetLocaleInfo(LocaleNumberData.NegativeMonetaryNumberFormat); + nfi.numberNegativePattern = GetLocaleInfo(LocaleNumberData.NegativeNumberFormat); + + // LOCALE_SNATIVEDIGITS (array of 10 single character strings). + string digits = GetLocaleInfo(LocaleStringData.Digits); + nfi.nativeDigits = new string[10]; + for (int i = 0; i < nfi.nativeDigits.Length; i++) + { + nfi.nativeDigits[i] = new string(digits[i], 1); + } + nfi.digitSubstitution = GetDigitSubstitution(_sRealName); + } // // Gather additional data @@ -2568,289 +2280,188 @@ namespace System.Globalization //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 workaround this here because our default currency format will never use nfi. + //decimal point doesn't show up. We'll just hack this here because our default currency format will never use nfi. if (nfi.currencyDecimalSeparator == null || nfi.currencyDecimalSeparator.Length == 0) { nfi.currencyDecimalSeparator = nfi.numberDecimalSeparator; } } - static private int ConvertFirstDayOfWeekMonToSun(int iTemp) - { - // Convert Mon-Sun to Sun-Sat format - iTemp++; - if (iTemp > 6) - { - // Wrap Sunday and convert invalid data to Sunday - iTemp = 0; - } - return iTemp; - } - // Helper // This is ONLY used for caching names and shouldn't be used for anything else internal static string AnsiToLower(string testString) { - StringBuilder sb = new StringBuilder(testString.Length); - - for (int ich = 0; ich < testString.Length; ich++) + int index = 0; + + while (index'Z' )) { - char ch = testString[ich]; - sb.Append(ch <= 'Z' && ch >= 'A' ? (char)(ch - 'A' + 'a') : ch); + index++; } - - return (sb.ToString()); - } - - // If we get a group from windows, then its in 3;0 format with the 0 backwards - // of how NLS+ uses it (ie: if the string has a 0, then the int[] shouldn't and vice versa) - // EXCEPT in the case where the list only contains 0 in which NLS and NLS+ have the same meaning. - static private int[] ConvertWin32GroupString(String win32Str) - { - // None of these cases make any sense - if (win32Str == null || win32Str.Length == 0) + if (index >= testString.Length) { - return (new int[] { 3 }); + return testString; // we didn't really change the string } - - if (win32Str[0] == '0') + + StringBuilder sb = new StringBuilder(testString.Length); + for (int i=0; i 1 - values = new int[(win32Str.Length / 2)]; - } - else - { - // Need extra space for trailing zero 1 -> 1;0 - values = new int[(win32Str.Length / 2) + 2]; - values[values.Length - 1] = 0; - } + sb.Append((char) (testString[index] -'A' + 'a')); - int i; - int j; - for (i = 0, j = 0; i < win32Str.Length && j < values.Length; i += 2, j++) + for (int ich = index+1; ich < testString.Length; ich++) { - // Note that this # shouldn't ever be zero, 'cause 0 is only at end - // But we'll test because its registry that could be anything - if (win32Str[i] < '1' || win32Str[i] > '9') - return new int[] { 3 }; - - values[j] = (int)(win32Str[i] - '0'); + char ch = testString[ich]; + sb.Append(ch <= 'Z' && ch >= 'A' ? (char)(ch - 'A' + 'a') : ch); } - return (values); + return (sb.ToString()); } - // LCTYPES for GetLocaleInfo - private const uint LOCALE_NOUSEROVERRIDE = 0x80000000; // do not use user overrides - private const uint LOCALE_RETURN_NUMBER = 0x20000000; // return number instead of string - - // Modifier for genitive names - private const uint LOCALE_RETURN_GENITIVE_NAMES = 0x10000000; //Flag to return the Genitive forms of month names - - // - // The following LCTypes are mutually exclusive in that they may NOT - // be used in combination with each other. - // - - // - // These are the various forms of the name of the locale: - // - private const uint LOCALE_SLOCALIZEDDISPLAYNAME = 0x00000002; // localized name of locale, eg "German (Germany)" in UI language - private const uint LOCALE_SENGLISHDISPLAYNAME = 0x00000072; // Display name (language + country usually) in English, eg "German (Germany)" - private const uint LOCALE_SNATIVEDISPLAYNAME = 0x00000073; // Display name in native locale language, eg "Deutsch (Deutschland) - - private const uint LOCALE_SLOCALIZEDLANGUAGENAME = 0x0000006f; // Language Display Name for a language, eg "German" in UI language - private const uint LOCALE_SENGLISHLANGUAGENAME = 0x00001001; // English name of language, eg "German" - private const uint LOCALE_SNATIVELANGUAGENAME = 0x00000004; // native name of language, eg "Deutsch" - - private const uint LOCALE_SLOCALIZEDCOUNTRYNAME = 0x00000006; // localized name of country, eg "Germany" in UI language - private const uint LOCALE_SENGLISHCOUNTRYNAME = 0x00001002; // English name of country, eg "Germany" - private const uint LOCALE_SNATIVECOUNTRYNAME = 0x00000008; // native name of country, eg "Deutschland" - - - // private const uint LOCALE_ILANGUAGE =0x00000001; // language id // Don't use, use NewApis::LocaleNameToLCID instead (GetLocaleInfo doesn't return neutrals) - - // private const uint LOCALE_SLANGUAGE =LOCALE_SLOCALIZEDDISPLAYNAME; // localized name of language (use LOCALE_SLOCALIZEDDISPLAYNAME instead) - // private const uint LOCALE_SENGLANGUAGE =LOCALE_SENGLISHLANGUAGENAME; // English name of language (use LOCALE_SENGLISHLANGUAGENAME instead) - private const uint LOCALE_SABBREVLANGNAME = 0x00000003; // abbreviated language name - // private const uint LOCALE_SNATIVELANGNAME =LOCALE_SNATIVELANGUAGENAME; // native name of language (use LOCALE_SNATIVELANGUAGENAME instead) - - private const uint LOCALE_ICOUNTRY = 0x00000005; // country code - // private const uint LOCALE_SCOUNTRY =LOCALE_SLOCALIZEDCOUNTRYNAME; // localized name of country (use LOCALE_SLOCALIZEDCOUNTRYNAME instead) - // private const uint LOCALE_SENGCOUNTRY =LOCALE_SENGLISHCOUNTRYNAME; // English name of country (use LOCALE_SENGLISHCOUNTRYNAME instead) - private const uint LOCALE_SABBREVCTRYNAME = 0x00000007; // abbreviated country name - // private const uint LOCALE_SNATIVECTRYNAME =LOCALE_SNATIVECOUNTRYNAME; // native name of country ( use LOCALE_SNATIVECOUNTRYNAME instead) - private const uint LOCALE_IGEOID = 0x0000005B; // geographical location id - - private const uint LOCALE_IDEFAULTLANGUAGE = 0x00000009; // default language id - private const uint LOCALE_IDEFAULTCOUNTRY = 0x0000000A; // default country code - private const uint LOCALE_IDEFAULTCODEPAGE = 0x0000000B; // default oem code page - private const uint LOCALE_IDEFAULTANSICODEPAGE = 0x00001004; // default ansi code page - private const uint LOCALE_IDEFAULTMACCODEPAGE = 0x00001011; // default mac code page - - private const uint LOCALE_SLIST = 0x0000000C; // list item separator - private const uint LOCALE_IMEASURE = 0x0000000D; // 0 = metric, 1 = US - - private const uint LOCALE_SDECIMAL = 0x0000000E; // decimal separator - private const uint LOCALE_STHOUSAND = 0x0000000F; // thousand separator - private const uint LOCALE_SGROUPING = 0x00000010; // digit grouping - private const uint LOCALE_IDIGITS = 0x00000011; // number of fractional digits - private const uint LOCALE_ILZERO = 0x00000012; // leading zeros for decimal - private const uint LOCALE_INEGNUMBER = 0x00001010; // negative number mode - private const uint LOCALE_SNATIVEDIGITS = 0x00000013; // native digits for 0-9 - - private const uint LOCALE_SCURRENCY = 0x00000014; // local monetary symbol - private const uint LOCALE_SINTLSYMBOL = 0x00000015; // uintl monetary symbol - private const uint LOCALE_SMONDECIMALSEP = 0x00000016; // monetary decimal separator - private const uint LOCALE_SMONTHOUSANDSEP = 0x00000017; // monetary thousand separator - private const uint LOCALE_SMONGROUPING = 0x00000018; // monetary grouping - private const uint LOCALE_ICURRDIGITS = 0x00000019; // # local monetary digits - private const uint LOCALE_IINTLCURRDIGITS = 0x0000001A; // # uintl monetary digits - private const uint LOCALE_ICURRENCY = 0x0000001B; // positive currency mode - private const uint LOCALE_INEGCURR = 0x0000001C; // negative currency mode - - private const uint LOCALE_SDATE = 0x0000001D; // date separator (derived from LOCALE_SSHORTDATE, use that instead) - private const uint LOCALE_STIME = 0x0000001E; // time separator (derived from LOCALE_STIMEFORMAT, use that instead) - private const uint LOCALE_SSHORTDATE = 0x0000001F; // short date format string - private const uint LOCALE_SLONGDATE = 0x00000020; // long date format string - private const uint LOCALE_STIMEFORMAT = 0x00001003; // time format string - private const uint LOCALE_IDATE = 0x00000021; // short date format ordering (derived from LOCALE_SSHORTDATE, use that instead) - private const uint LOCALE_ILDATE = 0x00000022; // long date format ordering (derived from LOCALE_SLONGDATE, use that instead) - private const uint LOCALE_ITIME = 0x00000023; // time format specifier (derived from LOCALE_STIMEFORMAT, use that instead) - private const uint LOCALE_ITIMEMARKPOSN = 0x00001005; // time marker position (derived from LOCALE_STIMEFORMAT, use that instead) - private const uint LOCALE_ICENTURY = 0x00000024; // century format specifier (short date, LOCALE_SSHORTDATE is preferred) - private const uint LOCALE_ITLZERO = 0x00000025; // leading zeros in time field (derived from LOCALE_STIMEFORMAT, use that instead) - private const uint LOCALE_IDAYLZERO = 0x00000026; // leading zeros in day field (short date, LOCALE_SSHORTDATE is preferred) - private const uint LOCALE_IMONLZERO = 0x00000027; // leading zeros in month field (short date, LOCALE_SSHORTDATE is preferred) - private const uint LOCALE_S1159 = 0x00000028; // AM designator - private const uint LOCALE_S2359 = 0x00000029; // PM designator - - private const uint LOCALE_ICALENDARTYPE = 0x00001009; // type of calendar specifier - private const uint LOCALE_IOPTIONALCALENDAR = 0x0000100B; // additional calendar types specifier - private const uint LOCALE_IFIRSTDAYOFWEEK = 0x0000100C; // first day of week specifier - private const uint LOCALE_IFIRSTWEEKOFYEAR = 0x0000100D; // first week of year specifier - - private const uint LOCALE_SDAYNAME1 = 0x0000002A; // long name for Monday - private const uint LOCALE_SDAYNAME2 = 0x0000002B; // long name for Tuesday - private const uint LOCALE_SDAYNAME3 = 0x0000002C; // long name for Wednesday - private const uint LOCALE_SDAYNAME4 = 0x0000002D; // long name for Thursday - private const uint LOCALE_SDAYNAME5 = 0x0000002E; // long name for Friday - private const uint LOCALE_SDAYNAME6 = 0x0000002F; // long name for Saturday - private const uint LOCALE_SDAYNAME7 = 0x00000030; // long name for Sunday - private const uint LOCALE_SABBREVDAYNAME1 = 0x00000031; // abbreviated name for Monday - private const uint LOCALE_SABBREVDAYNAME2 = 0x00000032; // abbreviated name for Tuesday - private const uint LOCALE_SABBREVDAYNAME3 = 0x00000033; // abbreviated name for Wednesday - private const uint LOCALE_SABBREVDAYNAME4 = 0x00000034; // abbreviated name for Thursday - private const uint LOCALE_SABBREVDAYNAME5 = 0x00000035; // abbreviated name for Friday - private const uint LOCALE_SABBREVDAYNAME6 = 0x00000036; // abbreviated name for Saturday - private const uint LOCALE_SABBREVDAYNAME7 = 0x00000037; // abbreviated name for Sunday - private const uint LOCALE_SMONTHNAME1 = 0x00000038; // long name for January - private const uint LOCALE_SMONTHNAME2 = 0x00000039; // long name for February - private const uint LOCALE_SMONTHNAME3 = 0x0000003A; // long name for March - private const uint LOCALE_SMONTHNAME4 = 0x0000003B; // long name for April - private const uint LOCALE_SMONTHNAME5 = 0x0000003C; // long name for May - private const uint LOCALE_SMONTHNAME6 = 0x0000003D; // long name for June - private const uint LOCALE_SMONTHNAME7 = 0x0000003E; // long name for July - private const uint LOCALE_SMONTHNAME8 = 0x0000003F; // long name for August - private const uint LOCALE_SMONTHNAME9 = 0x00000040; // long name for September - private const uint LOCALE_SMONTHNAME10 = 0x00000041; // long name for October - private const uint LOCALE_SMONTHNAME11 = 0x00000042; // long name for November - private const uint LOCALE_SMONTHNAME12 = 0x00000043; // long name for December - private const uint LOCALE_SMONTHNAME13 = 0x0000100E; // long name for 13th month (if exists) - private const uint LOCALE_SABBREVMONTHNAME1 = 0x00000044; // abbreviated name for January - private const uint LOCALE_SABBREVMONTHNAME2 = 0x00000045; // abbreviated name for February - private const uint LOCALE_SABBREVMONTHNAME3 = 0x00000046; // abbreviated name for March - private const uint LOCALE_SABBREVMONTHNAME4 = 0x00000047; // abbreviated name for April - private const uint LOCALE_SABBREVMONTHNAME5 = 0x00000048; // abbreviated name for May - private const uint LOCALE_SABBREVMONTHNAME6 = 0x00000049; // abbreviated name for June - private const uint LOCALE_SABBREVMONTHNAME7 = 0x0000004A; // abbreviated name for July - private const uint LOCALE_SABBREVMONTHNAME8 = 0x0000004B; // abbreviated name for August - private const uint LOCALE_SABBREVMONTHNAME9 = 0x0000004C; // abbreviated name for September - private const uint LOCALE_SABBREVMONTHNAME10 = 0x0000004D; // abbreviated name for October - private const uint LOCALE_SABBREVMONTHNAME11 = 0x0000004E; // abbreviated name for November - private const uint LOCALE_SABBREVMONTHNAME12 = 0x0000004F; // abbreviated name for December - private const uint LOCALE_SABBREVMONTHNAME13 = 0x0000100F; // abbreviated name for 13th month (if exists) - - private const uint LOCALE_SPOSITIVESIGN = 0x00000050; // positive sign - private const uint LOCALE_SNEGATIVESIGN = 0x00000051; // negative sign - private const uint LOCALE_IPOSSIGNPOSN = 0x00000052; // positive sign position (derived from INEGCURR) - private const uint LOCALE_INEGSIGNPOSN = 0x00000053; // negative sign position (derived from INEGCURR) - private const uint LOCALE_IPOSSYMPRECEDES = 0x00000054; // mon sym precedes pos amt (derived from ICURRENCY) - private const uint LOCALE_IPOSSEPBYSPACE = 0x00000055; // mon sym sep by space from pos amt (derived from ICURRENCY) - private const uint LOCALE_INEGSYMPRECEDES = 0x00000056; // mon sym precedes neg amt (derived from INEGCURR) - private const uint LOCALE_INEGSEPBYSPACE = 0x00000057; // mon sym sep by space from neg amt (derived from INEGCURR) - - private const uint LOCALE_FONTSIGNATURE = 0x00000058; // font signature - private const uint LOCALE_SISO639LANGNAME = 0x00000059; // ISO abbreviated language name - private const uint LOCALE_SISO3166CTRYNAME = 0x0000005A; // ISO abbreviated country name - - private const uint LOCALE_IDEFAULTEBCDICCODEPAGE = 0x00001012; // default ebcdic code page - private const uint LOCALE_IPAPERSIZE = 0x0000100A; // 1 = letter, 5 = legal, 8 = a3, 9 = a4 - private const uint LOCALE_SENGCURRNAME = 0x00001007; // english name of currency - private const uint LOCALE_SNATIVECURRNAME = 0x00001008; // native name of currency - private const uint LOCALE_SYEARMONTH = 0x00001006; // year month format string - private const uint LOCALE_SSORTNAME = 0x00001013; // sort name - private const uint LOCALE_IDIGITSUBSTITUTION = 0x00001014; // 0 = context, 1 = none, 2 = national - - private const uint LOCALE_SNAME = 0x0000005c; // locale name (with sort info) (ie: de-DE_phoneb) - private const uint LOCALE_SDURATION = 0x0000005d; // time duration format - private const uint LOCALE_SKEYBOARDSTOINSTALL = 0x0000005e; // (windows only) keyboards to install - private const uint LOCALE_SSHORTESTDAYNAME1 = 0x00000060; // Shortest day name for Monday - private const uint LOCALE_SSHORTESTDAYNAME2 = 0x00000061; // Shortest day name for Tuesday - private const uint LOCALE_SSHORTESTDAYNAME3 = 0x00000062; // Shortest day name for Wednesday - private const uint LOCALE_SSHORTESTDAYNAME4 = 0x00000063; // Shortest day name for Thursday - private const uint LOCALE_SSHORTESTDAYNAME5 = 0x00000064; // Shortest day name for Friday - private const uint LOCALE_SSHORTESTDAYNAME6 = 0x00000065; // Shortest day name for Saturday - private const uint LOCALE_SSHORTESTDAYNAME7 = 0x00000066; // Shortest day name for Sunday - private const uint LOCALE_SISO639LANGNAME2 = 0x00000067; // 3 character ISO abbreviated language name - private const uint LOCALE_SISO3166CTRYNAME2 = 0x00000068; // 3 character ISO country name - private const uint LOCALE_SNAN = 0x00000069; // Not a Number - private const uint LOCALE_SPOSINFINITY = 0x0000006a; // + Infinity - private const uint LOCALE_SNEGINFINITY = 0x0000006b; // - Infinity - private const uint LOCALE_SSCRIPTS = 0x0000006c; // Typical scripts in the locale - private const uint LOCALE_SPARENT = 0x0000006d; // Fallback name for resources - private const uint LOCALE_SCONSOLEFALLBACKNAME = 0x0000006e; // Fallback name for within the console - // private const uint LOCALE_SLANGDISPLAYNAME =LOCALE_SLOCALIZEDLANGUAGENAME; // Language Display Name for a language (use LOCALE_SLOCALIZEDLANGUAGENAME instead) - - // Windows 7 LCTYPES - private const uint LOCALE_IREADINGLAYOUT = 0x00000070; // Returns one of the following 4 reading layout values: - // 0 - Left to right (eg en-US) - // 1 - Right to left (eg arabic locales) - // 2 - Vertical top to bottom with columns to the left and also left to right (ja-JP locales) - // 3 - Vertical top to bottom with columns proceeding to the right - private const uint LOCALE_INEUTRAL = 0x00000071; // Returns 0 for specific cultures, 1 for neutral cultures. - private const uint LOCALE_INEGATIVEPERCENT = 0x00000074; // Returns 0-11 for the negative percent format - private const uint LOCALE_IPOSITIVEPERCENT = 0x00000075; // Returns 0-3 for the positive percent formatIPOSITIVEPERCENT - private const uint LOCALE_SPERCENT = 0x00000076; // Returns the percent symbol - private const uint LOCALE_SPERMILLE = 0x00000077; // Returns the permille (U+2030) symbol - private const uint LOCALE_SMONTHDAY = 0x00000078; // Returns the preferred month/day format - private const uint LOCALE_SSHORTTIME = 0x00000079; // Returns the preferred short time format (ie: no seconds, just h:mm) - private const uint LOCALE_SOPENTYPELANGUAGETAG = 0x0000007a; // Open type language tag, eg: "latn" or "dflt" - private const uint LOCALE_SSORTLOCALE = 0x0000007b; // Name of locale to use for sorting/collation/casing behavior. - - // Time formats enumerations - internal const uint TIME_NOSECONDS = 0x00000002; // Don't use seconds (get short time format for enumtimeformats on win7+) - - // Get our initial minimal culture data (name, parent, etc.) - [MethodImplAttribute(MethodImplOptions.InternalCall)] - internal static extern bool nativeInitCultureData(CultureData cultureData); - - // Grab the NumberFormatInfo data - [MethodImplAttribute(MethodImplOptions.InternalCall)] - internal static extern bool nativeGetNumberFormatInfoValues(String localeName, NumberFormatInfo nfi, bool useUserOverride); - - [MethodImplAttribute(MethodImplOptions.InternalCall)] - private static extern String[] nativeEnumTimeFormats(String localeName, uint dwFlags, bool useUserOverride); - - [SuppressUnmanagedCodeSecurityAttribute()] - [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] - internal static extern int nativeEnumCultureNames(int cultureTypes, ObjectHandleOnStack retStringArray); + /// + /// The numeric values of the enum members match their Win32 counterparts. The CultureData Win32 PAL implementation + /// takes a dependency on this fact, in order to prevent having to construct a mapping from internal values to LCTypes. + /// + private enum LocaleStringData : uint + { + /// localized name of locale, eg "German (Germany)" in UI language (coresponds to LOCALE_SLOCALIZEDDISPLAYNAME) + LocalizedDisplayName = 0x00000002, + /// Display name (language + country usually) in English, eg "German (Germany)" (coresponds to LOCALE_SENGLISHDISPLAYNAME) + EnglishDisplayName = 0x00000072, + /// Display name in native locale language, eg "Deutsch (Deutschland) (coresponds to LOCALE_SNATIVEDISPLAYNAME) + NativeDisplayName = 0x00000073, + /// Language Display Name for a language, eg "German" in UI language (coresponds to LOCALE_SLOCALIZEDLANGUAGENAME) + LocalizedLanguageName = 0x0000006f, + /// English name of language, eg "German" (coresponds to LOCALE_SENGLISHLANGUAGENAME) + EnglishLanguageName = 0x00001001, + /// native name of language, eg "Deutsch" (coresponds to LOCALE_SNATIVELANGUAGENAME) + NativeLanguageName = 0x00000004, + /// localized name of country, eg "Germany" in UI language (coresponds to LOCALE_SLOCALIZEDCOUNTRYNAME) + LocalizedCountryName = 0x00000006, + /// English name of country, eg "Germany" (coresponds to LOCALE_SENGLISHCOUNTRYNAME) + EnglishCountryName = 0x00001002, + /// native name of country, eg "Deutschland" (coresponds to LOCALE_SNATIVECOUNTRYNAME) + NativeCountryName = 0x00000008, + /// abbreviated language name (coresponds to LOCALE_SABBREVLANGNAME) + AbbreviatedWindowsLanguageName = 0x00000003, + /// list item separator (coresponds to LOCALE_SLIST) + ListSeparator = 0x0000000C, + /// decimal separator (coresponds to LOCALE_SDECIMAL) + DecimalSeparator = 0x0000000E, + /// thousand separator (coresponds to LOCALE_STHOUSAND) + ThousandSeparator = 0x0000000F, + /// digit grouping (coresponds to LOCALE_SGROUPING) + Digits = 0x00000013, + /// local monetary symbol (coresponds to LOCALE_SCURRENCY) + MonetarySymbol = 0x00000014, + /// English currency name (coresponds to LOCALE_SENGCURRNAME) + CurrencyEnglishName = 0x00001007, + /// Native currency name (coresponds to LOCALE_SNATIVECURRNAME) + CurrencyNativeName = 0x00001008, + /// uintl monetary symbol (coresponds to LOCALE_SINTLSYMBOL) + Iso4217MonetarySymbol = 0x00000015, + /// monetary decimal separator (coresponds to LOCALE_SMONDECIMALSEP) + MonetaryDecimalSeparator = 0x00000016, + /// monetary thousand separator (coresponds to LOCALE_SMONTHOUSANDSEP) + MonetaryThousandSeparator = 0x00000017, + /// AM designator (coresponds to LOCALE_S1159) + AMDesignator = 0x00000028, + /// PM designator (coresponds to LOCALE_S2359) + PMDesignator = 0x00000029, + /// positive sign (coresponds to LOCALE_SPOSITIVESIGN) + PositiveSign = 0x00000050, + /// negative sign (coresponds to LOCALE_SNEGATIVESIGN) + NegativeSign = 0x00000051, + /// ISO abbreviated language name (coresponds to LOCALE_SISO639LANGNAME) + Iso639LanguageTwoLetterName = 0x00000059, + /// ISO abbreviated country name (coresponds to LOCALE_SISO639LANGNAME2) + Iso639LanguageThreeLetterName = 0x00000067, + /// ISO abbreviated language name (coresponds to LOCALE_SISO639LANGNAME) + Iso639LanguageName = 0x00000059, + /// ISO abbreviated country name (coresponds to LOCALE_SISO3166CTRYNAME) + Iso3166CountryName = 0x0000005A, + /// 3 letter ISO country code (coresponds to LOCALE_SISO3166CTRYNAME2) + Iso3166CountryName2 = 0x00000068, // 3 character ISO country name + /// Not a Number (coresponds to LOCALE_SNAN) + NaNSymbol = 0x00000069, + /// + Infinity (coresponds to LOCALE_SPOSINFINITY) + PositiveInfinitySymbol = 0x0000006a, + /// - Infinity (coresponds to LOCALE_SNEGINFINITY) + NegativeInfinitySymbol = 0x0000006b, + /// Fallback name for resources (coresponds to LOCALE_SPARENT) + ParentName = 0x0000006d, + /// Fallback name for within the console (coresponds to LOCALE_SCONSOLEFALLBACKNAME) + ConsoleFallbackName = 0x0000006e, + /// Returns the percent symbol (coresponds to LOCALE_SPERCENT) + PercentSymbol = 0x00000076, + /// Returns the permille (U+2030) symbol (coresponds to LOCALE_SPERMILLE) + PerMilleSymbol = 0x00000077 + } + + /// + /// The numeric values of the enum members match their Win32 counterparts. The CultureData Win32 PAL implementation + /// takes a dependency on this fact, in order to prevent having to construct a mapping from internal values to LCTypes. + /// + private enum LocaleGroupingData : uint + { + /// digit grouping (coresponds to LOCALE_SGROUPING) + Digit = 0x00000010, + /// monetary grouping (coresponds to LOCALE_SMONGROUPING) + Monetary = 0x00000018, + } + + /// + /// The numeric values of the enum members match their Win32 counterparts. The CultureData Win32 PAL implementation + /// takes a dependency on this fact, in order to prevent having to construct a mapping from internal values to LCTypes. + /// + private enum LocaleNumberData : uint + { + /// language id (coresponds to LOCALE_ILANGUAGE) + LanguageId = 0x00000001, + /// geographical location id, (coresponds to LOCALE_IGEOID) + GeoId = 0x0000005B, + /// 0 = context, 1 = none, 2 = national (coresponds to LOCALE_IDIGITSUBSTITUTION) + DigitSubstitution = 0x00001014, + /// 0 = metric, 1 = US (coresponds to LOCALE_IMEASURE) + MeasurementSystem = 0x0000000D, + /// number of fractional digits (coresponds to LOCALE_IDIGITS) + FractionalDigitsCount = 0x00000011, + /// negative number mode (coresponds to LOCALE_INEGNUMBER) + NegativeNumberFormat = 0x00001010, + /// # local monetary digits (coresponds to LOCALE_ICURRDIGITS) + MonetaryFractionalDigitsCount = 0x00000019, + /// positive currency mode (coresponds to LOCALE_ICURRENCY) + PositiveMonetaryNumberFormat = 0x0000001B, + /// negative currency mode (coresponds to LOCALE_INEGCURR) + NegativeMonetaryNumberFormat = 0x0000001C, + /// type of calendar specifier (coresponds to LOCALE_ICALENDARTYPE) + CalendarType = 0x00001009, + /// first day of week specifier (coresponds to LOCALE_IFIRSTDAYOFWEEK) + FirstDayOfWeek = 0x0000100C, + /// first week of year specifier (coresponds to LOCALE_IFIRSTWEEKOFYEAR) + FirstWeekOfYear = 0x0000100D, + /// + /// Returns one of the following 4 reading layout values: + /// 0 - Left to right (eg en-US) + /// 1 - Right to left (eg arabic locales) + /// 2 - Vertical top to bottom with columns to the left and also left to right (ja-JP locales) + /// 3 - Vertical top to bottom with columns proceeding to the right + /// (coresponds to LOCALE_IREADINGLAYOUT) + /// + ReadingLayout = 0x00000070, + /// Returns 0-11 for the negative percent format (coresponds to LOCALE_INEGATIVEPERCENT) + NegativePercentFormat = 0x00000074, + /// Returns 0-3 for the positive percent format (coresponds to LOCALE_IPOSITIVEPERCENT) + PositivePercentFormat = 0x00000075, + /// default ansi code page (coresponds to LOCALE_IDEFAULTCODEPAGE) + OemCodePage = 0x0000000B, + /// default ansi code page (coresponds to LOCALE_IDEFAULTANSICODEPAGE) + AnsiCodePage = 0x00001004, + /// default mac code page (coresponds to LOCALE_IDEFAULTMACCODEPAGE) + MacCodePage = 0x00001011, + /// default ebcdic code page (coresponds to LOCALE_IDEFAULTEBCDICCODEPAGE) + EbcdicCodePage = 0x00001012, + } } } diff --git a/src/mscorlib/src/System/Globalization/CultureInfo.Unix.cs b/src/mscorlib/src/System/Globalization/CultureInfo.Unix.cs new file mode 100644 index 0000000..d7950b0 --- /dev/null +++ b/src/mscorlib/src/System/Globalization/CultureInfo.Unix.cs @@ -0,0 +1,124 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Threading; + +namespace System.Globalization +{ + public partial class CultureInfo : IFormatProvider + { + private static CultureInfo GetUserDefaultCultureCacheOverride() + { + return null; // ICU doesn't provide a user override + } + + internal static CultureInfo GetUserDefaultCulture() + { + CultureInfo cultureInfo = null; + string localeName; + if (CultureData.GetDefaultLocaleName(out localeName)) + { + cultureInfo = GetCultureByName(localeName, true); + cultureInfo._isReadOnly = true; + } + else + { + cultureInfo = CultureInfo.InvariantCulture; + } + + return cultureInfo; + } + + private static CultureInfo GetUserDefaultUILanguage() + { + return GetUserDefaultCulture(); + } + + //////////////////////////////////////////////////////////////////////// + // + // CurrentCulture + // + // This instance provides methods based on the current user settings. + // These settings are volatile and may change over the lifetime of the + // thread. + // + //////////////////////////////////////////////////////////////////////// + + // + // We use the following order to return CurrentCulture and CurrentUICulture + // o use current thread culture if the user already set one using CurrentCulture/CurrentUICulture + // o use thread culture if the user already set one using DefaultThreadCurrentCulture + // or DefaultThreadCurrentUICulture + // o Use NLS default user culture + // o Use NLS default system culture + // o Use Invariant culture + // + public static CultureInfo CurrentCulture + { + get + { + if (Thread.m_CurrentCulture != null) + { + return Thread.m_CurrentCulture; + } + + CultureInfo ci = s_DefaultThreadCurrentCulture; + if (ci != null) + { + return ci; + } + + // if s_userDefaultCulture == null means CultureInfo statics didn't get initialized yet. this can happen if there early static + // method get executed which eventually hit the cultureInfo code while CultureInfo statics didn’t get chance to initialize + if (s_userDefaultCulture == null) + { + Init(); + } + + Debug.Assert(s_userDefaultCulture != null); + return s_userDefaultCulture; + } + + set + { + if (value == null) + { + throw new ArgumentNullException(nameof(value)); + } + + if (s_asyncLocalCurrentCulture == null) + { + Interlocked.CompareExchange(ref s_asyncLocalCurrentCulture, new AsyncLocal(AsyncLocalSetCurrentCulture), null); + } + s_asyncLocalCurrentCulture.Value = value; + } + } + + public static CultureInfo CurrentUICulture + { + get + { + return GetCurrentUICultureNoAppX(); + } + + set + { + if (value == null) + { + throw new ArgumentNullException(nameof(value)); + } + + CultureInfo.VerifyCultureName(value, true); + if (s_asyncLocalCurrentUICulture == null) + { + Interlocked.CompareExchange(ref s_asyncLocalCurrentUICulture, new AsyncLocal(AsyncLocalSetCurrentUICulture), null); + } + + // this one will set s_currentThreadUICulture too + s_asyncLocalCurrentUICulture.Value = value; + } + } + + } +} diff --git a/src/mscorlib/src/System/Globalization/CultureInfo.Windows.cs b/src/mscorlib/src/System/Globalization/CultureInfo.Windows.cs new file mode 100644 index 0000000..941b9d6 --- /dev/null +++ b/src/mscorlib/src/System/Globalization/CultureInfo.Windows.cs @@ -0,0 +1,292 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#if ENABLE_WINRT +using Internal.Runtime.Augments; +#endif + +using System.Threading; +#if FEATURE_APPX +using System.Resources; +#endif + +namespace System.Globalization +{ + public partial class CultureInfo : IFormatProvider + { +#if FEATURE_APPX + // When running under AppX, we use this to get some information about the language list + private static volatile WindowsRuntimeResourceManagerBase s_WindowsRuntimeResourceManager; + + [ThreadStatic] + private static bool ts_IsDoingAppXCultureInfoLookup; +#endif + + /// + /// Gets the default user culture from WinRT, if available. + /// + /// + /// This method may return null, if there is no default user culture or if WinRT isn't available. + /// + private static CultureInfo GetUserDefaultCultureCacheOverride() + { +#if ENABLE_WINRT + WinRTInteropCallbacks callbacks = WinRTInterop.UnsafeCallbacks; + if (callbacks != null && callbacks.IsAppxModel()) + { + return (CultureInfo)callbacks.GetUserDefaultCulture(); + } +#endif + + return null; + } + + internal static CultureInfo GetUserDefaultCulture() + { + const uint LOCALE_SNAME = 0x0000005c; + const string LOCALE_NAME_USER_DEFAULT = null; + const string LOCALE_NAME_SYSTEM_DEFAULT = "!x-sys-default-locale"; + + string strDefault = CultureData.GetLocaleInfoEx(LOCALE_NAME_USER_DEFAULT, LOCALE_SNAME); + if (strDefault == null) + { + strDefault = CultureData.GetLocaleInfoEx(LOCALE_NAME_SYSTEM_DEFAULT, LOCALE_SNAME); + + if (strDefault == null) + { + // If system default doesn't work, use invariant + return CultureInfo.InvariantCulture; + } + } + + CultureInfo temp = GetCultureByName(strDefault, true); + + temp._isReadOnly = true; + + return temp; + } + + private static CultureInfo GetUserDefaultUILanguage() + { + const uint MUI_LANGUAGE_NAME = 0x8; // Use ISO language (culture) name convention + uint langCount = 0; + uint bufLen = 0; + + if (Interop.Kernel32.GetUserPreferredUILanguages(MUI_LANGUAGE_NAME, out langCount, null, ref bufLen)) + { + char [] languages = new char[bufLen]; + if (Interop.Kernel32.GetUserPreferredUILanguages(MUI_LANGUAGE_NAME, out langCount, languages, ref bufLen)) + { + int index = 0; + while (languages[index] != (char) 0 && index(AsyncLocalSetCurrentCulture), null); + } + s_asyncLocalCurrentCulture.Value = value; + } + } + + public static CultureInfo CurrentUICulture + { + get + { +#if FEATURE_APPX + if (AppDomain.IsAppXModel()) + { + CultureInfo culture = GetCultureInfoForUserPreferredLanguageInAppX(); + if (culture != null) + return culture; + } +#endif + return GetCurrentUICultureNoAppX(); + } + + set + { + if (value == null) + { + throw new ArgumentNullException(nameof(value)); + } + + CultureInfo.VerifyCultureName(value, true); +#if FEATURE_APPX + if (AppDomain.IsAppXModel()) + { + if (SetCultureInfoForUserPreferredLanguageInAppX(value)) + { + // successfully set the culture, otherwise fallback to legacy path + return; + } + } +#endif + if (s_asyncLocalCurrentUICulture == null) + { + Interlocked.CompareExchange(ref s_asyncLocalCurrentUICulture, new AsyncLocal(AsyncLocalSetCurrentUICulture), null); + } + + // this one will set s_currentThreadUICulture too + s_asyncLocalCurrentUICulture.Value = value; + } + } + +#if FEATURE_APPX + internal static CultureInfo GetCultureInfoForUserPreferredLanguageInAppX() + { + // If a call to GetCultureInfoForUserPreferredLanguageInAppX() generated a recursive + // call to itself, return null, since we don't want to stack overflow. For example, + // this can happen if some code in this method ends up calling CultureInfo.CurrentCulture + // (which is common on check'd build because of BCLDebug logging which calls Int32.ToString()). + // In this case, returning null will mean CultureInfo.CurrentCulture gets the default Win32 + // value, which should be fine. + if (ts_IsDoingAppXCultureInfoLookup) + { + return null; + } + + // If running within a compilation process (mscorsvw.exe, for example), it is illegal to + // load any non-mscorlib assembly for execution. Since WindowsRuntimeResourceManager lives + // in System.Runtime.WindowsRuntime, caller will need to fall back to default Win32 value, + // which should be fine because we should only ever need to access FX resources during NGEN. + // FX resources are always loaded from satellite assemblies - even in AppX processes (see the + // comments in code:System.Resources.ResourceManager.SetAppXConfiguration for more details). + if (AppDomain.IsAppXNGen) + { + return null; + } + + CultureInfo toReturn = null; + + try + { + ts_IsDoingAppXCultureInfoLookup = true; + + if (s_WindowsRuntimeResourceManager == null) + { + s_WindowsRuntimeResourceManager = ResourceManager.GetWinRTResourceManager(); + } + + toReturn = s_WindowsRuntimeResourceManager.GlobalResourceContextBestFitCultureInfo; + } + finally + { + ts_IsDoingAppXCultureInfoLookup = false; + } + + return toReturn; + } + + internal static bool SetCultureInfoForUserPreferredLanguageInAppX(CultureInfo ci) + { + // If running within a compilation process (mscorsvw.exe, for example), it is illegal to + // load any non-mscorlib assembly for execution. Since WindowsRuntimeResourceManager lives + // in System.Runtime.WindowsRuntime, caller will need to fall back to default Win32 value, + // which should be fine because we should only ever need to access FX resources during NGEN. + // FX resources are always loaded from satellite assemblies - even in AppX processes (see the + // comments in code:System.Resources.ResourceManager.SetAppXConfiguration for more details). + if (AppDomain.IsAppXNGen) + { + return false; + } + + if (s_WindowsRuntimeResourceManager == null) + { + s_WindowsRuntimeResourceManager = ResourceManager.GetWinRTResourceManager(); + } + + return s_WindowsRuntimeResourceManager.SetGlobalResourceContextDefaultCulture(ci); + } +#endif + } +} diff --git a/src/mscorlib/src/System/Globalization/CultureInfo.cs b/src/mscorlib/src/System/Globalization/CultureInfo.cs index fc21342..60938de 100644 --- a/src/mscorlib/src/System/Globalization/CultureInfo.cs +++ b/src/mscorlib/src/System/Globalization/CultureInfo.cs @@ -26,25 +26,26 @@ // //////////////////////////////////////////////////////////////////////////// +using System.Collections.Generic; +using System.Diagnostics; +using System.Diagnostics.Contracts; +using System.Runtime.Serialization; +using System.Threading; + namespace System.Globalization { - using System; - using System.Security; - using System.Threading; - using System.Collections; - using System.Runtime; - using System.Runtime.CompilerServices; - using System.Runtime.InteropServices; - using System.Runtime.Serialization; - using System.Runtime.Versioning; - using System.Reflection; - using Microsoft.Win32; - using System.Diagnostics; - using System.Diagnostics.Contracts; - using System.Resources; +#if CORECLR + using StringCultureInfoDictionary = Dictionary; + using StringLcidDictionary = Dictionary; + + using Lock = Object; +#else + using StringCultureInfoDictionary = LowLevelDictionary; + using StringLcidDictionary = LowLevelDictionary; +#endif [Serializable] - public partial class CultureInfo : ICloneable, IFormatProvider + public partial class CultureInfo : IFormatProvider, ICloneable { //--------------------------------------------------------------------// // Internal Information // @@ -55,38 +56,32 @@ namespace System.Globalization //--------------------------------------------------------------------// // We use an RFC4646 type string to construct CultureInfo. - // This string is stored in m_name and is authoritative. - // We use the m_cultureData to get the data for our object - - // WARNING - // WARNING: All member fields declared here must also be in ndp/clr/src/vm/object.h - // WARNING: They aren't really private because object.h can access them, but other C# stuff cannot - // WARNING: The type loader will rearrange class member offsets so the mscorwks!CultureInfoBaseObject - // WARNING: must be manually structured to match the true loaded class layout - // WARNING - internal bool m_isReadOnly; - internal CompareInfo compareInfo; - internal TextInfo textInfo; + // This string is stored in _name and is authoritative. + // We use the _cultureData to get the data for our object + + private bool _isReadOnly; + private CompareInfo compareInfo; + private TextInfo textInfo; internal NumberFormatInfo numInfo; internal DateTimeFormatInfo dateTimeInfo; - internal Calendar calendar; - [OptionalField(VersionAdded = 1)] - internal int m_dataItem; // NEVER USED, DO NOT USE THIS! (Serialized in Whidbey/Everett) - [OptionalField(VersionAdded = 1)] - internal int cultureID = 0x007f; // NEVER USED, DO NOT USE THIS! (Serialized in Whidbey/Everett) + private Calendar calendar; // // The CultureData instance that we are going to read data from. // For supported culture, this will be the CultureData instance that read data from mscorlib assembly. // For customized culture, this will be the CultureData instance that read data from user customized culture binary file. // - [NonSerialized] internal CultureData m_cultureData; + [NonSerialized] + internal CultureData _cultureData; + + [NonSerialized] + internal bool _isInherited; - [NonSerialized] internal bool m_isInherited; - [NonSerialized] private CultureInfo m_consoleFallbackCulture; + [NonSerialized] + private CultureInfo _consoleFallbackCulture; // Names are confusing. Here are 3 names we have: // - // new CultureInfo() m_name m_nonSortName m_sortName + // new CultureInfo() _name _nonSortName _sortName // en-US en-US en-US en-US // de-de_phoneb de-DE_phoneb de-DE de-DE_phoneb // fj-fj (custom) fj-FJ fj-FJ en-US (if specified sort is en-US) @@ -98,17 +93,18 @@ namespace System.Globalization // Note that the name used to be serialized for Everett; it is now serialized // because alernate sorts can have alternate names. // This has a de-DE, de-DE_phoneb or fj-FJ style name - internal string m_name; + internal string _name; // This will hold the non sorting name to be returned from CultureInfo.Name property. // This has a de-DE style name even for de-DE_phoneb type cultures - [NonSerialized] private string m_nonSortName; + [NonSerialized] + private string _nonSortName; // This will hold the sorting name to be returned from CultureInfo.SortName property. // This might be completely unrelated to the culture name if a custom culture. Ie en-US for fj-FJ. // Otherwise its the sort name, ie: de-DE or de-DE_phoneb - [NonSerialized] private string m_sortName; - + [NonSerialized] + private string _sortName; //--------------------------------------------------------------------// // @@ -119,183 +115,74 @@ namespace System.Globalization //Get the current user default culture. This one is almost always used, so we create it by default. private static volatile CultureInfo s_userDefaultCulture; + //The culture used in the user interface. This is mostly used to load correct localized resources. + private static volatile CultureInfo s_userDefaultUICulture; // // All of the following will be created on demand. // + // WARNING: We allow diagnostic tools to directly inspect these three members (s_InvariantCultureInfo, s_DefaultThreadCurrentUICulture and s_DefaultThreadCurrentCulture) + // See https://github.com/dotnet/corert/blob/master/Documentation/design-docs/diagnostics/diagnostics-tools-contract.md for more details. + // Please do not change the type, the name, or the semantic usage of this member without understanding the implication for tools. + // Get in touch with the diagnostics team if you have questions. + //The Invariant culture; private static volatile CultureInfo s_InvariantCultureInfo; - //The culture used in the user interface. This is mostly used to load correct localized resources. - private static volatile CultureInfo s_userDefaultUICulture; - - //This is the UI culture used to install the OS. - private static volatile CultureInfo s_InstalledUICultureInfo; - //These are defaults that we use if a thread has not opted into having an explicit culture private static volatile CultureInfo s_DefaultThreadCurrentUICulture; private static volatile CultureInfo s_DefaultThreadCurrentCulture; - //This is a cache of all previously created cultures. Valid keys are LCIDs or the name. We use two hashtables to track them, - // depending on how they are called. - private static volatile Hashtable s_LcidCachedCultures; - private static volatile Hashtable s_NameCachedCultures; + internal static AsyncLocal s_asyncLocalCurrentCulture; + internal static AsyncLocal s_asyncLocalCurrentUICulture; -#if FEATURE_APPX - // When running under AppX, we use this to get some information about the language list - private static volatile WindowsRuntimeResourceManagerBase s_WindowsRuntimeResourceManager; + internal static void AsyncLocalSetCurrentCulture(AsyncLocalValueChangedArgs args) + { + Thread.m_CurrentCulture = args.CurrentValue; + } - [ThreadStatic] - private static bool ts_IsDoingAppXCultureInfoLookup; -#endif + internal static void AsyncLocalSetCurrentUICulture(AsyncLocalValueChangedArgs args) + { + Thread.m_CurrentUICulture = args.CurrentValue; + } + + private static readonly Lock _lock = new Lock(); + private static volatile StringCultureInfoDictionary s_NameCachedCultures; + private static volatile StringLcidDictionary s_LcidCachedCultures; //The parent culture. - [NonSerialized] private CultureInfo m_parent; + [NonSerialized] + private CultureInfo _parent; // LOCALE constants of interest to us internally and privately for LCID functions // (ie: avoid using these and use names if possible) - internal const int LOCALE_NEUTRAL = 0x0000; - private const int LOCALE_USER_DEFAULT = 0x0400; - private const int LOCALE_SYSTEM_DEFAULT = 0x0800; - internal const int LOCALE_CUSTOM_DEFAULT = 0x0c00; + internal const int LOCALE_NEUTRAL = 0x0000; + private const int LOCALE_USER_DEFAULT = 0x0400; + private const int LOCALE_SYSTEM_DEFAULT = 0x0800; internal const int LOCALE_CUSTOM_UNSPECIFIED = 0x1000; - internal const int LOCALE_INVARIANT = 0x007F; - private const int LOCALE_TRADITIONAL_SPANISH = 0x040a; + internal const int LOCALE_CUSTOM_DEFAULT = 0x0c00; + internal const int LOCALE_INVARIANT = 0x007F; // // The CultureData instance that reads the data provided by our CultureData class. // - //Using a field initializer rather than a static constructor so that the whole class can be lazy - //init. + // Using a field initializer rather than a static constructor so that the whole class can be lazy + // init. private static readonly bool init = Init(); private static bool Init() { if (s_InvariantCultureInfo == null) { CultureInfo temp = new CultureInfo("", false); - temp.m_isReadOnly = true; + temp._isReadOnly = true; s_InvariantCultureInfo = temp; } - // First we set it to Invariant in case someone needs it before we're done finding it. - // For example, if we throw an exception in InitUserDefaultCulture, we will still need an valid - // s_userDefaultCulture to be used in Thread.CurrentCulture. - s_userDefaultCulture = s_userDefaultUICulture = s_InvariantCultureInfo; - s_userDefaultCulture = InitUserDefaultCulture(); - s_userDefaultUICulture = InitUserDefaultUICulture(); + s_userDefaultCulture = GetUserDefaultCulture(); + s_userDefaultUICulture = GetUserDefaultUILanguage(); return true; } - private static CultureInfo InitUserDefaultCulture() - { - String strDefault = GetDefaultLocaleName(LOCALE_USER_DEFAULT); - if (strDefault == null) - { - strDefault = GetDefaultLocaleName(LOCALE_SYSTEM_DEFAULT); - - if (strDefault == null) - { - // If system default doesn't work, keep using the invariant - return (CultureInfo.InvariantCulture); - } - } - CultureInfo temp = GetCultureByName(strDefault, true); - - temp.m_isReadOnly = true; - - return (temp); - } - - private static CultureInfo InitUserDefaultUICulture() - { - String strDefault = GetUserDefaultUILanguage(); - - // In most of cases, UserDefaultCulture == UserDefaultUICulture, so we should use the same instance if possible. - if (strDefault == UserDefaultCulture.Name) - { - return (UserDefaultCulture); - } - - CultureInfo temp = GetCultureByName(strDefault, true); - - if (temp == null) - { - return (CultureInfo.InvariantCulture); - } - - temp.m_isReadOnly = true; - - return (temp); - } - -#if FEATURE_APPX - internal static CultureInfo GetCultureInfoForUserPreferredLanguageInAppX() - { - // If a call to GetCultureInfoForUserPreferredLanguageInAppX() generated a recursive - // call to itself, return null, since we don't want to stack overflow. For example, - // this can happen if some code in this method ends up calling CultureInfo.CurrentCulture - // (which is common on check'd build because of BCLDebug logging which calls Int32.ToString()). - // In this case, returning null will mean CultureInfo.CurrentCulture gets the default Win32 - // value, which should be fine. - if (ts_IsDoingAppXCultureInfoLookup) - { - return null; - } - - // If running within a compilation process (mscorsvw.exe, for example), it is illegal to - // load any non-mscorlib assembly for execution. Since WindowsRuntimeResourceManager lives - // in System.Runtime.WindowsRuntime, caller will need to fall back to default Win32 value, - // which should be fine because we should only ever need to access FX resources during NGEN. - // FX resources are always loaded from satellite assemblies - even in AppX processes (see the - // comments in code:System.Resources.ResourceManager.SetAppXConfiguration for more details). - if (AppDomain.IsAppXNGen) - { - return null; - } - - CultureInfo toReturn = null; - - try - { - ts_IsDoingAppXCultureInfoLookup = true; - - if (s_WindowsRuntimeResourceManager == null) - { - s_WindowsRuntimeResourceManager = ResourceManager.GetWinRTResourceManager(); - } - - toReturn = s_WindowsRuntimeResourceManager.GlobalResourceContextBestFitCultureInfo; - } - finally - { - ts_IsDoingAppXCultureInfoLookup = false; - } - - return toReturn; - } - - internal static bool SetCultureInfoForUserPreferredLanguageInAppX(CultureInfo ci) - { - // If running within a compilation process (mscorsvw.exe, for example), it is illegal to - // load any non-mscorlib assembly for execution. Since WindowsRuntimeResourceManager lives - // in System.Runtime.WindowsRuntime, caller will need to fall back to default Win32 value, - // which should be fine because we should only ever need to access FX resources during NGEN. - // FX resources are always loaded from satellite assemblies - even in AppX processes (see the - // comments in code:System.Resources.ResourceManager.SetAppXConfiguration for more details). - if (AppDomain.IsAppXNGen) - { - return false; - } - - if (s_WindowsRuntimeResourceManager == null) - { - s_WindowsRuntimeResourceManager = ResourceManager.GetWinRTResourceManager(); - } - - return s_WindowsRuntimeResourceManager.SetGlobalResourceContextDefaultCulture(ci); - } -#endif - //////////////////////////////////////////////////////////////////////// // // CultureInfo Constructors @@ -303,7 +190,8 @@ namespace System.Globalization //////////////////////////////////////////////////////////////////////// - public CultureInfo(String name) : this(name, true) + public CultureInfo(String name) + : this(name, true) { } @@ -313,25 +201,13 @@ namespace System.Globalization if (name == null) { throw new ArgumentNullException(nameof(name), - Environment.GetResourceString("ArgumentNull_String")); + SR.ArgumentNull_String); } - Contract.EndContractBlock(); - - // Get our data providing record - this.m_cultureData = CultureData.GetCultureData(name, useUserOverride); - if (this.m_cultureData == null) - { - throw new CultureNotFoundException(nameof(name), name, Environment.GetResourceString("Argument_CultureNotSupported")); - } - - this.m_name = this.m_cultureData.CultureName; - this.m_isInherited = (this.GetType() != typeof(System.Globalization.CultureInfo)); + InitializeFromName(name, useUserOverride); } - -#if FEATURE_USE_LCID - public CultureInfo(int culture) : this(culture, true) + public CultureInfo(int culture) : this(culture, true) { } @@ -340,8 +216,7 @@ namespace System.Globalization // We don't check for other invalid LCIDS here... if (culture < 0) { - throw new ArgumentOutOfRangeException(nameof(culture), - Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum")); + throw new ArgumentOutOfRangeException(nameof(culture), SR.ArgumentOutOfRange_NeedPosNum); } Contract.EndContractBlock(); @@ -359,87 +234,30 @@ namespace System.Globalization case LOCALE_CUSTOM_UNSPECIFIED: // Can't support unknown custom cultures and we do not support neutral or // non-custom user locales. - throw new CultureNotFoundException( - nameof(culture), culture, Environment.GetResourceString("Argument_CultureNotSupported")); + throw new CultureNotFoundException(nameof(culture), culture, SR.Argument_CultureNotSupported); default: - // Now see if this LCID is supported in the system default CultureData table. - this.m_cultureData = CultureData.GetCultureData(culture, useUserOverride); + // Now see if this LCID is supported in the system default CultureData table. + _cultureData = CultureData.GetCultureData(culture, useUserOverride); break; } - this.m_isInherited = (this.GetType() != typeof(System.Globalization.CultureInfo)); - this.m_name = this.m_cultureData.CultureName; + _isInherited = (this.GetType() != typeof(System.Globalization.CultureInfo)); + _name = _cultureData.CultureName; } -#endif // FEATURE_USE_LCID - - #region Serialization - // We need to store the override from the culture data record. - private bool m_useUserOverride; - [OnDeserialized] - private void OnDeserialized(StreamingContext ctx) + private void InitializeFromName(string name, bool useUserOverride) { -#if FEATURE_USE_LCID - // Whidbey+ should remember our name - // but v1 and v1.1 did not store name -- only lcid - // Whidbey did not store actual alternate sort name in m_name - // like we do in v4 so we can't use name for alternate sort - // e.g. for es-ES_tradnl: v2 puts es-ES in m_name; v4 puts es-ES_tradnl - if (m_name == null || IsAlternateSortLcid(cultureID)) - { - Debug.Assert(cultureID >= 0, "[CultureInfo.OnDeserialized] cultureID >= 0"); - InitializeFromCultureId(cultureID, m_useUserOverride); - } - else - { -#endif - Debug.Assert(m_name != null, "[CultureInfo.OnDeserialized] m_name != null"); - - this.m_cultureData = CultureData.GetCultureData(m_name, m_useUserOverride); - if (this.m_cultureData == null) - throw new CultureNotFoundException( - nameof(m_name), m_name, Environment.GetResourceString("Argument_CultureNotSupported")); - -#if FEATURE_USE_LCID - } -#endif - m_isInherited = (this.GetType() != typeof(System.Globalization.CultureInfo)); - } - -#if FEATURE_USE_LCID - // A locale ID is a 32 bit value which is the combination of a - // language ID, a sort ID, and a reserved area. The bits are - // allocated as follows: - // - // +------------------------+-------+--------------------------------+ - // | Reserved |Sort ID| Language ID | - // +------------------------+-------+--------------------------------+ - // 31 20 19 16 15 0 bit - private const int LOCALE_SORTID_MASK = 0x000f0000; + // Get our data providing record + _cultureData = CultureData.GetCultureData(name, useUserOverride); - static private bool IsAlternateSortLcid(int lcid) - { - if (lcid == LOCALE_TRADITIONAL_SPANISH) + if (_cultureData == null) { - return true; + throw new CultureNotFoundException(nameof(name), name, SR.Argument_CultureNotSupported); } - return (lcid & LOCALE_SORTID_MASK) != 0; + _name = _cultureData.CultureName; + _isInherited = (this.GetType() != typeof(System.Globalization.CultureInfo)); } -#endif - - [OnSerializing] - private void OnSerializing(StreamingContext ctx) - { - this.m_name = this.m_cultureData.CultureName; - m_useUserOverride = this.m_cultureData.UseUserOverride; -#if FEATURE_USE_LCID - // for compatibility with v2 serialize cultureID - this.cultureID = this.m_cultureData.ILANGUAGE; -#endif - } - - #endregion Serialization // Constructor called by SQL Server's special munged culture - creates a culture with // a TextInfo and CompareInfo that come from a supplied alternate source. This object @@ -451,37 +269,44 @@ namespace System.Globalization { if (cultureName == null) { - throw new ArgumentNullException(nameof(cultureName), - Environment.GetResourceString("ArgumentNull_String")); + throw new ArgumentNullException(nameof(cultureName),SR.ArgumentNull_String); } Contract.EndContractBlock(); - this.m_cultureData = CultureData.GetCultureData(cultureName, false); - if (this.m_cultureData == null) - throw new CultureNotFoundException( - nameof(cultureName), cultureName, Environment.GetResourceString("Argument_CultureNotSupported")); - - this.m_name = this.m_cultureData.CultureName; + _cultureData = CultureData.GetCultureData(cultureName, false); + if (_cultureData == null) + throw new CultureNotFoundException(nameof(cultureName), cultureName, SR.Argument_CultureNotSupported); + + _name = _cultureData.CultureName; CultureInfo altCulture = GetCultureInfo(textAndCompareCultureName); - this.compareInfo = altCulture.CompareInfo; - this.textInfo = altCulture.TextInfo; + compareInfo = altCulture.CompareInfo; + textInfo = altCulture.TextInfo; } // We do this to try to return the system UI language and the default user languages - // The callers should have a fallback if this fails (like Invariant) + // This method will fallback if this fails (like Invariant) + // + // TODO: It would appear that this is only ever called with userOveride = true + // and this method only has one caller. Can we fold it into the caller? private static CultureInfo GetCultureByName(String name, bool userOverride) { + CultureInfo ci = null; // Try to get our culture try { - return userOverride ? new CultureInfo(name) : CultureInfo.GetCultureInfo(name); + ci = userOverride ? new CultureInfo(name) : CultureInfo.GetCultureInfo(name); } catch (ArgumentException) { } - return null; + if (ci == null) + { + ci = InvariantCulture; + } + + return ci; } // @@ -528,39 +353,39 @@ namespace System.Globalization } } - if (null == culture) + if (culture == null) { // nothing to save here; throw the original exception throw; } } - //In the most common case, they've given us a specific culture, so we'll just return that. + // In the most common case, they've given us a specific culture, so we'll just return that. if (!(culture.IsNeutralCulture)) { return culture; } - return (new CultureInfo(culture.m_cultureData.SSPECIFICCULTURE)); + return (new CultureInfo(culture._cultureData.SSPECIFICCULTURE)); } internal static bool VerifyCultureName(String cultureName, bool throwException) { - // This function is used by ResourceManager.GetResourceFileName(). + // 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]; - + // TODO: Names can only be RFC4646 names (ie: a-zA-Z0-9) while this allows any unicode letter/digit if (Char.IsLetterOrDigit(c) || c == '-' || c == '_') { continue; } if (throwException) { - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidResourceCultureName", cultureName)); + throw new ArgumentException(SR.Format(SR.Argument_InvalidResourceCultureName, cultureName)); } return false; } @@ -569,11 +394,9 @@ namespace System.Globalization internal static bool VerifyCultureName(CultureInfo culture, bool throwException) { - Debug.Assert(culture != null, "[CultureInfo.VerifyCultureName]culture!=null"); - //If we have an instance of one of our CultureInfos, the user can't have changed the //name and we know that all names are valid in files. - if (!culture.m_isInherited) + if (!culture._isInherited) { return true; } @@ -581,209 +404,73 @@ namespace System.Globalization return VerifyCultureName(culture.Name, throwException); } - //////////////////////////////////////////////////////////////////////// - // - // CurrentCulture - // - // This instance provides methods based on the current user settings. - // These settings are volatile and may change over the lifetime of the - // thread. - // - //////////////////////////////////////////////////////////////////////// - + // We need to store the override from the culture data record. + private bool _useUserOverride; - public static CultureInfo CurrentCulture + [OnSerializing] + private void OnSerializing(StreamingContext ctx) { - get - { - Contract.Ensures(Contract.Result() != null); - - // In the case of CoreCLR, Thread.m_CurrentCulture and - // Thread.m_CurrentUICulture are thread static so as not to let - // CultureInfo objects leak across AppDomain boundaries. The - // fact that these fields are thread static introduces overhead - // in accessing them (through Thread.CurrentCulture). There is - // also overhead in accessing Thread.CurrentThread. In this - // case, we can avoid the overhead of Thread.CurrentThread - // because these fields are thread static, and so do not - // require a Thread instance to be accessed. -#if FEATURE_APPX - if (AppDomain.IsAppXModel()) - { - CultureInfo culture = GetCultureInfoForUserPreferredLanguageInAppX(); - if (culture != null) - return culture; - } -#endif - return Thread.m_CurrentCulture ?? - s_DefaultThreadCurrentCulture ?? - s_userDefaultCulture ?? - UserDefaultCulture; - } - - set - { -#if FEATURE_APPX - if (value == null) - { - throw new ArgumentNullException(nameof(value)); - } - - if (AppDomain.IsAppXModel()) - { - if (SetCultureInfoForUserPreferredLanguageInAppX(value)) - { - // successfully set the culture, otherwise fallback to legacy path - return; - } - } -#endif - Thread.CurrentThread.CurrentCulture = value; - } + _name = _cultureData.CultureName; + _useUserOverride = _cultureData.UseUserOverride; } - // - // This is the equivalence of the Win32 GetUserDefaultLCID() - // - internal static CultureInfo UserDefaultCulture + [OnDeserialized] + private void OnDeserialized(StreamingContext ctx) { - get - { - Contract.Ensures(Contract.Result() != null); - - CultureInfo temp = s_userDefaultCulture; - if (temp == null) - { - // - // setting the s_userDefaultCulture with invariant culture before intializing it is a protection - // against recursion problem just in case if somebody called CurrentCulture from the CultureInfo - // creation path. the recursion can happen if the current user culture is a replaced custom culture. - // - - s_userDefaultCulture = CultureInfo.InvariantCulture; - temp = InitUserDefaultCulture(); - s_userDefaultCulture = temp; - } - return (temp); - } + Debug.Assert(_name != null, "[CultureInfo.OnDeserialized] _name != null"); + InitializeFromName(_name, _useUserOverride); } - - // - // This is the equivalence of the Win32 GetUserDefaultUILanguage() - // - internal static CultureInfo UserDefaultUICulture + + internal static CultureInfo GetCurrentUICultureNoAppX() { - get + CultureInfo ci = GetUserDefaultCultureCacheOverride(); + if (ci != null) { - Contract.Ensures(Contract.Result() != null); - - CultureInfo temp = s_userDefaultUICulture; - if (temp == null) - { - // - // setting the s_userDefaultCulture with invariant culture before intializing it is a protection - // against recursion problem just in case if somebody called CurrentUICulture from the CultureInfo - // creation path. the recursion can happen if the current user culture is a replaced custom culture. - // - - s_userDefaultUICulture = CultureInfo.InvariantCulture; - - temp = InitUserDefaultUICulture(); - s_userDefaultUICulture = temp; - } - return (temp); + return ci; } - } - - public static CultureInfo CurrentUICulture - { - get + if (Thread.m_CurrentUICulture != null) { - Contract.Ensures(Contract.Result() != null); - - // In the case of CoreCLR, Thread.m_CurrentCulture and - // Thread.m_CurrentUICulture are thread static so as not to let - // CultureInfo objects leak across AppDomain boundaries. The - // fact that these fields are thread static introduces overhead - // in accessing them (through Thread.CurrentCulture). There is - // also overhead in accessing Thread.CurrentThread. In this - // case, we can avoid the overhead of Thread.CurrentThread - // because these fields are thread static, and so do not - // require a Thread instance to be accessed. -#if FEATURE_APPX - if (AppDomain.IsAppXModel()) - { - CultureInfo culture = GetCultureInfoForUserPreferredLanguageInAppX(); - if (culture != null) - return culture; - } -#endif - return Thread.m_CurrentUICulture ?? - s_DefaultThreadCurrentUICulture ?? - s_userDefaultUICulture ?? - UserDefaultUICulture; + return Thread.m_CurrentUICulture; } - set + ci = s_DefaultThreadCurrentUICulture; + if (ci != null) { -#if FEATURE_APPX - if (value == null) - { - throw new ArgumentNullException(nameof(value)); - } + return ci; + } - if (AppDomain.IsAppXModel()) - { - if (SetCultureInfoForUserPreferredLanguageInAppX(value)) - { - // successfully set the culture, otherwise fallback to legacy path - return; - } - } -#endif - Thread.CurrentThread.CurrentUICulture = value; + // if s_userDefaultUICulture == null means CultureInfo statics didn't get initialized yet. this can happen if there early static + // method get executed which eventually hit the cultureInfo code while CultureInfo statics didn’t get chance to initialize + if (s_userDefaultUICulture == null) + { + Init(); } - } + Debug.Assert(s_userDefaultUICulture != null); + return s_userDefaultUICulture; + } - // - // This is the equivalence of the Win32 GetSystemDefaultUILanguage() - // public static CultureInfo InstalledUICulture { get { Contract.Ensures(Contract.Result() != null); - - CultureInfo temp = s_InstalledUICultureInfo; - if (temp == null) + if (s_userDefaultCulture == null) { - String strDefault = GetSystemDefaultUILanguage(); - temp = GetCultureByName(strDefault, true); - - if (temp == null) - { - temp = InvariantCulture; - } - - temp.m_isReadOnly = true; - s_InstalledUICultureInfo = temp; + Init(); } - return (temp); + Debug.Assert(s_userDefaultCulture != null, "[CultureInfo.InstalledUICulture] s_userDefaultCulture != null"); + return s_userDefaultCulture; } } public static CultureInfo DefaultThreadCurrentCulture { - get - { - return s_DefaultThreadCurrentCulture; - } - + get { return s_DefaultThreadCurrentCulture; } set { - // If you add pre-conditions to this method, check to see if you also need to + // If you add pre-conditions to this method, check to see if you also need to // add them to Thread.CurrentCulture.set. s_DefaultThreadCurrentCulture = value; @@ -792,17 +479,13 @@ namespace System.Globalization public static CultureInfo DefaultThreadCurrentUICulture { - get - { - return s_DefaultThreadCurrentUICulture; - } - + get { return s_DefaultThreadCurrentUICulture; } set { //If they're trying to use a Culture with a name that we can't use in resource lookup, //don't even let them set it on the thread. - // If you add more pre-conditions to this method, check to see if you also need to + // If you add more pre-conditions to this method, check to see if you also need to // add them to Thread.CurrentUICulture.set. if (value != null) @@ -830,10 +513,8 @@ namespace System.Globalization public static CultureInfo InvariantCulture { - [Pure] get { - Contract.Ensures(Contract.Result() != null); return (s_InvariantCultureInfo); } } @@ -851,21 +532,19 @@ namespace System.Globalization { get { - Contract.Ensures(Contract.Result() != null); - CultureInfo culture = null; - - if (null == m_parent) + if (null == _parent) { try { - string parentName = this.m_cultureData.SPARENT; + string parentName = _cultureData.SPARENT; + if (String.IsNullOrEmpty(parentName)) { - culture = InvariantCulture; + _parent = InvariantCulture; } else { - culture = new CultureInfo(parentName, this.m_cultureData.UseUserOverride); + _parent = new CultureInfo(parentName, _cultureData.UseUserOverride); } } catch (ArgumentException) @@ -873,54 +552,28 @@ namespace System.Globalization // For whatever reason our IPARENT or SPARENT wasn't correct, so use invariant // We can't allow ourselves to fail. In case of custom cultures the parent of the // current custom culture isn't installed. - culture = InvariantCulture; + _parent = InvariantCulture; } - - Interlocked.CompareExchange(ref m_parent, culture, null); } - return m_parent; + return _parent; } } - //////////////////////////////////////////////////////////////////////// - // - // LCID - // - // Returns a properly formed culture identifier for the current - // culture info. - // - //////////////////////////////////////////////////////////////////////// - -#if FEATURE_USE_LCID public virtual int LCID { get { - return (this.m_cultureData.ILANGUAGE); + return (this._cultureData.ILANGUAGE); } } -#endif - //////////////////////////////////////////////////////////////////////// - // - // BaseInputLanguage - // - // Essentially an LCID, though one that may be different than LCID in the case - // of a customized culture (LCID == LOCALE_CUSTOM_UNSPECIFIED). - // - //////////////////////////////////////////////////////////////////////// -#if FEATURE_USE_LCID public virtual int KeyboardLayoutId { get { - int keyId = this.m_cultureData.IINPUTLANGUAGEHANDLE; - - // Not a customized culture, return the default Keyboard layout ID, which is the same as the language ID. - return (keyId); + return _cultureData.IINPUTLANGUAGEHANDLE; } } -#endif public static CultureInfo[] GetCultures(CultureTypes types) { @@ -946,18 +599,16 @@ namespace System.Globalization { get { - Contract.Ensures(Contract.Result() != null); - // We return non sorting name here. - if (m_nonSortName == null) + if (_nonSortName == null) { - m_nonSortName = this.m_cultureData.SNAME; - if (m_nonSortName == null) + _nonSortName = _cultureData.SNAME; + if (_nonSortName == null) { - m_nonSortName = String.Empty; + _nonSortName = String.Empty; } } - return m_nonSortName; + return _nonSortName; } } @@ -966,20 +617,20 @@ namespace System.Globalization { get { - if (m_sortName == null) + if (_sortName == null) { - m_sortName = this.m_cultureData.SCOMPAREINFO; + _sortName = _cultureData.SCOMPAREINFO; } - return m_sortName; + return _sortName; } } - public String IetfLanguageTag + public string IetfLanguageTag { get { - Contract.Ensures(Contract.Result() != null); + Contract.Ensures(Contract.Result() != null); // special case the compatibility cultures switch (this.Name) @@ -1008,9 +659,9 @@ namespace System.Globalization get { Contract.Ensures(Contract.Result() != null); - Debug.Assert(m_name != null, "[CultureInfo.DisplayName]Always expect m_name to be set"); + Debug.Assert(_name != null, "[CultureInfo.DisplayName] Always expect _name to be set"); - return m_cultureData.SLOCALIZEDDISPLAYNAME; + return _cultureData.SLOCALIZEDDISPLAYNAME; } } @@ -1028,7 +679,7 @@ namespace System.Globalization get { Contract.Ensures(Contract.Result() != null); - return (this.m_cultureData.SNATIVEDISPLAYNAME); + return (_cultureData.SNATIVEDISPLAYNAME); } } @@ -1046,7 +697,7 @@ namespace System.Globalization get { Contract.Ensures(Contract.Result() != null); - return (this.m_cultureData.SENGDISPLAYNAME); + return (_cultureData.SENGDISPLAYNAME); } } @@ -1056,7 +707,7 @@ namespace System.Globalization get { Contract.Ensures(Contract.Result() != null); - return (this.m_cultureData.SISO639LANGNAME); + return (_cultureData.SISO639LANGNAME); } } @@ -1066,7 +717,7 @@ namespace System.Globalization get { Contract.Ensures(Contract.Result() != null); - return (this.m_cultureData.SISO639LANGNAME2); + return _cultureData.SISO639LANGNAME2; } } @@ -1083,7 +734,7 @@ namespace System.Globalization get { Contract.Ensures(Contract.Result() != null); - return (this.m_cultureData.SABBREVLANGNAME); + return _cultureData.SABBREVLANGNAME; } } @@ -1098,16 +749,14 @@ namespace System.Globalization { get { - Contract.Ensures(Contract.Result() != null); - if (this.compareInfo == null) { // Since CompareInfo's don't have any overrideable properties, get the CompareInfo from // the Non-Overridden CultureInfo so that we only create one CompareInfo per culture CompareInfo temp = UseUserOverride - ? GetCultureInfo(this.m_name).CompareInfo + ? GetCultureInfo(this._name).CompareInfo : new CompareInfo(this); - if (CompatibilitySwitches.IsCompatibilityBehaviorDefined) + if (OkayToCacheClassWithCompatibilityBehavior) { this.compareInfo = temp; } @@ -1120,6 +769,14 @@ namespace System.Globalization } } + private static bool OkayToCacheClassWithCompatibilityBehavior + { + get + { + return true; + } + } + //////////////////////////////////////////////////////////////////////// // // TextInfo @@ -1127,21 +784,17 @@ namespace System.Globalization // Gets the TextInfo for this culture. // //////////////////////////////////////////////////////////////////////// - - public virtual TextInfo TextInfo { get { - Contract.Ensures(Contract.Result() != null); - if (textInfo == null) { // Make a new textInfo - TextInfo tempTextInfo = new TextInfo(this.m_cultureData); - tempTextInfo.SetReadOnlyState(m_isReadOnly); + TextInfo tempTextInfo = new TextInfo(_cultureData); + tempTextInfo.SetReadOnlyState(_isReadOnly); - if (CompatibilitySwitches.IsCompatibilityBehaviorDefined) + if (OkayToCacheClassWithCompatibilityBehavior) { textInfo = tempTextInfo; } @@ -1211,23 +864,16 @@ namespace System.Globalization public override String ToString() { - Contract.Ensures(Contract.Result() != null); - - Debug.Assert(m_name != null, "[CultureInfo.ToString]Always expect m_name to be set"); - return m_name; + return _name; } public virtual Object GetFormat(Type formatType) { if (formatType == typeof(NumberFormatInfo)) - { return (NumberFormat); - } if (formatType == typeof(DateTimeFormatInfo)) - { return (DateTimeFormat); - } return (null); } @@ -1235,7 +881,7 @@ namespace System.Globalization { get { - return this.m_cultureData.IsNeutralCulture; + return _cultureData.IsNeutralCulture; } } @@ -1245,20 +891,20 @@ namespace System.Globalization { CultureTypes types = 0; - if (m_cultureData.IsNeutralCulture) + if (_cultureData.IsNeutralCulture) types |= CultureTypes.NeutralCultures; else types |= CultureTypes.SpecificCultures; - types |= m_cultureData.IsWin32Installed ? CultureTypes.InstalledWin32Cultures : 0; + types |= _cultureData.IsWin32Installed ? CultureTypes.InstalledWin32Cultures : 0; // Disable warning 618: System.Globalization.CultureTypes.FrameworkCultures' is obsolete #pragma warning disable 618 - types |= m_cultureData.IsFramework ? CultureTypes.FrameworkCultures : 0; -#pragma warning restore 618 + types |= _cultureData.IsFramework ? CultureTypes.FrameworkCultures : 0; - types |= m_cultureData.IsSupplementalCustomCulture ? CultureTypes.UserCustomCulture : 0; - types |= m_cultureData.IsReplacementCulture ? CultureTypes.ReplacementCultures | CultureTypes.UserCustomCulture : 0; +#pragma warning restore 618 + types |= _cultureData.IsSupplementalCustomCulture ? CultureTypes.UserCustomCulture : 0; + types |= _cultureData.IsReplacementCulture ? CultureTypes.ReplacementCultures | CultureTypes.UserCustomCulture : 0; return types; } @@ -1268,12 +914,10 @@ namespace System.Globalization { get { - Contract.Ensures(Contract.Result() != null); - if (numInfo == null) { - NumberFormatInfo temp = new NumberFormatInfo(this.m_cultureData); - temp.isReadOnly = m_isReadOnly; + NumberFormatInfo temp = new NumberFormatInfo(_cultureData); + temp.isReadOnly = _isReadOnly; Interlocked.CompareExchange(ref numInfo, temp, null); } return (numInfo); @@ -1282,10 +926,8 @@ namespace System.Globalization { if (value == null) { - throw new ArgumentNullException(nameof(value), - Environment.GetResourceString("ArgumentNull_Obj")); + throw new ArgumentNullException(nameof(value), SR.ArgumentNull_Obj); } - Contract.EndContractBlock(); VerifyWritable(); numInfo = value; } @@ -1299,20 +941,15 @@ namespace System.Globalization // the CultureID. // //////////////////////////////////////////////////////////////////////// - - public virtual DateTimeFormatInfo DateTimeFormat { get { - Contract.Ensures(Contract.Result() != null); - if (dateTimeInfo == null) { // Change the calendar of DTFI to the specified calendar of this CultureInfo. - DateTimeFormatInfo temp = new DateTimeFormatInfo( - this.m_cultureData, this.Calendar); - temp.m_isReadOnly = m_isReadOnly; + DateTimeFormatInfo temp = new DateTimeFormatInfo(_cultureData, this.Calendar); + temp._isReadOnly = _isReadOnly; Interlocked.CompareExchange(ref dateTimeInfo, temp, null); } return (dateTimeInfo); @@ -1322,10 +959,8 @@ namespace System.Globalization { if (value == null) { - throw new ArgumentNullException(nameof(value), - Environment.GetResourceString("ArgumentNull_Obj")); + throw new ArgumentNullException(nameof(value), SR.ArgumentNull_Obj); } - Contract.EndContractBlock(); VerifyWritable(); dateTimeInfo = value; } @@ -1333,16 +968,13 @@ namespace System.Globalization public void ClearCachedData() { - s_userDefaultUICulture = null; s_userDefaultCulture = null; RegionInfo.s_currentRegionInfo = null; -#pragma warning disable CS0618 + #pragma warning disable 0618 // disable the obsolete warning TimeZone.ResetTimeZone(); -#pragma warning restore CS0618 + #pragma warning restore 0618 TimeZoneInfo.ClearCachedData(); - - // Delete the cached cultures. s_LcidCachedCultures = null; s_NameCachedCultures = null; @@ -1357,9 +989,9 @@ namespace System.Globalization ** Shouldn't throw exception since the calType value is from our data table or from Win32 registry. ** If we are in trouble (like getting a weird value from Win32 registry), just return the GregorianCalendar. ============================================================================*/ - internal static Calendar GetCalendarInstance(int calType) + internal static Calendar GetCalendarInstance(CalendarId calType) { - if (calType == Calendar.CAL_GREGORIAN) + if (calType == CalendarId.GREGORIAN) { return (new GregorianCalendar()); } @@ -1368,47 +1000,38 @@ namespace System.Globalization //This function exists as a shortcut to prevent us from loading all of the non-gregorian //calendars unless they're required. - internal static Calendar GetCalendarInstanceRare(int calType) + internal static Calendar GetCalendarInstanceRare(CalendarId calType) { - Debug.Assert(calType != Calendar.CAL_GREGORIAN, "calType!=Calendar.CAL_GREGORIAN"); + Debug.Assert(calType != CalendarId.GREGORIAN, "calType!=CalendarId.GREGORIAN"); switch (calType) { - case Calendar.CAL_GREGORIAN_US: // Gregorian (U.S.) calendar - case Calendar.CAL_GREGORIAN_ME_FRENCH: // Gregorian Middle East French calendar - case Calendar.CAL_GREGORIAN_ARABIC: // Gregorian Arabic calendar - case Calendar.CAL_GREGORIAN_XLIT_ENGLISH: // Gregorian Transliterated English calendar - case Calendar.CAL_GREGORIAN_XLIT_FRENCH: // Gregorian Transliterated French calendar + case CalendarId.GREGORIAN_US: // Gregorian (U.S.) calendar + case CalendarId.GREGORIAN_ME_FRENCH: // Gregorian Middle East French calendar + case CalendarId.GREGORIAN_ARABIC: // Gregorian Arabic calendar + case CalendarId.GREGORIAN_XLIT_ENGLISH: // Gregorian Transliterated English calendar + case CalendarId.GREGORIAN_XLIT_FRENCH: // Gregorian Transliterated French calendar return (new GregorianCalendar((GregorianCalendarTypes)calType)); - case Calendar.CAL_TAIWAN: // Taiwan Era calendar + case CalendarId.TAIWAN: // Taiwan Era calendar return (new TaiwanCalendar()); - case Calendar.CAL_JAPAN: // Japanese Emperor Era calendar + case CalendarId.JAPAN: // Japanese Emperor Era calendar return (new JapaneseCalendar()); - case Calendar.CAL_KOREA: // Korean Tangun Era calendar + case CalendarId.KOREA: // Korean Tangun Era calendar return (new KoreanCalendar()); - case Calendar.CAL_THAI: // Thai calendar + case CalendarId.THAI: // Thai calendar return (new ThaiBuddhistCalendar()); - case Calendar.CAL_HIJRI: // Hijri (Arabic Lunar) calendar + case CalendarId.HIJRI: // Hijri (Arabic Lunar) calendar return (new HijriCalendar()); - case Calendar.CAL_HEBREW: // Hebrew (Lunar) calendar + case CalendarId.HEBREW: // Hebrew (Lunar) calendar return (new HebrewCalendar()); - case Calendar.CAL_UMALQURA: + case CalendarId.UMALQURA: return (new UmAlQuraCalendar()); - case Calendar.CAL_PERSIAN: + case CalendarId.PERSIAN: return (new PersianCalendar()); - case Calendar.CAL_CHINESELUNISOLAR: - return (new ChineseLunisolarCalendar()); - case Calendar.CAL_JAPANESELUNISOLAR: - return (new JapaneseLunisolarCalendar()); - case Calendar.CAL_KOREANLUNISOLAR: - return (new KoreanLunisolarCalendar()); - case Calendar.CAL_TAIWANLUNISOLAR: - return (new TaiwanLunisolarCalendar()); } return (new GregorianCalendar()); } - /*=================================Calendar========================== **Action: Return/set the default calendar used by this culture. ** This value can be overridden by regional option if this is a current culture. @@ -1417,22 +1040,19 @@ namespace System.Globalization **Exceptions: ** ArgumentNull_Obj if the set value is null. ============================================================================*/ - - public virtual Calendar Calendar { get { - Contract.Ensures(Contract.Result() != null); if (calendar == null) { - Debug.Assert(this.m_cultureData.CalendarIds.Length > 0, "this.m_cultureData.CalendarIds.Length > 0"); + Debug.Assert(_cultureData.CalendarIds.Length > 0, "_cultureData.CalendarIds.Length > 0"); // Get the default calendar for this culture. Note that the value can be // from registry if this is a user default culture. - Calendar newObj = this.m_cultureData.DefaultCalendar; + Calendar newObj = _cultureData.DefaultCalendar; - System.Threading.Thread.MemoryBarrier(); - newObj.SetReadOnlyState(m_isReadOnly); + System.Threading.Interlocked.MemoryBarrier(); + newObj.SetReadOnlyState(_isReadOnly); calendar = newObj; } return (calendar); @@ -1456,7 +1076,7 @@ namespace System.Globalization // // This property always returns a new copy of the calendar array. // - int[] calID = this.m_cultureData.CalendarIds; + CalendarId[] calID = _cultureData.CalendarIds; Calendar[] cals = new Calendar[calID.Length]; for (int i = 0; i < cals.Length; i++) { @@ -1466,12 +1086,11 @@ namespace System.Globalization } } - public bool UseUserOverride { get { - return (this.m_cultureData.UseUserOverride); + return _cultureData.UseUserOverride; } } @@ -1479,26 +1098,24 @@ namespace System.Globalization { Contract.Ensures(Contract.Result() != null); - CultureInfo temp = m_consoleFallbackCulture; + CultureInfo temp = _consoleFallbackCulture; if (temp == null) { - temp = CreateSpecificCulture(this.m_cultureData.SCONSOLEFALLBACKNAME); - temp.m_isReadOnly = true; - m_consoleFallbackCulture = temp; + temp = CreateSpecificCulture(_cultureData.SCONSOLEFALLBACKNAME); + _isReadOnly = true; + _consoleFallbackCulture = temp; } return (temp); } public virtual Object Clone() { - Contract.Ensures(Contract.Result() != null); - CultureInfo ci = (CultureInfo)MemberwiseClone(); - ci.m_isReadOnly = false; + ci._isReadOnly = false; //If this is exactly our type, we can make certain optimizations so that we don't allocate NumberFormatInfo or DTFI unless //they've already been allocated. If this is a derived type, we'll take a more generic codepath. - if (!m_isInherited) + if (!_isInherited) { if (this.dateTimeInfo != null) { @@ -1528,7 +1145,6 @@ namespace System.Globalization return (ci); } - public static CultureInfo ReadOnly(CultureInfo ci) { if (ci == null) @@ -1548,7 +1164,7 @@ namespace System.Globalization { //If this is exactly our type, we can make certain optimizations so that we don't allocate NumberFormatInfo or DTFI unless //they've already been allocated. If this is a derived type, we'll take a more generic codepath. - if (!ci.m_isInherited) + if (!ci._isInherited) { if (ci.dateTimeInfo != null) { @@ -1578,7 +1194,7 @@ namespace System.Globalization // Don't set the read-only flag too early. // We should set the read-only flag here. Otherwise, info.DateTimeFormat will not be able to set. - newInfo.m_isReadOnly = true; + newInfo._isReadOnly = true; return (newInfo); } @@ -1588,17 +1204,16 @@ namespace System.Globalization { get { - return (m_isReadOnly); + return (_isReadOnly); } } private void VerifyWritable() { - if (m_isReadOnly) + if (_isReadOnly) { - throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly")); + throw new InvalidOperationException(SR.InvalidOperation_ReadOnly); } - Contract.EndContractBlock(); } // For resource lookup, we consider a culture the invariant culture by name equality. @@ -1613,18 +1228,11 @@ namespace System.Globalization // If lcid is -1, use the altName and create one of those special SQL cultures. internal static CultureInfo GetCultureInfoHelper(int lcid, string name, string altName) { - // There is a race condition in this code with the side effect that the second thread's value - // clobbers the first in the dictionary. This is an acceptable race condition since the CultureInfo objects - // are content equal (but not reference equal). Since we make no guarantees there, this race condition is - // acceptable. - // See code:Dictionary#DictionaryVersusHashtableThreadSafety for details on Dictionary versus - // Hashtable thread safety. - // retval is our return value. CultureInfo retval; // Temporary hashtable for the names. - Hashtable tempNameHT = s_NameCachedCultures; + StringCultureInfoDictionary tempNameHT = s_NameCachedCultures; if (name != null) { @@ -1639,50 +1247,51 @@ namespace System.Globalization // We expect the same result for both hashtables, but will test individually for added safety. if (tempNameHT == null) { - tempNameHT = Hashtable.Synchronized(new Hashtable()); + tempNameHT = new StringCultureInfoDictionary(); } else { // If we are called by name, check if the object exists in the hashtable. If so, return it. - if (lcid == -1) + if (lcid == -1 || lcid == 0) { - retval = (CultureInfo)tempNameHT[name + '\xfffd' + altName]; - if (retval != null) + bool ret; + lock (_lock) { - return retval; + ret = tempNameHT.TryGetValue(lcid == 0 ? name : name + '\xfffd' + altName, out retval); } - } - else if (lcid == 0) - { - retval = (CultureInfo)tempNameHT[name]; - if (retval != null) + + if (ret && retval != null) { return retval; } } } -#if FEATURE_USE_LCID + // Next, the Lcid table. - Hashtable tempLcidHT = s_LcidCachedCultures; + StringLcidDictionary tempLcidHT = s_LcidCachedCultures; if (tempLcidHT == null) { // Case insensitive is not an issue here, save the constructor call. - tempLcidHT = Hashtable.Synchronized(new Hashtable()); + tempLcidHT = new StringLcidDictionary(); } else { // If we were called by Lcid, check if the object exists in the table. If so, return it. if (lcid > 0) { - retval = (CultureInfo)tempLcidHT[lcid]; - if (retval != null) + bool ret; + lock (_lock) + { + ret = tempLcidHT.TryGetValue(lcid, out retval); + } + if (ret && retval != null) { return retval; } } } -#endif + // We now have two temporary hashtables and the desired object was not found. // We'll construct it. We catch any exceptions from the constructor call and return null. try @@ -1699,12 +1308,8 @@ namespace System.Globalization break; default: -#if FEATURE_USE_LCID retval = new CultureInfo(lcid, false); break; -#else - return null; -#endif } } catch (ArgumentException) @@ -1713,43 +1318,38 @@ namespace System.Globalization } // Set it to read-only - retval.m_isReadOnly = true; + retval._isReadOnly = true; if (lcid == -1) { - // This new culture will be added only to the name hash table. - tempNameHT[name + '\xfffd' + altName] = retval; - + lock (_lock) + { + // This new culture will be added only to the name hash table. + tempNameHT[name + '\xfffd' + altName] = retval; + } // when lcid == -1 then TextInfo object is already get created and we need to set it as read only. retval.TextInfo.SetReadOnlyState(true); } - else + else if (lcid == 0) { // Remember our name (as constructed). Do NOT use alternate sort name versions because // we have internal state representing the sort. (So someone would get the wrong cached version) - string newName = CultureData.AnsiToLower(retval.m_name); + string newName = CultureData.AnsiToLower(retval._name); // We add this new culture info object to both tables. - tempNameHT[newName] = retval; -#if FEATURE_USE_LCID - const int LCID_ZH_CHS_HANS = 0x0004; - const int LCID_ZH_CHT_HANT = 0x7c04; - - if ((retval.LCID == LCID_ZH_CHS_HANS && newName == "zh-hans") - || (retval.LCID == LCID_ZH_CHT_HANT && newName == "zh-hant")) + lock (_lock) { - // do nothing because we only want zh-CHS and zh-CHT to cache - // by lcid + tempNameHT[newName] = retval; } - else + } + else + { + lock (_lock) { - tempLcidHT[retval.LCID] = retval; + tempLcidHT[lcid] = retval; } - -#endif } -#if FEATURE_USE_LCID // Copy the two hashtables to the corresponding member variables. This will potentially overwrite // new tables simultaneously created by a new thread, but maximizes thread safety. if (-1 != lcid) @@ -1757,7 +1357,6 @@ namespace System.Globalization // Only when we modify the lcid hash table, is there a need to overwrite. s_LcidCachedCultures = tempLcidHT; } -#endif s_NameCachedCultures = tempNameHT; @@ -1765,7 +1364,6 @@ namespace System.Globalization return retval; } -#if FEATURE_USE_LCID // Gets a cached copy of the specified culture from an internal hashtable (or creates it // if not found). (LCID version)... use named version public static CultureInfo GetCultureInfo(int culture) @@ -1773,22 +1371,19 @@ namespace System.Globalization // Must check for -1 now since the helper function uses the value to signal // the altCulture code path for SQL Server. // Also check for zero as this would fail trying to add as a key to the hash. - if (culture <= 0) + if (culture <= 0) { - throw new ArgumentOutOfRangeException(nameof(culture), - Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum")); + throw new ArgumentOutOfRangeException(nameof(culture), SR.ArgumentOutOfRange_NeedPosNum); } Contract.Ensures(Contract.Result() != null); Contract.EndContractBlock(); CultureInfo retval = GetCultureInfoHelper(culture, null, null); if (null == retval) { - throw new CultureNotFoundException( - nameof(culture), culture, Environment.GetResourceString("Argument_CultureNotSupported")); + throw new CultureNotFoundException(nameof(culture), culture, SR.Argument_CultureNotSupported); } return retval; } -#endif // Gets a cached copy of the specified culture from an internal hashtable (or creates it // if not found). (Named version) @@ -1799,14 +1394,12 @@ namespace System.Globalization { throw new ArgumentNullException(nameof(name)); } - Contract.Ensures(Contract.Result() != null); - Contract.EndContractBlock(); CultureInfo retval = GetCultureInfoHelper(0, name, null); if (retval == null) { throw new CultureNotFoundException( - nameof(name), name, Environment.GetResourceString("Argument_CultureNotSupported")); + nameof(name), name, SR.Argument_CultureNotSupported); } return retval; } @@ -1816,32 +1409,28 @@ namespace System.Globalization public static CultureInfo GetCultureInfo(string name, string altName) { // Make sure we have a valid, non-zero length string as name - if (null == name) + if (name == null) { throw new ArgumentNullException(nameof(name)); } - if (null == altName) + if (altName == null) { throw new ArgumentNullException(nameof(altName)); } + Contract.Ensures(Contract.Result() != null); Contract.EndContractBlock(); CultureInfo retval = GetCultureInfoHelper(-1, name, altName); if (retval == null) { - throw new CultureNotFoundException(nameof(name) + " or " + nameof(altName), - String.Format( - CultureInfo.CurrentCulture, - Environment.GetResourceString("Argument_OneOfCulturesNotSupported"), - name, - altName)); + throw new CultureNotFoundException("name or altName", + SR.Format(SR.Argument_OneOfCulturesNotSupported, name, altName)); } return retval; } - // This function is deprecated, we don't like it public static CultureInfo GetCultureInfoByIetfLanguageTag(string name) { @@ -1850,10 +1439,7 @@ namespace System.Globalization // Disallow old zh-CHT/zh-CHS names if (name == "zh-CHT" || name == "zh-CHS") { - throw new CultureNotFoundException( - nameof(name), - String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Argument_CultureIetfNotSupported"), name) - ); + throw new CultureNotFoundException(nameof(name), SR.Format(SR.Argument_CultureIetfNotSupported, name)); } CultureInfo ci = GetCultureInfo(name); @@ -1861,90 +1447,11 @@ namespace System.Globalization // Disallow alt sorts and es-es_TS if (ci.LCID > 0xffff || ci.LCID == 0x040a) { - throw new CultureNotFoundException( - nameof(name), - String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Argument_CultureIetfNotSupported"), name) - ); + throw new CultureNotFoundException(nameof(name), SR.Format(SR.Argument_CultureIetfNotSupported, name)); } return ci; } - - private static volatile bool s_isTaiwanSku; - private static volatile bool s_haveIsTaiwanSku; - internal static bool IsTaiwanSku - { - get - { - if (!s_haveIsTaiwanSku) - { - s_isTaiwanSku = (GetSystemDefaultUILanguage() == "zh-TW"); - s_haveIsTaiwanSku = true; - } - return (bool)s_isTaiwanSku; - } - } - - // - // Helper Methods. - // - - // Get Locale Info Ex calls. So we don't have to muck with the different int/string return types we declared two of these: - [MethodImplAttribute(MethodImplOptions.InternalCall)] - internal static extern String nativeGetLocaleInfoEx(String localeName, uint field); - - [MethodImplAttribute(MethodImplOptions.InternalCall)] - internal static extern int nativeGetLocaleInfoExInt(String localeName, uint field); - - private static String GetDefaultLocaleName(int localeType) - { - Debug.Assert(localeType == LOCALE_USER_DEFAULT || localeType == LOCALE_SYSTEM_DEFAULT, "[CultureInfo.GetDefaultLocaleName] localeType must be LOCALE_USER_DEFAULT or LOCALE_SYSTEM_DEFAULT"); - - string localeName = null; - if (InternalGetDefaultLocaleName(localeType, JitHelpers.GetStringHandleOnStack(ref localeName))) - { - return localeName; - } - return string.Empty; - } - - // Get the default locale name - [SuppressUnmanagedCodeSecurity] - [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] - [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool InternalGetDefaultLocaleName(int localetype, StringHandleOnStack localeString); - - private static String GetUserDefaultUILanguage() - { - string userDefaultUiLanguage = null; - if (InternalGetUserDefaultUILanguage(JitHelpers.GetStringHandleOnStack(ref userDefaultUiLanguage))) - { - return userDefaultUiLanguage; - } - return String.Empty; - } - - // Get the user's default UI language, return locale name - [SuppressUnmanagedCodeSecurity] - [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] - [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool InternalGetUserDefaultUILanguage(StringHandleOnStack userDefaultUiLanguage); - - private static String GetSystemDefaultUILanguage() - { - string systemDefaultUiLanguage = null; - if (InternalGetSystemDefaultUILanguage(JitHelpers.GetStringHandleOnStack(ref systemDefaultUiLanguage))) - { - return systemDefaultUiLanguage; - } - return String.Empty; - } - - [MethodImplAttribute(MethodImplOptions.InternalCall)] - [SuppressUnmanagedCodeSecurity] - [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] - [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool InternalGetSystemDefaultUILanguage(StringHandleOnStack systemDefaultUiLanguage); } } diff --git a/src/mscorlib/src/System/Globalization/CultureNotFoundException.cs b/src/mscorlib/src/System/Globalization/CultureNotFoundException.cs index 8752cf3..d296ad8 100644 --- a/src/mscorlib/src/System/Globalization/CultureNotFoundException.cs +++ b/src/mscorlib/src/System/Globalization/CultureNotFoundException.cs @@ -2,20 +2,17 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. - - using System; using System.Runtime.Serialization; using System.Threading; -using System.Diagnostics.Contracts; namespace System.Globalization { [Serializable] - public partial class CultureNotFoundException : ArgumentException, ISerializable + public class CultureNotFoundException : ArgumentException, ISerializable { - private string m_invalidCultureName; // unrecognized culture name - private Nullable m_invalidCultureId; // unrecognized culture Lcid + private string _invalidCultureName; // unrecognized culture name + private int? _invalidCultureId; // unrecognized culture Lcid public CultureNotFoundException() : base(DefaultMessage) @@ -37,64 +34,59 @@ namespace System.Globalization { } - public CultureNotFoundException(String paramName, int invalidCultureId, String message) + public CultureNotFoundException(String paramName, string invalidCultureName, String message) : base(message, paramName) { - m_invalidCultureId = invalidCultureId; + _invalidCultureName = invalidCultureName; } - public CultureNotFoundException(String message, int invalidCultureId, Exception innerException) + public CultureNotFoundException(String message, string invalidCultureName, Exception innerException) : base(message, innerException) { - m_invalidCultureId = invalidCultureId; + _invalidCultureName = invalidCultureName; } - public CultureNotFoundException(String paramName, string invalidCultureName, String message) - : base(message, paramName) + public CultureNotFoundException(string message, int invalidCultureId, Exception innerException) + : base(message, innerException) { - m_invalidCultureName = invalidCultureName; + _invalidCultureId = invalidCultureId; } - public CultureNotFoundException(String message, string invalidCultureName, Exception innerException) - : base(message, innerException) + public CultureNotFoundException(string paramName, int invalidCultureId, string message) + : base(message, paramName) { - m_invalidCultureName = invalidCultureName; + _invalidCultureId = invalidCultureId; } - protected CultureNotFoundException(SerializationInfo info, StreamingContext context) : base(info, context) + protected CultureNotFoundException(SerializationInfo info, StreamingContext context) + : base(info, context) { - m_invalidCultureId = (Nullable)info.GetValue("InvalidCultureId", typeof(Nullable)); - m_invalidCultureName = (string)info.GetValue("InvalidCultureName", typeof(string)); + _invalidCultureId = (int?)info.GetValue("InvalidCultureId", typeof(int?)); + _invalidCultureName = (string)info.GetValue("InvalidCultureName", typeof(string)); } public override void GetObjectData(SerializationInfo info, StreamingContext context) { - if (info == null) - { - throw new ArgumentNullException(nameof(info)); - } - Contract.EndContractBlock(); base.GetObjectData(info, context); - Nullable invalidCultureId = null; - invalidCultureId = m_invalidCultureId; - info.AddValue("InvalidCultureId", invalidCultureId, typeof(Nullable)); - info.AddValue("InvalidCultureName", m_invalidCultureName, typeof(string)); + info.AddValue("InvalidCultureId", _invalidCultureId, typeof(int?)); + info.AddValue("InvalidCultureName", _invalidCultureName, typeof(string)); } + public virtual Nullable InvalidCultureId { - get { return m_invalidCultureId; } + get { return _invalidCultureId; } } public virtual string InvalidCultureName { - get { return m_invalidCultureName; } + get { return _invalidCultureName; } } private static String DefaultMessage { get { - return Environment.GetResourceString("Argument_CultureNotSupported"); + return SR.Argument_CultureNotSupported; } } @@ -102,12 +94,9 @@ namespace System.Globalization { get { - if (InvalidCultureId != null) - { - return String.Format(CultureInfo.InvariantCulture, - "{0} (0x{0:x4})", (int)InvalidCultureId); - } - return InvalidCultureName; + return InvalidCultureId != null ? + String.Format(CultureInfo.InvariantCulture, "{0} (0x{0:x4})", (int)InvalidCultureId) : + InvalidCultureName; } } @@ -116,13 +105,14 @@ namespace System.Globalization get { String s = base.Message; - if ( - m_invalidCultureId != null || - m_invalidCultureName != null) + if (_invalidCultureId != null || _invalidCultureName != null) { - String valueMessage = Environment.GetResourceString("Argument_CultureInvalidIdentifier", FormatedInvalidCultureId); + String valueMessage = SR.Format(SR.Argument_CultureInvalidIdentifier, FormatedInvalidCultureId); if (s == null) + { return valueMessage; + } + return s + Environment.NewLine + valueMessage; } return s; diff --git a/src/mscorlib/src/System/Globalization/CultureTypes.cs b/src/mscorlib/src/System/Globalization/CultureTypes.cs index 3cb12d6..10d9246 100644 --- a/src/mscorlib/src/System/Globalization/CultureTypes.cs +++ b/src/mscorlib/src/System/Globalization/CultureTypes.cs @@ -2,10 +2,9 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -// // The enumeration constants used in CultureInfo.GetCultures(). -// -// Note that this isn't exposed in Silverlight +// On Linux platforms, the only enum values used there is NeutralCultures and SpecificCultures +// the rest are obsolete or not valid on Linux namespace System.Globalization { diff --git a/src/mscorlib/src/System/Globalization/DateTimeFormatInfo.cs b/src/mscorlib/src/System/Globalization/DateTimeFormatInfo.cs index 892fa53..90e243b 100644 --- a/src/mscorlib/src/System/Globalization/DateTimeFormatInfo.cs +++ b/src/mscorlib/src/System/Globalization/DateTimeFormatInfo.cs @@ -2,21 +2,13 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System.Collections.Generic; +using System.Diagnostics; +using System.Diagnostics.Contracts; +using System.Runtime.Serialization; namespace System.Globalization { - using System; - using System.Security; - using System.Threading; - using System.Collections; - using System.Collections.Generic; - using System.Runtime.Serialization; - using System.Runtime.InteropServices; - using System.Runtime.Versioning; - using System.Text; - using System.Diagnostics; - using System.Diagnostics.Contracts; - // // Flags used to indicate different styles of month names. // This is an internal flag used by internalGetMonthName(). @@ -58,91 +50,90 @@ namespace System.Globalization [Serializable] - public sealed class DateTimeFormatInfo : ICloneable, IFormatProvider + public sealed class DateTimeFormatInfo : IFormatProvider, ICloneable { - // - // Note, some fields are derived so don't really need to be serialized, but we can't mark as - // optional because Whidbey was expecting them. Post-Arrowhead we could fix that - // once Whidbey serialization is no longer necessary. - // - // cache for the invariant culture. // invariantInfo is constant irrespective of your current culture. - private static volatile DateTimeFormatInfo invariantInfo; + private static volatile DateTimeFormatInfo s_invariantInfo; // an index which points to a record in Culture Data Table. - [NonSerialized] private CultureData m_cultureData; + [NonSerialized] + private CultureData _cultureData; // The culture name used to create this DTFI. + [OptionalField(VersionAdded = 2)] - internal String m_name = null; + private String _name = null; // The language name of the culture used to create this DTFI. - [NonSerialized] private String m_langName = null; + [NonSerialized] + private String _langName = null; // CompareInfo usually used by the parser. - [NonSerialized] private CompareInfo m_compareInfo = null; + [NonSerialized] + private CompareInfo _compareInfo = null; // Culture matches current DTFI. mainly used for string comparisons during parsing. - [NonSerialized] private CultureInfo m_cultureInfo = null; + [NonSerialized] + private CultureInfo _cultureInfo = null; // // Caches for various properties. // - internal String amDesignator = null; - internal String pmDesignator = null; - [OptionalField(VersionAdded = 1)] - internal String dateSeparator = null; // derived from short date (whidbey expects, arrowhead doesn't) - [OptionalField(VersionAdded = 1)] - internal String generalShortTimePattern = null; // short date + short time (whidbey expects, arrowhead doesn't) - [OptionalField(VersionAdded = 1)] - internal String generalLongTimePattern = null; // short date + long time (whidbey expects, arrowhead doesn't) - [OptionalField(VersionAdded = 1)] - internal String timeSeparator = null; // derived from long time (whidbey expects, arrowhead doesn't) - internal String monthDayPattern = null; - [OptionalField(VersionAdded = 2)] // added in .NET Framework Release {2.0SP1/3.0SP1/3.5RTM} - internal String dateTimeOffsetPattern = null; + private String amDesignator = null; + private String pmDesignator = null; + + private String dateSeparator = null; // derived from short date (whidbey expects, arrowhead doesn't) + + private String generalShortTimePattern = null; // short date + short time (whidbey expects, arrowhead doesn't) + + private String generalLongTimePattern = null; // short date + long time (whidbey expects, arrowhead doesn't) + + private String timeSeparator = null; // derived from long time (whidbey expects, arrowhead doesn't) + private String monthDayPattern = null; + // added in .NET Framework Release {2.0SP1/3.0SP1/3.5RTM} + private String dateTimeOffsetPattern = null; // // The following are constant values. // - internal const String rfc1123Pattern = "ddd, dd MMM yyyy HH':'mm':'ss 'GMT'"; + private const String rfc1123Pattern = "ddd, dd MMM yyyy HH':'mm':'ss 'GMT'"; // The sortable pattern is based on ISO 8601. - internal const String sortableDateTimePattern = "yyyy'-'MM'-'dd'T'HH':'mm':'ss"; - internal const String universalSortableDateTimePattern = "yyyy'-'MM'-'dd HH':'mm':'ss'Z'"; + private const String sortableDateTimePattern = "yyyy'-'MM'-'dd'T'HH':'mm':'ss"; + private const String universalSortableDateTimePattern = "yyyy'-'MM'-'dd HH':'mm':'ss'Z'"; // // The following are affected by calendar settings. // - internal Calendar calendar = null; + private Calendar calendar = null; - internal int firstDayOfWeek = -1; - internal int calendarWeekRule = -1; + private int firstDayOfWeek = -1; + private int calendarWeekRule = -1; - [OptionalField(VersionAdded = 1)] - internal String fullDateTimePattern = null; // long date + long time (whidbey expects, arrowhead doesn't) - internal String[] abbreviatedDayNames = null; + private String fullDateTimePattern = null; // long date + long time (whidbey expects, arrowhead doesn't) - [OptionalField(VersionAdded = 2)] - internal String[] m_superShortDayNames = null; + private String[] abbreviatedDayNames = null; + + + private String[] m_superShortDayNames = null; - internal String[] dayNames = null; - internal String[] abbreviatedMonthNames = null; - internal String[] monthNames = null; + private String[] dayNames = null; + private String[] abbreviatedMonthNames = null; + private String[] monthNames = null; // Cache the genitive month names that we retrieve from the data table. - [OptionalField(VersionAdded = 2)] - internal String[] genitiveMonthNames = null; + + private String[] genitiveMonthNames = null; // Cache the abbreviated genitive month names that we retrieve from the data table. - [OptionalField(VersionAdded = 2)] - internal String[] m_genitiveAbbreviatedMonthNames = null; + + private String[] m_genitiveAbbreviatedMonthNames = null; // Cache the month names of a leap year that we retrieve from the data table. - [OptionalField(VersionAdded = 2)] - internal String[] leapYearMonthNames = null; + + private String[] leapYearMonthNames = null; // For our "patterns" arrays we have 2 variables, a string and a string[] // @@ -151,48 +142,46 @@ namespace System.Globalization // When we initially construct our string[], we set the string to string[0] // The "default" Date/time patterns - internal String longDatePattern = null; - internal String shortDatePattern = null; - internal String yearMonthPattern = null; - internal String longTimePattern = null; - internal String shortTimePattern = null; - - // These are Whidbey-serialization compatable arrays (eg: default not included) - // "all" is a bit of a misnomer since the "default" pattern stored above isn't - // necessarily a member of the list + private String longDatePattern = null; + private String shortDatePattern = null; + private String yearMonthPattern = null; + private String longTimePattern = null; + private String shortTimePattern = null; + [OptionalField(VersionAdded = 3)] - private String[] allYearMonthPatterns = null; // This was wasn't serialized in Whidbey - internal String[] allShortDatePatterns = null; - internal String[] allLongDatePatterns = null; - internal String[] allShortTimePatterns = null; - internal String[] allLongTimePatterns = null; + private String[] allYearMonthPatterns = null; + + private String[] allShortDatePatterns = null; + private String[] allLongDatePatterns = null; + private String[] allShortTimePatterns = null; + private String[] allLongTimePatterns = null; // Cache the era names for this DateTimeFormatInfo instance. - internal String[] m_eraNames = null; - internal String[] m_abbrevEraNames = null; - internal String[] m_abbrevEnglishEraNames = null; + private String[] m_eraNames = null; + private String[] m_abbrevEraNames = null; + private String[] m_abbrevEnglishEraNames = null; - internal int[] optionalCalendars = null; + private CalendarId[] optionalCalendars = null; private const int DEFAULT_ALL_DATETIMES_SIZE = 132; // CultureInfo updates this - internal bool m_isReadOnly = false; + internal bool _isReadOnly = false; // This flag gives hints about if formatting/parsing should perform special code path for things like // genitive form or leap year month names. - [OptionalField(VersionAdded = 2)] - internal DateTimeFormatFlags formatFlags = DateTimeFormatFlags.NotInitialized; + + private DateTimeFormatFlags formatFlags = DateTimeFormatFlags.NotInitialized; private String CultureName { get { - if (m_name == null) + if (_name == null) { - m_name = m_cultureData.CultureName; + _name = _cultureData.CultureName; } - return (m_name); + return (_name); } } @@ -200,23 +189,24 @@ namespace System.Globalization { get { - if (m_cultureInfo == null) + if (_cultureInfo == null) { - m_cultureInfo = CultureInfo.GetCultureInfo(this.CultureName); + _cultureInfo = CultureInfo.GetCultureInfo(this.CultureName); } - return m_cultureInfo; + return _cultureInfo; } } + // TODO: This ignores other cultures that might want to do something similar private String LanguageName { get { - if (m_langName == null) + if (_langName == null) { - m_langName = m_cultureData.SISO639LANGNAME; + _langName = _cultureData.SISO639LANGNAME; } - return (m_langName); + return (_langName); } } @@ -231,12 +221,13 @@ namespace System.Globalization if (this.abbreviatedDayNames == null) { // Get the abbreviated day names for our current calendar - this.abbreviatedDayNames = m_cultureData.AbbreviatedDayNames(Calendar.ID); + this.abbreviatedDayNames = _cultureData.AbbreviatedDayNames(Calendar.ID); Debug.Assert(this.abbreviatedDayNames.Length == 7, "[DateTimeFormatInfo.GetAbbreviatedDayOfWeekNames] Expected 7 day names in a week"); } return (this.abbreviatedDayNames); } + //////////////////////////////////////////////////////////////////////// // // Action: Returns the string array of the one-letter day of week names. @@ -254,7 +245,7 @@ namespace System.Globalization if (this.m_superShortDayNames == null) { // Get the super short day names for our current calendar - this.m_superShortDayNames = m_cultureData.SuperShortDayNames(Calendar.ID); + this.m_superShortDayNames = _cultureData.SuperShortDayNames(Calendar.ID); Debug.Assert(this.m_superShortDayNames.Length == 7, "[DateTimeFormatInfo.internalGetSuperShortDayNames] Expected 7 day names in a week"); } return (this.m_superShortDayNames); @@ -271,7 +262,7 @@ namespace System.Globalization if (this.dayNames == null) { // Get the day names for our current calendar - this.dayNames = m_cultureData.DayNames(Calendar.ID); + this.dayNames = _cultureData.DayNames(Calendar.ID); Debug.Assert(this.dayNames.Length == 7, "[DateTimeFormatInfo.GetDayOfWeekNames] Expected 7 day names in a week"); } return (this.dayNames); @@ -288,7 +279,7 @@ namespace System.Globalization if (this.abbreviatedMonthNames == null) { // Get the month names for our current calendar - this.abbreviatedMonthNames = m_cultureData.AbbreviatedMonthNames(Calendar.ID); + this.abbreviatedMonthNames = _cultureData.AbbreviatedMonthNames(Calendar.ID); Debug.Assert(this.abbreviatedMonthNames.Length == 12 || this.abbreviatedMonthNames.Length == 13, "[DateTimeFormatInfo.GetAbbreviatedMonthNames] Expected 12 or 13 month names in a year"); } @@ -307,7 +298,7 @@ namespace System.Globalization if (this.monthNames == null) { // Get the month names for our current calendar - this.monthNames = m_cultureData.MonthNames(Calendar.ID); + this.monthNames = _cultureData.MonthNames(Calendar.ID); Debug.Assert(this.monthNames.Length == 12 || this.monthNames.Length == 13, "[DateTimeFormatInfo.GetMonthNames] Expected 12 or 13 month names in a year"); } @@ -320,28 +311,25 @@ namespace System.Globalization // Invariant DateTimeFormatInfo doesn't have user-overriden values // Default calendar is gregorian public DateTimeFormatInfo() - : this(CultureInfo.InvariantCulture.m_cultureData, - GregorianCalendar.GetDefaultInstance()) + : this(CultureInfo.InvariantCulture._cultureData, GregorianCalendar.GetDefaultInstance()) { } internal DateTimeFormatInfo(CultureData cultureData, Calendar cal) { - Contract.Requires(cultureData != null); - Contract.Requires(cal != null); + Debug.Assert(cultureData != null); + Debug.Assert(cal != null); // Remember our culture - m_cultureData = cultureData; + _cultureData = cultureData; - // m_isDefaultCalendar is set in the setter of Calendar below. this.Calendar = cal; } - private void InitializeOverridableProperties(CultureData cultureData, int calendarID) + + private void InitializeOverridableProperties(CultureData cultureData, CalendarId calendarId) { - // Silverlight 2.0 never took a snapshot of the user's overridable properties - // This has a substantial performance impact so skip when CoreCLR - Contract.Requires(cultureData != null); - Debug.Assert(calendarID > 0, "[DateTimeFormatInfo.Populate] Expected Calendar.ID > 0"); + Debug.Assert(cultureData != null); + Debug.Assert(calendarId != CalendarId.UNINITIALIZED_VALUE, "[DateTimeFormatInfo.Populate] Expected initalized calendarId"); if (this.firstDayOfWeek == -1) { this.firstDayOfWeek = cultureData.IFIRSTDAYOFWEEK; } if (this.calendarWeekRule == -1) { this.calendarWeekRule = cultureData.IFIRSTWEEKOFYEAR; } @@ -349,71 +337,79 @@ namespace System.Globalization if (this.amDesignator == null) { this.amDesignator = cultureData.SAM1159; } if (this.pmDesignator == null) { this.pmDesignator = cultureData.SPM2359; } if (this.timeSeparator == null) { this.timeSeparator = cultureData.TimeSeparator; } - if (this.dateSeparator == null) { this.dateSeparator = cultureData.DateSeparator(calendarID); } + if (this.dateSeparator == null) { this.dateSeparator = cultureData.DateSeparator(calendarId); } - this.allLongTimePatterns = m_cultureData.LongTimes; + this.allLongTimePatterns = _cultureData.LongTimes; Debug.Assert(this.allLongTimePatterns.Length > 0, "[DateTimeFormatInfo.Populate] Expected some long time patterns"); - this.allShortTimePatterns = m_cultureData.ShortTimes; + this.allShortTimePatterns = _cultureData.ShortTimes; Debug.Assert(this.allShortTimePatterns.Length > 0, "[DateTimeFormatInfo.Populate] Expected some short time patterns"); - this.allLongDatePatterns = cultureData.LongDates(calendarID); + this.allLongDatePatterns = cultureData.LongDates(calendarId); Debug.Assert(this.allLongDatePatterns.Length > 0, "[DateTimeFormatInfo.Populate] Expected some long date patterns"); - this.allShortDatePatterns = cultureData.ShortDates(calendarID); + this.allShortDatePatterns = cultureData.ShortDates(calendarId); Debug.Assert(this.allShortDatePatterns.Length > 0, "[DateTimeFormatInfo.Populate] Expected some short date patterns"); - allYearMonthPatterns = cultureData.YearMonths(calendarID); - Debug.Assert(allYearMonthPatterns.Length > 0, "[DateTimeFormatInfo.Populate] Expected some year month patterns"); + this.allYearMonthPatterns = cultureData.YearMonths(calendarId); + Debug.Assert(this.allYearMonthPatterns.Length > 0, "[DateTimeFormatInfo.Populate] Expected some year month patterns"); } - #region Serialization - // The following fields are defined to keep the serialization compatibility with .NET V1.0/V1.1. - [OptionalField(VersionAdded = 1)] - private int CultureID; - [OptionalField(VersionAdded = 1)] - private bool m_useUserOverride; - [OptionalField(VersionAdded = 1)] - private bool bUseCalendarInfo; [OptionalField(VersionAdded = 1)] - private int nDataItem; - [OptionalField(VersionAdded = 2)] - internal bool m_isDefaultCalendar; // NEVER USED, DO NOT USE THIS! (Serialized in Whidbey) + private bool _useUserOverride; // This was synthesized by Whidbey so we knew what words might appear in the middle of a date string // Now we always synthesize so its not helpful - [OptionalField(VersionAdded = 1)] - internal String[] m_dateWords = null; // calculated, no need to serialze (whidbey expects, arrowhead doesn't) + + internal String[] m_dateWords = null; + + [OnSerializing] + private void OnSerializing(StreamingContext ctx) + { + _name = this.CultureName; // make sure the _name is initialized. + _useUserOverride = _cultureData.UseUserOverride; + + // Important to initialize these fields otherwise we may run into exception when deserializing on Whidbey + // because Whidbey try to initialize some of these fields using calendar data which could be null values + // and then we get exceptions. So we call the accessors to force the caches to get loaded. + Object o; + o = this.LongTimePattern; + o = this.LongDatePattern; + o = this.ShortTimePattern; + o = this.ShortDatePattern; + o = this.YearMonthPattern; + o = this.AllLongTimePatterns; + o = this.AllLongDatePatterns; + o = this.AllShortTimePatterns; + o = this.AllShortDatePatterns; + o = this.AllYearMonthPatterns; + } [OnDeserialized] private void OnDeserialized(StreamingContext ctx) { - if (this.m_name != null) + if (_name != null) { - m_cultureData = CultureData.GetCultureData(m_name, m_useUserOverride); - - if (m_cultureData == null) - throw new CultureNotFoundException( - nameof(m_name), m_name, Environment.GetResourceString("Argument_CultureNotSupported")); + _cultureData = CultureData.GetCultureData(_name, _useUserOverride); + if (_cultureData == null) + { + throw new CultureNotFoundException("_name", _name, SR.Argument_CultureNotSupported); + } } - // Note: This is for Everett compatibility -#if FEATURE_USE_LCID - else - m_cultureData = CultureData.GetCultureData(CultureID, m_useUserOverride); -#endif if (calendar == null) { calendar = (Calendar)GregorianCalendar.GetDefaultInstance().Clone(); - calendar.SetReadOnlyState(m_isReadOnly); + calendar.SetReadOnlyState(_isReadOnly); } - InitializeOverridableProperties(m_cultureData, calendar.ID); + + InitializeOverridableProperties(_cultureData, calendar.ID); // // turn off read only state till we finish initializing all fields and then store read only state after we are done. // - bool isReadOnly = m_isReadOnly; - m_isReadOnly = false; + bool isReadOnly = _isReadOnly; + _isReadOnly = false; // If we deserialized defaults ala Whidbey, make sure they're still defaults // Whidbey's arrays could get a bit mixed up. @@ -423,36 +419,8 @@ namespace System.Globalization if (longTimePattern != null) this.LongTimePattern = longTimePattern; if (shortTimePattern != null) this.ShortTimePattern = shortTimePattern; - m_isReadOnly = isReadOnly; - } - - [OnSerializing] - private void OnSerializing(StreamingContext ctx) - { -#if FEATURE_USE_LCID - CultureID = m_cultureData.ILANGUAGE; // Used for serialization compatibility with Whidbey which didn't always serialize the name -#endif - m_useUserOverride = m_cultureData.UseUserOverride; - - // make sure the m_name is initialized. - m_name = this.CultureName; - - // Important to initialize these fields otherwise we may run into exception when deserializing on Whidbey - // because Whidbey try to initialize some of these fields using calendar data which could be null values - // and then we get exceptions. So we call the accessors to force the caches to get loaded. - Object o; - o = this.LongTimePattern; - o = this.LongDatePattern; - o = this.ShortTimePattern; - o = this.ShortDatePattern; - o = this.YearMonthPattern; - o = this.AllLongTimePatterns; - o = this.AllLongDatePatterns; - o = this.AllShortTimePatterns; - o = this.AllShortDatePatterns; - o = this.AllYearMonthPatterns; + _isReadOnly = isReadOnly; } - #endregion Serialization // Returns a default DateTimeFormatInfo that will be universally // supported and constant irrespective of the current culture. @@ -464,14 +432,14 @@ namespace System.Globalization get { Contract.Ensures(Contract.Result() != null); - if (invariantInfo == null) + if (s_invariantInfo == null) { DateTimeFormatInfo info = new DateTimeFormatInfo(); info.Calendar.SetReadOnlyState(true); - info.m_isReadOnly = true; - invariantInfo = info; + info._isReadOnly = true; + s_invariantInfo = info; } - return (invariantInfo); + return (s_invariantInfo); } } @@ -483,8 +451,8 @@ namespace System.Globalization get { Contract.Ensures(Contract.Result() != null); - System.Globalization.CultureInfo culture = System.Threading.Thread.CurrentThread.CurrentCulture; - if (!culture.m_isInherited) + System.Globalization.CultureInfo culture = System.Globalization.CultureInfo.CurrentCulture; + if (!culture._isInherited) { DateTimeFormatInfo info = culture.dateTimeInfo; if (info != null) @@ -502,7 +470,7 @@ namespace System.Globalization // Fast case for a regular CultureInfo DateTimeFormatInfo info; CultureInfo cultureProvider = provider as CultureInfo; - if (cultureProvider != null && !cultureProvider.m_isInherited) + if (cultureProvider != null && !cultureProvider._isInherited) { return cultureProvider.DateTimeFormat; } @@ -538,7 +506,7 @@ namespace System.Globalization // We can use the data member calendar in the setter, instead of the property Calendar, // since the cloned copy should have the same state as the original copy. n.calendar = (Calendar)this.Calendar.Clone(); - n.m_isReadOnly = false; + n._isReadOnly = false; return n; } @@ -549,9 +517,8 @@ namespace System.Globalization { if (this.amDesignator == null) { - this.amDesignator = m_cultureData.SAM1159; + this.amDesignator = _cultureData.SAM1159; } - Debug.Assert(this.amDesignator != null, "DateTimeFormatInfo.AMDesignator, amDesignator != null"); return (this.amDesignator); } @@ -559,11 +526,11 @@ namespace System.Globalization set { if (IsReadOnly) - throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly")); + throw new InvalidOperationException(SR.InvalidOperation_ReadOnly); if (value == null) { throw new ArgumentNullException(nameof(value), - Environment.GetResourceString("ArgumentNull_String")); + SR.ArgumentNull_String); } Contract.EndContractBlock(); ClearTokenHashTable(); @@ -585,11 +552,10 @@ namespace System.Globalization set { if (IsReadOnly) - throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly")); + throw new InvalidOperationException(SR.InvalidOperation_ReadOnly); if (value == null) { - throw new ArgumentNullException(nameof(value), - Environment.GetResourceString("ArgumentNull_Obj")); + throw new ArgumentNullException(nameof(value), SR.ArgumentNull_Obj); } Contract.EndContractBlock(); if (value == calendar) @@ -653,19 +619,13 @@ namespace System.Globalization // firstDayOfWeek // calendarWeekRule - // We don't need to clear these because they're only used for whidbey compat serialization - // the only values we use are the all...Patterns[0] - // longDatePattern - // shortDatePattern - // yearMonthPattern - // remember to reload tokens ClearTokenHashTable(); } // Remember the new calendar calendar = value; - InitializeOverridableProperties(m_cultureData, calendar.ID); + InitializeOverridableProperties(_cultureData, calendar.ID); // We succeeded, return return; @@ -673,17 +633,17 @@ namespace System.Globalization } // The assigned calendar is not a valid calendar for this culture, throw - throw new ArgumentOutOfRangeException(nameof(value), Environment.GetResourceString("Argument_InvalidCalendar")); + throw new ArgumentOutOfRangeException(nameof(value), SR.Argument_InvalidCalendar); } } - private int[] OptionalCalendars + private CalendarId[] OptionalCalendars { get { if (this.optionalCalendars == null) { - this.optionalCalendars = m_cultureData.CalendarIds; + this.optionalCalendars = _cultureData.CalendarIds; } return (this.optionalCalendars); } @@ -703,11 +663,11 @@ namespace System.Globalization if (eraName == null) { throw new ArgumentNullException(nameof(eraName), - Environment.GetResourceString("ArgumentNull_String")); + SR.ArgumentNull_String); } Contract.EndContractBlock(); - // For Geo-Political reasons, the Era Name and Abbreviated Era Name + // The Era Name and Abbreviated Era Name // for Taiwan Calendar on non-Taiwan SKU returns empty string (which // would be matched below) but we don't want the empty string to give // us an Era number @@ -728,7 +688,7 @@ namespace System.Globalization // Compare the era name in a case-insensitive way for the appropriate culture. if (m_eraNames[i].Length > 0) { - if (String.Compare(eraName, m_eraNames[i], this.Culture, CompareOptions.IgnoreCase) == 0) + if (this.Culture.CompareInfo.Compare(eraName, m_eraNames[i], CompareOptions.IgnoreCase) == 0) { return (i + 1); } @@ -737,7 +697,7 @@ namespace System.Globalization for (int i = 0; i < AbbreviatedEraNames.Length; i++) { // Compare the abbreviated era name in a case-insensitive way for the appropriate culture. - if (String.Compare(eraName, m_abbrevEraNames[i], this.Culture, CompareOptions.IgnoreCase) == 0) + if (this.Culture.CompareInfo.Compare(eraName, m_abbrevEraNames[i], CompareOptions.IgnoreCase) == 0) { return (i + 1); } @@ -746,7 +706,7 @@ namespace System.Globalization { // this comparison should use the InvariantCulture. The English name could have linguistically // interesting characters. - if (String.Compare(eraName, m_abbrevEnglishEraNames[i], StringComparison.InvariantCultureIgnoreCase) == 0) + if (CultureInfo.InvariantCulture.CompareInfo.Compare(eraName, m_abbrevEnglishEraNames[i], CompareOptions.IgnoreCase) == 0) { return (i + 1); } @@ -754,13 +714,14 @@ namespace System.Globalization return (-1); } + internal String[] EraNames { get { if (this.m_eraNames == null) { - this.m_eraNames = m_cultureData.EraNames(Calendar.ID); ; + this.m_eraNames = _cultureData.EraNames(Calendar.ID); ; } return (this.m_eraNames); } @@ -790,7 +751,7 @@ namespace System.Globalization { return (m_eraNames[era]); } - throw new ArgumentOutOfRangeException(nameof(era), Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue")); + throw new ArgumentOutOfRangeException(nameof(era), SR.ArgumentOutOfRange_InvalidEraValue); } internal String[] AbbreviatedEraNames @@ -799,7 +760,7 @@ namespace System.Globalization { if (this.m_abbrevEraNames == null) { - this.m_abbrevEraNames = m_cultureData.AbbrevEraNames(Calendar.ID); + this.m_abbrevEraNames = _cultureData.AbbrevEraNames(Calendar.ID); } return (this.m_abbrevEraNames); } @@ -822,7 +783,7 @@ namespace System.Globalization { return (m_abbrevEraNames[era]); } - throw new ArgumentOutOfRangeException(nameof(era), Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue")); + throw new ArgumentOutOfRangeException(nameof(era), SR.ArgumentOutOfRange_InvalidEraValue); } internal String[] AbbreviatedEnglishEraNames @@ -832,61 +793,57 @@ namespace System.Globalization if (this.m_abbrevEnglishEraNames == null) { Debug.Assert(Calendar.ID > 0, "[DateTimeFormatInfo.AbbreviatedEnglishEraNames] Expected Calendar.ID > 0"); - this.m_abbrevEnglishEraNames = m_cultureData.AbbreviatedEnglishEraNames(Calendar.ID); + this.m_abbrevEnglishEraNames = _cultureData.AbbreviatedEnglishEraNames(Calendar.ID); } return (this.m_abbrevEnglishEraNames); } } - // Note that cultureData derives this from the short date format (unless someone's set this previously) // Note that this property is quite undesirable. - public String DateSeparator + public string DateSeparator { get { - if (this.dateSeparator == null) + if (dateSeparator == null) { - this.dateSeparator = m_cultureData.DateSeparator(Calendar.ID); + dateSeparator = _cultureData.DateSeparator(Calendar.ID); } - Debug.Assert(this.dateSeparator != null, "DateTimeFormatInfo.DateSeparator, dateSeparator != null"); - return (this.dateSeparator); + return dateSeparator; } - set { if (IsReadOnly) - throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly")); + throw new InvalidOperationException(SR.InvalidOperation_ReadOnly); + if (value == null) { - throw new ArgumentNullException(nameof(value), - Environment.GetResourceString("ArgumentNull_String")); + throw new ArgumentNullException(nameof(value), SR.ArgumentNull_String); } Contract.EndContractBlock(); ClearTokenHashTable(); - this.dateSeparator = value; + dateSeparator = value; } } - public DayOfWeek FirstDayOfWeek { get { if (this.firstDayOfWeek == -1) { - this.firstDayOfWeek = m_cultureData.IFIRSTDAYOFWEEK; + this.firstDayOfWeek = _cultureData.IFIRSTDAYOFWEEK; } - Debug.Assert(this.firstDayOfWeek != -1, "DateTimeFormatInfo.FirstDayOfWeek, firstDayOfWeek != -1"); + return ((DayOfWeek)this.firstDayOfWeek); } set { if (IsReadOnly) - throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly")); + throw new InvalidOperationException(SR.InvalidOperation_ReadOnly); if (value >= DayOfWeek.Sunday && value <= DayOfWeek.Saturday) { firstDayOfWeek = (int)value; @@ -894,22 +851,20 @@ namespace System.Globalization else { throw new ArgumentOutOfRangeException( - nameof(value), Environment.GetResourceString("ArgumentOutOfRange_Range", + nameof(value), SR.Format(SR.ArgumentOutOfRange_Range, DayOfWeek.Sunday, DayOfWeek.Saturday)); } } } - public CalendarWeekRule CalendarWeekRule { get { if (this.calendarWeekRule == -1) { - this.calendarWeekRule = m_cultureData.IFIRSTWEEKOFYEAR; + this.calendarWeekRule = _cultureData.IFIRSTWEEKOFYEAR; } - Debug.Assert(this.calendarWeekRule != -1, "DateTimeFormatInfo.CalendarWeekRule, calendarWeekRule != -1"); return ((CalendarWeekRule)this.calendarWeekRule); } @@ -917,7 +872,7 @@ namespace System.Globalization set { if (IsReadOnly) - throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly")); + throw new InvalidOperationException(SR.InvalidOperation_ReadOnly); if (value >= CalendarWeekRule.FirstDay && value <= CalendarWeekRule.FirstFourDayWeek) { calendarWeekRule = (int)value; @@ -925,14 +880,12 @@ namespace System.Globalization else { throw new ArgumentOutOfRangeException( - nameof(value), Environment.GetResourceString("ArgumentOutOfRange_Range", + nameof(value), SR.Format(SR.ArgumentOutOfRange_Range, CalendarWeekRule.FirstDay, CalendarWeekRule.FirstFourDayWeek)); } } } - - public String FullDateTimePattern { get @@ -947,11 +900,11 @@ namespace System.Globalization set { if (IsReadOnly) - throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly")); + throw new InvalidOperationException(SR.InvalidOperation_ReadOnly); if (value == null) { throw new ArgumentNullException(nameof(value), - Environment.GetResourceString("ArgumentNull_String")); + SR.ArgumentNull_String); } Contract.EndContractBlock(); fullDateTimePattern = value; @@ -981,11 +934,11 @@ namespace System.Globalization set { if (IsReadOnly) - throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly")); + throw new InvalidOperationException(SR.InvalidOperation_ReadOnly); if (value == null) { throw new ArgumentNullException(nameof(value), - Environment.GetResourceString("ArgumentNull_String")); + SR.ArgumentNull_String); } Contract.EndContractBlock(); @@ -1022,11 +975,11 @@ namespace System.Globalization set { if (IsReadOnly) - throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly")); + throw new InvalidOperationException(SR.InvalidOperation_ReadOnly); if (value == null) { throw new ArgumentNullException(nameof(value), - Environment.GetResourceString("ArgumentNull_String")); + SR.ArgumentNull_String); } Contract.EndContractBlock(); @@ -1052,7 +1005,7 @@ namespace System.Globalization if (this.monthDayPattern == null) { Debug.Assert(Calendar.ID > 0, "[DateTimeFormatInfo.MonthDayPattern] Expected calID > 0"); - this.monthDayPattern = m_cultureData.MonthDay(Calendar.ID); + this.monthDayPattern = _cultureData.MonthDay(Calendar.ID); } Debug.Assert(this.monthDayPattern != null, "DateTimeFormatInfo.MonthDayPattern, monthDayPattern != null"); return (this.monthDayPattern); @@ -1061,11 +1014,11 @@ namespace System.Globalization set { if (IsReadOnly) - throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly")); + throw new InvalidOperationException(SR.InvalidOperation_ReadOnly); if (value == null) { throw new ArgumentNullException(nameof(value), - Environment.GetResourceString("ArgumentNull_String")); + SR.ArgumentNull_String); } Contract.EndContractBlock(); @@ -1080,9 +1033,8 @@ namespace System.Globalization { if (this.pmDesignator == null) { - this.pmDesignator = m_cultureData.SPM2359; + this.pmDesignator = _cultureData.SPM2359; } - Debug.Assert(this.pmDesignator != null, "DateTimeFormatInfo.PMDesignator, pmDesignator != null"); return (this.pmDesignator); } @@ -1090,11 +1042,11 @@ namespace System.Globalization set { if (IsReadOnly) - throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly")); + throw new InvalidOperationException(SR.InvalidOperation_ReadOnly); if (value == null) { throw new ArgumentNullException(nameof(value), - Environment.GetResourceString("ArgumentNull_String")); + SR.ArgumentNull_String); } Contract.EndContractBlock(); ClearTokenHashTable(); @@ -1134,10 +1086,10 @@ namespace System.Globalization set { if (IsReadOnly) - throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly")); + throw new InvalidOperationException(SR.InvalidOperation_ReadOnly); if (value == null) throw new ArgumentNullException(nameof(value), - Environment.GetResourceString("ArgumentNull_String")); + SR.ArgumentNull_String); Contract.EndContractBlock(); // Remember the new string @@ -1175,11 +1127,11 @@ namespace System.Globalization set { if (IsReadOnly) - throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly")); + throw new InvalidOperationException(SR.InvalidOperation_ReadOnly); if (value == null) { throw new ArgumentNullException(nameof(value), - Environment.GetResourceString("ArgumentNull_String")); + SR.ArgumentNull_String); } Contract.EndContractBlock(); @@ -1316,15 +1268,14 @@ namespace System.Globalization // Note that cultureData derives this from the long time format (unless someone's set this previously) // Note that this property is quite undesirable. - public String TimeSeparator + public string TimeSeparator { get { if (timeSeparator == null) { - timeSeparator = m_cultureData.TimeSeparator; + timeSeparator = _cultureData.TimeSeparator; } - Debug.Assert(this.timeSeparator != null, "DateTimeFormatInfo.TimeSeparator, timeSeparator != null"); return (timeSeparator); } @@ -1332,12 +1283,13 @@ namespace System.Globalization set { if (IsReadOnly) - throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly")); + throw new InvalidOperationException(SR.InvalidOperation_ReadOnly); + if (value == null) { - throw new ArgumentNullException(nameof(value), - Environment.GetResourceString("ArgumentNull_String")); + throw new ArgumentNullException(nameof(value), SR.ArgumentNull_String); } + Contract.EndContractBlock(); ClearTokenHashTable(); @@ -1345,7 +1297,6 @@ namespace System.Globalization } } - public String UniversalSortableDateTimePattern { get @@ -1375,11 +1326,11 @@ namespace System.Globalization set { if (IsReadOnly) - throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly")); + throw new InvalidOperationException(SR.InvalidOperation_ReadOnly); if (value == null) { throw new ArgumentNullException(nameof(value), - Environment.GetResourceString("ArgumentNull_String")); + SR.ArgumentNull_String); } Contract.EndContractBlock(); @@ -1394,16 +1345,16 @@ namespace System.Globalization // // Check if a string array contains a null value, and throw ArgumentNullException with parameter name "value" // - static private void CheckNullValue(String[] values, int length) + private static void CheckNullValue(String[] values, int length) { - Contract.Requires(values != null, "value != null"); - Contract.Requires(values.Length >= length); + Debug.Assert(values != null, "value != null"); + Debug.Assert(values.Length >= length); for (int i = 0; i < length; i++) { if (values[i] == null) { throw new ArgumentNullException("value", - Environment.GetResourceString("ArgumentNull_ArrayValue")); + SR.ArgumentNull_ArrayValue); } } } @@ -1419,15 +1370,15 @@ namespace System.Globalization set { if (IsReadOnly) - throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly")); + throw new InvalidOperationException(SR.InvalidOperation_ReadOnly); if (value == null) { throw new ArgumentNullException(nameof(value), - Environment.GetResourceString("ArgumentNull_Array")); + SR.ArgumentNull_Array); } if (value.Length != 7) { - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidArrayLength", 7), nameof(value)); + throw new ArgumentException(SR.Format(SR.Argument_InvalidArrayLength, 7), nameof(value)); } Contract.EndContractBlock(); CheckNullValue(value, value.Length); @@ -1437,7 +1388,6 @@ namespace System.Globalization } } - // Returns the string array of the one-letter day of week names. public String[] ShortestDayNames { @@ -1449,15 +1399,15 @@ namespace System.Globalization set { if (IsReadOnly) - throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly")); + throw new InvalidOperationException(SR.InvalidOperation_ReadOnly); if (value == null) { throw new ArgumentNullException(nameof(value), - Environment.GetResourceString("ArgumentNull_Array")); + SR.ArgumentNull_Array); } if (value.Length != 7) { - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidArrayLength", 7), nameof(value)); + throw new ArgumentException(SR.Format(SR.Argument_InvalidArrayLength, 7), nameof(value)); } Contract.EndContractBlock(); CheckNullValue(value, value.Length); @@ -1476,15 +1426,15 @@ namespace System.Globalization set { if (IsReadOnly) - throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly")); + throw new InvalidOperationException(SR.InvalidOperation_ReadOnly); if (value == null) { throw new ArgumentNullException(nameof(value), - Environment.GetResourceString("ArgumentNull_Array")); + SR.ArgumentNull_Array); } if (value.Length != 7) { - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidArrayLength", 7), nameof(value)); + throw new ArgumentException(SR.Format(SR.Argument_InvalidArrayLength, 7), nameof(value)); } Contract.EndContractBlock(); CheckNullValue(value, value.Length); @@ -1505,15 +1455,15 @@ namespace System.Globalization set { if (IsReadOnly) - throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly")); + throw new InvalidOperationException(SR.InvalidOperation_ReadOnly); if (value == null) { throw new ArgumentNullException(nameof(value), - Environment.GetResourceString("ArgumentNull_Array")); + SR.ArgumentNull_Array); } if (value.Length != 13) { - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidArrayLength", 13), nameof(value)); + throw new ArgumentException(SR.Format(SR.Argument_InvalidArrayLength, 13), nameof(value)); } Contract.EndContractBlock(); CheckNullValue(value, value.Length - 1); @@ -1533,15 +1483,15 @@ namespace System.Globalization set { if (IsReadOnly) - throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly")); + throw new InvalidOperationException(SR.InvalidOperation_ReadOnly); if (value == null) { throw new ArgumentNullException(nameof(value), - Environment.GetResourceString("ArgumentNull_Array")); + SR.ArgumentNull_Array); } if (value.Length != 13) { - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidArrayLength", 13), nameof(value)); + throw new ArgumentException(SR.Format(SR.Argument_InvalidArrayLength, 13), nameof(value)); } Contract.EndContractBlock(); CheckNullValue(value, value.Length - 1); @@ -1552,7 +1502,7 @@ namespace System.Globalization // Whitespaces that we allow in the month names. // U+00a0 is non-breaking space. - private static char[] MonthSpaces = { ' ', '\u00a0' }; + private static readonly char[] s_monthSpaces = { ' ', '\u00a0' }; internal bool HasSpacesInMonthNames { @@ -1607,7 +1557,7 @@ namespace System.Globalization if ((month < 1) || (month > monthNamesArray.Length)) { throw new ArgumentOutOfRangeException( - nameof(month), Environment.GetResourceString("ArgumentOutOfRange_Range", + nameof(month), SR.Format(SR.ArgumentOutOfRange_Range, 1, monthNamesArray.Length)); } return (monthNamesArray[month - 1]); @@ -1627,7 +1577,7 @@ namespace System.Globalization { if (this.m_genitiveAbbreviatedMonthNames == null) { - this.m_genitiveAbbreviatedMonthNames = m_cultureData.AbbreviatedGenitiveMonthNames(this.Calendar.ID); + this.m_genitiveAbbreviatedMonthNames = _cultureData.AbbreviatedGenitiveMonthNames(this.Calendar.ID); Debug.Assert(this.m_genitiveAbbreviatedMonthNames.Length == 13, "[DateTimeFormatInfo.GetGenitiveMonthNames] Expected 13 abbreviated genitive month names in a year"); } @@ -1636,7 +1586,7 @@ namespace System.Globalization if (this.genitiveMonthNames == null) { - this.genitiveMonthNames = m_cultureData.GenitiveMonthNames(this.Calendar.ID); + this.genitiveMonthNames = _cultureData.GenitiveMonthNames(this.Calendar.ID); Debug.Assert(this.genitiveMonthNames.Length == 13, "[DateTimeFormatInfo.GetGenitiveMonthNames] Expected 13 genitive month names in a year"); } @@ -1655,7 +1605,7 @@ namespace System.Globalization if (this.leapYearMonthNames == null) { Debug.Assert(Calendar.ID > 0, "[DateTimeFormatInfo.internalGetLeapYearMonthNames] Expected Calendar.ID > 0"); - this.leapYearMonthNames = m_cultureData.LeapYearMonthNames(Calendar.ID); + this.leapYearMonthNames = _cultureData.LeapYearMonthNames(Calendar.ID); Debug.Assert(this.leapYearMonthNames.Length == 13, "[DateTimeFormatInfo.internalGetLeapYearMonthNames] Expepcted 13 leap year month names"); } @@ -1668,7 +1618,7 @@ namespace System.Globalization if ((int)dayofweek < 0 || (int)dayofweek > 6) { throw new ArgumentOutOfRangeException( - nameof(dayofweek), Environment.GetResourceString("ArgumentOutOfRange_Range", + nameof(dayofweek), SR.Format(SR.ArgumentOutOfRange_Range, DayOfWeek.Sunday, DayOfWeek.Saturday)); } Contract.EndContractBlock(); @@ -1679,14 +1629,13 @@ namespace System.Globalization return (internalGetAbbreviatedDayOfWeekNames()[(int)dayofweek]); } - // Returns the super short day of week names for the specified day of week. - public String GetShortestDayName(DayOfWeek dayOfWeek) + public string GetShortestDayName(DayOfWeek dayOfWeek) { if ((int)dayOfWeek < 0 || (int)dayOfWeek > 6) { throw new ArgumentOutOfRangeException( - nameof(dayOfWeek), Environment.GetResourceString("ArgumentOutOfRange_Range", + nameof(dayOfWeek), SR.Format(SR.ArgumentOutOfRange_Range, DayOfWeek.Sunday, DayOfWeek.Saturday)); } Contract.EndContractBlock(); @@ -1698,10 +1647,10 @@ namespace System.Globalization } // Get all possible combination of inputs - static private String[] GetCombinedPatterns(String[] patterns1, String[] patterns2, String connectString) + private static String[] GetCombinedPatterns(String[] patterns1, String[] patterns2, String connectString) { - Contract.Requires(patterns1 != null); - Contract.Requires(patterns2 != null); + Debug.Assert(patterns1 != null); + Debug.Assert(patterns2 != null); // Get array size String[] result = new String[patterns1.Length * patterns2.Length]; @@ -1721,8 +1670,7 @@ namespace System.Globalization return (result); } - - public String[] GetAllDateTimePatterns() + public string[] GetAllDateTimePatterns() { List results = new List(DEFAULT_ALL_DATETIMES_SIZE); @@ -1737,8 +1685,7 @@ namespace System.Globalization return results.ToArray(); } - - public String[] GetAllDateTimePatterns(char format) + public string[] GetAllDateTimePatterns(char format) { Contract.Ensures(Contract.Result() != null); String[] result = null; @@ -1770,7 +1717,7 @@ namespace System.Globalization break; case 'o': case 'O': - result = new String[] { DateTimeFormat.RoundtripFormat }; + result = new String[] { RoundtripFormat }; break; case 'r': case 'R': @@ -1793,7 +1740,7 @@ namespace System.Globalization result = this.AllYearMonthPatterns; break; default: - throw new ArgumentException(Environment.GetResourceString("Format_BadFormatSpecifier"), nameof(format)); + throw new ArgumentException(SR.Format_BadFormatSpecifier, nameof(format)); } return (result); } @@ -1804,7 +1751,7 @@ namespace System.Globalization if ((int)dayofweek < 0 || (int)dayofweek > 6) { throw new ArgumentOutOfRangeException( - nameof(dayofweek), Environment.GetResourceString("ArgumentOutOfRange_Range", + nameof(dayofweek), SR.Format(SR.ArgumentOutOfRange_Range, DayOfWeek.Sunday, DayOfWeek.Saturday)); } Contract.EndContractBlock(); @@ -1820,7 +1767,7 @@ namespace System.Globalization if (month < 1 || month > 13) { throw new ArgumentOutOfRangeException( - nameof(month), Environment.GetResourceString("ArgumentOutOfRange_Range", + nameof(month), SR.Format(SR.ArgumentOutOfRange_Range, 1, 13)); } Contract.EndContractBlock(); @@ -1834,7 +1781,7 @@ namespace System.Globalization if (month < 1 || month > 13) { throw new ArgumentOutOfRangeException( - nameof(month), Environment.GetResourceString("ArgumentOutOfRange_Range", + nameof(month), SR.Format(SR.ArgumentOutOfRange_Range, 1, 13)); } Contract.EndContractBlock(); @@ -1900,6 +1847,10 @@ namespace System.Globalization return newPatterns; } + // Needed by DateTimeFormatInfo and DateTimeFormat + internal const String RoundtripFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss.fffffffK"; + internal const String RoundtripDateTimeUnfixed = "yyyy'-'MM'-'ddTHH':'mm':'ss zzz"; + // Default string isn't necessarily in our string array, so get the // merged patterns of both private String[] AllYearMonthPatterns @@ -1951,8 +1902,8 @@ namespace System.Globalization if (allYearMonthPatterns == null) { Debug.Assert(Calendar.ID > 0, "[DateTimeFormatInfo.UnclonedYearMonthPatterns] Expected Calendar.ID > 0"); - allYearMonthPatterns = m_cultureData.YearMonths(this.Calendar.ID); - Debug.Assert(allYearMonthPatterns.Length > 0, + this.allYearMonthPatterns = _cultureData.YearMonths(this.Calendar.ID); + Debug.Assert(this.allYearMonthPatterns.Length > 0, "[DateTimeFormatInfo.UnclonedYearMonthPatterns] Expected some year month patterns"); } @@ -1970,7 +1921,7 @@ namespace System.Globalization if (allShortDatePatterns == null) { Debug.Assert(Calendar.ID > 0, "[DateTimeFormatInfo.UnclonedShortDatePatterns] Expected Calendar.ID > 0"); - this.allShortDatePatterns = m_cultureData.ShortDates(this.Calendar.ID); + this.allShortDatePatterns = _cultureData.ShortDates(this.Calendar.ID); Debug.Assert(this.allShortDatePatterns.Length > 0, "[DateTimeFormatInfo.UnclonedShortDatePatterns] Expected some short date patterns"); } @@ -1988,7 +1939,7 @@ namespace System.Globalization if (allLongDatePatterns == null) { Debug.Assert(Calendar.ID > 0, "[DateTimeFormatInfo.UnclonedLongDatePatterns] Expected Calendar.ID > 0"); - this.allLongDatePatterns = m_cultureData.LongDates(this.Calendar.ID); + this.allLongDatePatterns = _cultureData.LongDates(this.Calendar.ID); Debug.Assert(this.allLongDatePatterns.Length > 0, "[DateTimeFormatInfo.UnclonedLongDatePatterns] Expected some long date patterns"); } @@ -2005,7 +1956,7 @@ namespace System.Globalization { if (this.allShortTimePatterns == null) { - this.allShortTimePatterns = m_cultureData.ShortTimes; + this.allShortTimePatterns = _cultureData.ShortTimes; Debug.Assert(this.allShortTimePatterns.Length > 0, "[DateTimeFormatInfo.UnclonedShortTimePatterns] Expected some short time patterns"); } @@ -2022,7 +1973,7 @@ namespace System.Globalization { if (this.allLongTimePatterns == null) { - this.allLongTimePatterns = m_cultureData.LongTimes; + this.allLongTimePatterns = _cultureData.LongTimes; Debug.Assert(this.allLongTimePatterns.Length > 0, "[DateTimeFormatInfo.UnclonedLongTimePatterns] Expected some long time patterns"); } @@ -2036,7 +1987,7 @@ namespace System.Globalization if (dtfi == null) { throw new ArgumentNullException(nameof(dtfi), - Environment.GetResourceString("ArgumentNull_Obj")); + SR.ArgumentNull_Obj); } Contract.EndContractBlock(); if (dtfi.IsReadOnly) @@ -2047,16 +1998,15 @@ namespace System.Globalization // We can use the data member calendar in the setter, instead of the property Calendar, // since the cloned copy should have the same state as the original copy. newInfo.calendar = Calendar.ReadOnly(dtfi.Calendar); - newInfo.m_isReadOnly = true; + newInfo._isReadOnly = true; return (newInfo); } - public bool IsReadOnly { get { - return (m_isReadOnly); + return (_isReadOnly); } } @@ -2066,11 +2016,11 @@ namespace System.Globalization // String nativeName = dtfi.NativeCalendarName; // Get the Japanese name for the Japanese calendar. // DateTimeFormatInfo dtfi = new CultureInfo("ja-JP", false).DateTimeFormat.Calendar = new GregorianCalendar(GregorianCalendarTypes.Localized); // String nativeName = dtfi.NativeCalendarName; // Get the Japanese name for the Gregorian calendar. - public String NativeCalendarName + public string NativeCalendarName { get { - return m_cultureData.CalendarName(Calendar.ID); + return _cultureData.CalendarName(Calendar.ID); } } @@ -2091,28 +2041,28 @@ namespace System.Globalization // // WARNING: If more validation is ever done in one place, it should be done in the other. // - public void SetAllDateTimePatterns(String[] patterns, char format) { if (IsReadOnly) - throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly")); + throw new InvalidOperationException(SR.InvalidOperation_ReadOnly); + if (patterns == null) { - throw new ArgumentNullException(nameof(patterns), - Environment.GetResourceString("ArgumentNull_Array")); + throw new ArgumentNullException(nameof(patterns), SR.ArgumentNull_Array); } if (patterns.Length == 0) { - throw new ArgumentException(Environment.GetResourceString("Arg_ArrayZeroError"), nameof(patterns)); + throw new ArgumentException(SR.Arg_ArrayZeroError, nameof(patterns)); } + Contract.EndContractBlock(); for (int i = 0; i < patterns.Length; i++) { if (patterns[i] == null) { - throw new ArgumentNullException("patterns[" + i + "]", Environment.GetResourceString("ArgumentNull_ArrayValue")); + throw new ArgumentNullException("patterns[" + i + "]", SR.ArgumentNull_ArrayValue); } } @@ -2120,39 +2070,37 @@ namespace System.Globalization switch (format) { case 'd': - this.allShortDatePatterns = patterns; - this.shortDatePattern = this.allShortDatePatterns[0]; + allShortDatePatterns = patterns; + shortDatePattern = allShortDatePatterns[0]; break; case 'D': - this.allLongDatePatterns = patterns; - this.longDatePattern = this.allLongDatePatterns[0]; + allLongDatePatterns = patterns; + longDatePattern = allLongDatePatterns[0]; break; case 't': - this.allShortTimePatterns = patterns; - this.shortTimePattern = this.allShortTimePatterns[0]; + allShortTimePatterns = patterns; + shortTimePattern = allShortTimePatterns[0]; break; case 'T': - this.allLongTimePatterns = patterns; - this.longTimePattern = this.allLongTimePatterns[0]; + allLongTimePatterns = patterns; + longTimePattern = allLongTimePatterns[0]; break; case 'y': case 'Y': allYearMonthPatterns = patterns; - this.yearMonthPattern = allYearMonthPatterns[0]; + yearMonthPattern = allYearMonthPatterns[0]; break; default: - throw new ArgumentException(Environment.GetResourceString("Format_BadFormatSpecifier"), nameof(format)); + throw new ArgumentException(SR.Format_BadFormatSpecifier, nameof(format)); } // Clear the token hash table, note that even short dates could require this ClearTokenHashTable(); - - return; } public String[] AbbreviatedMonthGenitiveNames @@ -2165,15 +2113,15 @@ namespace System.Globalization set { if (IsReadOnly) - throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly")); + throw new InvalidOperationException(SR.InvalidOperation_ReadOnly); if (value == null) { throw new ArgumentNullException(nameof(value), - Environment.GetResourceString("ArgumentNull_Array")); + SR.ArgumentNull_Array); } if (value.Length != 13) { - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidArrayLength", 13), nameof(value)); + throw new ArgumentException(SR.Format(SR.Argument_InvalidArrayLength, 13), nameof(value)); } Contract.EndContractBlock(); CheckNullValue(value, value.Length - 1); @@ -2192,15 +2140,15 @@ namespace System.Globalization set { if (IsReadOnly) - throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly")); + throw new InvalidOperationException(SR.InvalidOperation_ReadOnly); if (value == null) { throw new ArgumentNullException(nameof(value), - Environment.GetResourceString("ArgumentNull_Array")); + SR.ArgumentNull_Array); } if (value.Length != 13) { - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidArrayLength", 13), nameof(value)); + throw new ArgumentException(SR.Format(SR.Argument_InvalidArrayLength, 13), nameof(value)); } Contract.EndContractBlock(); CheckNullValue(value, value.Length - 1); @@ -2213,23 +2161,23 @@ namespace System.Globalization // Positive TimeSpan Pattern // [NonSerialized] - private string m_fullTimeSpanPositivePattern; + private string _fullTimeSpanPositivePattern; internal String FullTimeSpanPositivePattern { get { - if (m_fullTimeSpanPositivePattern == null) + if (_fullTimeSpanPositivePattern == null) { CultureData cultureDataWithoutUserOverrides; - if (m_cultureData.UseUserOverride) - cultureDataWithoutUserOverrides = CultureData.GetCultureData(m_cultureData.CultureName, false); + if (_cultureData.UseUserOverride) + cultureDataWithoutUserOverrides = CultureData.GetCultureData(_cultureData.CultureName, false); else - cultureDataWithoutUserOverrides = m_cultureData; + cultureDataWithoutUserOverrides = _cultureData; String decimalSeparator = new NumberFormatInfo(cultureDataWithoutUserOverrides).NumberDecimalSeparator; - m_fullTimeSpanPositivePattern = "d':'h':'mm':'ss'" + decimalSeparator + "'FFFFFFF"; + _fullTimeSpanPositivePattern = "d':'h':'mm':'ss'" + decimalSeparator + "'FFFFFFF"; } - return m_fullTimeSpanPositivePattern; + return _fullTimeSpanPositivePattern; } } @@ -2237,14 +2185,14 @@ namespace System.Globalization // Negative TimeSpan Pattern // [NonSerialized] - private string m_fullTimeSpanNegativePattern; + private string _fullTimeSpanNegativePattern; internal String FullTimeSpanNegativePattern { get { - if (m_fullTimeSpanNegativePattern == null) - m_fullTimeSpanNegativePattern = "'-'" + FullTimeSpanPositivePattern; - return m_fullTimeSpanNegativePattern; + if (_fullTimeSpanNegativePattern == null) + _fullTimeSpanNegativePattern = "'-'" + FullTimeSpanPositivePattern; + return _fullTimeSpanNegativePattern; } } @@ -2255,14 +2203,14 @@ namespace System.Globalization { get { - if (m_compareInfo == null) + if (_compareInfo == null) { // We use the regular GetCompareInfo here to make sure the created CompareInfo object is stored in the - // CompareInfo cache. otherwise we would just create CompareInfo using m_cultureData. - m_compareInfo = CompareInfo.GetCompareInfo(m_cultureData.SCOMPAREINFO); + // CompareInfo cache. otherwise we would just create CompareInfo using _cultureData. + _compareInfo = CompareInfo.GetCompareInfo(_cultureData.SCOMPAREINFO); } - return m_compareInfo; + return _compareInfo; } } @@ -2276,17 +2224,17 @@ namespace System.Globalization { if ((style & InvalidDateTimeStyles) != 0) { - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidDateTimeStyles"), parameterName); + throw new ArgumentException(SR.Argument_InvalidDateTimeStyles, parameterName); } if (((style & (DateTimeStyles.AssumeLocal)) != 0) && ((style & (DateTimeStyles.AssumeUniversal)) != 0)) { - throw new ArgumentException(Environment.GetResourceString("Argument_ConflictingDateTimeStyles"), parameterName); + throw new ArgumentException(SR.Argument_ConflictingDateTimeStyles, parameterName); } Contract.EndContractBlock(); if (((style & DateTimeStyles.RoundtripKind) != 0) && ((style & (DateTimeStyles.AssumeLocal | DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal)) != 0)) { - throw new ArgumentException(Environment.GetResourceString("Argument_ConflictingDateTimeRoundtripStyles"), parameterName); + throw new ArgumentException(SR.Argument_ConflictingDateTimeRoundtripStyles, parameterName); } } @@ -2319,6 +2267,7 @@ namespace System.Globalization { switch (calendar.ID) { + // Handle Japanese and Taiwan cases. // If is y/yy, do not get (year % 100). "y" will print // year without leading zero. "yy" will print year with two-digit in leading zero. // If pattern is yyy/yyyy/..., print year value with two-digit in leading zero. @@ -2326,8 +2275,8 @@ namespace System.Globalization // The reason for not doing (year % 100) is for Taiwan calendar. // If year 125, then output 125 and not 25. // Note: OS uses "yyyy" for Taiwan calendar by default. - case (Calendar.CAL_JAPAN): - case (Calendar.CAL_TAIWAN): + case (CalendarId.JAPAN): + case (CalendarId.TAIWAN): return true; } return false; @@ -2392,7 +2341,7 @@ namespace System.Globalization // DateTimeFormatInfo tokenizer. This is used by DateTime.Parse() to break input string into tokens. // [NonSerialized] - private TokenHashValue[] m_dtfiTokenHash; + private TokenHashValue[] _dtfiTokenHash; private const int TOKEN_HASH_SIZE = 199; private const int SECOND_PRIME = 197; @@ -2429,6 +2378,9 @@ namespace System.Globalization internal const String LocalTimeMark = "T"; + internal const String GMTName = "GMT"; + internal const String ZuluName = "Z"; + internal const String KoreanLangName = "ko"; internal const String JapaneseLangName = "ja"; internal const String EnglishLangName = "en"; @@ -2453,6 +2405,11 @@ namespace System.Globalization } return (temp); } + + // Create a Taiwan DTFI which uses TaiwanCalendar. This is used to parse + // date string with era name correctly even when the supplied DTFI + // does not use Taiwan calendar. + // The created instance is stored in global s_zhtwDTFI. internal static DateTimeFormatInfo GetTaiwanCalendarDTFI() { DateTimeFormatInfo temp = s_zhtwDTFI; @@ -2469,13 +2426,13 @@ namespace System.Globalization // DTFI properties should call this when the setter are called. private void ClearTokenHashTable() { - m_dtfiTokenHash = null; + _dtfiTokenHash = null; formatFlags = DateTimeFormatFlags.NotInitialized; } internal TokenHashValue[] CreateTokenHashTable() { - TokenHashValue[] temp = m_dtfiTokenHash; + TokenHashValue[] temp = _dtfiTokenHash; if (temp == null) { temp = new TokenHashValue[TOKEN_HASH_SIZE]; @@ -2500,6 +2457,7 @@ namespace System.Globalization InsertHash(temp, this.AMDesignator, TokenType.SEP_Am | TokenType.Am, 0); InsertHash(temp, this.PMDesignator, TokenType.SEP_Pm | TokenType.Pm, 1); + // TODO: This ignores similar custom cultures if (LanguageName.Equals("sq")) { // Albanian allows time formats like "12:00.PD" @@ -2520,6 +2478,7 @@ namespace System.Globalization InsertHash(temp, CJKMinuteSuff, TokenType.SEP_MinuteSuff, 0); InsertHash(temp, CJKSecondSuff, TokenType.SEP_SecondSuff, 0); + // TODO: This ignores other custom cultures that might want to do something similar if (koreanLanguage) { // Korean suffix @@ -2543,8 +2502,6 @@ namespace System.Globalization // We need to rescan the date words since we're always synthetic scanner = new DateTimeFormatInfoScanner(); - // Enumarate all LongDatePatterns, and get the DateWords and scan for month postfix. - // The only reason they're being assigned to m_dateWords is for Whidbey Deserialization m_dateWords = dateWords = scanner.GetDateWordsOfDTFI(this); // Ensure the formatflags is initialized. DateTimeFormatFlags flag = FormatFlags; @@ -2573,14 +2530,15 @@ namespace System.Globalization case DateTimeFormatInfoScanner.IgnorableSymbolChar: String symbol = dateWords[i].Substring(1); InsertHash(temp, symbol, TokenType.IgnorableSymbol, 0); - if (this.DateSeparator.Trim().Equals(symbol)) + if (this.DateSeparator.Trim(null).Equals(symbol)) { - // The date separator is the same as the ingorable symbol. + // The date separator is the same as the ignorable symbol. useDateSepAsIgnorableSymbol = true; } break; default: InsertHash(temp, dateWords[i], TokenType.DateWordToken, 0); + // TODO: This ignores similar custom cultures if (LanguageName.Equals("eu")) { // Basque has date words with leading dots @@ -2644,6 +2602,7 @@ namespace System.Globalization InsertHash(temp, GetAbbreviatedEraName(i), TokenType.EraToken, i); } + // TODO: This ignores other cultures that might want to do something similar if (LanguageName.Equals(JapaneseLangName)) { // Japanese allows day of week forms like: "(Tue)" @@ -2666,6 +2625,7 @@ namespace System.Globalization } } } + // TODO: This prohibits similar custom cultures, but we hard coded the name else if (CultureName.Equals("zh-TW")) { DateTimeFormatInfo twDtfi = GetTaiwanCalendarDTFI(); @@ -2711,13 +2671,13 @@ namespace System.Globalization } InsertHash(temp, LocalTimeMark, TokenType.SEP_LocalTimeMark, 0); - InsertHash(temp, DateTimeParse.GMTName, TokenType.TimeZoneToken, 0); - InsertHash(temp, DateTimeParse.ZuluName, TokenType.TimeZoneToken, 0); + InsertHash(temp, GMTName, TokenType.TimeZoneToken, 0); + InsertHash(temp, ZuluName, TokenType.TimeZoneToken, 0); InsertHash(temp, invariantDateSeparator, TokenType.SEP_Date, 0); InsertHash(temp, invariantTimeSeparator, TokenType.SEP_Time, 0); - m_dtfiTokenHash = temp; + _dtfiTokenHash = temp; } return (temp); } @@ -2763,7 +2723,11 @@ namespace System.Globalization //////////////////////////////////////////////////////////////////////// private static bool TryParseHebrewNumber( +#if CORECLR ref __DTString str, +#else + ref FormatProvider.__DTString str, +#endif out Boolean badFormat, out int number) { @@ -2817,7 +2781,12 @@ namespace System.Globalization return (ch >= '\x0590' && ch <= '\x05ff'); } - internal bool Tokenize(TokenType TokenMask, out TokenType tokenType, out int tokenValue, ref __DTString str) + internal bool Tokenize(TokenType TokenMask, out TokenType tokenType, out int tokenValue, +#if CORECLR + ref __DTString str) +#else + ref FormatProvider.__DTString str) +#endif { tokenType = TokenType.UnknownToken; tokenValue = 0; @@ -2829,7 +2798,7 @@ namespace System.Globalization bool isLetter = Char.IsLetter(ch); if (isLetter) { - ch = Char.ToLower(ch, this.Culture); + ch = this.Culture.TextInfo.ToLower(ch); if (IsHebrewChar(ch) && TokenMask == TokenType.RegularTokenMask) { bool badFormat; @@ -2854,7 +2823,7 @@ namespace System.Globalization int remaining = str.len - str.Index; int i = 0; - TokenHashValue[] hashTable = m_dtfiTokenHash; + TokenHashValue[] hashTable = _dtfiTokenHash; if (hashTable == null) { hashTable = CreateTokenHashTable(); @@ -2870,42 +2839,34 @@ namespace System.Globalization // Check this value has the right category (regular token or separator token) that we are looking for. if (((int)value.tokenType & (int)TokenMask) > 0 && value.tokenString.Length <= remaining) { - if (String.Compare(str.Value, str.Index, value.tokenString, 0, value.tokenString.Length, this.Culture, CompareOptions.IgnoreCase) == 0) + bool compareStrings = true; + if (isLetter) { - if (isLetter) + // If this token starts with a letter, make sure that we won't allow partial match. So you can't tokenize "MarchWed" separately. + // Also an optimization to avoid string comparison + int nextCharIndex = str.Index + value.tokenString.Length; + if (nextCharIndex > str.len) { - // If this token starts with a letter, make sure that we won't allow partial match. So you can't tokenize "MarchWed" separately. - int nextCharIndex; - if ((nextCharIndex = str.Index + value.tokenString.Length) < str.len) - { - // Check word boundary. The next character should NOT be a letter. - char nextCh = str.Value[nextCharIndex]; - if (Char.IsLetter(nextCh)) - { - return (false); - } - } + compareStrings = false; } + else if (nextCharIndex < str.len) + { + // Check word boundary. The next character should NOT be a letter. + char nextCh = str.Value[nextCharIndex]; + compareStrings = !(Char.IsLetter(nextCh)); + } + } + if (compareStrings && CompareStringIgnoreCaseOptimized(str.Value, str.Index, value.tokenString.Length, value.tokenString, 0, value.tokenString.Length)) + { tokenType = value.tokenType & TokenMask; tokenValue = value.tokenValue; str.Advance(value.tokenString.Length); return (true); } - else if (value.tokenType == TokenType.MonthToken && HasSpacesInMonthNames) - { - // For month token, we will match the month names which have spaces. - int matchStrLen = 0; - if (str.MatchSpecifiedWords(value.tokenString, true, ref matchStrLen)) - { - tokenType = value.tokenType & TokenMask; - tokenValue = value.tokenValue; - str.Advance(matchStrLen); - return (true); - } - } - else if (value.tokenType == TokenType.DayOfWeekToken && HasSpacesInDayNames) + else if ((value.tokenType == TokenType.MonthToken && HasSpacesInMonthNames) || + (value.tokenType == TokenType.DayOfWeekToken && HasSpacesInDayNames)) { - // For month token, we will match the month names which have spaces. + // For month or day token, we will match the names which have spaces. int matchStrLen = 0; if (str.MatchSpecifiedWords(value.tokenString, true, ref matchStrLen)) { @@ -2940,7 +2901,7 @@ namespace System.Globalization // Remember this slot TokenHashValue temp = hashTable[hashcode]; - if (temp != null && Char.ToLower(temp.tokenString[0], this.Culture) != ch) + if (temp != null && this.Culture.TextInfo.ToLower(temp.tokenString[0]) != ch) { continue; } @@ -2970,12 +2931,12 @@ namespace System.Globalization // DateTime.Parse(). if (Char.IsWhiteSpace(str[0]) || Char.IsWhiteSpace(str[str.Length - 1])) { - str = str.Trim(); // Trim white space characters. + str = str.Trim(null); // Trim white space characters. // Could have space for separators if (str.Length == 0) return; } - char ch = Char.ToLower(str[0], this.Culture); + char ch = this.Culture.TextInfo.ToLower(str[0]); int hashcode = ch % TOKEN_HASH_SIZE; int hashProbe = 1 + ch % SECOND_PRIME; do @@ -2994,7 +2955,7 @@ namespace System.Globalization { // If there are two tokens with the same prefix, we have to make sure that the longer token should be at the front of // the shorter ones. - if (String.Compare(str, 0, value.tokenString, 0, value.tokenString.Length, this.Culture, CompareOptions.IgnoreCase) == 0) + if (this.CompareStringIgnoreCaseOptimized(str, 0, value.tokenString.Length, value.tokenString, 0, value.tokenString.Length)) { if (str.Length > value.tokenString.Length) { @@ -3018,8 +2979,12 @@ namespace System.Globalization int nTokenType = (int)tokenType; int nCurrentTokenTypeInHash = (int)value.tokenType; + // + // The folowing is the fix for the issue of throwing FormatException when "mar" is passed in string of the short date format dd/MMM/yyyy for es-MX + // + if (((nCurrentTokenTypeInHash & (int)TokenType.RegularTokenMask) == 0) && ((nTokenType & (int)TokenType.RegularTokenMask) != 0) || - ((nCurrentTokenTypeInHash & (int)TokenType.SeparatorTokenMask) == 0) && ((nTokenType & (int)TokenType.SeparatorTokenMask) != 0)) + ((nCurrentTokenTypeInHash & (int)TokenType.SeparatorTokenMask) == 0) && ((nTokenType & (int)TokenType.SeparatorTokenMask) != 0)) { value.tokenType |= tokenType; if (tokenValue != 0) @@ -3028,6 +2993,7 @@ namespace System.Globalization } } // The token to be inserted is already in the table. Skip it. + return; } } } @@ -3039,19 +3005,81 @@ namespace System.Globalization } while (i < TOKEN_HASH_SIZE); Debug.Assert(false, "The hashtable is full. This should not happen."); } - } // class DateTimeFormatInfo - internal class TokenHashValue - { - internal String tokenString; - internal TokenType tokenType; - internal int tokenValue; + private bool CompareStringIgnoreCaseOptimized(string string1, int offset1, int length1, string string2, int offset2, int length2) + { + // Optimize for one character cases which are common due to date and time separators (/ and :) + if (length1 == 1 && length2 == 1 && string1[offset1] == string2[offset2]) + { + return true; + } + + return (this.Culture.CompareInfo.Compare(string1, offset1, length1, string2, offset2, length2, CompareOptions.IgnoreCase) == 0); + } + + // class DateTimeFormatInfo - internal TokenHashValue(String tokenString, TokenType tokenType, int tokenValue) + internal class TokenHashValue { - this.tokenString = tokenString; - this.tokenType = tokenType; - this.tokenValue = tokenValue; + internal String tokenString; + internal TokenType tokenType; + internal int tokenValue; + + internal TokenHashValue(String tokenString, TokenType tokenType, int tokenValue) + { + this.tokenString = tokenString; + this.tokenType = tokenType; + this.tokenValue = tokenValue; + } } } + +#if !CORECLR + // + // The type of token that will be returned by DateTimeFormatInfo.Tokenize(). + // + internal enum TokenType + { + // The valid token should start from 1. + + // Regular tokens. The range is from 0x00 ~ 0xff. + NumberToken = 1, // The number. E.g. "12" + YearNumberToken = 2, // The number which is considered as year number, which has 3 or more digits. E.g. "2003" + Am = 3, // AM timemark. E.g. "AM" + Pm = 4, // PM timemark. E.g. "PM" + MonthToken = 5, // A word (or words) that represents a month name. E.g. "March" + EndOfString = 6, // End of string + DayOfWeekToken = 7, // A word (or words) that represents a day of week name. E.g. "Monday" or "Mon" + TimeZoneToken = 8, // A word that represents a timezone name. E.g. "GMT" + EraToken = 9, // A word that represents a era name. E.g. "A.D." + DateWordToken = 10, // A word that can appear in a DateTime string, but serves no parsing semantics. E.g. "de" in Spanish culture. + UnknownToken = 11, // An unknown word, which signals an error in parsing. + HebrewNumber = 12, // A number that is composed of Hebrew text. Hebrew calendar uses Hebrew digits for year values, month values, and day values. + JapaneseEraToken = 13, // Era name for JapaneseCalendar + TEraToken = 14, // Era name for TaiwanCalendar + IgnorableSymbol = 15, // A separator like "," that is equivalent to whitespace + + + // Separator tokens. + SEP_Unk = 0x100, // Unknown separator. + SEP_End = 0x200, // The end of the parsing string. + SEP_Space = 0x300, // Whitespace (including comma). + SEP_Am = 0x400, // AM timemark. E.g. "AM" + SEP_Pm = 0x500, // PM timemark. E.g. "PM" + SEP_Date = 0x600, // date separator. E.g. "/" + SEP_Time = 0x700, // time separator. E.g. ":" + SEP_YearSuff = 0x800, // Chinese/Japanese/Korean year suffix. + SEP_MonthSuff = 0x900, // Chinese/Japanese/Korean month suffix. + SEP_DaySuff = 0xa00, // Chinese/Japanese/Korean day suffix. + SEP_HourSuff = 0xb00, // Chinese/Japanese/Korean hour suffix. + SEP_MinuteSuff = 0xc00, // Chinese/Japanese/Korean minute suffix. + SEP_SecondSuff = 0xd00, // Chinese/Japanese/Korean second suffix. + SEP_LocalTimeMark = 0xe00, // 'T', used in ISO 8601 format. + SEP_DateOrOffset = 0xf00, // '-' which could be a date separator or start of a time zone offset + + RegularTokenMask = 0x00ff, + SeparatorTokenMask = 0xff00, + } +#endif + } diff --git a/src/mscorlib/src/System/Globalization/DateTimeFormatInfoScanner.cs b/src/mscorlib/src/System/Globalization/DateTimeFormatInfoScanner.cs index 630d345..ddf7d7e 100644 --- a/src/mscorlib/src/System/Globalization/DateTimeFormatInfoScanner.cs +++ b/src/mscorlib/src/System/Globalization/DateTimeFormatInfoScanner.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. + //////////////////////////////////////////////////////////////////////////// // // DateTimeFormatInfoScanner @@ -18,13 +19,22 @@ // //////////////////////////////////////////////////////////////////////////// +using System; +using System.Globalization; +using System.Collections; +using System.Collections.Generic; +using System.Text; + namespace System.Globalization { - using System; - using System.Globalization; - using System.Collections; - using System.Collections.Generic; - using System.Text; + +#if CORECLR + using StringStringDictionary = Dictionary; + using StringList = List; +#else + using StringStringDictionary = LowLevelDictionary; + using StringList = LowLevelList; +#endif // // from LocaleEx.txt header @@ -42,13 +52,9 @@ namespace System.Globalization UseDigitPrefixInTokens = 0x00000020, // Has token starting with numbers. } - // - // To change in CalendarId you have to do the same change in Calendar.cs - // To do: make the definintion shared between these two files. - // - internal enum CalendarId : ushort { + UNINITIALIZED_VALUE = 0, GREGORIAN = 1, // Gregorian (localized) calendar GREGORIAN_US = 2, // Gregorian (U.S.) calendar JAPAN = 3, // Japanese Emperor Era calendar @@ -119,17 +125,17 @@ namespace System.Globalization internal const String CJKSecondSuff = "\u79d2"; // The collection fo date words & postfix. - internal List m_dateWords = new List(); + internal StringList m_dateWords = new StringList(); // Hashtable for the known words. - private static volatile Dictionary s_knownWords; + private static volatile StringStringDictionary s_knownWords; - private static Dictionary KnownWords + static StringStringDictionary KnownWords { get { if (s_knownWords == null) { - Dictionary temp = new Dictionary(); + StringStringDictionary temp = new StringStringDictionary(); // Add known words into the hash table. // Skip these special symbols. @@ -232,7 +238,7 @@ namespace System.Globalization { if (m_dateWords == null) { - m_dateWords = new List(); + m_dateWords = new StringList(); } if (formatPostfix == "MMMM") { @@ -378,9 +384,9 @@ namespace System.Globalization if (m_dateWords == null) { // Create the date word array. - m_dateWords = new List(); + m_dateWords = new StringList(); } - // Add the ingorable symbol into the ArrayList. + // Add the ignorable symbol into the ArrayList. String temp = IgnorableSymbolChar + text; if (!m_dateWords.Contains(temp)) { @@ -402,7 +408,7 @@ namespace System.Globalization } // Check if we have found all of the year/month/day pattern. - private FoundDatePattern m_ymdFlags = FoundDatePattern.None; + private FoundDatePattern _ymdFlags = FoundDatePattern.None; //////////////////////////////////////////////////////////////////////////// @@ -430,7 +436,7 @@ namespace System.Globalization internal void ScanDateWord(String pattern) { // Check if we have found all of the year/month/day pattern. - m_ymdFlags = FoundDatePattern.None; + _ymdFlags = FoundDatePattern.None; int i = 0; while (i < pattern.Length) @@ -453,11 +459,11 @@ namespace System.Globalization i = AddDateWords(pattern, i + 1, "MMMM"); } } - m_ymdFlags |= FoundDatePattern.FoundMonthPatternFlag; + _ymdFlags |= FoundDatePattern.FoundMonthPatternFlag; break; case 'y': i = ScanRepeatChar(pattern, 'y', i, out chCount); - m_ymdFlags |= FoundDatePattern.FoundYearPatternFlag; + _ymdFlags |= FoundDatePattern.FoundYearPatternFlag; break; case 'd': i = ScanRepeatChar(pattern, 'd', i, out chCount); @@ -465,7 +471,7 @@ namespace System.Globalization { // Only count "d" & "dd". // ddd, dddd are day names. Do not count them. - m_ymdFlags |= FoundDatePattern.FoundDayPatternFlag; + _ymdFlags |= FoundDatePattern.FoundDayPatternFlag; } break; case '\\': @@ -474,21 +480,21 @@ namespace System.Globalization i += 2; break; case '.': - if (m_ymdFlags == FoundDatePattern.FoundYMDPatternFlag) + if (_ymdFlags == FoundDatePattern.FoundYMDPatternFlag) { // If we find a dot immediately after the we have seen all of the y, m, d pattern. // treat it as a ignroable symbol. Check for comments in AddIgnorableSymbols for // more details. AddIgnorableSymbols("."); - m_ymdFlags = FoundDatePattern.None; + _ymdFlags = FoundDatePattern.None; } i++; break; default: - if (m_ymdFlags == FoundDatePattern.FoundYMDPatternFlag && !Char.IsWhiteSpace(ch)) + if (_ymdFlags == FoundDatePattern.FoundYMDPatternFlag && !Char.IsWhiteSpace(ch)) { // We are not seeing "." after YMD. Clear the flag. - m_ymdFlags = FoundDatePattern.None; + _ymdFlags = FoundDatePattern.None; } // We are not in quote. Skip the current character. i++; @@ -557,18 +563,6 @@ namespace System.Globalization return (result); } -#if ADDITIONAL_DTFI_SCANNER_METHODS - //////////////////////////////////////////////////////////////////////////// - // - // Reset the date word ArrayList - // - //////////////////////////////////////////////////////////////////////////// - - internal void Reset() - { - m_dateWords.RemoveRange(0, m_dateWords.Count); - } -#endif //////////////////////////////////////////////////////////////////////////// // diff --git a/src/mscorlib/src/System/Globalization/DaylightTime.cs b/src/mscorlib/src/System/Globalization/DaylightTime.cs index 92c2437..f066e4b 100644 --- a/src/mscorlib/src/System/Globalization/DaylightTime.cs +++ b/src/mscorlib/src/System/Globalization/DaylightTime.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System.Runtime.InteropServices; +using System; namespace System.Globalization { @@ -10,9 +10,9 @@ namespace System.Globalization [Serializable] public class DaylightTime { - internal DateTime m_start; - internal DateTime m_end; - internal TimeSpan m_delta; + private readonly DateTime _start; + private readonly DateTime _end; + private readonly TimeSpan _delta; private DaylightTime() { @@ -20,37 +20,19 @@ namespace System.Globalization public DaylightTime(DateTime start, DateTime end, TimeSpan delta) { - m_start = start; - m_end = end; - m_delta = delta; + _start = start; + _end = end; + _delta = delta; } // The start date of a daylight saving period. - public DateTime Start - { - get - { - return m_start; - } - } + public DateTime Start => _start; // The end date of a daylight saving period. - public DateTime End - { - get - { - return m_end; - } - } + public DateTime End => _end; // Delta to stardard offset in ticks. - public TimeSpan Delta - { - get - { - return m_delta; - } - } + public TimeSpan Delta => _delta; } // Value type version of DaylightTime @@ -63,8 +45,8 @@ namespace System.Globalization Delta = delta; } - public DateTime Start { get; } - public DateTime End { get; } - public TimeSpan Delta { get; } + public readonly DateTime Start; + public readonly DateTime End; + public readonly TimeSpan Delta; } } diff --git a/src/mscorlib/src/System/Globalization/DigitShapes.cs b/src/mscorlib/src/System/Globalization/DigitShapes.cs index 7a30dd2..0e4dcc8 100644 --- a/src/mscorlib/src/System/Globalization/DigitShapes.cs +++ b/src/mscorlib/src/System/Globalization/DigitShapes.cs @@ -11,11 +11,8 @@ namespace System.Globalization [Serializable] public enum DigitShapes : int { - Context = 0x0000, // The shape depends on the previous text in the same output. - - None = 0x0001, // Gives full Unicode compatibility. - - NativeNational = 0x0002, // National shapes determined by LOCALE_SNATIVEDIGITS + Context = 0x0000, // The shape depends on the previous text in the same output. + None = 0x0001, // Gives full Unicode compatibility. + NativeNational = 0x0002 // National shapes } -} - +} \ No newline at end of file diff --git a/src/mscorlib/src/System/Globalization/EastAsianLunisolarCalendar.cs b/src/mscorlib/src/System/Globalization/EastAsianLunisolarCalendar.cs index 0d026fd..f82fad8 100644 --- a/src/mscorlib/src/System/Globalization/EastAsianLunisolarCalendar.cs +++ b/src/mscorlib/src/System/Globalization/EastAsianLunisolarCalendar.cs @@ -13,7 +13,6 @@ namespace System.Globalization // //////////////////////////////////////////////////////////////////////////// - [Serializable] public abstract class EastAsianLunisolarCalendar : Calendar { @@ -38,9 +37,6 @@ namespace System.Globalization internal const int DatePartMonth = 2; internal const int DatePartDay = 3; - // Return the type of the East Asian Lunisolar calendars. - // - public override CalendarAlgorithmType AlgorithmType { get @@ -72,7 +68,7 @@ namespace System.Globalization { throw new ArgumentOutOfRangeException( nameof(sexagenaryYear), - Environment.GetResourceString("ArgumentOutOfRange_Range", 1, 60)); + SR.Format(SR.ArgumentOutOfRange_Range, 1, 60)); } Contract.EndContractBlock(); @@ -89,7 +85,7 @@ namespace System.Globalization { throw new ArgumentOutOfRangeException( nameof(sexagenaryYear), - Environment.GetResourceString("ArgumentOutOfRange_Range", 1, 60)); + SR.Format(SR.ArgumentOutOfRange_Range, 1, 60)); } Contract.EndContractBlock(); @@ -135,7 +131,7 @@ namespace System.Globalization return (mEraInfo[i].minEraYear); } } - throw new ArgumentOutOfRangeException(nameof(era), Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue")); + throw new ArgumentOutOfRangeException(nameof(era), SR.ArgumentOutOfRange_InvalidEraValue); } internal int MaxEraCalendarYear(int era) @@ -164,11 +160,9 @@ namespace System.Globalization return (mEraInfo[i].maxEraYear); } } - throw new ArgumentOutOfRangeException(nameof(era), Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue")); + throw new ArgumentOutOfRangeException(nameof(era), SR.ArgumentOutOfRange_InvalidEraValue); } - // Construct an instance of EastAsianLunisolar calendar. - internal EastAsianLunisolarCalendar() { } @@ -179,7 +173,7 @@ namespace System.Globalization { throw new ArgumentOutOfRangeException( "time", - String.Format(CultureInfo.InvariantCulture, Environment.GetResourceString("ArgumentOutOfRange_CalendarRange"), + String.Format(CultureInfo.InvariantCulture, SR.ArgumentOutOfRange_CalendarRange, MinSupportedDateTime, MaxSupportedDateTime)); } Contract.EndContractBlock(); @@ -194,7 +188,7 @@ namespace System.Globalization if ((era < GetEra(MinDate)) || (era > GetEra(MaxDate))) { - throw new ArgumentOutOfRangeException(nameof(era), Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue")); + throw new ArgumentOutOfRangeException(nameof(era), SR.ArgumentOutOfRange_InvalidEraValue); } } @@ -207,7 +201,7 @@ namespace System.Globalization { throw new ArgumentOutOfRangeException( nameof(year), - Environment.GetResourceString("ArgumentOutOfRange_Range", MinEraCalendarYear(era), MaxEraCalendarYear(era))); + SR.Format(SR.ArgumentOutOfRange_Range, MinEraCalendarYear(era), MaxEraCalendarYear(era))); } return year; } @@ -220,12 +214,12 @@ namespace System.Globalization { //Reject if there is no leap month this year if (GetYearInfo(year, LeapMonth) == 0) - throw new ArgumentOutOfRangeException(nameof(month), Environment.GetResourceString("ArgumentOutOfRange_Month")); + throw new ArgumentOutOfRangeException(nameof(month), SR.ArgumentOutOfRange_Month); } if (month < 1 || month > 13) { - throw new ArgumentOutOfRangeException(nameof(month), Environment.GetResourceString("ArgumentOutOfRange_Month")); + throw new ArgumentOutOfRangeException(nameof(month), SR.ArgumentOutOfRange_Month); } return year; } @@ -269,10 +263,9 @@ namespace System.Globalization int daysInMonth = InternalGetDaysInMonth(year, month); if (day < 1 || day > daysInMonth) { - BCLDebug.Log("year = " + year + ", month = " + month + ", day = " + day); throw new ArgumentOutOfRangeException( nameof(day), - Environment.GetResourceString("ArgumentOutOfRange_Day", daysInMonth, month)); + SR.Format(SR.ArgumentOutOfRange_Day, daysInMonth, month)); } int gy = 0; int gm = 0; int gd = 0; @@ -283,7 +276,7 @@ namespace System.Globalization } else { - throw new ArgumentOutOfRangeException(null, Environment.GetResourceString("ArgumentOutOfRange_BadYearMonthDay")); + throw new ArgumentOutOfRangeException(null, SR.ArgumentOutOfRange_BadYearMonthDay); } } @@ -453,7 +446,7 @@ namespace System.Globalization { throw new ArgumentOutOfRangeException( nameof(months), - Environment.GetResourceString("ArgumentOutOfRange_Range", -120000, 120000)); + SR.Format(SR.ArgumentOutOfRange_Range, -120000, 120000)); } Contract.EndContractBlock(); @@ -633,7 +626,7 @@ namespace System.Globalization { throw new ArgumentOutOfRangeException( nameof(day), - Environment.GetResourceString("ArgumentOutOfRange_Day", daysInMonth, month)); + SR.Format(SR.ArgumentOutOfRange_Day, daysInMonth, month)); } int m = GetYearInfo(year, LeapMonth); return ((m != 0) && (month == (m + 1))); @@ -700,7 +693,7 @@ namespace System.Globalization { throw new ArgumentOutOfRangeException( nameof(value), - Environment.GetResourceString("ArgumentOutOfRange_Range", 99, MaxCalendarYear)); + SR.Format(SR.ArgumentOutOfRange_Range, 99, MaxCalendarYear)); } twoDigitYearMax = value; } @@ -712,7 +705,7 @@ namespace System.Globalization if (year < 0) { throw new ArgumentOutOfRangeException(nameof(year), - Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + SR.ArgumentOutOfRange_NeedNonNegNum); } Contract.EndContractBlock(); diff --git a/src/mscorlib/src/System/Globalization/GregorianCalendar.cs b/src/mscorlib/src/System/Globalization/GregorianCalendar.cs index d8a4db3..6dbf5b2 100644 --- a/src/mscorlib/src/System/Globalization/GregorianCalendar.cs +++ b/src/mscorlib/src/System/Globalization/GregorianCalendar.cs @@ -2,20 +2,11 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -// -// N.B.: -// A lot of this code is directly from DateTime.cs. If you update that class, -// update this one as well. -// However, we still need these duplicated code because we will add era support -// in this class. -// -// - -using System.Threading; using System; using System.Globalization; -using System.Runtime.Serialization; using System.Diagnostics.Contracts; +using System.Runtime.Serialization; +using System.Threading; namespace System.Globalization { @@ -24,6 +15,7 @@ namespace System.Globalization // 1 BeforeCurrentEra (BC) [Serializable] + public class GregorianCalendar : Calendar { /* @@ -58,8 +50,6 @@ namespace System.Globalization private static volatile Calendar s_defaultInstance; - - #region Serialization [OnDeserialized] private void OnDeserialized(StreamingContext ctx) { @@ -67,15 +57,9 @@ namespace System.Globalization m_type > GregorianCalendarTypes.TransliteratedFrench) { throw new SerializationException( - String.Format( - CultureInfo.CurrentCulture, - Environment.GetResourceString( - "Serialization_MemberOutOfRange"), - "type", - "GregorianCalendar")); + String.Format(CultureInfo.CurrentCulture, SR.Serialization_MemberOutOfRange, "type", "GregorianCalendar")); } } - #endregion Serialization public override DateTime MinSupportedDateTime { @@ -93,9 +77,6 @@ namespace System.Globalization } } - // Return the type of the Gregorian calendar. - // - public override CalendarAlgorithmType AlgorithmType { get @@ -135,7 +116,7 @@ namespace System.Globalization { throw new ArgumentOutOfRangeException( nameof(type), - Environment.GetResourceString("ArgumentOutOfRange_Range", + SR.Format(SR.ArgumentOutOfRange_Range, GregorianCalendarTypes.Localized, GregorianCalendarTypes.TransliteratedFrench)); } Contract.EndContractBlock(); @@ -165,12 +146,12 @@ namespace System.Globalization break; default: - throw new ArgumentOutOfRangeException(nameof(m_type), Environment.GetResourceString("ArgumentOutOfRange_Enum")); + throw new ArgumentOutOfRangeException("m_type", SR.ArgumentOutOfRange_Enum); } } } - internal override int ID + internal override CalendarId ID { get { @@ -178,7 +159,7 @@ namespace System.Globalization // we can support the Transliterated Gregorian calendar. // DateTimeFormatInfo will use this ID to get formatting information about // the calendar. - return ((int)m_type); + return ((CalendarId)m_type); } } @@ -264,7 +245,7 @@ namespace System.Globalization return (absoluteDate); } } - throw new ArgumentOutOfRangeException(null, Environment.GetResourceString("ArgumentOutOfRange_BadYearMonthDay")); + throw new ArgumentOutOfRangeException(null, SR.ArgumentOutOfRange_BadYearMonthDay); } // Returns the tick count corresponding to the given year, month, and day. @@ -300,7 +281,7 @@ namespace System.Globalization nameof(months), String.Format( CultureInfo.CurrentCulture, - Environment.GetResourceString("ArgumentOutOfRange_Range"), + SR.ArgumentOutOfRange_Range, -120000, 120000)); } @@ -386,17 +367,17 @@ namespace System.Globalization { if (year < 1 || year > MaxYear) { - throw new ArgumentOutOfRangeException(nameof(year), Environment.GetResourceString("ArgumentOutOfRange_Range", + throw new ArgumentOutOfRangeException(nameof(year), SR.Format(SR.ArgumentOutOfRange_Range, 1, MaxYear)); } if (month < 1 || month > 12) { - throw new ArgumentOutOfRangeException(nameof(month), Environment.GetResourceString("ArgumentOutOfRange_Month")); + throw new ArgumentOutOfRangeException(nameof(month), SR.ArgumentOutOfRange_Month); } int[] days = ((year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) ? DaysToMonth366 : DaysToMonth365); return (days[month] - days[month - 1]); } - throw new ArgumentOutOfRangeException(nameof(era), Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue")); + throw new ArgumentOutOfRangeException(nameof(era), SR.ArgumentOutOfRange_InvalidEraValue); } // Returns the number of days in the year given by the year argument for the current era. @@ -414,11 +395,11 @@ namespace System.Globalization nameof(year), String.Format( CultureInfo.CurrentCulture, - Environment.GetResourceString("ArgumentOutOfRange_Range"), + SR.ArgumentOutOfRange_Range, 1, MaxYear)); } - throw new ArgumentOutOfRangeException(nameof(era), Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue")); + throw new ArgumentOutOfRangeException(nameof(era), SR.ArgumentOutOfRange_InvalidEraValue); } // Returns the era for the specified DateTime value. @@ -461,11 +442,11 @@ namespace System.Globalization nameof(year), String.Format( CultureInfo.CurrentCulture, - Environment.GetResourceString("ArgumentOutOfRange_Range"), + SR.ArgumentOutOfRange_Range, 1, MaxYear)); } - throw new ArgumentOutOfRangeException(nameof(era), Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue")); + throw new ArgumentOutOfRangeException(nameof(era), SR.ArgumentOutOfRange_InvalidEraValue); } // Returns the year part of the specified DateTime. The returned value is an @@ -485,25 +466,25 @@ namespace System.Globalization { if (month < 1 || month > 12) { - throw new ArgumentOutOfRangeException(nameof(month), Environment.GetResourceString("ArgumentOutOfRange_Range", + throw new ArgumentOutOfRangeException(nameof(month), SR.Format(SR.ArgumentOutOfRange_Range, 1, 12)); } Contract.EndContractBlock(); if (era != CurrentEra && era != ADEra) { - throw new ArgumentOutOfRangeException(nameof(era), Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue")); + throw new ArgumentOutOfRangeException(nameof(era), SR.ArgumentOutOfRange_InvalidEraValue); } if (year < 1 || year > MaxYear) { throw new ArgumentOutOfRangeException( nameof(year), - Environment.GetResourceString("ArgumentOutOfRange_Range", 1, MaxYear)); + SR.Format(SR.ArgumentOutOfRange_Range, 1, MaxYear)); } if (day < 1 || day > GetDaysInMonth(year, month)) { - throw new ArgumentOutOfRangeException(nameof(day), Environment.GetResourceString("ArgumentOutOfRange_Range", + throw new ArgumentOutOfRangeException(nameof(day), SR.Format(SR.ArgumentOutOfRange_Range, 1, GetDaysInMonth(year, month))); } if (!IsLeapYear(year)) @@ -525,7 +506,7 @@ namespace System.Globalization { if (era != CurrentEra && era != ADEra) { - throw new ArgumentOutOfRangeException(nameof(era), Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue")); + throw new ArgumentOutOfRangeException(nameof(era), SR.ArgumentOutOfRange_InvalidEraValue); } if (year < 1 || year > MaxYear) { @@ -533,7 +514,7 @@ namespace System.Globalization nameof(year), String.Format( CultureInfo.CurrentCulture, - Environment.GetResourceString("ArgumentOutOfRange_Range"), 1, MaxYear)); + SR.ArgumentOutOfRange_Range, 1, MaxYear)); } Contract.EndContractBlock(); return (0); @@ -547,7 +528,7 @@ namespace System.Globalization { if (era != CurrentEra && era != ADEra) { - throw new ArgumentOutOfRangeException(nameof(era), Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue")); + throw new ArgumentOutOfRangeException(nameof(era), SR.ArgumentOutOfRange_InvalidEraValue); } if (year < 1 || year > MaxYear) @@ -556,12 +537,12 @@ namespace System.Globalization nameof(year), String.Format( CultureInfo.CurrentCulture, - Environment.GetResourceString("ArgumentOutOfRange_Range"), 1, MaxYear)); + SR.ArgumentOutOfRange_Range, 1, MaxYear)); } if (month < 1 || month > 12) { - throw new ArgumentOutOfRangeException(nameof(month), Environment.GetResourceString("ArgumentOutOfRange_Range", + throw new ArgumentOutOfRangeException(nameof(month), SR.Format(SR.ArgumentOutOfRange_Range, 1, 12)); } Contract.EndContractBlock(); @@ -585,9 +566,9 @@ namespace System.Globalization nameof(year), String.Format( CultureInfo.CurrentCulture, - Environment.GetResourceString("ArgumentOutOfRange_Range"), 1, MaxYear)); + SR.ArgumentOutOfRange_Range, 1, MaxYear)); } - throw new ArgumentOutOfRangeException(nameof(era), Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue")); + throw new ArgumentOutOfRangeException(nameof(era), SR.ArgumentOutOfRange_InvalidEraValue); } // Returns the date and time converted to a DateTime value. Throws an exception if the n-tuple is invalid. @@ -599,14 +580,28 @@ namespace System.Globalization { return new DateTime(year, month, day, hour, minute, second, millisecond); } - throw new ArgumentOutOfRangeException(nameof(era), Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue")); + throw new ArgumentOutOfRangeException(nameof(era), SR.ArgumentOutOfRange_InvalidEraValue); } internal override Boolean TryToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era, out DateTime result) { if (era == CurrentEra || era == ADEra) { - return DateTime.TryCreate(year, month, day, hour, minute, second, millisecond, out result); + try + { + result = new DateTime(year, month, day, hour, minute, second, millisecond); + return true; + } + catch (ArgumentOutOfRangeException) + { + result = DateTime.Now; + return false; + } + catch (ArgumentException) + { + result = DateTime.Now; + return false; + } } result = DateTime.MinValue; return false; @@ -635,7 +630,7 @@ namespace System.Globalization "year", String.Format( CultureInfo.CurrentCulture, - Environment.GetResourceString("ArgumentOutOfRange_Range"), + SR.ArgumentOutOfRange_Range, 99, MaxYear)); } @@ -649,7 +644,7 @@ namespace System.Globalization if (year < 0) { throw new ArgumentOutOfRangeException(nameof(year), - Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + SR.ArgumentOutOfRange_NeedNonNegNum); } Contract.EndContractBlock(); @@ -659,7 +654,7 @@ namespace System.Globalization nameof(year), String.Format( CultureInfo.CurrentCulture, - Environment.GetResourceString("ArgumentOutOfRange_Range"), 1, MaxYear)); + SR.ArgumentOutOfRange_Range, 1, MaxYear)); } return (base.ToFourDigitYear(year)); } diff --git a/src/mscorlib/src/System/Globalization/GregorianCalendarHelper.cs b/src/mscorlib/src/System/Globalization/GregorianCalendarHelper.cs index 3536733..ee8ba13 100644 --- a/src/mscorlib/src/System/Globalization/GregorianCalendarHelper.cs +++ b/src/mscorlib/src/System/Globalization/GregorianCalendarHelper.cs @@ -2,17 +2,14 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. - using System; +using System.Diagnostics.Contracts; using System.Runtime.Serialization; using System.Threading; -using System.Diagnostics.Contracts; namespace System.Globalization { // Gregorian Calendars use Era Info - // Note: We shouldn't have to serialize this since the info doesn't change, but we have been. - // (We really only need the calendar #, and maybe culture) [Serializable] internal class EraInfo { @@ -116,32 +113,23 @@ namespace System.Globalization 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }; - // Strictly these don't need serialized since they can be recreated from the calendar id [OptionalField(VersionAdded = 1)] internal int m_maxYear = 9999; [OptionalField(VersionAdded = 1)] internal int m_minYear; internal Calendar m_Cal; - // Era information doesn't need serialized, its constant for the same calendars (ie: we can recreate it from the calendar id) [OptionalField(VersionAdded = 1)] internal EraInfo[] m_EraInfo; [OptionalField(VersionAdded = 1)] internal int[] m_eras = null; - // m_minDate is existing here just to keep the serialization compatibility. - // it has nothing to do with the code anymore. - [OptionalField(VersionAdded = 1)] - internal DateTime m_minDate; // Construct an instance of gregorian calendar. internal GregorianCalendarHelper(Calendar cal, EraInfo[] eraInfo) { m_Cal = cal; m_EraInfo = eraInfo; - // m_minDate is existing here just to keep the serialization compatibility. - // it has nothing to do with the code anymore. - m_minDate = m_Cal.MinSupportedDateTime; m_maxYear = m_EraInfo[0].maxEraYear; m_minYear = m_EraInfo[0].minEraYear; ; } @@ -161,7 +149,7 @@ namespace System.Globalization if (year < 0) { throw new ArgumentOutOfRangeException(nameof(year), - Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + SR.ArgumentOutOfRange_NeedNonNegNum); } Contract.EndContractBlock(); @@ -180,14 +168,14 @@ namespace System.Globalization nameof(year), String.Format( CultureInfo.CurrentCulture, - Environment.GetResourceString("ArgumentOutOfRange_Range"), + SR.ArgumentOutOfRange_Range, m_EraInfo[i].minEraYear, m_EraInfo[i].maxEraYear)); } return (m_EraInfo[i].yearOffset + year); } } - throw new ArgumentOutOfRangeException(nameof(era), Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue")); + throw new ArgumentOutOfRangeException(nameof(era), SR.ArgumentOutOfRange_InvalidEraValue); } internal bool IsValidYear(int year, int era) @@ -299,7 +287,7 @@ namespace System.Globalization return (absoluteDate); } } - throw new ArgumentOutOfRangeException(null, Environment.GetResourceString("ArgumentOutOfRange_BadYearMonthDay")); + throw new ArgumentOutOfRangeException(null, SR.ArgumentOutOfRange_BadYearMonthDay); } // Returns the tick count corresponding to the given year, month, and day. @@ -323,13 +311,13 @@ namespace System.Globalization nameof(millisecond), String.Format( CultureInfo.CurrentCulture, - Environment.GetResourceString("ArgumentOutOfRange_Range"), + SR.ArgumentOutOfRange_Range, 0, MillisPerSecond - 1)); } - return (TimeSpan.TimeToTicks(hour, minute, second) + millisecond * TicksPerMillisecond); ; + return (InternalGloablizationHelper.TimeToTicks(hour, minute, second) + millisecond * TicksPerMillisecond); ; } - throw new ArgumentOutOfRangeException(null, Environment.GetResourceString("ArgumentOutOfRange_BadHourMinuteSecond")); + throw new ArgumentOutOfRangeException(null, SR.ArgumentOutOfRange_BadHourMinuteSecond); } @@ -341,7 +329,7 @@ namespace System.Globalization "time", String.Format( CultureInfo.InvariantCulture, - Environment.GetResourceString("ArgumentOutOfRange_CalendarRange"), + SR.ArgumentOutOfRange_CalendarRange, m_Cal.MinSupportedDateTime, m_Cal.MaxSupportedDateTime)); } @@ -373,7 +361,7 @@ namespace System.Globalization nameof(months), String.Format( CultureInfo.CurrentCulture, - Environment.GetResourceString("ArgumentOutOfRange_Range"), + SR.ArgumentOutOfRange_Range, -120000, 120000)); } @@ -458,7 +446,7 @@ namespace System.Globalization year = GetGregorianYear(year, era); if (month < 1 || month > 12) { - throw new ArgumentOutOfRangeException(nameof(month), Environment.GetResourceString("ArgumentOutOfRange_Month")); + throw new ArgumentOutOfRangeException(nameof(month), SR.ArgumentOutOfRange_Month); } int[] days = ((year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) ? DaysToMonth366 : DaysToMonth365); return (days[month] - days[month - 1]); @@ -488,7 +476,7 @@ namespace System.Globalization return (m_EraInfo[i].era); } } - throw new ArgumentOutOfRangeException(nameof(time), Environment.GetResourceString("ArgumentOutOfRange_Era")); + throw new ArgumentOutOfRangeException(nameof(time), SR.ArgumentOutOfRange_Era); } @@ -537,7 +525,7 @@ namespace System.Globalization return (year - m_EraInfo[i].yearOffset); } } - throw new ArgumentException(Environment.GetResourceString("Argument_NoEra")); + throw new ArgumentException(SR.Argument_NoEra); } // Returns the year that match the specified Gregorian year. The returned value is an @@ -548,9 +536,9 @@ namespace System.Globalization long ticks = time.Ticks; for (int i = 0; i < m_EraInfo.Length; i++) { - // while calculating dates with JapaneseLuniSolarCalendar, we can run into cases right after the start of the era - // and still belong to the month which is started in previous era. Calculating equivalent calendar date will cause - // using the new era info which will have the year offset equal to the year we are calculating year = m_EraInfo[i].yearOffset + // while calculating dates with JapaneseLuniSolarCalendar, we can run into cases right after the start of the era + // and still belong to the month which is started in previous era. Calculating equivalent calendar date will cause + // using the new era info which will have the year offset equal to the year we are calculating year = m_EraInfo[i].yearOffset // which will end up with zero as calendar year. // We should use the previous era info instead to get the right year number. Example of such date is Feb 2nd 1989 if (ticks >= m_EraInfo[i].ticks && year > m_EraInfo[i].yearOffset) @@ -558,7 +546,7 @@ namespace System.Globalization return (year - m_EraInfo[i].yearOffset); } } - throw new ArgumentException(Environment.GetResourceString("Argument_NoEra")); + throw new ArgumentException(SR.Argument_NoEra); } // Checks whether a given day in the specified era is a leap day. This method returns true if @@ -573,7 +561,7 @@ namespace System.Globalization nameof(day), String.Format( CultureInfo.CurrentCulture, - Environment.GetResourceString("ArgumentOutOfRange_Range"), + SR.ArgumentOutOfRange_Range, 1, GetDaysInMonth(year, month, era))); } @@ -613,7 +601,7 @@ namespace System.Globalization nameof(month), String.Format( CultureInfo.CurrentCulture, - Environment.GetResourceString("ArgumentOutOfRange_Range"), + SR.ArgumentOutOfRange_Range, 1, 12)); } @@ -653,7 +641,7 @@ namespace System.Globalization if (year < 0) { throw new ArgumentOutOfRangeException(nameof(year), - Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum")); + SR.ArgumentOutOfRange_NeedPosNum); } Contract.EndContractBlock(); @@ -669,7 +657,7 @@ namespace System.Globalization nameof(year), String.Format( CultureInfo.CurrentCulture, - Environment.GetResourceString("ArgumentOutOfRange_Range"), m_minYear, m_maxYear)); + SR.ArgumentOutOfRange_Range, m_minYear, m_maxYear)); } // If the year value is above 100, just return the year value. Don't have to do // the TwoDigitYearMax comparison. diff --git a/src/mscorlib/src/System/Globalization/GregorianCalendarTypes.cs b/src/mscorlib/src/System/Globalization/GregorianCalendarTypes.cs index 70cd11b..a14010f 100644 --- a/src/mscorlib/src/System/Globalization/GregorianCalendarTypes.cs +++ b/src/mscorlib/src/System/Globalization/GregorianCalendarTypes.cs @@ -6,14 +6,16 @@ using System; namespace System.Globalization { + // Note: The values of the members of this enum must match the coresponding values + // in the CalendarId enum (since we cast between GregorianCalendarTypes and CalendarId). [Serializable] public enum GregorianCalendarTypes { - Localized = Calendar.CAL_GREGORIAN, - USEnglish = Calendar.CAL_GREGORIAN_US, - MiddleEastFrench = Calendar.CAL_GREGORIAN_ME_FRENCH, - Arabic = Calendar.CAL_GREGORIAN_ARABIC, - TransliteratedEnglish = Calendar.CAL_GREGORIAN_XLIT_ENGLISH, - TransliteratedFrench = Calendar.CAL_GREGORIAN_XLIT_FRENCH, + Localized = CalendarId.GREGORIAN, + USEnglish = CalendarId.GREGORIAN_US, + MiddleEastFrench = CalendarId.GREGORIAN_ME_FRENCH, + Arabic = CalendarId.GREGORIAN_ARABIC, + TransliteratedEnglish = CalendarId.GREGORIAN_XLIT_ENGLISH, + TransliteratedFrench = CalendarId.GREGORIAN_XLIT_FRENCH, } } diff --git a/src/mscorlib/src/System/Globalization/HebrewCalendar.cs b/src/mscorlib/src/System/Globalization/HebrewCalendar.cs index ba54a67..b4f54f8 100644 --- a/src/mscorlib/src/System/Globalization/HebrewCalendar.cs +++ b/src/mscorlib/src/System/Globalization/HebrewCalendar.cs @@ -2,8 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System; -using System.Text; using System.Diagnostics; using System.Diagnostics.Contracts; @@ -140,7 +138,7 @@ namespace System.Globalization private const int MinHebrewYear = HebrewYearOf1AD + FirstGregorianTableYear; // == 5343 private const int MaxHebrewYear = HebrewYearOf1AD + LastGregorianTableYear; // == 5999 - private static readonly int[] HebrewTable = { + private static readonly byte[] s_hebrewTable = { 7,3,17,3, // 1583-1584 (Hebrew year: 5343 - 5344) 0,4,11,2,21,6,1,3,13,2, // 1585-1589 25,4,5,3,16,2,27,6,9,1, // 1590-1594 @@ -276,22 +274,22 @@ namespace System.Globalization 6,1 // 2240 (Hebrew year: 6000) }; + private const int MaxMonthPlusOne = 14; + // // The lunar calendar has 6 different variations of month lengths // within a year. // - private static readonly int[,] LunarMonthLen = { - {0,00,00,00,00,00,00,00,00,00,00,00,00,0}, - {0,30,29,29,29,30,29,30,29,30,29,30,29,0}, // 3 common year variations - {0,30,29,30,29,30,29,30,29,30,29,30,29,0}, - {0,30,30,30,29,30,29,30,29,30,29,30,29,0}, - {0,30,29,29,29,30,30,29,30,29,30,29,30,29}, // 3 leap year variations - {0,30,29,30,29,30,30,29,30,29,30,29,30,29}, - {0,30,30,30,29,30,30,29,30,29,30,29,30,29} + private static readonly byte[] s_lunarMonthLen = { + 0,00,00,00,00,00,00,00,00,00,00,00,00,0, + 0,30,29,29,29,30,29,30,29,30,29,30,29,0, // 3 common year variations + 0,30,29,30,29,30,29,30,29,30,29,30,29,0, + 0,30,30,30,29,30,29,30,29,30,29,30,29,0, + 0,30,29,29,29,30,30,29,30,29,30,29,30,29, // 3 leap year variations + 0,30,29,30,29,30,30,29,30,29,30,29,30,29, + 0,30,30,30,29,30,30,29,30,29,30,29,30,29 }; - //internal static Calendar m_defaultInstance; - internal static readonly DateTime calendarMinValue = new DateTime(1583, 1, 1); // Gregorian 2239/9/29 = Hebrew 5999/13/29 (last day in Hebrew year 5999). // We can only format/parse Hebrew numbers up to 999, so we limit the max range to Hebrew year 5999. @@ -317,11 +315,6 @@ namespace System.Globalization } } - - // Return the type of the Hebrew calendar. - // - - public override CalendarAlgorithmType AlgorithmType { get @@ -330,35 +323,15 @@ namespace System.Globalization } } - /*=================================GetDefaultInstance========================== - **Action: Internal method to provide a default intance of HebrewCalendar. Used by NLS+ implementation - ** and other calendars. - **Returns: - **Arguments: - **Exceptions: - ============================================================================*/ - - /* - internal static Calendar GetDefaultInstance() { - if (m_defaultInstance == null) { - m_defaultInstance = new HebrewCalendar(); - } - return (m_defaultInstance); - } - */ - - - // Construct an instance of gregorian calendar. - public HebrewCalendar() { } - internal override int ID + internal override CalendarId ID { get { - return (CAL_HEBREW); + return (CalendarId.HEBREW); } } @@ -373,7 +346,7 @@ namespace System.Globalization ** We use a table for the Hebrew calendar calculation, so the year supported is limited. ============================================================================*/ - static private void CheckHebrewYearValue(int y, int era, String varName) + private static void CheckHebrewYearValue(int y, int era, String varName) { CheckEraRange(era); if (y > MaxHebrewYear || y < MinHebrewYear) @@ -382,7 +355,7 @@ namespace System.Globalization varName, String.Format( CultureInfo.CurrentCulture, - Environment.GetResourceString("ArgumentOutOfRange_Range"), + SR.ArgumentOutOfRange_Range, MinHebrewYear, MaxHebrewYear)); } @@ -407,7 +380,7 @@ namespace System.Globalization nameof(month), String.Format( CultureInfo.CurrentCulture, - Environment.GetResourceString("ArgumentOutOfRange_Range"), + SR.ArgumentOutOfRange_Range, 1, monthsInYear)); } @@ -433,21 +406,21 @@ namespace System.Globalization nameof(day), String.Format( CultureInfo.CurrentCulture, - Environment.GetResourceString("ArgumentOutOfRange_Range"), + SR.ArgumentOutOfRange_Range, 1, daysInMonth)); } } - static internal void CheckEraRange(int era) + internal static void CheckEraRange(int era) { if (era != CurrentEra && era != HebrewEra) { - throw new ArgumentOutOfRangeException(nameof(era), Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue")); + throw new ArgumentOutOfRangeException(nameof(era), SR.ArgumentOutOfRange_InvalidEraValue); } } - static private void CheckTicksRange(long ticks) + private static void CheckTicksRange(long ticks) { if (ticks < calendarMinValue.Ticks || ticks > calendarMaxValue.Ticks) { @@ -456,13 +429,13 @@ namespace System.Globalization // Print out the date in Gregorian using InvariantCulture since the DateTime is based on GreograinCalendar. String.Format( CultureInfo.InvariantCulture, - Environment.GetResourceString("ArgumentOutOfRange_CalendarRange"), + SR.ArgumentOutOfRange_CalendarRange, calendarMinValue, calendarMaxValue)); } } - static internal int GetResult(__DateBuffer result, int part) + internal static int GetResult(__DateBuffer result, int part) { switch (part) { @@ -474,7 +447,7 @@ namespace System.Globalization return (result.day); } - throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_DateTimeParsing")); + throw new InvalidOperationException(SR.InvalidOperation_DateTimeParsing); } /*=================================GetLunarMonthDay========================== @@ -494,7 +467,7 @@ namespace System.Globalization **Exceptions: ============================================================================*/ - static internal int GetLunarMonthDay(int gregorianYear, __DateBuffer lunarDate) + internal static int GetLunarMonthDay(int gregorianYear, __DateBuffer lunarDate) { // // Get the offset into the LunarMonthLen array and the lunar day @@ -507,10 +480,10 @@ namespace System.Globalization } index *= 2; - lunarDate.day = HebrewTable[index]; + lunarDate.day = s_hebrewTable[index]; // Get the type of the year. The value is from 1 to 6 - int LunarYearType = HebrewTable[index + 1]; + int LunarYearType = s_hebrewTable[index + 1]; // // Get the Lunar Month. @@ -608,7 +581,7 @@ namespace System.Globalization // If the requested date is within the current lunar month, then // we're done. // - if ((NumDays + (long)lunarDate.day) <= (long)(LunarMonthLen[hebrewYearType, lunarDate.month])) + if ((NumDays + (long)lunarDate.day) <= (long)(s_lunarMonthLen[hebrewYearType * MaxMonthPlusOne + lunarDate.month])) { result.day += (int)NumDays; return (GetResult(result, part)); @@ -627,7 +600,7 @@ namespace System.Globalization // Assumes Jan 1 can never translate to the last Lunar month, which // is true. // - NumDays -= (long)(LunarMonthLen[hebrewYearType, lunarDate.month] - lunarDate.day); + NumDays -= (long)(s_lunarMonthLen[hebrewYearType * MaxMonthPlusOne + lunarDate.month] - lunarDate.day); Debug.Assert(NumDays >= 1, "NumDays >= 1"); // If NumDays is 1, then we are done. Otherwise, find the correct Hebrew month @@ -637,24 +610,24 @@ namespace System.Globalization // // See if we're on the correct Lunar month. // - while (NumDays > (long)(LunarMonthLen[hebrewYearType, result.month])) + while (NumDays > (long)(s_lunarMonthLen[hebrewYearType * MaxMonthPlusOne + result.month])) { // // Adjust the number of days and move to the next month. // - NumDays -= (long)(LunarMonthLen[hebrewYearType, result.month++]); + NumDays -= (long)(s_lunarMonthLen[hebrewYearType * MaxMonthPlusOne + result.month++]); // // See if we need to adjust the Year. // Must handle both 12 and 13 month years. // - if ((result.month > 13) || (LunarMonthLen[hebrewYearType, result.month] == 0)) + if ((result.month > 13) || (s_lunarMonthLen[hebrewYearType * MaxMonthPlusOne + result.month] == 0)) { // // Adjust the Year. // result.year++; - hebrewYearType = HebrewTable[(gregorianYear + 1 - FirstGregorianTableYear) * 2 + 1]; + hebrewYearType = s_hebrewTable[(gregorianYear + 1 - FirstGregorianTableYear) * 2 + 1]; // // Adjust the Month. @@ -741,7 +714,7 @@ namespace System.Globalization nameof(months), String.Format( CultureInfo.CurrentCulture, - Environment.GetResourceString("ArgumentOutOfRange_AddValue"))); + SR.ArgumentOutOfRange_AddValue)); } } @@ -802,12 +775,12 @@ namespace System.Globalization return ((DayOfWeek)((int)(time.Ticks / TicksPerDay + 1) % 7)); } - static internal int GetHebrewYearType(int year, int era) + internal static int GetHebrewYearType(int year, int era) { CheckHebrewYearValue(year, era, nameof(year)); // The HebrewTable is indexed by Gregorian year and starts from FirstGregorianYear. // So we need to convert year (Hebrew year value) to Gregorian Year below. - return (HebrewTable[(year - HebrewYearOf1AD - FirstGregorianTableYear) * 2 + 1]); + return (s_hebrewTable[(year - HebrewYearOf1AD - FirstGregorianTableYear) * 2 + 1]); } // Returns the day-of-year part of the specified DateTime. The returned value @@ -854,10 +827,10 @@ namespace System.Globalization Debug.Assert(hebrewYearType >= 1 && hebrewYearType <= 6, "hebrewYearType should be from 1 to 6, but now hebrewYearType = " + hebrewYearType + " for hebrew year " + year); - int monthDays = LunarMonthLen[hebrewYearType, month]; + int monthDays = s_lunarMonthLen[hebrewYearType * MaxMonthPlusOne + month]; if (monthDays == 0) { - throw new ArgumentOutOfRangeException(nameof(month), Environment.GetResourceString("ArgumentOutOfRange_Month")); + throw new ArgumentOutOfRangeException(nameof(month), SR.ArgumentOutOfRange_Month); } return (monthDays); } @@ -1014,7 +987,7 @@ namespace System.Globalization } // Get the number of days from (month1,day1) to (month1, end of month1) - int days = LunarMonthLen[lunarYearType, month1] - day1; + int days = s_lunarMonthLen[lunarYearType * MaxMonthPlusOne + month1] - day1; // Move to next month. month1++; @@ -1022,7 +995,7 @@ namespace System.Globalization // Add up the days. while (month1 < month2) { - days += LunarMonthLen[lunarYearType, month1++]; + days += s_lunarMonthLen[lunarYearType * MaxMonthPlusOne + month1++]; } days += day2; @@ -1123,7 +1096,7 @@ namespace System.Globalization if (year < 0) { throw new ArgumentOutOfRangeException(nameof(year), - Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + SR.ArgumentOutOfRange_NeedNonNegNum); } Contract.EndContractBlock(); @@ -1138,7 +1111,7 @@ namespace System.Globalization nameof(year), String.Format( CultureInfo.CurrentCulture, - Environment.GetResourceString("ArgumentOutOfRange_Range"), + SR.ArgumentOutOfRange_Range, MinHebrewYear, MaxHebrewYear)); } diff --git a/src/mscorlib/src/System/Globalization/HebrewNumber.cs b/src/mscorlib/src/System/Globalization/HebrewNumber.cs index b868d3e..1e8fff2 100644 --- a/src/mscorlib/src/System/Globalization/HebrewNumber.cs +++ b/src/mscorlib/src/System/Globalization/HebrewNumber.cs @@ -2,11 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. - -using System; using System.Text; using System.Diagnostics; -using System.Diagnostics.Contracts; namespace System.Globalization { @@ -228,7 +225,7 @@ namespace System.Globalization // //////////////////////////////////////////////////////////////////////////// - private enum HebrewToken + private enum HebrewToken : short { Invalid = -1, Digit400 = 0, @@ -249,11 +246,11 @@ namespace System.Globalization // //////////////////////////////////////////////////////////////////////////// - private class HebrewValue + private struct HebrewValue { internal HebrewToken token; - internal int value; - internal HebrewValue(HebrewToken token, int value) + internal short value; + internal HebrewValue(HebrewToken token, short value) { this.token = token; this.value = value; @@ -264,7 +261,7 @@ namespace System.Globalization // Map a Hebrew character from U+05D0 ~ U+05EA to its digit value. // The value is -1 if the Hebrew character does not have a associated value. // - private static HebrewValue[] HebrewValues = { + private static readonly HebrewValue[] s_hebrewValues = { new HebrewValue(HebrewToken.Digit1, 1) , // '\x05d0 new HebrewValue(HebrewToken.Digit1, 2) , // '\x05d1 new HebrewValue(HebrewToken.Digit1, 3) , // '\x05d2 @@ -295,7 +292,7 @@ namespace System.Globalization }; private const int minHebrewNumberCh = 0x05d0; - private static char maxHebrewNumberCh = (char)(minHebrewNumberCh + HebrewValues.Length - 1); + private static char s_maxHebrewNumberCh = (char)(minHebrewNumberCh + s_hebrewValues.Length - 1); //////////////////////////////////////////////////////////////////////////// // @@ -305,7 +302,7 @@ namespace System.Globalization // //////////////////////////////////////////////////////////////////////////// - internal enum HS + internal enum HS : sbyte { _err = -1, // an error state Start = 0, @@ -331,27 +328,47 @@ namespace System.Globalization // // The state machine for Hebrew number pasing. // - private readonly static HS[][] NumberPasingState = { - // 400 300/200 100 90~10 8~1 6, 7, 9, ' " - /* 0 */ new HS[] {HS.S400, HS.X00, HS.X00, HS.X0, HS.X, HS.X, HS.X, HS.S9, HS._err, HS._err}, - /* 1: S400 */ new HS[] {HS.S400_400, HS.S400_X00, HS.S400_X00, HS.S400_X0, HS._err, HS._err, HS._err, HS.X00_S9 ,HS.END, HS.S400_DQ}, - /* 2: S400_400 */ new HS[] {HS._err, HS._err, HS.S400_400_100,HS.S400_X0, HS._err, HS._err, HS._err, HS.X00_S9 ,HS._err, HS.S400_400_DQ}, - /* 3: S400_X00 */ new HS[] {HS._err, HS._err, HS._err, HS.S400_X00_X0, HS._err, HS._err, HS._err, HS.X00_S9 ,HS._err, HS.X00_DQ}, - /* 4: S400_X0 */ new HS[] {HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS.X0_DQ}, - /* 5: X00_DQ */ new HS[] {HS._err, HS._err, HS._err, HS.END, HS.END, HS.END, HS.END, HS.END, HS._err, HS._err}, - /* 6: S400_X00_X0 */new HS[] {HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS.X0_DQ}, - /* 7: X0_DQ */ new HS[] {HS._err, HS._err, HS._err, HS._err, HS.END, HS.END, HS.END, HS.END, HS._err, HS._err}, - /* 8: X */ new HS[] {HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS.END, HS._err}, - /* 9: X0 */ new HS[] {HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS.END, HS.X0_DQ}, - /* 10: X00 */ new HS[] {HS._err, HS._err, HS._err, HS.S400_X0, HS._err, HS._err, HS._err, HS.X00_S9, HS.END, HS.X00_DQ}, - /* 11: S400_DQ */ new HS[] {HS.END, HS.END, HS.END, HS.END, HS.END, HS.END, HS.END, HS.END, HS._err, HS._err}, - /* 12: S400_400_DQ*/new HS[] {HS._err, HS._err, HS.END, HS.END, HS.END, HS.END, HS.END, HS.END, HS._err, HS._err}, - /* 13: S400_400_100*/new HS[]{HS._err, HS._err, HS._err, HS.S400_X00_X0, HS._err, HS._err, HS._err, HS.X00_S9, HS._err, HS.X00_DQ}, - /* 14: S9 */ new HS[] {HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err,HS.END, HS.S9_DQ}, - /* 15: X00_S9 */ new HS[] {HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS.S9_DQ}, - /* 16: S9_DQ */ new HS[] {HS._err, HS._err, HS._err, HS._err, HS._err, HS.END, HS.END, HS._err, HS._err, HS._err}, - }; + private static readonly HS[] s_numberPasingState = + { + // 400 300/200 100 90~10 8~1 6, 7, 9, ' " + /* 0 */ + HS.S400, HS.X00, HS.X00, HS.X0, HS.X, HS.X, HS.X, HS.S9, HS._err, HS._err, + /* 1: S400 */ + HS.S400_400, HS.S400_X00, HS.S400_X00, HS.S400_X0, HS._err, HS._err, HS._err, HS.X00_S9 ,HS.END, HS.S400_DQ, + /* 2: S400_400 */ + HS._err, HS._err, HS.S400_400_100,HS.S400_X0, HS._err, HS._err, HS._err, HS.X00_S9 ,HS._err, HS.S400_400_DQ, + /* 3: S400_X00 */ + HS._err, HS._err, HS._err, HS.S400_X00_X0, HS._err, HS._err, HS._err, HS.X00_S9 ,HS._err, HS.X00_DQ, + /* 4: S400_X0 */ + HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS.X0_DQ, + /* 5: X00_DQ */ + HS._err, HS._err, HS._err, HS.END, HS.END, HS.END, HS.END, HS.END, HS._err, HS._err, + /* 6: S400_X00_X0 */ + HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS.X0_DQ, + /* 7: X0_DQ */ + HS._err, HS._err, HS._err, HS._err, HS.END, HS.END, HS.END, HS.END, HS._err, HS._err, + /* 8: X */ + HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS.END, HS._err, + /* 9: X0 */ + HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS.END, HS.X0_DQ, + /* 10: X00 */ + HS._err, HS._err, HS._err, HS.S400_X0, HS._err, HS._err, HS._err, HS.X00_S9, HS.END, HS.X00_DQ, + /* 11: S400_DQ */ + HS.END, HS.END, HS.END, HS.END, HS.END, HS.END, HS.END, HS.END, HS._err, HS._err, + /* 12: S400_400_DQ*/ + HS._err, HS._err, HS.END, HS.END, HS.END, HS.END, HS.END, HS.END, HS._err, HS._err, + /* 13: S400_400_100*/ + HS._err, HS._err, HS._err, HS.S400_X00_X0, HS._err, HS._err, HS._err, HS.X00_S9, HS._err, HS.X00_DQ, + /* 14: S9 */ + HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS.END, HS.S9_DQ, + /* 15: X00_S9 */ + HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS.S9_DQ, + /* 16: S9_DQ */ + HS._err, HS._err, HS._err, HS._err, HS._err, HS.END, HS.END, HS._err, HS._err, HS._err + }; + // Count of valid HebrewToken, column count in the NumberPasingState array + private const int HebrewTokenCount = 10; //////////////////////////////////////////////////////////////////////// // @@ -373,6 +390,8 @@ namespace System.Globalization internal static HebrewNumberParsingState ParseByChar(char ch, ref HebrewNumberParsingContext context) { + Debug.Assert(s_numberPasingState.Length == HebrewTokenCount * ((int)HS.S9_DQ + 1)); + HebrewToken token; if (ch == '\'') { @@ -385,14 +404,14 @@ namespace System.Globalization else { int index = (int)ch - minHebrewNumberCh; - if (index >= 0 && index < HebrewValues.Length) + if (index >= 0 && index < s_hebrewValues.Length) { - token = HebrewValues[index].token; + token = s_hebrewValues[index].token; if (token == HebrewToken.Invalid) { return (HebrewNumberParsingState.NotHebrewDigit); } - context.result += HebrewValues[index].value; + context.result += s_hebrewValues[index].value; } else { @@ -400,7 +419,7 @@ namespace System.Globalization return (HebrewNumberParsingState.NotHebrewDigit); } } - context.state = NumberPasingState[(int)context.state][(int)token]; + context.state = s_numberPasingState[(int)context.state * (int)HebrewTokenCount + (int)token]; if (context.state == HS._err) { // Invalid Hebrew state. This indicates an incorrect Hebrew number. @@ -428,9 +447,9 @@ namespace System.Globalization internal static bool IsDigit(char ch) { - if (ch >= minHebrewNumberCh && ch <= maxHebrewNumberCh) + if (ch >= minHebrewNumberCh && ch <= s_maxHebrewNumberCh) { - return (HebrewValues[ch - minHebrewNumberCh].value >= 0); + return (s_hebrewValues[ch - minHebrewNumberCh].value >= 0); } return (ch == '\'' || ch == '\"'); } diff --git a/src/mscorlib/corefx/System/Globalization/HijriCalendar.Unix.cs b/src/mscorlib/src/System/Globalization/HijriCalendar.Unix.cs similarity index 100% rename from src/mscorlib/corefx/System/Globalization/HijriCalendar.Unix.cs rename to src/mscorlib/src/System/Globalization/HijriCalendar.Unix.cs diff --git a/src/mscorlib/corefx/System/Globalization/HijriCalendar.Win32.cs b/src/mscorlib/src/System/Globalization/HijriCalendar.Win32.cs similarity index 100% rename from src/mscorlib/corefx/System/Globalization/HijriCalendar.Win32.cs rename to src/mscorlib/src/System/Globalization/HijriCalendar.Win32.cs diff --git a/src/mscorlib/corefx/System/Globalization/HijriCalendar.WinRT.cs b/src/mscorlib/src/System/Globalization/HijriCalendar.WinRT.cs similarity index 100% rename from src/mscorlib/corefx/System/Globalization/HijriCalendar.WinRT.cs rename to src/mscorlib/src/System/Globalization/HijriCalendar.WinRT.cs diff --git a/src/mscorlib/src/System/Globalization/HijriCalendar.cs b/src/mscorlib/src/System/Globalization/HijriCalendar.cs index 9eeab44..0c72d9e 100644 --- a/src/mscorlib/src/System/Globalization/HijriCalendar.cs +++ b/src/mscorlib/src/System/Globalization/HijriCalendar.cs @@ -2,16 +2,12 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System; +using System.Runtime.Versioning; +using System.Diagnostics.Contracts; + namespace System.Globalization { - using System; - using System.Runtime.Versioning; - using System.Diagnostics.Contracts; -#if !FEATURE_WIN32_REGISTRY - using System.Text; - using Microsoft.Win32; -#endif // FEATURE_WIN32_REGISTRY - //////////////////////////////////////////////////////////////////////////// // // Rules for the Hijri calendar: @@ -49,7 +45,7 @@ namespace System.Globalization */ [Serializable] - public class HijriCalendar : Calendar + public partial class HijriCalendar : Calendar { public static readonly int HijriEra = 1; @@ -63,14 +59,7 @@ namespace System.Globalization internal static readonly int[] HijriMonthDays = { 0, 30, 59, 89, 118, 148, 177, 207, 236, 266, 295, 325, 355 }; - //internal static Calendar m_defaultInstance; - -#if FEATURE_WIN32_REGISTRY - private const String InternationalRegKey = "Control Panel\\International"; - private const String HijriAdvanceRegKeyEntry = "AddHijriDate"; -#endif - - private int m_HijriAdvance = Int32.MinValue; + private int _hijriAdvance = Int32.MinValue; // DateTime.MaxValue = Hijri calendar (year:9666, month: 4, day: 3). internal const int MaxCalendarYear = 9666; @@ -99,9 +88,6 @@ namespace System.Globalization } } - // Return the type of the Hijri calendar. - // - public override CalendarAlgorithmType AlgorithmType { get @@ -110,33 +96,15 @@ namespace System.Globalization } } - /*=================================GetDefaultInstance========================== - **Action: Internal method to provide a default intance of HijriCalendar. Used by NLS+ implementation - ** and other calendars. - **Returns: - **Arguments: - **Exceptions: - ============================================================================*/ - /* - internal static Calendar GetDefaultInstance() { - if (m_defaultInstance == null) { - m_defaultInstance = new HijriCalendar(); - } - return (m_defaultInstance); - } - */ - - // Construct an instance of Hijri calendar. - public HijriCalendar() { } - internal override int ID + internal override CalendarId ID { get { - return (CAL_HIJRI); + return CalendarId.HIJRI; } } @@ -208,17 +176,16 @@ namespace System.Globalization return (NumDays); } - public int HijriAdjustment { get { - if (m_HijriAdvance == Int32.MinValue) + if (_hijriAdvance == Int32.MinValue) { // Never been set before. Use the system value from registry. - m_HijriAdvance = GetAdvanceHijriDate(); + _hijriAdvance = GetHijriDateAdjustment(); } - return (m_HijriAdvance); + return (_hijriAdvance); } set @@ -227,99 +194,21 @@ namespace System.Globalization if (value < MinAdvancedHijri || value > MaxAdvancedHijri) { throw new ArgumentOutOfRangeException( - nameof(HijriAdjustment), + "HijriAdjustment", String.Format( CultureInfo.CurrentCulture, - Environment.GetResourceString("ArgumentOutOfRange_Bounds_Lower_Upper"), + SR.ArgumentOutOfRange_Bounds_Lower_Upper, MinAdvancedHijri, MaxAdvancedHijri)); } Contract.EndContractBlock(); VerifyWritable(); - m_HijriAdvance = value; + _hijriAdvance = value; } } - /*=================================GetAdvanceHijriDate========================== - **Action: Gets the AddHijriDate value from the registry. - **Returns: - **Arguments: None. - **Exceptions: - **Note: - ** The HijriCalendar has a user-overidable calculation. That is, use can set a value from the control - ** panel, so that the calculation of the Hijri Calendar can move ahead or backwards from -2 to +2 days. - ** - ** The valid string values in the registry are: - ** "AddHijriDate-2" => Add -2 days to the current calculated Hijri date. - ** "AddHijriDate" => Add -1 day to the current calculated Hijri date. - ** "" => Add 0 day to the current calculated Hijri date. - ** "AddHijriDate+1" => Add +1 days to the current calculated Hijri date. - ** "AddHijriDate+2" => Add +2 days to the current calculated Hijri date. - ============================================================================*/ - private static int GetAdvanceHijriDate() - { -#if FEATURE_WIN32_REGISTRY - - int hijriAdvance = 0; - Microsoft.Win32.RegistryKey key = null; - - try - { - // Open in read-only mode. - // Use InternalOpenSubKey so that we avoid the security check. - key = Microsoft.Win32.Registry.CurrentUser.InternalOpenSubKey(InternationalRegKey, false); - } - //If this fails for any reason, we'll just return 0. - catch (ObjectDisposedException) { return 0; } - catch (ArgumentException) { return 0; } - - if (key != null) - { - try - { - Object value = key.InternalGetValue(HijriAdvanceRegKeyEntry, null, false, false); - if (value == null) - { - return (0); - } - String str = value.ToString(); - if (String.Compare(str, 0, HijriAdvanceRegKeyEntry, 0, HijriAdvanceRegKeyEntry.Length, StringComparison.OrdinalIgnoreCase) == 0) - { - if (str.Length == HijriAdvanceRegKeyEntry.Length) - hijriAdvance = -1; - else - { - str = str.Substring(HijriAdvanceRegKeyEntry.Length); - try - { - int advance = Int32.Parse(str.ToString(), CultureInfo.InvariantCulture); - if ((advance >= MinAdvancedHijri) && (advance <= MaxAdvancedHijri)) - { - hijriAdvance = advance; - } - } - // If we got garbage from registry just ignore it. - // hijriAdvance = 0 because of declaraction assignment up above. - catch (ArgumentException) { } - catch (FormatException) { } - catch (OverflowException) { } - } - } - } - finally - { - key.Close(); - } - } - return (hijriAdvance); - -#else //FEATURE_WIN32_REGISTRY - return 0; -#endif // FEATURE_WIN32_REGISTRY - } - - static internal void CheckTicksRange(long ticks) + internal static void CheckTicksRange(long ticks) { if (ticks < calendarMinValue.Ticks || ticks > calendarMaxValue.Ticks) { @@ -327,21 +216,21 @@ namespace System.Globalization "time", String.Format( CultureInfo.InvariantCulture, - Environment.GetResourceString("ArgumentOutOfRange_CalendarRange"), + SR.ArgumentOutOfRange_CalendarRange, calendarMinValue, calendarMaxValue)); } } - static internal void CheckEraRange(int era) + internal static void CheckEraRange(int era) { if (era != CurrentEra && era != HijriEra) { - throw new ArgumentOutOfRangeException(nameof(era), Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue")); + throw new ArgumentOutOfRangeException(nameof(era), SR.ArgumentOutOfRange_InvalidEraValue); } } - static internal void CheckYearRange(int year, int era) + internal static void CheckYearRange(int year, int era) { CheckEraRange(era); if (year < 1 || year > MaxCalendarYear) @@ -350,13 +239,13 @@ namespace System.Globalization nameof(year), String.Format( CultureInfo.CurrentCulture, - Environment.GetResourceString("ArgumentOutOfRange_Range"), + SR.ArgumentOutOfRange_Range, 1, MaxCalendarYear)); } } - static internal void CheckYearMonthRange(int year, int month, int era) + internal static void CheckYearMonthRange(int year, int month, int era) { CheckYearRange(year, era); if (year == MaxCalendarYear) @@ -367,7 +256,7 @@ namespace System.Globalization nameof(month), String.Format( CultureInfo.CurrentCulture, - Environment.GetResourceString("ArgumentOutOfRange_Range"), + SR.ArgumentOutOfRange_Range, 1, MaxCalendarMonth)); } @@ -375,7 +264,7 @@ namespace System.Globalization if (month < 1 || month > 12) { - throw new ArgumentOutOfRangeException(nameof(month), Environment.GetResourceString("ArgumentOutOfRange_Month")); + throw new ArgumentOutOfRangeException(nameof(month), SR.ArgumentOutOfRange_Month); } } @@ -476,7 +365,7 @@ namespace System.Globalization return (HijriDay); } // Incorrect part value. - throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_DateTimeParsing")); + throw new InvalidOperationException(SR.InvalidOperation_DateTimeParsing); } // Returns the DateTime resulting from adding the given number of @@ -505,7 +394,7 @@ namespace System.Globalization nameof(months), String.Format( CultureInfo.CurrentCulture, - Environment.GetResourceString("ArgumentOutOfRange_Range"), + SR.ArgumentOutOfRange_Range, -120000, 120000)); } @@ -661,7 +550,7 @@ namespace System.Globalization nameof(day), String.Format( CultureInfo.CurrentCulture, - Environment.GetResourceString("ArgumentOutOfRange_Day"), + SR.ArgumentOutOfRange_Day, daysInMonth, month)); } @@ -707,12 +596,11 @@ namespace System.Globalization int daysInMonth = GetDaysInMonth(year, month, era); if (day < 1 || day > daysInMonth) { - BCLDebug.Log("year = " + year + ", month = " + month + ", day = " + day); throw new ArgumentOutOfRangeException( nameof(day), String.Format( CultureInfo.CurrentCulture, - Environment.GetResourceString("ArgumentOutOfRange_Day"), + SR.ArgumentOutOfRange_Day, daysInMonth, month)); } @@ -725,7 +613,7 @@ namespace System.Globalization } else { - throw new ArgumentOutOfRangeException(null, Environment.GetResourceString("ArgumentOutOfRange_BadYearMonthDay")); + throw new ArgumentOutOfRangeException(null, SR.ArgumentOutOfRange_BadYearMonthDay); } } @@ -752,7 +640,7 @@ namespace System.Globalization nameof(value), String.Format( CultureInfo.CurrentCulture, - Environment.GetResourceString("ArgumentOutOfRange_Range"), + SR.ArgumentOutOfRange_Range, 99, MaxCalendarYear)); } @@ -766,7 +654,7 @@ namespace System.Globalization if (year < 0) { throw new ArgumentOutOfRangeException(nameof(year), - Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + SR.ArgumentOutOfRange_NeedNonNegNum); } Contract.EndContractBlock(); @@ -781,7 +669,7 @@ namespace System.Globalization nameof(year), String.Format( CultureInfo.CurrentCulture, - Environment.GetResourceString("ArgumentOutOfRange_Range"), + SR.ArgumentOutOfRange_Range, 1, MaxCalendarYear)); } diff --git a/src/mscorlib/corefx/System/Globalization/IdnMapping.Unix.cs b/src/mscorlib/src/System/Globalization/IdnMapping.Unix.cs similarity index 100% rename from src/mscorlib/corefx/System/Globalization/IdnMapping.Unix.cs rename to src/mscorlib/src/System/Globalization/IdnMapping.Unix.cs diff --git a/src/mscorlib/corefx/System/Globalization/IdnMapping.Windows.cs b/src/mscorlib/src/System/Globalization/IdnMapping.Windows.cs similarity index 82% rename from src/mscorlib/corefx/System/Globalization/IdnMapping.Windows.cs rename to src/mscorlib/src/System/Globalization/IdnMapping.Windows.cs index 3d3292e..5950a54 100644 --- a/src/mscorlib/corefx/System/Globalization/IdnMapping.Windows.cs +++ b/src/mscorlib/src/System/Globalization/IdnMapping.Windows.cs @@ -14,7 +14,7 @@ namespace System.Globalization uint flags = Flags; // Determine the required length - int length = Interop.mincore.IdnToAscii(flags, new IntPtr(unicode), count, IntPtr.Zero, 0); + int length = Interop.Normaliz.IdnToAscii(flags, new IntPtr(unicode), count, IntPtr.Zero, 0); if (length == 0) { ThrowForZeroLength(nameof(unicode), SR.Argument_IdnIllegalName, SR.Argument_InvalidCharSequenceNoIndex); @@ -39,7 +39,7 @@ namespace System.Globalization private unsafe string GetAsciiCore(char* unicode, int count, uint flags, char* output, int outputLength) { - int length = Interop.mincore.IdnToAscii(flags, new IntPtr(unicode), count, new IntPtr(output), outputLength); + int length = Interop.Normaliz.IdnToAscii(flags, new IntPtr(unicode), count, new IntPtr(output), outputLength); if (length == 0) { ThrowForZeroLength(nameof(unicode), SR.Argument_IdnIllegalName, SR.Argument_InvalidCharSequenceNoIndex); @@ -53,7 +53,7 @@ namespace System.Globalization uint flags = Flags; // Determine the required length - int length = Interop.mincore.IdnToUnicode(flags, new IntPtr(ascii), count, IntPtr.Zero, 0); + int length = Interop.Normaliz.IdnToUnicode(flags, new IntPtr(ascii), count, IntPtr.Zero, 0); if (length == 0) { ThrowForZeroLength(nameof(ascii), SR.Argument_IdnIllegalName, SR.Argument_IdnBadPunycode); @@ -78,7 +78,7 @@ namespace System.Globalization private unsafe string GetUnicodeCore(char* ascii, int count, uint flags, char* output, int outputLength) { - int length = Interop.mincore.IdnToUnicode(flags, new IntPtr(ascii), count, new IntPtr(output), outputLength); + int length = Interop.Normaliz.IdnToUnicode(flags, new IntPtr(ascii), count, new IntPtr(output), outputLength); if (length == 0) { ThrowForZeroLength(nameof(ascii), SR.Argument_IdnIllegalName, SR.Argument_IdnBadPunycode); @@ -96,8 +96,8 @@ namespace System.Globalization get { int flags = - (AllowUnassigned ? Interop.mincore.IDN_ALLOW_UNASSIGNED : 0) | - (UseStd3AsciiRules ? Interop.mincore.IDN_USE_STD3_ASCII_RULES : 0); + (AllowUnassigned ? Interop.Normaliz.IDN_ALLOW_UNASSIGNED : 0) | + (UseStd3AsciiRules ? Interop.Normaliz.IDN_USE_STD3_ASCII_RULES : 0); return (uint)flags; } } @@ -105,7 +105,7 @@ namespace System.Globalization private static void ThrowForZeroLength(string paramName, string invalidNameString, string otherString) { throw new ArgumentException( - Marshal.GetLastWin32Error() == Interop.ERROR_INVALID_NAME ? invalidNameString : otherString, + Marshal.GetLastWin32Error() == Interop.Normaliz.ERROR_INVALID_NAME ? invalidNameString : otherString, paramName); } } diff --git a/src/mscorlib/src/System/Globalization/IdnMapping.cs b/src/mscorlib/src/System/Globalization/IdnMapping.cs index f3a70d6..8424472 100644 --- a/src/mscorlib/src/System/Globalization/IdnMapping.cs +++ b/src/mscorlib/src/System/Globalization/IdnMapping.cs @@ -2,7 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -// // This file contains the IDN functions and implementation. // // This allows encoding of non-ASCII domain names in a "punycode" form, @@ -24,69 +23,16 @@ // RFC 3490 - Internationalizing Domain Names in Applications (IDNA) // RFC 3491 - Nameprep: A Stringprep Profile for Internationalized Domain Names (IDN) // RFC 3492 - Punycode: A Bootstring encoding of Unicode for Internationalized Domain Names in Applications (IDNA) -// - -/* - -The punycode implementation is based on the sample code in RFC 3492 - -Copyright (C) The Internet Society (2003). All Rights Reserved. - -This document and translations of it may be copied and furnished to -others, and derivative works that comment on or otherwise explain it -or assist in its implementation may be prepared, copied, published -and distributed, in whole or in part, without restriction of any -kind, provided that the above copyright notice and this paragraph are -included on all such copies and derivative works. However, this -document itself may not be modified in any way, such as by removing -the copyright notice or references to the Internet Society or other -Internet organizations, except as needed for the purpose of -developing Internet standards in which case the procedures for -copyrights defined in the Internet Standards process must be -followed, or as required to translate it into languages other than -English. -The limited permissions granted above are perpetual and will not be -revoked by the Internet Society or its successors or assigns. - -This document and the information contained herein is provided on an -"AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING -TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING -BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION -HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF -MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. -*/ - -using System; -using System.Security; -using System.Globalization; -using System.Text; -using System.Runtime.Versioning; -using System.Runtime.InteropServices; -using System.Diagnostics; using System.Diagnostics.Contracts; namespace System.Globalization { // IdnMapping class used to map names to Punycode - - public sealed class IdnMapping + public sealed partial class IdnMapping { - // Legal name lengths for domain names - private const int M_labelLimit = 63; // Not including dots - private const int M_defaultNameLimit = 255; // Including dots - - // IDNA prefix - private const String M_strAcePrefix = "xn--"; - - // Legal "dot" seperators (i.e: . in www.microsoft.com) - private static char[] M_Dots = - { - '.', '\u3002', '\uFF0E', '\uFF61' - }; - - private bool m_bAllowUnassigned; - private bool m_bUseStd3AsciiRules; + private bool _allowUnassigned; + private bool _useStd3AsciiRules; public IdnMapping() { @@ -94,1094 +40,113 @@ namespace System.Globalization public bool AllowUnassigned { - get - { - return m_bAllowUnassigned; - } - - set - { - m_bAllowUnassigned = value; - } + get { return _allowUnassigned; } + set { _allowUnassigned = value; } } public bool UseStd3AsciiRules { - get - { - return m_bUseStd3AsciiRules; - } - - set - { - m_bUseStd3AsciiRules = value; - } + get { return _useStd3AsciiRules; } + set { _useStd3AsciiRules = value; } } // Gets ASCII (Punycode) version of the string - public String GetAscii(String unicode) + public string GetAscii(string unicode) { return GetAscii(unicode, 0); } - public String GetAscii(String unicode, int index) + public string GetAscii(string unicode, int index) { - if (unicode == null) throw new ArgumentNullException(nameof(unicode)); + if (unicode == null) + throw new ArgumentNullException(nameof(unicode)); Contract.EndContractBlock(); return GetAscii(unicode, index, unicode.Length - index); } - public string GetAscii(String unicode, int index, int count) + public string GetAscii(string unicode, int index, int count) { - if (unicode == null) throw new ArgumentNullException(nameof(unicode)); + if (unicode == null) + throw new ArgumentNullException(nameof(unicode)); if (index < 0 || count < 0) - throw new ArgumentOutOfRangeException((index < 0) ? nameof(index) : nameof(count), - Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException((index < 0) ? nameof(index) : nameof(count), SR.ArgumentOutOfRange_NeedNonNegNum); if (index > unicode.Length) - throw new ArgumentOutOfRangeException(nameof(index), - Environment.GetResourceString("ArgumentOutOfRange_Index")); + throw new ArgumentOutOfRangeException(nameof(index), SR.ArgumentOutOfRange_Index); if (index > unicode.Length - count) - throw new ArgumentOutOfRangeException(nameof(unicode), - Environment.GetResourceString("ArgumentOutOfRange_IndexCountBuffer")); + throw new ArgumentOutOfRangeException(nameof(unicode), SR.ArgumentOutOfRange_IndexCountBuffer); Contract.EndContractBlock(); - // We're only using part of the string - unicode = unicode.Substring(index, count); - - if (Environment.IsWindows8OrAbove) - { - return GetAsciiUsingOS(unicode); - } - - // Check for ASCII only string, which will be unchanged - if (ValidateStd3AndAscii(unicode, UseStd3AsciiRules, true)) - { - return unicode; - } - - // Cannot be null terminated (normalization won't help us with this one, and - // may have returned false before checking the whole string above) - Debug.Assert(unicode.Length >= 1, "[IdnMapping.GetAscii]Expected 0 length strings to fail before now."); - if (unicode[unicode.Length - 1] <= 0x1f) - { - throw new ArgumentException( - Environment.GetResourceString("Argument_InvalidCharSequence", unicode.Length - 1), - nameof(unicode)); - } - - // Have to correctly IDNA normalize the string and Unassigned flags - bool bHasLastDot = (unicode.Length > 0) && IsDot(unicode[unicode.Length - 1]); - unicode = unicode.Normalize((NormalizationForm)(m_bAllowUnassigned ? - ExtendedNormalizationForms.FormIdna : ExtendedNormalizationForms.FormIdnaDisallowUnassigned)); - - // Make sure we didn't normalize away something after a last dot - if ((!bHasLastDot) && unicode.Length > 0 && IsDot(unicode[unicode.Length - 1])) - { - throw new ArgumentException(Environment.GetResourceString( - "Argument_IdnBadLabelSize"), nameof(unicode)); - } - - // May need to check Std3 rules again for non-ascii - if (UseStd3AsciiRules) + if (count == 0) { - ValidateStd3AndAscii(unicode, true, false); + throw new ArgumentException(SR.Argument_IdnBadLabelSize, nameof(unicode)); } - - // Go ahead and encode it - return punycode_encode(unicode); - } - - - private String GetAsciiUsingOS(String unicode) - { - if (unicode.Length == 0) - { - throw new ArgumentException(Environment.GetResourceString( - "Argument_IdnBadLabelSize"), nameof(unicode)); - } - - if (unicode[unicode.Length - 1] == 0) + if (unicode[index + count - 1] == 0) { - throw new ArgumentException( - Environment.GetResourceString("Argument_InvalidCharSequence", unicode.Length - 1), - nameof(unicode)); + throw new ArgumentException(SR.Format(SR.Argument_InvalidCharSequence, index + count - 1), nameof(unicode)); } - uint flags = (uint)((AllowUnassigned ? IDN_ALLOW_UNASSIGNED : 0) | (UseStd3AsciiRules ? IDN_USE_STD3_ASCII_RULES : 0)); - int length = IdnToAscii(flags, unicode, unicode.Length, null, 0); - - int lastError; - - if (length == 0) + unsafe { - lastError = Marshal.GetLastWin32Error(); - if (lastError == ERROR_INVALID_NAME) + fixed (char* pUnicode = unicode) { - throw new ArgumentException(Environment.GetResourceString("Argument_IdnIllegalName"), nameof(unicode)); + return GetAsciiCore(pUnicode + index, count); } - - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidCharSequenceNoIndex"), nameof(unicode)); } - - char[] output = new char[length]; - - length = IdnToAscii(flags, unicode, unicode.Length, output, length); - if (length == 0) - { - lastError = Marshal.GetLastWin32Error(); - if (lastError == ERROR_INVALID_NAME) - { - throw new ArgumentException(Environment.GetResourceString("Argument_IdnIllegalName"), nameof(unicode)); - } - - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidCharSequenceNoIndex"), nameof(unicode)); - } - - return new String(output, 0, length); } // Gets Unicode version of the string. Normalized and limited to IDNA characters. - public String GetUnicode(String ascii) + public string GetUnicode(string ascii) { return GetUnicode(ascii, 0); } - public String GetUnicode(String ascii, int index) + public string GetUnicode(string ascii, int index) { - if (ascii == null) throw new ArgumentNullException(nameof(ascii)); + if (ascii == null) + throw new ArgumentNullException(nameof(ascii)); Contract.EndContractBlock(); return GetUnicode(ascii, index, ascii.Length - index); } - public String GetUnicode(String ascii, int index, int count) + public string GetUnicode(string ascii, int index, int count) { - if (ascii == null) throw new ArgumentNullException(nameof(ascii)); + if (ascii == null) + throw new ArgumentNullException(nameof(ascii)); if (index < 0 || count < 0) - throw new ArgumentOutOfRangeException((index < 0) ? nameof(index) : nameof(count), - Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException((index < 0) ? nameof(index) : nameof(count), SR.ArgumentOutOfRange_NeedNonNegNum); if (index > ascii.Length) - throw new ArgumentOutOfRangeException("byteIndex", - Environment.GetResourceString("ArgumentOutOfRange_Index")); + throw new ArgumentOutOfRangeException(nameof(index), SR.ArgumentOutOfRange_Index); if (index > ascii.Length - count) - throw new ArgumentOutOfRangeException(nameof(ascii), - Environment.GetResourceString("ArgumentOutOfRange_IndexCountBuffer")); + throw new ArgumentOutOfRangeException(nameof(ascii), SR.ArgumentOutOfRange_IndexCountBuffer); // This is a case (i.e. explicitly null-terminated input) where behavior in .NET and Win32 intentionally differ. // The .NET APIs should (and did in v4.0 and earlier) throw an ArgumentException on input that includes a terminating null. // The Win32 APIs fail on an embedded null, but not on a terminating null. if (count > 0 && ascii[index + count - 1] == (char)0) - throw new ArgumentException(Environment.GetResourceString("Argument_IdnBadPunycode"), - nameof(ascii)); + throw new ArgumentException(SR.Argument_IdnBadPunycode, nameof(ascii)); Contract.EndContractBlock(); - // We're only using part of the string - ascii = ascii.Substring(index, count); - - if (Environment.IsWindows8OrAbove) + unsafe { - return GetUnicodeUsingOS(ascii); - } - - // Convert Punycode to Unicode - String strUnicode = punycode_decode(ascii); - - // Output name MUST obey IDNA rules & round trip (casing differences are allowed) - if (!ascii.Equals(GetAscii(strUnicode), StringComparison.OrdinalIgnoreCase)) - throw new ArgumentException(Environment.GetResourceString( - "Argument_IdnIllegalName"), nameof(ascii)); - - return strUnicode; - } - - - private string GetUnicodeUsingOS(string ascii) - { - uint flags = (uint)((AllowUnassigned ? IDN_ALLOW_UNASSIGNED : 0) | (UseStd3AsciiRules ? IDN_USE_STD3_ASCII_RULES : 0)); - int length = IdnToUnicode(flags, ascii, ascii.Length, null, 0); - int lastError; - - if (length == 0) - { - lastError = Marshal.GetLastWin32Error(); - if (lastError == ERROR_INVALID_NAME) + fixed (char* pAscii = ascii) { - throw new ArgumentException(Environment.GetResourceString("Argument_IdnIllegalName"), nameof(ascii)); + return GetUnicodeCore(pAscii + index, count); } - - throw new ArgumentException(Environment.GetResourceString("Argument_IdnBadPunycode"), nameof(ascii)); } - - char[] output = new char[length]; - - length = IdnToUnicode(flags, ascii, ascii.Length, output, length); - if (length == 0) - { - lastError = Marshal.GetLastWin32Error(); - if (lastError == ERROR_INVALID_NAME) - { - throw new ArgumentException(Environment.GetResourceString("Argument_IdnIllegalName"), nameof(ascii)); - } - - throw new ArgumentException(Environment.GetResourceString("Argument_IdnBadPunycode"), nameof(ascii)); - } - - return new String(output, 0, length); } - public override bool Equals(Object obj) + public override bool Equals(object obj) { IdnMapping that = obj as IdnMapping; - - if (that != null) - { - return m_bAllowUnassigned == that.m_bAllowUnassigned && - m_bUseStd3AsciiRules == that.m_bUseStd3AsciiRules; - } - - return (false); + return + that != null && + _allowUnassigned == that._allowUnassigned && + _useStd3AsciiRules == that._useStd3AsciiRules; } public override int GetHashCode() { - return (m_bAllowUnassigned ? 100 : 200) + (m_bUseStd3AsciiRules ? 1000 : 2000); - } - - // Helpers - private static bool IsSupplementary(int cTest) - { - return cTest >= 0x10000; - } - - // Is it a dot? - // are we U+002E (., full stop), U+3002 (ideographic full stop), U+FF0E (fullwidth full stop), or - // U+FF61 (halfwidth ideographic full stop). - // Note: IDNA Normalization gets rid of dots now, but testing for last dot is before normalization - private static bool IsDot(char c) - { - return c == '.' || c == '\u3002' || c == '\uFF0E' || c == '\uFF61'; - } - - - // See if we're only ASCII - private static bool ValidateStd3AndAscii(string unicode, bool bUseStd3, bool bCheckAscii) - { - // If its empty, then its too small - if (unicode.Length == 0) - throw new ArgumentException(Environment.GetResourceString( - "Argument_IdnBadLabelSize"), nameof(unicode)); - Contract.EndContractBlock(); - - int iLastDot = -1; - - // Loop the whole string - for (int i = 0; i < unicode.Length; i++) - { - // Aren't allowing control chars (or 7f, but idn tables catch that, they don't catch \0 at end though) - if (unicode[i] <= 0x1f) - { - throw new ArgumentException( - Environment.GetResourceString("Argument_InvalidCharSequence", i), - nameof(unicode)); - } - - // If its Unicode or a control character, return false (non-ascii) - if (bCheckAscii && unicode[i] >= 0x7f) - return false; - - // Check for dots - if (IsDot(unicode[i])) - { - // Can't have 2 dots in a row - if (i == iLastDot + 1) - throw new ArgumentException(Environment.GetResourceString( - "Argument_IdnBadLabelSize"), nameof(unicode)); - - // If its too far between dots then fail - if (i - iLastDot > M_labelLimit + 1) - throw new ArgumentException(Environment.GetResourceString( - "Argument_IdnBadLabelSize"), nameof(unicode)); - - // If validating Std3, then char before dot can't be - char - if (bUseStd3 && i > 0) - ValidateStd3(unicode[i - 1], true); - - // Remember where the last dot is - iLastDot = i; - continue; - } - - // If necessary, make sure its a valid std3 character - if (bUseStd3) - { - ValidateStd3(unicode[i], (i == iLastDot + 1)); - } - } - - // If we never had a dot, then we need to be shorter than the label limit - if (iLastDot == -1 && unicode.Length > M_labelLimit) - throw new ArgumentException(Environment.GetResourceString( - "Argument_IdnBadLabelSize"), nameof(unicode)); - - // Need to validate entire string length, 1 shorter if last char wasn't a dot - if (unicode.Length > M_defaultNameLimit - (IsDot(unicode[unicode.Length - 1]) ? 0 : 1)) - throw new ArgumentException(Environment.GetResourceString( - "Argument_IdnBadNameSize", - M_defaultNameLimit - (IsDot(unicode[unicode.Length - 1]) ? 0 : 1)), - nameof(unicode)); - - // If last char wasn't a dot we need to check for trailing - - if (bUseStd3 && !IsDot(unicode[unicode.Length - 1])) - ValidateStd3(unicode[unicode.Length - 1], true); - - return true; - } - - // Validate Std3 rules for a character - private static void ValidateStd3(char c, bool bNextToDot) - { - // Check for illegal characters - if ((c <= ',' || c == '/' || (c >= ':' && c <= '@') || // Lots of characters not allowed - (c >= '[' && c <= '`') || (c >= '{' && c <= (char)0x7F)) || - (c == '-' && bNextToDot)) - throw new ArgumentException(Environment.GetResourceString( - "Argument_IdnBadStd3", c), "Unicode"); - } - - // - // The following punycode implementation is ported from the sample punycode.c in RFC 3492 - // Original sample code was written by Adam M. Costello. - // - - // Return whether a punycode code point is flagged as being upper case. - - private static bool HasUpperCaseFlag(char punychar) - { - return (punychar >= 'A' && punychar <= 'Z'); - } - - - /**********************************************************/ - /* Implementation (would normally go in its own .c file): */ - - /*** Bootstring parameters for Punycode ***/ - private const int punycodeBase = 36; - private const int tmin = 1; - private const int tmax = 26; - private const int skew = 38; - private const int damp = 700; - private const int initial_bias = 72; - private const int initial_n = 0x80; - private const char delimiter = '-'; - - /* basic(cp) tests whether cp is a basic code point: */ - private static bool basic(uint cp) - { - // Is it in ASCII range? - return cp < 0x80; - } - - // decode_digit(cp) returns the numeric value of a basic code */ - // point (for use in representing integers) in the range 0 to */ - // punycodeBase-1, or <0 if cp is does not represent a value. */ - - private static int decode_digit(char cp) - { - if (cp >= '0' && cp <= '9') - return cp - '0' + 26; - - // Two flavors for case differences - if (cp >= 'a' && cp <= 'z') - return cp - 'a'; - - if (cp >= 'A' && cp <= 'Z') - return cp - 'A'; - - // Expected 0-9, A-Z or a-z, everything else is illegal - throw new ArgumentException(Environment.GetResourceString( - "Argument_IdnBadPunycode"), "ascii"); - } - - /* encode_digit(d,flag) returns the basic code point whose value */ - /* (when used for representing integers) is d, which needs to be in */ - /* the range 0 to punycodeBase-1. The lowercase form is used unless flag is */ - /* true, in which case the uppercase form is used. */ - - private static char encode_digit(int d) - { - Debug.Assert(d >= 0 && d < punycodeBase, "[IdnMapping.encode_digit]Expected 0 <= d < punycodeBase"); - // 26-35 map to ASCII 0-9 - if (d > 25) return (char)(d - 26 + '0'); - - // 0-25 map to a-z or A-Z - return (char)(d + 'a'); - } - - - - /* encode_basic(bcp,flag) forces a basic code point to lowercase */ - /* if flag is false, uppercase if flag is true, and returns */ - /* the resulting code point. The code point is unchanged if it */ - /* is caseless. The behavior is undefined if bcp is not a basic */ - /* code point. */ - - private static char encode_basic(char bcp) - { - if (HasUpperCaseFlag(bcp)) - bcp += (char)('a' - 'A'); - - return bcp; - } - - /*** Platform-specific constants ***/ - - /* maxint is the maximum value of a uint variable: */ - private const int maxint = 0x7ffffff; - - /*** Bias adaptation function ***/ - - private static int adapt( - int delta, int numpoints, bool firsttime) - { - uint k; - - delta = firsttime ? delta / damp : delta / 2; - Debug.Assert(numpoints != 0, "[IdnMapping.adapt]Expected non-zero numpoints."); - delta += delta / numpoints; - - for (k = 0; delta > ((punycodeBase - tmin) * tmax) / 2; k += punycodeBase) - { - delta /= punycodeBase - tmin; - } - - Debug.Assert(delta + skew != 0, "[IdnMapping.adapt]Expected non-zero delta+skew."); - return (int)(k + (punycodeBase - tmin + 1) * delta / (delta + skew)); - } - - /*** Main encode function ***/ - - /* punycode_encode() converts Unicode to Punycode. The input */ - /* is represented as an array of Unicode code points (not code */ - /* units; surrogate pairs are not allowed), and the output */ - /* will be represented as an array of ASCII code points. The */ - /* output string is *not* null-terminated; it will contain */ - /* zeros if and only if the input contains zeros. (Of course */ - /* the caller can leave room for a terminator and add one if */ - /* needed.) The input_length is the number of code points in */ - /* the input. The output_length is an in/out argument: the */ - /* caller passes in the maximum number of code points that it */ - - /* can receive, and on successful return it will contain the */ - /* number of code points actually output. The case_flags array */ - /* holds input_length boolean values, where nonzero suggests that */ - /* the corresponding Unicode character be forced to uppercase */ - /* after being decoded (if possible), and zero suggests that */ - /* it be forced to lowercase (if possible). ASCII code points */ - /* are encoded literally, except that ASCII letters are forced */ - /* to uppercase or lowercase according to the corresponding */ - /* uppercase flags. If case_flags is a null pointer then ASCII */ - /* letters are left as they are, and other code points are */ - /* treated as if their uppercase flags were zero. The return */ - /* value can be any of the punycode_status values defined above */ - /* except punycode_bad_input; if not punycode_success, then */ - /* output_size and output might contain garbage. */ - - private static String punycode_encode(String unicode) - { - // 0 length strings aren't allowed - if (unicode.Length == 0) - throw new ArgumentException(Environment.GetResourceString( - "Argument_IdnBadLabelSize"), nameof(unicode)); - Contract.EndContractBlock(); - - StringBuilder output = new StringBuilder(unicode.Length); - int iNextDot = 0; - int iAfterLastDot = 0; - int iOutputAfterLastDot = 0; - - // Find the next dot - while (iNextDot < unicode.Length) - { - // Find end of this segment - iNextDot = unicode.IndexOfAny(M_Dots, iAfterLastDot); - Debug.Assert(iNextDot <= unicode.Length, "[IdnMapping.punycode_encode]IndexOfAny is broken"); - if (iNextDot < 0) - iNextDot = unicode.Length; - - // Only allowed to have empty . section at end (www.microsoft.com.) - if (iNextDot == iAfterLastDot) - { - // Only allowed to have empty sections as trailing . - if (iNextDot != unicode.Length) - throw new ArgumentException(Environment.GetResourceString( - "Argument_IdnBadLabelSize"), nameof(unicode)); - // Last dot, stop - break; - } - - // We'll need an Ace prefix - output.Append(M_strAcePrefix); - - // Everything resets every segment. - bool bRightToLeft = false; - - // Check for RTL. If right-to-left, then 1st & last chars must be RTL - BidiCategory eBidi = CharUnicodeInfo.GetBidiCategory(unicode, iAfterLastDot); - if (eBidi == BidiCategory.RightToLeft || eBidi == BidiCategory.RightToLeftArabic) - { - // It has to be right to left. - bRightToLeft = true; - - // Check last char - int iTest = iNextDot - 1; - if (Char.IsLowSurrogate(unicode, iTest)) - { - iTest--; - } - - eBidi = CharUnicodeInfo.GetBidiCategory(unicode, iTest); - if (eBidi != BidiCategory.RightToLeft && eBidi != BidiCategory.RightToLeftArabic) - { - // Oops, last wasn't RTL, last should be RTL if first is RTL - throw new ArgumentException(Environment.GetResourceString( - "Argument_IdnBadBidi"), nameof(unicode)); - } - } - - // Handle the basic code points - int basicCount; - int numProcessed = 0; // Num code points that have been processed so far (this segment) - for (basicCount = iAfterLastDot; basicCount < iNextDot; basicCount++) - { - // Can't be lonely surrogate because it would've thrown in normalization - Debug.Assert(Char.IsLowSurrogate(unicode, basicCount) == false, - "[IdnMapping.punycode_encode]Unexpected low surrogate"); - - // Double check our bidi rules - BidiCategory testBidi = CharUnicodeInfo.GetBidiCategory(unicode, basicCount); - - // If we're RTL, we can't have LTR chars - if (bRightToLeft && testBidi == BidiCategory.LeftToRight) - { - // Oops, throw error - throw new ArgumentException(Environment.GetResourceString( - "Argument_IdnBadBidi"), nameof(unicode)); - } - - // If we're not RTL we can't have RTL chars - if (!bRightToLeft && (testBidi == BidiCategory.RightToLeft || - testBidi == BidiCategory.RightToLeftArabic)) - { - // Oops, throw error - throw new ArgumentException(Environment.GetResourceString( - "Argument_IdnBadBidi"), nameof(unicode)); - } - - // If its basic then add it - if (basic(unicode[basicCount])) - { - output.Append(encode_basic(unicode[basicCount])); - numProcessed++; - } - // If its a surrogate, skip the next since our bidi category tester doesn't handle it. - else if (Char.IsSurrogatePair(unicode, basicCount)) - basicCount++; - } - - int numBasicCodePoints = numProcessed; // number of basic code points - - // Stop if we ONLY had basic code points - if (numBasicCodePoints == iNextDot - iAfterLastDot) - { - // Get rid of xn-- and this segments done - output.Remove(iOutputAfterLastDot, M_strAcePrefix.Length); - } - else - { - // If it has some non-basic code points the input cannot start with xn-- - if (unicode.Length - iAfterLastDot >= M_strAcePrefix.Length && - unicode.Substring(iAfterLastDot, M_strAcePrefix.Length).Equals( - M_strAcePrefix, StringComparison.OrdinalIgnoreCase)) - throw new ArgumentException(Environment.GetResourceString( - "Argument_IdnBadPunycode"), nameof(unicode)); - - // Need to do ACE encoding - int numSurrogatePairs = 0; // number of surrogate pairs so far - - // Add a delimiter (-) if we had any basic code points (between basic and encoded pieces) - if (numBasicCodePoints > 0) - { - output.Append(delimiter); - } - - // Initialize the state - int n = initial_n; - int delta = 0; - int bias = initial_bias; - - // Main loop - while (numProcessed < (iNextDot - iAfterLastDot)) - { - /* All non-basic code points < n have been */ - /* handled already. Find the next larger one: */ - int j; - int m; - int test = 0; - for (m = maxint, j = iAfterLastDot; - j < iNextDot; - j += IsSupplementary(test) ? 2 : 1) - { - test = Char.ConvertToUtf32(unicode, j); - if (test >= n && test < m) m = test; - } - - /* Increase delta enough to advance the decoder's */ - /* state to , but guard against overflow: */ - delta += (int)((m - n) * ((numProcessed - numSurrogatePairs) + 1)); - Debug.Assert(delta > 0, "[IdnMapping.cs]1 punycode_encode - delta overflowed int"); - n = m; - - for (j = iAfterLastDot; j < iNextDot; j += IsSupplementary(test) ? 2 : 1) - { - // Make sure we're aware of surrogates - test = Char.ConvertToUtf32(unicode, j); - - // Adjust for character position (only the chars in our string already, some - // haven't been processed. - - if (test < n) - { - delta++; - Debug.Assert(delta > 0, "[IdnMapping.cs]2 punycode_encode - delta overflowed int"); - } - - if (test == n) - { - // Represent delta as a generalized variable-length integer: - int q, k; - for (q = delta, k = punycodeBase; ; k += punycodeBase) - { - int t = k <= bias ? tmin : - k >= bias + tmax ? tmax : k - bias; - if (q < t) break; - Debug.Assert(punycodeBase != t, "[IdnMapping.punycode_encode]Expected punycodeBase (36) to be != t"); - - int mod; - q = Math.DivRem(q - t, punycodeBase - t, out mod); - output.Append(encode_digit(t + mod)); - } - - output.Append(encode_digit(q)); - bias = adapt(delta, (numProcessed - numSurrogatePairs) + 1, numProcessed == numBasicCodePoints); - delta = 0; - numProcessed++; - - if (IsSupplementary(m)) - { - numProcessed++; - numSurrogatePairs++; - } - } - } - ++delta; - ++n; - Debug.Assert(delta > 0, "[IdnMapping.cs]3 punycode_encode - delta overflowed int"); - } - } - - // Make sure its not too big - if (output.Length - iOutputAfterLastDot > M_labelLimit) - throw new ArgumentException(Environment.GetResourceString( - "Argument_IdnBadLabelSize"), nameof(unicode)); - - // Done with this segment, add dot if necessary - if (iNextDot != unicode.Length) - output.Append('.'); - - iAfterLastDot = iNextDot + 1; - iOutputAfterLastDot = output.Length; - } - - // Throw if we're too long - if (output.Length > M_defaultNameLimit - (IsDot(unicode[unicode.Length - 1]) ? 0 : 1)) - throw new ArgumentException(Environment.GetResourceString( - "Argument_IdnBadNameSize", - M_defaultNameLimit - (IsDot(unicode[unicode.Length - 1]) ? 0 : 1)), - nameof(unicode)); - - // Return our output string - return output.ToString(); + return (_allowUnassigned ? 100 : 200) + (_useStd3AsciiRules ? 1000 : 2000); } - - /*** Main decode function ***/ - - /* punycode_decode() converts Punycode to Unicode. The input is */ - /* represented as an array of ASCII code points, and the output */ - /* will be represented as an array of Unicode code points. The */ - /* input_length is the number of code points in the input. The */ - /* output_length is an in/out argument: the caller passes in */ - /* the maximum number of code points that it can receive, and */ - /* on successful return it will contain the actual number of */ - /* code points output. The case_flags array needs room for at */ - /* least output_length values, or it can be a null pointer if the */ - /* case information is not needed. A nonzero flag suggests that */ - /* the corresponding Unicode character be forced to uppercase */ - /* by the caller (if possible), while zero suggests that it be */ - /* forced to lowercase (if possible). ASCII code points are */ - /* output already in the proper case, but their flags will be set */ - /* appropriately so that applying the flags would be harmless. */ - /* The return value can be any of the punycode_status values */ - /* defined above; if not punycode_success, then output_length, */ - /* output, and case_flags might contain garbage. On success, the */ - /* decoder will never need to write an output_length greater than */ - /* input_length, because of how the encoding is defined. */ - - private static String punycode_decode(String ascii) - { - // 0 length strings aren't allowed - if (ascii.Length == 0) - throw new ArgumentException(Environment.GetResourceString( - "Argument_IdnBadLabelSize"), nameof(ascii)); - Contract.EndContractBlock(); - - // Throw if we're too long - if (ascii.Length > M_defaultNameLimit - (IsDot(ascii[ascii.Length - 1]) ? 0 : 1)) - throw new ArgumentException(Environment.GetResourceString( - "Argument_IdnBadNameSize", - M_defaultNameLimit - (IsDot(ascii[ascii.Length - 1]) ? 0 : 1)), nameof(ascii)); - - // output stringbuilder - StringBuilder output = new StringBuilder(ascii.Length); - - // Dot searching - int iNextDot = 0; - int iAfterLastDot = 0; - int iOutputAfterLastDot = 0; - - while (iNextDot < ascii.Length) - { - // Find end of this segment - iNextDot = ascii.IndexOf('.', iAfterLastDot); - if (iNextDot < 0 || iNextDot > ascii.Length) - iNextDot = ascii.Length; - - // Only allowed to have empty . section at end (www.microsoft.com.) - if (iNextDot == iAfterLastDot) - { - // Only allowed to have empty sections as trailing . - if (iNextDot != ascii.Length) - throw new ArgumentException(Environment.GetResourceString( - "Argument_IdnBadLabelSize"), nameof(ascii)); - - // Last dot, stop - break; - } - - // In either case it can't be bigger than segment size - if (iNextDot - iAfterLastDot > M_labelLimit) - throw new ArgumentException(Environment.GetResourceString( - "Argument_IdnBadLabelSize"), nameof(ascii)); - - // See if this section's ASCII or ACE - if (ascii.Length < M_strAcePrefix.Length + iAfterLastDot || - !ascii.Substring(iAfterLastDot, M_strAcePrefix.Length).Equals( - M_strAcePrefix, StringComparison.OrdinalIgnoreCase)) - { - // Its supposed to be just ASCII - // Actually, for non xn-- stuff do we want to allow Unicode? - // for (int i = iAfterLastDot; i < iNextDot; i++) - // { - // // Only ASCII is allowed - // if (ascii[i] >= 0x80) - // throw new ArgumentException(Environment.GetResourceString( - // "Argument_IdnBadPunycode"), nameof(ascii)); - // } - - // Its ASCII, copy it - output.Append(ascii.Substring(iAfterLastDot, iNextDot - iAfterLastDot)); - - // ASCII doesn't have BIDI issues - } - else - { - // Not ASCII, bump up iAfterLastDot to be after ACE Prefix - iAfterLastDot += M_strAcePrefix.Length; - - // Get number of basic code points (where delimiter is) - // numBasicCodePoints < 0 if there're no basic code points - int iTemp = ascii.LastIndexOf(delimiter, iNextDot - 1); - - // Trailing - not allowed - if (iTemp == iNextDot - 1) - throw new ArgumentException(Environment.GetResourceString( - "Argument_IdnBadPunycode"), nameof(ascii)); - - int numBasicCodePoints; - if (iTemp <= iAfterLastDot) - numBasicCodePoints = 0; - else - { - numBasicCodePoints = iTemp - iAfterLastDot; - - // Copy all the basic code points, making sure they're all in the allowed range, - // and losing the casing for all of them. - for (int copyAscii = iAfterLastDot; - copyAscii < iAfterLastDot + numBasicCodePoints; - copyAscii++) - { - // Make sure we don't allow unicode in the ascii part - if (ascii[copyAscii] > 0x7f) - throw new ArgumentException(Environment.GetResourceString( - "Argument_IdnBadPunycode"), nameof(ascii)); - - // When appending make sure they get lower cased - output.Append((char)(ascii[copyAscii] >= 'A' && ascii[copyAscii] <= 'Z' ? - ascii[copyAscii] - 'A' + 'a' : - ascii[copyAscii])); - } - } - - // Get ready for main loop. Start at beginning if we didn't have any - // basic code points, otherwise start after the -. - // asciiIndex will be next character to read from ascii - int asciiIndex = iAfterLastDot + - (numBasicCodePoints > 0 ? numBasicCodePoints + 1 : 0); - - // initialize our state - int n = initial_n; - int bias = initial_bias; - int i = 0; - - int w, k; - - // no Supplementary characters yet - int numSurrogatePairs = 0; - - // Main loop, read rest of ascii - while (asciiIndex < iNextDot) - { - /* Decode a generalized variable-length integer into delta, */ - /* which gets added to i. The overflow checking is easier */ - /* if we increase i as we go, then subtract off its starting */ - /* value at the end to obtain delta. */ - int oldi = i; - - for (w = 1, k = punycodeBase; ; k += punycodeBase) - { - // Check to make sure we aren't overrunning our ascii string - if (asciiIndex >= iNextDot) - throw new ArgumentException(Environment.GetResourceString( - "Argument_IdnBadPunycode"), nameof(ascii)); - - // decode the digit from the next char - int digit = decode_digit(ascii[asciiIndex++]); - - Debug.Assert(w > 0, "[IdnMapping.punycode_decode]Expected w > 0"); - if (digit > (maxint - i) / w) - throw new ArgumentException(Environment.GetResourceString( - "Argument_IdnBadPunycode"), nameof(ascii)); - - i += (int)(digit * w); - int t = k <= bias ? tmin : - k >= bias + tmax ? tmax : k - bias; - if (digit < t) break; - Debug.Assert(punycodeBase != t, "[IdnMapping.punycode_decode]Expected t != punycodeBase (36)"); - if (w > maxint / (punycodeBase - t)) - throw new ArgumentException(Environment.GetResourceString( - "Argument_IdnBadPunycode"), nameof(ascii)); - w *= (punycodeBase - t); - } - - bias = adapt(i - oldi, - (output.Length - iOutputAfterLastDot - numSurrogatePairs) + 1, oldi == 0); - - /* i was supposed to wrap around from output.Length to 0, */ - /* incrementing n each time, so we'll fix that now: */ - Debug.Assert((output.Length - iOutputAfterLastDot - numSurrogatePairs) + 1 > 0, - "[IdnMapping.punycode_decode]Expected to have added > 0 characters this segment"); - if (i / ((output.Length - iOutputAfterLastDot - numSurrogatePairs) + 1) > maxint - n) - throw new ArgumentException(Environment.GetResourceString( - "Argument_IdnBadPunycode"), nameof(ascii)); - n += (int)(i / (output.Length - iOutputAfterLastDot - numSurrogatePairs + 1)); - i %= (output.Length - iOutputAfterLastDot - numSurrogatePairs + 1); - - // If it was flagged it needs to be capitalized - // if (HasUpperCaseFlag(ascii[asciiIndex - 1])) - // { - // /* Case of last character determines uppercase flag: */ - // // Any casing stuff need to happen last. - // If we wanted to reverse the IDNA casing data - // n = MakeNUpperCase(n) - // } - - // Make sure n is legal - if ((n < 0 || n > 0x10ffff) || (n >= 0xD800 && n <= 0xDFFF)) - throw new ArgumentException(Environment.GetResourceString( - "Argument_IdnBadPunycode"), nameof(ascii)); - - // insert n at position i of the output: Really tricky if we have surrogates - int iUseInsertLocation; - String strTemp = Char.ConvertFromUtf32(n); - - // If we have supplimentary characters - if (numSurrogatePairs > 0) - { - // Hard way, we have supplimentary characters - int iCount; - for (iCount = i, iUseInsertLocation = iOutputAfterLastDot; - iCount > 0; - iCount--, iUseInsertLocation++) - { - // If its a surrogate, we have to go one more - if (iUseInsertLocation >= output.Length) - throw new ArgumentException(Environment.GetResourceString( - "Argument_IdnBadPunycode"), nameof(ascii)); - if (Char.IsSurrogate(output[iUseInsertLocation])) - iUseInsertLocation++; - } - } - else - { - // No Supplementary chars yet, just add i - iUseInsertLocation = iOutputAfterLastDot + i; - } - - // Insert it - output.Insert(iUseInsertLocation, strTemp); - - // If it was a surrogate increment our counter - if (IsSupplementary(n)) - numSurrogatePairs++; - - // Index gets updated - i++; - } - - // Do BIDI testing - bool bRightToLeft = false; - - // Check for RTL. If right-to-left, then 1st & last chars must be RTL - BidiCategory eBidi = CharUnicodeInfo.GetBidiCategory(output.ToString(), iOutputAfterLastDot); - if (eBidi == BidiCategory.RightToLeft || eBidi == BidiCategory.RightToLeftArabic) - { - // It has to be right to left. - bRightToLeft = true; - } - - // Check the rest of them to make sure RTL/LTR is consistent - for (int iTest = iOutputAfterLastDot; iTest < output.Length; iTest++) - { - // This might happen if we run into a pair - if (Char.IsLowSurrogate(output.ToString(), iTest)) continue; - - // Check to see if its LTR - eBidi = CharUnicodeInfo.GetBidiCategory(output.ToString(), iTest); - if ((bRightToLeft && eBidi == BidiCategory.LeftToRight) || - (!bRightToLeft && (eBidi == BidiCategory.RightToLeft || - eBidi == BidiCategory.RightToLeftArabic))) - throw new ArgumentException(Environment.GetResourceString( - "Argument_IdnBadBidi"), nameof(ascii)); - - // Make it lower case if we must (so we can test IsNormalized later) - // if (output[iTest] >= 'A' && output[iTest] <= 'Z') - // output[iTest] = (char)(output[iTest] + (char)('a' - 'A')); - } - - // Its also a requirement that the last one be RTL if 1st is RTL - if (bRightToLeft && eBidi != BidiCategory.RightToLeft && eBidi != BidiCategory.RightToLeftArabic) - { - // Oops, last wasn't RTL, last should be RTL if first is RTL - throw new ArgumentException(Environment.GetResourceString( - "Argument_IdnBadBidi"), nameof(ascii)); - } - } - - // See if this label was too long - if (iNextDot - iAfterLastDot > M_labelLimit) - throw new ArgumentException(Environment.GetResourceString( - "Argument_IdnBadLabelSize"), nameof(ascii)); - - // Done with this segment, add dot if necessary - if (iNextDot != ascii.Length) - output.Append('.'); - - iAfterLastDot = iNextDot + 1; - iOutputAfterLastDot = output.Length; - } - - // Throw if we're too long - if (output.Length > M_defaultNameLimit - (IsDot(output[output.Length - 1]) ? 0 : 1)) - throw new ArgumentException(Environment.GetResourceString( - "Argument_IdnBadNameSize", - M_defaultNameLimit - (IsDot(output[output.Length - 1]) ? 0 : 1)), nameof(ascii)); - - // Return our output string - return output.ToString(); - } - - /* - The previous punycode implimentation is based on the sample code in RFC 3492 - - Full Copyright Statement - - Copyright (C) The Internet Society (2003). All Rights Reserved. - - This document and translations of it may be copied and furnished to - others, and derivative works that comment on or otherwise explain it - or assist in its implementation may be prepared, copied, published - and distributed, in whole or in part, without restriction of any - kind, provided that the above copyright notice and this paragraph are - included on all such copies and derivative works. However, this - document itself may not be modified in any way, such as by removing - the copyright notice or references to the Internet Society or other - Internet organizations, except as needed for the purpose of - developing Internet standards in which case the procedures for - copyrights defined in the Internet Standards process must be - followed, or as required to translate it into languages other than - English. - - The limited permissions granted above are perpetual and will not be - revoked by the Internet Society or its successors or assigns. - - This document and the information contained herein is provided on an - "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING - TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING - BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION - HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF - MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - */ - - - private const int IDN_ALLOW_UNASSIGNED = 0x1; - private const int IDN_USE_STD3_ASCII_RULES = 0x2; - - private const int ERROR_INVALID_NAME = 123; - - - [SuppressUnmanagedCodeSecurityAttribute()] - [DllImport("normaliz.dll", CharSet = CharSet.Unicode, SetLastError = true)] - private static extern int IdnToAscii( - uint dwFlags, - [InAttribute()] - [MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPWStr)] - String lpUnicodeCharStr, - int cchUnicodeChar, - [System.Runtime.InteropServices.OutAttribute()] - - char [] lpASCIICharStr, - int cchASCIIChar); - - [SuppressUnmanagedCodeSecurityAttribute()] - [DllImport("normaliz.dll", CharSet = CharSet.Unicode, SetLastError = true)] - private static extern int IdnToUnicode( - uint dwFlags, - [InAttribute()] - [MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPWStr)] - string lpASCIICharStr, - int cchASCIIChar, - [System.Runtime.InteropServices.OutAttribute()] - - char [] lpUnicodeCharStr, - int cchUnicodeChar); } } - diff --git a/src/mscorlib/corefx/System/Globalization/InternalGlobalizationHelper.cs b/src/mscorlib/src/System/Globalization/InternalGlobalizationHelper.cs similarity index 100% rename from src/mscorlib/corefx/System/Globalization/InternalGlobalizationHelper.cs rename to src/mscorlib/src/System/Globalization/InternalGlobalizationHelper.cs diff --git a/src/mscorlib/corefx/System/Globalization/JapaneseCalendar.Unix.cs b/src/mscorlib/src/System/Globalization/JapaneseCalendar.Unix.cs similarity index 100% rename from src/mscorlib/corefx/System/Globalization/JapaneseCalendar.Unix.cs rename to src/mscorlib/src/System/Globalization/JapaneseCalendar.Unix.cs diff --git a/src/mscorlib/corefx/System/Globalization/JapaneseCalendar.Win32.cs b/src/mscorlib/src/System/Globalization/JapaneseCalendar.Win32.cs similarity index 100% rename from src/mscorlib/corefx/System/Globalization/JapaneseCalendar.Win32.cs rename to src/mscorlib/src/System/Globalization/JapaneseCalendar.Win32.cs diff --git a/src/mscorlib/corefx/System/Globalization/JapaneseCalendar.WinRT.cs b/src/mscorlib/src/System/Globalization/JapaneseCalendar.WinRT.cs similarity index 100% rename from src/mscorlib/corefx/System/Globalization/JapaneseCalendar.WinRT.cs rename to src/mscorlib/src/System/Globalization/JapaneseCalendar.WinRT.cs diff --git a/src/mscorlib/src/System/Globalization/JapaneseCalendar.cs b/src/mscorlib/src/System/Globalization/JapaneseCalendar.cs index 82be6a5..f0216c8 100644 --- a/src/mscorlib/src/System/Globalization/JapaneseCalendar.cs +++ b/src/mscorlib/src/System/Globalization/JapaneseCalendar.cs @@ -2,13 +2,13 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Diagnostics.Contracts; + namespace System.Globalization { - using System; - using System.Diagnostics.CodeAnalysis; - using System.Diagnostics.Contracts; - using Microsoft.Win32; - /*=================================JapaneseCalendar========================== ** ** JapaneseCalendar is based on Gregorian calendar. The month and day values are the same as @@ -39,7 +39,7 @@ namespace System.Globalization [Serializable] - public class JapaneseCalendar : Calendar + public partial class JapaneseCalendar : Calendar { internal static readonly DateTime calendarMinValue = new DateTime(1868, 9, 8); @@ -60,9 +60,6 @@ namespace System.Globalization } } - // Return the type of the Japanese calendar. - // - public override CalendarAlgorithmType AlgorithmType { get @@ -74,7 +71,7 @@ namespace System.Globalization // // Using a field initializer rather than a static constructor so that the whole class can be lazy // init. - static internal volatile EraInfo[] japaneseEraInfo; + internal static volatile EraInfo[] japaneseEraInfo; // // Read our era info @@ -85,6 +82,7 @@ namespace System.Globalization // // We know about 4 built-in eras, however users may add additional era(s) from the // registry, by adding values to HKLM\SYSTEM\CurrentControlSet\Control\Nls\Calendars\Japanese\Eras + // we don't read the registry and instead we call WinRT to get the needed informatio // // Registry values look like: // yyyy.mm.dd=era_abbrev_english_englishabbrev @@ -104,9 +102,7 @@ namespace System.Globalization // See if we need to build it if (japaneseEraInfo == null) { - // See if we have any eras from the registry - japaneseEraInfo = GetErasFromRegistry(); - + japaneseEraInfo = GetJapaneseEras(); // See if we have to use the built-in eras if (japaneseEraInfo == null) { @@ -130,202 +126,6 @@ namespace System.Globalization return japaneseEraInfo; } - -#if FEATURE_WIN32_REGISTRY - private const string c_japaneseErasHive = @"System\CurrentControlSet\Control\Nls\Calendars\Japanese\Eras"; - private const string c_japaneseErasHivePermissionList = @"HKEY_LOCAL_MACHINE\" + c_japaneseErasHive; - - // - // GetErasFromRegistry() - // - // We know about 4 built-in eras, however users may add additional era(s) from the - // registry, by adding values to HKLM\SYSTEM\CurrentControlSet\Control\Nls\Calendars\Japanese\Eras - // - // Registry values look like: - // yyyy.mm.dd=era_abbrev_english_englishabbrev - // - // Where yyyy.mm.dd is the registry value name, and also the date of the era start. - // yyyy, mm, and dd are the year, month & day the era begins (4, 2 & 2 digits long) - // era is the Japanese Era name - // abbrev is the Abbreviated Japanese Era Name - // english is the English name for the Era (unused) - // englishabbrev is the Abbreviated English name for the era. - // . is a delimiter, but the value of . doesn't matter. - // '_' marks the space between the japanese era name, japanese abbreviated era name - // english name, and abbreviated english names. - private static EraInfo[] GetErasFromRegistry() - { - // Look in the registry key and see if we can find any ranges - int iFoundEras = 0; - EraInfo[] registryEraRanges = null; - - try - { - RegistryKey key = Registry.LocalMachine.OpenSubKey(c_japaneseErasHive, writable: false); - - // Abort if we didn't find anything - if (key == null) return null; - - // Look up the values in our reg key - String[] valueNames = key.GetValueNames(); - if (valueNames != null && valueNames.Length > 0) - { - registryEraRanges = new EraInfo[valueNames.Length]; - - // Loop through the registry and read in all the values - for (int i = 0; i < valueNames.Length; i++) - { - // See if the era is a valid date - EraInfo era = GetEraFromValue(valueNames[i], key.GetValue(valueNames[i]).ToString()); - - // continue if not valid - if (era == null) continue; - - // Remember we found one. - registryEraRanges[iFoundEras] = era; - iFoundEras++; - } - } - } - catch (System.Security.SecurityException) - { - // If we weren't allowed to read, then just ignore the error - return null; - } - catch (System.IO.IOException) - { - // If key is being deleted just ignore the error - return null; - } - catch (System.UnauthorizedAccessException) - { - // Registry access rights permissions, just ignore the error - return null; - } - - // - // If we didn't have valid eras, then fail - // should have at least 4 eras - // - if (iFoundEras < 4) return null; - - // - // Now we have eras, clean them up. - // - // Clean up array length - Array.Resize(ref registryEraRanges, iFoundEras); - - // Sort them - Array.Sort(registryEraRanges, CompareEraRanges); - - // Clean up era information - for (int i = 0; i < registryEraRanges.Length; i++) - { - // eras count backwards from length to 1 (and are 1 based indexes into string arrays) - registryEraRanges[i].era = registryEraRanges.Length - i; - - // update max era year - if (i == 0) - { - // First range is 'til the end of the calendar - registryEraRanges[0].maxEraYear = GregorianCalendar.MaxYear - registryEraRanges[0].yearOffset; - } - else - { - // Rest are until the next era (remember most recent era is first in array) - registryEraRanges[i].maxEraYear = registryEraRanges[i - 1].yearOffset + 1 - registryEraRanges[i].yearOffset; - } - } - - // Return our ranges - return registryEraRanges; - } -#else - private static EraInfo[] GetErasFromRegistry() - { - return null; - } -#endif - - // - // Compare two era ranges, eg just the ticks - // Remember the era array is supposed to be in reverse chronological order - // - private static int CompareEraRanges(EraInfo a, EraInfo b) - { - return b.ticks.CompareTo(a.ticks); - } - - // - // GetEraFromValue - // - // Parse the registry value name/data pair into an era - // - // Registry values look like: - // yyyy.mm.dd=era_abbrev_english_englishabbrev - // - // Where yyyy.mm.dd is the registry value name, and also the date of the era start. - // yyyy, mm, and dd are the year, month & day the era begins (4, 2 & 2 digits long) - // era is the Japanese Era name - // abbrev is the Abbreviated Japanese Era Name - // english is the English name for the Era (unused) - // englishabbrev is the Abbreviated English name for the era. - // . is a delimiter, but the value of . doesn't matter. - // '_' marks the space between the japanese era name, japanese abbreviated era name - // english name, and abbreviated english names. - private static EraInfo GetEraFromValue(String value, String data) - { - // Need inputs - if (value == null || data == null) return null; - - // - // Get Date - // - // Need exactly 10 characters in name for date - // yyyy.mm.dd although the . can be any character - if (value.Length != 10) return null; - - int year; - int month; - int day; - - if (!Number.TryParseInt32(value.Substring(0, 4), NumberStyles.None, NumberFormatInfo.InvariantInfo, out year) || - !Number.TryParseInt32(value.Substring(5, 2), NumberStyles.None, NumberFormatInfo.InvariantInfo, out month) || - !Number.TryParseInt32(value.Substring(8, 2), NumberStyles.None, NumberFormatInfo.InvariantInfo, out day)) - { - // Couldn't convert integer, fail - return null; - } - - // - // Get Strings - // - // Needs to be a certain length e_a_E_A at least (7 chars, exactly 4 groups) - String[] names = data.Split('_'); - - // Should have exactly 4 parts - // 0 - Era Name - // 1 - Abbreviated Era Name - // 2 - English Era Name - // 3 - Abbreviated English Era Name - if (names.Length != 4) return null; - - // Each part should have data in it - if (names[0].Length == 0 || - names[1].Length == 0 || - names[2].Length == 0 || - names[3].Length == 0) - return null; - - // - // Now we have an era we can build - // Note that the era # and max era year need cleaned up after sorting - // Don't use the full English Era Name (names[2]) - // - return new EraInfo(0, year, month, day, year - 1, 1, 0, - names[0], names[1], names[3]); - } - internal static volatile Calendar s_defaultInstance; internal GregorianCalendarHelper helper; @@ -355,16 +155,16 @@ namespace System.Globalization } catch (ArgumentException e) { - throw new TypeInitializationException(this.GetType().FullName, e); + throw new TypeInitializationException(this.GetType().ToString(), e); } helper = new GregorianCalendarHelper(this, GetEraInfo()); } - internal override int ID + internal override CalendarId ID { get { - return (CAL_JAPAN); + return CalendarId.JAPAN; } } @@ -501,7 +301,7 @@ namespace System.Globalization if (year <= 0) { throw new ArgumentOutOfRangeException(nameof(year), - Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum")); + SR.ArgumentOutOfRange_NeedPosNum); } Contract.EndContractBlock(); @@ -511,7 +311,7 @@ namespace System.Globalization nameof(year), String.Format( CultureInfo.CurrentCulture, - Environment.GetResourceString("ArgumentOutOfRange_Range"), + SR.ArgumentOutOfRange_Range, 1, helper.MaxYear)); } @@ -600,7 +400,7 @@ namespace System.Globalization "year", String.Format( CultureInfo.CurrentCulture, - Environment.GetResourceString("ArgumentOutOfRange_Range"), + SR.ArgumentOutOfRange_Range, 99, helper.MaxYear)); } diff --git a/src/mscorlib/src/System/Globalization/JapaneseLunisolarCalendar.cs b/src/mscorlib/src/System/Globalization/JapaneseLunisolarCalendar.cs index 7fff27c..cc3d349 100644 --- a/src/mscorlib/src/System/Globalization/JapaneseLunisolarCalendar.cs +++ b/src/mscorlib/src/System/Globalization/JapaneseLunisolarCalendar.cs @@ -70,10 +70,11 @@ namespace System.Globalization } } - private static readonly int[,] yinfo = + private static readonly int[,] s_yinfo = { -/*Y LM Lmon Lday DaysPerMonth D1 D2 D3 D4 D5 D6 D7 D8 D9 D10 D11 D12 D13 #Days -1960 */{ 6 , 1 , 28 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 29 384 + /*Y LM Lmon Lday DaysPerMonth D1 D2 D3 D4 D5 D6 D7 D8 D9 D10 D11 D12 D13 #Days + 1960 */ + { 6 , 1 , 28 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 29 384 1961 */{ 0 , 2 , 15 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 0 355 1962 */{ 0 , 2 , 5 , 19808 },/* 29 30 29 29 30 30 29 30 29 30 30 29 0 354 1963 */{ 4 , 1 , 25 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 29 384 @@ -205,21 +206,21 @@ namespace System.Globalization } } - internal override int GetYearInfo(int LunarYear, int Index) + internal override int GetYearInfo(int lunarYear, int index) { - if ((LunarYear < MIN_LUNISOLAR_YEAR) || (LunarYear > MAX_LUNISOLAR_YEAR)) + if ((lunarYear < MIN_LUNISOLAR_YEAR) || (lunarYear > MAX_LUNISOLAR_YEAR)) { throw new ArgumentOutOfRangeException( "year", String.Format( CultureInfo.CurrentCulture, - Environment.GetResourceString("ArgumentOutOfRange_Range"), + SR.ArgumentOutOfRange_Range, MIN_LUNISOLAR_YEAR, MAX_LUNISOLAR_YEAR)); } Contract.EndContractBlock(); - return yinfo[LunarYear - MIN_LUNISOLAR_YEAR, Index]; + return s_yinfo[lunarYear - MIN_LUNISOLAR_YEAR, index]; } internal override int GetYear(int year, DateTime time) @@ -282,19 +283,19 @@ namespace System.Globalization return (helper.GetEra(time)); } - internal override int BaseCalendarID + internal override CalendarId BaseCalendarID { get { - return (CAL_JAPAN); + return (CalendarId.JAPAN); } } - internal override int ID + internal override CalendarId ID { get { - return (CAL_JAPANESELUNISOLAR); + return (CalendarId.JAPANESELUNISOLAR); } } diff --git a/src/mscorlib/src/System/Globalization/JulianCalendar.cs b/src/mscorlib/src/System/Globalization/JulianCalendar.cs index f0555d0..43e6ad0 100644 --- a/src/mscorlib/src/System/Globalization/JulianCalendar.cs +++ b/src/mscorlib/src/System/Globalization/JulianCalendar.cs @@ -2,7 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. - using System; using System.Diagnostics.Contracts; @@ -34,14 +33,12 @@ namespace System.Globalization // Number of days in 4 years private const int JulianDaysPer4Years = JulianDaysPerYear * 4 + 1; - //internal static Calendar m_defaultInstance; - - private static readonly int[] DaysToMonth365 = + private static readonly int[] s_daysToMonth365 = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }; - private static readonly int[] DaysToMonth366 = + private static readonly int[] s_daysToMonth366 = { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }; @@ -67,9 +64,6 @@ namespace System.Globalization } } - // Return the type of the Julian calendar. - // - public override CalendarAlgorithmType AlgorithmType { get @@ -78,43 +72,25 @@ namespace System.Globalization } } - /*=================================GetDefaultInstance========================== - **Action: Internal method to provide a default intance of JulianCalendar. Used by NLS+ implementation - ** and other calendars. - **Returns: - **Arguments: - **Exceptions: - ============================================================================*/ - /* - internal static Calendar GetDefaultInstance() { - if (m_defaultInstance == null) { - m_defaultInstance = new JulianCalendar(); - } - return (m_defaultInstance); - } - */ - - // Construct an instance of gregorian calendar. - public JulianCalendar() { // There is no system setting of TwoDigitYear max, so set the value here. twoDigitYearMax = 2029; } - internal override int ID + internal override CalendarId ID { get { - return (CAL_JULIAN); + return CalendarId.JULIAN; } } - static internal void CheckEraRange(int era) + internal static void CheckEraRange(int era) { if (era != CurrentEra && era != JulianEra) { - throw new ArgumentOutOfRangeException(nameof(era), Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue")); + throw new ArgumentOutOfRangeException(nameof(era), SR.ArgumentOutOfRange_InvalidEraValue); } } @@ -127,21 +103,21 @@ namespace System.Globalization nameof(year), String.Format( CultureInfo.CurrentCulture, - Environment.GetResourceString("ArgumentOutOfRange_Range"), + SR.ArgumentOutOfRange_Range, 1, MaxYear)); } } - static internal void CheckMonthRange(int month) + internal static void CheckMonthRange(int month) { if (month < 1 || month > 12) { - throw new ArgumentOutOfRangeException(nameof(month), Environment.GetResourceString("ArgumentOutOfRange_Month")); + throw new ArgumentOutOfRangeException(nameof(month), SR.ArgumentOutOfRange_Month); } } - /*=================================GetDefaultInstance========================== + /*===================================CheckDayRange============================ **Action: Check for if the day value is valid. **Returns: **Arguments: @@ -151,7 +127,7 @@ namespace System.Globalization ** sure year/month values are correct. ============================================================================*/ - static internal void CheckDayRange(int year, int month, int day) + internal static void CheckDayRange(int year, int month, int day) { if (year == 1 && month == 1) { @@ -159,11 +135,11 @@ namespace System.Globalization if (day < 3) { throw new ArgumentOutOfRangeException(null, - Environment.GetResourceString("ArgumentOutOfRange_BadYearMonthDay")); + SR.ArgumentOutOfRange_BadYearMonthDay); } } bool isLeapYear = (year % 4) == 0; - int[] days = isLeapYear ? DaysToMonth366 : DaysToMonth365; + int[] days = isLeapYear ? s_daysToMonth366 : s_daysToMonth365; int monthDays = days[month] - days[month - 1]; if (day < 1 || day > monthDays) { @@ -171,7 +147,7 @@ namespace System.Globalization nameof(day), String.Format( CultureInfo.CurrentCulture, - Environment.GetResourceString("ArgumentOutOfRange_Range"), + SR.ArgumentOutOfRange_Range, 1, monthDays)); } @@ -180,7 +156,7 @@ namespace System.Globalization // Returns a given date part of this DateTime. This method is used // to compute the year, day-of-year, month, or day part. - static internal int GetDatePart(long ticks, int part) + internal static int GetDatePart(long ticks, int part) { // Gregorian 1/1/0001 is Julian 1/3/0001. Remember DateTime(0) is refered to Gregorian 1/1/0001. // The following line convert Gregorian ticks to Julian ticks. @@ -210,7 +186,7 @@ namespace System.Globalization // Leap year calculation looks different from IsLeapYear since y1, y4, // and y100 are relative to year 1, not year 0 bool leapYear = (y1 == 3); - int[] days = leapYear ? DaysToMonth366 : DaysToMonth365; + int[] days = leapYear ? s_daysToMonth366 : s_daysToMonth365; // All months have less than 32 days, so n >> 5 is a good conservative // estimate for the month int m = (n >> 5) + 1; @@ -223,9 +199,9 @@ namespace System.Globalization } // Returns the tick count corresponding to the given year, month, and day. - static internal long DateToTicks(int year, int month, int day) + internal static long DateToTicks(int year, int month, int day) { - int[] days = (year % 4 == 0) ? DaysToMonth366 : DaysToMonth365; + int[] days = (year % 4 == 0) ? s_daysToMonth366 : s_daysToMonth365; int y = year - 1; int n = y * 365 + y / 4 + days[month - 1] + day - 1; // Gregorian 1/1/0001 is Julian 1/3/0001. n * TicksPerDay is the ticks in JulianCalendar. @@ -243,7 +219,7 @@ namespace System.Globalization nameof(months), String.Format( CultureInfo.CurrentCulture, - Environment.GetResourceString("ArgumentOutOfRange_Range"), + SR.ArgumentOutOfRange_Range, -120000, 120000)); } @@ -262,7 +238,7 @@ namespace System.Globalization m = 12 + (i + 1) % 12; y = y + (i - 11) / 12; } - int[] daysArray = (y % 4 == 0 && (y % 100 != 0 || y % 400 == 0)) ? DaysToMonth366 : DaysToMonth365; + int[] daysArray = (y % 4 == 0 && (y % 100 != 0 || y % 400 == 0)) ? s_daysToMonth366 : s_daysToMonth365; int days = (daysArray[m] - daysArray[m - 1]); if (d > days) @@ -303,7 +279,7 @@ namespace System.Globalization { CheckYearEraRange(year, era); CheckMonthRange(month); - int[] days = (year % 4 == 0) ? DaysToMonth366 : DaysToMonth365; + int[] days = (year % 4 == 0) ? s_daysToMonth366 : s_daysToMonth365; return (days[month] - days[month - 1]); } @@ -402,7 +378,7 @@ namespace System.Globalization nameof(millisecond), String.Format( CultureInfo.CurrentCulture, - Environment.GetResourceString("ArgumentOutOfRange_Range"), + SR.ArgumentOutOfRange_Range, 0, MillisPerSecond - 1)); } @@ -413,7 +389,7 @@ namespace System.Globalization } else { - throw new ArgumentOutOfRangeException(null, Environment.GetResourceString("ArgumentOutOfRange_BadHourMinuteSecond")); + throw new ArgumentOutOfRangeException(null, SR.ArgumentOutOfRange_BadHourMinuteSecond); } } @@ -434,7 +410,7 @@ namespace System.Globalization "year", String.Format( CultureInfo.CurrentCulture, - Environment.GetResourceString("ArgumentOutOfRange_Range"), + SR.ArgumentOutOfRange_Range, 99, MaxYear)); } @@ -448,7 +424,7 @@ namespace System.Globalization if (year < 0) { throw new ArgumentOutOfRangeException(nameof(year), - Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + SR.ArgumentOutOfRange_NeedNonNegNum); } Contract.EndContractBlock(); @@ -458,7 +434,7 @@ namespace System.Globalization nameof(year), String.Format( CultureInfo.CurrentCulture, - Environment.GetResourceString("ArgumentOutOfRange_Bounds_Lower_Upper"), + SR.ArgumentOutOfRange_Bounds_Lower_Upper, 1, MaxYear)); } diff --git a/src/mscorlib/src/System/Globalization/KoreanCalendar.cs b/src/mscorlib/src/System/Globalization/KoreanCalendar.cs index 6ee425b..b015aa0 100644 --- a/src/mscorlib/src/System/Globalization/KoreanCalendar.cs +++ b/src/mscorlib/src/System/Globalization/KoreanCalendar.cs @@ -2,7 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. - using System; using System.Diagnostics.CodeAnalysis; using System.Diagnostics.Contracts; @@ -44,7 +43,7 @@ namespace System.Globalization //m_EraInfo[0] = new EraInfo(1, new DateTime(1, 1, 1).Ticks, -2333, 2334, GregorianCalendar.MaxYear + 2333); // Initialize our era info. - static internal EraInfo[] koreanEraInfo = new EraInfo[] { + internal static EraInfo[] koreanEraInfo = new EraInfo[] { new EraInfo( 1, 1, 1, 1, -2333, 2334, GregorianCalendar.MaxYear + 2333) // era #, start year/month/day, yearOffset, minEraYear }; @@ -67,9 +66,6 @@ namespace System.Globalization } } - // Return the type of the Korean calendar. - // - public override CalendarAlgorithmType AlgorithmType { get @@ -78,23 +74,6 @@ namespace System.Globalization } } - /*=================================GetDefaultInstance========================== - **Action: Internal method to provide a default intance of KoreanCalendar. Used by NLS+ implementation - ** and other calendars. - **Returns: - **Arguments: - **Exceptions: - ============================================================================*/ - /* - internal static Calendar GetDefaultInstance() { - if (m_defaultInstance == null) { - m_defaultInstance = new KoreanCalendar(); - } - return (m_defaultInstance); - } - */ - - public KoreanCalendar() { try @@ -103,16 +82,16 @@ namespace System.Globalization } catch (ArgumentException e) { - throw new TypeInitializationException(this.GetType().FullName, e); + throw new TypeInitializationException(this.GetType().ToString(), e); } helper = new GregorianCalendarHelper(this, koreanEraInfo); } - internal override int ID + internal override CalendarId ID { get { - return (CAL_KOREA); + return CalendarId.KOREA; } } @@ -264,7 +243,7 @@ namespace System.Globalization "year", String.Format( CultureInfo.CurrentCulture, - Environment.GetResourceString("ArgumentOutOfRange_Range"), + SR.ArgumentOutOfRange_Range, 99, helper.MaxYear)); } @@ -278,7 +257,7 @@ namespace System.Globalization if (year < 0) { throw new ArgumentOutOfRangeException(nameof(year), - Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + SR.ArgumentOutOfRange_NeedNonNegNum); } Contract.EndContractBlock(); diff --git a/src/mscorlib/src/System/Globalization/KoreanLunisolarCalendar.cs b/src/mscorlib/src/System/Globalization/KoreanLunisolarCalendar.cs index b6f02d7..6d09128 100644 --- a/src/mscorlib/src/System/Globalization/KoreanLunisolarCalendar.cs +++ b/src/mscorlib/src/System/Globalization/KoreanLunisolarCalendar.cs @@ -29,8 +29,6 @@ namespace System.Globalization public const int GregorianEra = 1; - //internal static Calendar m_defaultInstance; - internal const int MIN_LUNISOLAR_YEAR = 918; internal const int MAX_LUNISOLAR_YEAR = 2050; @@ -73,10 +71,11 @@ namespace System.Globalization } } - private static readonly int[,] yinfo = + private static readonly int[,] s_yinfo = { -/*Y LM Lmon Lday DaysPerMonth D1 D2 D3 D4 D5 D6 D7 D8 D9 D10 D11 D12 D13 #Days -918 */{ 0 , 2 , 14 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 0 355 + /*Y LM Lmon Lday DaysPerMonth D1 D2 D3 D4 D5 D6 D7 D8 D9 D10 D11 D12 D13 #Days + 918 */ + { 0 , 2 , 14 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 0 355 919 */{ 0 , 2 , 4 , 17872 },/* 29 30 29 29 29 30 29 30 30 30 29 30 0 354 920 */{ 6 , 1 , 24 , 41688 },/* 30 29 30 29 29 29 30 29 30 30 29 30 30 384 921 */{ 0 , 2 , 11 , 41648 },/* 30 29 30 29 29 29 30 29 30 29 30 30 0 354 @@ -1252,20 +1251,20 @@ namespace System.Globalization } } - internal override int GetYearInfo(int LunarYear, int Index) + internal override int GetYearInfo(int lunarYear, int index) { - if ((LunarYear < MIN_LUNISOLAR_YEAR) || (LunarYear > MAX_LUNISOLAR_YEAR)) + if ((lunarYear < MIN_LUNISOLAR_YEAR) || (lunarYear > MAX_LUNISOLAR_YEAR)) { throw new ArgumentOutOfRangeException( "year", String.Format( CultureInfo.CurrentCulture, - Environment.GetResourceString("ArgumentOutOfRange_Range"), + SR.ArgumentOutOfRange_Range, MIN_LUNISOLAR_YEAR, MAX_LUNISOLAR_YEAR)); } Contract.EndContractBlock(); - return yinfo[LunarYear - MIN_LUNISOLAR_YEAR, Index]; + return s_yinfo[lunarYear - MIN_LUNISOLAR_YEAR, index]; } internal override int GetYear(int year, DateTime time) @@ -1276,7 +1275,7 @@ namespace System.Globalization internal override int GetGregorianYear(int year, int era) { if (era != CurrentEra && era != GregorianEra) - throw new ArgumentOutOfRangeException(nameof(era), Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue")); + throw new ArgumentOutOfRangeException(nameof(era), SR.ArgumentOutOfRange_InvalidEraValue); if (year < MIN_LUNISOLAR_YEAR || year > MAX_LUNISOLAR_YEAR) { @@ -1284,57 +1283,36 @@ namespace System.Globalization nameof(year), String.Format( CultureInfo.CurrentCulture, - Environment.GetResourceString("ArgumentOutOfRange_Range"), MIN_LUNISOLAR_YEAR, MAX_LUNISOLAR_YEAR)); + SR.ArgumentOutOfRange_Range, MIN_LUNISOLAR_YEAR, MAX_LUNISOLAR_YEAR)); } Contract.EndContractBlock(); return year; } - /*=================================GetDefaultInstance========================== - **Action: Internal method to provide a default intance of KoreanLunisolarCalendar. Used by NLS+ implementation - ** and other calendars. - **Returns: - **Arguments: - **Exceptions: - ============================================================================*/ - /* - internal static Calendar GetDefaultInstance() - { - if (m_defaultInstance == null) { - m_defaultInstance = new KoreanLunisolarCalendar(); - } - return (m_defaultInstance); - } - */ - - // Construct an instance of KoreanLunisolar calendar. - public KoreanLunisolarCalendar() { } - - public override int GetEra(DateTime time) { CheckTicksRange(time.Ticks); return (GregorianEra); } - internal override int BaseCalendarID + internal override CalendarId BaseCalendarID { get { - return (CAL_KOREA); + return (CalendarId.KOREA); } } - internal override int ID + internal override CalendarId ID { get { - return (CAL_KOREANLUNISOLAR); + return (CalendarId.KOREANLUNISOLAR); } } diff --git a/src/mscorlib/corefx/System/Globalization/LocaleData.Unix.cs b/src/mscorlib/src/System/Globalization/LocaleData.Unix.cs similarity index 100% rename from src/mscorlib/corefx/System/Globalization/LocaleData.Unix.cs rename to src/mscorlib/src/System/Globalization/LocaleData.Unix.cs diff --git a/src/mscorlib/src/System/Globalization/NumberFormatInfo.cs b/src/mscorlib/src/System/Globalization/NumberFormatInfo.cs index 5d36dab..c44c085 100644 --- a/src/mscorlib/src/System/Globalization/NumberFormatInfo.cs +++ b/src/mscorlib/src/System/Globalization/NumberFormatInfo.cs @@ -2,10 +2,10 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System.Runtime.Serialization; -using System.Text; using System; using System.Diagnostics.Contracts; +using System.Runtime.Serialization; +using System.Text; namespace System.Globalization { @@ -42,10 +42,10 @@ namespace System.Globalization // [Serializable] - sealed public partial class NumberFormatInfo : ICloneable, IFormatProvider + sealed public class NumberFormatInfo : IFormatProvider, ICloneable { // invariantInfo is constant irrespective of your current culture. - private static volatile NumberFormatInfo invariantInfo; + private static volatile NumberFormatInfo s_invariantInfo; // READTHIS READTHIS READTHIS // This class has an exact mapping onto a native structure defined in COMNumber.cpp @@ -62,10 +62,6 @@ namespace System.Globalization internal String currencyGroupSeparator = ","; internal String currencyDecimalSeparator = "."; internal String currencySymbol = "\x00a4"; // U+00a4 is the symbol for International Monetary Fund. - // The alternative currency symbol used in Win9x ANSI codepage, that can not roundtrip between ANSI and Unicode. - // Currently, only ja-JP and ko-KR has non-null values (which is U+005c, backslash) - // NOTE: The only legal values for this string are null and "\x005c" - internal String ansiCurrencySymbol = null; internal String nanSymbol = "NaN"; internal String positiveInfinitySymbol = "Infinity"; internal String negativeInfinitySymbol = "-Infinity"; @@ -74,15 +70,10 @@ namespace System.Globalization internal String percentSymbol = "%"; internal String perMilleSymbol = "\u2030"; + [OptionalField(VersionAdded = 2)] internal String[] nativeDigits = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" }; - // an index which points to a record in Culture Data Table. - // We shouldn't be persisting dataItem (since its useless & we weren't using it), - // but since COMNumber.cpp uses it and since serialization isn't implimented, its stuck for now. - [OptionalField(VersionAdded = 1)] - internal int m_dataItem = 0; // NEVER USED, DO NOT USE THIS! (Serialized in Everett) - internal int numberDecimalDigits = 2; internal int currencyDecimalDigits = 2; internal int currencyPositivePattern = 0; @@ -93,15 +84,12 @@ namespace System.Globalization internal int percentDecimalDigits = 2; [OptionalField(VersionAdded = 2)] - internal int digitSubstitution = 1; // DigitShapes.None + internal int digitSubstitution = (int) DigitShapes.None; internal bool isReadOnly = false; - // We shouldn't be persisting m_useUserOverride (since its useless & we weren't using it), - // but since COMNumber.cpp uses it and since serialization isn't implimented, its stuck for now. - [OptionalField(VersionAdded = 1)] - internal bool m_useUserOverride = false; // NEVER USED, DO NOT USE THIS! (Serialized in Everett) // Is this NumberFormatInfo for invariant culture? + [OptionalField(VersionAdded = 2)] internal bool m_isInvariant = false; @@ -109,67 +97,50 @@ namespace System.Globalization { } - #region Serialization - // Check if NumberFormatInfo was not set up ambiguously for parsing as number and currency - // eg. if the NumberDecimalSeparator and the NumberGroupSeparator were the same. This check - // is solely for backwards compatibility / version tolerant serialization - [OptionalField(VersionAdded = 1)] - internal bool validForParseAsNumber = true; // NEVER USED, DO NOT USE THIS! (Serialized in Whidbey/Everett) - [OptionalField(VersionAdded = 1)] - internal bool validForParseAsCurrency = true; // NEVER USED, DO NOT USE THIS! (Serialized in Whidbey/Everett) - [OnSerializing] - private void OnSerializing(StreamingContext ctx) - { - } + private void OnSerializing(StreamingContext ctx) { } [OnDeserializing] - private void OnDeserializing(StreamingContext ctx) - { - } + private void OnDeserializing(StreamingContext ctx) { } [OnDeserialized] - private void OnDeserialized(StreamingContext ctx) - { - } - #endregion Serialization + private void OnDeserialized(StreamingContext ctx) { } - static private void VerifyDecimalSeparator(String decSep, String propertyName) + private static void VerifyDecimalSeparator(String decSep, String propertyName) { if (decSep == null) { throw new ArgumentNullException(propertyName, - Environment.GetResourceString("ArgumentNull_String")); + SR.ArgumentNull_String); } if (decSep.Length == 0) { - throw new ArgumentException(Environment.GetResourceString("Argument_EmptyDecString")); + throw new ArgumentException(SR.Argument_EmptyDecString); } Contract.EndContractBlock(); } - static private void VerifyGroupSeparator(String groupSep, String propertyName) + private static void VerifyGroupSeparator(String groupSep, String propertyName) { if (groupSep == null) { throw new ArgumentNullException(propertyName, - Environment.GetResourceString("ArgumentNull_String")); + SR.ArgumentNull_String); } Contract.EndContractBlock(); } - static private void VerifyNativeDigits(String[] nativeDig, String propertyName) + private static void VerifyNativeDigits(string [] nativeDig, string propertyName) { if (nativeDig == null) { - throw new ArgumentNullException(propertyName, - Environment.GetResourceString("ArgumentNull_Array")); + throw new ArgumentNullException(propertyName, SR.ArgumentNull_Array); } if (nativeDig.Length != 10) { - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidNativeDigitCount"), propertyName); + throw new ArgumentException(SR.Argument_InvalidNativeDigitCount, propertyName); } Contract.EndContractBlock(); @@ -177,22 +148,20 @@ namespace System.Globalization { if (nativeDig[i] == null) { - throw new ArgumentNullException(propertyName, - Environment.GetResourceString("ArgumentNull_ArrayValue")); + throw new ArgumentNullException(propertyName, SR.ArgumentNull_ArrayValue); } - if (nativeDig[i].Length != 1) { if (nativeDig[i].Length != 2) { // Not 1 or 2 UTF-16 code points - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidNativeDigitValue"), propertyName); - } + throw new ArgumentException(SR.Argument_InvalidNativeDigitValue, propertyName); + } else if (!char.IsSurrogatePair(nativeDig[i][0], nativeDig[i][1])) { // 2 UTF-6 code points, but not a surrogate pair - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidNativeDigitValue"), propertyName); + throw new ArgumentException(SR.Argument_InvalidNativeDigitValue, propertyName); } } @@ -201,13 +170,13 @@ namespace System.Globalization { // Not the appropriate digit according to the Unicode data properties // (Digit 0 must be a 0, etc.). - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidNativeDigitValue"), propertyName); + throw new ArgumentException(SR.Argument_InvalidNativeDigitValue, propertyName); } } } - static private void VerifyDigitSubstitution(DigitShapes digitSub, String propertyName) - { + private static void VerifyDigitSubstitution(DigitShapes digitSub, string propertyName) + { switch (digitSub) { case DigitShapes.Context: @@ -217,12 +186,10 @@ namespace System.Globalization break; default: - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidDigitSubstitution"), propertyName); + throw new ArgumentException(SR.Argument_InvalidDigitSubstitution, propertyName); } } - // We aren't persisting dataItem any more (since its useless & we weren't using it), - // Ditto with m_useUserOverride. Don't use them, we use a local copy of everything. internal NumberFormatInfo(CultureData cultureData) { if (cultureData != null) @@ -244,7 +211,7 @@ namespace System.Globalization { if (isReadOnly) { - throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly")); + throw new InvalidOperationException(SR.InvalidOperation_ReadOnly); } Contract.EndContractBlock(); } @@ -258,25 +225,24 @@ namespace System.Globalization { get { - if (invariantInfo == null) + if (s_invariantInfo == null) { // Lazy create the invariant info. This cannot be done in a .cctor because exceptions can // be thrown out of a .cctor stack that will need this. NumberFormatInfo nfi = new NumberFormatInfo(); nfi.m_isInvariant = true; - invariantInfo = ReadOnly(nfi); + s_invariantInfo = ReadOnly(nfi); } - return invariantInfo; + return s_invariantInfo; } } - public static NumberFormatInfo GetInstance(IFormatProvider formatProvider) { // Fast case for a regular CultureInfo NumberFormatInfo info; CultureInfo cultureProvider = formatProvider as CultureInfo; - if (cultureProvider != null && !cultureProvider.m_isInherited) + if (cultureProvider != null && !cultureProvider._isInherited) { info = cultureProvider.numInfo; if (info != null) @@ -326,7 +292,7 @@ namespace System.Globalization nameof(CurrencyDecimalDigits), String.Format( CultureInfo.CurrentCulture, - Environment.GetResourceString("ArgumentOutOfRange_Range"), + SR.ArgumentOutOfRange_Range, 0, 99)); } @@ -343,7 +309,7 @@ namespace System.Globalization set { VerifyWritable(); - VerifyDecimalSeparator(value, nameof(CurrencyDecimalSeparator)); + VerifyDecimalSeparator(value, "CurrencyDecimalSeparator"); currencyDecimalSeparator = value; } } @@ -363,7 +329,7 @@ namespace System.Globalization // Every element in the groupSize array should be between 1 and 9 // excpet the last element could be zero. // - static internal void CheckGroupSize(String propName, int[] groupSize) + internal static void CheckGroupSize(String propName, int[] groupSize) { for (int i = 0; i < groupSize.Length; i++) { @@ -371,11 +337,11 @@ namespace System.Globalization { if (i == groupSize.Length - 1 && groupSize[i] == 0) return; - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidGroupSize"), propName); + throw new ArgumentException(SR.Argument_InvalidGroupSize, propName); } else if (groupSize[i] > 9) { - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidGroupSize"), propName); + throw new ArgumentException(SR.Argument_InvalidGroupSize, propName); } } } @@ -392,7 +358,7 @@ namespace System.Globalization if (value == null) { throw new ArgumentNullException(nameof(CurrencyGroupSizes), - Environment.GetResourceString("ArgumentNull_Obj")); + SR.ArgumentNull_Obj); } Contract.EndContractBlock(); VerifyWritable(); @@ -416,7 +382,7 @@ namespace System.Globalization if (value == null) { throw new ArgumentNullException(nameof(NumberGroupSizes), - Environment.GetResourceString("ArgumentNull_Obj")); + SR.ArgumentNull_Obj); } Contract.EndContractBlock(); VerifyWritable(); @@ -438,13 +404,13 @@ namespace System.Globalization { if (value == null) { - throw new ArgumentNullException(nameof(PercentGroupSizes), - Environment.GetResourceString("ArgumentNull_Obj")); + throw new ArgumentNullException("PercentGroupSizes", + SR.ArgumentNull_Obj); } Contract.EndContractBlock(); VerifyWritable(); Int32[] inputSizes = (Int32[])value.Clone(); - CheckGroupSize(nameof(PercentGroupSizes), inputSizes); + CheckGroupSize("PercentGroupSizes", inputSizes); percentGroupSizes = inputSizes; } } @@ -470,7 +436,7 @@ namespace System.Globalization if (value == null) { throw new ArgumentNullException(nameof(CurrencySymbol), - Environment.GetResourceString("ArgumentNull_String")); + SR.ArgumentNull_String); } Contract.EndContractBlock(); VerifyWritable(); @@ -485,8 +451,8 @@ namespace System.Globalization { get { - System.Globalization.CultureInfo culture = System.Threading.Thread.CurrentThread.CurrentCulture; - if (!culture.m_isInherited) + System.Globalization.CultureInfo culture = CultureInfo.CurrentCulture; + if (!culture._isInherited) { NumberFormatInfo info = culture.numInfo; if (info != null) @@ -510,7 +476,7 @@ namespace System.Globalization if (value == null) { throw new ArgumentNullException(nameof(NaNSymbol), - Environment.GetResourceString("ArgumentNull_String")); + SR.ArgumentNull_String); } Contract.EndContractBlock(); VerifyWritable(); @@ -531,7 +497,7 @@ namespace System.Globalization nameof(CurrencyNegativePattern), String.Format( CultureInfo.CurrentCulture, - Environment.GetResourceString("ArgumentOutOfRange_Range"), + SR.ArgumentOutOfRange_Range, 0, 15)); } @@ -556,7 +522,7 @@ namespace System.Globalization nameof(NumberNegativePattern), String.Format( CultureInfo.CurrentCulture, - Environment.GetResourceString("ArgumentOutOfRange_Range"), + SR.ArgumentOutOfRange_Range, 0, 4)); } @@ -581,7 +547,7 @@ namespace System.Globalization nameof(PercentPositivePattern), String.Format( CultureInfo.CurrentCulture, - Environment.GetResourceString("ArgumentOutOfRange_Range"), + SR.ArgumentOutOfRange_Range, 0, 3)); } @@ -606,7 +572,7 @@ namespace System.Globalization nameof(PercentNegativePattern), String.Format( CultureInfo.CurrentCulture, - Environment.GetResourceString("ArgumentOutOfRange_Range"), + SR.ArgumentOutOfRange_Range, 0, 11)); } @@ -628,7 +594,7 @@ namespace System.Globalization if (value == null) { throw new ArgumentNullException(nameof(NegativeInfinitySymbol), - Environment.GetResourceString("ArgumentNull_String")); + SR.ArgumentNull_String); } Contract.EndContractBlock(); VerifyWritable(); @@ -645,7 +611,7 @@ namespace System.Globalization if (value == null) { throw new ArgumentNullException(nameof(NegativeSign), - Environment.GetResourceString("ArgumentNull_String")); + SR.ArgumentNull_String); } Contract.EndContractBlock(); VerifyWritable(); @@ -665,7 +631,7 @@ namespace System.Globalization nameof(NumberDecimalDigits), String.Format( CultureInfo.CurrentCulture, - Environment.GetResourceString("ArgumentOutOfRange_Range"), + SR.ArgumentOutOfRange_Range, 0, 99)); } @@ -711,7 +677,7 @@ namespace System.Globalization nameof(CurrencyPositivePattern), String.Format( CultureInfo.CurrentCulture, - Environment.GetResourceString("ArgumentOutOfRange_Range"), + SR.ArgumentOutOfRange_Range, 0, 3)); } @@ -733,7 +699,7 @@ namespace System.Globalization if (value == null) { throw new ArgumentNullException(nameof(PositiveInfinitySymbol), - Environment.GetResourceString("ArgumentNull_String")); + SR.ArgumentNull_String); } Contract.EndContractBlock(); VerifyWritable(); @@ -750,7 +716,7 @@ namespace System.Globalization if (value == null) { throw new ArgumentNullException(nameof(PositiveSign), - Environment.GetResourceString("ArgumentNull_String")); + SR.ArgumentNull_String); } Contract.EndContractBlock(); VerifyWritable(); @@ -770,7 +736,7 @@ namespace System.Globalization nameof(PercentDecimalDigits), String.Format( CultureInfo.CurrentCulture, - Environment.GetResourceString("ArgumentOutOfRange_Range"), + SR.ArgumentOutOfRange_Range, 0, 99)); } @@ -816,7 +782,7 @@ namespace System.Globalization if (value == null) { throw new ArgumentNullException(nameof(PercentSymbol), - Environment.GetResourceString("ArgumentNull_String")); + SR.ArgumentNull_String); } Contract.EndContractBlock(); VerifyWritable(); @@ -833,7 +799,7 @@ namespace System.Globalization if (value == null) { throw new ArgumentNullException(nameof(PerMilleSymbol), - Environment.GetResourceString("ArgumentNull_String")); + SR.ArgumentNull_String); } Contract.EndContractBlock(); VerifyWritable(); @@ -841,10 +807,9 @@ namespace System.Globalization } } - - public String[] NativeDigits + public string [] NativeDigits { - get { return (String[])nativeDigits.Clone(); } + get { return (String[]) nativeDigits.Clone(); } set { VerifyWritable(); @@ -855,12 +820,12 @@ namespace System.Globalization public DigitShapes DigitSubstitution { - get { return (DigitShapes)digitSubstitution; } + get { return (DigitShapes) digitSubstitution; } set { VerifyWritable(); VerifyDigitSubstitution(value, nameof(DigitSubstitution)); - digitSubstitution = (int)value; + digitSubstitution = (int) value; } } @@ -897,14 +862,14 @@ namespace System.Globalization // Check for undefined flags if ((style & InvalidNumberStyles) != 0) { - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidNumberStyles"), nameof(style)); + throw new ArgumentException(SR.Argument_InvalidNumberStyles, nameof(style)); } Contract.EndContractBlock(); if ((style & NumberStyles.AllowHexSpecifier) != 0) { // Check for hex number if ((style & ~NumberStyles.HexNumber) != 0) { - throw new ArgumentException(Environment.GetResourceString("Arg_InvalidHexStyle")); + throw new ArgumentException(SR.Arg_InvalidHexStyle); } } } @@ -914,12 +879,12 @@ namespace System.Globalization // Check for undefined flags if ((style & InvalidNumberStyles) != 0) { - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidNumberStyles"), nameof(style)); + throw new ArgumentException(SR.Argument_InvalidNumberStyles, nameof(style)); } Contract.EndContractBlock(); if ((style & NumberStyles.AllowHexSpecifier) != 0) { // Check for hex number - throw new ArgumentException(Environment.GetResourceString("Arg_HexStyleNotSupported")); + throw new ArgumentException(SR.Arg_HexStyleNotSupported); } } } // NumberFormatInfo diff --git a/src/mscorlib/src/System/Globalization/PersianCalendar.cs b/src/mscorlib/src/System/Globalization/PersianCalendar.cs index dca34e8..b8b3da6 100644 --- a/src/mscorlib/src/System/Globalization/PersianCalendar.cs +++ b/src/mscorlib/src/System/Globalization/PersianCalendar.cs @@ -2,7 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System; using System.Diagnostics; using System.Diagnostics.Contracts; @@ -50,24 +49,6 @@ namespace System.Globalization internal static DateTime minDate = new DateTime(622, 3, 22); internal static DateTime maxDate = DateTime.MaxValue; - /*=================================GetDefaultInstance========================== - **Action: Internal method to provide a default intance of PersianCalendar. Used by NLS+ implementation - ** and other calendars. - **Returns: - **Arguments: - **Exceptions: - ============================================================================*/ - /* - internal static Calendar GetDefaultInstance() { - if (m_defaultInstance == null) { - m_defaultInstance = new PersianCalendar(); - } - return (m_defaultInstance); - } - */ - - - public override DateTime MinSupportedDateTime { get @@ -76,7 +57,6 @@ namespace System.Globalization } } - public override DateTime MaxSupportedDateTime { get @@ -85,10 +65,6 @@ namespace System.Globalization } } - // Return the type of the Persian calendar. - // - - public override CalendarAlgorithmType AlgorithmType { get @@ -104,19 +80,19 @@ namespace System.Globalization } - internal override int BaseCalendarID + internal override CalendarId BaseCalendarID { get { - return (CAL_GREGORIAN); + return CalendarId.GREGORIAN; } } - internal override int ID + internal override CalendarId ID { get { - return (CAL_PERSIAN); + return CalendarId.PERSIAN; } } @@ -139,10 +115,10 @@ namespace System.Globalization yearStart += ordinalDay; return yearStart; } - throw new ArgumentOutOfRangeException(null, Environment.GetResourceString("ArgumentOutOfRange_BadYearMonthDay")); + throw new ArgumentOutOfRangeException(null, SR.ArgumentOutOfRange_BadYearMonthDay); } - static internal void CheckTicksRange(long ticks) + internal static void CheckTicksRange(long ticks) { if (ticks < minDate.Ticks || ticks > maxDate.Ticks) { @@ -150,21 +126,21 @@ namespace System.Globalization "time", String.Format( CultureInfo.InvariantCulture, - Environment.GetResourceString("ArgumentOutOfRange_CalendarRange"), + SR.ArgumentOutOfRange_CalendarRange, minDate, maxDate)); } } - static internal void CheckEraRange(int era) + internal static void CheckEraRange(int era) { if (era != CurrentEra && era != PersianEra) { - throw new ArgumentOutOfRangeException(nameof(era), Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue")); + throw new ArgumentOutOfRangeException(nameof(era), SR.ArgumentOutOfRange_InvalidEraValue); } } - static internal void CheckYearRange(int year, int era) + internal static void CheckYearRange(int year, int era) { CheckEraRange(era); if (year < 1 || year > MaxCalendarYear) @@ -173,13 +149,13 @@ namespace System.Globalization nameof(year), String.Format( CultureInfo.CurrentCulture, - Environment.GetResourceString("ArgumentOutOfRange_Range"), + SR.ArgumentOutOfRange_Range, 1, MaxCalendarYear)); } } - static internal void CheckYearMonthRange(int year, int month, int era) + internal static void CheckYearMonthRange(int year, int month, int era) { CheckYearRange(year, era); if (year == MaxCalendarYear) @@ -190,7 +166,7 @@ namespace System.Globalization nameof(month), String.Format( CultureInfo.CurrentCulture, - Environment.GetResourceString("ArgumentOutOfRange_Range"), + SR.ArgumentOutOfRange_Range, 1, MaxCalendarMonth)); } @@ -198,7 +174,7 @@ namespace System.Globalization if (month < 1 || month > 12) { - throw new ArgumentOutOfRangeException(nameof(month), Environment.GetResourceString("ArgumentOutOfRange_Month")); + throw new ArgumentOutOfRangeException(nameof(month), SR.ArgumentOutOfRange_Month); } } @@ -285,7 +261,7 @@ namespace System.Globalization } // Incorrect part value. - throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_DateTimeParsing")); + throw new InvalidOperationException(SR.InvalidOperation_DateTimeParsing); } // Returns the DateTime resulting from adding the given number of @@ -315,7 +291,7 @@ namespace System.Globalization nameof(months), String.Format( CultureInfo.CurrentCulture, - Environment.GetResourceString("ArgumentOutOfRange_Range"), + SR.ArgumentOutOfRange_Range, -120000, 120000)); } @@ -496,7 +472,7 @@ namespace System.Globalization nameof(day), String.Format( CultureInfo.CurrentCulture, - Environment.GetResourceString("ArgumentOutOfRange_Day"), + SR.ArgumentOutOfRange_Day, daysInMonth, month)); } @@ -551,12 +527,12 @@ namespace System.Globalization int daysInMonth = GetDaysInMonth(year, month, era); if (day < 1 || day > daysInMonth) { - BCLDebug.Log("year = " + year + ", month = " + month + ", day = " + day); + // BCLDebug.Log("year = " + year + ", month = " + month + ", day = " + day); throw new ArgumentOutOfRangeException( nameof(day), String.Format( CultureInfo.CurrentCulture, - Environment.GetResourceString("ArgumentOutOfRange_Day"), + SR.ArgumentOutOfRange_Day, daysInMonth, month)); } @@ -569,7 +545,7 @@ namespace System.Globalization } else { - throw new ArgumentOutOfRangeException(null, Environment.GetResourceString("ArgumentOutOfRange_BadYearMonthDay")); + throw new ArgumentOutOfRangeException(null, SR.ArgumentOutOfRange_BadYearMonthDay); } } @@ -595,7 +571,7 @@ namespace System.Globalization nameof(value), String.Format( CultureInfo.CurrentCulture, - Environment.GetResourceString("ArgumentOutOfRange_Range"), + SR.ArgumentOutOfRange_Range, 99, MaxCalendarYear)); } @@ -610,7 +586,7 @@ namespace System.Globalization if (year < 0) { throw new ArgumentOutOfRangeException(nameof(year), - Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + SR.ArgumentOutOfRange_NeedNonNegNum); } Contract.EndContractBlock(); @@ -625,7 +601,7 @@ namespace System.Globalization nameof(year), String.Format( CultureInfo.CurrentCulture, - Environment.GetResourceString("ArgumentOutOfRange_Range"), + SR.ArgumentOutOfRange_Range, 1, MaxCalendarYear)); } diff --git a/src/mscorlib/src/System/Globalization/RegionInfo.cs b/src/mscorlib/src/System/Globalization/RegionInfo.cs index e791c78..c3d5e65 100644 --- a/src/mscorlib/src/System/Globalization/RegionInfo.cs +++ b/src/mscorlib/src/System/Globalization/RegionInfo.cs @@ -2,7 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. - //////////////////////////////////////////////////////////////////////////// // // @@ -15,15 +14,14 @@ // //////////////////////////////////////////////////////////////////////////// +using System.Diagnostics; +using System.Diagnostics.Contracts; +using System.Runtime.Serialization; + namespace System.Globalization { - using System; - using System.Runtime.Serialization; - using System.Diagnostics; - using System.Diagnostics.Contracts; - [Serializable] - public partial class RegionInfo + public class RegionInfo { //--------------------------------------------------------------------// // Internal Information // @@ -36,12 +34,12 @@ namespace System.Globalization // // Name of this region (ie: es-US): serialized, the field used for deserialization // - internal String m_name; + internal String _name; // // The CultureData instance that we are going to read data from. // - [NonSerialized] internal CultureData m_cultureData; + internal CultureData _cultureData; // // The RegionInfo for our current region @@ -66,119 +64,87 @@ namespace System.Globalization if (name.Length == 0) //The InvariantCulture has no matching region { - throw new ArgumentException(Environment.GetResourceString("Argument_NoRegionInvariantCulture"), nameof(name)); + throw new ArgumentException(SR.Argument_NoRegionInvariantCulture, nameof(name)); } Contract.EndContractBlock(); // - // First try it as an entire culture. We must have user override as true here so - // that we can pick up custom cultures *before* built-in ones (if they want to - // prefer built-in cultures they will pass "us" instead of "en-US"). + // For CoreCLR we only want the region names that are full culture names // - this.m_cultureData = CultureData.GetCultureDataForRegion(name, true); - // this.m_name = name.ToUpper(CultureInfo.InvariantCulture); - - if (this.m_cultureData == null) + _cultureData = CultureData.GetCultureDataForRegion(name, true); + if (_cultureData == null) throw new ArgumentException( String.Format( CultureInfo.CurrentCulture, - Environment.GetResourceString("Argument_InvalidCultureName"), name), nameof(name)); + SR.Argument_InvalidCultureName, name), nameof(name)); // Not supposed to be neutral - if (this.m_cultureData.IsNeutralCulture) - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidNeutralRegionName", name), nameof(name)); + if (_cultureData.IsNeutralCulture) + throw new ArgumentException(SR.Format(SR.Argument_InvalidNeutralRegionName, name), nameof(name)); SetName(name); } -#if FEATURE_USE_LCID - // We'd rather people use the named version since this doesn't allow custom locales public RegionInfo(int culture) { if (culture == CultureInfo.LOCALE_INVARIANT) //The InvariantCulture has no matching region - { - throw new ArgumentException(Environment.GetResourceString("Argument_NoRegionInvariantCulture")); + { + throw new ArgumentException(SR.Argument_NoRegionInvariantCulture); } if (culture == CultureInfo.LOCALE_NEUTRAL) { // Not supposed to be neutral - throw new ArgumentException(Environment.GetResourceString("Argument_CultureIsNeutral", culture), nameof(culture)); + throw new ArgumentException(SR.Format(SR.Argument_CultureIsNeutral, culture), nameof(culture)); } if (culture == CultureInfo.LOCALE_CUSTOM_DEFAULT) { // Not supposed to be neutral - throw new ArgumentException(Environment.GetResourceString("Argument_CustomCultureCannotBePassedByNumber", culture), nameof(culture)); + throw new ArgumentException(SR.Format(SR.Argument_CustomCultureCannotBePassedByNumber, culture), nameof(culture)); } + + _cultureData = CultureData.GetCultureData(culture, true); + _name = _cultureData.SREGIONNAME; - this.m_cultureData = CultureData.GetCultureData(culture, true); - this.m_name = this.m_cultureData.SREGIONNAME; - - if (this.m_cultureData.IsNeutralCulture) + if (_cultureData.IsNeutralCulture) { // Not supposed to be neutral - throw new ArgumentException(Environment.GetResourceString("Argument_CultureIsNeutral", culture), nameof(culture)); + throw new ArgumentException(SR.Format(SR.Argument_CultureIsNeutral, culture), nameof(culture)); } - m_cultureId = culture; } -#endif internal RegionInfo(CultureData cultureData) { - this.m_cultureData = cultureData; - this.m_name = this.m_cultureData.SREGIONNAME; + _cultureData = cultureData; + _name = _cultureData.SREGIONNAME; } private void SetName(string name) { // Use the name of the region we found - this.m_name = this.m_cultureData.SREGIONNAME; + _name = _cultureData.SREGIONNAME; } - #region Serialization - // - // m_cultureId is needed for serialization only to detect the case if the region info is created using the name or using the LCID. - // in case m_cultureId is zero means that the RigionInfo is created using name. otherwise it is created using LCID. - // - - [OptionalField(VersionAdded = 2)] - private int m_cultureId; - // the following field is defined to keep the compatibility with Everett. - // don't change/remove the names/types of these field. - [OptionalField(VersionAdded = 2)] - internal int m_dataItem = 0; + [OnSerializing] + private void OnSerializing(StreamingContext ctx) { } [OnDeserialized] private void OnDeserialized(StreamingContext ctx) { - // This won't happen anyway since CoreCLR doesn't support serialization - this.m_cultureData = CultureData.GetCultureData(m_name, true); - - if (this.m_cultureData == null) - throw new ArgumentException( - String.Format( - CultureInfo.CurrentCulture, - Environment.GetResourceString("Argument_InvalidCultureName"), m_name), nameof(m_name)); + _cultureData = CultureData.GetCultureData(_name, true); - if (m_cultureId == 0) - { - SetName(this.m_name); - } - else + if (_cultureData == null) { - this.m_name = this.m_cultureData.SREGIONNAME; + throw new ArgumentException( + String.Format(CultureInfo.CurrentCulture, SR.Argument_InvalidCultureName, _name), + "_name"); } - } - [OnSerializing] - private void OnSerializing(StreamingContext ctx) - { - // Used to fill in everett data item, unnecessary now + _name = _cultureData.SREGIONNAME; } - #endregion Serialization //////////////////////////////////////////////////////////////////////// // @@ -196,10 +162,10 @@ namespace System.Globalization RegionInfo temp = s_currentRegionInfo; if (temp == null) { - temp = new RegionInfo(CultureInfo.CurrentCulture.m_cultureData); + temp = new RegionInfo(CultureInfo.CurrentCulture._cultureData); // Need full name for custom cultures - temp.m_name = temp.m_cultureData.SREGIONNAME; + temp._name = temp._cultureData.SREGIONNAME; s_currentRegionInfo = temp; } return temp; @@ -217,8 +183,8 @@ namespace System.Globalization { get { - Debug.Assert(m_name != null, "Expected RegionInfo.m_name to be populated already"); - return (m_name); + Debug.Assert(_name != null, "Expected RegionInfo._name to be populated already"); + return (_name); } } @@ -233,7 +199,7 @@ namespace System.Globalization { get { - return (this.m_cultureData.SENGCOUNTRY); + return (_cultureData.SENGCOUNTRY); } } @@ -250,7 +216,7 @@ namespace System.Globalization { get { - return (this.m_cultureData.SLOCALIZEDCOUNTRY); + return (_cultureData.SLOCALIZEDCOUNTRY); } } @@ -267,7 +233,7 @@ namespace System.Globalization { get { - return (this.m_cultureData.SNATIVECOUNTRY); + return (_cultureData.SNATIVECOUNTRY); } } @@ -282,11 +248,10 @@ namespace System.Globalization { get { - return (this.m_cultureData.SISO3166CTRYNAME); + return (_cultureData.SISO3166CTRYNAME); } } - //////////////////////////////////////////////////////////////////////// // // ThreeLetterISORegionName @@ -298,7 +263,7 @@ namespace System.Globalization { get { - return (this.m_cultureData.SISO3166CTRYNAME2); + return (_cultureData.SISO3166CTRYNAME2); } } @@ -313,10 +278,12 @@ namespace System.Globalization { get { - return (this.m_cultureData.SABBREVCTRYNAME); + // ThreeLetterWindowsRegionName is really same as ThreeLetterISORegionName + return ThreeLetterISORegionName; } } + //////////////////////////////////////////////////////////////////////// // // IsMetric @@ -328,17 +295,16 @@ namespace System.Globalization { get { - int value = this.m_cultureData.IMEASURE; + int value = _cultureData.IMEASURE; return (value == 0); } } - - public virtual int GeoId + public virtual int GeoId { get { - return (this.m_cultureData.IGEOID); + return (_cultureData.IGEOID); } } @@ -349,27 +315,27 @@ namespace System.Globalization // English name for this region's currency, ie: Swiss Franc // //////////////////////////////////////////////////////////////////////// - public virtual String CurrencyEnglishName + public virtual string CurrencyEnglishName { get { - return (this.m_cultureData.SENGLISHCURRENCY); + return (_cultureData.SENGLISHCURRENCY); } } //////////////////////////////////////////////////////////////////////// // - // CurrencyEnglishName + // CurrencyNativeName // - // English name for this region's currency, ie: Schweizer Franken + // Native name for this region's currency, ie: Schweizer Franken // WARNING: You need a full locale name for this to make sense. // //////////////////////////////////////////////////////////////////////// - public virtual String CurrencyNativeName + public virtual string CurrencyNativeName { get { - return (this.m_cultureData.SNATIVECURRENCY); + return (_cultureData.SNATIVECURRENCY); } } @@ -384,7 +350,7 @@ namespace System.Globalization { get { - return (this.m_cultureData.SCURRENCY); + return (_cultureData.SCURRENCY); } } @@ -399,7 +365,7 @@ namespace System.Globalization { get { - return (this.m_cultureData.SINTLSYMBOL); + return (_cultureData.SINTLSYMBOL); } } diff --git a/src/mscorlib/src/System/Globalization/SortKey.cs b/src/mscorlib/src/System/Globalization/SortKey.cs index 700699b..0930965 100644 --- a/src/mscorlib/src/System/Globalization/SortKey.cs +++ b/src/mscorlib/src/System/Globalization/SortKey.cs @@ -26,20 +26,16 @@ namespace System.Globalization // Internal Information // //--------------------------------------------------------------------// - // - // Variables. - // - [OptionalField(VersionAdded = 3)] - internal String localeName; // locale identifier + internal string _localeName; // locale identifier [OptionalField(VersionAdded = 1)] // LCID field so serialization is Whidbey compatible though we don't officially support it - internal int win32LCID; - // Whidbey serialization + internal int _win32LCID; + // Whidbey serialization - internal CompareOptions options; // options - internal String m_String; // original string - internal byte[] m_KeyData; // sortkey data + internal CompareOptions _options; // options + internal string _string; // original string + internal byte[] _keyData; // sortkey data // // The following constructor is designed to be called from CompareInfo to get the @@ -47,20 +43,19 @@ namespace System.Globalization // internal SortKey(String localeName, String str, CompareOptions options, byte[] keyData) { - this.m_KeyData = keyData; - this.localeName = localeName; - this.options = options; - this.m_String = str; + _keyData = keyData; + _localeName = localeName; + _options = options; + _string = str; } -#if FEATURE_USE_LCID [OnSerializing] private void OnSerializing(StreamingContext context) { //set LCID to proper value for Whidbey serialization (no other use) - if (win32LCID == 0) + if (_win32LCID == 0) { - win32LCID = CultureInfo.GetCultureInfo(localeName).LCID; + _win32LCID = CultureInfo.GetCultureInfo(_localeName).LCID; } } @@ -68,12 +63,11 @@ namespace System.Globalization private void OnDeserialized(StreamingContext context) { //set locale name to proper value after Whidbey deserialization - if (String.IsNullOrEmpty(localeName) && win32LCID != 0) + if (String.IsNullOrEmpty(_localeName) && _win32LCID != 0) { - localeName = CultureInfo.GetCultureInfo(win32LCID).Name; + _localeName = CultureInfo.GetCultureInfo(_win32LCID).Name; } } -#endif //FEATURE_USE_LCID //////////////////////////////////////////////////////////////////////// // @@ -87,11 +81,10 @@ namespace System.Globalization { get { - return (m_String); + return (_string); } } - - + //////////////////////////////////////////////////////////////////////// // // GetKeyData @@ -104,11 +97,10 @@ namespace System.Globalization { get { - return (byte[])(m_KeyData.Clone()); + return (byte[])(_keyData.Clone()); } } - - + //////////////////////////////////////////////////////////////////////// // // Compare @@ -120,17 +112,16 @@ namespace System.Globalization //////////////////////////////////////////////////////////////////////// public static int Compare(SortKey sortkey1, SortKey sortkey2) { - if (sortkey1 == null || sortkey2 == null) + if (sortkey1==null || sortkey2==null) { throw new ArgumentNullException((sortkey1 == null ? nameof(sortkey1) : nameof(sortkey2))); } Contract.EndContractBlock(); - - byte[] key1Data = sortkey1.m_KeyData; - byte[] key2Data = sortkey2.m_KeyData; - - Debug.Assert(key1Data != null, "key1Data!=null"); - Debug.Assert(key2Data != null, "key2Data!=null"); + byte[] key1Data = sortkey1._keyData; + byte[] key2Data = sortkey2._keyData; + + Debug.Assert(key1Data != null, "key1Data != null"); + Debug.Assert(key2Data != null, "key2Data != null"); if (key1Data.Length == 0) { @@ -147,13 +138,13 @@ namespace System.Globalization int compLen = (key1Data.Length < key2Data.Length) ? key1Data.Length : key2Data.Length; - for (int i = 0; i < compLen; i++) + for (int i=0; i key2Data[i]) + if (key1Data[i]>key2Data[i]) { return (1); } - if (key1Data[i] < key2Data[i]) + if (key1Data[i] { - private int m_NlsVersion; - private Guid m_SortId; + private int _nlsVersion; + private Guid _sortId; public int FullVersion { get { - return m_NlsVersion; + return _nlsVersion; } } @@ -25,31 +25,30 @@ namespace System.Globalization { get { - return m_SortId; + return _sortId; } } public SortVersion(int fullVersion, Guid sortId) { - m_SortId = sortId; - m_NlsVersion = fullVersion; + _sortId = sortId; + _nlsVersion = fullVersion; } internal SortVersion(int nlsVersion, int effectiveId, Guid customVersion) { - m_NlsVersion = nlsVersion; + _nlsVersion = nlsVersion; if (customVersion == Guid.Empty) { - byte[] b = BitConverter.GetBytes(effectiveId); - byte b1 = (byte)((uint)effectiveId >> 24); + byte b1 = (byte)(effectiveId >> 24); byte b2 = (byte)((effectiveId & 0x00FF0000) >> 16); byte b3 = (byte)((effectiveId & 0x0000FF00) >> 8); byte b4 = (byte)(effectiveId & 0xFF); customVersion = new Guid(0, 0, 0, 0, 0, 0, 0, b1, b2, b3, b4); } - m_SortId = customVersion; + _sortId = customVersion; } public override bool Equals(object obj) @@ -70,12 +69,12 @@ namespace System.Globalization return false; } - return m_NlsVersion == other.m_NlsVersion && m_SortId == other.m_SortId; + return _nlsVersion == other._nlsVersion && _sortId == other._sortId; } public override int GetHashCode() { - return m_NlsVersion * 7 | m_SortId.GetHashCode(); + return _nlsVersion * 7 | _sortId.GetHashCode(); } public static bool operator ==(SortVersion left, SortVersion right) diff --git a/src/mscorlib/src/System/Globalization/StringInfo.cs b/src/mscorlib/src/System/Globalization/StringInfo.cs index 1cc2df3..f1dd305 100644 --- a/src/mscorlib/src/System/Globalization/StringInfo.cs +++ b/src/mscorlib/src/System/Globalization/StringInfo.cs @@ -12,63 +12,59 @@ // //////////////////////////////////////////////////////////////////////////// - using System; -using System.Runtime.Serialization; using System.Diagnostics; using System.Diagnostics.Contracts; +using System.Runtime.Serialization; namespace System.Globalization { [Serializable] public class StringInfo { - [OptionalField(VersionAdded = 2)] - private String m_str; + [OptionalField(VersionAdded = 2)] + private string _str; - // We allow this class to be serialized but there is no conceivable reason - // for them to do so. Thus, we do not serialize the instance variables. - [NonSerialized] private int[] m_indexes; + [NonSerialized] + private int[] _indexes; // Legacy constructor public StringInfo() : this("") { } // Primary, useful constructor - public StringInfo(String value) + public StringInfo(string value) { this.String = value; } - #region Serialization [OnDeserializing] private void OnDeserializing(StreamingContext ctx) { - m_str = String.Empty; + _str = String.Empty; } [OnDeserialized] private void OnDeserialized(StreamingContext ctx) { - if (m_str.Length == 0) + if (_str.Length == 0) { - m_indexes = null; + _indexes = null; } } - #endregion Serialization public override bool Equals(Object value) { StringInfo that = value as StringInfo; if (that != null) { - return (m_str.Equals(that.m_str)); + return (_str.Equals(that._str)); } return (false); } public override int GetHashCode() { - return m_str.GetHashCode(); + return _str.GetHashCode(); } @@ -78,32 +74,32 @@ namespace System.Globalization { get { - if ((null == m_indexes) && (0 < this.String.Length)) + if ((null == _indexes) && (0 < this.String.Length)) { - m_indexes = StringInfo.ParseCombiningCharacters(this.String); + _indexes = StringInfo.ParseCombiningCharacters(this.String); } - return (m_indexes); + return (_indexes); } } - public String String + public string String { get { - return (m_str); + return (_str); } set { if (null == value) { - throw new ArgumentNullException(nameof(String), - Environment.GetResourceString("ArgumentNull_String")); + throw new ArgumentNullException("String", + SR.ArgumentNull_String); } Contract.EndContractBlock(); - m_str = value; - m_indexes = null; + _str = value; + _indexes = null; } } @@ -121,58 +117,49 @@ namespace System.Globalization } } - public String SubstringByTextElements(int startingTextElement) + public string SubstringByTextElements(int startingTextElement) { // If the string is empty, no sense going further. - if (null == this.Indexes) + if (null == this.Indexes) { // Just decide which error to give depending on the param they gave us.... - if (startingTextElement < 0) + if (startingTextElement < 0) { - throw new ArgumentOutOfRangeException(nameof(startingTextElement), - Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum")); + throw new ArgumentOutOfRangeException(nameof(startingTextElement), SR.ArgumentOutOfRange_NeedPosNum); } else { - throw new ArgumentOutOfRangeException(nameof(startingTextElement), - Environment.GetResourceString("Arg_ArgumentOutOfRangeException")); + throw new ArgumentOutOfRangeException(nameof(startingTextElement), SR.Arg_ArgumentOutOfRangeException); } } - return (this.SubstringByTextElements(startingTextElement, this.Indexes.Length - startingTextElement)); + return (SubstringByTextElements(startingTextElement, Indexes.Length - startingTextElement)); } - public String SubstringByTextElements(int startingTextElement, int lengthInTextElements) + public string SubstringByTextElements(int startingTextElement, int lengthInTextElements) { - // - // Parameter checking - // if (startingTextElement < 0) { - throw new ArgumentOutOfRangeException(nameof(startingTextElement), - Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum")); + throw new ArgumentOutOfRangeException(nameof(startingTextElement), SR.ArgumentOutOfRange_NeedPosNum); } - if (this.String.Length == 0 || startingTextElement >= this.Indexes.Length) + if (this.String.Length == 0 || startingTextElement >= Indexes.Length) { - throw new ArgumentOutOfRangeException(nameof(startingTextElement), - Environment.GetResourceString("Arg_ArgumentOutOfRangeException")); + throw new ArgumentOutOfRangeException(nameof(startingTextElement), SR.Arg_ArgumentOutOfRangeException); } if (lengthInTextElements < 0) { - throw new ArgumentOutOfRangeException(nameof(lengthInTextElements), - Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum")); + throw new ArgumentOutOfRangeException(nameof(lengthInTextElements), SR.ArgumentOutOfRange_NeedPosNum); } - if (startingTextElement > this.Indexes.Length - lengthInTextElements) + if (startingTextElement > Indexes.Length - lengthInTextElements) { - throw new ArgumentOutOfRangeException(nameof(lengthInTextElements), - Environment.GetResourceString("Arg_ArgumentOutOfRangeException")); + throw new ArgumentOutOfRangeException(nameof(lengthInTextElements), SR.Arg_ArgumentOutOfRangeException); } - int start = this.Indexes[startingTextElement]; + int start = Indexes[startingTextElement]; - if (startingTextElement + lengthInTextElements == this.Indexes.Length) + if (startingTextElement + lengthInTextElements == Indexes.Length) { // We are at the last text element in the string and because of that // must handle the call differently. @@ -180,11 +167,11 @@ namespace System.Globalization } else { - return (this.String.Substring(start, (this.Indexes[lengthInTextElements + startingTextElement] - start))); + return (this.String.Substring(start, (Indexes[lengthInTextElements + startingTextElement] - start))); } } - public static String GetNextTextElement(String str) + public static string GetNextTextElement(string str) { return (GetNextTextElement(str, 0)); } @@ -222,7 +209,7 @@ namespace System.Globalization // //////////////////////////////////////////////////////////////////////// - internal static int GetCurrentTextElementLen(String str, int index, int len, ref UnicodeCategory ucCurrent, ref int currentCharCount) + internal static int GetCurrentTextElementLen(string str, int index, int len, ref UnicodeCategory ucCurrent, ref int currentCharCount) { Debug.Assert(index >= 0 && len >= 0, "StringInfo.GetCurrentTextElementLen() : index = " + index + ", len = " + len); Debug.Assert(index < len, "StringInfo.GetCurrentTextElementLen() : index = " + index + ", len = " + len); @@ -285,7 +272,7 @@ namespace System.Globalization // of str. It recognizes a base character plus one or more combining // characters or a properly formed surrogate pair as a text element. See also // the ParseCombiningCharacters() and the ParseSurrogates() methods. - public static String GetNextTextElement(String str, int index) + public static string GetNextTextElement(string str, int index) { // // Validate parameters. @@ -303,7 +290,7 @@ namespace System.Globalization { return (String.Empty); } - throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_Index")); + throw new ArgumentOutOfRangeException(nameof(index), SR.ArgumentOutOfRange_Index); } int charLen; @@ -311,12 +298,12 @@ namespace System.Globalization return (str.Substring(index, GetCurrentTextElementLen(str, index, len, ref uc, ref charLen))); } - public static TextElementEnumerator GetTextElementEnumerator(String str) + public static TextElementEnumerator GetTextElementEnumerator(string str) { return (GetTextElementEnumerator(str, 0)); } - public static TextElementEnumerator GetTextElementEnumerator(String str, int index) + public static TextElementEnumerator GetTextElementEnumerator(string str, int index) { // // Validate parameters. @@ -330,7 +317,7 @@ namespace System.Globalization int len = str.Length; if (index < 0 || (index > len)) { - throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_Index")); + throw new ArgumentOutOfRangeException(nameof(index), SR.ArgumentOutOfRange_Index); } return (new TextElementEnumerator(str, index, len)); @@ -348,7 +335,7 @@ namespace System.Globalization * return the indices: 0, 2, 4. */ - public static int[] ParseCombiningCharacters(String str) + public static int[] ParseCombiningCharacters(string str) { if (str == null) { diff --git a/src/mscorlib/src/System/Globalization/Tables/charinfo.nlp b/src/mscorlib/src/System/Globalization/Tables/charinfo.nlp deleted file mode 100644 index 2d5444f524688548be64ccc17d36581931dc9507..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 36992 zcmeHQdu(IbSwB0;c%01a_!ZmN?`y|SoX2LpkJ-uWgYisX*>*eQ?TfUO)}>I~r4P42 zoARnDTSy;JQwmKB2#bG+;14VzL=Z?dAVm1j5<&zdB#VL+5Jg4^Df~73zVDoK&%M{l zJm^-mmCwyR-}^h?`OdlLo_n1*?-eca9`RA}e(@pkKJj6(0r&yY7XI=q7~yvaae%Y& zSs}Wg10xcS*pXVK9%)3Hk#?jL=|*~yeq<0CMn;iwL`1_;J6em@0UOa~v>ok4yU|{> zA00%8(NT096|r#4j@4rISR>YqwPT%FH`a^wV}sZ*Hj0g7Vj;X>FN9(LU`Or$VDn%t zeDm7%g@%f<3D{ofEOZxo3;l(`wVJ>G~nS;e?&2;jAYbiDsgm=p?#{UZS5EfH%ac51GSJVw@03&2vL1$EQk- zCh6Jt&@tL)W8|lntSe8ASHR=hZQYNgc}4{7Gx&a=on$xJOZJn4*w$-t^R?q5N1Gh%P8J`EdI;VD%85mlVJTGTtjqj;rEJVtT>nnw^ z_iusUS1P`#pJ@iB8JK2Znt^EsrWu%KV48tx2BsO9W?-6uX$Gblm}X#_foTS&8JK2Z znt@j+1F72dZLsrc)+?0L?;w8<`sv|R|GOyz_0)G$Z>D{D&)YPyylK%b6HVDCYyi8%%n-*>W|TS3j58-0kqu_USu1O2tJzw1Gh1hRE8EC!XPenpww>L9yp!F{ zb|K%(_E^53?Pm`_53+~ZVfH9H${uIO&_BtFTrd~ThI3ZV&egKjT#f0?Ts^l1y211? zvz=?^TA_LB+>2Xciy^j5SpLO@S zKFAO9hst)KedLewBjCsEpW5iB#`zO1y=M!|eZqsftY}-3_hk3h>UDw{Td-lFfS4`hN;A3DP zf*vw1ubU%V&VP43^6-xBv3-nVY@eVO#ULNyqE)nu)ncut+r^z? zr?^|}7W=zG;gW_RvSUf6@a2yxM#gpQ3L6m}}<3hM(m28}6A6018N}HuR zA6uXr(B1}YmRhAY;BjH6)X%hW9-)m+X;~3?HXk+IiXgof64+?Oj-R%kYDH z%U-!x#vR7-*DoKGo9RLMusj5xj-&FZd|V!vPhdfZs01s+Ot@m9ro*mO8LL$`D_9BA z^$K0-Ti`V++oq>#fBS){54Y!mr?n%_zr9plsx56U)tBU5Rn}We zjiqf5$1R=2n@fG?{@Y@^HaPvv&QdGg!MVHCUD{jfE$#b!_LmNpT54}HSUOx9qSr?_ zdxg=`@zQwdWJxR!Gl%)$@}MwK^TpjGyBuD&aM;ULK5EOG%SVg#Wonyd?G|H1>4U~l zdgx{w%iHii%rsHA7;B^6VXU*fD{XOocbD~uk@f(02<@#;W0aA19o%guT9b0R=ILIv z>$1}xddp+%boNpAaUS3tEFUUA+{W3&*{Zf#Lq;Iw*SUsw4;d&ZoM%82R$JJKh1W>F5SHdgAw^pRwUa79sRyJ4a;O=C%RvIh1)$Nt$ zN{e;dD?2N#LT4o?_hT#FmA#doqo?)#kXpfYy3&WOUq&=Z4^{>%hbu$&CH0S1MoORP zvjjMP?tOi$4^K~W#{NTuG6sYDslI?u9teN`>TE62Z|oRkG|_3x_r8$ z&~n-ZSe?VxTiaZ#uWfx zd3`vgUOQPMEwOH8g6rXRYu#S2uGiK#*X!$BIHiZiI`#j^vr9Q#++J_;f!+0DYu)T3 z+Q6}AP`3R{2lTGu4OY7j-$ZBfZ}RNM_PBjF=kB=NTlMbCs=mCx?%#j8=|0D+`+l%~ z%sUgn!obs$Lk}gbaCcHGx_kb5ae2i_-l6Bt?bY+%)xEOQDfcx+SE)PSetd}NkJioM zm&^HeR*hZ3UH2!W^@nshH*;=wMiUaw%*>oS9|&9sUI+x{<^vZmJ$&iXWv5&UghHV} zAbe(-3(QBNk=U7KE;Juf4SCyjQwxD0N<0vWCz2s69!aG$nMf=Uh-4DkTrPK3^C1=0 zS&fIZAdJ7RIqjHW`WezF77H_i3J6t%NkSshj+6+KB1U2fuwn_6a6YDfe2uUXgzOKs zI%Mp!B`MSr@(7<&f$M@Uwym%TitUs_foM}$Ns)HMCj`IfE7Y0skmH}Kh#eu)w7G1FE2ADs}(Mx(CUQ?YnRsJahLz~N5uO2hOazoXjZK` z<-%i+LAz+=4z|9bysjwsk3L!~GP<$hT)vl~{`lh?>z*PW@jGQZ5(?W3UmLC4kX+TG4C)4aS9V+7|*&a283%1tdFzC(47< z{8NcUFnE#HSiPBaBECijiX>!uT&1sY&9gV*IlKyCz#* zWMiP<+Q}!{x*Oyp0u!2U2u9Jb1jb_VY#q*+SHY-kBtao;E)LYPp> zWWi=q!nN)P2g*|bD##n>4jQ0{A%PHREzTtvXBNWO`Il{}#vQi~0(F{P(7(b%Av-3W z6gg7e20`5WsFZ{!Khl|Og7dRU?yd*`O1B<2P_iI;?y@2QoN$P*$II!j>aFRo$!q$`lG|1tq^AIk+^<%q>edGz#Q} zYw4J5oIn`YDj*#H7!)0^D9{L@xUUQqTB%f$cN(WImBA|(QK6W40d1KRp}&xBhwmgC}a$XMk1g&N}`!!rIjU)90Nw0pf!|+ep#5Vd; z$#}X7h8ca0DSe6u?PGwcAb%=(Se{+El<9Ty3Ijdg^zPJmc`q{UEDE|Y>76{IpjLc} znARFqoOU#$1UUj#+6u5QPAK#f3DaMN>x5z5uu+h zqyS5mddyIYcn*<=rnR1?^Qth7)q~9QkrC340W&`CgBtZ#hT$QLez(?uk83I#>WrbvVf zk>2&7(1MT)1f-^rJk)xLSHToKdv|&ykwu9eeQgJ~$t*8LsN|BwD-Sjl6{fLXUUZ?wR4kdQf^F)zP!Hi{xc9SB(CXJ=`z!JWo~{x?yL^9MqRm5 z;RP>F>_Q?Ck30P>79){@XDbwds(aJJs-+S?5jdBIvM0bnIs!rvqS>5!Bm zxwX*Ol7GST$)VsW`U!&4f+_p&>9*-n0l78%1KB}&ztweuR)5+^suHlZgkS-W zdD5FR2-oxuUXLhlkyM=bop?71OLNdOZ*38QceZqK7`_X`#iI5Bkn8pp zOcV-y*Fm@xGKa0N1>Ss7LP=MSXQ>oSNlWSgA~`(5IAi{5`}$QxlcDC;M~1U6ZT zGCd!0(fL&SReosDJhQ)p3);`B4J^W>2F#WXm?)U>qXw0~q8V@_=Z5ulu3O~3%k3fu zOmdwUH0*uepr(~)OgGwPlQQBaZ>nElNJo=3o#hs?aT28yrls!n zbBiu@wf;GB@=J*#*Zh793`Yn=x@Q)n&-=>jeMS2BOebcs&uY=UWW8umVDdewASi#d zbYtTUzT%FKapx`XBr=c1b&^XQ?Zqu!!;Gf6i-H}c)Cg26(WqWPHDo!oqS5H3z$Fp5 zgw1wYm=Pf>GF>n6m^oCN^`S?XF-%>@*^V_$*w4VOjwN}67I1_?-Qc;Sb9MFcij;Jha znuuGlb{r{0xpCN4qy`T)q|VPaWKUgjcSp$>XhR~XI3IsV(rreKJMnN_FlLDAwnhlb z_Sv=ar@ZL|g5=9Ip!#ci0c+OPaVb&;=6C_36r5(2tT9>KR^r9UqU6%yo9=Y#>bgP)6`-`Z(P%<8}2aqM&`ct9K${cCvDzJaVV?zU#N@Jq*FYrH=LSAa1%qE{Q5`- z2S_oOT=7a8423Y@Bm$Fh$rn$SrMiv}4HV`!kxUmywaK5j$4vm<^y~L{bW75ABzjA9 zR#7^xU7_2~c#s(VJ_LWLp&t~SUsfPFo}rb2hKfY{tZ0JMb}mJ&!;$jGCn{!_j`pXa z>6PYaXqpPYS@R~K`W+hM#fKS7zowD+o%%I>E?v?1HH}X#!KT^#wu8o8Q$^1o1NC%K zACI|6|7A!Mi0$}(=iL2n-BQk+3C4S4*QOX-SA2gkehiOM;z%O~M6r(1mmE#QT)R;A z%+WlT*wqj<;7Ft@w$`5F*+S9=*2i#d68R$^og;o30Z)c@UDR%_`(kH(PxJ2P_`#i; zcQZZVz?5m13oX|yO-tzNj#jWVBB5SfH1s}>3Gp8&Iht4D%c0AWixDeo&8O!VqVZ^I z&bkzv3kFkByb;Hf%tPYhrEGLoB%-0q+45Y9J=Ie8yS*Nu&qMuv+?=s*%O1x}RAWSGtM3h$+-9t;zCAn~=|hvg zK^)&M9vR^r^Y@4wYd2;uxT*hNytYvPHj3tz$OXRPoaa;Xp8aZ1XmlnxuS7&sAK#f7 z=uT(Dx9`e4jcl5MX$Gblm}X#_foTS&8JK2Znt^EsrWu%KV48tx2BsO9W?-6uX$Gbl zm}X#_foTS&8JK2Znt^XJ13mn&?B2pY*Al0?@1u?6ZkXT8q+eq_soPsP@U?n?|KV*c zPLsQ(BtP`&4}J8JkM`S-?jrX`Z0KYB|8K9SNy=y&%&&E_AmV=B-RL0xV)btF{RIp1 zv)gmq`g7k~uut{9f2KcoJ8oRIa<-j2iYopix|??6oA_Vp_4wAA^4>xtzK#E--f}eB z@f`=3o;vYe`akRU94)P}hyTfr4C4Q?YtFsl!G!JroJ0Iqcd{kCw{Yaqnaq}KW#nib zJD6!-TAgJp$K5S;lU^48X-Ll?-m9!_Mx~G#@Cyj42QJt_bKDDjpcxf+HyNe%fKM6OJ z_2gEvk=#x;ldWVsxpNOM-ZuUII?3I8*dHXi_s}pt_maKjezJe2zNN z7T(_s72=_DGqdOM=VkmwEiAlviNVA8P2-UK${N2`BpSOMUeKPP1%{^Zm4+JiKnq`T zh#vvDaSIL8ekhyE7wlqb(e;-AE*B49yi{3QuCA=c*VZ4|c(nG|*ZqI*9TdPU)9P@to6+r1={qUPa#xu@!y(^>0Wy?&2@JaU*dnnY@iC zu5C14RKIiUm_z=iH@{^85v|=XPqwJ*=T37#;i4Fir(sg(l-m4WwD}ETr$b(SWLYst z!N?qS*WVkERF8^y>)XC}`|a=ezIT5A`n%rUe9sSv_x|7yz3-79ZoU7dANjxsKlEYs z`{0fj%R75aJHRrE;+E2m$b`u)){p+!kAE!r@tsfH z{)wObsh@u0XFl0!{OqTG?q#=^%c0cf#;x0p%{YzrZ3&)e#8a3FD4YB{*!&HLiI4DK zcR^<(6uPOe9OKKn%=ld*A$bZd7#m=ZYwBYXNu}d!?mym9Vz>oAX)XzFC%$IHSFdh* zEzy+rlmdo}(^o!?`Qi^3fBkZH;$HmuU)cT3XFvD(U;L#nbbtAazw)JD{k1RC{G`Bq zt|giBc2yt@tw-&8>=Z-GWu_8IGyk1sLB|)meB&n6Pti!4Re;tJcW_1`V{y}J-7z5m z)2oYGWaLugB#jY#yQ{+nw)Yiq0db;Sd;008pLyn46!t_0S2s6lt-Nt_>&DIK<=0)l z9J+DykqxzonRu|2KJnFG|Bc`Dgd-kv=8KmvDPw)V*mGt<#CPNfp_Wm{IsNSbl{u@e7l78 zFDP25qW$~ZJyCvUmHs6KqY5SzOe>gIu&ChZYl6#z_Wwy`|2+!6TEXWPyd`1hMMb|w z(QlJ*_b(LxF$Eu2@CgMUG#(+oSbiQqe||mtS0BO8pI-m!SE&5)^|x~QTLu3`@&8)E zzrQZOiuUV@{#T{3O=RaRRuQ{yr$sO3O=LYvkE?^;B^J-5_S|6Hx#X)xT$Cb#j6ypp&rlID87Q? zwTf0yyiU;yiY-MeDBdsW!AB(&pHTFtBpiKO@joM>{do!Nza?S&cNG2mivA-BxBo=( zzb4_A{!GH%zmf2Te^m6>75xnflmDss|0Uu7{C8c>k8jBFd?|QCpmc6W8H$%INxz&| z{1U^#J1a_FWmy0C+70RF51si#euNl0^H0vFe^B#gq~_N@IrCELAA9HByXIv(?@BZ5 ayu88i<-hwfLHpgkb2kBh`%CE$-uz#3H*o9# diff --git a/src/mscorlib/src/System/Globalization/TaiwanCalendar.cs b/src/mscorlib/src/System/Globalization/TaiwanCalendar.cs index 060776f..2e735e0 100644 --- a/src/mscorlib/src/System/Globalization/TaiwanCalendar.cs +++ b/src/mscorlib/src/System/Globalization/TaiwanCalendar.cs @@ -2,27 +2,24 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. - using System; using System.Diagnostics.CodeAnalysis; using System.Diagnostics.Contracts; namespace System.Globalization { - /* SSS_DROP_BEGIN */ /* SSS_WARNINGS_OFF */ - /*=================================TaiwanCalendar========================== - ** - ** Taiwan calendar is based on the Gregorian calendar. And the year is an offset to Gregorian calendar. - ** That is, - ** Taiwan year = Gregorian year - 1911. So 1912/01/01 A.D. is Taiwan 1/01/01 - ** - ** Calendar support range: - ** Calendar Minimum Maximum - ** ========== ========== ========== - ** Gregorian 1912/01/01 9999/12/31 - ** Taiwan 01/01/01 8088/12/31 - ============================================================================*/ - /* SSS_WARNINGS_ON */ /* SSS_DROP_END */ + /*=================================TaiwanCalendar========================== + ** + ** Taiwan calendar is based on the Gregorian calendar. And the year is an offset to Gregorian calendar. + ** That is, + ** Taiwan year = Gregorian year - 1911. So 1912/01/01 A.D. is Taiwan 1/01/01 + ** + ** Calendar support range: + ** Calendar Minimum Maximum + ** ========== ========== ========== + ** Gregorian 1912/01/01 9999/12/31 + ** Taiwan 01/01/01 8088/12/31 + ============================================================================*/ [Serializable] public class TaiwanCalendar : Calendar @@ -39,7 +36,7 @@ namespace System.Globalization //m_EraInfo[0] = new EraInfo(1, new DateTime(1912, 1, 1).Ticks, 1911, 1, GregorianCalendar.MaxYear - 1911); // Initialize our era info. - static internal EraInfo[] taiwanEraInfo = new EraInfo[] { + internal static EraInfo[] taiwanEraInfo = new EraInfo[] { new EraInfo( 1, 1912, 1, 1, 1911, 1, GregorianCalendar.MaxYear - 1911) // era #, start year/month/day, yearOffset, minEraYear }; @@ -83,9 +80,6 @@ namespace System.Globalization } } - // Return the type of the Taiwan calendar. - // - public override CalendarAlgorithmType AlgorithmType { get @@ -94,6 +88,8 @@ namespace System.Globalization } } + // Return the type of the Taiwan calendar. + // public TaiwanCalendar() { @@ -103,16 +99,16 @@ namespace System.Globalization } catch (ArgumentException e) { - throw new TypeInitializationException(this.GetType().FullName, e); + throw new TypeInitializationException(this.GetType().ToString(), e); } helper = new GregorianCalendarHelper(this, taiwanEraInfo); } - internal override int ID + internal override CalendarId ID { get { - return (CAL_TAIWAN); + return CalendarId.TAIWAN; } } @@ -252,7 +248,7 @@ namespace System.Globalization "year", String.Format( CultureInfo.CurrentCulture, - Environment.GetResourceString("ArgumentOutOfRange_Range"), + SR.ArgumentOutOfRange_Range, 99, helper.MaxYear)); } @@ -268,7 +264,7 @@ namespace System.Globalization if (year <= 0) { throw new ArgumentOutOfRangeException(nameof(year), - Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum")); + SR.ArgumentOutOfRange_NeedPosNum); } Contract.EndContractBlock(); @@ -278,7 +274,7 @@ namespace System.Globalization nameof(year), String.Format( CultureInfo.CurrentCulture, - Environment.GetResourceString("ArgumentOutOfRange_Range"), + SR.ArgumentOutOfRange_Range, 1, helper.MaxYear)); } diff --git a/src/mscorlib/src/System/Globalization/TaiwanLunisolarCalendar.cs b/src/mscorlib/src/System/Globalization/TaiwanLunisolarCalendar.cs index 4331cb4..1f75ac9 100644 --- a/src/mscorlib/src/System/Globalization/TaiwanLunisolarCalendar.cs +++ b/src/mscorlib/src/System/Globalization/TaiwanLunisolarCalendar.cs @@ -31,7 +31,7 @@ namespace System.Globalization //m_EraInfo[0] = new EraInfo(1, new DateTime(1912, 1, 1).Ticks, 1911, 1, GregorianCalendar.MaxYear - 1911); // Initialize our era info. - static internal EraInfo[] taiwanLunisolarEraInfo = new EraInfo[] { + internal static EraInfo[] taiwanLunisolarEraInfo = new EraInfo[] { new EraInfo( 1, 1912, 1, 1, 1911, 1, GregorianCalendar.MaxYear - 1911) // era #, start year/month/day, yearOffset, minEraYear }; @@ -78,10 +78,11 @@ namespace System.Globalization } } - private static readonly int[,] yinfo = + private static readonly int[,] s_yinfo = { -/*Y LM Lmon Lday DaysPerMonth D1 D2 D3 D4 D5 D6 D7 D8 D9 D10 D11 D12 D13 #Days -1912 */{ 0 , 2 , 18 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354 + /*Y LM Lmon Lday DaysPerMonth D1 D2 D3 D4 D5 D6 D7 D8 D9 D10 D11 D12 D13 #Days + 1912 */ + { 0 , 2 , 18 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354 1913 */{ 0 , 2 , 6 , 53840 },/* 30 30 29 30 29 29 30 29 29 30 29 30 0 354 1914 */{ 5 , 1 , 26 , 54568 },/* 30 30 29 30 29 30 29 30 29 29 30 29 30 384 1915 */{ 0 , 2 , 14 , 46400 },/* 30 29 30 30 29 30 29 30 29 30 29 29 0 354 @@ -263,21 +264,21 @@ namespace System.Globalization } } - internal override int GetYearInfo(int LunarYear, int Index) + internal override int GetYearInfo(int lunarYear, int index) { - if ((LunarYear < MIN_LUNISOLAR_YEAR) || (LunarYear > MAX_LUNISOLAR_YEAR)) + if ((lunarYear < MIN_LUNISOLAR_YEAR) || (lunarYear > MAX_LUNISOLAR_YEAR)) { throw new ArgumentOutOfRangeException( "year", String.Format( CultureInfo.CurrentCulture, - Environment.GetResourceString("ArgumentOutOfRange_Range"), + SR.ArgumentOutOfRange_Range, MIN_LUNISOLAR_YEAR, MAX_LUNISOLAR_YEAR)); } Contract.EndContractBlock(); - return yinfo[LunarYear - MIN_LUNISOLAR_YEAR, Index]; + return s_yinfo[lunarYear - MIN_LUNISOLAR_YEAR, index]; } internal override int GetYear(int year, DateTime time) @@ -290,50 +291,29 @@ namespace System.Globalization return helper.GetGregorianYear(year, era); } - /*=================================GetDefaultInstance========================== - **Action: Internal method to provide a default intance of TaiwanLunisolarCalendar. Used by NLS+ implementation - ** and other calendars. - **Returns: - **Arguments: - **Exceptions: - ============================================================================*/ - /* - internal static Calendar GetDefaultInstance() - { - if (m_defaultInstance == null) { - m_defaultInstance = new TaiwanLunisolarCalendar(); - } - return (m_defaultInstance); - } - */ - - // Construct an instance of TaiwanLunisolar calendar. - public TaiwanLunisolarCalendar() { helper = new GregorianCalendarHelper(this, taiwanLunisolarEraInfo); } - - public override int GetEra(DateTime time) { return (helper.GetEra(time)); } - internal override int BaseCalendarID + internal override CalendarId BaseCalendarID { get { - return (CAL_TAIWAN); + return (CalendarId.TAIWAN); } } - internal override int ID + internal override CalendarId ID { get { - return (CAL_TAIWANLUNISOLAR); + return (CalendarId.TAIWANLUNISOLAR); } } diff --git a/src/mscorlib/src/System/Globalization/TextElementEnumerator.cs b/src/mscorlib/src/System/Globalization/TextElementEnumerator.cs index 45b7009..464897b 100644 --- a/src/mscorlib/src/System/Globalization/TextElementEnumerator.cs +++ b/src/mscorlib/src/System/Globalization/TextElementEnumerator.cs @@ -10,12 +10,9 @@ // //////////////////////////////////////////////////////////////////////////// -using System.Runtime.Serialization; - - using System.Collections; using System.Diagnostics; -using System.Diagnostics.Contracts; +using System.Runtime.Serialization; namespace System.Globalization { @@ -26,78 +23,73 @@ namespace System.Globalization [Serializable] public class TextElementEnumerator : IEnumerator { - private String str; - private int index; - private int startIndex; + private String _str; + private int _index; + private int _startIndex; - [NonSerialized] - private int strLen; // This is the length of the total string, counting from the beginning of string. + [NonSerialized] + private int _strLen; // This is the length of the total string, counting from the beginning of string. - [NonSerialized] - private int currTextElementLen; // The current text element lenght after MoveNext() is called. + [NonSerialized] + private int _currTextElementLen; // The current text element lenght after MoveNext() is called. - [OptionalField(VersionAdded = 2)] - private UnicodeCategory uc; + [OptionalField(VersionAdded = 2)] + private UnicodeCategory _uc; - [OptionalField(VersionAdded = 2)] - private int charLen; // The next abstract char to look at after MoveNext() is called. It could be 1 or 2, depending on if it is a surrogate or not. + [OptionalField(VersionAdded = 2)] + private int _charLen; // The next abstract char to look at after MoveNext() is called. It could be 1 or 2, depending on if it is a surrogate or not. internal TextElementEnumerator(String str, int startIndex, int strLen) { Debug.Assert(str != null, "TextElementEnumerator(): str != null"); Debug.Assert(startIndex >= 0 && strLen >= 0, "TextElementEnumerator(): startIndex >= 0 && strLen >= 0"); Debug.Assert(strLen >= startIndex, "TextElementEnumerator(): strLen >= startIndex"); - this.str = str; - this.startIndex = startIndex; - this.strLen = strLen; + _str = str; + _startIndex = startIndex; + _strLen = strLen; Reset(); } - #region Serialization // the following fields is defined to keep the compatibility with Everett. // don't change/remove the names/types of these fields. - private int endIndex; - private int nextTextElementLen; + private int _endIndex; + private int _nextTextElementLen; [OnDeserializing] private void OnDeserializing(StreamingContext ctx) { - charLen = -1; + _charLen = -1; } [OnDeserialized] private void OnDeserialized(StreamingContext ctx) { - strLen = endIndex + 1; - currTextElementLen = nextTextElementLen; + _strLen = _endIndex + 1; + _currTextElementLen = _nextTextElementLen; - if (charLen == -1) + if (_charLen == -1) { - uc = CharUnicodeInfo.InternalGetUnicodeCategory(str, index, out charLen); + _uc = CharUnicodeInfo.InternalGetUnicodeCategory(_str, _index, out _charLen); } } [OnSerializing] private void OnSerializing(StreamingContext ctx) { - endIndex = strLen - 1; - nextTextElementLen = currTextElementLen; + _endIndex = _strLen - 1; + _nextTextElementLen = _currTextElementLen; } - #endregion Serialization - - - public bool MoveNext() { - if (index >= strLen) + if (_index >= _strLen) { - // Make the index to be greater than strLen so that we can throw exception if GetTextElement() is called. - index = strLen + 1; + // Make the _index to be greater than _strLen so that we can throw exception if GetTextElement() is called. + _index = _strLen + 1; return (false); } - currTextElementLen = StringInfo.GetCurrentTextElementLen(str, index, strLen, ref uc, ref charLen); - index += currTextElementLen; + _currTextElementLen = StringInfo.GetCurrentTextElementLen(_str, _index, _strLen, ref _uc, ref _charLen); + _index += _currTextElementLen; return (true); } @@ -119,16 +111,16 @@ namespace System.Globalization public String GetTextElement() { - if (index == startIndex) + if (_index == _startIndex) { - throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumNotStarted")); + throw new InvalidOperationException(SR.InvalidOperation_EnumNotStarted); } - if (index > strLen) + if (_index > _strLen) { - throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumEnded")); + throw new InvalidOperationException(SR.InvalidOperation_EnumEnded); } - return (str.Substring(index - currTextElementLen, currTextElementLen)); + return (_str.Substring(_index - _currTextElementLen, _currTextElementLen)); } // @@ -139,22 +131,22 @@ namespace System.Globalization { get { - if (index == startIndex) + if (_index == _startIndex) { - throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumNotStarted")); + throw new InvalidOperationException(SR.InvalidOperation_EnumNotStarted); } - return (index - currTextElementLen); + return (_index - _currTextElementLen); } } public void Reset() { - index = startIndex; - if (index < strLen) + _index = _startIndex; + if (_index < _strLen) { // If we have more than 1 character, get the category of the current char. - uc = CharUnicodeInfo.InternalGetUnicodeCategory(str, index, out charLen); + _uc = CharUnicodeInfo.InternalGetUnicodeCategory(_str, _index, out _charLen); } } } diff --git a/src/mscorlib/corefx/System/Globalization/TextInfo.Unix.cs b/src/mscorlib/src/System/Globalization/TextInfo.Unix.cs similarity index 100% rename from src/mscorlib/corefx/System/Globalization/TextInfo.Unix.cs rename to src/mscorlib/src/System/Globalization/TextInfo.Unix.cs diff --git a/src/mscorlib/corefx/System/Globalization/TextInfo.Windows.cs b/src/mscorlib/src/System/Globalization/TextInfo.Windows.cs similarity index 90% rename from src/mscorlib/corefx/System/Globalization/TextInfo.Windows.cs rename to src/mscorlib/src/System/Globalization/TextInfo.Windows.cs index b2f692e..052e95a 100644 --- a/src/mscorlib/corefx/System/Globalization/TextInfo.Windows.cs +++ b/src/mscorlib/src/System/Globalization/TextInfo.Windows.cs @@ -24,12 +24,12 @@ namespace System.Globalization FinishInitialization(_textInfoName); } - private void FinishInitialization(string textInfoName) + private unsafe void FinishInitialization(string textInfoName) { const uint LCMAP_SORTHANDLE = 0x20000000; long handle; - int ret = Interop.mincore.LCMapStringEx(_textInfoName, LCMAP_SORTHANDLE, null, 0, &handle, IntPtr.Size, null, null, IntPtr.Zero); + int ret = Interop.Kernel32.LCMapStringEx(_textInfoName, LCMAP_SORTHANDLE, null, 0, &handle, IntPtr.Size, null, null, IntPtr.Zero); _sortHandle = ret > 0 ? (IntPtr)handle : IntPtr.Zero; } @@ -64,7 +64,7 @@ namespace System.Globalization fixed (char* pSource = s) fixed (char* pResult = result) { - ret = Interop.mincore.LCMapStringEx(_sortHandle != IntPtr.Zero ? null : _textInfoName, + ret = Interop.Kernel32.LCMapStringEx(_sortHandle != IntPtr.Zero ? null : _textInfoName, toUpper ? LCMAP_UPPERCASE | linguisticCasing : LCMAP_LOWERCASE | linguisticCasing, pSource, nLengthInput, @@ -92,7 +92,7 @@ namespace System.Globalization // Check for Invariant to avoid A/V in LCMapStringEx uint linguisticCasing = IsInvariantLocale(_textInfoName) ? 0 : LCMAP_LINGUISTIC_CASING; - Interop.mincore.LCMapStringEx(_sortHandle != IntPtr.Zero ? null : _textInfoName, + Interop.Kernel32.LCMapStringEx(_sortHandle != IntPtr.Zero ? null : _textInfoName, toUpper ? LCMAP_UPPERCASE | linguisticCasing : LCMAP_LOWERCASE | linguisticCasing, &c, 1, @@ -107,7 +107,7 @@ namespace System.Globalization // PAL Ends here - private readonly IntPtr _sortHandle; + private IntPtr _sortHandle; private const uint LCMAP_LINGUISTIC_CASING = 0x01000000; private const uint LCMAP_LOWERCASE = 0x00000100; diff --git a/src/mscorlib/src/System/Globalization/TextInfo.cs b/src/mscorlib/src/System/Globalization/TextInfo.cs index d698e64..00a416e 100644 --- a/src/mscorlib/src/System/Globalization/TextInfo.cs +++ b/src/mscorlib/src/System/Globalization/TextInfo.cs @@ -12,28 +12,19 @@ // //////////////////////////////////////////////////////////////////////////// -using System.Security; +using System.Diagnostics; +using System.Diagnostics.Contracts; +using System.Runtime.Serialization; +using System.Text; namespace System.Globalization { - using System; - using System.Text; - using System.Threading; - using System.Runtime; - using System.Runtime.InteropServices; - using System.Runtime.CompilerServices; - using System.Runtime.Serialization; - using System.Runtime.Versioning; - using System.Diagnostics; - using System.Diagnostics.Contracts; - - [Serializable] public partial class TextInfo : ICloneable, IDeserializationCallback { - //--------------------------------------------------------------------// - // Internal Information // - //--------------------------------------------------------------------// + ////--------------------------------------------------------------------// + //// Internal Information // + ////--------------------------------------------------------------------// private enum Tristate : byte { @@ -42,44 +33,33 @@ namespace System.Globalization False, } - // - // Variables. - // + //// + //// Variables. + //// [OptionalField(VersionAdded = 2)] - private String m_listSeparator; - + private String _listSeparator; [OptionalField(VersionAdded = 2)] - private bool m_isReadOnly = false; - - // - // In Whidbey we had several names: - // m_win32LangID is the name of the culture, but only used for (de)serialization. - // customCultureName is the name of the creating custom culture (if custom) In combination with m_win32LangID - // this is authoratative, ie when deserializing. - // m_cultureTableRecord was the data record of the creating culture. (could have different name if custom) - // m_textInfoID is the LCID of the textinfo itself (no longer used) - // m_name is the culture name (from cultureinfo.name) - // - // In Silverlight/Arrowhead this is slightly different: - // m_cultureName is the name of the creating culture. Note that we consider this authoratative, - // if the culture's textinfo changes when deserializing, then behavior may change. - // (ala Whidbey behavior). This is the only string Arrowhead needs to serialize. - // m_cultureData is the data that backs this class. - // m_textInfoName is the actual name of the textInfo (from cultureData.STEXTINFO) - // m_textInfoName can be the same as m_cultureName on Silverlight since the OS knows - // how to do the sorting. However in the desktop, when we call the sorting dll, it doesn't - // know how to resolve custom locle names to sort ids so we have to have alredy resolved this. - // + private bool _isReadOnly = false; + + //// _cultureName is the name of the creating culture. Note that we consider this authoratative, + //// if the culture's textinfo changes when deserializing, then behavior may change. + //// (ala Whidbey behavior). This is the only string Arrowhead needs to serialize. + //// _cultureData is the data that backs this class. + //// _textInfoName is the actual name of the textInfo (from cultureData.STEXTINFO) + //// this can be the same as _cultureName on Silverlight since the OS knows + //// how to do the sorting. However in the desktop, when we call the sorting dll, it doesn't + //// know how to resolve custom locle names to sort ids so we have to have alredy resolved this. + //// [OptionalField(VersionAdded = 3)] - private String m_cultureName; // Name of the culture that created this text info - [NonSerialized] private CultureData m_cultureData; // Data record for the culture that made us, not for this textinfo - [NonSerialized] private String m_textInfoName; // Name of the text info we're using (ie: m_cultureData.STEXTINFO) - [NonSerialized] private IntPtr m_dataHandle; // Sort handle - [NonSerialized] private IntPtr m_handleOrigin; - [NonSerialized] private Tristate m_IsAsciiCasingSameAsInvariant = Tristate.NotInitialized; - + private String _cultureName; // Name of the culture that created this text info + [NonSerialized] + private CultureData _cultureData; // Data record for the culture that made us, not for this textinfo + [NonSerialized] + private String _textInfoName; // Name of the text info we're using (ie: _cultureData.STEXTINFO) + [NonSerialized] + private Tristate _isAsciiCasingSameAsInvariant = Tristate.NotInitialized; // Invariant text info internal static TextInfo Invariant @@ -93,88 +73,15 @@ namespace System.Globalization } internal volatile static TextInfo s_Invariant; - //////////////////////////////////////////////////////////////////////// - // - // TextInfo Constructors - // - // Implements CultureInfo.TextInfo. - // - //////////////////////////////////////////////////////////////////////// - internal TextInfo(CultureData cultureData) - { - // This is our primary data source, we don't need most of the rest of this - m_cultureData = cultureData; - m_cultureName = m_cultureData.CultureName; - m_textInfoName = m_cultureData.STEXTINFO; - } - - //////////////////////////////////////////////////////////////////////// - // - // Serialization / Deserialization - // - // Note that we have to respect the Whidbey behavior for serialization compatibility - // - //////////////////////////////////////////////////////////////////////// - - #region Serialization - // the following fields are defined to keep the compatibility with Whidbey. - // don't change/remove the names/types of these fields. - [OptionalField(VersionAdded = 2)] - private string customCultureName; - - // the following fields are defined to keep compatibility with Everett. - // don't change/remove the names/types of these fields. - [OptionalField(VersionAdded = 1)] - internal int m_nDataItem; - [OptionalField(VersionAdded = 1)] - internal bool m_useUserOverride; - [OptionalField(VersionAdded = 1)] - internal int m_win32LangID; - + [OnSerializing] + private void OnSerializing(StreamingContext ctx) { } [OnDeserializing] private void OnDeserializing(StreamingContext ctx) { // Clear these so we can check if we've fixed them yet - m_cultureData = null; - m_cultureName = null; - } - - private void OnDeserialized() - { - // this method will be called twice because of the support of IDeserializationCallback - if (m_cultureData == null) - { - if (m_cultureName == null) - { - // This is whidbey data, get it from customCultureName/win32langid - if (customCultureName != null) - { - // They gave a custom cultuer name, so use that - m_cultureName = customCultureName; - } -#if FEATURE_USE_LCID - else - { - if (m_win32LangID == 0) - { - // m_cultureName and m_win32LangID are nulls which means we got uninitialized textinfo serialization stream. - // To be compatible with v2/3/3.5 we need to return ar-SA TextInfo in this case. - m_cultureName = "ar-SA"; - } - else - { - // No custom culture, use the name from the LCID - m_cultureName = CultureInfo.GetCultureInfo(m_win32LangID).m_cultureData.CultureName; - } - } -#endif - } - - // Get the text info name belonging to that culture - m_cultureData = CultureInfo.GetCultureInfo(m_cultureName).m_cultureData; - m_textInfoName = m_cultureData.STEXTINFO; - } + _cultureData = null; + _cultureName = null; } [OnDeserialized] @@ -183,142 +90,56 @@ namespace System.Globalization OnDeserialized(); } - [OnSerializing] - private void OnSerializing(StreamingContext ctx) + void IDeserializationCallback.OnDeserialization(Object sender) { - // Relabel our name since Whidbey expects it to be called customCultureName - customCultureName = m_cultureName; - -#if FEATURE_USE_LCID - // Ignore the m_win32LangId because whidbey'll just get it by name if we make it the LOCALE_CUSTOM_UNSPECIFIED. - this.m_win32LangID = (CultureInfo.GetCultureInfo(m_cultureName)).LCID; -#endif + OnDeserialized(); } - #endregion Serialization + private void OnDeserialized() + { + // this method will be called twice because of the support of IDeserializationCallback + if (_cultureData == null) + { + // Get the text info name belonging to that culture + _cultureData = CultureInfo.GetCultureInfo(_cultureName)._cultureData; + _textInfoName = _cultureData.STEXTINFO; + FinishInitialization(_textInfoName); + } + } // // Internal ordinal comparison functions // - internal static int GetHashCodeOrdinalIgnoreCase(String s) - { - return GetHashCodeOrdinalIgnoreCase(s, false, 0); - } - internal static int GetHashCodeOrdinalIgnoreCase(String s, bool forceRandomizedHashing, long additionalEntropy) + internal static int GetHashCodeOrdinalIgnoreCase(String s) { // This is the same as an case insensitive hash for Invariant // (not necessarily true for sorting, but OK for casing & then we apply normal hash code rules) - return (Invariant.GetCaseInsensitiveHashCode(s, forceRandomizedHashing, additionalEntropy)); - } - - internal static unsafe bool TryFastFindStringOrdinalIgnoreCase(int searchFlags, String source, int startIndex, String value, int count, ref int foundIndex) - { - return InternalTryFindStringOrdinalIgnoreCase(searchFlags, source, count, startIndex, value, value.Length, ref foundIndex); - } - - // This function doesn't check arguments. Please do check in the caller. - // The underlying unmanaged code will assert the sanity of arguments. - internal static unsafe int CompareOrdinalIgnoreCase(String str1, String str2) - { - // Compare the whole string and ignore case. - return InternalCompareStringOrdinalIgnoreCase(str1, 0, str2, 0, str1.Length, str2.Length); - } - - // This function doesn't check arguments. Please do check in the caller. - // The underlying unmanaged code will assert the sanity of arguments. - internal static unsafe int CompareOrdinalIgnoreCaseEx(String strA, int indexA, String strB, int indexB, int lengthA, int lengthB) - { - Debug.Assert(strA.Length >= indexA + lengthA, "[TextInfo.CompareOrdinalIgnoreCaseEx] Caller should've validated strA.Length >= indexA + lengthA"); - Debug.Assert(strB.Length >= indexB + lengthB, "[TextInfo.CompareOrdinalIgnoreCaseEx] Caller should've validated strB.Length >= indexB + lengthB"); - return InternalCompareStringOrdinalIgnoreCase(strA, indexA, strB, indexB, lengthA, lengthB); + return (Invariant.GetCaseInsensitiveHashCode(s)); } + // Currently we don't have native functions to do this, so we do it the hard way internal static int IndexOfStringOrdinalIgnoreCase(String source, String value, int startIndex, int count) { - Debug.Assert(source != null, "[TextInfo.IndexOfStringOrdinalIgnoreCase] Caller should've validated source != null"); - Debug.Assert(value != null, "[TextInfo.IndexOfStringOrdinalIgnoreCase] Caller should've validated value != null"); - Debug.Assert(startIndex + count <= source.Length, "[TextInfo.IndexOfStringOrdinalIgnoreCase] Caller should've validated startIndex + count <= source.Length"); - - // We return 0 if both inputs are empty strings - if (source.Length == 0 && value.Length == 0) + if (count > source.Length || count < 0 || startIndex < 0 || startIndex >= source.Length || startIndex + count > source.Length) { - return 0; + return -1; } - // fast path - int ret = -1; - if (TryFastFindStringOrdinalIgnoreCase(Microsoft.Win32.Win32Native.FIND_FROMSTART, source, startIndex, value, count, ref ret)) - return ret; - - // the search space within [source] starts at offset [startIndex] inclusive and includes - // [count] characters (thus the last included character is at index [startIndex + count -1] - // [end] is the index of the next character after the search space - // (it points past the end of the search space) - int end = startIndex + count; - - // maxStartIndex is the index beyond which we never *start* searching, inclusive; in other words; - // a search could include characters beyond maxStartIndex, but we'd never begin a search at an - // index strictly greater than maxStartIndex. - int maxStartIndex = end - value.Length; - - for (; startIndex <= maxStartIndex; startIndex++) - { - // We should always have the same or more characters left to search than our actual pattern - Debug.Assert(end - startIndex >= value.Length); - // since this is an ordinal comparison, we can assume that the lengths must match - if (CompareOrdinalIgnoreCaseEx(source, startIndex, value, 0, value.Length, value.Length) == 0) - { - return startIndex; - } - } - - // Not found - return -1; + return CompareInfo.IndexOfOrdinal(source, value, startIndex, count, ignoreCase: true); } + // Currently we don't have native functions to do this, so we do it the hard way internal static int LastIndexOfStringOrdinalIgnoreCase(String source, String value, int startIndex, int count) { - Debug.Assert(source != null, "[TextInfo.LastIndexOfStringOrdinalIgnoreCase] Caller should've validated source != null"); - Debug.Assert(value != null, "[TextInfo.LastIndexOfStringOrdinalIgnoreCase] Caller should've validated value != null"); - Debug.Assert(startIndex - count + 1 >= 0, "[TextInfo.LastIndexOfStringOrdinalIgnoreCase] Caller should've validated startIndex - count+1 >= 0"); - Debug.Assert(startIndex <= source.Length, "[TextInfo.LastIndexOfStringOrdinalIgnoreCase] Caller should've validated startIndex <= source.Length"); - - // If value is Empty, the return value is startIndex - if (value.Length == 0) - { - return startIndex; - } - - // fast path - int ret = -1; - if (TryFastFindStringOrdinalIgnoreCase(Microsoft.Win32.Win32Native.FIND_FROMEND, source, startIndex, value, count, ref ret)) - return ret; - - // the search space within [source] ends at offset [startIndex] inclusive - // and includes [count] characters - // minIndex is the first included character and is at index [startIndex - count + 1] - int minIndex = startIndex - count + 1; - - // First place we can find it is start index - (value.length -1) - if (value.Length > 0) + if (count > source.Length || count < 0 || startIndex < 0 || startIndex > source.Length - 1 || (startIndex - count + 1 < 0)) { - startIndex -= (value.Length - 1); + return -1; } - for (; startIndex >= minIndex; startIndex--) - { - if (CompareOrdinalIgnoreCaseEx(source, startIndex, value, 0, value.Length, value.Length) == 0) - { - return startIndex; - } - } - - // Not found - return -1; + return CompareInfo.LastIndexOfOrdinal(source, value, startIndex, count, ignoreCase: true); } - //////////////////////////////////////////////////////////////////////// // // CodePage @@ -336,7 +157,7 @@ namespace System.Globalization { get { - return (m_cultureData.IDEFAULTANSICODEPAGE); + return (_cultureData.IDEFAULTANSICODEPAGE); } } @@ -345,7 +166,7 @@ namespace System.Globalization { get { - return (m_cultureData.IDEFAULTOEMCODEPAGE); + return (_cultureData.IDEFAULTOEMCODEPAGE); } } @@ -354,7 +175,7 @@ namespace System.Globalization { get { - return (m_cultureData.IDEFAULTMACCODEPAGE); + return (_cultureData.IDEFAULTMACCODEPAGE); } } @@ -363,41 +184,31 @@ namespace System.Globalization { get { - return (m_cultureData.IDEFAULTEBCDICCODEPAGE); + return (_cultureData.IDEFAULTEBCDICCODEPAGE); } } - //////////////////////////////////////////////////////////////////////// - // - // LCID - // - // We need a way to get an LCID from outside of the BCL. This prop is the way. - // NOTE: neutral cultures will cause GPS incorrect LCIDS from this - // - //////////////////////////////////////////////////////////////////////// - -#if FEATURE_USE_LCID - public int LCID + public int LCID { get { // Just use the LCID from our text info name - return CultureInfo.GetCultureInfo(m_textInfoName).LCID; + return CultureInfo.GetCultureInfo(_textInfoName).LCID; } } -#endif - //////////////////////////////////////////////////////////////////////// - // - // CultureName - // - // The name of the culture associated with the current TextInfo. - // - //////////////////////////////////////////////////////////////////////// + + ////////////////////////////////////////////////////////////////////////// + //// + //// CultureName + //// + //// The name of the culture associated with the current TextInfo. + //// + ////////////////////////////////////////////////////////////////////////// public string CultureName { get { - return (m_textInfoName); + return _textInfoName; } } @@ -410,17 +221,17 @@ namespace System.Globalization //////////////////////////////////////////////////////////////////////// public bool IsReadOnly { - get { return (m_isReadOnly); } + get { return (_isReadOnly); } } - //////////////////////////////////////////////////////////////////////// - // - // Clone - // - // Is the implementation of ICloneable. - // - //////////////////////////////////////////////////////////////////////// - public virtual Object Clone() + ////////////////////////////////////////////////////////////////////////// + //// + //// Clone + //// + //// Is the implementation of ICloneable. + //// + ////////////////////////////////////////////////////////////////////////// + public virtual object Clone() { object o = MemberwiseClone(); ((TextInfo)o).SetReadOnlyState(false); @@ -449,16 +260,15 @@ namespace System.Globalization private void VerifyWritable() { - if (m_isReadOnly) + if (_isReadOnly) { - throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly")); + throw new InvalidOperationException(SR.InvalidOperation_ReadOnly); } - Contract.EndContractBlock(); } internal void SetReadOnlyState(bool readOnly) { - m_isReadOnly = readOnly; + _isReadOnly = readOnly; } @@ -469,28 +279,25 @@ namespace System.Globalization // Returns the string used to separate items in a list. // //////////////////////////////////////////////////////////////////////// - - public virtual String ListSeparator { get { - if (m_listSeparator == null) + if (_listSeparator == null) { - m_listSeparator = m_cultureData.SLIST; + _listSeparator = _cultureData.SLIST; } - return (m_listSeparator); + return (_listSeparator); } set { if (value == null) { - throw new ArgumentNullException(nameof(value), Environment.GetResourceString("ArgumentNull_String")); + throw new ArgumentNullException(nameof(value), SR.ArgumentNull_String); } - Contract.EndContractBlock(); VerifyWritable(); - m_listSeparator = value; + _listSeparator = value; } } @@ -502,27 +309,25 @@ namespace System.Globalization // have different casing semantics from the file systems in Win32. // //////////////////////////////////////////////////////////////////////// - public unsafe virtual char ToLower(char c) { if (IsAscii(c) && IsAsciiCasingSameAsInvariant) { return ToLowerAsciiInvariant(c); } - return (InternalChangeCaseChar(m_dataHandle, m_handleOrigin, m_textInfoName, c, false)); + return (ChangeCase(c, toUpper: false)); } public unsafe virtual String ToLower(String str) { if (str == null) { throw new ArgumentNullException(nameof(str)); } - Contract.EndContractBlock(); - return InternalChangeCaseString(m_dataHandle, m_handleOrigin, m_textInfoName, str, false); + return ChangeCase(str, toUpper: false); } - static private Char ToLowerAsciiInvariant(Char c) + private static Char ToLowerAsciiInvariant(Char c) { - if ('A' <= c && c <= 'Z') + if ((uint)(c - 'A') <= (uint)('Z' - 'A')) { c = (Char)(c | 0x20); } @@ -537,34 +342,32 @@ namespace System.Globalization // have different casing semantics from the file systems in Win32. // //////////////////////////////////////////////////////////////////////// - public unsafe virtual char ToUpper(char c) { if (IsAscii(c) && IsAsciiCasingSameAsInvariant) { return ToUpperAsciiInvariant(c); } - return (InternalChangeCaseChar(m_dataHandle, m_handleOrigin, m_textInfoName, c, true)); + return (ChangeCase(c, toUpper: true)); } - public unsafe virtual String ToUpper(String str) { if (str == null) { throw new ArgumentNullException(nameof(str)); } - Contract.EndContractBlock(); - return InternalChangeCaseString(m_dataHandle, m_handleOrigin, m_textInfoName, str, true); + + return ChangeCase(str, toUpper: true); } - static private Char ToUpperAsciiInvariant(Char c) + private static Char ToUpperAsciiInvariant(Char c) { - if ('a' <= c && c <= 'z') + if ((uint)(c - 'a') <= (uint)('z' - 'a')) { c = (Char)(c & ~0x20); } return c; } - static private bool IsAscii(Char c) + private static bool IsAscii(Char c) { return c < 0x80; } @@ -573,14 +376,25 @@ namespace System.Globalization { get { - if (m_IsAsciiCasingSameAsInvariant == Tristate.NotInitialized) + if (_isAsciiCasingSameAsInvariant == Tristate.NotInitialized) { - m_IsAsciiCasingSameAsInvariant = - CultureInfo.GetCultureInfo(m_textInfoName).CompareInfo.Compare("abcdefghijklmnopqrstuvwxyz", + _isAsciiCasingSameAsInvariant = CultureInfo.GetCultureInfo(_textInfoName).CompareInfo.Compare("abcdefghijklmnopqrstuvwxyz", "ABCDEFGHIJKLMNOPQRSTUVWXYZ", CompareOptions.IgnoreCase) == 0 ? Tristate.True : Tristate.False; } - return m_IsAsciiCasingSameAsInvariant == Tristate.True; + return _isAsciiCasingSameAsInvariant == Tristate.True; + } + } + + // IsRightToLeft + // + // Returns true if the dominant direction of text and UI such as the relative position of buttons and scroll bars + // + public bool IsRightToLeft + { + get + { + return _cultureData.IsRightToLeft; } } @@ -592,8 +406,6 @@ namespace System.Globalization // or not object refers to the same CultureInfo as the current instance. // //////////////////////////////////////////////////////////////////////// - - public override bool Equals(Object obj) { TextInfo that = obj as TextInfo; @@ -606,7 +418,6 @@ namespace System.Globalization return (false); } - //////////////////////////////////////////////////////////////////////// // // GetHashCode @@ -616,14 +427,11 @@ namespace System.Globalization // and B where A.Equals(B) is true. // //////////////////////////////////////////////////////////////////////// - - public override int GetHashCode() { return (this.CultureName.GetHashCode()); } - //////////////////////////////////////////////////////////////////////// // // ToString @@ -632,14 +440,11 @@ namespace System.Globalization // TextInfo. // //////////////////////////////////////////////////////////////////////// - - public override String ToString() { - return ("TextInfo - " + m_cultureData.CultureName); + return ("TextInfo - " + _cultureData.CultureName); } - // // Titlecasing: // ----------- @@ -654,15 +459,6 @@ namespace System.Globalization // influence which letter or letters of a "word" are uppercased when titlecasing strings. For example // "l'arbre" is considered two words in French, whereas "can't" is considered one word in English. // - // - // Differences between UNICODE 5.0 and the .NET Framework: - // ------------------------------------------------------------------------------------- - // The .NET Framework previously shipped a naive titlecasing implementation. Every word is titlecased - // regardless of language or orthographic practice. Furthermore, apostrophe is always considered to be - // a word joiner as used in English. The longterm vision is to depend on the operating system for - // titlecasing. Windows 7 is expected to be the first release with this feature. On the Macintosh side, - // titlecasing is not available as of version 10.5 of the operating system. - // public unsafe String ToTitleCase(String str) { if (str == null) @@ -676,7 +472,7 @@ namespace System.Globalization } StringBuilder result = new StringBuilder(); - String lowercaseData = null; + string lowercaseData = null; for (int i = 0; i < str.Length; i++) { @@ -734,7 +530,7 @@ namespace System.Globalization { // This category is considered to be part of the word. // This is any category that is marked as false in wordSeprator array. - i += charLen; + i+= charLen; } else { @@ -792,7 +588,6 @@ namespace System.Globalization return inputIndex; } - private int AddTitlecaseLetter(ref StringBuilder result, ref String input, int inputIndex, int charLen) { Debug.Assert(charLen == 1 || charLen == 2, "[TextInfo.AddTitlecaseLetter] CharUnicodeInfo.InternalGetUnicodeCategory returned an unexpected charLen!"); @@ -801,7 +596,7 @@ namespace System.Globalization if (charLen == 2) { // Surrogate pair - result.Append(this.ToUpper(input.Substring(inputIndex, charLen))); + result.Append(ToUpper(input.Substring(inputIndex, charLen))); inputIndex++; } else @@ -810,75 +605,74 @@ namespace System.Globalization { // // For AppCompat, the Titlecase Case Mapping data from NDP 2.0 is used below. - case (char)0x01C4: // DZ with Caron -> Dz with Caron - case (char)0x01C5: // Dz with Caron -> Dz with Caron - case (char)0x01C6: // dz with Caron -> Dz with Caron - result.Append((char)0x01C5); + case (char) 0x01C4: // DZ with Caron -> Dz with Caron + case (char) 0x01C5: // Dz with Caron -> Dz with Caron + case (char) 0x01C6: // dz with Caron -> Dz with Caron + result.Append((char) 0x01C5); break; - case (char)0x01C7: // LJ -> Lj - case (char)0x01C8: // Lj -> Lj - case (char)0x01C9: // lj -> Lj - result.Append((char)0x01C8); + case (char) 0x01C7: // LJ -> Lj + case (char) 0x01C8: // Lj -> Lj + case (char) 0x01C9: // lj -> Lj + result.Append((char) 0x01C8); break; - case (char)0x01CA: // NJ -> Nj - case (char)0x01CB: // Nj -> Nj - case (char)0x01CC: // nj -> Nj - result.Append((char)0x01CB); + case (char) 0x01CA: // NJ -> Nj + case (char) 0x01CB: // Nj -> Nj + case (char) 0x01CC: // nj -> Nj + result.Append((char) 0x01CB); break; - case (char)0x01F1: // DZ -> Dz - case (char)0x01F2: // Dz -> Dz - case (char)0x01F3: // dz -> Dz - result.Append((char)0x01F2); + case (char) 0x01F1: // DZ -> Dz + case (char) 0x01F2: // Dz -> Dz + case (char) 0x01F3: // dz -> Dz + result.Append((char) 0x01F2); break; default: - result.Append(this.ToUpper(input[inputIndex])); + result.Append(ToUpper(input[inputIndex])); break; } } return inputIndex; } - // // Used in ToTitleCase(): // When we find a starting letter, the following array decides if a category should be // considered as word seprator or not. // - private const int wordSeparatorMask = - /* false */ (0 << 0) | // UppercaseLetter = 0, - /* false */ (0 << 1) | // LowercaseLetter = 1, - /* false */ (0 << 2) | // TitlecaseLetter = 2, - /* false */ (0 << 3) | // ModifierLetter = 3, - /* false */ (0 << 4) | // OtherLetter = 4, - /* false */ (0 << 5) | // NonSpacingMark = 5, - /* false */ (0 << 6) | // SpacingCombiningMark = 6, - /* false */ (0 << 7) | // EnclosingMark = 7, - /* false */ (0 << 8) | // DecimalDigitNumber = 8, - /* false */ (0 << 9) | // LetterNumber = 9, - /* false */ (0 << 10) | // OtherNumber = 10, - /* true */ (1 << 11) | // SpaceSeparator = 11, - /* true */ (1 << 12) | // LineSeparator = 12, - /* true */ (1 << 13) | // ParagraphSeparator = 13, - /* true */ (1 << 14) | // Control = 14, - /* true */ (1 << 15) | // Format = 15, - /* false */ (0 << 16) | // Surrogate = 16, - /* false */ (0 << 17) | // PrivateUse = 17, - /* true */ (1 << 18) | // ConnectorPunctuation = 18, - /* true */ (1 << 19) | // DashPunctuation = 19, - /* true */ (1 << 20) | // OpenPunctuation = 20, - /* true */ (1 << 21) | // ClosePunctuation = 21, - /* true */ (1 << 22) | // InitialQuotePunctuation = 22, - /* true */ (1 << 23) | // FinalQuotePunctuation = 23, - /* true */ (1 << 24) | // OtherPunctuation = 24, - /* true */ (1 << 25) | // MathSymbol = 25, - /* true */ (1 << 26) | // CurrencySymbol = 26, - /* true */ (1 << 27) | // ModifierSymbol = 27, - /* true */ (1 << 28) | // OtherSymbol = 28, - /* false */ (0 << 29); // OtherNotAssigned = 29; - - private static bool IsWordSeparator(UnicodeCategory category) - { - return (wordSeparatorMask & (1 << (int)category)) != 0; + private const int c_wordSeparatorMask = + /* false */ (0 << 0) | // UppercaseLetter = 0, + /* false */ (0 << 1) | // LowercaseLetter = 1, + /* false */ (0 << 2) | // TitlecaseLetter = 2, + /* false */ (0 << 3) | // ModifierLetter = 3, + /* false */ (0 << 4) | // OtherLetter = 4, + /* false */ (0 << 5) | // NonSpacingMark = 5, + /* false */ (0 << 6) | // SpacingCombiningMark = 6, + /* false */ (0 << 7) | // EnclosingMark = 7, + /* false */ (0 << 8) | // DecimalDigitNumber = 8, + /* false */ (0 << 9) | // LetterNumber = 9, + /* false */ (0 << 10) | // OtherNumber = 10, + /* true */ (1 << 11) | // SpaceSeparator = 11, + /* true */ (1 << 12) | // LineSeparator = 12, + /* true */ (1 << 13) | // ParagraphSeparator = 13, + /* true */ (1 << 14) | // Control = 14, + /* true */ (1 << 15) | // Format = 15, + /* false */ (0 << 16) | // Surrogate = 16, + /* false */ (0 << 17) | // PrivateUse = 17, + /* true */ (1 << 18) | // ConnectorPunctuation = 18, + /* true */ (1 << 19) | // DashPunctuation = 19, + /* true */ (1 << 20) | // OpenPunctuation = 20, + /* true */ (1 << 21) | // ClosePunctuation = 21, + /* true */ (1 << 22) | // InitialQuotePunctuation = 22, + /* true */ (1 << 23) | // FinalQuotePunctuation = 23, + /* true */ (1 << 24) | // OtherPunctuation = 24, + /* true */ (1 << 25) | // MathSymbol = 25, + /* true */ (1 << 26) | // CurrencySymbol = 26, + /* true */ (1 << 27) | // ModifierSymbol = 27, + /* true */ (1 << 28) | // OtherSymbol = 28, + /* false */ (0 << 29); // OtherNotAssigned = 29; + + private static bool IsWordSeparator(UnicodeCategory category) + { + return (c_wordSeparatorMask & (1 << (int) category)) != 0; } private static bool IsLetterCategory(UnicodeCategory uc) @@ -890,75 +684,63 @@ namespace System.Globalization || uc == UnicodeCategory.OtherLetter); } - // IsRightToLeft - // - // Returns true if the dominant direction of text and UI such as the relative position of buttons and scroll bars - // - public bool IsRightToLeft - { - get - { - return m_cultureData.IsRightToLeft; - } - } - - /// - void IDeserializationCallback.OnDeserialization(Object sender) - { - OnDeserialized(); - } - // // Get case-insensitive hash code for the specified string. // - // NOTENOTE: this is an internal function. The caller should verify the string - // is not null before calling this. Currenlty, CaseInsensitiveHashCodeProvider - // does that. - // internal unsafe int GetCaseInsensitiveHashCode(String str) { - return GetCaseInsensitiveHashCode(str, false, 0); - } - - internal unsafe int GetCaseInsensitiveHashCode(String str, bool forceRandomizedHashing, long additionalEntropy) - { // Validate inputs if (str == null) { throw new ArgumentNullException(nameof(str)); } - Contract.EndContractBlock(); - // Return our result - return (InternalGetCaseInsHash(m_dataHandle, m_handleOrigin, m_textInfoName, str, forceRandomizedHashing, additionalEntropy)); + // This code assumes that ASCII casing is safe for whatever context is passed in. + // this is true today, because we only ever call these methods on Invariant. It would be ideal to refactor + // these methods so they were correct by construction and we could only ever use Invariant. + + uint hash = 5381; + uint c; + + // Note: We assume that str contains only ASCII characters until + // we hit a non-ASCII character to optimize the common case. + for (int i = 0; i < str.Length; i++) + { + c = str[i]; + if (c >= 0x80) + { + return GetCaseInsensitiveHashCodeSlow(str); + } + + // If we have a lowercase character, ANDing off 0x20 + // will make it an uppercase character. + if ((c - 'a') <= ('z' - 'a')) + { + c = (uint)((int)c & ~0x20); + } + + hash = ((hash << 5) + hash) ^ c; + } + + return (int)hash; } - // Change case (ToUpper/ToLower) -- COMNlsInfo::InternalChangeCaseChar - [MethodImplAttribute(MethodImplOptions.InternalCall)] - private static unsafe extern char InternalChangeCaseChar(IntPtr handle, IntPtr handleOrigin, String localeName, char ch, bool isToUpper); + private unsafe int GetCaseInsensitiveHashCodeSlow(String str) + { + Debug.Assert(str != null); - // Change case (ToUpper/ToLower) -- COMNlsInfo::InternalChangeCaseString - [MethodImplAttribute(MethodImplOptions.InternalCall)] - private static unsafe extern String InternalChangeCaseString(IntPtr handle, IntPtr handleOrigin, String localeName, String str, bool isToUpper); + string upper = ToUpper(str); - // Get case insensitive hash -- ComNlsInfo::InternalGetCaseInsHash - [MethodImplAttribute(MethodImplOptions.InternalCall)] - private static unsafe extern int InternalGetCaseInsHash(IntPtr handle, IntPtr handleOrigin, String localeName, String str, bool forceRandomizedHashing, long additionalEntropy); + uint hash = 5381; + uint c; - // Call ::CompareStringOrdinal -- ComNlsInfo::InternalCompareStringOrdinalIgnoreCase - // Start at indexes and compare for length characters (or remainder of string if length == -1) - [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] - [SuppressUnmanagedCodeSecurity] - private static unsafe extern int InternalCompareStringOrdinalIgnoreCase(String string1, int index1, String string2, int index2, int length1, int length2); + for (int i = 0; i < upper.Length; i++) + { + c = upper[i]; + hash = ((hash << 5) + hash) ^ c; + } - // ComNlsInfo::InternalTryFindStringOrdinalIgnoreCase attempts a faster IndexOf/LastIndexOf OrdinalIgnoreCase using a kernel function. - // Returns true if FindStringOrdinal was handled, with foundIndex set to the target's index into the source - // Returns false when FindStringOrdinal wasn't handled - [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] - [SuppressUnmanagedCodeSecurity] - [return: MarshalAs(UnmanagedType.Bool)] - private static unsafe extern bool InternalTryFindStringOrdinalIgnoreCase(int searchFlags, String source, int sourceCount, int startIndex, String target, int targetCount, ref int foundIndex); + return (int)hash; + } } } - - diff --git a/src/mscorlib/src/System/Globalization/ThaiBuddhistCalendar.cs b/src/mscorlib/src/System/Globalization/ThaiBuddhistCalendar.cs index 65489ce..9e6e304 100644 --- a/src/mscorlib/src/System/Globalization/ThaiBuddhistCalendar.cs +++ b/src/mscorlib/src/System/Globalization/ThaiBuddhistCalendar.cs @@ -2,7 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. - using System; using System.Diagnostics.CodeAnalysis; using System.Diagnostics.Contracts; @@ -21,12 +20,11 @@ namespace System.Globalization ** Thai 0544/01/01 10542/12/31 ============================================================================*/ - [Serializable] public class ThaiBuddhistCalendar : Calendar { // Initialize our era info. - static internal EraInfo[] thaiBuddhistEraInfo = new EraInfo[] { + internal static EraInfo[] thaiBuddhistEraInfo = new EraInfo[] { new EraInfo( 1, 1, 1, 1, -543, 544, GregorianCalendar.MaxYear + 543) // era #, start year/month/day, yearOffset, minEraYear }; @@ -36,8 +34,6 @@ namespace System.Globalization public const int ThaiBuddhistEra = 1; - //internal static Calendar m_defaultInstance; - internal GregorianCalendarHelper helper; @@ -57,9 +53,6 @@ namespace System.Globalization } } - // Return the type of the Thai Buddhist calendar. - // - public override CalendarAlgorithmType AlgorithmType { get @@ -73,11 +66,11 @@ namespace System.Globalization helper = new GregorianCalendarHelper(this, thaiBuddhistEraInfo); } - internal override int ID + internal override CalendarId ID { get { - return (CAL_THAI); + return (CalendarId.THAI); } } @@ -218,7 +211,7 @@ namespace System.Globalization "year", String.Format( CultureInfo.CurrentCulture, - Environment.GetResourceString("ArgumentOutOfRange_Range"), + SR.ArgumentOutOfRange_Range, 99, helper.MaxYear)); } @@ -232,7 +225,7 @@ namespace System.Globalization if (year < 0) { throw new ArgumentOutOfRangeException(nameof(year), - Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + SR.ArgumentOutOfRange_NeedNonNegNum); } Contract.EndContractBlock(); diff --git a/src/mscorlib/src/System/Globalization/UmAlQuraCalendar.cs b/src/mscorlib/src/System/Globalization/UmAlQuraCalendar.cs index f53f629..7b47d9c 100644 --- a/src/mscorlib/src/System/Globalization/UmAlQuraCalendar.cs +++ b/src/mscorlib/src/System/Globalization/UmAlQuraCalendar.cs @@ -2,7 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System; using System.Diagnostics; using System.Diagnostics.Contracts; @@ -17,12 +16,12 @@ namespace System.Globalization ** Calendar support range: ** Calendar Minimum Maximum ** ========== ========== ========== - ** Gregorian 1900/04/30 2077/11/17 + ** Gregorian 1900/04/30 2077/05/13 ** UmAlQura 1318/01/01 1500/12/30 */ [Serializable] - public class UmAlQuraCalendar : Calendar + public partial class UmAlQuraCalendar : Calendar { internal const int MinCalendarYear = 1318; internal const int MaxCalendarYear = 1500; @@ -38,200 +37,199 @@ namespace System.Globalization internal DateTime GregorianDate; } - private static readonly DateMapping[] HijriYearInfo = InitDateMapping(); + private static readonly DateMapping[] s_hijriYearInfo = InitDateMapping(); private static DateMapping[] InitDateMapping() { - short[] rawData = new short[] { -//These data is taken from Tables/Excel/UmAlQura.xls please make sure that the two places are in sync -/* DaysPerM GY GM GD D1 D2 D3 D4 D5 D6 D7 D8 D9 D10 D11 D12 -1318*/0x02EA, 1900, 4, 30,/* 0 1 0 1 0 1 1 1 0 1 0 0 4/30/1900 -1319*/0x06E9, 1901, 4, 19,/* 1 0 0 1 0 1 1 1 0 1 1 0 4/19/1901 -1320*/0x0ED2, 1902, 4, 9,/* 0 1 0 0 1 0 1 1 0 1 1 1 4/9/1902 -1321*/0x0EA4, 1903, 3, 30,/* 0 0 1 0 0 1 0 1 0 1 1 1 3/30/1903 -1322*/0x0D4A, 1904, 3, 18,/* 0 1 0 1 0 0 1 0 1 0 1 1 3/18/1904 -1323*/0x0A96, 1905, 3, 7,/* 0 1 1 0 1 0 0 1 0 1 0 1 3/7/1905 -1324*/0x0536, 1906, 2, 24,/* 0 1 1 0 1 1 0 0 1 0 1 0 2/24/1906 -1325*/0x0AB5, 1907, 2, 13,/* 1 0 1 0 1 1 0 1 0 1 0 1 2/13/1907 -1326*/0x0DAA, 1908, 2, 3,/* 0 1 0 1 0 1 0 1 1 0 1 1 2/3/1908 -1327*/0x0BA4, 1909, 1, 23,/* 0 0 1 0 0 1 0 1 1 1 0 1 1/23/1909 -1328*/0x0B49, 1910, 1, 12,/* 1 0 0 1 0 0 1 0 1 1 0 1 1/12/1910 -1329*/0x0A93, 1911, 1, 1,/* 1 1 0 0 1 0 0 1 0 1 0 1 1/1/1911 -1330*/0x052B, 1911, 12, 21,/* 1 1 0 1 0 1 0 0 1 0 1 0 12/21/1911 -1331*/0x0A57, 1912, 12, 9,/* 1 1 1 0 1 0 1 0 0 1 0 1 12/9/1912 -1332*/0x04B6, 1913, 11, 29,/* 0 1 1 0 1 1 0 1 0 0 1 0 11/29/1913 -1333*/0x0AB5, 1914, 11, 18,/* 1 0 1 0 1 1 0 1 0 1 0 1 11/18/1914 -1334*/0x05AA, 1915, 11, 8,/* 0 1 0 1 0 1 0 1 1 0 1 0 11/8/1915 -1335*/0x0D55, 1916, 10, 27,/* 1 0 1 0 1 0 1 0 1 0 1 1 10/27/1916 -1336*/0x0D2A, 1917, 10, 17,/* 0 1 0 1 0 1 0 0 1 0 1 1 10/17/1917 -1337*/0x0A56, 1918, 10, 6,/* 0 1 1 0 1 0 1 0 0 1 0 1 10/6/1918 -1338*/0x04AE, 1919, 9, 25,/* 0 1 1 1 0 1 0 1 0 0 1 0 9/25/1919 -1339*/0x095D, 1920, 9, 13,/* 1 0 1 1 1 0 1 0 1 0 0 1 9/13/1920 -1340*/0x02EC, 1921, 9, 3,/* 0 0 1 1 0 1 1 1 0 1 0 0 9/3/1921 -1341*/0x06D5, 1922, 8, 23,/* 1 0 1 0 1 0 1 1 0 1 1 0 8/23/1922 -1342*/0x06AA, 1923, 8, 13,/* 0 1 0 1 0 1 0 1 0 1 1 0 8/13/1923 -1343*/0x0555, 1924, 8, 1,/* 1 0 1 0 1 0 1 0 1 0 1 0 8/1/1924 -1344*/0x04AB, 1925, 7, 21,/* 1 1 0 1 0 1 0 1 0 0 1 0 7/21/1925 -1345*/0x095B, 1926, 7, 10,/* 1 1 0 1 1 0 1 0 1 0 0 1 7/10/1926 -1346*/0x02BA, 1927, 6, 30,/* 0 1 0 1 1 1 0 1 0 1 0 0 6/30/1927 -1347*/0x0575, 1928, 6, 18,/* 1 0 1 0 1 1 1 0 1 0 1 0 6/18/1928 -1348*/0x0BB2, 1929, 6, 8,/* 0 1 0 0 1 1 0 1 1 1 0 1 6/8/1929 -1349*/0x0764, 1930, 5, 29,/* 0 0 1 0 0 1 1 0 1 1 1 0 5/29/1930 -1350*/0x0749, 1931, 5, 18,/* 1 0 0 1 0 0 1 0 1 1 1 0 5/18/1931 -1351*/0x0655, 1932, 5, 6,/* 1 0 1 0 1 0 1 0 0 1 1 0 5/6/1932 -1352*/0x02AB, 1933, 4, 25,/* 1 1 0 1 0 1 0 1 0 1 0 0 4/25/1933 -1353*/0x055B, 1934, 4, 14,/* 1 1 0 1 1 0 1 0 1 0 1 0 4/14/1934 -1354*/0x0ADA, 1935, 4, 4,/* 0 1 0 1 1 0 1 1 0 1 0 1 4/4/1935 -1355*/0x06D4, 1936, 3, 24,/* 0 0 1 0 1 0 1 1 0 1 1 0 3/24/1936 -1356*/0x0EC9, 1937, 3, 13,/* 1 0 0 1 0 0 1 1 0 1 1 1 3/13/1937 -1357*/0x0D92, 1938, 3, 3,/* 0 1 0 0 1 0 0 1 1 0 1 1 3/3/1938 -1358*/0x0D25, 1939, 2, 20,/* 1 0 1 0 0 1 0 0 1 0 1 1 2/20/1939 -1359*/0x0A4D, 1940, 2, 9,/* 1 0 1 1 0 0 1 0 0 1 0 1 2/9/1940 -1360*/0x02AD, 1941, 1, 28,/* 1 0 1 1 0 1 0 1 0 1 0 0 1/28/1941 -1361*/0x056D, 1942, 1, 17,/* 1 0 1 1 0 1 1 0 1 0 1 0 1/17/1942 -1362*/0x0B6A, 1943, 1, 7,/* 0 1 0 1 0 1 1 0 1 1 0 1 1/7/1943 -1363*/0x0B52, 1943, 12, 28,/* 0 1 0 0 1 0 1 0 1 1 0 1 12/28/1943 -1364*/0x0AA5, 1944, 12, 16,/* 1 0 1 0 0 1 0 1 0 1 0 1 12/16/1944 -1365*/0x0A4B, 1945, 12, 5,/* 1 1 0 1 0 0 1 0 0 1 0 1 12/5/1945 -1366*/0x0497, 1946, 11, 24,/* 1 1 1 0 1 0 0 1 0 0 1 0 11/24/1946 -1367*/0x0937, 1947, 11, 13,/* 1 1 1 0 1 1 0 0 1 0 0 1 11/13/1947 -1368*/0x02B6, 1948, 11, 2,/* 0 1 1 0 1 1 0 1 0 1 0 0 11/2/1948 -1369*/0x0575, 1949, 10, 22,/* 1 0 1 0 1 1 1 0 1 0 1 0 10/22/1949 -1370*/0x0D6A, 1950, 10, 12,/* 0 1 0 1 0 1 1 0 1 0 1 1 10/12/1950 -1371*/0x0D52, 1951, 10, 2,/* 0 1 0 0 1 0 1 0 1 0 1 1 10/2/1951 -1372*/0x0A96, 1952, 9, 20,/* 0 1 1 0 1 0 0 1 0 1 0 1 9/20/1952 -1373*/0x092D, 1953, 9, 9,/* 1 0 1 1 0 1 0 0 1 0 0 1 9/9/1953 -1374*/0x025D, 1954, 8, 29,/* 1 0 1 1 1 0 1 0 0 1 0 0 8/29/1954 -1375*/0x04DD, 1955, 8, 18,/* 1 0 1 1 1 0 1 1 0 0 1 0 8/18/1955 -1376*/0x0ADA, 1956, 8, 7,/* 0 1 0 1 1 0 1 1 0 1 0 1 8/7/1956 -1377*/0x05D4, 1957, 7, 28,/* 0 0 1 0 1 0 1 1 1 0 1 0 7/28/1957 -1378*/0x0DA9, 1958, 7, 17,/* 1 0 0 1 0 1 0 1 1 0 1 1 7/17/1958 -1379*/0x0D52, 1959, 7, 7,/* 0 1 0 0 1 0 1 0 1 0 1 1 7/7/1959 -1380*/0x0AAA, 1960, 6, 25,/* 0 1 0 1 0 1 0 1 0 1 0 1 6/25/1960 -1381*/0x04D6, 1961, 6, 14,/* 0 1 1 0 1 0 1 1 0 0 1 0 6/14/1961 -1382*/0x09B6, 1962, 6, 3,/* 0 1 1 0 1 1 0 1 1 0 0 1 6/3/1962 -1383*/0x0374, 1963, 5, 24,/* 0 0 1 0 1 1 1 0 1 1 0 0 5/24/1963 -1384*/0x0769, 1964, 5, 12,/* 1 0 0 1 0 1 1 0 1 1 1 0 5/12/1964 -1385*/0x0752, 1965, 5, 2,/* 0 1 0 0 1 0 1 0 1 1 1 0 5/2/1965 -1386*/0x06A5, 1966, 4, 21,/* 1 0 1 0 0 1 0 1 0 1 1 0 4/21/1966 -1387*/0x054B, 1967, 4, 10,/* 1 1 0 1 0 0 1 0 1 0 1 0 4/10/1967 -1388*/0x0AAB, 1968, 3, 29,/* 1 1 0 1 0 1 0 1 0 1 0 1 3/29/1968 -1389*/0x055A, 1969, 3, 19,/* 0 1 0 1 1 0 1 0 1 0 1 0 3/19/1969 -1390*/0x0AD5, 1970, 3, 8,/* 1 0 1 0 1 0 1 1 0 1 0 1 3/8/1970 -1391*/0x0DD2, 1971, 2, 26,/* 0 1 0 0 1 0 1 1 1 0 1 1 2/26/1971 -1392*/0x0DA4, 1972, 2, 16,/* 0 0 1 0 0 1 0 1 1 0 1 1 2/16/1972 -1393*/0x0D49, 1973, 2, 4,/* 1 0 0 1 0 0 1 0 1 0 1 1 2/4/1973 -1394*/0x0A95, 1974, 1, 24,/* 1 0 1 0 1 0 0 1 0 1 0 1 1/24/1974 -1395*/0x052D, 1975, 1, 13,/* 1 0 1 1 0 1 0 0 1 0 1 0 1/13/1975 -1396*/0x0A5D, 1976, 1, 2,/* 1 0 1 1 1 0 1 0 0 1 0 1 1/2/1976 -1397*/0x055A, 1976, 12, 22,/* 0 1 0 1 1 0 1 0 1 0 1 0 12/22/1976 -1398*/0x0AD5, 1977, 12, 11,/* 1 0 1 0 1 0 1 1 0 1 0 1 12/11/1977 -1399*/0x06AA, 1978, 12, 1,/* 0 1 0 1 0 1 0 1 0 1 1 0 12/1/1978 -1400*/0x0695, 1979, 11, 20,/* 1 0 1 0 1 0 0 1 0 1 1 0 11/20/1979 -1401*/0x052B, 1980, 11, 8,/* 1 1 0 1 0 1 0 0 1 0 1 0 11/8/1980 -1402*/0x0A57, 1981, 10, 28,/* 1 1 1 0 1 0 1 0 0 1 0 1 10/28/1981 -1403*/0x04AE, 1982, 10, 18,/* 0 1 1 1 0 1 0 1 0 0 1 0 10/18/1982 -1404*/0x0976, 1983, 10, 7,/* 0 1 1 0 1 1 1 0 1 0 0 1 10/7/1983 -1405*/0x056C, 1984, 9, 26,/* 0 0 1 1 0 1 1 0 1 0 1 0 9/26/1984 -1406*/0x0B55, 1985, 9, 15,/* 1 0 1 0 1 0 1 0 1 1 0 1 9/15/1985 -1407*/0x0AAA, 1986, 9, 5,/* 0 1 0 1 0 1 0 1 0 1 0 1 9/5/1986 -1408*/0x0A55, 1987, 8, 25,/* 1 0 1 0 1 0 1 0 0 1 0 1 8/25/1987 -1409*/0x04AD, 1988, 8, 13,/* 1 0 1 1 0 1 0 1 0 0 1 0 8/13/1988 -1410*/0x095D, 1989, 8, 2,/* 1 0 1 1 1 0 1 0 1 0 0 1 8/2/1989 -1411*/0x02DA, 1990, 7, 23,/* 0 1 0 1 1 0 1 1 0 1 0 0 7/23/1990 -1412*/0x05D9, 1991, 7, 12,/* 1 0 0 1 1 0 1 1 1 0 1 0 7/12/1991 -1413*/0x0DB2, 1992, 7, 1,/* 0 1 0 0 1 1 0 1 1 0 1 1 7/1/1992 -1414*/0x0BA4, 1993, 6, 21,/* 0 0 1 0 0 1 0 1 1 1 0 1 6/21/1993 -1415*/0x0B4A, 1994, 6, 10,/* 0 1 0 1 0 0 1 0 1 1 0 1 6/10/1994 -1416*/0x0A55, 1995, 5, 30,/* 1 0 1 0 1 0 1 0 0 1 0 1 5/30/1995 -1417*/0x02B5, 1996, 5, 18,/* 1 0 1 0 1 1 0 1 0 1 0 0 5/18/1996 -1418*/0x0575, 1997, 5, 7,/* 1 0 1 0 1 1 1 0 1 0 1 0 5/7/1997 -1419*/0x0B6A, 1998, 4, 27,/* 0 1 0 1 0 1 1 0 1 1 0 1 4/27/1998 -1420*/0x0BD2, 1999, 4, 17,/* 0 1 0 0 1 0 1 1 1 1 0 1 4/17/1999 -1421*/0x0BC4, 2000, 4, 6,/* 0 0 1 0 0 0 1 1 1 1 0 1 4/6/2000 -1422*/0x0B89, 2001, 3, 26,/* 1 0 0 1 0 0 0 1 1 1 0 1 3/26/2001 -1423*/0x0A95, 2002, 3, 15,/* 1 0 1 0 1 0 0 1 0 1 0 1 3/15/2002 -1424*/0x052D, 2003, 3, 4,/* 1 0 1 1 0 1 0 0 1 0 1 0 3/4/2003 -1425*/0x05AD, 2004, 2, 21,/* 1 0 1 1 0 1 0 1 1 0 1 0 2/21/2004 -1426*/0x0B6A, 2005, 2, 10,/* 0 1 0 1 0 1 1 0 1 1 0 1 2/10/2005 -1427*/0x06D4, 2006, 1, 31,/* 0 0 1 0 1 0 1 1 0 1 1 0 1/31/2006 -1428*/0x0DC9, 2007, 1, 20,/* 1 0 0 1 0 0 1 1 1 0 1 1 1/20/2007 -1429*/0x0D92, 2008, 1, 10,/* 0 1 0 0 1 0 0 1 1 0 1 1 1/10/2008 -1430*/0x0AA6, 2008, 12, 29,/* 0 1 1 0 0 1 0 1 0 1 0 1 12/29/2008 -1431*/0x0956, 2009, 12, 18,/* 0 1 1 0 1 0 1 0 1 0 0 1 12/18/2009 -1432*/0x02AE, 2010, 12, 7,/* 0 1 1 1 0 1 0 1 0 1 0 0 12/7/2010 -1433*/0x056D, 2011, 11, 26,/* 1 0 1 1 0 1 1 0 1 0 1 0 11/26/2011 -1434*/0x036A, 2012, 11, 15,/* 0 1 0 1 0 1 1 0 1 1 0 0 11/15/2012 -1435*/0x0B55, 2013, 11, 4,/* 1 0 1 0 1 0 1 0 1 1 0 1 11/4/2013 -1436*/0x0AAA, 2014, 10, 25,/* 0 1 0 1 0 1 0 1 0 1 0 1 10/25/2014 -1437*/0x094D, 2015, 10, 14,/* 1 0 1 1 0 0 1 0 1 0 0 1 10/14/2015 -1438*/0x049D, 2016, 10, 2,/* 1 0 1 1 1 0 0 1 0 0 1 0 10/2/2016 -1439*/0x095D, 2017, 9, 21,/* 1 0 1 1 1 0 1 0 1 0 0 1 9/21/2017 -1440*/0x02BA, 2018, 9, 11,/* 0 1 0 1 1 1 0 1 0 1 0 0 9/11/2018 -1441*/0x05B5, 2019, 8, 31,/* 1 0 1 0 1 1 0 1 1 0 1 0 8/31/2019 -1442*/0x05AA, 2020, 8, 20,/* 0 1 0 1 0 1 0 1 1 0 1 0 8/20/2020 -1443*/0x0D55, 2021, 8, 9,/* 1 0 1 0 1 0 1 0 1 0 1 1 8/9/2021 -1444*/0x0A9A, 2022, 7, 30,/* 0 1 0 1 1 0 0 1 0 1 0 1 7/30/2022 -1445*/0x092E, 2023, 7, 19,/* 0 1 1 1 0 1 0 0 1 0 0 1 7/19/2023 -1446*/0x026E, 2024, 7, 7,/* 0 1 1 1 0 1 1 0 0 1 0 0 7/7/2024 -1447*/0x055D, 2025, 6, 26,/* 1 0 1 1 1 0 1 0 1 0 1 0 6/26/2025 -1448*/0x0ADA, 2026, 6, 16,/* 0 1 0 1 1 0 1 1 0 1 0 1 6/16/2026 -1449*/0x06D4, 2027, 6, 6,/* 0 0 1 0 1 0 1 1 0 1 1 0 6/6/2027 -1450*/0x06A5, 2028, 5, 25,/* 1 0 1 0 0 1 0 1 0 1 1 0 5/25/2028 -1451*/0x054B, 2029, 5, 14,/* 1 1 0 1 0 0 1 0 1 0 1 0 5/14/2029 -1452*/0x0A97, 2030, 5, 3,/* 1 1 1 0 1 0 0 1 0 1 0 1 5/3/2030 -1453*/0x054E, 2031, 4, 23,/* 0 1 1 1 0 0 1 0 1 0 1 0 4/23/2031 -1454*/0x0AAE, 2032, 4, 11,/* 0 1 1 1 0 1 0 1 0 1 0 1 4/11/2032 -1455*/0x05AC, 2033, 4, 1,/* 0 0 1 1 0 1 0 1 1 0 1 0 4/1/2033 -1456*/0x0BA9, 2034, 3, 21,/* 1 0 0 1 0 1 0 1 1 1 0 1 3/21/2034 -1457*/0x0D92, 2035, 3, 11,/* 0 1 0 0 1 0 0 1 1 0 1 1 3/11/2035 -1458*/0x0B25, 2036, 2, 28,/* 1 0 1 0 0 1 0 0 1 1 0 1 2/28/2036 -1459*/0x064B, 2037, 2, 16,/* 1 1 0 1 0 0 1 0 0 1 1 0 2/16/2037 -1460*/0x0CAB, 2038, 2, 5,/* 1 1 0 1 0 1 0 1 0 0 1 1 2/5/2038 -1461*/0x055A, 2039, 1, 26,/* 0 1 0 1 1 0 1 0 1 0 1 0 1/26/2039 -1462*/0x0B55, 2040, 1, 15,/* 1 0 1 0 1 0 1 0 1 1 0 1 1/15/2040 -1463*/0x06D2, 2041, 1, 4,/* 0 1 0 0 1 0 1 1 0 1 1 0 1/4/2041 -1464*/0x0EA5, 2041, 12, 24,/* 1 0 1 0 0 1 0 1 0 1 1 1 12/24/2041 -1465*/0x0E4A, 2042, 12, 14,/* 0 1 0 1 0 0 1 0 0 1 1 1 12/14/2042 -1466*/0x0A95, 2043, 12, 3,/* 1 0 1 0 1 0 0 1 0 1 0 1 12/3/2043 -1467*/0x052D, 2044, 11, 21,/* 1 0 1 1 0 1 0 0 1 0 1 0 11/21/2044 -1468*/0x0AAD, 2045, 11, 10,/* 1 0 1 1 0 1 0 1 0 1 0 1 11/10/2045 -1469*/0x036C, 2046, 10, 31,/* 0 0 1 1 0 1 1 0 1 1 0 0 10/31/2046 -1470*/0x0759, 2047, 10, 20,/* 1 0 0 1 1 0 1 0 1 1 1 0 10/20/2047 -1471*/0x06D2, 2048, 10, 9,/* 0 1 0 0 1 0 1 1 0 1 1 0 10/9/2048 -1472*/0x0695, 2049, 9, 28,/* 1 0 1 0 1 0 0 1 0 1 1 0 9/28/2049 -1473*/0x052D, 2050, 9, 17,/* 1 0 1 1 0 1 0 0 1 0 1 0 9/17/2050 -1474*/0x0A5B, 2051, 9, 6,/* 1 1 0 1 1 0 1 0 0 1 0 1 9/6/2051 -1475*/0x04BA, 2052, 8, 26,/* 0 1 0 1 1 1 0 1 0 0 1 0 8/26/2052 -1476*/0x09BA, 2053, 8, 15,/* 0 1 0 1 1 1 0 1 1 0 0 1 8/15/2053 -1477*/0x03B4, 2054, 8, 5,/* 0 0 1 0 1 1 0 1 1 1 0 0 8/5/2054 -1478*/0x0B69, 2055, 7, 25,/* 1 0 0 1 0 1 1 0 1 1 0 1 7/25/2055 -1479*/0x0B52, 2056, 7, 14,/* 0 1 0 0 1 0 1 0 1 1 0 1 7/14/2056 -1480*/0x0AA6, 2057, 7, 3,/* 0 1 1 0 0 1 0 1 0 1 0 1 7/3/2057 -1481*/0x04B6, 2058, 6, 22,/* 0 1 1 0 1 1 0 1 0 0 1 0 6/22/2058 -1482*/0x096D, 2059, 6, 11,/* 1 0 1 1 0 1 1 0 1 0 0 1 6/11/2059 -1483*/0x02EC, 2060, 5, 31,/* 0 0 1 1 0 1 1 1 0 1 0 0 5/31/2060 -1484*/0x06D9, 2061, 5, 20,/* 1 0 0 1 1 0 1 1 0 1 1 0 5/20/2061 -1485*/0x0EB2, 2062, 5, 10,/* 0 1 0 0 1 1 0 1 0 1 1 1 5/10/2062 -1486*/0x0D54, 2063, 4, 30,/* 0 0 1 0 1 0 1 0 1 0 1 1 4/30/2063 -1487*/0x0D2A, 2064, 4, 18,/* 0 1 0 1 0 1 0 0 1 0 1 1 4/18/2064 -1488*/0x0A56, 2065, 4, 7,/* 0 1 1 0 1 0 1 0 0 1 0 1 4/7/2065 -1489*/0x04AE, 2066, 3, 27,/* 0 1 1 1 0 1 0 1 0 0 1 0 3/27/2066 -1490*/0x096D, 2067, 3, 16,/* 1 0 1 1 0 1 1 0 1 0 0 1 3/16/2067 -1491*/0x0D6A, 2068, 3, 5,/* 0 1 0 1 0 1 1 0 1 0 1 1 3/5/2068 -1492*/0x0B54, 2069, 2, 23,/* 0 0 1 0 1 0 1 0 1 1 0 1 2/23/2069 -1493*/0x0B29, 2070, 2, 12,/* 1 0 0 1 0 1 0 0 1 1 0 1 2/12/2070 -1494*/0x0A93, 2071, 2, 1,/* 1 1 0 0 1 0 0 1 0 1 0 1 2/1/2071 -1495*/0x052B, 2072, 1, 21,/* 1 1 0 1 0 1 0 0 1 0 1 0 1/21/2072 -1496*/0x0A57, 2073, 1, 9,/* 1 1 1 0 1 0 1 0 0 1 0 1 1/9/2073 -1497*/0x0536, 2073, 12, 30,/* 0 1 1 0 1 1 0 0 1 0 1 0 12/30/2073 -1498*/0x0AB5, 2074, 12, 19,/* 1 0 1 0 1 1 0 1 0 1 0 1 12/19/2074 -1499*/0x06AA, 2075, 12, 9,/* 0 1 0 1 0 1 0 1 0 1 1 0 12/9/2075 -1500*/0x0E93, 2076, 11, 27,/* 1 1 0 0 1 0 0 1 0 1 1 1 11/27/2076 -1501*/ 0, 2077, 11, 17,/* 0 0 0 0 0 0 0 0 0 0 0 0 11/17/2077 - -*/ }; - + short[] rawData = new short[] + { + //These data is taken from Tables/Excel/UmAlQura.xls please make sure that the two places are in sync + /* DaysPerM GY GM GD D1 D2 D3 D4 D5 D6 D7 D8 D9 D10 D11 D12 + 1318*/0x02EA, 1900, 4, 30,/* 0 1 0 1 0 1 1 1 0 1 0 0 4/30/1900 + 1319*/0x06E9, 1901, 4, 19,/* 1 0 0 1 0 1 1 1 0 1 1 0 4/19/1901 + 1320*/0x0ED2, 1902, 4, 9,/* 0 1 0 0 1 0 1 1 0 1 1 1 4/9/1902 + 1321*/0x0EA4, 1903, 3, 30,/* 0 0 1 0 0 1 0 1 0 1 1 1 3/30/1903 + 1322*/0x0D4A, 1904, 3, 18,/* 0 1 0 1 0 0 1 0 1 0 1 1 3/18/1904 + 1323*/0x0A96, 1905, 3, 7,/* 0 1 1 0 1 0 0 1 0 1 0 1 3/7/1905 + 1324*/0x0536, 1906, 2, 24,/* 0 1 1 0 1 1 0 0 1 0 1 0 2/24/1906 + 1325*/0x0AB5, 1907, 2, 13,/* 1 0 1 0 1 1 0 1 0 1 0 1 2/13/1907 + 1326*/0x0DAA, 1908, 2, 3,/* 0 1 0 1 0 1 0 1 1 0 1 1 2/3/1908 + 1327*/0x0BA4, 1909, 1, 23,/* 0 0 1 0 0 1 0 1 1 1 0 1 1/23/1909 + 1328*/0x0B49, 1910, 1, 12,/* 1 0 0 1 0 0 1 0 1 1 0 1 1/12/1910 + 1329*/0x0A93, 1911, 1, 1,/* 1 1 0 0 1 0 0 1 0 1 0 1 1/1/1911 + 1330*/0x052B, 1911, 12, 21,/* 1 1 0 1 0 1 0 0 1 0 1 0 12/21/1911 + 1331*/0x0A57, 1912, 12, 9,/* 1 1 1 0 1 0 1 0 0 1 0 1 12/9/1912 + 1332*/0x04B6, 1913, 11, 29,/* 0 1 1 0 1 1 0 1 0 0 1 0 11/29/1913 + 1333*/0x0AB5, 1914, 11, 18,/* 1 0 1 0 1 1 0 1 0 1 0 1 11/18/1914 + 1334*/0x05AA, 1915, 11, 8,/* 0 1 0 1 0 1 0 1 1 0 1 0 11/8/1915 + 1335*/0x0D55, 1916, 10, 27,/* 1 0 1 0 1 0 1 0 1 0 1 1 10/27/1916 + 1336*/0x0D2A, 1917, 10, 17,/* 0 1 0 1 0 1 0 0 1 0 1 1 10/17/1917 + 1337*/0x0A56, 1918, 10, 6,/* 0 1 1 0 1 0 1 0 0 1 0 1 10/6/1918 + 1338*/0x04AE, 1919, 9, 25,/* 0 1 1 1 0 1 0 1 0 0 1 0 9/25/1919 + 1339*/0x095D, 1920, 9, 13,/* 1 0 1 1 1 0 1 0 1 0 0 1 9/13/1920 + 1340*/0x02EC, 1921, 9, 3,/* 0 0 1 1 0 1 1 1 0 1 0 0 9/3/1921 + 1341*/0x06D5, 1922, 8, 23,/* 1 0 1 0 1 0 1 1 0 1 1 0 8/23/1922 + 1342*/0x06AA, 1923, 8, 13,/* 0 1 0 1 0 1 0 1 0 1 1 0 8/13/1923 + 1343*/0x0555, 1924, 8, 1,/* 1 0 1 0 1 0 1 0 1 0 1 0 8/1/1924 + 1344*/0x04AB, 1925, 7, 21,/* 1 1 0 1 0 1 0 1 0 0 1 0 7/21/1925 + 1345*/0x095B, 1926, 7, 10,/* 1 1 0 1 1 0 1 0 1 0 0 1 7/10/1926 + 1346*/0x02BA, 1927, 6, 30,/* 0 1 0 1 1 1 0 1 0 1 0 0 6/30/1927 + 1347*/0x0575, 1928, 6, 18,/* 1 0 1 0 1 1 1 0 1 0 1 0 6/18/1928 + 1348*/0x0BB2, 1929, 6, 8,/* 0 1 0 0 1 1 0 1 1 1 0 1 6/8/1929 + 1349*/0x0764, 1930, 5, 29,/* 0 0 1 0 0 1 1 0 1 1 1 0 5/29/1930 + 1350*/0x0749, 1931, 5, 18,/* 1 0 0 1 0 0 1 0 1 1 1 0 5/18/1931 + 1351*/0x0655, 1932, 5, 6,/* 1 0 1 0 1 0 1 0 0 1 1 0 5/6/1932 + 1352*/0x02AB, 1933, 4, 25,/* 1 1 0 1 0 1 0 1 0 1 0 0 4/25/1933 + 1353*/0x055B, 1934, 4, 14,/* 1 1 0 1 1 0 1 0 1 0 1 0 4/14/1934 + 1354*/0x0ADA, 1935, 4, 4,/* 0 1 0 1 1 0 1 1 0 1 0 1 4/4/1935 + 1355*/0x06D4, 1936, 3, 24,/* 0 0 1 0 1 0 1 1 0 1 1 0 3/24/1936 + 1356*/0x0EC9, 1937, 3, 13,/* 1 0 0 1 0 0 1 1 0 1 1 1 3/13/1937 + 1357*/0x0D92, 1938, 3, 3,/* 0 1 0 0 1 0 0 1 1 0 1 1 3/3/1938 + 1358*/0x0D25, 1939, 2, 20,/* 1 0 1 0 0 1 0 0 1 0 1 1 2/20/1939 + 1359*/0x0A4D, 1940, 2, 9,/* 1 0 1 1 0 0 1 0 0 1 0 1 2/9/1940 + 1360*/0x02AD, 1941, 1, 28,/* 1 0 1 1 0 1 0 1 0 1 0 0 1/28/1941 + 1361*/0x056D, 1942, 1, 17,/* 1 0 1 1 0 1 1 0 1 0 1 0 1/17/1942 + 1362*/0x0B6A, 1943, 1, 7,/* 0 1 0 1 0 1 1 0 1 1 0 1 1/7/1943 + 1363*/0x0B52, 1943, 12, 28,/* 0 1 0 0 1 0 1 0 1 1 0 1 12/28/1943 + 1364*/0x0AA5, 1944, 12, 16,/* 1 0 1 0 0 1 0 1 0 1 0 1 12/16/1944 + 1365*/0x0A4B, 1945, 12, 5,/* 1 1 0 1 0 0 1 0 0 1 0 1 12/5/1945 + 1366*/0x0497, 1946, 11, 24,/* 1 1 1 0 1 0 0 1 0 0 1 0 11/24/1946 + 1367*/0x0937, 1947, 11, 13,/* 1 1 1 0 1 1 0 0 1 0 0 1 11/13/1947 + 1368*/0x02B6, 1948, 11, 2,/* 0 1 1 0 1 1 0 1 0 1 0 0 11/2/1948 + 1369*/0x0575, 1949, 10, 22,/* 1 0 1 0 1 1 1 0 1 0 1 0 10/22/1949 + 1370*/0x0D6A, 1950, 10, 12,/* 0 1 0 1 0 1 1 0 1 0 1 1 10/12/1950 + 1371*/0x0D52, 1951, 10, 2,/* 0 1 0 0 1 0 1 0 1 0 1 1 10/2/1951 + 1372*/0x0A96, 1952, 9, 20,/* 0 1 1 0 1 0 0 1 0 1 0 1 9/20/1952 + 1373*/0x092D, 1953, 9, 9,/* 1 0 1 1 0 1 0 0 1 0 0 1 9/9/1953 + 1374*/0x025D, 1954, 8, 29,/* 1 0 1 1 1 0 1 0 0 1 0 0 8/29/1954 + 1375*/0x04DD, 1955, 8, 18,/* 1 0 1 1 1 0 1 1 0 0 1 0 8/18/1955 + 1376*/0x0ADA, 1956, 8, 7,/* 0 1 0 1 1 0 1 1 0 1 0 1 8/7/1956 + 1377*/0x05D4, 1957, 7, 28,/* 0 0 1 0 1 0 1 1 1 0 1 0 7/28/1957 + 1378*/0x0DA9, 1958, 7, 17,/* 1 0 0 1 0 1 0 1 1 0 1 1 7/17/1958 + 1379*/0x0D52, 1959, 7, 7,/* 0 1 0 0 1 0 1 0 1 0 1 1 7/7/1959 + 1380*/0x0AAA, 1960, 6, 25,/* 0 1 0 1 0 1 0 1 0 1 0 1 6/25/1960 + 1381*/0x04D6, 1961, 6, 14,/* 0 1 1 0 1 0 1 1 0 0 1 0 6/14/1961 + 1382*/0x09B6, 1962, 6, 3,/* 0 1 1 0 1 1 0 1 1 0 0 1 6/3/1962 + 1383*/0x0374, 1963, 5, 24,/* 0 0 1 0 1 1 1 0 1 1 0 0 5/24/1963 + 1384*/0x0769, 1964, 5, 12,/* 1 0 0 1 0 1 1 0 1 1 1 0 5/12/1964 + 1385*/0x0752, 1965, 5, 2,/* 0 1 0 0 1 0 1 0 1 1 1 0 5/2/1965 + 1386*/0x06A5, 1966, 4, 21,/* 1 0 1 0 0 1 0 1 0 1 1 0 4/21/1966 + 1387*/0x054B, 1967, 4, 10,/* 1 1 0 1 0 0 1 0 1 0 1 0 4/10/1967 + 1388*/0x0AAB, 1968, 3, 29,/* 1 1 0 1 0 1 0 1 0 1 0 1 3/29/1968 + 1389*/0x055A, 1969, 3, 19,/* 0 1 0 1 1 0 1 0 1 0 1 0 3/19/1969 + 1390*/0x0AD5, 1970, 3, 8,/* 1 0 1 0 1 0 1 1 0 1 0 1 3/8/1970 + 1391*/0x0DD2, 1971, 2, 26,/* 0 1 0 0 1 0 1 1 1 0 1 1 2/26/1971 + 1392*/0x0DA4, 1972, 2, 16,/* 0 0 1 0 0 1 0 1 1 0 1 1 2/16/1972 + 1393*/0x0D49, 1973, 2, 4,/* 1 0 0 1 0 0 1 0 1 0 1 1 2/4/1973 + 1394*/0x0A95, 1974, 1, 24,/* 1 0 1 0 1 0 0 1 0 1 0 1 1/24/1974 + 1395*/0x052D, 1975, 1, 13,/* 1 0 1 1 0 1 0 0 1 0 1 0 1/13/1975 + 1396*/0x0A5D, 1976, 1, 2,/* 1 0 1 1 1 0 1 0 0 1 0 1 1/2/1976 + 1397*/0x055A, 1976, 12, 22,/* 0 1 0 1 1 0 1 0 1 0 1 0 12/22/1976 + 1398*/0x0AD5, 1977, 12, 11,/* 1 0 1 0 1 0 1 1 0 1 0 1 12/11/1977 + 1399*/0x06AA, 1978, 12, 1,/* 0 1 0 1 0 1 0 1 0 1 1 0 12/1/1978 + 1400*/0x0695, 1979, 11, 20,/* 1 0 1 0 1 0 0 1 0 1 1 0 11/20/1979 + 1401*/0x052B, 1980, 11, 8,/* 1 1 0 1 0 1 0 0 1 0 1 0 11/8/1980 + 1402*/0x0A57, 1981, 10, 28,/* 1 1 1 0 1 0 1 0 0 1 0 1 10/28/1981 + 1403*/0x04AE, 1982, 10, 18,/* 0 1 1 1 0 1 0 1 0 0 1 0 10/18/1982 + 1404*/0x0976, 1983, 10, 7,/* 0 1 1 0 1 1 1 0 1 0 0 1 10/7/1983 + 1405*/0x056C, 1984, 9, 26,/* 0 0 1 1 0 1 1 0 1 0 1 0 9/26/1984 + 1406*/0x0B55, 1985, 9, 15,/* 1 0 1 0 1 0 1 0 1 1 0 1 9/15/1985 + 1407*/0x0AAA, 1986, 9, 5,/* 0 1 0 1 0 1 0 1 0 1 0 1 9/5/1986 + 1408*/0x0A55, 1987, 8, 25,/* 1 0 1 0 1 0 1 0 0 1 0 1 8/25/1987 + 1409*/0x04AD, 1988, 8, 13,/* 1 0 1 1 0 1 0 1 0 0 1 0 8/13/1988 + 1410*/0x095D, 1989, 8, 2,/* 1 0 1 1 1 0 1 0 1 0 0 1 8/2/1989 + 1411*/0x02DA, 1990, 7, 23,/* 0 1 0 1 1 0 1 1 0 1 0 0 7/23/1990 + 1412*/0x05D9, 1991, 7, 12,/* 1 0 0 1 1 0 1 1 1 0 1 0 7/12/1991 + 1413*/0x0DB2, 1992, 7, 1,/* 0 1 0 0 1 1 0 1 1 0 1 1 7/1/1992 + 1414*/0x0BA4, 1993, 6, 21,/* 0 0 1 0 0 1 0 1 1 1 0 1 6/21/1993 + 1415*/0x0B4A, 1994, 6, 10,/* 0 1 0 1 0 0 1 0 1 1 0 1 6/10/1994 + 1416*/0x0A55, 1995, 5, 30,/* 1 0 1 0 1 0 1 0 0 1 0 1 5/30/1995 + 1417*/0x02B5, 1996, 5, 18,/* 1 0 1 0 1 1 0 1 0 1 0 0 5/18/1996 + 1418*/0x0575, 1997, 5, 7,/* 1 0 1 0 1 1 1 0 1 0 1 0 5/7/1997 + 1419*/0x0B6A, 1998, 4, 27,/* 0 1 0 1 0 1 1 0 1 1 0 1 4/27/1998 + 1420*/0x0BD2, 1999, 4, 17,/* 0 1 0 0 1 0 1 1 1 1 0 1 4/17/1999 + 1421*/0x0BC4, 2000, 4, 6,/* 0 0 1 0 0 0 1 1 1 1 0 1 4/6/2000 + 1422*/0x0B89, 2001, 3, 26,/* 1 0 0 1 0 0 0 1 1 1 0 1 3/26/2001 + 1423*/0x0A95, 2002, 3, 15,/* 1 0 1 0 1 0 0 1 0 1 0 1 3/15/2002 + 1424*/0x052D, 2003, 3, 4,/* 1 0 1 1 0 1 0 0 1 0 1 0 3/4/2003 + 1425*/0x05AD, 2004, 2, 21,/* 1 0 1 1 0 1 0 1 1 0 1 0 2/21/2004 + 1426*/0x0B6A, 2005, 2, 10,/* 0 1 0 1 0 1 1 0 1 1 0 1 2/10/2005 + 1427*/0x06D4, 2006, 1, 31,/* 0 0 1 0 1 0 1 1 0 1 1 0 1/31/2006 + 1428*/0x0DC9, 2007, 1, 20,/* 1 0 0 1 0 0 1 1 1 0 1 1 1/20/2007 + 1429*/0x0D92, 2008, 1, 10,/* 0 1 0 0 1 0 0 1 1 0 1 1 1/10/2008 + 1430*/0x0AA6, 2008, 12, 29,/* 0 1 1 0 0 1 0 1 0 1 0 1 12/29/2008 + 1431*/0x0956, 2009, 12, 18,/* 0 1 1 0 1 0 1 0 1 0 0 1 12/18/2009 + 1432*/0x02AE, 2010, 12, 7,/* 0 1 1 1 0 1 0 1 0 1 0 0 12/7/2010 + 1433*/0x056D, 2011, 11, 26,/* 1 0 1 1 0 1 1 0 1 0 1 0 11/26/2011 + 1434*/0x036A, 2012, 11, 15,/* 0 1 0 1 0 1 1 0 1 1 0 0 11/15/2012 + 1435*/0x0B55, 2013, 11, 4,/* 1 0 1 0 1 0 1 0 1 1 0 1 11/4/2013 + 1436*/0x0AAA, 2014, 10, 25,/* 0 1 0 1 0 1 0 1 0 1 0 1 10/25/2014 + 1437*/0x094D, 2015, 10, 14,/* 1 0 1 1 0 0 1 0 1 0 0 1 10/14/2015 + 1438*/0x049D, 2016, 10, 2,/* 1 0 1 1 1 0 0 1 0 0 1 0 10/2/2016 + 1439*/0x095D, 2017, 9, 21,/* 1 0 1 1 1 0 1 0 1 0 0 1 9/21/2017 + 1440*/0x02BA, 2018, 9, 11,/* 0 1 0 1 1 1 0 1 0 1 0 0 9/11/2018 + 1441*/0x05B5, 2019, 8, 31,/* 1 0 1 0 1 1 0 1 1 0 1 0 8/31/2019 + 1442*/0x05AA, 2020, 8, 20,/* 0 1 0 1 0 1 0 1 1 0 1 0 8/20/2020 + 1443*/0x0D55, 2021, 8, 9,/* 1 0 1 0 1 0 1 0 1 0 1 1 8/9/2021 + 1444*/0x0A9A, 2022, 7, 30,/* 0 1 0 1 1 0 0 1 0 1 0 1 7/30/2022 + 1445*/0x092E, 2023, 7, 19,/* 0 1 1 1 0 1 0 0 1 0 0 1 7/19/2023 + 1446*/0x026E, 2024, 7, 7,/* 0 1 1 1 0 1 1 0 0 1 0 0 7/7/2024 + 1447*/0x055D, 2025, 6, 26,/* 1 0 1 1 1 0 1 0 1 0 1 0 6/26/2025 + 1448*/0x0ADA, 2026, 6, 16,/* 0 1 0 1 1 0 1 1 0 1 0 1 6/16/2026 + 1449*/0x06D4, 2027, 6, 6,/* 0 0 1 0 1 0 1 1 0 1 1 0 6/6/2027 + 1450*/0x06A5, 2028, 5, 25,/* 1 0 1 0 0 1 0 1 0 1 1 0 5/25/2028 + 1451*/0x054B, 2029, 5, 14,/* 1 1 0 1 0 0 1 0 1 0 1 0 5/14/2029 + 1452*/0x0A97, 2030, 5, 3,/* 1 1 1 0 1 0 0 1 0 1 0 1 5/3/2030 + 1453*/0x054E, 2031, 4, 23,/* 0 1 1 1 0 0 1 0 1 0 1 0 4/23/2031 + 1454*/0x0AAE, 2032, 4, 11,/* 0 1 1 1 0 1 0 1 0 1 0 1 4/11/2032 + 1455*/0x05AC, 2033, 4, 1,/* 0 0 1 1 0 1 0 1 1 0 1 0 4/1/2033 + 1456*/0x0BA9, 2034, 3, 21,/* 1 0 0 1 0 1 0 1 1 1 0 1 3/21/2034 + 1457*/0x0D92, 2035, 3, 11,/* 0 1 0 0 1 0 0 1 1 0 1 1 3/11/2035 + 1458*/0x0B25, 2036, 2, 28,/* 1 0 1 0 0 1 0 0 1 1 0 1 2/28/2036 + 1459*/0x064B, 2037, 2, 16,/* 1 1 0 1 0 0 1 0 0 1 1 0 2/16/2037 + 1460*/0x0CAB, 2038, 2, 5,/* 1 1 0 1 0 1 0 1 0 0 1 1 2/5/2038 + 1461*/0x055A, 2039, 1, 26,/* 0 1 0 1 1 0 1 0 1 0 1 0 1/26/2039 + 1462*/0x0B55, 2040, 1, 15,/* 1 0 1 0 1 0 1 0 1 1 0 1 1/15/2040 + 1463*/0x06D2, 2041, 1, 4,/* 0 1 0 0 1 0 1 1 0 1 1 0 1/4/2041 + 1464*/0x0EA5, 2041, 12, 24,/* 1 0 1 0 0 1 0 1 0 1 1 1 12/24/2041 + 1465*/0x0E4A, 2042, 12, 14,/* 0 1 0 1 0 0 1 0 0 1 1 1 12/14/2042 + 1466*/0x0A95, 2043, 12, 3,/* 1 0 1 0 1 0 0 1 0 1 0 1 12/3/2043 + 1467*/0x052D, 2044, 11, 21,/* 1 0 1 1 0 1 0 0 1 0 1 0 11/21/2044 + 1468*/0x0AAD, 2045, 11, 10,/* 1 0 1 1 0 1 0 1 0 1 0 1 11/10/2045 + 1469*/0x036C, 2046, 10, 31,/* 0 0 1 1 0 1 1 0 1 1 0 0 10/31/2046 + 1470*/0x0759, 2047, 10, 20,/* 1 0 0 1 1 0 1 0 1 1 1 0 10/20/2047 + 1471*/0x06D2, 2048, 10, 9,/* 0 1 0 0 1 0 1 1 0 1 1 0 10/9/2048 + 1472*/0x0695, 2049, 9, 28,/* 1 0 1 0 1 0 0 1 0 1 1 0 9/28/2049 + 1473*/0x052D, 2050, 9, 17,/* 1 0 1 1 0 1 0 0 1 0 1 0 9/17/2050 + 1474*/0x0A5B, 2051, 9, 6,/* 1 1 0 1 1 0 1 0 0 1 0 1 9/6/2051 + 1475*/0x04BA, 2052, 8, 26,/* 0 1 0 1 1 1 0 1 0 0 1 0 8/26/2052 + 1476*/0x09BA, 2053, 8, 15,/* 0 1 0 1 1 1 0 1 1 0 0 1 8/15/2053 + 1477*/0x03B4, 2054, 8, 5,/* 0 0 1 0 1 1 0 1 1 1 0 0 8/5/2054 + 1478*/0x0B69, 2055, 7, 25,/* 1 0 0 1 0 1 1 0 1 1 0 1 7/25/2055 + 1479*/0x0B52, 2056, 7, 14,/* 0 1 0 0 1 0 1 0 1 1 0 1 7/14/2056 + 1480*/0x0AA6, 2057, 7, 3,/* 0 1 1 0 0 1 0 1 0 1 0 1 7/3/2057 + 1481*/0x04B6, 2058, 6, 22,/* 0 1 1 0 1 1 0 1 0 0 1 0 6/22/2058 + 1482*/0x096D, 2059, 6, 11,/* 1 0 1 1 0 1 1 0 1 0 0 1 6/11/2059 + 1483*/0x02EC, 2060, 5, 31,/* 0 0 1 1 0 1 1 1 0 1 0 0 5/31/2060 + 1484*/0x06D9, 2061, 5, 20,/* 1 0 0 1 1 0 1 1 0 1 1 0 5/20/2061 + 1485*/0x0EB2, 2062, 5, 10,/* 0 1 0 0 1 1 0 1 0 1 1 1 5/10/2062 + 1486*/0x0D54, 2063, 4, 30,/* 0 0 1 0 1 0 1 0 1 0 1 1 4/30/2063 + 1487*/0x0D2A, 2064, 4, 18,/* 0 1 0 1 0 1 0 0 1 0 1 1 4/18/2064 + 1488*/0x0A56, 2065, 4, 7,/* 0 1 1 0 1 0 1 0 0 1 0 1 4/7/2065 + 1489*/0x04AE, 2066, 3, 27,/* 0 1 1 1 0 1 0 1 0 0 1 0 3/27/2066 + 1490*/0x096D, 2067, 3, 16,/* 1 0 1 1 0 1 1 0 1 0 0 1 3/16/2067 + 1491*/0x0D6A, 2068, 3, 5,/* 0 1 0 1 0 1 1 0 1 0 1 1 3/5/2068 + 1492*/0x0B54, 2069, 2, 23,/* 0 0 1 0 1 0 1 0 1 1 0 1 2/23/2069 + 1493*/0x0B29, 2070, 2, 12,/* 1 0 0 1 0 1 0 0 1 1 0 1 2/12/2070 + 1494*/0x0A93, 2071, 2, 1,/* 1 1 0 0 1 0 0 1 0 1 0 1 2/1/2071 + 1495*/0x052B, 2072, 1, 21,/* 1 1 0 1 0 1 0 0 1 0 1 0 1/21/2072 + 1496*/0x0A57, 2073, 1, 9,/* 1 1 1 0 1 0 1 0 0 1 0 1 1/9/2073 + 1497*/0x0536, 2073, 12, 30,/* 0 1 1 0 1 1 0 0 1 0 1 0 12/30/2073 + 1498*/0x0AB5, 2074, 12, 19,/* 1 0 1 0 1 1 0 1 0 1 0 1 12/19/2074 + 1499*/0x06AA, 2075, 12, 9,/* 0 1 0 1 0 1 0 1 0 1 1 0 12/9/2075 + 1500*/0x0E93, 2076, 11, 27,/* 1 1 0 0 1 0 0 1 0 1 1 1 11/27/2076 + 1501*/ 0, 2077, 11, 17,/* 0 0 0 0 0 0 0 0 0 0 0 0 11/17/2077 + */ }; // Direct inline initialization of DateMapping array would produce a lot of code bloat. // We take advantage of C# compiler compiles inline initialization of primitive type array into very compact code. @@ -251,31 +249,11 @@ namespace System.Globalization internal const int DatePartMonth = 2; internal const int DatePartDay = 3; - //internal static Calendar m_defaultInstance; - // This is the minimal Gregorian date that we support in the UmAlQuraCalendar. internal static DateTime minDate = new DateTime(1900, 4, 30); internal static DateTime maxDate = new DateTime((new DateTime(2077, 11, 16, 23, 59, 59, 999)).Ticks + 9999); - /*=================================GetDefaultInstance========================== - **Action: Internal method to provide a default intance of UmAlQuraCalendar. Used by NLS+ implementation - ** and other calendars. - **Returns: - **Arguments: - **Exceptions: - ============================================================================*/ - /* - internal static Calendar GetDefaultInstance() { - if (m_defaultInstance == null) { - m_defaultInstance = new UmAlQuraCalendar(); - } - return (m_defaultInstance); - } - */ - - - public override DateTime MinSupportedDateTime { get @@ -284,7 +262,6 @@ namespace System.Globalization } } - public override DateTime MaxSupportedDateTime { get @@ -293,11 +270,6 @@ namespace System.Globalization } } - - // Return the type of the UmAlQura calendar. - // - - public override CalendarAlgorithmType AlgorithmType { get @@ -306,25 +278,23 @@ namespace System.Globalization } } - // Construct an instance of UmAlQura calendar. - public UmAlQuraCalendar() { } - internal override int BaseCalendarID + internal override CalendarId BaseCalendarID { get { - return (CAL_HIJRI); + return (CalendarId.HIJRI); } } - internal override int ID + internal override CalendarId ID { get { - return (CAL_UMALQURA); + return (CalendarId.UMALQURA); } } @@ -339,10 +309,11 @@ namespace System.Globalization } /*==========================ConvertHijriToGregorian========================== - ** Purpose: convert Hdate(year,month,day) to Gdate(year,month,day) + ** Purpose: convert Hdate(year,month,day) to Gdate(year,month,day) ** Arguments: - ** Input: Hijrah date: year:HijriYear, month:HijriMonth, day:HijriDay - ** Output: Gregorian date: year:yg, month:mg, day:dg + ** Input/Ouput: Hijrah date: year:yh, month:mh, day:dh + ** Output: Gregorian date: year:yg, month:mg, day:dg , day of week:dayweek + ** and returns flag found:1 not found:0 =========================ConvertHijriToGregorian============================*/ private static void ConvertHijriToGregorian(int HijriYear, int HijriMonth, int HijriDay, ref int yg, ref int mg, ref int dg) { @@ -354,14 +325,14 @@ namespace System.Globalization index = HijriYear - MinCalendarYear; - dt = HijriYearInfo[index].GregorianDate; + dt = s_hijriYearInfo[index].GregorianDate; - b = HijriYearInfo[index].HijriMonthsLengthFlags; + b = s_hijriYearInfo[index].HijriMonthsLengthFlags; for (int m = 1; m < HijriMonth; m++) { - nDays += 29 + (b & 0x1); + nDays = nDays + 29 + (b & 1); /* Add the months lengths before mh */ b = b >> 1; } @@ -387,7 +358,7 @@ namespace System.Globalization return GregorianCalendar.GetAbsoluteDate(yg, mg, dg); } - static internal void CheckTicksRange(long ticks) + internal static void CheckTicksRange(long ticks) { if (ticks < minDate.Ticks || ticks > maxDate.Ticks) { @@ -395,21 +366,21 @@ namespace System.Globalization "time", String.Format( CultureInfo.InvariantCulture, - Environment.GetResourceString("ArgumentOutOfRange_CalendarRange"), + SR.ArgumentOutOfRange_CalendarRange, minDate, maxDate)); } } - static internal void CheckEraRange(int era) + internal static void CheckEraRange(int era) { if (era != CurrentEra && era != UmAlQuraEra) { - throw new ArgumentOutOfRangeException(nameof(era), Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue")); + throw new ArgumentOutOfRangeException(nameof(era), SR.ArgumentOutOfRange_InvalidEraValue); } } - static internal void CheckYearRange(int year, int era) + internal static void CheckYearRange(int year, int era) { CheckEraRange(era); if (year < MinCalendarYear || year > MaxCalendarYear) @@ -418,18 +389,18 @@ namespace System.Globalization nameof(year), String.Format( CultureInfo.CurrentCulture, - Environment.GetResourceString("ArgumentOutOfRange_Range"), + SR.ArgumentOutOfRange_Range, MinCalendarYear, MaxCalendarYear)); } } - static internal void CheckYearMonthRange(int year, int month, int era) + internal static void CheckYearMonthRange(int year, int month, int era) { CheckYearRange(year, era); if (month < 1 || month > 12) { - throw new ArgumentOutOfRangeException(nameof(month), Environment.GetResourceString("ArgumentOutOfRange_Month")); + throw new ArgumentOutOfRangeException(nameof(month), SR.ArgumentOutOfRange_Month); } } @@ -437,7 +408,7 @@ namespace System.Globalization ** Purpose: convert DateTime to Hdate(year,month,day) ** Arguments: ** Input: DateTime - ** Output: Hijrah date: year:HijriYear, month:HijriMonth, day:HijriDay + ** Output: Hijrah date: year:yh, month:mh, day:dh ============================================================================*/ private static void ConvertGregorianToHijri(DateTime time, ref int HijriYear, ref int HijriMonth, ref int HijriDay) { @@ -454,20 +425,20 @@ namespace System.Globalization index = (int)((time.Ticks - minDate.Ticks) / Calendar.TicksPerDay) / 355; do { - } while (time.CompareTo(HijriYearInfo[++index].GregorianDate) > 0); //while greater + } while (time.CompareTo(s_hijriYearInfo[++index].GregorianDate) > 0); //while greater - if (time.CompareTo(HijriYearInfo[index].GregorianDate) != 0) + if (time.CompareTo(s_hijriYearInfo[index].GregorianDate) != 0) { index--; } - ts = time.Subtract(HijriYearInfo[index].GregorianDate); + ts = time.Subtract(s_hijriYearInfo[index].GregorianDate); yh1 = index + MinCalendarYear; mh1 = 1; dh1 = 1; nDays = ts.TotalDays; - b = HijriYearInfo[index].HijriMonthsLengthFlags; + b = s_hijriYearInfo[index].HijriMonthsLengthFlags; DaysPerThisMonth = 29 + (b & 1); while (nDays >= DaysPerThisMonth) @@ -520,7 +491,7 @@ namespace System.Globalization return (int)(GetAbsoluteDateUmAlQura(UmAlQuraYear, UmAlQuraMonth, UmAlQuraDay) - GetAbsoluteDateUmAlQura(UmAlQuraYear, 1, 1) + 1); // Incorrect part value. - throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_DateTimeParsing")); + throw new InvalidOperationException(SR.InvalidOperation_DateTimeParsing); } // Returns the DateTime resulting from adding the given number of @@ -550,7 +521,7 @@ namespace System.Globalization nameof(months), String.Format( CultureInfo.CurrentCulture, - Environment.GetResourceString("ArgumentOutOfRange_Range"), + SR.ArgumentOutOfRange_Range, -120000, 120000)); } @@ -649,23 +620,23 @@ namespace System.Globalization { CheckYearMonthRange(year, month, era); - if ((HijriYearInfo[year - MinCalendarYear].HijriMonthsLengthFlags & (1 << month - 1)) == 0) + if ((s_hijriYearInfo[year - MinCalendarYear].HijriMonthsLengthFlags & (1 << month - 1)) == 0) return 29; else return 30; } - static internal int RealGetDaysInYear(int year) + internal static int RealGetDaysInYear(int year) { int days = 0, b; Debug.Assert((year >= MinCalendarYear) && (year <= MaxCalendarYear), "Hijri year is out of range."); - b = HijriYearInfo[year - MinCalendarYear].HijriMonthsLengthFlags; + b = s_hijriYearInfo[year - MinCalendarYear].HijriMonthsLengthFlags; for (int m = 1; m <= 12; m++) { - days += 29 + (b & 0x1); + days = days + 29 + (b & 1); /* Add the months lengths before mh */ b = b >> 1; } Debug.Assert((days == 354) || (days == 355), "Hijri year has to be 354 or 355 days."); @@ -751,7 +722,7 @@ namespace System.Globalization nameof(day), String.Format( CultureInfo.CurrentCulture, - Environment.GetResourceString("ArgumentOutOfRange_Day"), + SR.ArgumentOutOfRange_Day, daysInMonth, month)); } @@ -811,12 +782,11 @@ namespace System.Globalization if (day < 1 || day > daysInMonth) { - BCLDebug.Log("year = " + year + ", month = " + month + ", day = " + day); throw new ArgumentOutOfRangeException( nameof(day), String.Format( CultureInfo.CurrentCulture, - Environment.GetResourceString("ArgumentOutOfRange_Day"), + SR.ArgumentOutOfRange_Day, daysInMonth, month)); } @@ -829,7 +799,7 @@ namespace System.Globalization } else { - throw new ArgumentOutOfRangeException(null, Environment.GetResourceString("ArgumentOutOfRange_BadYearMonthDay")); + throw new ArgumentOutOfRangeException(null, SR.ArgumentOutOfRange_BadYearMonthDay); } } @@ -856,7 +826,7 @@ namespace System.Globalization nameof(value), String.Format( CultureInfo.CurrentCulture, - Environment.GetResourceString("ArgumentOutOfRange_Range"), + SR.ArgumentOutOfRange_Range, MinCalendarYear, MaxCalendarYear)); } @@ -874,7 +844,7 @@ namespace System.Globalization if (year < 0) { throw new ArgumentOutOfRangeException(nameof(year), - Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + SR.ArgumentOutOfRange_NeedNonNegNum); } Contract.EndContractBlock(); @@ -889,7 +859,7 @@ namespace System.Globalization nameof(year), String.Format( CultureInfo.CurrentCulture, - Environment.GetResourceString("ArgumentOutOfRange_Range"), + SR.ArgumentOutOfRange_Range, MinCalendarYear, MaxCalendarYear)); } diff --git a/src/mscorlib/src/System/Globalization/UnicodeCategory.cs b/src/mscorlib/src/System/Globalization/UnicodeCategory.cs index 008f219..1c5e6bc 100644 --- a/src/mscorlib/src/System/Globalization/UnicodeCategory.cs +++ b/src/mscorlib/src/System/Globalization/UnicodeCategory.cs @@ -2,15 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -/*============================================================ -** -** -** -** Purpose: -** -** -============================================================*/ - namespace System.Globalization { [Serializable] diff --git a/src/mscorlib/src/System/Resources/ResourceManager.cs b/src/mscorlib/src/System/Resources/ResourceManager.cs index 8ac9ed0..94bc720 100644 --- a/src/mscorlib/src/System/Resources/ResourceManager.cs +++ b/src/mscorlib/src/System/Resources/ResourceManager.cs @@ -39,7 +39,7 @@ namespace System.Resources // allowing us to ask for a WinRT-specific ResourceManager. // It is important to have WindowsRuntimeResourceManagerBase as regular class with virtual methods and default implementations. // Defining WindowsRuntimeResourceManagerBase as abstract class or interface will cause issues when adding more methods to it - // because it’ll create dependency between mscorlib and System.Runtime.WindowsRuntime which will require always shipping both DLLs together. + // because it�ll create dependency between mscorlib and System.Runtime.WindowsRuntime which will require always shipping both DLLs together. // Also using interface or abstract class will not play nice with FriendAccessAllowed. // [FriendAccessAllowed] @@ -1133,11 +1133,11 @@ namespace System.Resources else #endif // FEATURE_APPX { - if (null == culture) + if (culture == null) { // When running inside AppX we want to ignore the languages list when trying to come up with our CurrentUICulture. // This line behaves the same way as CultureInfo.CurrentUICulture would have in .NET 4 - culture = Thread.CurrentThread.GetCurrentUICultureNoAppX(); + culture = CultureInfo.GetCurrentUICultureNoAppX(); } ResourceSet last = GetFirstResourceSet(culture); @@ -1226,7 +1226,7 @@ namespace System.Resources { // When running inside AppX we want to ignore the languages list when trying to come up with our CurrentUICulture. // This line behaves the same way as CultureInfo.CurrentUICulture would have in .NET 4 - culture = Thread.CurrentThread.GetCurrentUICultureNoAppX(); + culture = CultureInfo.GetCurrentUICultureNoAppX(); } ResourceSet last = GetFirstResourceSet(culture); diff --git a/src/mscorlib/src/System/String.Comparison.cs b/src/mscorlib/src/System/String.Comparison.cs index d35e900..bc78000 100644 --- a/src/mscorlib/src/System/String.Comparison.cs +++ b/src/mscorlib/src/System/String.Comparison.cs @@ -436,12 +436,7 @@ namespace System return (CompareOrdinalIgnoreCaseHelper(strA, strB)); } -#if FEATURE_COREFX_GLOBALIZATION return CompareInfo.CompareOrdinalIgnoreCase(strA, 0, strA.Length, strB, 0, strB.Length); -#else - // Take the slow path. - return TextInfo.CompareOrdinalIgnoreCase(strA, strB); -#endif default: throw new NotSupportedException(Environment.GetResourceString("NotSupported_StringComparison")); @@ -635,11 +630,7 @@ namespace System return CompareOrdinalHelper(strA, indexA, lengthA, strB, indexB, lengthB); case StringComparison.OrdinalIgnoreCase: -#if FEATURE_COREFX_GLOBALIZATION return (CompareInfo.CompareOrdinalIgnoreCase(strA, indexA, lengthA, strB, indexB, lengthB)); -#else - return (TextInfo.CompareOrdinalIgnoreCaseEx(strA, indexA, strB, indexB, lengthA, lengthB)); -#endif default: throw new ArgumentException(Environment.GetResourceString("NotSupported_StringComparison")); @@ -807,11 +798,7 @@ namespace System return this.Length < value.Length ? false : (CompareOrdinalHelper(this, this.Length - value.Length, value.Length, value, 0, value.Length) == 0); case StringComparison.OrdinalIgnoreCase: -#if FEATURE_COREFX_GLOBALIZATION return this.Length < value.Length ? false : (CompareInfo.CompareOrdinalIgnoreCase(this, this.Length - value.Length, value.Length, value, 0, value.Length) == 0); -#else - return this.Length < value.Length ? false : (TextInfo.CompareOrdinalIgnoreCaseEx(this, this.Length - value.Length, value, 0, value.Length, value.Length) == 0); -#endif default: throw new ArgumentException(Environment.GetResourceString("NotSupported_StringComparison"), nameof(comparisonType)); } @@ -929,12 +916,7 @@ namespace System return EqualsIgnoreCaseAsciiHelper(this, value); } -#if FEATURE_COREFX_GLOBALIZATION return (CompareInfo.CompareOrdinalIgnoreCase(this, 0, this.Length, value, 0, value.Length) == 0); -#else - // Take the slow path. - return (TextInfo.CompareOrdinalIgnoreCase(this, value) == 0); -#endif default: throw new ArgumentException(Environment.GetResourceString("NotSupported_StringComparison"), nameof(comparisonType)); @@ -1008,11 +990,7 @@ namespace System } // Take the slow path. -#if FEATURE_COREFX_GLOBALIZATION return (CompareInfo.CompareOrdinalIgnoreCase(a, 0, a.Length, b, 0, b.Length) == 0); -#else - return (TextInfo.CompareOrdinalIgnoreCase(a, b) == 0); -#endif } default: @@ -1188,11 +1166,7 @@ namespace System return false; } -#if FEATURE_COREFX_GLOBALIZATION return (CompareInfo.CompareOrdinalIgnoreCase(this, 0, value.Length, value, 0, value.Length) == 0); -#else - return (TextInfo.CompareOrdinalIgnoreCaseEx(this, 0, value, 0, value.Length, value.Length) == 0); -#endif default: throw new ArgumentException(Environment.GetResourceString("NotSupported_StringComparison"), nameof(comparisonType)); diff --git a/src/mscorlib/src/System/Threading/Thread.cs b/src/mscorlib/src/System/Threading/Thread.cs index 0b6c166..6342aa4 100644 --- a/src/mscorlib/src/System/Threading/Thread.cs +++ b/src/mscorlib/src/System/Threading/Thread.cs @@ -146,19 +146,6 @@ namespace System.Threading [ThreadStatic] internal static CultureInfo m_CurrentUICulture; - private static AsyncLocal s_asyncLocalCurrentCulture; - private static AsyncLocal s_asyncLocalCurrentUICulture; - - private static void AsyncLocalSetCurrentCulture(AsyncLocalValueChangedArgs args) - { - m_CurrentCulture = args.CurrentValue; - } - - private static void AsyncLocalSetCurrentUICulture(AsyncLocalValueChangedArgs args) - { - m_CurrentUICulture = args.CurrentValue; - } - // Adding an empty default ctor for annotation purposes internal Thread() { } @@ -451,73 +438,21 @@ namespace System.Threading get { Contract.Ensures(Contract.Result() != null); -#if FEATURE_APPX && !FEATURE_COREFX_GLOBALIZATION - if (AppDomain.IsAppXModel()) - { - return CultureInfo.GetCultureInfoForUserPreferredLanguageInAppX() ?? GetCurrentUICultureNoAppX(); - } - else -#endif - { - return GetCurrentUICultureNoAppX(); - } + return CultureInfo.CurrentUICulture; } set { - if (value == null) - { - throw new ArgumentNullException(nameof(value)); - } - Contract.EndContractBlock(); - - //If they're trying to use a Culture with a name that we can't use in resource lookup, - //don't even let them set it on the thread. - CultureInfo.VerifyCultureName(value, true); - // If you add more pre-conditions to this method, check to see if you also need to // add them to CultureInfo.DefaultThreadCurrentUICulture.set. if (m_CurrentUICulture == null && m_CurrentCulture == null) nativeInitCultureAccessors(); - if (!AppContextSwitches.NoAsyncCurrentCulture) - { - if (s_asyncLocalCurrentUICulture == null) - { - Interlocked.CompareExchange(ref s_asyncLocalCurrentUICulture, new AsyncLocal(AsyncLocalSetCurrentUICulture), null); - } - - // this one will set m_CurrentUICulture too - s_asyncLocalCurrentUICulture.Value = value; - } - else - { - m_CurrentUICulture = value; - } + CultureInfo.CurrentUICulture = value; } } - internal CultureInfo GetCurrentUICultureNoAppX() - { - Contract.Ensures(Contract.Result() != null); - -#if FEATURE_COREFX_GLOBALIZATION - return CultureInfo.CurrentUICulture; -#else - - // Fetch a local copy of m_CurrentUICulture to - // avoid race conditions that malicious user can introduce - if (m_CurrentUICulture == null) - { - CultureInfo appDomainDefaultUICulture = CultureInfo.DefaultThreadCurrentUICulture; - return (appDomainDefaultUICulture != null ? appDomainDefaultUICulture : CultureInfo.UserDefaultUICulture); - } - - return m_CurrentUICulture; -#endif - } - // This returns the exposed context for a given context ID. // As the culture can be customized object then we cannot hold any @@ -537,25 +472,11 @@ namespace System.Threading get { Contract.Ensures(Contract.Result() != null); - -#if FEATURE_APPX && !FEATURE_COREFX_GLOBALIZATION - if (AppDomain.IsAppXModel()) - { - return CultureInfo.GetCultureInfoForUserPreferredLanguageInAppX() ?? GetCurrentCultureNoAppX(); - } - else -#endif - { - return GetCurrentCultureNoAppX(); - } + return CultureInfo.CurrentCulture; } set { - if (null == value) - { - throw new ArgumentNullException(nameof(value)); - } Contract.EndContractBlock(); // If you add more pre-conditions to this method, check to see if you also need to @@ -563,40 +484,9 @@ namespace System.Threading if (m_CurrentCulture == null && m_CurrentUICulture == null) nativeInitCultureAccessors(); - - if (!AppContextSwitches.NoAsyncCurrentCulture) - { - if (s_asyncLocalCurrentCulture == null) - { - Interlocked.CompareExchange(ref s_asyncLocalCurrentCulture, new AsyncLocal(AsyncLocalSetCurrentCulture), null); - } - // this one will set m_CurrentCulture too - s_asyncLocalCurrentCulture.Value = value; - } - else - { - m_CurrentCulture = value; - } - } - } - - private CultureInfo GetCurrentCultureNoAppX() - { -#if FEATURE_COREFX_GLOBALIZATION - return CultureInfo.CurrentCulture; -#else - Contract.Ensures(Contract.Result() != null); - - // Fetch a local copy of m_CurrentCulture to - // avoid race conditions that malicious user can introduce - if (m_CurrentCulture == null) - { - CultureInfo appDomainDefaultCulture = CultureInfo.DefaultThreadCurrentCulture; - return (appDomainDefaultCulture != null ? appDomainDefaultCulture : CultureInfo.UserDefaultCulture); + + CultureInfo.CurrentCulture = value; } - - return m_CurrentCulture; -#endif } [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] diff --git a/src/utilcode/newapis.cpp b/src/utilcode/newapis.cpp index 599197c..e7d4b9f 100644 --- a/src/utilcode/newapis.cpp +++ b/src/utilcode/newapis.cpp @@ -182,9 +182,6 @@ namespace NewApis GetLocaleInfoEx (__in LPCWSTR lpLocaleName, __in LCTYPE LCType, __out_ecount_opt(cchData) LPWSTR lpLCData, __in int cchData) { _ASSERTE((lpLCData == NULL && cchData == 0) || (lpLCData != NULL && cchData > 0)); - // ComNlsInfo::nativeInitCultureData calls GetLocaleInfoEx with LcType LOCALE_SNAME - // to determine if this is a valid culture. We shouldn't assert in this case, but - // all others we should. _ASSERTE(LCType == LOCALE_SNAME || NotLeakingFrameworkOnlyCultures(lpLocaleName)); int retVal; diff --git a/src/vm/ecalllist.h b/src/vm/ecalllist.h index 06f150f..008a0e7 100644 --- a/src/vm/ecalllist.h +++ b/src/vm/ecalllist.h @@ -888,7 +888,6 @@ FCFuncStart(gCalendarDataFuncs) FCFuncEnd() FCFuncStart(gCultureDataFuncs) - FCFuncElement("nativeInitCultureData", COMNlsInfo::nativeInitCultureData) FCFuncElement("nativeGetNumberFormatInfoValues", COMNlsInfo::nativeGetNumberFormatInfoValues) FCFuncElement("nativeEnumTimeFormats", CalendarData::nativeEnumTimeFormats) FCFuncElement("LCIDToLocaleName", COMNlsInfo::LCIDToLocaleName) diff --git a/src/vm/mscorlib.h b/src/vm/mscorlib.h index 7f139a6..178ce2c 100644 --- a/src/vm/mscorlib.h +++ b/src/vm/mscorlib.h @@ -304,80 +304,6 @@ DEFINE_FIELD_U(m_encodedEnumType, CustomAttributeType, m_enumType) DEFINE_FIELD_U(m_encodedArrayType, CustomAttributeType, m_arrayType) DEFINE_FIELD_U(m_padding, CustomAttributeType, m_padding) - - - -#ifndef FEATURE_COREFX_GLOBALIZATION -DEFINE_CLASS_U(Globalization, CultureData, CultureDataBaseObject) -DEFINE_FIELD_U(sRealName, CultureDataBaseObject, sRealName) -DEFINE_FIELD_U(sWindowsName, CultureDataBaseObject, sWindowsName) -DEFINE_FIELD_U(sName, CultureDataBaseObject, sName) -DEFINE_FIELD_U(sParent, CultureDataBaseObject, sParent) -DEFINE_FIELD_U(sLocalizedDisplayName, CultureDataBaseObject, sLocalizedDisplayName) -DEFINE_FIELD_U(sEnglishDisplayName, CultureDataBaseObject, sEnglishDisplayName) -DEFINE_FIELD_U(sNativeDisplayName, CultureDataBaseObject, sNativeDisplayName) -DEFINE_FIELD_U(sSpecificCulture, CultureDataBaseObject, sSpecificCulture) -DEFINE_FIELD_U(sISO639Language, CultureDataBaseObject, sISO639Language) -DEFINE_FIELD_U(sLocalizedLanguage, CultureDataBaseObject, sLocalizedLanguage) -DEFINE_FIELD_U(sEnglishLanguage, CultureDataBaseObject, sEnglishLanguage) -DEFINE_FIELD_U(sNativeLanguage, CultureDataBaseObject, sNativeLanguage) -DEFINE_FIELD_U(sRegionName, CultureDataBaseObject, sRegionName) -//DEFINE_FIELD_U(iCountry, CultureDataBaseObject, iCountry) -DEFINE_FIELD_U(iGeoId, CultureDataBaseObject, iGeoId) -DEFINE_FIELD_U(sLocalizedCountry, CultureDataBaseObject, sLocalizedCountry) -DEFINE_FIELD_U(sEnglishCountry, CultureDataBaseObject, sEnglishCountry) -DEFINE_FIELD_U(sNativeCountry, CultureDataBaseObject, sNativeCountry) -DEFINE_FIELD_U(sISO3166CountryName, CultureDataBaseObject, sISO3166CountryName) -DEFINE_FIELD_U(sPositiveSign, CultureDataBaseObject, sPositiveSign) -DEFINE_FIELD_U(sNegativeSign, CultureDataBaseObject, sNegativeSign) -DEFINE_FIELD_U(saNativeDigits, CultureDataBaseObject, saNativeDigits) -DEFINE_FIELD_U(iDigitSubstitution, CultureDataBaseObject, iDigitSubstitution) -DEFINE_FIELD_U(iLeadingZeros, CultureDataBaseObject, iLeadingZeros) -DEFINE_FIELD_U(iDigits, CultureDataBaseObject, iDigits) -DEFINE_FIELD_U(iNegativeNumber, CultureDataBaseObject, iNegativeNumber) -DEFINE_FIELD_U(waGrouping, CultureDataBaseObject, waGrouping) -DEFINE_FIELD_U(sDecimalSeparator, CultureDataBaseObject, sDecimalSeparator) -DEFINE_FIELD_U(sThousandSeparator, CultureDataBaseObject, sThousandSeparator) -DEFINE_FIELD_U(sNaN, CultureDataBaseObject, sNaN) -DEFINE_FIELD_U(sPositiveInfinity, CultureDataBaseObject, sPositiveInfinity) -DEFINE_FIELD_U(sNegativeInfinity, CultureDataBaseObject, sNegativeInfinity) -DEFINE_FIELD_U(iNegativePercent, CultureDataBaseObject, iNegativePercent) -DEFINE_FIELD_U(iPositivePercent, CultureDataBaseObject, iPositivePercent) -DEFINE_FIELD_U(sPercent, CultureDataBaseObject, sPercent) -DEFINE_FIELD_U(sPerMille, CultureDataBaseObject, sPerMille) -DEFINE_FIELD_U(sCurrency, CultureDataBaseObject, sCurrency) -DEFINE_FIELD_U(sIntlMonetarySymbol, CultureDataBaseObject, sIntlMonetarySymbol) -DEFINE_FIELD_U(sEnglishCurrency, CultureDataBaseObject, sEnglishCurrency) -DEFINE_FIELD_U(sNativeCurrency, CultureDataBaseObject, sNativeCurrency) -DEFINE_FIELD_U(iCurrencyDigits, CultureDataBaseObject, iCurrencyDigits) -DEFINE_FIELD_U(iCurrency, CultureDataBaseObject, iCurrency) -DEFINE_FIELD_U(iNegativeCurrency, CultureDataBaseObject, iNegativeCurrency) -DEFINE_FIELD_U(waMonetaryGrouping, CultureDataBaseObject, waMonetaryGrouping) -DEFINE_FIELD_U(sMonetaryDecimal, CultureDataBaseObject, sMonetaryDecimal) -DEFINE_FIELD_U(sMonetaryThousand, CultureDataBaseObject, sMonetaryThousand) -DEFINE_FIELD_U(iMeasure, CultureDataBaseObject, iMeasure) -DEFINE_FIELD_U(sListSeparator, CultureDataBaseObject, sListSeparator) -//DEFINE_FIELD_U(iPaperSize, CultureDataBaseObject, iPaperSize) -//DEFINE_FIELD_U(waFontSignature, CultureDataBaseObject, waFontSignature) -DEFINE_FIELD_U(sAM1159, CultureDataBaseObject, sAM1159) -DEFINE_FIELD_U(sPM2359, CultureDataBaseObject, sPM2359) -DEFINE_FIELD_U(sTimeSeparator, CultureDataBaseObject, sTimeSeparator) -DEFINE_FIELD_U(saLongTimes, CultureDataBaseObject, saLongTimes) -DEFINE_FIELD_U(saShortTimes, CultureDataBaseObject, saShortTimes) -DEFINE_FIELD_U(saDurationFormats, CultureDataBaseObject, saDurationFormats) -DEFINE_FIELD_U(iFirstDayOfWeek, CultureDataBaseObject, iFirstDayOfWeek) -DEFINE_FIELD_U(iFirstWeekOfYear, CultureDataBaseObject, iFirstWeekOfYear) -DEFINE_FIELD_U(waCalendars, CultureDataBaseObject, waCalendars) -DEFINE_FIELD_U(calendars, CultureDataBaseObject, calendars) -DEFINE_FIELD_U(iReadingLayout, CultureDataBaseObject, iReadingLayout) -DEFINE_FIELD_U(sTextInfo, CultureDataBaseObject, sTextInfo) -DEFINE_FIELD_U(sCompareInfo, CultureDataBaseObject, sCompareInfo) -DEFINE_FIELD_U(sScripts, CultureDataBaseObject, sScripts) -DEFINE_FIELD_U(bUseOverrides, CultureDataBaseObject, bUseOverrides) -DEFINE_FIELD_U(bNeutral, CultureDataBaseObject, bNeutral) -DEFINE_FIELD_U(bWin32Installed, CultureDataBaseObject, bWin32Installed) -DEFINE_FIELD_U(bFramework, CultureDataBaseObject, bFramework) -#endif #ifndef FEATURE_COREFX_GLOBALIZATION DEFINE_CLASS_U(Globalization, CalendarData, CalendarDataBaseObject) DEFINE_FIELD_U(sNativeName, CalendarDataBaseObject, sNativeName) @@ -407,16 +333,14 @@ DEFINE_FIELD_U(textInfo, CultureInfoBaseObject, textInfo) DEFINE_FIELD_U(numInfo, CultureInfoBaseObject, numInfo) DEFINE_FIELD_U(dateTimeInfo, CultureInfoBaseObject, dateTimeInfo) DEFINE_FIELD_U(calendar, CultureInfoBaseObject, calendar) -DEFINE_FIELD_U(m_consoleFallbackCulture, CultureInfoBaseObject, m_consoleFallbackCulture) -DEFINE_FIELD_U(m_name, CultureInfoBaseObject, m_name) -DEFINE_FIELD_U(m_nonSortName, CultureInfoBaseObject, m_nonSortName) -DEFINE_FIELD_U(m_sortName, CultureInfoBaseObject, m_sortName) -DEFINE_FIELD_U(m_parent, CultureInfoBaseObject, m_parent) -DEFINE_FIELD_U(m_isReadOnly, CultureInfoBaseObject, m_isReadOnly) -DEFINE_FIELD_U(m_isInherited, CultureInfoBaseObject, m_isInherited) -#ifndef FEATURE_COREFX_GLOBALIZATION -DEFINE_FIELD_U(m_useUserOverride, CultureInfoBaseObject, m_useUserOverride) -#endif +DEFINE_FIELD_U(_consoleFallbackCulture, CultureInfoBaseObject, _consoleFallbackCulture) +DEFINE_FIELD_U(_name, CultureInfoBaseObject, _name) +DEFINE_FIELD_U(_nonSortName, CultureInfoBaseObject, _nonSortName) +DEFINE_FIELD_U(_sortName, CultureInfoBaseObject, _sortName) +DEFINE_FIELD_U(_parent, CultureInfoBaseObject, _parent) +DEFINE_FIELD_U(_isReadOnly, CultureInfoBaseObject, _isReadOnly) +DEFINE_FIELD_U(_isInherited, CultureInfoBaseObject, _isInherited) +DEFINE_FIELD_U(_useUserOverride, CultureInfoBaseObject, _useUserOverride) DEFINE_CLASS(CULTURE_INFO, Globalization, CultureInfo) DEFINE_METHOD(CULTURE_INFO, STR_CTOR, .ctor, IM_Str_RetVoid) DEFINE_FIELD(CULTURE_INFO, CURRENT_CULTURE, s_userDefaultCulture) @@ -769,9 +693,6 @@ DEFINE_FIELD_U(numberGroupSeparator, NumberFormatInfo, sNumberGroup) DEFINE_FIELD_U(currencyGroupSeparator, NumberFormatInfo, sCurrencyGroup) DEFINE_FIELD_U(currencyDecimalSeparator,NumberFormatInfo, sCurrencyDecimal) DEFINE_FIELD_U(currencySymbol, NumberFormatInfo, sCurrency) -#ifndef FEATURE_COREFX_GLOBALIZATION -DEFINE_FIELD_U(ansiCurrencySymbol, NumberFormatInfo, sAnsiCurrency) -#endif DEFINE_FIELD_U(nanSymbol, NumberFormatInfo, sNaN) DEFINE_FIELD_U(positiveInfinitySymbol, NumberFormatInfo, sPositiveInfinity) DEFINE_FIELD_U(negativeInfinitySymbol, NumberFormatInfo, sNegativeInfinity) @@ -780,9 +701,6 @@ DEFINE_FIELD_U(percentGroupSeparator, NumberFormatInfo, sPercentGroup) DEFINE_FIELD_U(percentSymbol, NumberFormatInfo, sPercent) DEFINE_FIELD_U(perMilleSymbol, NumberFormatInfo, sPerMille) DEFINE_FIELD_U(nativeDigits, NumberFormatInfo, sNativeDigits) -#ifndef FEATURE_COREFX_GLOBALIZATION -DEFINE_FIELD_U(m_dataItem, NumberFormatInfo, iDataItem) -#endif DEFINE_FIELD_U(numberDecimalDigits, NumberFormatInfo, cNumberDecimals) DEFINE_FIELD_U(currencyDecimalDigits, NumberFormatInfo, cCurrencyDecimals) DEFINE_FIELD_U(currencyPositivePattern,NumberFormatInfo, cPosCurrencyFormat) @@ -793,14 +711,7 @@ DEFINE_FIELD_U(percentNegativePattern, NumberFormatInfo, cNegativePercentForma DEFINE_FIELD_U(percentDecimalDigits, NumberFormatInfo, cPercentDecimals) DEFINE_FIELD_U(digitSubstitution, NumberFormatInfo, iDigitSubstitution) DEFINE_FIELD_U(isReadOnly, NumberFormatInfo, bIsReadOnly) -#ifndef FEATURE_COREFX_GLOBALIZATION -DEFINE_FIELD_U(m_useUserOverride, NumberFormatInfo, bUseUserOverride) -#endif DEFINE_FIELD_U(m_isInvariant, NumberFormatInfo, bIsInvariant) -#ifndef FEATURE_COREFX_GLOBALIZATION -DEFINE_FIELD_U(validForParseAsNumber, NumberFormatInfo, bvalidForParseAsNumber) -DEFINE_FIELD_U(validForParseAsCurrency,NumberFormatInfo, bvalidForParseAsCurrency) -#endif // Defined as element type alias // DEFINE_CLASS(OBJECT, System, Object) diff --git a/src/vm/object.h b/src/vm/object.h index 8f711cd..1a9d8fd 100644 --- a/src/vm/object.h +++ b/src/vm/object.h @@ -1580,143 +1580,33 @@ private: OBJECTREF numInfo; OBJECTREF dateTimeInfo; OBJECTREF calendar; - OBJECTREF m_cultureData; - OBJECTREF m_consoleFallbackCulture; - STRINGREF m_name; // "real" name - en-US, de-DE_phoneb or fj-FJ - STRINGREF m_nonSortName; // name w/o sort info (de-DE for de-DE_phoneb) - STRINGREF m_sortName; // Sort only name (de-DE_phoneb, en-us for fj-fj (w/us sort) - CULTUREINFOBASEREF m_parent; -#ifndef FEATURE_COREFX_GLOBALIZATION - INT32 iDataItem; // NEVER USED, DO NOT USE THIS! (Serialized in Whidbey/Everett) - INT32 iCultureID; // NEVER USED, DO NOT USE THIS! (Serialized in Whidbey/Everett) -#endif // !FEATURE_COREFX_GLOBALIZATION - CLR_BOOL m_isReadOnly; - CLR_BOOL m_isInherited; - CLR_BOOL m_useUserOverride; + OBJECTREF _cultureData; + OBJECTREF _consoleFallbackCulture; + STRINGREF _name; // "real" name - en-US, de-DE_phoneb or fj-FJ + STRINGREF _nonSortName; // name w/o sort info (de-DE for de-DE_phoneb) + STRINGREF _sortName; // Sort only name (de-DE_phoneb, en-us for fj-fj (w/us sort) + CULTUREINFOBASEREF _parent; + CLR_BOOL _isReadOnly; + CLR_BOOL _isInherited; + CLR_BOOL _useUserOverride; public: CULTUREINFOBASEREF GetParent() { LIMITED_METHOD_CONTRACT; - return m_parent; + return _parent; }// GetParent STRINGREF GetName() { LIMITED_METHOD_CONTRACT; - return m_name; + return _name; }// GetName - }; // class CultureInfoBaseObject - #ifndef FEATURE_COREFX_GLOBALIZATION -typedef DPTR(class CultureDataBaseObject) PTR_CultureDataBaseObject; -class CultureDataBaseObject : public Object -{ -public: - // offsets are for Silverlight - /* 0x000 */ STRINGREF sRealName ; // Name you passed in (ie: en-US, en, or de-DE_phoneb) - /* 0x008 */ STRINGREF sWindowsName ; // Name OS thinks the object is (ie: de-DE_phoneb, or en-US (even if en was passed in)) - /* 0x010 */ STRINGREF sName ; // locale name (ie: en-us, NO sort info, but could be neutral) - /* 0x012 */ STRINGREF sParent ; // Parent name (which may be a custom locale/culture) - /* 0x020 */ STRINGREF sLocalizedDisplayName ; // Localized pretty name for this locale - /* 0x028 */ STRINGREF sEnglishDisplayName ; // English pretty name for this locale - /* 0x030 */ STRINGREF sNativeDisplayName ; // Native pretty name for this locale - /* 0x038 */ STRINGREF sSpecificCulture ; // The culture name to be used in CultureInfo.CreateSpecificCulture(), en-US form if neutral, sort name if sort - /* 0x040 */ STRINGREF sISO639Language ; // ISO 639 Language Name - /* 0x048 */ STRINGREF sLocalizedLanguage ; // Localized name for this language - /* 0x050 */ STRINGREF sEnglishLanguage ; // English name for this language - /* 0x058 */ STRINGREF sNativeLanguage ; // Native name of this language - /* 0x060 */ STRINGREF sRegionName ; // (RegionInfo) - /* 0x068 */ STRINGREF sLocalizedCountry ; // localized country name - /* 0x070 */ STRINGREF sEnglishCountry ; // english country name (RegionInfo) - /* 0x078 */ STRINGREF sNativeCountry ; // native country name - /* 0x080 */ STRINGREF sISO3166CountryName ; // (RegionInfo), ie: US - /* 0x088 */ STRINGREF sPositiveSign ; // (user can override) positive sign - /* 0x090 */ STRINGREF sNegativeSign ; // (user can override) negative sign - - /* 0x098 */ PTRARRAYREF saNativeDigits ; // (user can override) native characters for digits 0-9 - /* 0x0a0 */ I4ARRAYREF waGrouping ; // (user can override) grouping of digits - - /* 0x0a8 */ STRINGREF sDecimalSeparator ; // (user can override) decimal separator - /* 0x0b0 */ STRINGREF sThousandSeparator ; // (user can override) thousands separator - /* 0x0b8 */ STRINGREF sNaN ; // Not a Number - /* 0x0c0 */ STRINGREF sPositiveInfinity ; // + Infinity - /* 0x0c8 */ STRINGREF sNegativeInfinity ; // - Infinity - /* 0x0d0 */ STRINGREF sPercent ; // Percent (%) symbol - /* 0x0d8 */ STRINGREF sPerMille ; // PerMille (U+2030) symbol - /* 0x0e0 */ STRINGREF sCurrency ; // (user can override) local monetary symbol - /* 0x0e8 */ STRINGREF sIntlMonetarySymbol ; // international monetary symbol (RegionInfo) - /* 0x0f0 */ STRINGREF sEnglishCurrency ; // English name for this currency - /* 0x0f8 */ STRINGREF sNativeCurrency ; // Native name for this currency - - /* 0x100 */ I4ARRAYREF waMonetaryGrouping ; // (user can override) monetary grouping of digits - - /* 0x108 */ STRINGREF sMonetaryDecimal ; // (user can override) monetary decimal separator - /* 0x110 */ STRINGREF sMonetaryThousand ; // (user can override) monetary thousands separator - /* 0x118 */ STRINGREF sListSeparator ; // (user can override) list separator - /* 0x120 */ STRINGREF sAM1159 ; // (user can override) AM designator - /* 0x128 */ STRINGREF sPM2359 ; // (user can override) PM designator - STRINGREF sTimeSeparator ; // Time Separator - - /* 0x130 */ PTRARRAYREF saLongTimes ; // (user can override) time format - /* 0x138 */ PTRARRAYREF saShortTimes ; // short time format - /* 0x140 */ PTRARRAYREF saDurationFormats ; // time duration format - - /* 0x148 */ I4ARRAYREF waCalendars ; // all available calendar type(s). The first one is the default calendar - - /* 0x150 */ PTRARRAYREF calendars ; // Store for specific calendar data - - /* 0x158 */ STRINGREF sTextInfo ; // Text info name to use for custom - /* 0x160 */ STRINGREF sCompareInfo ; // Compare info name (including sorting key) to use if custom - /* 0x168 */ STRINGREF sScripts ; // Typical Scripts for this locale (latn;cyrl; etc) - - // these are ordered correctly - /* ????? */ STRINGREF sAbbrevLang ; // abbreviated language name (Windows Language Name) ex: ENU - /* ????? */ STRINGREF sAbbrevCountry ; // abbreviated country name (RegionInfo) (Windows Region Name) ex: USA - /* ????? */ STRINGREF sISO639Language2 ; // 3 char ISO 639 lang name 2 ex: eng - /* ????? */ STRINGREF sISO3166CountryName2 ; // 3 char ISO 639 country name 2 2(RegionInfo) ex: USA (ISO) - /* ????? */ STRINGREF sConsoleFallbackName ; // The culture name for the console fallback UI culture - /* ????? */ STRINGREF sKeyboardsToInstall ; // Keyboard installation string. - /* ????? */ STRINGREF fontSignature ; // Font signature (16 WORDS) - -// Unused for now: /* ????? */ INT32 iCountry ; // (user can override) country code (RegionInfo) - /* 0x170 */ INT32 iGeoId ; // GeoId - /* 0x174 */ INT32 iDigitSubstitution ; // (user can override) Digit substitution 0=context, 1=none/arabic, 2=Native/national (2 seems to be unused) - /* 0x178 */ INT32 iLeadingZeros ; // (user can override) leading zeros 0 = no leading zeros, 1 = leading zeros - /* 0x17c */ INT32 iDigits ; // (user can override) number of fractional digits - /* 0x180 */ INT32 iNegativeNumber ; // (user can override) negative number format - /* 0x184 */ INT32 iNegativePercent ; // Negative Percent (0-3) - /* 0x188 */ INT32 iPositivePercent ; // Positive Percent (0-11) - /* 0x18c */ INT32 iCurrencyDigits ; // (user can override) # local monetary fractional digits - /* 0x190 */ INT32 iCurrency ; // (user can override) positive currency format - /* 0x194 */ INT32 iNegativeCurrency ; // (user can override) negative currency format - /* 0x198 */ INT32 iMeasure ; // (user can override) system of measurement 0=metric, 1=US (RegionInfo) -// Unused for now /* ????? */ INT32 iPaperSize ; // default paper size (RegionInfo) - /* 0x19c */ INT32 iFirstDayOfWeek ; // (user can override) first day of week (gregorian really) - /* 0x1a0 */ INT32 iFirstWeekOfYear ; // (user can override) first week of year (gregorian really) - - /* ????? */ INT32 iReadingLayout; // Reading Layout Data (0-3) - - // these are ordered correctly - /* ????? */ INT32 iDefaultAnsiCodePage ; // default ansi code page ID (ACP) - /* ????? */ INT32 iDefaultOemCodePage ; // default oem code page ID (OCP or OEM) - /* ????? */ INT32 iDefaultMacCodePage ; // default macintosh code page - /* ????? */ INT32 iDefaultEbcdicCodePage ; // default EBCDIC code page - /* ????? */ INT32 iLanguage ; // locale ID (0409) - NO sort information - /* ????? */ INT32 iInputLanguageHandle ; // input language handle - /* 0x1a4 */ CLR_BOOL bUseOverrides ; // use user overrides? - /* 0x1a5 */ CLR_BOOL bNeutral ; // Flags for the culture (ie: neutral or not right now) - /* ????? */ CLR_BOOL bWin32Installed ; // Flags indicate if the culture is Win32 installed - /* ????? */ CLR_BOOL bFramework ; // Flags for indicate if the culture is one of Whidbey cultures - -}; // class CultureDataBaseObject - - - typedef DPTR(class CalendarDataBaseObject) PTR_CalendarDataBaseObject; class CalendarDataBaseObject : public Object { @@ -3814,9 +3704,6 @@ public: STRINGREF sCurrencyGroup; // currencyDecimalSeparator STRINGREF sCurrencyDecimal; // currencyGroupSeparator STRINGREF sCurrency; // currencySymbol -#ifndef FEATURE_COREFX_GLOBALIZATION - STRINGREF sAnsiCurrency; // ansiCurrencySymbol -#endif STRINGREF sNaN; // nanSymbol STRINGREF sPositiveInfinity; // positiveInfinitySymbol STRINGREF sNegativeInfinity; // negativeInfinitySymbol @@ -3827,9 +3714,6 @@ public: PTRARRAYREF sNativeDigits; // nativeDigits (a string array) -#ifndef FEATURE_COREFX_GLOBALIZATION - INT32 iDataItem; // Index into the CultureInfo Table. Only used from managed code. -#endif INT32 cNumberDecimals; // numberDecimalDigits INT32 cCurrencyDecimals; // currencyDecimalDigits INT32 cPosCurrencyFormat; // positiveCurrencyFormat @@ -3841,14 +3725,7 @@ public: INT32 iDigitSubstitution; // digitSubstitution CLR_BOOL bIsReadOnly; // Is this NumberFormatInfo ReadOnly? -#ifndef FEATURE_COREFX_GLOBALIZATION - CLR_BOOL bUseUserOverride; // Flag to use user override. Only used from managed code. -#endif CLR_BOOL bIsInvariant; // Is this the NumberFormatInfo for the Invariant Culture? -#ifndef FEATURE_COREFX_GLOBALIZATION - CLR_BOOL bvalidForParseAsNumber; // NEVER USED, DO NOT USE THIS! (Serialized in Whidbey/Everett) - CLR_BOOL bvalidForParseAsCurrency; // NEVER USED, DO NOT USE THIS! (Serialized in Whidbey/Everett) -#endif }; typedef NumberFormatInfo * NUMFMTREF; -- 2.7.4