listType = MemberListType.CaseSensitive;
}
- if (allowPrefixLookup && name.EndsWith("*", StringComparison.Ordinal))
+ if (allowPrefixLookup && name.EndsWith('*'))
{
// We set prefixLookup to true if name ends with a "*".
// We will also set listType to All so that all members are included in
internal static string CheckQuoted(string value)
{
- if (value.Length < 2 || value[0] != '\"' || value[value.Length - 1] != '\"')
- return value;
-
- return value.Length == 2 ? string.Empty : value.Substring(1, value.Length - 2);
+ return (value.Length >= 2 && value.StartsWith('\"') && value.EndsWith('\"'))
+ ? value.Substring(1, value.Length - 2)
+ : value;
}
internal bool EndofHeader()
// cross-platform with Windows (which has only '\' as an invalid char).
if (Path.IsPathRooted(pipeName))
{
- if (pipeName.IndexOfAny(s_invalidPathNameChars) >= 0 || pipeName[pipeName.Length - 1] == Path.DirectorySeparatorChar)
+ if (pipeName.IndexOfAny(s_invalidPathNameChars) >= 0 || pipeName.EndsWith(Path.DirectorySeparatorChar))
throw new PlatformNotSupportedException(SR.PlatformNotSupported_InvalidPipeNameChars);
// Caller is in full control of file location.
// We need the string to be at least 3 chars long: 2x quotes and at least 1 character. Also make sure we
// have a quoted string. Note that NameValueHeaderValue will never have leading/trailing whitespace.
string valueString = nameValue.Value;
- if ((valueString.Length < 3) || (valueString[0] != '\"') || (valueString[valueString.Length - 1] != '\"'))
+ if ((valueString.Length < 3) || !valueString.StartsWith('\"') || !valueString.EndsWith('\"'))
{
return false;
}
}
// Trailing/leading space are not allowed
- if (value[0] == ' ' || value[0] == '\t' || value[^1] == ' ' || value[^1] == '\t')
+ if (value.StartsWith(' ') || value.StartsWith('\t') || value.EndsWith(' ') || value.EndsWith('\t'))
{
ThrowFormatException(value);
}
{
// Remove at most a single set of quotes.
if (charset.Length > 2 &&
- charset[0] == '\"' &&
- charset[charset.Length - 1] == '\"')
+ charset.StartsWith('\"') &&
+ charset.EndsWith('\"'))
{
encoding = Encoding.GetEncoding(charset.Substring(1, charset.Length - 2));
}
{
throw new ArgumentException(SR.net_listener_host, nameof(uriPrefix));
}
- if (uriPrefix[uriPrefix.Length - 1] != '/')
+ if (!uriPrefix.EndsWith('/'))
{
throw new ArgumentException(SR.net_listener_slash, nameof(uriPrefix));
}
internal static void FillFromString(NameValueCollection nvc, string s, bool urlencoded, Encoding encoding)
{
+ int i = s.StartsWith('?') ? 1 : 0;
int l = s.Length;
- int i = (l > 0 && s[0] == '?') ? 1 : 0;
while (i < l)
{
string host = uri.Host;
int port = uri.Port;
string path = WebUtility.UrlDecode(uri.AbsolutePath);
- string pathSlash = path[path.Length - 1] == '/' ? path : path + "/";
+ string pathSlash = path.EndsWith('/') ? path : path + "/";
HttpListener? bestMatch = null;
int bestLength = -1;
ContentId = cid;
return cid;
}
- if (cid.Length >= 2 && cid[0] == '<' && cid[cid.Length - 1] == '>')
+ if (cid.StartsWith('<') && cid.EndsWith('>'))
{
return cid.Substring(1, cid.Length - 2);
}
return false;
}
- if (displayName.Length >= 2 && displayName[0] == '\"' && displayName[^1] == '\"')
+ if (displayName.Length >= 2 && displayName.StartsWith('\"') && displayName.EndsWith('\"'))
{
- // Peal bounding quotes, they'll get re-added later.
+ // Peel bounding quotes, they'll get re-added later.
displayName = displayName.Substring(1, displayName.Length - 2);
}
}
}
internal bool InternalSetName(string? value)
{
- if (string.IsNullOrEmpty(value) || value[0] == '$' || value.IndexOfAny(ReservedToName) != -1 || value[0] == ' ' || value[value.Length - 1] == ' ')
+ if (string.IsNullOrEmpty(value)
+ || value.StartsWith('$')
+ || value.StartsWith(' ')
+ || value.EndsWith(' ')
+ || value.IndexOfAny(ReservedToName) >= 0)
{
m_name = string.Empty;
return false;
}
// Check the name
- if (string.IsNullOrEmpty(m_name) || m_name[0] == '$' || m_name.IndexOfAny(ReservedToName) != -1 || m_name[0] == ' ' || m_name[m_name.Length - 1] == ' ')
+ if (string.IsNullOrEmpty(m_name) ||
+ m_name.StartsWith('$') ||
+ m_name.StartsWith(' ') ||
+ m_name.EndsWith(' ') ||
+ m_name.IndexOfAny(ReservedToName) >= 0)
{
if (shouldThrow)
{
// Check the value
if (m_value == null ||
- (!(m_value.Length > 2 && m_value[0] == '\"' && m_value[m_value.Length - 1] == '\"') && m_value.IndexOfAny(ReservedToValue) != -1))
+ (!(m_value.Length > 2 && m_value.StartsWith('\"') && m_value.EndsWith('\"')) && m_value.IndexOfAny(ReservedToValue) >= 0))
{
if (shouldThrow)
{
}
// Check Comment syntax
- if (Comment != null && !(Comment.Length > 2 && Comment[0] == '\"' && Comment[Comment.Length - 1] == '\"')
- && (Comment.IndexOfAny(ReservedToValue) != -1))
+ if (Comment != null && !(Comment.Length > 2 && Comment.StartsWith('\"') && Comment.EndsWith('\"'))
+ && (Comment.IndexOfAny(ReservedToValue) >= 0))
{
if (shouldThrow)
{
}
// Check Path syntax
- if (Path != null && !(Path.Length > 2 && Path[0] == '\"' && Path[Path.Length - 1] == '\"')
- && (Path.IndexOfAny(ReservedToValue) != -1))
+ if (Path != null && !(Path.Length > 2 && Path.StartsWith('\"') && Path.EndsWith('\"'))
+ && (Path.IndexOfAny(ReservedToValue) >= 0))
{
if (shouldThrow)
{
// Note: Normally Uri.AbsolutePath contains at least one "/" after parsing,
// but it's possible construct Uri with an empty path using a custom UriParser
int lastSlash;
- if (path.Length == 0 || path[0] != '/' || (lastSlash = path.LastIndexOf('/')) == 0)
+ if (!path.StartsWith('/') || (lastSlash = path.LastIndexOf('/')) == 0)
{
m_path = "/";
break;
else
{
// Parse port list
- if (value[0] != '\"' || value[value.Length - 1] != '\"')
+ if (!value.StartsWith('\"') || !value.EndsWith('\"'))
{
throw new CookieException(SR.Format(SR.net_cookie_attribute, CookieFields.PortAttributeName, value));
}
- string[] ports = value.Split(PortSplitDelimiters);
-
- List<int> portList = new List<int>();
- int port;
+ string[] ports = value.Split(PortSplitDelimiters, StringSplitOptions.RemoveEmptyEntries);
+ int[] parsedPorts = new int[ports.Length];
for (int i = 0; i < ports.Length; ++i)
{
- // Skip spaces
- if (ports[i] != string.Empty)
+ if (!int.TryParse(ports[i], out int port))
{
- if (!int.TryParse(ports[i], out port))
- {
- throw new CookieException(SR.Format(SR.net_cookie_attribute, CookieFields.PortAttributeName, value));
- }
-
- // valid values for port 0 - 0xFFFF
- if ((port < 0) || (port > 0xFFFF))
- {
- throw new CookieException(SR.Format(SR.net_cookie_attribute, CookieFields.PortAttributeName, value));
- }
+ throw new CookieException(SR.Format(SR.net_cookie_attribute, CookieFields.PortAttributeName, value));
+ }
- portList.Add(port);
+ // valid values for port 0 - 0xFFFF
+ if ((port < 0) || (port > 0xFFFF))
+ {
+ throw new CookieException(SR.Format(SR.net_cookie_attribute, CookieFields.PortAttributeName, value));
}
+
+ parsedPorts[i] = port;
}
- m_port_list = portList.ToArray();
+ m_port_list = parsedPorts;
m_port = value;
m_version = MaxSupportedVersion;
m_cookieVariant = CookieVariant.Rfc2965;
if (!requestPath.StartsWith(cookiePath, StringComparison.Ordinal))
return false;
return requestPath.Length == cookiePath.Length ||
- cookiePath.Length > 0 && cookiePath[^1] == '/' ||
+ cookiePath.EndsWith('/') ||
requestPath[cookiePath.Length] == '/';
}
commandList.Add(new PipelineEntry(FormatFtpCommand("RNFR", baseDir + requestFilename), flags));
string renameTo;
- if (!string.IsNullOrEmpty(request.RenameTo)
- && request.RenameTo.StartsWith("/", StringComparison.OrdinalIgnoreCase))
+ if (request.RenameTo is not null && request.RenameTo.StartsWith('/'))
{
renameTo = request.RenameTo; // Absolute path
}
}
// strip off trailing '/' on directory if present
- if (directory.Length > 1 && directory[directory.Length - 1] == '/')
+ if (directory.Length > 1 && directory.EndsWith('/'))
directory = directory.Substring(0, directory.Length - 1);
}
escapedFilename = escapedFilename.Replace("#", "%23");
// help us out if the user forgot to add a slash to the directory name
- string orginalPath = baseUri.AbsolutePath;
- if (orginalPath.Length > 0 && orginalPath[orginalPath.Length - 1] != '/')
+ string originalPath = baseUri.AbsolutePath;
+ if (originalPath.Length > 0 && !originalPath.EndsWith('/'))
{
UriBuilder uriBuilder = new UriBuilder(baseUri);
- uriBuilder.Path = orginalPath + "/";
+ uriBuilder.Path = originalPath + "/";
baseUri = uriBuilder.Uri;
}
// "$XDG_DATA_HOME defines the base directory relative to which user specific data files should be stored."
// "If $XDG_DATA_HOME is either not set or empty, a default equal to $HOME/.local/share should be used."
string? data = GetEnvironmentVariable("XDG_DATA_HOME");
- if (string.IsNullOrEmpty(data) || data[0] != '/')
+ if (data is null || !data.StartsWith('/'))
{
data = Path.Combine(home, ".local", "share");
}
// "$XDG_CONFIG_HOME defines the base directory relative to which user specific configuration files should be stored."
// "If $XDG_CONFIG_HOME is either not set or empty, a default equal to $HOME/.config should be used."
string? config = GetEnvironmentVariable("XDG_CONFIG_HOME");
- if (string.IsNullOrEmpty(config) || config[0] != '/')
+ if (config is null || !config.StartsWith('/'))
{
config = Path.Combine(home, ".config");
}
Debug.Assert(!string.IsNullOrEmpty(fallback), $"Expected non-empty fallback");
string? envPath = GetEnvironmentVariable(key);
- if (!string.IsNullOrEmpty(envPath) && envPath[0] == '/')
+ if (envPath is not null && envPath.StartsWith('/'))
{
return envPath;
}
return new int[] { 3 };
}
- if (win32Str[0] == '0')
+ if (win32Str.StartsWith('0'))
{
return new int[] { 0 };
}
// Since its in n;n;n;n;n format, we can always get the length quickly
int[] values;
- if (win32Str[^1] == '0')
+ if (win32Str.EndsWith('0'))
{
// Trailing 0 gets dropped. 1;0 -> 1
values = new int[win32Str.Length / 2];
// Our existing names mostly look like:
// "English" + "United States" -> "English (United States)"
// "Azeri (Latin)" + "Azerbaijan" -> "Azeri (Latin, Azerbaijan)"
- if (EnglishLanguageName[^1] == ')')
+ if (EnglishLanguageName.EndsWith(')'))
{
// "Azeri (Latin)" + "Azerbaijan" -> "Azeri (Latin, Azerbaijan)"
englishDisplayName = string.Concat(
m_dateWords.Add(str);
}
- if (str[^1] == '.')
+ if (str.EndsWith('.'))
{
// Old version ignore the trailing dot in the date words. Support this as well.
string strWithoutDot = str[0..^1];
throw new InvalidFilterCriteriaException(SR.InvalidFilterCriteriaException_CritString);
}
// Check to see if this is a prefix or exact match requirement
- if (str.Length > 0 && str[^1] == '*')
+ if (str.EndsWith('*'))
{
ReadOnlySpan<char> slice = str.AsSpan(0, str.Length - 1);
return cls.Name.AsSpan().StartsWith(slice, comparison);
public bool EndsWith(char value)
{
+ // If the string is empty, *(&_firstChar + length - 1) will deref within
+ // the _stringLength field, which will be all-zero. We must forbid '\0'
+ // from going down the optimized code path because otherwise empty strings
+ // would appear to end with '\0', which is incorrect.
+ // n.b. This optimization relies on the layout of string and is not valid
+ // for other data types like char[] or Span<char>.
+ if (RuntimeHelpers.IsKnownConstant(value) && value != '\0')
+ {
+ // deref Length now to front-load the null check; also take this time to zero-extend
+ // n.b. (localLength - 1) could be negative!
+ nuint localLength = (uint)Length;
+ return Unsafe.Add(ref _firstChar, (nint)localLength - 1) == value;
+ }
+
int lastPos = Length - 1;
return ((uint)lastPos < (uint)Length) && this[lastPos] == value;
}
public bool StartsWith(char value)
{
+ // If the string is empty, _firstChar will contain the null terminator.
+ // We forbid '\0' from going down the optimized code path because otherwise
+ // empty strings would appear to begin with '\0', which is incorrect.
+ // n.b. This optimization relies on the layout of string and is not valid
+ // for other data types like char[] or Span<char>.
if (RuntimeHelpers.IsKnownConstant(value) && value != '\0')
{
return _firstChar == value;
}
+
return Length != 0 && _firstChar == value;
}
{
text = string.Empty;
}
- else if (text.IndexOf("--", StringComparison.Ordinal) != -1 || (text.Length > 0 && text[text.Length - 1] == '-'))
+ else if (text.Contains("--") || text.StartsWith('-'))
{
throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.XmlInvalidCommentChars, nameof(text)));
}
{
fixed (char* fixedName = name)
{
- if (name[0] == '[' && name[name.Length - 1] == ']')
+ if (name.StartsWith('[') && name.EndsWith(']'))
{
// we require that _entire_ name is recognized as ipv6 address
if (IPv6AddressHelper.IsValid(fixedName, 1, ref end) && end == name.Length)
{
try
{
- if (null != text && (text.Contains("--") || (text.Length != 0 && text[text.Length - 1] == '-')))
+ if (null != text && (text.Contains("--") || text.StartsWith('-')))
{
throw new ArgumentException(SR.Xml_InvalidCommentChars);
}
{
throw new ArgumentException(SR.Format(SR.Xml_NamespaceDeclXmlXmlns, prefix));
}
- if (prefix.Length > 0 && prefix[0] == 'x')
+ if (prefix.StartsWith('x'))
{
if (prefix == "xml")
{
{
if (!doc.IsLoading)
{
- if (name.Length > 0 && name[0] == '#')
+ if (name.StartsWith('#'))
{
throw new ArgumentException(SR.Xdom_InvalidCharacter_EntityReference);
}
else
{
bool useReflection = typeDesc.UseReflection;
- if (member.Source[member.Source.Length - 1] == '(' || member.Source[member.Source.Length - 1] == '{')
+ if (member.Source.EndsWith('(') || member.Source.EndsWith('{'))
{
WriteCreateInstance(typeDescFullName, a, useReflection, typeDesc.CannotNew);
Writer.Write(member.Source);
Writer.Write(a);
- if (member.Source[member.Source.Length - 1] == '{')
+ if (member.Source.EndsWith('{'))
Writer.WriteLine("});");
else
Writer.WriteLine(");");
private void WriteSourceBegin(string source)
{
Writer.Write(source);
- if (source[source.Length - 1] != '(' && source[source.Length - 1] != '{')
+ if (!source.EndsWith('(') && !source.EndsWith('{'))
Writer.Write(" = ");
}
{
// source could be of the form "var", "arrayVar[i]",
// "collection.Add(" or "methodInfo.Invoke(collection, new object[] {"
- if (source[source.Length - 1] == '(')
+ if (source.EndsWith('('))
Writer.Write(")");
- else if (source[source.Length - 1] == '{')
+ else if (source.EndsWith('{'))
Writer.Write("})");
}
}
else
{
- if (member.Source[member.Source.Length - 1] == '(' || member.Source[member.Source.Length - 1] == '{')
+ if (member.Source.EndsWith('(') || member.Source.EndsWith('{'))
{
WriteCreateInstance(a, typeDesc.CannotNew, typeDesc.Type!);
WriteSourceBegin(member.Source);
{
int len, lenLocal, offset;
- if (s.Length != 0 && s[0] == '*')
+ if (s.StartsWith('*'))
{
// '*' as a NameTest
prefix = localName = null;
return token;
}
- if (token[0] == ' ' || token[token.Length - 1] == ' ' || token.IndexOfAny(crt) != -1 || token.IndexOf(" ", StringComparison.Ordinal) != -1)
+ if (token.StartsWith(' ') ||
+ token.EndsWith(' ') ||
+ token.IndexOfAny(crt) >= 0 ||
+ token.Contains(" "))
{
throw new XmlException(SR.Sch_NotTokenString, token);
}
internal static Exception? TryVerifyTOKEN(string token)
{
- if (token == null || token.Length == 0)
+ if (string.IsNullOrEmpty(token))
{
return null;
}
- if (token[0] == ' ' || token[token.Length - 1] == ' ' || token.IndexOfAny(crt) != -1 || token.IndexOf(" ", StringComparison.Ordinal) != -1)
+ if (token.StartsWith(' ') ||
+ token.EndsWith(' ') ||
+ token.IndexOfAny(crt) >= 0 ||
+ token.Contains(" "))
{
return new XmlException(SR.Sch_NotTokenString, token);
}
int count = baseUri.Length + resource.Length;
- if (baseUri[baseUri.Length - 1] == '/')
+ if (baseUri.EndsWith('/'))
{
return string.Create(
count,
HttpQSCollection result = new HttpQSCollection();
int queryLength = query.Length;
- int namePos = queryLength > 0 && query[0] == '?' ? 1 : 0;
+ int namePos = query.StartsWith('?') ? 1 : 0;
if (queryLength == namePos)
{
return result;
}
else
{
- if (output.Length > 0 && output[^1] == '\n')
+ if (output.EndsWith('\n'))
output = output[..^1];
}