in src/Tasks/GenerateResource.cs [3343:3511]
private void ReadTextResources(ReaderInfo reader, String fileName)
{
// Check for byte order marks in the beginning of the input file, but
// default to UTF-8.
using (LineNumberStreamReader sr = new LineNumberStreamReader(fileName, new UTF8Encoding(true), true))
{
StringBuilder name = new StringBuilder(255);
StringBuilder value = new StringBuilder(2048);
int ch = sr.Read();
while (ch != -1)
{
if (ch == '\n' || ch == '\r')
{
ch = sr.Read();
continue;
}
// Skip over commented lines or ones starting with whitespace.
// Support LocStudio INF format's comment char, ';'
if (ch == '#' || ch == '\t' || ch == ' ' || ch == ';')
{
// comment char (or blank line) - skip line.
sr.ReadLine();
ch = sr.Read();
continue;
}
// Note that in Beta of version 1 we recommended users should put a [strings]
// section in their file. Now it's completely unnecessary and can
// only cause bugs. We will not parse anything using '[' stuff now
// and we should give a warning about seeing [strings] stuff.
// In V1.1 or V2, we can rip this out completely, I hope.
if (ch == '[')
{
String skip = sr.ReadLine();
if (skip.Equals("strings]"))
_logger.LogWarningWithCodeFromResources(null, fileName, sr.LineNumber - 1, 1, 0, 0, "GenerateResource.ObsoleteStringsTag");
else
{
throw new TextFileException(_logger.FormatResourceString("GenerateResource.UnexpectedInfBracket", "[" + skip), fileName, sr.LineNumber - 1, 1);
}
ch = sr.Read();
continue;
}
// Read in name
name.Length = 0;
while (ch != '=')
{
if (ch == '\r' || ch == '\n')
throw new TextFileException(_logger.FormatResourceString("GenerateResource.NoEqualsInLine", name), fileName, sr.LineNumber, sr.LinePosition);
name.Append((char)ch);
ch = sr.Read();
if (ch == -1)
break;
}
if (name.Length == 0)
throw new TextFileException(_logger.FormatResourceString("GenerateResource.NoNameInLine"), fileName, sr.LineNumber, sr.LinePosition);
// For the INF file, we must allow a space on both sides of the equals
// sign. Deal with it.
if (name[name.Length - 1] == ' ')
{
name.Length = name.Length - 1;
}
ch = sr.Read(); // move past =
// If it exists, move past the first space after the equals sign.
if (ch == ' ')
ch = sr.Read();
// Read in value
value.Length = 0;
while (ch != -1)
{
// Did we read @"\r" or @"\n"?
bool quotedNewLine = false;
if (ch == '\\')
{
ch = sr.Read();
switch (ch)
{
case '\\':
// nothing needed
break;
case 'n':
ch = '\n';
quotedNewLine = true;
break;
case 'r':
ch = '\r';
quotedNewLine = true;
break;
case 't':
ch = '\t';
break;
case '"':
ch = '\"';
break;
case 'u':
char[] hex = new char[4];
int numChars = 4;
int index = 0;
while (numChars > 0)
{
int n = sr.Read(hex, index, numChars);
if (n == 0)
throw new TextFileException(_logger.FormatResourceString("GenerateResource.InvalidEscape", name.ToString(), (char)ch), fileName, sr.LineNumber, sr.LinePosition);
index += n;
numChars -= n;
}
try
{
ch = (char)UInt16.Parse(new String(hex), NumberStyles.HexNumber, CultureInfo.CurrentCulture);
}
catch (FormatException)
{
// We know about this one...
throw new TextFileException(_logger.FormatResourceString("GenerateResource.InvalidHexEscapeValue", name.ToString(), new String(hex)), fileName, sr.LineNumber, sr.LinePosition);
}
catch (OverflowException)
{
// We know about this one, too...
throw new TextFileException(_logger.FormatResourceString("GenerateResource.InvalidHexEscapeValue", name.ToString(), new String(hex)), fileName, sr.LineNumber, sr.LinePosition);
}
quotedNewLine = (ch == '\n' || ch == '\r');
break;
default:
throw new TextFileException(_logger.FormatResourceString("GenerateResource.InvalidEscape", name.ToString(), (char)ch), fileName, sr.LineNumber, sr.LinePosition);
}
}
// Consume endline...
// Endline can be \r\n or \n. But do not treat a
// quoted newline (ie, @"\r" or @"\n" in text) as a
// real new line. They aren't the end of a line.
if (!quotedNewLine)
{
if (ch == '\r')
{
ch = sr.Read();
if (ch == -1)
{
break;
}
else if (ch == '\n')
{
ch = sr.Read();
break;
}
}
else if (ch == '\n')
{
ch = sr.Read();
break;
}
}
value.Append((char)ch);
ch = sr.Read();
}
// Note that value can be an empty string
AddResource(reader, name.ToString(), value.ToString(), fileName, sr.LineNumber, sr.LinePosition);
}
}
}