private static void ParseArgumentsIntoList(string arguments, List<string> results)
{
var currentArgument = new StringBuilder();
bool inQuotes = false;
// Iterate through all of the characters in the argument string.
for (int i = 0; i < arguments.Length; i++)
{
// From the current position, iterate through contiguous backslashes.
int backslashCount = 0;
for (; i < arguments.Length && arguments[i] == '\\'; i++, backslashCount++) ;
if (backslashCount > 0)
{
if (i >= arguments.Length || arguments[i] != '"')
{
// Backslashes not followed by a double quote:
// they should all be treated as literal backslashes.
currentArgument.Append('\\', backslashCount);
i--;
}
else
{
// Backslashes followed by a double quote:
// - Output a literal slash for each complete pair of slashes
// - If one remains, use it to make the subsequent quote a literal.
currentArgument.Append('\\', backslashCount / 2);
if (backslashCount % 2 == 0)
{
i--;
}
else
{
currentArgument.Append('"');
}
}
continue;
}
char c = arguments[i];
// If this is a double quote, track whether we're inside of quotes or not.
// Anything within quotes will be treated as a single argument, even if
// it contains spaces.
if (c == '"')
{
inQuotes = !inQuotes;
continue;
}
// If this is a space/tab and we're not in quotes, we're done with the current
// argument, and if we've built up any characters in the current argument,
// it should be added to the results and then reset for the next one.
if ((c == ' ' || c == '\t') && !inQuotes)
{
if (currentArgument.Length > 0)
{
results.Add(currentArgument.ToString());
currentArgument.Clear();
}
continue;
}
// Nothing special; add the character to the current argument.
currentArgument.Append(c);
}
// If we reach the end of the string and we still have anything in our current
// argument buffer, treat it as an argument to be added to the results.
if (currentArgument.Length > 0)
{
results.Add(currentArgument.ToString());
}
}