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;
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;
//
// Get a culture name
- // TODO: NLS Arrowhead Arrowhead - note that this doesn't handle the new calendars (lunisolar, etc)
+ // TODO: Note that this doesn't handle the new calendars (lunisolar, etc)
String culture = CalendarIdToCultureName(calendarId);
// Return our calendar
int tmpHash = 0;
- if (Interop.mincore.LCMapStringEx(_sortHandle != IntPtr.Zero ? null : _sortName,
- LCMAP_HASH | (uint)GetNativeCompareFlags(options),
- source, source.Length,
- &tmpHash, sizeof(int),
- null, null, _sortHandle) == 0)
+ fixed (char* pSource = source)
{
- Environment.FailFast("LCMapStringEx failed!");
+ if (Interop.mincore.LCMapStringEx(_sortHandle != IntPtr.Zero ? null : _sortName,
+ LCMAP_HASH | (uint)GetNativeCompareFlags(options),
+ pSource, source.Length,
+ &tmpHash, sizeof(int),
+ null, null, _sortHandle) == 0)
+ {
+ Environment.FailFast("LCMapStringEx failed!");
+ }
}
return tmpHash;
Contract.Assert(target != null);
Contract.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
Contract.Assert(target != null);
Contract.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
private const int FIND_FROMSTART = 0x00400000;
private const int FIND_FROMEND = 0x00800000;
+ // TODO: Instead of this method could we just have upstack code call IndexOfOrdinal with ignoreCase = false?
private static unsafe int FastIndexOfString(string source, string target, int startIndex, int sourceCount, int targetCount, bool findLastIndex)
{
int retValue = -1;
if ((options & CompareOptions.IgnoreWidth) != 0) { nativeCompareFlags |= NORM_IGNOREWIDTH; }
if ((options & CompareOptions.StringSort) != 0) { nativeCompareFlags |= SORT_STRINGSORT; }
+ // TODO: Can we try for GetNativeCompareFlags to never
+ // take Ordinal or OrdinalIgnoreCase. This value is not part of Win32, we just handle it special
+ // in some places.
// Suffix & Prefix shouldn't use this, make sure to turn off the NORM_LINGUISTIC_CASING flag
if (options == CompareOptions.Ordinal) { nativeCompareFlags = COMPARE_OPTIONS_ORDINAL; }
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);
SR.ArgumentNull_String);
}
Contract.EndContractBlock();
- int suffixLen = suffix.Length;
- int sourceLength = source.Length;
- if (suffixLen == 0)
+ if (suffix.Length == 0)
{
return (true);
}
- if (sourceLength == 0)
+ if (source.Length == 0)
{
return false;
}
// 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;
// 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;
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: NLS Arrowhead - This is broken, names can only be RFC4646 names (ie: a-zA-Z0-9).
- // TODO: NLS Arrowhead - This allows any unicode letter/digit
+ // 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;
public static CultureInfo DefaultThreadCurrentCulture
{
get { return s_DefaultThreadCurrentCulture; }
- [System.Security.SecuritySafeCritical] // auto-generated
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;
public static CultureInfo DefaultThreadCurrentUICulture
{
get { return s_DefaultThreadCurrentUICulture; }
- [System.Security.SecuritySafeCritical] // auto-generated
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)
////////////////////////////////////////////////////////////////////////
public virtual String DisplayName
{
- [System.Security.SecuritySafeCritical] // auto-generated
get
{
Contract.Ensures(Contract.Result<String>() != null);
////////////////////////////////////////////////////////////////////////
public virtual String NativeName
{
- [System.Security.SecuritySafeCritical] // auto-generated
get
{
Contract.Ensures(Contract.Result<String>() != null);
////////////////////////////////////////////////////////////////////////
public virtual String EnglishName
{
- [System.Security.SecuritySafeCritical] // auto-generated
get
{
Contract.Ensures(Contract.Result<String>() != null);
// ie: en
public virtual String TwoLetterISOLanguageName
{
- [System.Security.SecuritySafeCritical] // auto-generated
get
{
Contract.Ensures(Contract.Result<String>() != null);
// 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 Internal.Runtime.Augments;
namespace System.Globalization
}
else
{
- int result;
+ int ret;
// Check for Invariant to avoid A/V in LCMapStringEx
uint linguisticCasing = IsInvariantLocale(_textInfoName) ? 0 : LCMAP_LINGUISTIC_CASING;
//
// Create the result string.
//
- char[] buffer = new char[nLengthInput];
- fixed (char* pBuffer = buffer)
+ string result = string.FastAllocateString(nLengthInput);
+
+ fixed (char* pSource = s)
+ fixed (char* pResult = result)
{
- result = Interop.mincore.LCMapStringEx(_sortHandle != IntPtr.Zero ? null : _textInfoName,
- toUpper ? LCMAP_UPPERCASE | linguisticCasing : LCMAP_LOWERCASE | linguisticCasing,
- s,
- nLengthInput,
- pBuffer,
- nLengthInput,
- null,
- null,
- _sortHandle);
+ ret = Interop.mincore.LCMapStringEx(_sortHandle != IntPtr.Zero ? null : _textInfoName,
+ toUpper ? LCMAP_UPPERCASE | linguisticCasing : LCMAP_LOWERCASE | linguisticCasing,
+ pSource,
+ nLengthInput,
+ pResult,
+ nLengthInput,
+ null,
+ null,
+ _sortHandle);
}
- if (0 == result)
+ if (0 == ret)
{
throw new InvalidOperationException(SR.InvalidOperation_ReadOnly);
}
- Contract.Assert(result == nLengthInput, "Expected getting the same length of the original string");
- return new string(buffer, 0, result);
+ Contract.Assert(ret == nLengthInput, "Expected getting the same length of the original string");
+ return result;
}
}
Interop.mincore.LCMapStringEx(_sortHandle != IntPtr.Zero ? null : _textInfoName,
toUpper ? LCMAP_UPPERCASE | linguisticCasing : LCMAP_LOWERCASE | linguisticCasing,
- new string(c, 1),
+ &c,
1,
&retVal,
1,