versionFound = true;
// Allow the version to include a 'v' or 'V' prefix...
- if (value.Length > 0 && (value[0] == c_versionValuePrefix || value[0] == 'V'))
- {
- value = value.Substring(1);
- }
- Version realVersion = Version.Parse(value);
+ Version realVersion = value.Length > 0 && (value[0] == c_versionValuePrefix || value[0] == 'V') ?
+ Version.Parse(value.AsSpan(1)) :
+ Version.Parse(value);
// The version class will represent some unset values as -1 internally (instead of 0).
version = realVersion.Major * 10000;
if (realVersion.Minor > 0)
{
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)));
+ // for surrogate pairs do a ToUpper operation on the substring
+ ReadOnlySpan<char> src = input.AsSpan(inputIndex, 2);
+ if (_invariantMode)
+ {
+ result.Append(src); // surrogate pair in invariant mode, so changing case is a nop
+ }
+ else
+ {
+ Span<char> dst = stackalloc char[2];
+ ChangeCase(src, dst, toUpper: true);
+ result.Append(dst);
+ }
inputIndex++;
}
else
continue;
if ((s.Length - i) < escapeReplacement.Length)
continue;
- string prefix = s.Substring(i, escapeReplacement.Length);
- if (prefix == escapeReplacement)
+ if (s.AsSpan(i, escapeReplacement.Length).SequenceEqual(escapeReplacement))
{
sb.Append('\\');
sb.Append(kv.Key);
public override string ToString() => ScopeName;
- public static readonly TypeFilter FilterTypeName = FilterTypeNameImpl;
- public static readonly TypeFilter FilterTypeNameIgnoreCase = FilterTypeNameIgnoreCaseImpl;
+ public static readonly TypeFilter FilterTypeName = (m, c) => FilterTypeNameImpl(m, c, StringComparison.Ordinal);
+ public static readonly TypeFilter FilterTypeNameIgnoreCase = (m, c) => FilterTypeNameImpl(m, c, StringComparison.OrdinalIgnoreCase);
private const BindingFlags DefaultLookup = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public;
// FilterTypeName
// This method will filter the class based upon the name. It supports
// a trailing wild card.
- private static bool FilterTypeNameImpl(Type cls, object filterCriteria)
+ private static bool FilterTypeNameImpl(Type cls, object filterCriteria, StringComparison comparison)
{
// Check that the criteria object is a String object
- if (filterCriteria == null || !(filterCriteria is string))
- throw new InvalidFilterCriteriaException(SR.InvalidFilterCriteriaException_CritString);
-
- string str = (string)filterCriteria;
-
- // Check to see if this is a prefix or exact match requirement
- if (str.Length > 0 && str[str.Length - 1] == '*')
+ if (!(filterCriteria is string str))
{
- str = str.Substring(0, str.Length - 1);
- return cls.Name.StartsWith(str, StringComparison.Ordinal);
- }
-
- return cls.Name.Equals(str);
- }
-
- // FilterFieldNameIgnoreCase
- // This method filter the Type based upon name, it ignores case.
- private static bool FilterTypeNameIgnoreCaseImpl(Type cls, object filterCriteria)
- {
- // Check that the criteria object is a String object
- if (filterCriteria == null || !(filterCriteria is string))
throw new InvalidFilterCriteriaException(SR.InvalidFilterCriteriaException_CritString);
-
- string str = (string)filterCriteria;
-
+ }
// Check to see if this is a prefix or exact match requirement
if (str.Length > 0 && str[str.Length - 1] == '*')
{
- str = str.Substring(0, str.Length - 1);
- string name = cls.Name;
- if (name.Length >= str.Length)
- return (string.Compare(name, 0, str, 0, str.Length, StringComparison.OrdinalIgnoreCase) == 0);
- else
- return false;
+ ReadOnlySpan<char> slice = str.AsSpan(0, str.Length - 1);
+ return cls.Name.AsSpan().StartsWith(slice, comparison);
}
- return (string.Compare(str, cls.Name, StringComparison.OrdinalIgnoreCase) == 0);
+
+ return cls.Name.Equals(str, comparison);
}
}
}
return null;
}
- private static TimeSpan? TZif_ParseOffsetString(string offset)
+ private static TimeSpan? TZif_ParseOffsetString(ReadOnlySpan<char> offset)
{
TimeSpan? result = null;
- if (!string.IsNullOrEmpty(offset))
+ if (offset.Length > 0)
{
bool negative = offset[0] == '-';
if (negative || offset[0] == '+')
{
- offset = offset.Substring(1);
+ offset = offset.Slice(1);
}
// Try parsing just hours first.
// This method will filter based upon the name. A partial wildcard
// at the end of the string is supported.
// filterCriteria -- This is the string name
- private static bool FilterNameImpl(MemberInfo m, object filterCriteria)
+ private static bool FilterNameImpl(MemberInfo m, object filterCriteria, StringComparison comparison)
{
// Check that the criteria object is a String object
- if (filterCriteria == null || !(filterCriteria is string))
+ if (!(filterCriteria is string filterCriteriaString))
+ {
throw new InvalidFilterCriteriaException(SR.InvalidFilterCriteriaException_CritString);
+ }
- // At the moment this fails if its done on a single line....
- string str = ((string)filterCriteria);
- str = str.Trim();
+ ReadOnlySpan<char> str = filterCriteriaString.AsSpan().Trim();
+ ReadOnlySpan<char> name = m.Name;
- string name = m.Name;
// Get the nested class name only, as opposed to the mangled one
if (m.MemberType == MemberTypes.NestedType)
- name = name.Substring(name.LastIndexOf('+') + 1);
- // Check to see if this is a prefix or exact match requirement
- if (str.Length > 0 && str[str.Length - 1] == '*')
{
- str = str.Substring(0, str.Length - 1);
- return (name.StartsWith(str, StringComparison.Ordinal));
+ name = name.Slice(name.LastIndexOf('+') + 1);
}
- return (name.Equals(str));
- }
-
- // FilterIgnoreCase
- // This delegate will do a name search but does it with the
- // ignore case specified.
- private static bool FilterNameIgnoreCaseImpl(MemberInfo m, object filterCriteria)
- {
- // Check that the criteria object is a String object
- if (filterCriteria == null || !(filterCriteria is string))
- throw new InvalidFilterCriteriaException(SR.InvalidFilterCriteriaException_CritString);
-
- string str = (string)filterCriteria;
- str = str.Trim();
-
- string name = m.Name;
- // Get the nested class name only, as opposed to the mangled one
- if (m.MemberType == MemberTypes.NestedType)
- name = name.Substring(name.LastIndexOf('+') + 1);
// Check to see if this is a prefix or exact match requirement
if (str.Length > 0 && str[str.Length - 1] == '*')
{
- str = str.Substring(0, str.Length - 1);
- return (string.Compare(name, 0, str, 0, str.Length, StringComparison.OrdinalIgnoreCase) == 0);
+ str = str.Slice(0, str.Length - 1);
+ return name.StartsWith(str, comparison);
}
- return (string.Compare(str, name, StringComparison.OrdinalIgnoreCase) == 0);
+ return name.Equals(str, comparison);
}
}
}
public static readonly object Missing = System.Reflection.Missing.Value;
public static readonly MemberFilter FilterAttribute = FilterAttributeImpl;
- public static readonly MemberFilter FilterName = FilterNameImpl;
- public static readonly MemberFilter FilterNameIgnoreCase = FilterNameIgnoreCaseImpl;
+ public static readonly MemberFilter FilterName = (m, c) => FilterNameImpl(m, c, StringComparison.Ordinal);
+ public static readonly MemberFilter FilterNameIgnoreCase = (m, c) => FilterNameImpl(m, c, StringComparison.OrdinalIgnoreCase);
private const BindingFlags DefaultLookup = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public;
}