190597d317
Improved enumerations by including a special ValueName attribute on the fields.
134 lines
3.7 KiB
C#
134 lines
3.7 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace UnicodeInformation
|
|
{
|
|
public class UnicodeDataBuilder
|
|
{
|
|
private readonly Version unicodeVersion;
|
|
private UnicodeCharacterDataBuilder[] characterDataBuilders = new UnicodeCharacterDataBuilder[10000];
|
|
private int characterCount;
|
|
|
|
public UnicodeDataBuilder(Version unicodeVersion)
|
|
{
|
|
this.unicodeVersion = unicodeVersion;
|
|
}
|
|
|
|
private int FindCodePoint(int codePoint)
|
|
{
|
|
if (characterCount == 0) return -1;
|
|
|
|
int minIndex = 0;
|
|
int maxIndex = characterCount - 1;
|
|
|
|
do
|
|
{
|
|
int index = (minIndex + maxIndex) >> 1;
|
|
|
|
int Δ = characterDataBuilders[index].CodePointRange.CompareCodePoint(codePoint);
|
|
|
|
if (Δ == 0) return index;
|
|
else if (Δ < 0) maxIndex = index - 1;
|
|
else minIndex = index + 1;
|
|
} while (minIndex <= maxIndex);
|
|
|
|
return -1;
|
|
}
|
|
|
|
private int FindInsertionPoint(int startCodePoint, int endCodePoint)
|
|
{
|
|
int minIndex;
|
|
int maxIndex;
|
|
|
|
if (characterCount == 0 || characterDataBuilders[maxIndex = characterCount - 1].CodePointRange.LastCodePoint < startCodePoint) return characterCount;
|
|
else if (endCodePoint < characterDataBuilders[minIndex = 0].CodePointRange.FirstCodePoint) return 0;
|
|
else if (characterCount == 1) return -1;
|
|
|
|
do
|
|
{
|
|
int index = (minIndex + maxIndex) >> 1;
|
|
|
|
int Δ = characterDataBuilders[index].CodePointRange.CompareCodePoint(startCodePoint);
|
|
|
|
if (Δ == 0) return -1;
|
|
else if (Δ < 0) maxIndex = index;
|
|
else minIndex = index;
|
|
} while (maxIndex - minIndex > 1);
|
|
|
|
if (characterDataBuilders[maxIndex].CodePointRange.FirstCodePoint < endCodePoint) return -1;
|
|
else return maxIndex;
|
|
}
|
|
|
|
public void Insert(UnicodeCharacterDataBuilder data)
|
|
{
|
|
int insertionPoint = FindInsertionPoint(data.CodePointRange.FirstCodePoint, data.CodePointRange.LastCodePoint);
|
|
|
|
if (insertionPoint < 0) throw new InvalidOperationException("The specified range overlaps with pre-existing ranges.");
|
|
|
|
if (insertionPoint >= characterDataBuilders.Length)
|
|
{
|
|
Array.Resize(ref characterDataBuilders, characterDataBuilders.Length << 1);
|
|
}
|
|
|
|
if (insertionPoint < characterCount)
|
|
{
|
|
Array.Copy(characterDataBuilders, insertionPoint, characterDataBuilders, insertionPoint + 1, characterCount - insertionPoint);
|
|
}
|
|
|
|
characterDataBuilders[insertionPoint] = data;
|
|
++characterCount;
|
|
}
|
|
|
|
public UnicodeCharacterDataBuilder Get(int codePoint)
|
|
{
|
|
int index = FindCodePoint(codePoint);
|
|
|
|
return index >= 0 ? characterDataBuilders[index] : null;
|
|
}
|
|
|
|
public void SetProperties(ContributoryProperties property, UnicodeCharacterRange codePointRange)
|
|
{
|
|
int firstIndex = FindCodePoint(codePointRange.FirstCodePoint);
|
|
int lastIndex = FindCodePoint(codePointRange.LastCodePoint);
|
|
|
|
if (firstIndex < 0 && lastIndex < 0)
|
|
{
|
|
Insert(new UnicodeCharacterDataBuilder(codePointRange) { ContributoryProperties = property });
|
|
return;
|
|
}
|
|
|
|
if (firstIndex < 0
|
|
|| lastIndex < 0
|
|
|| characterDataBuilders[firstIndex].CodePointRange.FirstCodePoint < codePointRange.FirstCodePoint
|
|
|| characterDataBuilders[lastIndex].CodePointRange.LastCodePoint > codePointRange.LastCodePoint)
|
|
{
|
|
throw new InvalidOperationException();
|
|
}
|
|
|
|
int i = firstIndex;
|
|
|
|
while (true)
|
|
{
|
|
characterDataBuilders[i].ContributoryProperties |= property;
|
|
|
|
if (i == lastIndex) break;
|
|
|
|
++i;
|
|
}
|
|
}
|
|
|
|
public UnicodeData ToUnicodeData()
|
|
{
|
|
var finalData = new UnicodeCharacterData[characterCount];
|
|
|
|
for (int i = 0; i < finalData.Length; ++i)
|
|
finalData[i] = characterDataBuilders[i].ToCharacterData();
|
|
|
|
return new UnicodeData(unicodeVersion, finalData);
|
|
}
|
|
}
|
|
}
|