private static void GenerateUppercaseMappings(StreamWriter writer) { // NOTE: In order to keep the generated code shorter, we leave out some line breaks in the case statements. This is intentional. string newLine = writer.NewLine; CultureInfo invariantCulture = CultureInfo.InvariantCulture; Console.Write("Generating uppercase mappings switch..."); StringBuilder builder = new StringBuilder(200000); #region Preparation List <SingleCharCaseMapping> singleCharMappings = new List <SingleCharCaseMapping>(100000); List <StringCaseMapping> stringMappings = new List <StringCaseMapping>(10000); foreach (CodePoint codePoint in CodePoint.CodePoints) { if (codePoint.Value > 0xFFFF) { break; } CodePoint[] uppercaseMapping = CodePoint.GetUppercaseMapping(codePoint); if (uppercaseMapping != null) { if (uppercaseMapping.Length == 1) { singleCharMappings.Add(new SingleCharCaseMapping(codePoint.Value, uppercaseMapping[0].Value)); } else { System.Diagnostics.Debug.Assert(uppercaseMapping.Length > 1); stringMappings.Add(new StringCaseMapping(codePoint.Value, uppercaseMapping)); } } } // Add the special cases for the second halves of surrogate pairs that map to the second halves of other surrogate pairs for (uint x = 0xDC28; x <= 0xDC4F; x++) { singleCharMappings.Add(new SingleCharCaseMapping(x, x - 0x28)); } #endregion // Preparation #region singleCharMappings // Sort the single char mappings by the difference first, then by the source code point value singleCharMappings.Sort(delegate(SingleCharCaseMapping x, SingleCharCaseMapping y) { int diff = x.Difference.CompareTo(y.Difference); return((diff != 0) ? diff : x.CodePointValue.CompareTo(y.CodePointValue)); }); const int CASES_PER_LINE = 8; int singleCharMappingsCount = singleCharMappings.Count; int singleCharMappingsCountMinusOne = singleCharMappingsCount - 1; for (int i = 0, casesOnLine = 0; i < singleCharMappingsCount; i++) { SingleCharCaseMapping singleCharMapping = singleCharMappings[i]; uint difference = singleCharMapping.Difference; bool isNewLine = (casesOnLine == 0); bool writeCaseBody = (i == singleCharMappingsCountMinusOne || difference != singleCharMappings[i + 1].Difference); bool isLastCaseOnLine = (writeCaseBody || casesOnLine == CASES_PER_LINE - 1); // When we only have a single case, we handle it separately if (writeCaseBody && (i == 0 || difference != singleCharMappings[i - 1].Difference)) { stringMappings.Add(new StringCaseMapping(singleCharMapping)); continue; } builder.AppendFormat(invariantCulture, "{0}case 0x{1:X4}:{2}", isNewLine ? "\t" : " ", singleCharMapping.CodePointValue, isLastCaseOnLine ? newLine : null); if (writeCaseBody) { if ((difference & 0x80000000) == 0) { if (difference == 0x28) { builder.AppendFormat(invariantCulture, "\t\t// The entries for code points 0xDC28 through 0xDC4F (inclusive) are a special case since they are{0}" + "\t\t// each the second half of a surrogate pair that maps to the second half of another surrogate pair.{0}" + "\t\t// Whether mapping these code points like this is actually correct or not is still to be determined...{0}", newLine); } builder.AppendFormat(invariantCulture, "\t\tx -= 0x{0:X4}; break;{1}", difference, newLine); } else { builder.AppendFormat(invariantCulture, "\t\tx += 0x{0:X4}; break;{1}", singleCharMapping.UppercaseMappingValue - singleCharMapping.CodePointValue, newLine); } } casesOnLine = isLastCaseOnLine ? 0 : casesOnLine + 1; } #endregion // singleCharMappings #region stringMappings // Sort the string mappings by the number of code point values in the upper case mapping, then by the source code point value stringMappings.Sort(delegate(StringCaseMapping x, StringCaseMapping y) { int diff = (x.UppercaseMappingValues != null ? x.UppercaseMappingValues.Length : 0).CompareTo( y.UppercaseMappingValues != null ? y.UppercaseMappingValues.Length : 0); return((diff != 0) ? diff : x.CodePointValue.CompareTo(y.CodePointValue)); }); int stringMappingsCount = stringMappings.Count; for (int i = 0; i < stringMappingsCount; i++) { StringCaseMapping stringMapping = stringMappings[i]; builder.AppendFormat(invariantCulture, "\tcase 0x{0:X4}: return \"", stringMapping.CodePointValue); if (stringMapping.UppercaseMappingValues != null) { for (int j = 0; j < stringMapping.UppercaseMappingValues.Length; j++) { builder.AppendFormat(invariantCulture, @"\u{0:X4}", stringMapping.UppercaseMappingValues[j]); } } else { builder.AppendFormat(invariantCulture, @"\u{0:X4}", stringMapping.UppercaseMappingValue); } builder.Append("\";"); builder.Append(newLine); } #endregion // stringMappings writer.Write(builder.ToString()); Console.WriteLine(" Done!"); }