unsafe static private ushort ParseSchemeCheckImplicitFile(char* uriString, ushort length,
ref ParsingError err, ref Flags flags, ref UriParser syntax)
{
ushort idx = 0;
//skip whitespace
while (idx < length && UriHelper.IsLWS(uriString[idx]))
{
++idx;
}
// sets the recognizer for well known registered schemes
// file, ftp, http, https, uuid, etc
// Note that we don't support one-letter schemes that will be put into a DOS path bucket
ushort end = idx;
while (end < length && uriString[end] != ':')
{
++end;
}
// NB: On 64-bits we will use less optimized code from CheckSchemeSyntax()
//
if (IntPtr.Size == 4)
{
// long = 4chars: The minimal size of a known scheme is 2 + ':'
if (end != length && end >= idx + 2 &&
CheckKnownSchemes((long*)(uriString + idx), (ushort)(end - idx), ref syntax))
{
return (ushort)(end + 1);
}
}
//NB: A string must have at least 3 characters and at least 1 before ':'
if (idx + 2 >= length || end == idx)
{
err = ParsingError.BadFormat;
return 0;
}
//Check for supported special cases like a DOS file path OR a UNC share path
//NB: A string may not have ':' if this is a UNC path
{
char c;
if ((c = uriString[idx + 1]) == ':' || c == '|')
{
//DOS-like path?
if (UriHelper.IsAsciiLetter(uriString[idx]))
{
if ((c = uriString[idx + 2]) == '\\' || c == '/')
{
flags |= (Flags.DosPath | Flags.ImplicitFile | Flags.AuthorityFound);
syntax = UriParser.FileUri;
return idx;
}
err = ParsingError.MustRootedPath;
return 0;
}
if (c == ':')
err = ParsingError.BadScheme;
else
err = ParsingError.BadFormat;
return 0;
}
else if ((c = uriString[idx]) == '/' || c == '\\')
{
//UNC share ?
if ((c = uriString[idx + 1]) == '\\' || c == '/')
{
flags |= (Flags.UncPath | Flags.ImplicitFile | Flags.AuthorityFound);
syntax = UriParser.FileUri;
idx += 2;
// V1.1 compat this will simply eat any slashes prepended to a UNC path
while (idx < length && ((c = uriString[idx]) == '/' || c == '\\'))
++idx;
return idx;
}
err = ParsingError.BadFormat;
return 0;
}
}
if (end == length)
{
err = ParsingError.BadFormat;
return 0;
}
// Here could be a possibly valid, and not well-known scheme
// Finds the scheme delimiter
// we don;t work with the schemes names > c_MaxUriSchemeName (should be ~1k)
if ((end - idx) > c_MaxUriSchemeName)
{
err = ParsingError.SchemeLimit;
return 0;
}
//Check the syntax, canonicalize and avoid a GC call
char* schemePtr = stackalloc char[end - idx];
for (length = 0; idx < end; ++idx)
{
schemePtr[length++] = uriString[idx];
}
err = CheckSchemeSyntax(schemePtr, length, ref syntax);
if (err != ParsingError.None)
{
return 0;
}
return (ushort)(end + 1);
}