in src/Microsoft.NuGet.Build.Tasks/Preprocessor.cs [19:98]
public static void Preprocess(TextReader reader, TextWriter writer, IReadOnlyDictionary<string, string> values)
{
// $$ is the escape for a $, which we can just replicate in the algorithm by giving the empty replacement the known value
var maximumKeyLength = values.Keys.Max<string, int?>(k => k.Length).GetValueOrDefault(0);
char[] buffer = new char[Math.Max(4096, maximumKeyLength + 2)];
int charsInBuffer = reader.ReadBlock(buffer, 0, buffer.Length);
while (charsInBuffer != 0)
{
int indexOfDelimiter = Array.IndexOf(buffer, PreprocessorDelimiter, 0, charsInBuffer);
if (indexOfDelimiter == -1)
{
// If the buffer doesn't contain any delimiters, then we can immediately write it out and move on
writer.Write(buffer, 0, charsInBuffer);
charsInBuffer = reader.ReadBlock(buffer, 0, buffer.Length);
}
else
{
// Write whatever is before the $ and advance up to the $
writer.Write(buffer, 0, indexOfDelimiter);
Advance(reader, buffer, ref charsInBuffer, charsToAdvance: indexOfDelimiter);
// Let's read in the token name
var token = new StringBuilder();
int position = 1;
while (true)
{
if (position == buffer.Length)
{
Advance(reader, buffer, ref charsInBuffer, buffer.Length);
position = 0;
}
// If at end, we'll want to fall through to the last case
var c = position < charsInBuffer ? buffer[position] : '\0';
if (c == PreprocessorDelimiter)
{
position++;
// Is it the escape case?
string value;
if (token.Length == 0)
{
writer.Write(PreprocessorDelimiter);
}
else if (values.TryGetValue(token.ToString(), out value))
{
writer.Write(value);
}
else
{
throw new ExceptionFromResource(nameof(Strings.UnspecifiedToken), PreprocessorDelimiter + token.ToString() + PreprocessorDelimiter);
}
break;
}
else if (IsTokenCharacter(c))
{
token.Append(c);
position++;
}
else
{
// The token ended prematurely, so we just treat it verbatim and write it out
writer.Write(PreprocessorDelimiter);
writer.Write(token);
break;
}
}
// Advance to the next position to start all over
Advance(reader, buffer, ref charsInBuffer, position);
}
}
}