singrdk/base/Applications/Runtime/Full/System/Globalization/CompareInfo.cs

2154 lines
123 KiB
C#
Raw Permalink Normal View History

2008-03-05 09:52:00 -05:00
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
////////////////////////////////////////////////////////////////////////////
//
// Class: CompareInfo
//
// Purpose: This class implements a set of methods for comparing
// strings.
//
////////////////////////////////////////////////////////////////////////////
2008-11-17 18:29:00 -05:00
namespace System.Globalization
{
2008-03-05 09:52:00 -05:00
//
// NOTE NOTE NOTE
//
// We're dependent on the SortingTable getting created when an instance of the
// class is initialized (through a call to InitializeCompareInfo). When in
// native, we assume that the table has already been allocated. If we decide
// to delay-allocate any of the tables (as we may do for US English), we should
// modify SortingTable::Get.
//
using System;
using System.Collections;
using System.Reflection;
using System.Runtime.CompilerServices;
//| <include path='docs/doc[@for="CompareOptions"]/*' />
[Flags]
public enum CompareOptions
{
//| <include path='docs/doc[@for="CompareOptions.None"]/*' />
None = 0x00000000,
//| <include path='docs/doc[@for="CompareOptions.IgnoreCase"]/*' />
IgnoreCase = 0x00000001,
//| <include path='docs/doc[@for="CompareOptions.Ordinal"]/*' />
Ordinal = 0x40000000, // This flag can not be used with other flags.
}
//| <include path='docs/doc[@for="CompareInfo"]/*' />
public class CompareInfo
{
private const int ValidMaskOffFlags =
~((int)CompareOptions.IgnoreCase);
// from ClassLibNative\NLS\SortingTable.h
// original name is all caps and without the "ScriptMember_"
private const int ScriptMember_Unsortable = 0;
private const int ScriptMember_Punctuation = 6;
private const int ScriptMember_Symbol_1 = 7;
private const int ScriptMember_Symbol_2 = 8;
private const int ScriptMember_Symbol_4 = 10;
private const int ScriptMember_Symbol_5 = 11;
private const int ScriptMember_Digit = 12;
private const int ScriptMember_Latin = 14;
// from VC7\PlatformSDK\winnls.h
private const int CSTR_LESS_THAN = 1; // string1 < string2
private const int CSTR_EQUAL = 2; // string1 = string2
private const int CSTR_GREATER_THAN = 3; // string1 > string2
// from ClassLibNative\NLS\SortingTable.h
private const byte CMP_MASKOFF_NONE = 0xff;
private const byte CMP_MASKOFF_CW = 0xe7;
private const int STATE_DW = 1; // normal diacritic weight state
private const int STATE_CW = 4; // case weight state
////////////////////////////////////////////////////////////////////////
//
// Compare
//
// Compares the two strings with the given options. Returns 0 if the
// two strings are equal, a number less than 0 if string1 is less
// than string2, and a number greater than 0 if string1 is greater
// than string2.
//
////////////////////////////////////////////////////////////////////////
public static int Compare(String string1, String string2)
{
return (Compare(string1, string2, CompareOptions.None));
}
// INT32 __stdcall
// COMNlsInfo::Compare(CompareInfo_CompareStringArgs* pargs)
// dwFlags --> options
public static int Compare(String string1,
String string2,
CompareOptions options) {
//Our paradigm is that null sorts less than any other string and
//that two nulls sort as equal.
if (string1 == null) {
if (string2 == null) {
return (0); // Equal
}
return (-1); // null < non-null
}
if (string2 == null) {
return (1); // non-null > null
}
//
// Check the parameters.
//
if (options < 0) {
throw new ArgumentOutOfRangeException("flags", "ArgumentOutOfRange_MustBePositive");
}
//
// Check if we can use the highly optimized comparisons
//
if ((options & CompareOptions.Ordinal) != 0) {
if (options == CompareOptions.Ordinal) {
// Ordinal means the code-point comparison. This option can
// not be used with other options.
// Compare the two strings to the length of the shorter
// string. If they're not equal lengths, and the heads are
// equal, then the longer string is greater.
return CompareOrdinal(string1, 0, string1.Length,
string2, 0, string2.Length);
2008-11-17 18:29:00 -05:00
}
else {
2008-03-05 09:52:00 -05:00
throw new ArgumentException("options", "Argument_CompareOptionOrdinal");
}
}
// The return value of NativeCompareInfo::CompareString() is
// Native-style value (1=less, 2=equal, 3=larger). So subtract by
// two to get the NLS+ value. Will change NativeCompareInfo to
// return the correct value later s.t. we don't have to subtract 2.
// NativeCompareInfo::CompareString() won't take -1 as the end of
// string anymore. Therefore, pass the correct string length. The
// change is for adding the null-embedded string support in
// CompareString().
2008-11-17 18:29:00 -05:00
// REVIEW: CLR has C# pass in a C++ object pointer that
2008-03-05 09:52:00 -05:00
// it finds this CompareString() method in. Do we need to do this,
// or do we have enough state in the CompareInfo object?
return CompareString(options,
string1, 0, string1.Length,
string2, 0, string2.Length) - 2;
}
public static int Compare(String string1, int offset1, int length1,
String string2, int offset2, int length2) {
return CompareRegion(string1, offset1, length1,
string2, offset2, length2,
CompareOptions.None);
}
public static int Compare(String string1, int offset1,
String string2, int offset2,
CompareOptions options) {
return CompareRegion(string1, offset1, -1, string2, offset2, -1,
options);
}
public static int Compare(String string1, int offset1,
String string2, int offset2) {
return CompareRegion(string1, offset1, -1, string2, offset2, -1,
CompareOptions.None);
}
public static int Compare(String string1, int offset1, int length1,
String string2, int offset2, int length2,
CompareOptions options) {
if (length1 < 0 || length2 < 0) {
throw new ArgumentOutOfRangeException
((length1 < 0) ? "length1" : "length2",
"Need positive length");
}
return CompareRegion(string1, offset1, length1,
string2, offset2, length2,
options);
}
private static int CompareRegion(String string1, int offset1, int length1,
String string2, int offset2, int length2,
CompareOptions options) {
//
// Check for the null case.
//
if (string1 == null) {
if (offset1 != 0 || (length1 != 0 && length1 != -1)) {
throw new ArgumentOutOfRangeException
("string1", "ArgumentOutOfRange_OffsetLength");
}
if (string2 == null) {
if (offset2 != 0 || (length2 != 0 && length2 != -1)) {
throw new ArgumentOutOfRangeException
("string2", "ArgumentOutOfRange_OffsetLength");
}
return (0);
}
return (-1);
}
if (string2 == null) {
if (offset2 != 0 || (length2 != 0 && length2 != -1)) {
throw new ArgumentOutOfRangeException
("string2", "ArgumentOutOfRange_OffsetLength");
}
return (1);
}
//
// Get the full length of the two strings.
//
int realLen1 = string1.Length;
int realLen2 = string2.Length;
//check the arguments.
// Criteria:
// OffsetX >= 0
// LengthX >= 0 || LengthX == -1 (that is, LengthX >= -1)
// If LengthX >= 0, OffsetX + LengthX <= realLenX
2008-11-17 18:29:00 -05:00
if (offset1 < 0) {
2008-03-05 09:52:00 -05:00
throw new ArgumentOutOfRangeException
("offset1", "ArgumentOutOfRange_Index");
}
2008-11-17 18:29:00 -05:00
if (offset2 < 0) {
2008-03-05 09:52:00 -05:00
throw new ArgumentOutOfRangeException
("offset2", "ArgumentOutOfRange_Index");
}
2008-11-17 18:29:00 -05:00
if (length1 >= 0 && length1 > realLen1 - offset1) {
2008-03-05 09:52:00 -05:00
throw new ArgumentOutOfRangeException
("string1", "ArgumentOutOfRange_OffsetLength");
}
2008-11-17 18:29:00 -05:00
if (length2 >= 0 && length2 > realLen2 - offset2) {
2008-03-05 09:52:00 -05:00
throw new ArgumentOutOfRangeException
("string2", "ArgumentOutOfRange_OffsetLength");
}
// NativeCompareInfo::CompareString() won't take -1 as the end of
// string anymore. Therefore, pass the correct string length. The
// change is for adding the null-embedded string support in
// CompareString(). Therefore, if the length is -1, we have to get
// the correct string length here.
if (length1 == -1) {
length1 = realLen1 - offset1;
}
if (length2 == -1) {
length2 = realLen2 - offset2;
}
if (length1 < 0) {
throw new ArgumentOutOfRangeException
("length1", "ArgumentOutOfRange_NegativeLength");
}
if (length2 < 0) {
throw new ArgumentOutOfRangeException
("length2", "ArgumentOutOfRange_NegativeLength");
}
if (options == CompareOptions.Ordinal) {
return CompareOrdinal(string1, offset1, length1,
string2, offset2, length2);
}
return CompareString(options,
string1, offset1, length1,
string2, offset2, length2) - 2;
}
// INT32 COMNlsInfo::CompareOrdinal(WCHAR* string1, int Length1,
// WCHAR* string2, int Length2 )
private static int CompareOrdinal(String string1,int index1,int Length1,
String string2,int index2,int Length2){
//
// NOTENOTE The code here should be in sync with
// COMString::FCCompareOrdinal
//
int strIndex1=index1;
int strIndex2=index2;
// If the strings are the same length, compare exactly
// the right # of chars. If they are different,
// compare the shortest # + 1 (the '\0').
int count = Length1;
if (count > Length2)
count = Length2;
2008-11-17 18:29:00 -05:00
// simplified and removed optimizations
2008-03-05 09:52:00 -05:00
while (--count >= 0) {
2008-11-17 18:29:00 -05:00
if (string1[strIndex1] != string2[strIndex2]) {
2008-03-05 09:52:00 -05:00
return string1[strIndex1] - string2[strIndex2];
}
++strIndex1;
++strIndex2;
}
return Length1 - Length2;
}
2008-11-17 18:29:00 -05:00
//============================CompareString==========================
//Action: Compare two string in a linguistic way.
//Returns:
//Arguments:
//Exceptions:
//=======================================================================
2008-03-05 09:52:00 -05:00
private static int CompareString(CompareOptions dwCmpFlags,
String lpString1,
int lpStringIndex1,
int cchCount1,
String lpString2,
int lpStringIndex2,
int cchCount2) {
// Make sure that we call InitSortingData() after ctor.
String pString1;
int pStringIndex1;
String pString2;
int pStringIndex2;
bool fIgnorePunct; // flag to ignore punctuation (not symbol)
int State; // state table
byte Mask; // mask for weights
int WhichDiacritic = 0; // DW => 1 = str1 smaller, 3 = str2 smaller
int WhichCase = 0; // CW => 1 = str1 smaller, 3 = str2 smaller
int WhichPunct1 = 0; // SW => 1 = str1 smaller, 3 = str2 smaller
int WhichPunct2 = 0; // SW => 1 = str1 smaller, 3 = str2 smaller
//cchCount1 is also used a counter to track the
//characters that we are tracing right now.
//cchCount2 is also used a counter to track the
//characters that we are tracing right now.
// Call longer compare string if any of the following is true:
// - locale is invalid
// - either count is not -1
// - dwCmpFlags is not 0 or ignore case (see NOTE below)
// - locale is Korean - script member weight adjustment needed
//
// NOTE: If the value of COMPARE_OPTIONS_IGNORECASE
// ever changes, this code should check for:
// ( (dwCmpFlags != 0) && (dwCmpFlags !=
// COMPARE_OPTIONS_IGNORECASE) )
// Since COMPARE_OPTIONS_IGNORECASE is equal
// to 1, we can optimize this by checking for > 1.
//
// From now on, in this function, we don't rely on
// scanning null string as the end of the string.
// Instead, we use cchCount1/cchCount2 to track the
// end of the string. Therefore, cchCount1/cchCount2
// can not be -1 anymore. we make sure in here about
// the assumption.
//_ASSERTE(cchCount1 >= 0 && cchCount2 >= 0);
if (dwCmpFlags != CompareOptions.None &&
dwCmpFlags != CompareOptions.IgnoreCase) {
throw new Exception("CompareInfo.LongCompareStringW not implemented in Bartok!");
}
// Initialize string pointers.
pString1 = lpString1; // (LPWSTR)lpString1;
pStringIndex1 = lpStringIndex1;
pString2 = lpString2; // (LPWSTR)lpString2;
pStringIndex2 = lpStringIndex2;
// Invalid Parameter Check:
// - null string pointers
//
// We have already validate pString1 and pString2 in
// COMNlsInfo::CompareString().
//
// _ASSERTE(pString1 != null && pString2 != null);
// Do a wchar by wchar compare.
2008-11-17 18:29:00 -05:00
// collapsed 8 times unrolled loop
while ((cchCount1 != 0 && cchCount2 != 0) &&
2008-03-05 09:52:00 -05:00
(pString1[pStringIndex1] == pString2[pStringIndex2])) {
pStringIndex1++; pStringIndex2++;
cchCount1--; cchCount2--;
}
// If strings are both at null terminators, return equal.
if ((cchCount1 == 0) && (cchCount2 == 0)) {
return (CSTR_EQUAL);
}
if (cchCount1 == 0 || cchCount2 == 0) {
goto ScanLongerString;
}
// Initialize flags, pointers, and counters.
fIgnorePunct = false;
// Switch on the different flag options. This will speed up
// the comparisons of two strings that are different.
//
// The only two possibilities in this optimized section are
// no flags and the ignore case flag.
if (dwCmpFlags == CompareOptions.None) {
Mask = CMP_MASKOFF_NONE;
2008-11-17 18:29:00 -05:00
}
else {
2008-03-05 09:52:00 -05:00
Mask = CMP_MASKOFF_CW;
}
State = STATE_DW | STATE_CW;
// Compare each character's sortkey weight in the two strings.
while ((cchCount1 != 0) && (cchCount2 != 0)) {
byte dw1 = GetDiacritic(pString1[pStringIndex1]);
byte dw2 = GetDiacritic(pString2[pStringIndex2]);
byte cw1 = (byte)(GetCase(pString1[pStringIndex1]) & Mask);
byte cw2 = (byte)(GetCase(pString2[pStringIndex2]) & Mask);
ushort uw1 = GetUnicode(pString1[pStringIndex1]);
ushort uw2 = GetUnicode(pString2[pStringIndex2]);
if (uw1 != uw2 || dw1 != dw2 || cw1 != cw2) {
byte sm1 = GET_SCRIPT_MEMBER(uw1); // script member 1
byte sm2 = GET_SCRIPT_MEMBER(uw2); // script member 2
bool fContinue; // flag to continue loop
// If Unicode Weights are different and no special cases,
// then we're done. Otherwise, we need to do extra checking.
//
// Must check ENTIRE string for any possibility of Unicode
// Weight differences. As soon as a Unicode Weight
// difference is found, then we're done. If no UW
// difference is found, then the first Diacritic Weight
// difference is used. If no DW difference is found, then
// use the first Case Difference. If no CW difference is
// found, then use the first Extra difference. If no XW
// difference is found, then use the first Special Weight
// difference.
if (uw1 != uw2) {
// Initialize the continue flag.
fContinue = false;
// Check for Unsortable characters and skip them. This
// needs to be outside the switch statement. If EITHER
// character is unsortable, must skip it and start
// over.
if (sm1 == ScriptMember_Unsortable) {
pStringIndex1++; cchCount1--;
fContinue = true;
}
if (sm2 == ScriptMember_Unsortable) {
pStringIndex2++; cchCount2--;
fContinue = true;
}
if (fContinue) {
continue;
}
// Switch on the script member of string 1 and take
// care of any special cases.
switch (sm1) {
case ( ScriptMember_Punctuation ) : {
// If the ignore punctuation flag is set, then
// skip over the punctuation.
if (fIgnorePunct) {
pStringIndex1++; cchCount1--;
fContinue = true;
2008-11-17 18:29:00 -05:00
}
else if (sm2 != ScriptMember_Punctuation) {
2008-03-05 09:52:00 -05:00
// The character in the second string is
// NOT punctuation.
if (WhichPunct2 != 0) {
// Set WP 2 to show that string 2 is smaller,
// since a punctuation char had already been
// found at an earlier position in string 2.
//
// Set the Ignore Punctuation flag so we just
// skip over any other punctuation chars in
// the string.
WhichPunct2 = CSTR_GREATER_THAN;
fIgnorePunct = true;
2008-11-17 18:29:00 -05:00
}
else {
2008-03-05 09:52:00 -05:00
// Set WP 1 to show that string 2 is smaller,
// and that string 1 has had a punctuation
// char - since no punctuation chars have
// been found in string 2.
WhichPunct1 = CSTR_GREATER_THAN;
}
// Advance pointer 1, and set flag to true.
pStringIndex1++; cchCount1--;
fContinue = true;
}
// Do NOT want to advance the pointer in string 1
// if string 2 is also a punctuation char. This
// will be done later.
break;
}
case ( ScriptMember_Unsortable ): {
// Fill out the case statement so the compiler
// will use a jump table.
break;
}
}
// Switch on the script member of string 2 and take care
// of any special cases.
switch (sm2) {
case ( ScriptMember_Punctuation ) : {
// If the ignore punctuation flag is set, then skip
// over the punctuation.
if (fIgnorePunct) {
// Pointer 2 will be advanced after if-else
// statement.
;
2008-11-17 18:29:00 -05:00
}
else if (sm1 != ScriptMember_Punctuation) {
2008-03-05 09:52:00 -05:00
// The character in the first string is
// NOT punctuation.
if (WhichPunct1 != 0) {
// Set WP 1 to show that string 1 is smaller,
// since a punctuation char had already
// been found at an earlier position in
// string 1.
//
// Set the Ignore Punctuation flag so we just
// skip over any other punctuation in the
// string.
WhichPunct1 = CSTR_LESS_THAN;
fIgnorePunct = true;
2008-11-17 18:29:00 -05:00
}
else {
2008-03-05 09:52:00 -05:00
// Set WP 2 to show that string 1 is smaller,
// and that string 2 has had a punctuation
// char - since no punctuation chars have
// been found in string 1.
WhichPunct2 = CSTR_LESS_THAN;
}
// Pointer 2 will be advanced after if-else
// statement.
2008-11-17 18:29:00 -05:00
}
else {
2008-03-05 09:52:00 -05:00
// Both code points are punctuation.
//
// See if either of the strings has encountered
// punctuation chars previous to this.
if (WhichPunct1 != 0) {
// String 1 has had a punctuation char, so
// it should be the smaller string (since
// both have punctuation chars).
WhichPunct1 = CSTR_LESS_THAN;
2008-11-17 18:29:00 -05:00
}
else if (WhichPunct2 != 0) {
2008-03-05 09:52:00 -05:00
// String 2 has had a punctuation char, so
// it should be the smaller string (since
// both have punctuation chars).
WhichPunct2 = CSTR_GREATER_THAN;
2008-11-17 18:29:00 -05:00
}
else {
2008-03-05 09:52:00 -05:00
// Position is the same, so compare the
// special weights. Set WhichPunct1 to
// the smaller special weight.
WhichPunct1 =
(((GET_ALPHA_NUMERIC(uw1) <
GET_ALPHA_NUMERIC(uw2)))
? CSTR_LESS_THAN
: CSTR_GREATER_THAN);
}
//Set the Ignore Punctuation flag so we just
//skip over any other punctuation in the string
fIgnorePunct = true;
// Advance pointer 1. Pointer 2 will be
// advanced after if-else statement.
pStringIndex1++; cchCount1--;
}
// Advance pointer 2 and set flag to true.
pStringIndex2++; cchCount2--;
fContinue = true;
break;
}
case ( ScriptMember_Unsortable ): {
// Fill out the case statement so the compiler
// will use a jump table.
break;
}
}
// See if the comparison should start again.
if (fContinue) {
continue;
}
// We're not supposed to drop down into the state table
// if unicode weights are different, so stop comparison
// and return result of unicode weight comparison.
if (uw1 != uw2) {
return (uw1 < uw2) ? CSTR_LESS_THAN : CSTR_GREATER_THAN;
}
}
// For each state in the state table, do the appropriate
// comparisons. (UW1 == UW2)
if ((State & STATE_DW) != 0) {
if (dw1 != dw2) {
// Save which string has the smaller diacritic
// weight if the diacritic weights are still
// different.
WhichDiacritic = (dw1 < dw2) ? CSTR_LESS_THAN : CSTR_GREATER_THAN;
// Remove state from state machine.
State &= ~STATE_DW;
}
}
if ((State & STATE_CW) != 0) {
// Get the case weights.
if (cw1 != cw2) {
// Save which string has the smaller case weight.
WhichCase = (cw1 < cw2) ? CSTR_LESS_THAN : CSTR_GREATER_THAN;
// Remove state from state machine.
State &= ~STATE_CW;
}
}
}
// Advance the string pointers.
pStringIndex1++; cchCount1--;
pStringIndex2++; cchCount2--;
}
ScanLongerString:
// If the end of BOTH strings has been reached, then the unicode
// weights match exactly. Check the diacritic, case and special
// weights. If all are zero, then return success. Otherwise,
// return the result of the weight difference.
//
// NOTE: The following checks MUST REMAIN IN THIS ORDER:
// Diacritic, Case, Punctuation.
if (cchCount1 == 0) {
if (cchCount2 == 0) {
// Both of the strings have reached the end.
if (WhichDiacritic != 0) {
return (WhichDiacritic);
}
if (WhichCase != 0) {
return (WhichCase);
}
if (WhichPunct1 != 0) {
return (WhichPunct1);
}
if (WhichPunct2 != 0) {
return (WhichPunct2);
}
return (CSTR_EQUAL);
2008-11-17 18:29:00 -05:00
}
else {
2008-03-05 09:52:00 -05:00
// String 2 is longer.
pString1 = pString2;
pStringIndex1 = pStringIndex2;
cchCount1 = cchCount2;
}
}
// Scan to the end of the longer string.
return QuickScanLongerString(pString1, pStringIndex1, cchCount1,
((cchCount2 == 0) ? CSTR_GREATER_THAN : CSTR_LESS_THAN),
WhichDiacritic, WhichCase, WhichPunct1,
WhichPunct2);
}
//int NativeCompareInfo::QUICK_SCAN_LONGER_STRING
//(LPCWSTR ptr, int cchCount1, int ret, int& WhichDiacritic,
// int& WhichCase, int& WhichPunct1, int& WhichPunct2)
private static int QuickScanLongerString(String ptr, int ptrIndex, int cchCount1,
int ret, int WhichDiacritic, int WhichCase, int WhichPunct1,
int WhichPunct2) {
// Search through the rest of the longer string to make sure all
// characters are not to be ignored. If find a character that
// should not be ignored, return the given return value immediately.
// The only exception to this is when a nonspace mark is found. If
// another DW difference has been found earlier, then use that.
while (cchCount1 != 0) {
switch (GET_SCRIPT_MEMBER(GetUnicode(ptr[ptrIndex]))) {
case ( ScriptMember_Unsortable ): {
break;
}
default : {
return (ret);
}
}
// Advance pointer.
ptrIndex++; cchCount1--;
}
// Need to check diacritic, case, extra, and special weights for
// final return value. Still could be equal if the longer part of
// the string contained only unsortable characters.
// NOTE: The following checks MUST REMAIN IN THIS ORDER: Diacritic,
// Case, Punctuation.
if (WhichDiacritic != 0) {
return (WhichDiacritic);
}
if (WhichCase != 0) {
return (WhichCase);
}
if (WhichPunct1 != 0) {
return (WhichPunct1);
}
if (WhichPunct2 != 0) {
return (WhichPunct2);
}
return (CSTR_EQUAL);
}
////////////////////////////////////////////////////////////////////////
//
// IsPrefix
//
// Determines whether prefix is a prefix of string. If prefix equals
// String.Empty, true is returned.
//
////////////////////////////////////////////////////////////////////////
//| <include path='docs/doc[@for="CompareInfo.IsPrefix"]/*' />
public static bool IsPrefix(String source, String prefix,
CompareOptions options) {
if (source == null || prefix == null) {
throw new ArgumentNullException(source==null?"source":"prefix",
"Argument is null");
}
int prefixLen = prefix.Length;
if (prefixLen == 0) {
return true;
}
if (((uint) options & ValidMaskOffFlags) != 0 &&
(options != CompareOptions.Ordinal)) {
throw new ArgumentException("Invalid flags", "options");
}
int sourceLen = source.Length;
if (options == CompareOptions.Ordinal) {
if (prefixLen > sourceLen) {
return false;
}
for (int i = 0; i < prefixLen; i++) {
if (prefix[i] != source[i]) {
return false;
}
}
return true;
}
int result = IndexOf(source, prefix, 0, options);
return (result == 0);
}
//| <include path='docs/doc[@for="CompareInfo.IsPrefix1"]/*' />
public static bool IsPrefix(String source, String prefix)
{
return (IsPrefix(source, prefix, 0));
}
////////////////////////////////////////////////////////////////////////
//
// IsSuffix
//
// Determines whether suffix is a suffix of string. If suffix equals
// String.Empty, true is returned.
//
////////////////////////////////////////////////////////////////////////
//| <include path='docs/doc[@for="CompareInfo.IsSuffix"]/*' />
public static bool IsSuffix(String source, String suffix,
CompareOptions options) {
if (source == null || suffix == null) {
throw new ArgumentNullException(source==null?"source":"suffix",
"Argument is null");
}
int suffixLen = suffix.Length;
if (suffixLen == 0) {
return true;
}
if (((uint) options & ValidMaskOffFlags) != 0 &&
(options != CompareOptions.Ordinal)) {
throw new ArgumentException("Invalid flags", "options");
}
// native boundary
// BUGBUG: fast string testing goes here: COMNlsInfo::nativeIsSuffix
int matchEnd;
int result = LastIndexOfString(source, suffix, source.Length-1,
source.Length, options, out matchEnd);
if (result >= 0) {
int sourceLen = source.Length;
if (matchEnd == sourceLen) {
return true;
}
if (matchEnd < sourceLen) {
return false;
}
}
return true;
}
//| <include path='docs/doc[@for="CompareInfo.IsSuffix1"]/*' />
public static bool IsSuffix(String source, String suffix)
{
return (IsSuffix(source, suffix, 0));
}
////////////////////////////////////////////////////////////////////////
//
// IndexOf
//
// Returns the first index where value is found in string. The
// search starts from startIndex and ends at endIndex. If endIndex
// is -1, then it will go to the end of the string. Returns -1 if
// the specified value is not found. If value equals String.Empty,
// startIndex is returned. Throws IndexOutOfRange if startIndex or
// endIndex is less than zero or greater than the length of string.
// Throws ArgumentException if value is null.
//
////////////////////////////////////////////////////////////////////////
//| <include path='docs/doc[@for="CompareInfo.IndexOf"]/*' />
public static int IndexOf(String source, char value) {
return IndexOfChar(source, value, 0, -1, CompareOptions.None);
}
//| <include path='docs/doc[@for="CompareInfo.IndexOf1"]/*' />
public static int IndexOf(String source, String value) {
return IndexOfString(source, value, 0, -1, CompareOptions.None);
}
//| <include path='docs/doc[@for="CompareInfo.IndexOf2"]/*' />
public static int IndexOf(String source, char value, CompareOptions options) {
return IndexOfChar(source, value, 0, -1, options);
}
//| <include path='docs/doc[@for="CompareInfo.IndexOf3"]/*' />
public static int IndexOf(String source, String value, CompareOptions options) {
return IndexOfString(source, value, 0, -1, options);
}
//| <include path='docs/doc[@for="CompareInfo.IndexOf4"]/*' />
public static int IndexOf(String source, char value, int startIndex) {
if (source == null) {
throw new ArgumentNullException("source");
}
if (startIndex > source.Length) {
throw new ArgumentOutOfRangeException("startIndex",
"greater than string len");
}
return IndexOfChar(source, value, startIndex, -1, CompareOptions.None);
}
//| <include path='docs/doc[@for="CompareInfo.IndexOf10"]/*' />
public static int IndexOf(String source, char value, int startIndex,
CompareOptions options) {
return IndexOfChar(source, value, startIndex, -1, options);
}
//| <include path='docs/doc[@for="CompareInfo.IndexOf5"]/*' />
public static int IndexOf(String source, char value,
int startIndex, int count) {
if (count < 0) {
throw new ArgumentOutOfRangeException("count", "negative");
}
return IndexOfChar(source, value, startIndex, count, CompareOptions.None);
}
//| <include path='docs/doc[@for="CompareInfo.IndexOf6"]/*' />
public static int IndexOf(String source, String value, int startIndex) {
if (source == null) {
throw new ArgumentNullException("source");
}
if (startIndex > source.Length) {
throw new ArgumentOutOfRangeException("startIndex",
"greater than string len");
}
return IndexOfString(source, value, startIndex, -1,
CompareOptions.None);
}
//| <include path='docs/doc[@for="CompareInfo.IndexOf11"]/*' />
public static int IndexOf(String source, String value,
int startIndex, CompareOptions options) {
return IndexOfString(source, value, startIndex, -1, options);
}
//| <include path='docs/doc[@for="CompareInfo.IndexOf7"]/*' />
public static int IndexOf(String source, String value,
int startIndex, int count) {
if (count < 0) {
throw new ArgumentOutOfRangeException("count", "negative");
}
return IndexOfString(source, value, startIndex, count,
CompareOptions.None);
}
//| <include path='docs/doc[@for="CompareInfo.IndexOf8"]/*' />
public static int IndexOf(String source, char value,
int startIndex, int count,
CompareOptions options) {
if (count < 0) {
throw new ArgumentOutOfRangeException("count", "negative");
}
return IndexOfChar(source, value, startIndex, count, options);
}
//| <include path='docs/doc[@for="CompareInfo.IndexOf9"]/*' />
public static int IndexOf(String source, String value,
int startIndex, int count,
CompareOptions options) {
if (count < 0) {
throw new ArgumentOutOfRangeException("count", "negative");
}
return IndexOfString(source, value, startIndex, count, options);
}
private static int IndexOfChar(String source, char value,
int startIndex, int count,
CompareOptions options) {
if (source == null) {
throw new ArgumentNullException("source");
}
int stringLen = source.Length;
if (stringLen == 0) {
return -1;
}
if (startIndex < 0 || startIndex > stringLen) {
throw new ArgumentOutOfRangeException("startIndex");
}
if (count == -1) {
count = stringLen - startIndex;
2008-11-17 18:29:00 -05:00
}
else if (count < 0 || count + startIndex > stringLen) {
2008-03-05 09:52:00 -05:00
throw new ArgumentOutOfRangeException("count");
}
int endIndex = startIndex + count - 1;
bool fAscii = false;
if (options != CompareOptions.Ordinal) {
2008-11-17 18:29:00 -05:00
if (source.StringState == StringState.Undetermined) {
2008-03-05 09:52:00 -05:00
source.CheckHighChars();
}
fAscii = ((source.IsFastIndex() && value < 0x7f) || value == 0);
}
if ((fAscii && options == CompareOptions.None) ||
(options == CompareOptions.Ordinal)) {
for (int i = startIndex; i <= endIndex; i++) {
if (source[i] == value) {
return i;
}
}
return -1;
2008-11-17 18:29:00 -05:00
}
else if (fAscii && options == CompareOptions.IgnoreCase) {
2008-03-05 09:52:00 -05:00
char lowerValue = value;
if (value >= 'A' && value <= 'Z') {
lowerValue = (char) (value | 0x20);
}
for (int i = startIndex; i <= endIndex; i++) {
char sourceValue = source[i];
if (sourceValue >= 'A' && sourceValue <= 'Z') {
sourceValue = (char) (sourceValue | 0x20);
}
if (lowerValue == sourceValue) {
return i;
}
}
return -1;
2008-11-17 18:29:00 -05:00
}
else {
2008-03-05 09:52:00 -05:00
return SlowIndexOfString(source, String.StringCTOR(value, 1),
startIndex, endIndex, options);
}
}
private static int IndexOfString(String source, String value,
int startIndex, int count,
CompareOptions options) {
if (source == null) {
throw new ArgumentNullException("source");
}
if (value == null) {
throw new ArgumentNullException("value");
}
int sourceLen = source.Length;
int valueLen = value.Length;
if (sourceLen == 0) {
if (valueLen == 0) {
return 0;
2008-11-17 18:29:00 -05:00
}
else {
2008-03-05 09:52:00 -05:00
return -1;
}
}
if (startIndex < 0 || startIndex > sourceLen) {
throw new ArgumentOutOfRangeException("startIndex");
}
if (count == -1) {
count = sourceLen - startIndex;
2008-11-17 18:29:00 -05:00
}
else if (count < 0 || count + startIndex > sourceLen) {
2008-03-05 09:52:00 -05:00
throw new ArgumentOutOfRangeException("count");
}
if (valueLen == 0) {
return startIndex;
}
int endIndex = startIndex + count - 1;
2008-11-17 18:29:00 -05:00
// NOTE: Currently we do not support cultures, so make
2008-03-05 09:52:00 -05:00
// requests for default comparisons the same as 'Ordinal' (fast,
// unicode-value-based). When we add proper support for
// cultures, take out the == CompareOptions.None case.
if ((options == CompareOptions.Ordinal) ||
(options == CompareOptions.None))
{
return FastIndexOfString(source, startIndex, endIndex, value);
}
return SlowIndexOfString(source, value, startIndex, endIndex, options);
}
private static int FastIndexOfString(String source, int startIndex,
int endIndex, String value) {
int valueLen = value.Length;
int endPattern = endIndex - valueLen + 1;
if (endPattern < 0) {
return -1;
}
if (valueLen <= 0) {
return startIndex;
}
for (int i = startIndex; i <= endPattern; i++) {
int j = 0;
2008-11-17 18:29:00 -05:00
while (source[i + j] == value[j]) {
2008-03-05 09:52:00 -05:00
j++;
if (j == valueLen) {
return i;
}
}
}
return -1;
}
private static int FastIndexOfStringInsensitive(String source,
int startIndex,
int endIndex,
String pattern) {
char srcChar, patChar;
int endPattern = endIndex - pattern.Length + 1;
2008-11-17 18:29:00 -05:00
if (endPattern < 0) {
2008-03-05 09:52:00 -05:00
return -1;
}
2008-11-17 18:29:00 -05:00
for (int ctrSrc = startIndex; ctrSrc <= endPattern; ctrSrc++) {
2008-03-05 09:52:00 -05:00
int ctrPat;
2008-11-17 18:29:00 -05:00
for (ctrPat = 0; ctrPat < pattern.Length; ctrPat++) {
2008-03-05 09:52:00 -05:00
srcChar = source[ctrSrc + ctrPat];
2008-11-17 18:29:00 -05:00
if (srcChar >= 'A' && srcChar <= 'Z') {
2008-03-05 09:52:00 -05:00
srcChar |= (char)0x20;
}
patChar = pattern[ctrPat];
2008-11-17 18:29:00 -05:00
if (patChar >= 'A' && patChar <= 'Z') {
2008-03-05 09:52:00 -05:00
patChar |= (char)0x20;
}
2008-11-17 18:29:00 -05:00
if (srcChar != patChar) {
2008-03-05 09:52:00 -05:00
break;
}
}
2008-11-17 18:29:00 -05:00
if (ctrPat == pattern.Length) {
2008-03-05 09:52:00 -05:00
return ctrSrc;
}
}
return -1;
}
private static int SlowIndexOfString(String source, String value,
int startIndex, int endIndex,
CompareOptions options) {
throw new Exception("CompareInfo.SlowIndexOfString not implemented in Bartok!");
}
////////////////////////////////////////////////////////////////////////
//
// LastIndexOf
//
// Returns the last index where value is found in string. The
// search starts from startIndex and ends at endIndex. If endIndex
// is -1, then it will go to the end of the string. Returns -1 if
// the specified value is not found. If value equals String.Empty,
// endIndex is returned. Throws IndexOutOfRange if startIndex or
// endIndex is less than zero or greater than the length of string.
// Throws ArgumentException if value is null.
//
////////////////////////////////////////////////////////////////////////
//| <include path='docs/doc[@for="CompareInfo.LastIndexOf"]/*' />
public static int LastIndexOf(String source, char value) {
if (source == null) {
throw new ArgumentNullException("source");
}
return LastIndexOfChar(source, value,
source.Length-1, source.Length,
CompareOptions.None);
}
//| <include path='docs/doc[@for="CompareInfo.LastIndexOf1"]/*' />
public static int LastIndexOf(String source, String value) {
if (source == null) {
throw new ArgumentNullException("source");
}
int ignore;
return LastIndexOfString(source, value,
source.Length-1, source.Length,
CompareOptions.None, out ignore);
}
//| <include path='docs/doc[@for="CompareInfo.LastIndexOf2"]/*' />
public static int LastIndexOf(String source, char value,
CompareOptions options) {
if (source == null) {
throw new ArgumentNullException("source");
}
return LastIndexOfChar(source, value,
source.Length-1, source.Length,
options);
}
//| <include path='docs/doc[@for="CompareInfo.LastIndexOf3"]/*' />
public static int LastIndexOf(String source, String value,
CompareOptions options) {
if (source == null) {
throw new ArgumentNullException("source");
}
int ignore;
return LastIndexOfString(source, value,
source.Length-1, source.Length,
options, out ignore);
}
//| <include path='docs/doc[@for="CompareInfo.LastIndexOf4"]/*' />
public static int LastIndexOf(String source, char value,
int startIndex) {
return LastIndexOfChar(source, value, startIndex, startIndex+1,
CompareOptions.None);
}
//| <include path='docs/doc[@for="CompareInfo.LastIndexOf11"]/*' />
public static int LastIndexOf(String source, char value,
int startIndex, CompareOptions options) {
return LastIndexOfChar(source, value, startIndex, startIndex+1,
options);
}
//| <include path='docs/doc[@for="CompareInfo.LastIndexOf5"]/*' />
public static int LastIndexOf(String source, char value,
int startIndex, int count) {
if (count < 0) {
throw new ArgumentOutOfRangeException("count", "negative");
}
return LastIndexOfChar(source, value, startIndex, count,
CompareOptions.None);
}
//| <include path='docs/doc[@for="CompareInfo.LastIndexOf6"]/*' />
public static int LastIndex(String source, String value,
int startIndex) {
int ignore;
return LastIndexOfString(source, value,
startIndex, startIndex+1,
CompareOptions.None, out ignore);
}
//| <include path='docs/doc[@for="CompareInfo.LastIndexOf10"]/*' />
public static int LastIndexOf(String source, String value,
int startIndex, CompareOptions options) {
int ignore;
return LastIndexOfString(source, value,
startIndex, startIndex+1,
options, out ignore);
}
//| <include path='docs/doc[@for="CompareInfo.LastIndexOf7"]/*' />
public static int LastIndexOf(String source, String value,
int startIndex, int count) {
if (count < 0) {
throw new ArgumentOutOfRangeException("count", "negative");
}
int ignore;
return LastIndexOfString(source, value, startIndex, count,
CompareOptions.None, out ignore);
}
//| <include path='docs/doc[@for="CompareInfo.LastIndexOf8"]/*' />
public static int LastIndexOf(String source, char value,
int startIndex, int count,
CompareOptions options) {
if (count < 0) {
throw new ArgumentOutOfRangeException("count", "negative");
}
return LastIndexOfChar(source, value, startIndex, count,
options);
}
//| <include path='docs/doc[@for="CompareInfo.LastIndexOf9"]/*' />
public static int LastIndexOf(String source, String value,
int startIndex, int count,
CompareOptions options) {
if (count < 0) {
throw new ArgumentOutOfRangeException("count", "negative");
}
int ignore;
return LastIndexOfString(source, value, startIndex, count,
options, out ignore);
}
internal static int LastIndexOfChar(String source, char value,
int startIndex, int count,
CompareOptions options) {
if (source == null) {
throw new ArgumentNullException("source");
}
int stringLen = source.Length;
if (stringLen == 0) {
return -1;
}
if (startIndex < 0 || startIndex > stringLen) {
throw new ArgumentOutOfRangeException("startIndex");
}
int endIndex;
if (count == -1) {
endIndex = 0;
count = startIndex + 1; // REVIEW: not the same as BCL code
2008-11-17 18:29:00 -05:00
}
else if (count < 0 || count > startIndex + 1) {
2008-03-05 09:52:00 -05:00
throw new ArgumentOutOfRangeException("count");
2008-11-17 18:29:00 -05:00
}
else {
2008-03-05 09:52:00 -05:00
endIndex = startIndex - count + 1;
}
bool fAscii = false;
if (options != CompareOptions.Ordinal) {
2008-11-17 18:29:00 -05:00
if (source.StringState == StringState.Undetermined) {
2008-03-05 09:52:00 -05:00
source.CheckHighChars();
}
fAscii = (source.IsFastIndex() && value < 0x7f) || value == 0;
}
if ((fAscii && options == CompareOptions.None) ||
(options == CompareOptions.Ordinal)) {
for (int i = startIndex; i >= endIndex; i--) {
if (source[i] == value) {
return i;
}
}
return -1;
2008-11-17 18:29:00 -05:00
}
else if (fAscii && options == CompareOptions.IgnoreCase) {
2008-03-05 09:52:00 -05:00
char lowerValue = value;
if (value >= 'A' && value <= 'Z') {
lowerValue = (char) (value | 0x20);
}
for (int i = startIndex; i >= endIndex; i--) {
char sourceValue = source[i];
if (sourceValue >= 'A' && sourceValue <= 'Z') {
sourceValue = (char) (sourceValue | 0x20);
}
if (lowerValue == sourceValue) {
return i;
}
}
return -1;
2008-11-17 18:29:00 -05:00
}
else {
// Probably wrong, but needed for Bartok.
2008-03-05 09:52:00 -05:00
// throw new Exception("CompareInfo.SlowLastIndexOfChar not implemented in Bartok!");
for (int i = startIndex; i >= endIndex; i--) {
if (source[i] == value) {
return i;
}
}
return -1;
}
}
internal static int LastIndexOfString(String source, String value,
int startIndex, int count,
CompareOptions options,
out int matchEndIndex) {
if (source == null) {
throw new ArgumentNullException("source");
}
if (value == null) {
throw new ArgumentNullException("value");
}
int sourceLen = source.Length;
int valueLen = value.Length;
if (sourceLen == 0) {
if (valueLen == 0) {
matchEndIndex = 0;
return 0;
2008-11-17 18:29:00 -05:00
}
else {
2008-03-05 09:52:00 -05:00
matchEndIndex = -1; // REVIEW: not the same as BCL
return -1;
}
}
if (startIndex < 0 || startIndex > sourceLen) {
throw new ArgumentOutOfRangeException("startIndex");
}
int endIndex;
if (count == -1) {
endIndex = 0;
count = startIndex + 1; // REVIEW: not the same as BCL
2008-11-17 18:29:00 -05:00
}
else if (count < 0 || count - 1 > startIndex) {
2008-03-05 09:52:00 -05:00
throw new ArgumentOutOfRangeException("count");
2008-11-17 18:29:00 -05:00
}
else {
2008-03-05 09:52:00 -05:00
endIndex = startIndex - count + 1;
}
if (valueLen == 0) {
matchEndIndex = startIndex; // REVIEW: not the same as BCL
return startIndex;
}
if (options == CompareOptions.Ordinal) {
return FastLastIndexOfString(source, startIndex, endIndex,
value, out matchEndIndex);
}
2008-11-17 18:29:00 -05:00
// NOTE: Currently we do not support cultures, so make
2008-03-05 09:52:00 -05:00
// requests for default comparisons the same as 'Ordinal' (fast,
// unicode-value-based). When we add proper support for
// cultures, take out the == CompareOptions.None case.
if ((options == CompareOptions.Ordinal) ||
(options == CompareOptions.None))
{
return FastLastIndexOfString(source, startIndex, endIndex, value,
out matchEndIndex);
}
matchEndIndex = -1;
return -1;
// throw new Exception("CompareInfo.SlowLastIndexOfString not implemented in Bartok!");
}
private static int FastLastIndexOfString(String source, int startIndex,
int endIndex, String value,
out int matchEndIndex) {
int valueLen = value.Length;
int startPattern = startIndex - valueLen + 1;
if (startPattern < 0) {
matchEndIndex = -1;
return -1;
}
for (int ctrSrc = startPattern; ctrSrc >= endIndex; ctrSrc--) {
int ctrPat;
for (ctrPat = 0;
(ctrPat < valueLen)
&& (source[ctrSrc + ctrPat] == value[ctrPat]);
ctrPat++) {
//Deliberately empty.
}
if (ctrPat == valueLen) {
matchEndIndex = ctrSrc;
return ctrSrc;
}
}
matchEndIndex = -1;
return -1;
}
//////////////////////////////////////////////////////////////////////
//
private static byte GET_SCRIPT_MEMBER(ushort pwt) {
return (byte) ((pwt & 0xff00) >> 8);
}
private static byte GET_ALPHA_NUMERIC(ushort pwt) {
return (byte) (pwt & 0x00ff);
}
private static ushort GetUnicode(char c) {
short firstIndex = unicodeTableLevel1[c >> 8];
short secondIndex = unicodeTableLevel2[firstIndex + ((c >> 4) & 0xf)];
return unicodeTableLevel3[secondIndex + (c & 0xf)];
}
private static byte GetDiacritic(char c) {
short firstIndex = diacriticTableLevel1[c >> 8];
short secondIndex = diacriticTableLevel2[firstIndex + ((c >> 4) & 0xf)];
return diacriticTableLevel3[secondIndex + (c & 0xf)];
}
private static byte GetCase(char c) {
short firstIndex = caseTableLevel1[c >> 8];
short secondIndex = caseTableLevel2[firstIndex + ((c >> 4) & 0xf)];
return caseTableLevel3[secondIndex + (c & 0xf)];
}
private static short[] unicodeTableLevel1 = new short[256] {
0 ,16 ,32 ,48 ,64 ,80 ,96 ,112 ,128 ,144 ,160 ,176 ,192 ,208 ,224 ,128 , // 0
240 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,256 ,128 , // 16
272 ,288 ,304 ,128 ,320 ,128 ,336 ,352 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 , // 32
368 ,128 ,384 ,400 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 , // 48
128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 , // 64
128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 , // 80
128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 , // 96
128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 , // 112
128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 , // 128
128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 , // 144
128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 , // 160
128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 , // 176
128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 , // 192
128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 , // 208
128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 , // 224
128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,416 ,128 ,128 ,432 ,448 , // 240
};
private static short[] unicodeTableLevel2 = new short[464] {
0 ,16 ,32 ,48 ,64 ,80 ,96 ,112 ,128 ,144 ,160 ,176 ,192 ,208 ,192 ,224 , // 0
240 ,256 ,272 ,288 ,304 ,320 ,336 ,352 ,368 ,384 ,400 ,416 ,432 ,448 ,464 ,480 , // 16
496 ,512 ,528 ,528 ,528 ,544 ,560 ,576 ,592 ,608 ,624 ,640 ,656 ,672 ,688 ,528 , // 32
528 ,528 ,528 ,528 ,528 ,528 ,528 ,704 ,720 ,528 ,528 ,528 ,528 ,528 ,528 ,528 , // 48
528 ,528 ,528 ,528 ,528 ,528 ,528 ,528 ,736 ,528 ,528 ,528 ,528 ,528 ,528 ,528 , // 64
528 ,528 ,528 ,528 ,528 ,752 ,528 ,528 ,768 ,528 ,528 ,784 ,800 ,528 ,528 ,816 , // 80
832 ,848 ,528 ,528 ,864 ,880 ,896 ,528 ,528 ,528 ,528 ,528 ,528 ,912 ,528 ,928 , // 96
944 ,528 ,528 ,528 ,528 ,528 ,528 ,528 ,528 ,528 ,528 ,528 ,528 ,528 ,528 ,528 , // 112
528 ,528 ,528 ,528 ,528 ,528 ,528 ,528 ,528 ,528 ,528 ,528 ,528 ,528 ,528 ,528 , // 128
528 ,528 ,528 ,960 ,528 ,976 ,992 ,1008,528 ,528 ,528 ,528 ,528 ,528 ,1024,1040, // 144
528 ,528 ,528 ,528 ,528 ,528 ,1056,528 ,528 ,528 ,528 ,528 ,528 ,528 ,1072,528 , // 160
528 ,528 ,528 ,528 ,528 ,528 ,1088,528 ,528 ,528 ,528 ,528 ,528 ,528 ,1104,1120, // 176
528 ,528 ,528 ,528 ,528 ,528 ,1136,528 ,528 ,528 ,528 ,528 ,528 ,528 ,1152,528 , // 192
528 ,528 ,528 ,528 ,528 ,528 ,1168,528 ,528 ,528 ,528 ,528 ,528 ,528 ,528 ,528 , // 208
528 ,528 ,528 ,1184,528 ,1200,528 ,528 ,528 ,528 ,528 ,528 ,528 ,1216,528 ,528 , // 224
528 ,528 ,528 ,528 ,528 ,528 ,528 ,528 ,528 ,528 ,528 ,528 ,528 ,528 ,528 ,1232, // 240
1248,1264,1280,1296,1312,1328,1344,1360,1376,1392,1408,1424,1440,1456,1472,1488, // 256
1504,1520,1536,1552,1568,528 ,528 ,1584,1600,528 ,1616,528 ,528 ,528 ,528 ,528 , // 272
1632,1648,1664,1680,528 ,1696,1712,1728,1744,528 ,528 ,528 ,528 ,528 ,528 ,528 , // 288
1760,1776,1792,1808,1824,1840,1856,1872,1888,1904,1920,1936,1952,1968,1984,2000, // 304
2016,2032,2048,528 ,2064,528 ,2080,2096,2112,2128,2144,2160,2176,2192,2208,528 , // 320
2224,2240,2256,2272,2288,2304,2320,528 ,528 ,528 ,528 ,528 ,528 ,528 ,528 ,528 , // 336
2336,2352,2368,2384,2400,2416,2432,2448,2464,2480,528 ,528 ,528 ,528 ,528 ,528 , // 352
2496,2512,2528,2544,528 ,528 ,528 ,528 ,528 ,528 ,528 ,528 ,528 ,528 ,528 ,2560, // 368
528 ,528 ,528 ,528 ,528 ,528 ,528 ,2576,528 ,528 ,528 ,528 ,528 ,528 ,528 ,528 , // 384
528 ,528 ,528 ,528 ,528 ,528 ,528 ,528 ,2592,2608,2624,2640,2656,2672,528 ,528 , // 400
2688,528 ,528 ,528 ,528 ,528 ,528 ,528 ,528 ,528 ,528 ,528 ,528 ,528 ,528 ,528 , // 416
528 ,528 ,528 ,2704,2720,2736,2752,2768,528 ,528 ,528 ,528 ,528 ,528 ,528 ,528 , // 432
2784,48 ,64 ,80 ,96 ,2800,2816,528 ,528 ,528 ,528 ,528 ,528 ,528 ,2832,528 , // 448
};
private static ushort[] unicodeTableLevel3 = new ushort[2848] {
0x0000,0x0603,0x0604,0x0605,0x0606,0x0607,0x0608,0x0609, // 0
0x060a,0x0705,0x0706,0x0707,0x0708,0x0709,0x060b,0x060c,
0x060d,0x060e,0x060f,0x0610,0x0611,0x0612,0x0613,0x0614, // 16
0x0615,0x0616,0x0617,0x0618,0x0619,0x061a,0x061b,0x061c,
0x0702,0x071c,0x071d,0x071f,0x0721,0x0723,0x0725,0x0680, // 32
0x0727,0x072a,0x072d,0x0803,0x072f,0x0682,0x0733,0x0735,
0x0c03,0x0c21,0x0c33,0x0c46,0x0c58,0x0c6a,0x0c7d,0x0c90, // 48
0x0ca2,0x0cb4,0x0737,0x073a,0x080e,0x0812,0x0814,0x073c,
0x073e,0x0e02,0x0e09,0x0e0a,0x0e1a,0x0e21,0x0e23,0x0e25, // 64
0x0e2c,0x0e32,0x0e35,0x0e36,0x0e48,0x0e51,0x0e70,0x0e7c,
0x0e7e,0x0e89,0x0e8a,0x0e91,0x0e99,0x0e9f,0x0ea2,0x0ea4, // 80
0x0ea6,0x0ea7,0x0ea9,0x073f,0x0741,0x0742,0x0743,0x0744,
0x0748,0x0e02,0x0e09,0x0e0a,0x0e1a,0x0e21,0x0e23,0x0e25, // 96
0x0e2c,0x0e32,0x0e35,0x0e36,0x0e48,0x0e51,0x0e70,0x0e7c,
0x0e7e,0x0e89,0x0e8a,0x0e91,0x0e99,0x0e9f,0x0ea2,0x0ea4, // 112
0x0ea6,0x0ea7,0x0ea9,0x074a,0x074c,0x074e,0x0750,0x061d,
0x061e,0x061f,0x0620,0x0621,0x0622,0x0623,0x0624,0x0625, // 128
0x0626,0x0627,0x0628,0x0629,0x062a,0x062b,0x062c,0x062d,
0x062e,0x062f,0x0630,0x0631,0x0632,0x0633,0x0634,0x0635, // 144
0x0636,0x0637,0x0638,0x0639,0x063a,0x063b,0x063c,0x063d,
0x0704,0x0751,0x0a02,0x0a03,0x0a04,0x0a05,0x0752,0x0a06, // 160
0x0753,0x0a07,0x0e02,0x0818,0x0a08,0x0683,0x0a09,0x0754,
0x0a0a,0x0817,0x0c33,0x0c46,0x0755,0x0a0b,0x0a0c,0x0a0d, // 176
0x0756,0x0c21,0x0e7c,0x081a,0x0c15,0x0c19,0x0c1d,0x0757,
0x0e02,0x0e02,0x0e02,0x0e02,0x0e02,0x0e02,0x0e02,0x0e0a, // 192
0x0e21,0x0e21,0x0e21,0x0e21,0x0e32,0x0e32,0x0e32,0x0e32,
0x0e1a,0x0e70,0x0e7c,0x0e7c,0x0e7c,0x0e7c,0x0e7c,0x081c, // 208
0x0e7c,0x0e9f,0x0e9f,0x0e9f,0x0e9f,0x0ea7,0x0e99,0x0e91,
0x0e1a,0x0e70,0x0e7c,0x0e7c,0x0e7c,0x0e7c,0x0e7c,0x081d, // 224
0x0e7c,0x0e9f,0x0e9f,0x0e9f,0x0e9f,0x0ea7,0x0e99,0x0ea7,
0x0e02,0x0e02,0x0e02,0x0e02,0x0e02,0x0e02,0x0e0a,0x0e0a, // 240
0x0e0a,0x0e0a,0x0e0a,0x0e0a,0x0e0a,0x0e0a,0x0e1a,0x0e1a,
0x0e1a,0x0e1a,0x0e21,0x0e21,0x0e21,0x0e21,0x0e21,0x0e21, // 256
0x0e21,0x0e21,0x0e21,0x0e21,0x0e25,0x0e25,0x0e25,0x0e25,
0x0e25,0x0e25,0x0e25,0x0e25,0x0e2c,0x0e2c,0x0e2c,0x0e2c, // 272
0x0e32,0x0e32,0x0e32,0x0e32,0x0e32,0x0e32,0x0e32,0x0e32,
0x0e32,0x0e32,0x0e32,0x0e32,0x0e35,0x0e35,0x0e36,0x0e36, // 288
0x0e36,0x0e48,0x0e48,0x0e48,0x0e48,0x0e48,0x0e48,0x0e48,
0x0e48,0x0e48,0x0e48,0x0e70,0x0e70,0x0e70,0x0e70,0x0e70, // 304
0x0e70,0x0e70,0x0e74,0x0e74,0x0e7c,0x0e7c,0x0e7c,0x0e7c,
0x0e7c,0x0e7c,0x0e7c,0x0e7c,0x0e8a,0x0e8a,0x0e8a,0x0e8a, // 320
0x0e8a,0x0e8a,0x0e91,0x0e91,0x0e91,0x0e91,0x0e91,0x0e91,
0x0e91,0x0e91,0x0e99,0x0e99,0x0e99,0x0e99,0x0e9e,0x0e9e, // 336
0x0e9f,0x0e9f,0x0e9f,0x0e9f,0x0e9f,0x0e9f,0x0e9f,0x0e9f,
0x0e9f,0x0e9f,0x0e9f,0x0e9f,0x0ea4,0x0ea4,0x0ea7,0x0ea7, // 352
0x0ea7,0x0ea9,0x0ea9,0x0ea9,0x0ea9,0x0ea9,0x0ea9,0x0e96,
0x0e09,0x0e09,0x0e09,0x0e09,0x0e09,0x0e09,0x0e0a,0x0e0a, // 368
0x0e0a,0x0e1b,0x0e1a,0x0e1a,0x0e1a,0x0e1a,0x0e21,0x0e21,
0x0e21,0x0e23,0x0e23,0x0e25,0x0e25,0x0e2c,0x0e32,0x0e32, // 384
0x0e36,0x0e36,0x0e48,0x0e48,0x0e51,0x0e70,0x0e70,0x0e7c,
0x0e7c,0x0e7c,0x0e7c,0x0e7c,0x0e7e,0x0e7e,0x0e8a,0x0e91, // 400
0x0e91,0x0e91,0x0e91,0x0e99,0x0e99,0x0e99,0x0e99,0x0e9f,
0x0e9f,0x0e9f,0x0ea2,0x0ea7,0x0ea7,0x0ea9,0x0ea9,0x0eaa, // 416
0x0eaa,0x0eaa,0x0eaa,0x0c33,0x0c6b,0x0c6b,0x0eb3,0x0ea4,
0x081e,0x081f,0x0820,0x0758,0x0e1a,0x0e1a,0x0e1a,0x0e48, // 432
0x0e48,0x0e48,0x0e70,0x0e70,0x0e70,0x0e02,0x0e02,0x0e32,
0x0e32,0x0e7c,0x0e7c,0x0e9f,0x0e9f,0x0e9f,0x0e9f,0x0e9f, // 448
0x0e9f,0x0e9f,0x0e9f,0x0e9f,0x0e9f,0x0e21,0x0e02,0x0e02,
0x0e02,0x0e02,0x0e02,0x0e02,0x0e25,0x0e25,0x0e25,0x0e25, // 464
0x0e36,0x0e36,0x0e7c,0x0e7c,0x0e7c,0x0e7c,0x0eaa,0x0eaa,
0x0e35,0x0e1a,0x0e1a,0x0e1a,0x0e25,0x0e25,0x0000,0x0000, // 480
0x0000,0x0000,0x0e02,0x0e02,0x0e02,0x0e02,0x0e7c,0x0e7c,
0x0e02,0x0e02,0x0e02,0x0e02,0x0e21,0x0e21,0x0e21,0x0e21, // 496
0x0e32,0x0e32,0x0e32,0x0e32,0x0e7c,0x0e7c,0x0e7c,0x0e7c,
0x0e8a,0x0e8a,0x0e8a,0x0e8a,0x0e9f,0x0e9f,0x0e9f,0x0e9f, // 512
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // 528
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0e02,0x0e02,0x0e02,0x0e09,0x0e0a,0x0e0a,0x0e1a,0x0e1a, // 544
0x0e21,0x0e21,0x0e21,0x0e21,0x0e21,0x0e21,0x0e21,0x0e35,
0x0e25,0x0e25,0x0e25,0x0e25,0x0e25,0x0e2c,0x0e2c,0x0e2d, // 560
0x0e32,0x0e32,0x0e32,0x0e48,0x0e48,0x0e48,0x0e48,0x0e51,
0x0e51,0x0e51,0x0e70,0x0e70,0x0e70,0x0e7c,0x0e7c,0x0e7c, // 576
0x0e7e,0x0e8a,0x0e8a,0x0e8a,0x0e8a,0x0e8a,0x0e8a,0x0e8a,
0x0e8a,0x0e8a,0x0e91,0x0e21,0x0e35,0x0e21,0x0e21,0x0e99, // 592
0x0e99,0x0e9f,0x0e9f,0x0ea2,0x0ea2,0x0ea4,0x0ea7,0x0ea7,
0x0ea9,0x0ea9,0x0eaa,0x0eaa,0x0eb3,0x0eb3,0x0eb3,0x0e0a, // 608
0x0eb4,0x0e09,0x0e21,0x0e25,0x0e2c,0x0e35,0x0e36,0x0e48,
0x0e89,0x0eb3,0x0eb3,0x0e1c,0x0e1a,0x0e1c,0x0e9d,0x0e99, // 624
0x0e99,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0e2c,0x0e2c,0x0e35,0x0e8a,0x0e8a,0x0e8a,0x0e8a,0x0ea4, // 640
0x0ea7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0743,0x0759, // 656
0x0000,0x0754,0x0755,0x0748,0x0000,0x0000,0x0000,0x0000,
0x07db,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // 672
0x0759,0x075a,0x075b,0x075c,0x075d,0x075e,0x0000,0x0000,
0x0e25,0x0e48,0x0e91,0x0ea6,0x0000,0x0000,0x0000,0x0000, // 688
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,0x0000,0x075f,0x0760,0x0000,0x0000, // 704
0x0000,0x0000,0x0761,0x0000,0x0000,0x0000,0x0762,0x0000,
0x0000,0x0000,0x0000,0x0000,0x0763,0x0764,0x0000,0x0000, // 720
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0000,0x0000,0x0cdb,0x0000,0x0000,0x0000,0x0000,0x0000, // 736
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // 752
0x0000,0x0000,0x0000,0x0765,0x0766,0x0767,0x0768,0x0769,
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // 768
0x0000,0x076a,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // 784
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x076b,0x0000,
0x0000,0x0000,0x0000,0x076d,0x0000,0x0000,0x0000,0x0000, // 800
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,0x076e,0x076f,0x0000,0x0000,0x0000, // 816
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // 832
0x0000,0x0000,0x0000,0x0000,0x0770,0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // 848
0x0000,0x0000,0x0000,0x0771,0x0000,0x0000,0x0000,0x0772,
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // 864
0x0000,0x0000,0x0000,0x06a0,0x06a1,0x06a2,0x06a3,0x06a4,
0x06a5,0x06a7,0x06a6,0x0000,0x0000,0x0000,0x0000,0x0000, // 880
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0c04,0x0c22,0x0c35,0x0c47,0x0c59,0x0c6c,0x0c7f,0x0c91, // 896
0x0ca3,0x0cb5,0x0773,0x0774,0x0775,0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,0x0000,0x0776,0x0000,0x0000,0x0000, // 912
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0c05,0x0c23,0x0c36,0x0c48,0x0c5a,0x0c6d,0x0c80,0x0c92, // 928
0x0ca4,0x0cb6,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x07e2,0x07e3,0x07e4,0x07e5,0x07e6,0x07e7,0x07e8,0x07e9, // 944
0x07ea,0x07eb,0x07ec,0x07ed,0x07ee,0x07ef,0x0000,0x07f0,
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // 960
0x0000,0x0000,0x0000,0x0000,0x0000,0x07de,0x0000,0x0000,
0x07dd,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // 976
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,0x0000,0x07df,0x07e0,0x0c06,0x0c24, // 992
0x0c37,0x0c49,0x0c5b,0x0c6e,0x0c81,0x0c93,0x0ca5,0x0cb7,
0x07e1,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // 1008
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0c07,0x0c25, // 1024
0x0c38,0x0c4a,0x0c5c,0x0c6f,0x0c82,0x0c94,0x0ca6,0x0cb8,
0x0000,0x0000,0x0000,0x0000,0x0c25,0x0c38,0x0c4a,0x0c5c, // 1040
0x0c02,0x0cd2,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0c08,0x0c26, // 1056
0x0c39,0x0c4b,0x0c5d,0x0c70,0x0c83,0x0c95,0x0ca7,0x0cb9,
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0c09,0x0c27, // 1072
0x0c3a,0x0c4c,0x0c5e,0x0c71,0x0c84,0x0c96,0x0ca8,0x0cba,
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0c0a,0x0c28, // 1088
0x0c3b,0x0c4d,0x0c5f,0x0c72,0x0c85,0x0c97,0x0ca9,0x0cbb,
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0c29, // 1104
0x0c3c,0x0c4e,0x0c60,0x0c73,0x0c86,0x0c98,0x0caa,0x0cbc,
0x0cc7,0x0cd8,0x0cdc,0x0000,0x0000,0x0000,0x0000,0x0000, // 1120
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0c0b,0x0c2a, // 1136
0x0c3d,0x0c4f,0x0c61,0x0c74,0x0c87,0x0c99,0x0cab,0x0cbd,
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0c0c,0x0c2b, // 1152
0x0c3e,0x0c50,0x0c62,0x0c75,0x0c88,0x0c9a,0x0cac,0x0cbe,
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0c0d,0x0c2c, // 1168
0x0c3f,0x0c51,0x0c63,0x0c76,0x0c89,0x0c9b,0x0cad,0x0cbf,
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // 1184
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0af9,
0x0c0e,0x0c2d,0x0c40,0x0c52,0x0c64,0x0c77,0x0c8a,0x0c9c, // 1200
0x0cae,0x0cc0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0c0f,0x0c2e,0x0c41,0x0c53,0x0c65,0x0c78,0x0c8b,0x0c9d, // 1216
0x0caf,0x0cc1,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // 1232
0x0000,0x0000,0x0000,0x07dc,0x0000,0x0000,0x0000,0x0000,
0x0e02,0x0e02,0x0e09,0x0e09,0x0e09,0x0e09,0x0e09,0x0e09, // 1248
0x0e0a,0x0e0a,0x0e1a,0x0e1a,0x0e1a,0x0e1a,0x0e1a,0x0e1a,
0x0e1a,0x0e1a,0x0e1a,0x0e1a,0x0e21,0x0e21,0x0e21,0x0e21, // 1264
0x0e21,0x0e21,0x0e21,0x0e21,0x0e21,0x0e21,0x0e23,0x0e23,
0x0e25,0x0e25,0x0e2c,0x0e2c,0x0e2c,0x0e2c,0x0e2c,0x0e2c, // 1280
0x0e2c,0x0e2c,0x0e2c,0x0e2c,0x0e32,0x0e32,0x0e32,0x0e32,
0x0e36,0x0e36,0x0e36,0x0e36,0x0e36,0x0e36,0x0e48,0x0e48, // 1296
0x0e48,0x0e48,0x0e48,0x0e48,0x0e48,0x0e48,0x0e51,0x0e51,
0x0e51,0x0e51,0x0e51,0x0e51,0x0e70,0x0e70,0x0e70,0x0e70, // 1312
0x0e70,0x0e70,0x0e70,0x0e70,0x0e7c,0x0e7c,0x0e7c,0x0e7c,
0x0e7c,0x0e7c,0x0e7c,0x0e7c,0x0e7e,0x0e7e,0x0e7e,0x0e7e, // 1328
0x0e8a,0x0e8a,0x0e8a,0x0e8a,0x0e8a,0x0e8a,0x0e8a,0x0e8a,
0x0e91,0x0e91,0x0e91,0x0e91,0x0e91,0x0e91,0x0e91,0x0e91, // 1344
0x0e91,0x0e91,0x0e99,0x0e99,0x0e99,0x0e99,0x0e99,0x0e99,
0x0e99,0x0e99,0x0e9f,0x0e9f,0x0e9f,0x0e9f,0x0e9f,0x0e9f, // 1360
0x0e9f,0x0e9f,0x0e9f,0x0e9f,0x0ea2,0x0ea2,0x0ea2,0x0ea2,
0x0ea4,0x0ea4,0x0ea4,0x0ea4,0x0ea4,0x0ea4,0x0ea4,0x0ea4, // 1376
0x0ea4,0x0ea4,0x0ea6,0x0ea6,0x0ea6,0x0ea6,0x0ea7,0x0ea7,
0x0ea9,0x0ea9,0x0ea9,0x0ea9,0x0ea9,0x0ea9,0x0e2c,0x0e99, // 1392
0x0ea4,0x0ea7,0x0e02,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0e02,0x0e02,0x0e02,0x0e02,0x0e02,0x0e02,0x0e02,0x0e02, // 1408
0x0e02,0x0e02,0x0e02,0x0e02,0x0e02,0x0e02,0x0e02,0x0e02,
0x0e02,0x0e02,0x0e02,0x0e02,0x0e02,0x0e02,0x0e02,0x0e02, // 1424
0x0e21,0x0e21,0x0e21,0x0e21,0x0e21,0x0e21,0x0e21,0x0e21,
0x0e21,0x0e21,0x0e21,0x0e21,0x0e21,0x0e21,0x0e21,0x0e21, // 1440
0x0e32,0x0e32,0x0e32,0x0e32,0x0e7c,0x0e7c,0x0e7c,0x0e7c,
0x0e7c,0x0e7c,0x0e7c,0x0e7c,0x0e7c,0x0e7c,0x0e7c,0x0e7c, // 1456
0x0e7c,0x0e7c,0x0e7c,0x0e7c,0x0e7c,0x0e7c,0x0e7c,0x0e7c,
0x0e7c,0x0e7c,0x0e7c,0x0e7c,0x0e9f,0x0e9f,0x0e9f,0x0e9f, // 1472
0x0e9f,0x0e9f,0x0e9f,0x0e9f,0x0e9f,0x0e9f,0x0e9f,0x0e9f,
0x0e9f,0x0e9f,0x0ea7,0x0ea7,0x0ea7,0x0ea7,0x0ea7,0x0ea7, // 1488
0x0ea7,0x0ea7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x070a,0x070b,0x070c,0x070d,0x070e,0x070f,0x0710,0x0711, // 1504
0x0712,0x0713,0x0714,0x0715,0x0000,0x0000,0x0000,0x0000,
0x0684,0x0685,0x0688,0x0689,0x068b,0x068c,0x0777,0x0778, // 1520
0x0779,0x077a,0x077b,0x077c,0x077d,0x077e,0x077f,0x0780,
0x0a0f,0x0a10,0x0a11,0x0a12,0x0a13,0x0a14,0x0a15,0x0686, // 1536
0x0717,0x0718,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0a16,0x0a17,0x0781,0x0782,0x0783,0x0784,0x0785,0x0786, // 1552
0x0787,0x0788,0x0789,0x0a18,0x078a,0x078b,0x078c,0x078d,
0x0a19,0x0a1a,0x0a1b,0x0687,0x0807,0x073f,0x0742,0x0000, // 1568
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0c03,0x0000,0x0000,0x0000,0x0c58,0x0c6a,0x0c7d,0x0c90, // 1584
0x0ca2,0x0cb4,0x0803,0x0682,0x0812,0x0727,0x072a,0x0e70,
0x0c03,0x0c21,0x0c33,0x0c46,0x0c58,0x0c6a,0x0c7d,0x0c90, // 1600
0x0ca2,0x0cb4,0x0803,0x0682,0x0812,0x0727,0x072a,0x0000,
0x0a1c,0x0a1d,0x0a1e,0x0a1f,0x0a20,0x0a21,0x0a22,0x0a23, // 1616
0x0a24,0x0a25,0x0a26,0x0a27,0x0afb,0x0000,0x0000,0x0000,
0x0e05,0x0e07,0x0e0a,0x0e0a,0x0e13,0x0e18,0x0e19,0x0e21, // 1632
0x0e92,0x0e23,0x0e25,0x0e2c,0x0e2c,0x0e2c,0x0e2c,0x0e2c,
0x0e32,0x0e32,0x0e48,0x0e48,0x0e49,0x0e70,0x0e71,0x0afa, // 1648
0x0e7e,0x0e7e,0x0e89,0x0e8a,0x0e8a,0x0e8a,0x0e8b,0x0e8c,
0x0e93,0x0e9a,0x0e9c,0x0ea3,0x0ea9,0x0ea9,0x0000,0x0000, // 1664
0x0ea9,0x0000,0x0e37,0x0e02,0x0e09,0x0e0a,0x0e21,0x0e21,
0x0e21,0x0e23,0x0e23,0x0e51,0x0e7c,0x0000,0x0000,0x0000, // 1680
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,0x0c16,0x0c1c,0x0c14,0x0c18,0x0c1a, // 1696
0x0c1e,0x0c13,0x0c1f,0x0c12,0x0c17,0x0c1b,0x0c20,0x0c21,
0x0c30,0x0c43,0x0c55,0x0c67,0x0c7a,0x0c8d,0x0c9f,0x0cb1, // 1712
0x0cc3,0x0cc8,0x0ccb,0x0ccd,0x0cd7,0x0cd9,0x0cda,0x0cdd,
0x0c30,0x0c43,0x0c55,0x0c67,0x0c7a,0x0c8d,0x0c9f,0x0cb1, // 1728
0x0cc3,0x0cc8,0x0ccb,0x0ccd,0x0cd7,0x0cd9,0x0cda,0x0cde,
0x0cdf,0x0ce0,0x0ce1,0x0000,0x0000,0x0000,0x0000,0x0000, // 1744
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0821,0x0822,0x0823,0x0824,0x0825,0x0826,0x0827,0x0828, // 1760
0x0829,0x082a,0x082b,0x082c,0x082d,0x082e,0x082f,0x0830,
0x0831,0x0832,0x0804,0x080c,0x0833,0x0808,0x0834,0x0809, // 1776
0x080a,0x080b,0x0835,0x0836,0x0837,0x0838,0x0cff,0x0839,
0x083a,0x083b,0x083c,0x083d,0x083e,0x083f,0x0840,0x0841, // 1792
0x0842,0x0843,0x0844,0x0845,0x0846,0x0847,0x0848,0x0849,
0x084a,0x084b,0x084c,0x084d,0x084e,0x084f,0x0850,0x0851, // 1808
0x0852,0x0853,0x0854,0x0855,0x0856,0x0857,0x0858,0x0859,
0x085a,0x085b,0x085c,0x085d,0x085e,0x085f,0x0860,0x0861, // 1824
0x0862,0x0863,0x0864,0x0865,0x0866,0x0867,0x0868,0x0869,
0x086a,0x086b,0x086c,0x086d,0x086e,0x086f,0x0870,0x0871, // 1840
0x0872,0x0873,0x0874,0x0875,0x0876,0x0877,0x0878,0x0879,
0x087a,0x087b,0x087c,0x087d,0x087e,0x087f,0x0880,0x0881, // 1856
0x0882,0x0883,0x0819,0x081b,0x0884,0x0885,0x0886,0x0887,
0x0888,0x0889,0x088a,0x088b,0x088c,0x088d,0x088e,0x088f, // 1872
0x0890,0x0891,0x080f,0x0815,0x0892,0x0893,0x0894,0x0895,
0x0896,0x0897,0x0898,0x0899,0x089a,0x089b,0x089c,0x089d, // 1888
0x089e,0x089f,0x08a0,0x08a1,0x08a2,0x08a3,0x08a4,0x08a5,
0x08a6,0x08a7,0x08a8,0x08a9,0x08aa,0x0803,0x0804,0x0806, // 1904
0x0808,0x080b,0x080a,0x0809,0x0812,0x0805,0x0803,0x0804,
0x0806,0x080b,0x08ab,0x08ac,0x08ad,0x08ae,0x08af,0x08b0, // 1920
0x08b1,0x08b2,0x08b3,0x08b4,0x08b5,0x08b6,0x08b7,0x08b8,
0x0810,0x0816,0x08b9,0x08ba,0x08bb,0x08bc,0x08bd,0x08be, // 1936
0x08bf,0x08c0,0x08c1,0x08c2,0x08c3,0x08c4,0x08c5,0x08c6,
0x08c7,0x08c8,0x08c9,0x08ca,0x08cb,0x08cc,0x08cd,0x08ce, // 1952
0x08cf,0x08d0,0x08d1,0x08d2,0x08d3,0x08d4,0x08d5,0x08d6,
0x08d7,0x08d8,0x08d9,0x08da,0x08db,0x08dc,0x08dd,0x08de, // 1968
0x08df,0x08e0,0x08e1,0x08e2,0x08e3,0x08e4,0x08e5,0x08e6,
0x08e7,0x08e8,0x08e9,0x08ea,0x08eb,0x08ec,0x08ed,0x08ee, // 1984
0x08ef,0x08f0,0x08f1,0x08f2,0x08f3,0x08f4,0x08f5,0x08f6,
0x08f7,0x08f8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // 2000
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x07b6,0x07b7,0x07b8,0x07b9,0x07ba,0x07bb,0x07bc,0x07bd, // 2016
0x07be,0x07bf,0x07c0,0x07c1,0x07c2,0x07c3,0x07c4,0x07c5,
0x07c6,0x07c7,0x07c8,0x07c9,0x07ca,0x07cb,0x07cc,0x07cd, // 2032
0x07ce,0x07cf,0x07d0,0x07d1,0x07d2,0x07d3,0x07d4,0x07d5,
0x07d6,0x07d7,0x0719,0x071a,0x07d8,0x0000,0x0000,0x0000, // 2048
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0aee,0x0aef,0x0af0,0x0af1,0x0af2,0x0af3,0x0af4,0x0af5, // 2064
0x0af6,0x0af7,0x0af8,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0c21,0x0c33,0x0c46,0x0c58,0x0c6a,0x0c7d,0x0c90,0x0ca2, // 2080
0x0cb4,0x0cc6,0x0cca,0x0ccc,0x0cce,0x0ccf,0x0cd0,0x0cd1,
0x0cd3,0x0cd4,0x0cd5,0x0cd6,0x0c21,0x0c33,0x0c46,0x0c58, // 2096
0x0c6a,0x0c7d,0x0c90,0x0ca2,0x0cb4,0x0cc6,0x0cca,0x0ccc,
0x0cce,0x0ccf,0x0cd0,0x0cd1,0x0cd3,0x0cd4,0x0cd5,0x0cd6, // 2112
0x0c21,0x0c33,0x0c46,0x0c58,0x0c6a,0x0c7d,0x0c90,0x0ca2,
0x0cb4,0x0cc6,0x0cca,0x0ccc,0x0cce,0x0ccf,0x0cd0,0x0cd1, // 2128
0x0cd3,0x0cd4,0x0cd5,0x0cd6,0x0e02,0x0e09,0x0e0a,0x0e1a,
0x0e21,0x0e23,0x0e25,0x0e2c,0x0e32,0x0e35,0x0e36,0x0e48, // 2144
0x0e51,0x0e70,0x0e7c,0x0e7e,0x0e89,0x0e8a,0x0e91,0x0e99,
0x0e9f,0x0ea2,0x0ea4,0x0ea6,0x0ea7,0x0ea9,0x0e02,0x0e09, // 2160
0x0e0a,0x0e1a,0x0e21,0x0e23,0x0e25,0x0e2c,0x0e32,0x0e35,
0x0e36,0x0e48,0x0e51,0x0e70,0x0e7c,0x0e7e,0x0e89,0x0e8a, // 2176
0x0e91,0x0e99,0x0e9f,0x0ea2,0x0ea4,0x0ea6,0x0ea7,0x0ea9,
0x0e02,0x0e09,0x0e0a,0x0e1a,0x0e21,0x0e23,0x0e25,0x0e2c, // 2192
0x0e32,0x0e35,0x0e36,0x0e48,0x0e51,0x0e70,0x0e7c,0x0e7e,
0x0e89,0x0e8a,0x0e91,0x0e99,0x0e9f,0x0ea2,0x0ea4,0x0ea6, // 2208
0x0ea7,0x0ea9,0x0c03,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0a2f,0x0a30,0x0a31,0x0a32,0x0a33,0x0a35,0x0a34,0x0a36, // 2224
0x0a37,0x0a38,0x0a39,0x0a3a,0x0a3b,0x0a3c,0x0a3d,0x0a3e,
0x0a3f,0x0a40,0x0a41,0x0a42,0x0000,0x0000,0x0000,0x0000, // 2240
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0a43,0x0a44,0x0a45,0x0a46,0x0a47,0x0a48,0x0a49,0x0a4a, // 2256
0x0a4b,0x0a4c,0x0a4d,0x0a4e,0x0a4f,0x0a50,0x0a51,0x0a52,
0x0a53,0x0a54,0x0a55,0x0a56,0x0a57,0x0a58,0x0a59,0x0a5a, // 2272
0x0a5b,0x0a5c,0x0a5d,0x0a5e,0x0a5f,0x0a60,0x0a61,0x0a62,
0x0a63,0x0a64,0x0a65,0x0a66,0x0a67,0x0a68,0x0a69,0x0a6a, // 2288
0x0a6b,0x0a6c,0x0a6d,0x0a6e,0x0a6f,0x0a70,0x0a71,0x0a72,
0x0a73,0x0a74,0x0a75,0x0a76,0x0a77,0x0a78,0x0a79,0x0a7a, // 2304
0x0a7b,0x0a7c,0x0a7d,0x0a7e,0x0a7f,0x0a80,0x0a81,0x0a82,
0x0a83,0x0a84,0x0a85,0x0a86,0x0a87,0x0a88,0x0a89,0x0a8a, // 2320
0x0a8b,0x0a8c,0x0a8d,0x0a8e,0x0a8f,0x0a90,0x0a91,0x0a92,
0x0000,0x0a93,0x0a94,0x0a95,0x0a96,0x0000,0x0a97,0x0a98, // 2336
0x0a99,0x0a9a,0x0000,0x0000,0x0a9b,0x0a9c,0x0a9d,0x0a9e,
0x0a9f,0x0aa0,0x0aa1,0x0aa2,0x0aa3,0x0aa4,0x0aa5,0x0aa6, // 2352
0x0aa7,0x0aa8,0x0aa9,0x0aaa,0x0aab,0x0aac,0x0aad,0x0aae,
0x0aaf,0x0ab0,0x0ab1,0x0ab2,0x0ab3,0x0ab4,0x0ab5,0x0ab6, // 2368
0x0000,0x0ab7,0x0abe,0x0ab9,0x0aba,0x0abb,0x0abc,0x0abd,
0x0ab8,0x0abf,0x0ac0,0x0ac1,0x0ac2,0x0ac3,0x0ac4,0x0ac5, // 2384
0x0ac6,0x0ac7,0x0ac8,0x0ac9,0x0aca,0x0acb,0x0acc,0x0acd,
0x0ace,0x0acf,0x0ad0,0x0ad1,0x0ad2,0x0ad3,0x0ad4,0x0ad5, // 2400
0x0ad6,0x0ad7,0x0ad8,0x0ad9,0x0000,0x0ada,0x0000,0x0adb,
0x0adc,0x0add,0x0ade,0x0000,0x0000,0x0000,0x0adf,0x0000, // 2416
0x0ae0,0x0ae1,0x0ae2,0x0ae3,0x0ae4,0x0ae5,0x0ae6,0x0000,
0x0000,0x0ae7,0x0ae8,0x0ae9,0x0aea,0x0aeb,0x0aec,0x0aed, // 2432
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0c21,0x0c33, // 2448
0x0c46,0x0c58,0x0c6a,0x0c7d,0x0c90,0x0ca2,0x0cb4,0x0cc6,
0x0c21,0x0c33,0x0c46,0x0c58,0x0c6a,0x0c7d,0x0c90,0x0ca2, // 2464
0x0cb4,0x0cc6,0x0c21,0x0c33,0x0c46,0x0c58,0x0c6a,0x0c7d,
0x0c90,0x0ca2,0x0cb4,0x0cc6,0x0000,0x0000,0x0000,0x0000, // 2480
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0702,0x0731,0x0734,0x07d9,0x0a2d,0x0000,0x07da,0x0000, // 2496
0x0793,0x0795,0x0797,0x0799,0x079b,0x079d,0x079f,0x07a1,
0x07a3,0x07a5,0x0a28,0x0a29,0x07a8,0x07ab,0x07ad,0x07ae, // 2512
0x07af,0x07b0,0x07b1,0x07b2,0x068d,0x07b3,0x07b4,0x07b5,
0x0a2a,0x0c32,0x0c45,0x0c57,0x0c69,0x0c7c,0x0c8f,0x0ca1, // 2528
0x0cb3,0x0cc5,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x068e,0x0000,0x0000,0x0000,0x0000,0x0000,0x0a2b,0x0000, // 2544
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0a2c,
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // 2560
0x0000,0x0000,0x0000,0x0a0e,0x0000,0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // 2576
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0a2e,
0x0e80,0x0e76,0x0e64,0x0e57,0x0e39,0x0e3a,0x0e58,0x0e28, // 2592
0x0e10,0x0e3b,0x0e81,0x0e77,0x0e65,0x0e66,0x0e5a,0x0e3c,
0x0e31,0x0e3d,0x0e5b,0x0e29,0x0e9b,0x0e67,0x0e5d,0x0e20, // 2608
0x0e3f,0x0e24,0x0e78,0x0e68,0x0e5e,0x0e14,0x0e40,0x0e60,
0x0e16,0x0e56,0x0e43,0x0e5f,0x0e15,0x0e52,0x0e42,0x0e54, // 2624
0x0e55,0x0e7f,0x0e44,0x0e62,0x0e2a,0x0e8e,0x0e8f,0x0e90,
0x0e86,0x0e79,0x0e69,0x0e63,0x0e87,0x0e7a,0x0e6a,0x0e6c, // 2640
0x0e46,0x0e6d,0x0e88,0x0e7b,0x0e6b,0x0e6e,0x0e47,0x0e6f,
0x0e38,0x0e53,0x0e06,0x0e08,0x0e11,0x0e12,0x0e0f,0x0e17, // 2656
0x0e1f,0x0e2b,0x0e2f,0x0e30,0x0e34,0x0e3e,0x0e41,0x0e45,
0x0e4d,0x0e4e,0x0e4f,0x0e50,0x0e59,0x0e5c,0x0e61,0x0e82, // 2672
0x0e83,0x0e84,0x0e85,0x0e94,0x0e95,0x0ea5,0x0000,0x0000,
0x0e23,0x0e23,0x0e23,0x0e23,0x0e23,0x0e96,0x0e91,0x0000, // 2688
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0738,0x068f,0x0690,0x078d,0x0792,0x0728,0x072b,0x074b, // 2704
0x074f,0x07a9,0x07ac,0x07a4,0x07a6,0x0798,0x079a,0x0794,
0x0796,0x079c,0x079e,0x07a0,0x07a2,0x0000,0x0000,0x0000, // 2720
0x0000,0x078e,0x078f,0x0790,0x0791,0x0745,0x0746,0x0747,
0x072e,0x0730,0x0732,0x0000,0x0739,0x0736,0x073b,0x071b, // 2736
0x068a,0x0726,0x0729,0x0749,0x074d,0x07a7,0x07aa,0x071e,
0x0724,0x072c,0x0802,0x0681,0x080d,0x0813,0x0811,0x0000, // 2752
0x0740,0x0720,0x0722,0x073d,0x0000,0x0000,0x0000,0x0000,
0x06a0,0x06a0,0x06a1,0x0000,0x06a2,0x0000,0x06a3,0x06a3, // 2768
0x06a4,0x06a4,0x06a5,0x06a5,0x0000,0x0000,0x06a6,0x06a6,
0x0000,0x071c,0x071d,0x071f,0x0721,0x0723,0x0725,0x0680, // 2784
0x0727,0x072a,0x072d,0x0803,0x072f,0x0682,0x0733,0x0735,
0x0e7e,0x0e89,0x0e8a,0x0e91,0x0e99,0x0e9f,0x0ea2,0x0ea4, // 2800
0x0ea6,0x0ea7,0x0ea9,0x074a,0x074c,0x074e,0x0750,0x0000,
0x0000,0x0734,0x079b,0x079d,0x0731,0x0a0e,0x0000,0x0000, // 2816
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0a02,0x0a03,0x0a08,0x0754,0x0752,0x0a05,0x0a25,0x0000, // 2832
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
};
private static short[] diacriticTableLevel1 = new short[256] {
0 ,16 ,32 ,48 ,64 ,80 ,96 ,112 ,128 ,144 ,160 ,176 ,192 ,208 ,224 ,128 , // 0
240 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,256 ,128 , // 16
272 ,288 ,304 ,128 ,320 ,128 ,336 ,352 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 , // 32
368 ,128 ,384 ,400 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 , // 48
128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 , // 64
128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 , // 80
128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 , // 96
128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 , // 112
128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 , // 128
128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 , // 144
128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 , // 160
128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 , // 176
128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 , // 192
128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 , // 208
128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 , // 224
128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,416 ,128 ,128 ,432 ,448 , // 240
};
private static short[] diacriticTableLevel2 = new short[464] {
0 ,16 ,16 ,16 ,16 ,16 ,16 ,16 ,16 ,16 ,32 ,32 ,48 ,64 ,48 ,80 , // 0
96 ,112 ,128 ,144 ,160 ,176 ,192 ,208 ,224 ,240 ,256 ,272 ,288 ,304 ,320 ,336 , // 16
352 ,368 ,384 ,384 ,384 ,400 ,416 ,432 ,448 ,464 ,480 ,496 ,512 ,528 ,544 ,384 , // 32
384 ,384 ,384 ,384 ,384 ,384 ,384 ,560 ,576 ,384 ,384 ,384 ,384 ,384 ,384 ,384 , // 48
384 ,384 ,384 ,384 ,384 ,384 ,384 ,384 ,592 ,384 ,384 ,384 ,384 ,384 ,384 ,384 , // 64
384 ,384 ,384 ,384 ,384 ,608 ,384 ,384 ,624 ,384 ,384 ,640 ,656 ,384 ,384 ,672 , // 80
688 ,704 ,384 ,384 ,608 ,720 ,736 ,384 ,384 ,384 ,384 ,384 ,384 ,752 ,384 ,768 , // 96
784 ,384 ,384 ,384 ,384 ,384 ,384 ,384 ,384 ,384 ,384 ,384 ,384 ,384 ,384 ,384 , // 112
384 ,384 ,384 ,384 ,384 ,384 ,384 ,384 ,384 ,384 ,384 ,384 ,384 ,384 ,384 ,384 , // 128
384 ,384 ,384 ,800 ,384 ,816 ,832 ,816 ,384 ,384 ,384 ,384 ,384 ,384 ,848 ,864 , // 144
384 ,384 ,384 ,384 ,384 ,384 ,880 ,384 ,384 ,384 ,384 ,384 ,384 ,384 ,896 ,384 , // 160
384 ,384 ,384 ,384 ,384 ,384 ,912 ,384 ,384 ,384 ,384 ,384 ,384 ,384 ,928 ,944 , // 176
384 ,384 ,384 ,384 ,384 ,384 ,960 ,384 ,384 ,384 ,384 ,384 ,384 ,384 ,976 ,384 , // 192
384 ,384 ,384 ,384 ,384 ,384 ,992 ,384 ,384 ,384 ,384 ,384 ,384 ,384 ,384 ,384 , // 208
384 ,384 ,384 ,1008,384 ,1024,384 ,384 ,384 ,384 ,384 ,384 ,384 ,1040,384 ,384 , // 224
384 ,384 ,384 ,384 ,384 ,384 ,384 ,384 ,384 ,384 ,384 ,384 ,384 ,384 ,384 ,1056, // 240
1072,1088,1104,1120,1136,1152,1168,1184,1200,1216,1232,1248,1264,1280,1296,1312, // 256
1328,16 ,1344,16 ,1360,384 ,384 ,1376,1392,384 ,1408,384 ,384 ,384 ,384 ,384 , // 272
1424,1440,1456,1472,384 ,1488,1504,1504,1520,384 ,384 ,384 ,384 ,384 ,384 ,384 , // 288
16 ,16 ,16 ,16 ,16 ,16 ,1536,16 ,16 ,1552,1568,16 ,16 ,16 ,16 ,1584, // 304
16 ,16 ,1600,384 ,1616,384 ,1632,1648,1664,1680,1696,1712,1632,1632,1728,384 , // 320
16 ,1744,16 ,16 ,16 ,16 ,16 ,384 ,384 ,384 ,384 ,384 ,384 ,384 ,384 ,384 , // 336
1760,16 ,1776,16 ,1792,1808,1824,1840,1632,1856,384 ,384 ,384 ,384 ,384 ,384 , // 352
1872,16 ,1888,1904,384 ,384 ,384 ,384 ,384 ,384 ,384 ,384 ,384 ,384 ,384 ,1056, // 368
384 ,384 ,384 ,384 ,384 ,384 ,384 ,1008,384 ,384 ,384 ,384 ,384 ,384 ,384 ,384 , // 384
384 ,384 ,384 ,384 ,384 ,384 ,384 ,384 ,16 ,16 ,16 ,16 ,16 ,1920,384 ,384 , // 400
1936,384 ,384 ,384 ,384 ,384 ,384 ,384 ,384 ,384 ,384 ,384 ,384 ,384 ,384 ,384 , // 416
384 ,384 ,384 ,16 ,1952,1968,1984,2000,384 ,384 ,384 ,384 ,384 ,384 ,384 ,384 , // 432
0 ,16 ,16 ,16 ,16 ,1392,2016,384 ,384 ,384 ,384 ,384 ,384 ,384 ,1936,384 , // 448
};
private static byte[] diacriticTableLevel3 = new byte[2032] {
0x00,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02, // 0
0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02, // 16
0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x03,0x02,0x02,0x02,0x02,0x02, // 32
0x0f,0x0e,0x12,0x19,0x13,0x1a,0x02,0x1c,0x0f,0x0e,0x12,0x13,0x0f,0x0e,0x12,0x13, // 48
0x68,0x19,0x0f,0x0e,0x12,0x19,0x13,0x02,0x21,0x0f,0x0e,0x12,0x13,0x0e,0x02,0x02, // 64
0x68,0x19,0x0f,0x0e,0x12,0x19,0x13,0x02,0x21,0x0f,0x0e,0x12,0x13,0x0e,0x02,0x13, // 80
0x17,0x17,0x15,0x15,0x1b,0x1b,0x0e,0x0e,0x12,0x12,0x10,0x10,0x14,0x14,0x14,0x14, // 96
0x1e,0x1e,0x17,0x17,0x15,0x15,0x10,0x10,0x1b,0x1b,0x14,0x14,0x12,0x12,0x15,0x15, // 112
0x10,0x10,0x1c,0x1c,0x12,0x12,0x1e,0x1e,0x19,0x19,0x17,0x17,0x15,0x15,0x1b,0x1b, // 128
0x10,0x03,0x02,0x02,0x12,0x12,0x1c,0x1c,0x03,0x0e,0x0e,0x1c,0x1c,0x14,0x14,0x11, // 144
0x11,0x1f,0x1f,0x0e,0x0e,0x1c,0x1c,0x14,0x14,0x48,0x02,0x02,0x17,0x17,0x15,0x15, // 160
0x1d,0x1d,0x02,0x02,0x0e,0x0e,0x1c,0x1c,0x14,0x14,0x0e,0x0e,0x12,0x12,0x1c,0x1c, // 176
0x14,0x14,0x1c,0x1c,0x14,0x14,0x1e,0x1e,0x19,0x19,0x17,0x17,0x15,0x15,0x1a,0x1a, // 192
0x1d,0x1d,0x1b,0x1b,0x12,0x12,0x12,0x12,0x13,0x0e,0x0e,0x10,0x10,0x14,0x14,0x02, // 208
0x1e,0x43,0x68,0x68,0x87,0x87,0x7d,0x43,0x43,0x04,0x43,0x1e,0x1e,0x7c,0x7d,0x7e, // 224
0x7b,0x43,0x7b,0x43,0x7b,0x7b,0x7b,0x1e,0x43,0x43,0x1e,0x20,0x7b,0x43,0x7b,0x20, // 240
0x52,0x52,0x7c,0x7c,0x43,0x43,0x7b,0x87,0x87,0x7c,0x7f,0x57,0x43,0x43,0x59,0x52, // 256
0x52,0x7b,0x7b,0x43,0x43,0x1e,0x1e,0x02,0x7c,0x7c,0x7d,0x03,0x03,0x03,0x02,0x7b, // 272
0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x14,0x14,0x14, // 288
0x14,0x14,0x14,0x14,0x14,0x28,0x28,0x1f,0x1f,0x25,0x25,0x20,0x20,0x7d,0x28,0x28, // 304
0x25,0x25,0x17,0x17,0x1e,0x1e,0x14,0x14,0x14,0x14,0x1b,0x1b,0x30,0x30,0x14,0x14, // 320
0x14,0x02,0x02,0x02,0x0e,0x0e,0x00,0x00,0x00,0x00,0x26,0x26,0x0e,0x0e,0x2b,0x2b, // 336
0x44,0x44,0x46,0x46,0x44,0x44,0x46,0x46,0x44,0x44,0x46,0x46,0x44,0x44,0x46,0x46, // 352
0x44,0x44,0x46,0x46,0x44,0x44,0x46,0x46,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 368
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 384
0x7b,0x7c,0x7d,0x43,0x7b,0x7c,0x59,0x43,0x80,0x7e,0x7f,0x7b,0x81,0x82,0x83,0x1e, // 400
0x43,0x7d,0x02,0x7b,0x7c,0x7c,0x43,0x43,0x1e,0x7b,0x02,0x19,0x7b,0x59,0x7c,0x7b, // 416
0x7c,0x43,0x43,0x59,0x02,0x20,0x7b,0x7e,0x7b,0x7b,0x7c,0x7d,0x7e,0x43,0x7f,0x80, // 432
0x02,0x7b,0x43,0x7c,0x43,0x84,0x85,0x7b,0x59,0x1e,0x7b,0x7b,0x7c,0x7c,0x7b,0x02, // 448
0x59,0x7e,0x02,0x7e,0x03,0x04,0x05,0x88,0x02,0x02,0x86,0x43,0x02,0x7b,0x7b,0x02, // 464
0x43,0x06,0x0b,0x7b,0x7b,0x7c,0x7b,0x7c,0x7d,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 480
0x7e,0x7f,0x7e,0x81,0x82,0x83,0x84,0x7e,0x7e,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 496
0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x02,0x00,0x03,0x03,0x03,0x00,0x00,0x00,0x00, // 512
0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x02,0x02,0x02,0x02,0x02,0x00,0x00, // 528
0x7e,0x7e,0x7e,0x7e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 544
0x00,0x00,0x00,0x00,0x02,0x02,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x02,0x00, // 560
0x00,0x00,0x00,0x00,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 576
0x00,0x00,0x37,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 592
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x02,0x02,0x02,0x02, // 608
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00, // 624
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00, // 640
0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 656
0x00,0x00,0x00,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 672
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00, // 688
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x02, // 704
0x02,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 720
0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x02,0x02,0x02,0x00,0x00,0x00, // 736
0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 752
0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x00,0x00,0x00,0x00,0x00,0x00, // 768
0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x00,0x02, // 784
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00, // 800
0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 816
0x00,0x00,0x00,0x00,0x02,0x02,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a, // 832
0x00,0x00,0x00,0x00,0x00,0x00,0x3b,0x3b,0x3b,0x3b,0x3b,0x3b,0x3b,0x3b,0x3b,0x3b, // 848
0x00,0x00,0x00,0x00,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x00,0x00,0x00,0x00,0x00,0x00, // 864
0x00,0x00,0x00,0x00,0x00,0x00,0x3d,0x3d,0x3d,0x3d,0x3d,0x3d,0x3d,0x3d,0x3d,0x3d, // 880
0x00,0x00,0x00,0x00,0x00,0x00,0x3e,0x3e,0x3e,0x3e,0x3e,0x3e,0x3e,0x3e,0x3e,0x3e, // 896
0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f, // 912
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40, // 928
0x40,0x40,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 944
0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41, // 960
0x00,0x00,0x00,0x00,0x00,0x00,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42, // 976
0x00,0x00,0x00,0x00,0x00,0x00,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43, // 992
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02, // 1008
0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x00,0x00,0x00,0x00,0x00,0x00, // 1024
0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x00,0x00,0x00,0x00,0x00,0x00, // 1040
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00, // 1056
0x5a,0x5a,0x10,0x10,0x58,0x58,0x55,0x55,0x28,0x28,0x10,0x10,0x58,0x58,0x55,0x55, // 1072
0x1c,0x1c,0x60,0x60,0x24,0x24,0x23,0x23,0x60,0x60,0x63,0x63,0x2f,0x2f,0x10,0x10, // 1088
0x17,0x17,0x10,0x10,0x58,0x58,0x13,0x13,0x1c,0x1c,0x61,0x61,0x63,0x63,0x1f,0x1f, // 1104
0x0e,0x0e,0x58,0x58,0x55,0x55,0x58,0x58,0x6e,0x6e,0x55,0x55,0x60,0x60,0x0e,0x0e, // 1120
0x10,0x10,0x58,0x58,0x10,0x10,0x58,0x58,0x55,0x55,0x60,0x60,0x25,0x25,0x2a,0x2a, // 1136
0x24,0x24,0x23,0x23,0x0e,0x0e,0x10,0x10,0x10,0x10,0x58,0x58,0x6e,0x6e,0x55,0x55, // 1152
0x10,0x10,0x58,0x58,0x1d,0x1d,0x22,0x22,0x68,0x68,0x10,0x10,0x58,0x58,0x55,0x55, // 1168
0x60,0x60,0x59,0x59,0x63,0x63,0x5a,0x5a,0x25,0x25,0x28,0x28,0x19,0x19,0x58,0x58, // 1184
0x0f,0x0f,0x0e,0x0e,0x13,0x13,0x10,0x10,0x58,0x58,0x10,0x10,0x13,0x13,0x10,0x10, // 1200
0x12,0x12,0x58,0x58,0x55,0x55,0x55,0x13,0x1a,0x1a,0x69,0x00,0x00,0x00,0x00,0x00, // 1216
0x59,0x59,0x43,0x43,0x1e,0x1e,0x1f,0x1f,0x55,0x55,0x29,0x29,0x6a,0x6a,0x21,0x21, // 1232
0x22,0x22,0x58,0x58,0x2c,0x2c,0x6d,0x6d,0x58,0x58,0x43,0x43,0x19,0x19,0x1e,0x1e, // 1248
0x1f,0x1f,0x55,0x55,0x29,0x29,0x6a,0x6a,0x43,0x43,0x58,0x58,0x58,0x58,0x43,0x43, // 1264
0x1e,0x1e,0x1f,0x1f,0x55,0x55,0x29,0x29,0x6a,0x6a,0x60,0x60,0x61,0x61,0x95,0x95, // 1280
0x69,0x69,0xaa,0xaa,0x58,0x58,0x43,0x43,0x60,0x60,0x61,0x61,0x95,0x95,0x69,0x69, // 1296
0xaa,0xaa,0x0f,0x0f,0x58,0x58,0x44,0x44,0x19,0x19,0x00,0x00,0x00,0x00,0x00,0x00, // 1312
0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x00,0x00,0x00,0x00, // 1328
0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x00, // 1344
0x02,0x02,0x02,0x02,0x02,0x1c,0x1c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 1360
0x02,0x00,0x00,0x00,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02, // 1376
0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x00, // 1392
0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x00,0x00,0x00, // 1408
0x02,0x02,0x03,0x04,0x02,0x02,0x02,0x64,0x02,0x04,0x03,0x05,0x04,0x03,0x03,0x68, // 1424
0x04,0x05,0x04,0x04,0x02,0x03,0x02,0x02,0x04,0x03,0x03,0x04,0x05,0x03,0x02,0x02, // 1440
0x02,0x02,0x02,0x02,0x03,0x63,0x00,0x00,0x05,0x00,0x02,0x1a,0x04,0x05,0x05,0x04, // 1456
0x04,0x05,0x03,0x04,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 1472
0x00,0x00,0x00,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x03, // 1488
0x47,0x47,0x47,0x47,0x47,0x47,0x47,0x47,0x47,0x47,0x47,0x47,0x47,0x47,0x47,0x47, // 1504
0x47,0x47,0x47,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 1520
0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x03,0x03,0x02,0x02,0x02,0x02, // 1536
0x02,0x02,0x02,0x02,0x02,0xee,0xee,0xee,0xee,0xee,0xee,0xee,0xee,0xee,0xef,0xef, // 1552
0xef,0xef,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02, // 1568
0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 1584
0x02,0x02,0x02,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 1600
0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x00,0x00,0x00,0x00,0x00, // 1616
0xee,0xee,0xee,0xee,0xee,0xee,0xee,0xee,0xee,0xee,0xee,0xee,0xee,0xee,0xee,0xee, // 1632
0xee,0xee,0xee,0xee,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3, // 1648
0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf4,0xf4,0xf4,0xf4,0xf4,0xf4,0xf4,0xf4, // 1664
0xf4,0xf4,0xf4,0xf4,0xf4,0xf4,0xf4,0xf4,0xf4,0xf4,0xf4,0xf4,0xf3,0xf3,0xf3,0xf3, // 1680
0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3, // 1696
0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xee,0xee,0xee,0xee,0xee,0xee,0xee,0xee,0xee,0xee, // 1712
0xee,0xee,0xee,0xee,0xee,0xee,0xee,0xee,0xee,0xee,0xee,0x00,0x00,0x00,0x00,0x00, // 1728
0x02,0x02,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 1744
0x00,0x02,0x02,0x02,0x02,0x00,0x02,0x02,0x02,0x02,0x00,0x00,0x02,0x02,0x02,0x02, // 1760
0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x00,0x02,0x02,0x02,0x02,0x02,0x02,0x02, // 1776
0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x00,0x02,0x00,0x02, // 1792
0x02,0x02,0x02,0x00,0x00,0x00,0x02,0x00,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x00, // 1808
0x00,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 1824
0x00,0x00,0x00,0x00,0x00,0x00,0xee,0xee,0xee,0xee,0xee,0xee,0xee,0xee,0xee,0xee, // 1840
0xee,0xee,0xee,0xee,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 1856
0x02,0x02,0x02,0x02,0x02,0x00,0x02,0x00,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02, // 1872
0x02,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x00,0x00,0x00,0x00,0x00,0x00, // 1888
0x02,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02, // 1904
0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x00,0x00, // 1920
0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 1936
0x02,0x02,0x02,0x02,0x02,0x00,0x00,0x00,0x00,0x02,0x02,0x02,0x02,0x02,0x02,0x02, // 1952
0x02,0x02,0x02,0x00,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02, // 1968
0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x00,0x02,0x02,0x02,0x02,0x00,0x00,0x00,0x00, // 1984
0x02,0x02,0x02,0x00,0x02,0x00,0x02,0x02,0x02,0x02,0x02,0x02,0x00,0x00,0x02,0x02, // 2000
0x00,0x02,0x02,0x02,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 2016
};
private static short[] caseTableLevel1 = new short[256] {
0 ,16 ,32 ,48 ,64 ,80 ,96 ,112 ,128 ,144 ,160 ,176 ,160 ,192 ,208 ,128 , // 0
224 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,240 ,128 , // 16
256 ,272 ,288 ,128 ,304 ,128 ,320 ,336 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 , // 32
352 ,128 ,368 ,384 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 , // 48
128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 , // 64
128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 , // 80
128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 , // 96
128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 , // 112
128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 , // 128
128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 , // 144
128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 , // 160
128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 , // 176
128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 , // 192
128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 , // 208
128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 , // 224
128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,400 ,128 ,128 ,416 ,432 , // 240
};
private static short[] caseTableLevel2 = new short[448] {
0 ,16 ,16 ,16 ,32 ,48 ,16 ,16 ,16 ,16 ,64 ,80 ,96 ,112 ,16 ,16 , // 0
128 ,128 ,128 ,144 ,160 ,128 ,128 ,176 ,192 ,208 ,224 ,240 ,256 ,272 ,128 ,288 , // 16
128 ,304 ,320 ,320 ,320 ,16 ,336 ,352 ,368 ,384 ,400 ,416 ,432 ,448 ,464 ,320 , // 32
320 ,320 ,320 ,320 ,320 ,320 ,320 ,480 ,496 ,320 ,320 ,320 ,320 ,320 ,320 ,320 , // 48
320 ,320 ,320 ,320 ,320 ,320 ,320 ,320 ,512 ,320 ,320 ,320 ,320 ,320 ,320 ,320 , // 64
320 ,320 ,320 ,320 ,320 ,528 ,320 ,320 ,544 ,320 ,320 ,560 ,576 ,320 ,320 ,592 , // 80
608 ,624 ,320 ,320 ,528 ,640 ,656 ,320 ,320 ,320 ,320 ,320 ,320 ,672 ,320 ,688 , // 96
704 ,320 ,320 ,320 ,320 ,320 ,320 ,320 ,320 ,320 ,320 ,320 ,320 ,320 ,320 ,320 , // 112
320 ,320 ,320 ,320 ,320 ,320 ,320 ,320 ,320 ,320 ,320 ,320 ,320 ,320 ,320 ,320 , // 128
320 ,320 ,320 ,720 ,320 ,736 ,752 ,736 ,320 ,320 ,320 ,320 ,320 ,320 ,768 ,784 , // 144
320 ,320 ,320 ,320 ,320 ,320 ,768 ,320 ,320 ,320 ,320 ,320 ,320 ,320 ,768 ,320 , // 160
320 ,320 ,320 ,320 ,320 ,320 ,768 ,320 ,320 ,320 ,320 ,320 ,320 ,320 ,800 ,640 , // 176
320 ,320 ,320 ,320 ,320 ,320 ,768 ,320 ,320 ,320 ,320 ,320 ,320 ,320 ,320 ,320 , // 192
320 ,320 ,320 ,816 ,320 ,688 ,320 ,320 ,320 ,320 ,320 ,320 ,320 ,688 ,320 ,320 , // 208
320 ,320 ,320 ,320 ,320 ,320 ,320 ,320 ,320 ,320 ,320 ,320 ,320 ,320 ,320 ,832 , // 224
128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,128 ,848 ,128 ,128 ,128 ,128 ,128 ,864 , // 240
880 ,16 ,688 ,16 ,896 ,320 ,320 ,912 ,928 ,320 ,656 ,320 ,320 ,320 ,320 ,320 , // 256
944 ,960 ,976 ,992 ,320 ,1008,96 ,16 ,1024,320 ,320 ,320 ,320 ,320 ,320 ,320 , // 272
16 ,16 ,16 ,16 ,16 ,16 ,16 ,16 ,16 ,16 ,16 ,16 ,16 ,16 ,16 ,1040, // 288
16 ,16 ,1056,320 ,1072,320 ,16 ,16 ,16 ,16 ,16 ,1088,96 ,16 ,1072,320 , // 304
16 ,464 ,16 ,16 ,16 ,16 ,16 ,320 ,320 ,320 ,320 ,320 ,320 ,320 ,320 ,320 , // 320
1104,16 ,1120,16 ,1136,1152,1168,1184,1200,1216,320 ,320 ,320 ,320 ,320 ,320 , // 336
1232,16 ,688 ,1248,320 ,320 ,320 ,320 ,320 ,320 ,320 ,320 ,320 ,320 ,320 ,1264, // 352
320 ,320 ,320 ,320 ,320 ,320 ,320 ,816 ,320 ,320 ,320 ,320 ,320 ,320 ,320 ,320 , // 368
320 ,320 ,320 ,320 ,320 ,320 ,320 ,320 ,16 ,16 ,16 ,16 ,16 ,1280,320 ,320 , // 384
896 ,320 ,320 ,320 ,320 ,320 ,320 ,320 ,320 ,320 ,320 ,320 ,320 ,320 ,320 ,320 , // 400
320 ,320 ,320 ,16 ,1296,1312,1328,1344,320 ,320 ,320 ,320 ,320 ,320 ,320 ,320 , // 416
1360,1376,1392,1408,1376,1424,1440,320 ,320 ,320 ,320 ,320 ,320 ,320 ,1456,320 , // 432
};
private static byte[] caseTableLevel3 = new byte[1472] {
0x00,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02, // 0
0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02, // 16
0x02,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, // 32
0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x02,0x02,0x02,0x02,0x02, // 48
0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x0e,0x02,0x02,0x02,0x02,0x02, // 64
0x02,0x02,0x0e,0x0e,0x02,0x02,0x02,0x02,0x02,0x0e,0x0e,0x02,0x02,0x02,0x02,0x02, // 80
0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, // 96
0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x02,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x02, // 112
0x12,0x02,0x12,0x02,0x12,0x02,0x12,0x02,0x12,0x02,0x12,0x02,0x12,0x02,0x12,0x02, // 128
0x12,0x02,0x12,0x02,0x12,0x02,0x12,0x02,0x02,0x12,0x02,0x12,0x02,0x12,0x02,0x12, // 144
0x02,0x12,0x02,0x12,0x02,0x12,0x02,0x12,0x02,0x02,0x12,0x02,0x12,0x02,0x12,0x02, // 160
0x12,0x02,0x12,0x02,0x12,0x02,0x12,0x02,0x12,0x12,0x02,0x12,0x02,0x12,0x02,0x02, // 176
0x02,0x12,0x12,0x02,0x12,0x02,0x12,0x12,0x02,0x12,0x12,0x12,0x02,0x02,0x12,0x12, // 192
0x12,0x12,0x02,0x12,0x12,0x02,0x12,0x12,0x12,0x02,0x02,0x02,0x12,0x12,0x02,0x12, // 208
0x12,0x02,0x12,0x02,0x12,0x02,0x12,0x12,0x02,0x12,0x02,0x02,0x12,0x02,0x12,0x12, // 224
0x02,0x12,0x12,0x12,0x02,0x12,0x02,0x12,0x12,0x02,0x02,0x02,0x12,0x02,0x02,0x02, // 240
0x02,0x02,0x02,0x02,0x12,0x12,0x02,0x12,0x12,0x02,0x12,0x12,0x02,0x12,0x02,0x12, // 256
0x02,0x12,0x02,0x12,0x02,0x12,0x02,0x12,0x02,0x12,0x02,0x12,0x02,0x02,0x12,0x02, // 272
0x02,0x12,0x12,0x02,0x12,0x02,0x00,0x00,0x00,0x00,0x12,0x02,0x12,0x02,0x12,0x02, // 288
0x12,0x02,0x12,0x02,0x12,0x02,0x12,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 304
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 320
0x02,0x02,0x0a,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x0a,0x02,0x02,0x02,0x02,0x02, // 336
0x02,0x02,0x02,0x02,0x0a,0x02,0x0a,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02, // 352
0x0a,0x0a,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x0a, // 368
0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x0a,0x02,0x0a,0x0a,0x02,0x02,0x0a, // 384
0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 400
0x02,0x02,0x02,0x02,0x02,0x02,0x0a,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 416
0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x02,0x00,0x02,0x02,0x02,0x00,0x00,0x00,0x00, // 432
0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x02,0x02,0x02,0x02,0x02,0x00,0x00, // 448
0x02,0x02,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 464
0x00,0x00,0x00,0x00,0x02,0x02,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x02,0x00, // 480
0x00,0x00,0x00,0x00,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 496
0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 512
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x02,0x02,0x02,0x02, // 528
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00, // 544
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00, // 560
0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 576
0x00,0x00,0x00,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 592
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00, // 608
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x02, // 624
0x02,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 640
0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x00,0x00,0x00, // 656
0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 672
0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x00, // 688
0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x00,0x02, // 704
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00, // 720
0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 736
0x00,0x00,0x00,0x00,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02, // 752
0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02, // 768
0x00,0x00,0x00,0x00,0x02,0x02,0x02,0x02,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x00, // 784
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02, // 800
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02, // 816
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00, // 832
0x12,0x02,0x12,0x02,0x12,0x02,0x02,0x02,0x02,0x02,0x02,0x00,0x00,0x00,0x00,0x00, // 848
0x12,0x02,0x12,0x02,0x12,0x02,0x12,0x02,0x12,0x02,0x00,0x00,0x00,0x00,0x00,0x00, // 864
0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x00,0x00,0x00,0x00, // 880
0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 896
0x0e,0x00,0x00,0x00,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e, // 912
0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x00, // 928
0x02,0x02,0x12,0x12,0x1a,0x02,0x02,0x12,0x12,0x12,0x02,0x12,0x12,0x12,0x02,0x02, // 944
0x12,0x12,0x12,0x02,0x02,0x12,0x12,0x02,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, // 960
0x12,0x12,0x12,0x12,0x12,0x12,0x00,0x00,0x12,0x00,0x12,0x1a,0x12,0x12,0x02,0x02, // 976
0x12,0x12,0x12,0x12,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 992
0x00,0x00,0x00,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02, // 1008
0x02,0x12,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 1024
0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 1040
0x02,0x02,0x02,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 1056
0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x00,0x00,0x00,0x00,0x00, // 1072
0x02,0x02,0x02,0x02,0x02,0x02,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, // 1088
0x00,0x02,0x02,0x02,0x02,0x00,0x02,0x02,0x02,0x02,0x00,0x00,0x02,0x02,0x02,0x02, // 1104
0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x00,0x02,0x02,0x02,0x02,0x02,0x02,0x02, // 1120
0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x00,0x02,0x00,0x02, // 1136
0x02,0x02,0x02,0x00,0x00,0x00,0x02,0x00,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x00, // 1152
0x00,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 1168
0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06, // 1184
0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e, // 1200
0x0e,0x0e,0x0e,0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 1216
0x03,0x03,0x03,0x02,0x02,0x00,0x02,0x00,0x02,0x02,0x02,0x02,0x03,0x03,0x02,0x02, // 1232
0x02,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02, // 1248
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00, // 1264
0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x00,0x00, // 1280
0x02,0x02,0x0c,0x02,0x02,0x00,0x00,0x00,0x00,0x02,0x02,0x02,0x02,0x02,0x02,0x02, // 1296
0x02,0x02,0x02,0x00,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02, // 1312
0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x00,0x02,0x02,0x02,0x02,0x00,0x00,0x00,0x00, // 1328
0x02,0x02,0x02,0x00,0x02,0x00,0x02,0x02,0x02,0x02,0x02,0x02,0x00,0x00,0x02,0x02, // 1344
0x00,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03, // 1360
0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03, // 1376
0x03,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, // 1392
0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x03,0x03,0x03,0x03,0x03, // 1408
0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x00, // 1424
0x00,0x02,0x02,0x02,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 1440
0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 1456
};
}
}