private void ModifyUCDFile(TextReader tr, TextWriter tw,
List<IUcdCharacter> ucdCharacters, bool add)
{
if (ucdCharacters.Count == 0)
{
// There is no point in processing this file if we aren't going to do anything to it.
tw.Write(tr.ReadToEnd());
// Allows us to know that there will be at least on ucdCharacter that we can access to get some properties
return;
}
//contains our current line
// not null so that we get into the while loop
var line = "unused value";
//Bidi class value from the previous line
var lastProperty = "blank";
//Bidi class value from the current line
// the index of the IPuaCharacter the we are currently trying to insert
// Note, the initial value will never be used, because there will be no
// bidi class value called "blank" in the file, thus it will be initialized before it is every used
// but VS requires an initialization value "just in case"
int codeIndex = -1;
// If we have read in the line already we want to use this line for the loop, set this to be true.
bool dontRead = false;
//Count the number of characters in each range
int rangeCount = 0;
//While there is a line to be read in the file
while ((dontRead && line != null) || (line = tr.ReadLine()) != null)
{
dontRead = false;
if (HasBidiData(line))
{
// We found another valid codepoint, increment the count
IncrementCount(ref rangeCount, line);
var currentProperty = GetProperty(line);
// If this is a new section of bidi class values
if (!ucdCharacters[0].SameRegion(currentProperty, lastProperty))
{
lastProperty = currentProperty;
// Find one of the ucdCharacters in this range in the list of ucdCharacters to add.
var fFound = false;
for (codeIndex = 0; codeIndex < ucdCharacters.Count; codeIndex++)
{
var ch = ucdCharacters[codeIndex];
if (ch != null && ch.CompareTo(currentProperty) == 0)
{
fFound = true;
break;
}
}
// if we don't have any characters to put in this section
if (!fFound)
{
tw.WriteLine(line);
line = ReadToEndOfSection(tr, tw, lastProperty, rangeCount, ucdCharacters[0]);
rangeCount = 0;
dontRead = true;
continue;
}
}
#region insert_the_PUACharacter
//Grab codepoint
string code = line.Substring(0, line.IndexOf(';')).Trim();
//If it's a range of codepoints
if (code.IndexOf('.') != -1)
{
#region if_range
//Grabs the end codepoint
string endCode = code.Substring(code.IndexOf("..") + 2).Trim();
code = code.Substring(0, code.IndexOf("..")).Trim();
//A dynamic array that contains our range of codepoints and the properties to go with it
var codepointsWithinRange = new List<IUcdCharacter>();
// If the IPuaCharacter we want to insert is before the range
while (
//If this is the last one stop looking for more
StillInRange(codeIndex, ucdCharacters, currentProperty) &&
// For every character before the given value
(ucdCharacters[codeIndex]).CompareCodePoint(code) < 0
)
{
//Insert characters before the code
AddUCDLine(tw, ucdCharacters[codeIndex], add);
codeIndex++;
}
while (
//If this is the last one stop looking for more
StillInRange(codeIndex, ucdCharacters, currentProperty) &&
// While our xmlCodepoint satisfies: code <= xmlCodepoint <= endCode
(ucdCharacters[codeIndex]).CompareCodePoint(endCode) < 1
)
{
//Adds the puaCharacter to the list of codepoints that are in range
codepointsWithinRange.Add(ucdCharacters[codeIndex]);
codeIndex++;
}
//If we found any codepoints in the range to insert
if (codepointsWithinRange.Count > 0)
{
#region parse_comments
//Do lots of smart stuff to insert the PUA characters into the block
string generalCategory = "";
//Contains the beginning and ending range names
string firstName = "";
string lastName = "";
//If a comment exists on the line in the proper format
// e.g. --- # --- [ --- ] --- ... ---
if (line.IndexOf('#') != -1 && line.IndexOf('[') != -1
&& (line.IndexOf('#') <= line.IndexOf('[')))
{
//Grabs the general category
generalCategory = line.Substring(line.IndexOf('#') + 1, line.IndexOf('[') - line.IndexOf('#') - 1).Trim();
}
//find the index of the second ".." in the line
int indexDotDot = line.Substring(line.IndexOf(']')).IndexOf("..");
if (indexDotDot != -1)
indexDotDot += line.IndexOf(']');
//int cat = line.IndexOf(']') ;
if (line.IndexOf('#') != -1 && line.IndexOf('[') != -1 && line.IndexOf(']') != -1 && indexDotDot != -1
&& (line.IndexOf('#') < line.IndexOf('['))
&& (line.IndexOf('[') < line.IndexOf(']'))
&& (line.IndexOf(']') < indexDotDot)
)
{
//Grab the name of the first character in the range
firstName = line.Substring(line.IndexOf(']') + 1, indexDotDot - line.IndexOf(']') - 1).Trim();
//Grab the name of the last character in the range
lastName = line.Substring(indexDotDot + 2).Trim();
}
#endregion
WriteBidiCodepointBlock(tw, code, endCode, codepointsWithinRange,
generalCategory, firstName, lastName, add);
}
else
{
tw.WriteLine(line);
}
#endregion
}
//if the codepoint in the file is equal to the codepoint that we want to insert
else
{
if (MiscUtils.CompareHex(code, ucdCharacters[codeIndex].CodePoint) > 0)
{
// Insert the new PuaDefinition before the line (as well as any others that might be)
while (
//If this is the last one stop looking for more
StillInRange(codeIndex, ucdCharacters, currentProperty) &&
// For every character before the given value
ucdCharacters[codeIndex].CompareCodePoint(code) < 0
)
{
//Insert characters before the code
AddUCDLine(tw, ucdCharacters[codeIndex], add);
codeIndex++;
}
}
//if the codepoint in the file is equal to the codepoint that we want to insert
if (StillInRange(codeIndex, ucdCharacters, currentProperty) &&
(code == ucdCharacters[codeIndex].CodePoint))
{
// Replace the line with the new PuaDefinition
AddUCDLine(tw, ucdCharacters[codeIndex], add);
// Look for the next PUA codepoint that we wish to insert
codeIndex++;
}
//if it's not a first tag and the codepoints don't match
else
{
tw.WriteLine(line);
}
}
//If we have no more codepoints to insert in this section, then just finish writing this section
if (!StillInRange(codeIndex, ucdCharacters, currentProperty))
{
line = ReadToEndOfSection(tr, tw, lastProperty, rangeCount, ucdCharacters[0]);
rangeCount = 0;
dontRead = true;
continue;
}
#endregion
}
//If it's a comment, simply write it out
else
{
// find the total count comment and replace it with the current count.
if (line.ToLowerInvariant().IndexOf("total code points") != -1)
{
line = "# Total code points:" + rangeCount;
rangeCount = 0;
}
tw.WriteLine(line);
}
}
}