Files
2026-06-04 11:42:34 +02:00

2417 lines
64 KiB
C#

using System;
using System.Globalization;
namespace Mono.Globalization.Unicode
{
// Token: 0x0200008A RID: 138
internal class SimpleCollator
{
// Token: 0x060007D7 RID: 2007 RVA: 0x00019DC4 File Offset: 0x00017FC4
public SimpleCollator(CultureInfo culture)
{
this.lcid = culture.LCID;
this.textInfo = culture.TextInfo;
this.SetCJKTable(culture, ref this.cjkIndexer, ref this.cjkCatTable, ref this.cjkLv1Table, ref this.cjkLv2Indexer, ref this.cjkLv2Table);
TailoringInfo tailoringInfo = null;
CultureInfo cultureInfo = culture;
while (cultureInfo.LCID != 127)
{
tailoringInfo = MSCompatUnicodeTable.GetTailoringInfo(cultureInfo.LCID);
if (tailoringInfo != null)
{
break;
}
cultureInfo = cultureInfo.Parent;
}
if (tailoringInfo == null)
{
tailoringInfo = MSCompatUnicodeTable.GetTailoringInfo(127);
}
this.frenchSort = tailoringInfo.FrenchSort;
MSCompatUnicodeTable.BuildTailoringTables(culture, tailoringInfo, ref this.contractions, ref this.level2Maps);
this.unsafeFlags = new byte[96];
foreach (Contraction contraction in this.contractions)
{
if (contraction.Source.Length > 1)
{
foreach (char c in contraction.Source)
{
byte[] array2 = this.unsafeFlags;
char c2 = c / '\b';
array2[(int)c2] = array2[(int)c2] | (byte)(1 << (int)(c & '\a'));
}
}
}
if (this.lcid != 127)
{
foreach (Contraction contraction2 in SimpleCollator.invariant.contractions)
{
if (contraction2.Source.Length > 1)
{
foreach (char c3 in contraction2.Source)
{
byte[] array4 = this.unsafeFlags;
char c4 = c3 / '\b';
array4[(int)c4] = array4[(int)c4] | (byte)(1 << (int)(c3 & '\a'));
}
}
}
}
}
// Token: 0x060007D9 RID: 2009 RVA: 0x00019FC4 File Offset: 0x000181C4
private unsafe void SetCJKTable(CultureInfo culture, ref CodePointIndexer cjkIndexer, ref byte* catTable, ref byte* lv1Table, ref CodePointIndexer lv2Indexer, ref byte* lv2Table)
{
string name = SimpleCollator.GetNeutralCulture(culture).Name;
MSCompatUnicodeTable.FillCJK(name, ref cjkIndexer, ref catTable, ref lv1Table, ref lv2Indexer, ref lv2Table);
}
// Token: 0x060007DA RID: 2010 RVA: 0x00019FEC File Offset: 0x000181EC
private static CultureInfo GetNeutralCulture(CultureInfo info)
{
CultureInfo cultureInfo = info;
while (cultureInfo.Parent != null && cultureInfo.Parent.LCID != 127)
{
cultureInfo = cultureInfo.Parent;
}
return cultureInfo;
}
// Token: 0x060007DB RID: 2011 RVA: 0x0001A028 File Offset: 0x00018228
private unsafe byte Category(int cp)
{
if (cp < 12288 || this.cjkCatTable == null)
{
return MSCompatUnicodeTable.Category(cp);
}
int num = this.cjkIndexer.ToIndex(cp);
return (num >= 0) ? this.cjkCatTable[num] : MSCompatUnicodeTable.Category(cp);
}
// Token: 0x060007DC RID: 2012 RVA: 0x0001A07C File Offset: 0x0001827C
private unsafe byte Level1(int cp)
{
if (cp < 12288 || this.cjkLv1Table == null)
{
return MSCompatUnicodeTable.Level1(cp);
}
int num = this.cjkIndexer.ToIndex(cp);
return (num >= 0) ? this.cjkLv1Table[num] : MSCompatUnicodeTable.Level1(cp);
}
// Token: 0x060007DD RID: 2013 RVA: 0x0001A0D0 File Offset: 0x000182D0
private unsafe byte Level2(int cp, SimpleCollator.ExtenderType ext)
{
if (ext == SimpleCollator.ExtenderType.Buggy)
{
return 5;
}
if (ext == SimpleCollator.ExtenderType.Conditional)
{
return 0;
}
if (cp < 12288 || this.cjkLv2Table == null)
{
return MSCompatUnicodeTable.Level2(cp);
}
int num = this.cjkLv2Indexer.ToIndex(cp);
byte b = ((num >= 0) ? this.cjkLv2Table[num] : 0);
if (b != 0)
{
return b;
}
b = MSCompatUnicodeTable.Level2(cp);
if (this.level2Maps.Length == 0)
{
return b;
}
for (int i = 0; i < this.level2Maps.Length; i++)
{
if (this.level2Maps[i].Source == b)
{
return this.level2Maps[i].Replace;
}
if (this.level2Maps[i].Source > b)
{
break;
}
}
return b;
}
// Token: 0x060007DE RID: 2014 RVA: 0x0001A1A4 File Offset: 0x000183A4
private static bool IsHalfKana(int cp, CompareOptions opt)
{
return (opt & CompareOptions.IgnoreWidth) != CompareOptions.None || MSCompatUnicodeTable.IsHalfWidthKana((char)cp);
}
// Token: 0x060007DF RID: 2015 RVA: 0x0001A1BC File Offset: 0x000183BC
private Contraction GetContraction(string s, int start, int end)
{
Contraction contraction = this.GetContraction(s, start, end, this.contractions);
if (contraction != null || this.lcid == 127)
{
return contraction;
}
return this.GetContraction(s, start, end, SimpleCollator.invariant.contractions);
}
// Token: 0x060007E0 RID: 2016 RVA: 0x0001A204 File Offset: 0x00018404
private Contraction GetContraction(string s, int start, int end, Contraction[] clist)
{
foreach (Contraction contraction in clist)
{
int num = (int)(contraction.Source[0] - s[start]);
if (num > 0)
{
return null;
}
if (num >= 0)
{
char[] source = contraction.Source;
if (end - start >= source.Length)
{
bool flag = true;
for (int j = 0; j < source.Length; j++)
{
if (s[start + j] != source[j])
{
flag = false;
break;
}
}
if (flag)
{
return contraction;
}
}
}
}
return null;
}
// Token: 0x060007E1 RID: 2017 RVA: 0x0001A2A8 File Offset: 0x000184A8
private Contraction GetTailContraction(string s, int start, int end)
{
Contraction tailContraction = this.GetTailContraction(s, start, end, this.contractions);
if (tailContraction != null || this.lcid == 127)
{
return tailContraction;
}
return this.GetTailContraction(s, start, end, SimpleCollator.invariant.contractions);
}
// Token: 0x060007E2 RID: 2018 RVA: 0x0001A2F0 File Offset: 0x000184F0
private Contraction GetTailContraction(string s, int start, int end, Contraction[] clist)
{
if (start == end || end < -1 || start >= s.Length || s.Length <= end + 1)
{
throw new SystemException(string.Format("MONO internal error. Failed to get TailContraction. start = {0} end = {1} string = '{2}'", start, end, s));
}
foreach (Contraction contraction in clist)
{
char[] source = contraction.Source;
if (source.Length <= start - end)
{
if (source[source.Length - 1] == s[start])
{
bool flag = true;
int j = 0;
int num = start - source.Length + 1;
while (j < source.Length)
{
if (s[num] != source[j])
{
flag = false;
break;
}
j++;
num++;
}
if (flag)
{
return contraction;
}
}
}
}
return null;
}
// Token: 0x060007E3 RID: 2019 RVA: 0x0001A3D8 File Offset: 0x000185D8
private Contraction GetContraction(char c)
{
Contraction contraction = this.GetContraction(c, this.contractions);
if (contraction != null || this.lcid == 127)
{
return contraction;
}
return this.GetContraction(c, SimpleCollator.invariant.contractions);
}
// Token: 0x060007E4 RID: 2020 RVA: 0x0001A41C File Offset: 0x0001861C
private Contraction GetContraction(char c, Contraction[] clist)
{
foreach (Contraction contraction in clist)
{
if (contraction.Source[0] > c)
{
return null;
}
if (contraction.Source[0] == c && contraction.Source.Length == 1)
{
return contraction;
}
}
return null;
}
// Token: 0x060007E5 RID: 2021 RVA: 0x0001A470 File Offset: 0x00018670
private int FilterOptions(int i, CompareOptions opt)
{
if ((opt & CompareOptions.IgnoreWidth) != CompareOptions.None)
{
int num = MSCompatUnicodeTable.ToWidthCompat(i);
if (num != 0)
{
i = num;
}
}
if ((opt & CompareOptions.OrdinalIgnoreCase) != CompareOptions.None)
{
i = (int)this.textInfo.ToLower((char)i);
}
if ((opt & CompareOptions.IgnoreCase) != CompareOptions.None)
{
i = (int)this.textInfo.ToLower((char)i);
}
if ((opt & CompareOptions.IgnoreKanaType) != CompareOptions.None)
{
i = MSCompatUnicodeTable.ToKanaTypeInsensitive(i);
}
return i;
}
// Token: 0x060007E6 RID: 2022 RVA: 0x0001A4DC File Offset: 0x000186DC
private SimpleCollator.ExtenderType GetExtenderType(int i)
{
if (i == 8213)
{
return (this.lcid != 16) ? SimpleCollator.ExtenderType.None : SimpleCollator.ExtenderType.Conditional;
}
if (i < 12293 || i > 65392)
{
return SimpleCollator.ExtenderType.None;
}
if (i >= 65148)
{
if (i == 65148 || i == 65149)
{
return SimpleCollator.ExtenderType.Simple;
}
if (i == 65438 || i == 65439)
{
return SimpleCollator.ExtenderType.Voiced;
}
if (i == 65392)
{
return SimpleCollator.ExtenderType.Conditional;
}
}
if (i > 12542)
{
return SimpleCollator.ExtenderType.None;
}
switch (i)
{
case 12540:
return SimpleCollator.ExtenderType.Conditional;
case 12541:
break;
case 12542:
return SimpleCollator.ExtenderType.Voiced;
default:
if (i != 12337 && i != 12338 && i != 12445)
{
if (i == 12446)
{
return SimpleCollator.ExtenderType.Voiced;
}
if (i != 12293)
{
return SimpleCollator.ExtenderType.None;
}
return SimpleCollator.ExtenderType.Buggy;
}
break;
}
return SimpleCollator.ExtenderType.Simple;
}
// Token: 0x060007E7 RID: 2023 RVA: 0x0001A5DC File Offset: 0x000187DC
private static byte ToDashTypeValue(SimpleCollator.ExtenderType ext, CompareOptions opt)
{
if ((opt & CompareOptions.IgnoreNonSpace) != CompareOptions.None)
{
return 3;
}
switch (ext)
{
case SimpleCollator.ExtenderType.None:
return 3;
case SimpleCollator.ExtenderType.Conditional:
return 5;
}
return 4;
}
// Token: 0x060007E8 RID: 2024 RVA: 0x0001A618 File Offset: 0x00018818
private int FilterExtender(int i, SimpleCollator.ExtenderType ext, CompareOptions opt)
{
if (ext == SimpleCollator.ExtenderType.Conditional && MSCompatUnicodeTable.HasSpecialWeight((char)i))
{
bool flag = SimpleCollator.IsHalfKana((int)((ushort)i), opt);
bool flag2 = !MSCompatUnicodeTable.IsHiragana((char)i);
switch (this.Level1(i) & 7)
{
case 2:
return (!flag) ? ((!flag2) ? 12354 : 12450) : 65393;
case 3:
return (!flag) ? ((!flag2) ? 12356 : 12452) : 65394;
case 4:
return (!flag) ? ((!flag2) ? 12358 : 12454) : 65395;
case 5:
return (!flag) ? ((!flag2) ? 12360 : 12456) : 65396;
case 6:
return (!flag) ? ((!flag2) ? 12362 : 12458) : 65397;
}
}
return i;
}
// Token: 0x060007E9 RID: 2025 RVA: 0x0001A738 File Offset: 0x00018938
private static bool IsIgnorable(int i, CompareOptions opt)
{
return MSCompatUnicodeTable.IsIgnorable(i, (byte)(1 + (((opt & CompareOptions.IgnoreSymbols) == CompareOptions.None) ? 0 : 2) + (((opt & CompareOptions.IgnoreNonSpace) == CompareOptions.None) ? 0 : 4)));
}
// Token: 0x060007EA RID: 2026 RVA: 0x0001A770 File Offset: 0x00018970
private bool IsSafe(int i)
{
return i / 8 >= this.unsafeFlags.Length || ((int)this.unsafeFlags[i / 8] & (1 << i % 8)) == 0;
}
// Token: 0x060007EB RID: 2027 RVA: 0x0001A7AC File Offset: 0x000189AC
public SortKey GetSortKey(string s)
{
return this.GetSortKey(s, CompareOptions.None);
}
// Token: 0x060007EC RID: 2028 RVA: 0x0001A7B8 File Offset: 0x000189B8
public SortKey GetSortKey(string s, CompareOptions options)
{
return this.GetSortKey(s, 0, s.Length, options);
}
// Token: 0x060007ED RID: 2029 RVA: 0x0001A7CC File Offset: 0x000189CC
public SortKey GetSortKey(string s, int start, int length, CompareOptions options)
{
SortKeyBuffer sortKeyBuffer = new SortKeyBuffer(this.lcid);
sortKeyBuffer.Initialize(options, this.lcid, s, this.frenchSort);
int num = start + length;
this.GetSortKey(s, start, num, sortKeyBuffer, options);
return sortKeyBuffer.GetResultAndReset();
}
// Token: 0x060007EE RID: 2030 RVA: 0x0001A810 File Offset: 0x00018A10
private unsafe void GetSortKey(string s, int start, int end, SortKeyBuffer buf, CompareOptions opt)
{
byte* ptr = stackalloc byte[checked(4 * 1)];
this.ClearBuffer(ptr, 4);
SimpleCollator.Context context = new SimpleCollator.Context(opt, null, null, null, null, ptr, false);
for (int i = start; i < end; i++)
{
int num = (int)s[i];
SimpleCollator.ExtenderType extenderType = this.GetExtenderType(num);
if (extenderType != SimpleCollator.ExtenderType.None)
{
num = this.FilterExtender(context.PrevCode, extenderType, opt);
if (num >= 0)
{
this.FillSortKeyRaw(num, extenderType, buf, opt);
}
else if (context.PrevSortKey != null)
{
byte* prevSortKey = context.PrevSortKey;
buf.AppendNormal(*prevSortKey, prevSortKey[1], (prevSortKey[2] == 1) ? this.Level2(num, extenderType) : prevSortKey[2], (prevSortKey[3] == 1) ? MSCompatUnicodeTable.Level3(num) : prevSortKey[3]);
}
}
else if (!SimpleCollator.IsIgnorable(num, opt))
{
num = this.FilterOptions(num, opt);
Contraction contraction = this.GetContraction(s, i, end);
if (contraction != null)
{
if (contraction.Replacement != null)
{
this.GetSortKey(contraction.Replacement, 0, contraction.Replacement.Length, buf, opt);
}
else
{
byte* prevSortKey2 = context.PrevSortKey;
for (int j = 0; j < contraction.SortKey.Length; j++)
{
prevSortKey2[j] = contraction.SortKey[j];
}
buf.AppendNormal(*prevSortKey2, prevSortKey2[1], (prevSortKey2[2] == 1) ? this.Level2(num, extenderType) : prevSortKey2[2], (prevSortKey2[3] == 1) ? MSCompatUnicodeTable.Level3(num) : prevSortKey2[3]);
context.PrevCode = -1;
}
i += contraction.Source.Length - 1;
}
else
{
if (!MSCompatUnicodeTable.IsIgnorableNonSpacing(num))
{
context.PrevCode = num;
}
this.FillSortKeyRaw(num, SimpleCollator.ExtenderType.None, buf, opt);
}
}
}
}
// Token: 0x060007EF RID: 2031 RVA: 0x0001AA0C File Offset: 0x00018C0C
private void FillSortKeyRaw(int i, SimpleCollator.ExtenderType ext, SortKeyBuffer buf, CompareOptions opt)
{
if (13312 <= i && i <= 19893)
{
int num = i - 13312;
buf.AppendCJKExtension((byte)(16 + num / 254), (byte)(num % 254 + 2));
return;
}
UnicodeCategory unicodeCategory = char.GetUnicodeCategory((char)i);
UnicodeCategory unicodeCategory2 = unicodeCategory;
if (unicodeCategory2 == UnicodeCategory.Surrogate)
{
this.FillSurrogateSortKeyRaw(i, buf);
return;
}
if (unicodeCategory2 != UnicodeCategory.PrivateUse)
{
byte b = this.Level2(i, ext);
if (MSCompatUnicodeTable.HasSpecialWeight((char)i))
{
byte b2 = this.Level1(i);
buf.AppendKana(this.Category(i), b2, b, MSCompatUnicodeTable.Level3(i), MSCompatUnicodeTable.IsJapaneseSmallLetter((char)i), SimpleCollator.ToDashTypeValue(ext, opt), !MSCompatUnicodeTable.IsHiragana((char)i), SimpleCollator.IsHalfKana((int)((ushort)i), opt));
if ((opt & CompareOptions.IgnoreNonSpace) == CompareOptions.None && ext == SimpleCollator.ExtenderType.Voiced)
{
buf.AppendNormal(1, 1, 1, 0);
}
}
else
{
buf.AppendNormal(this.Category(i), this.Level1(i), b, MSCompatUnicodeTable.Level3(i));
}
return;
}
int num2 = i - 57344;
buf.AppendNormal((byte)(229 + num2 / 254), (byte)(num2 % 254 + 2), 0, 0);
}
// Token: 0x060007F0 RID: 2032 RVA: 0x0001AB38 File Offset: 0x00018D38
private void FillSurrogateSortKeyRaw(int i, SortKeyBuffer buf)
{
int num;
int num2;
byte b;
if (i < 55360)
{
num = 55296;
num2 = 65;
b = ((i != 55296) ? 63 : 62);
}
else if (55360 <= i && i < 55424)
{
num = 55360;
num2 = 242;
b = 62;
}
else if (56192 <= i && i < 56320)
{
num = 56128;
num2 = 254;
b = 62;
}
else
{
num = 56074;
num2 = 65;
b = 63;
}
int num3 = i - num;
buf.AppendNormal((byte)(num2 + num3 / 254), (byte)(num3 % 254 + 2), b, b);
}
// Token: 0x060007F1 RID: 2033 RVA: 0x0001ABFC File Offset: 0x00018DFC
public int Compare(string s1, string s2)
{
return this.Compare(s1, s2, CompareOptions.None);
}
// Token: 0x060007F2 RID: 2034 RVA: 0x0001AC08 File Offset: 0x00018E08
public int Compare(string s1, string s2, CompareOptions options)
{
return this.Compare(s1, 0, s1.Length, s2, 0, s2.Length, options);
}
// Token: 0x060007F3 RID: 2035 RVA: 0x0001AC2C File Offset: 0x00018E2C
private int CompareOrdinal(string s1, int idx1, int len1, string s2, int idx2, int len2)
{
int num = ((len1 >= len2) ? len2 : len1);
int num2 = idx1 + num;
int num3 = idx2 + num;
if (idx1 < 0 || idx2 < 0 || num2 > s1.Length || num3 > s2.Length)
{
throw new SystemException(string.Format("CompareInfo Internal Error: Should not happen. {0} {1} {2} {3} {4} {5}", new object[] { idx1, idx2, len1, len2, s1.Length, s2.Length }));
}
int num4 = idx1;
int num5 = idx2;
while (num4 < num2 && num5 < num3)
{
if (s1[num4] != s2[num5])
{
return (int)(s1[num4] - s2[num5]);
}
num4++;
num5++;
}
return (len1 != len2) ? ((len1 != num) ? 1 : (-1)) : 0;
}
// Token: 0x060007F4 RID: 2036 RVA: 0x0001AD3C File Offset: 0x00018F3C
private int CompareQuick(string s1, int idx1, int len1, string s2, int idx2, int len2, out bool sourceConsumed, out bool targetConsumed, bool immediateBreakup)
{
sourceConsumed = false;
targetConsumed = false;
int num = ((len1 >= len2) ? len2 : len1);
int num2 = idx1 + num;
int num3 = idx2 + num;
if (idx1 < 0 || idx2 < 0 || num2 > s1.Length || num3 > s2.Length)
{
throw new SystemException(string.Format("CompareInfo Internal Error: Should not happen. {0} {1} {2} {3} {4} {5}", new object[] { idx1, idx2, len1, len2, s1.Length, s2.Length }));
}
int num4 = idx1;
int num5 = idx2;
while (num4 < num2 && num5 < num3)
{
if (s1[num4] != s2[num5])
{
if (immediateBreakup)
{
return -1;
}
int num6 = (int)(this.Category((int)s1[num4]) - this.Category((int)s2[num5]));
if (num6 == 0)
{
num6 = (int)(this.Level1((int)s1[num4]) - this.Level1((int)s2[num5]));
}
if (num6 == 0)
{
num6 = (int)(MSCompatUnicodeTable.Level3((int)s1[num4]) - MSCompatUnicodeTable.Level3((int)s2[num5]));
}
if (num6 == 0)
{
throw new SystemException(string.Format("CompareInfo Internal Error: Should not happen. '{0}' {2} {3} '{1}' {4} {5}", new object[] { s1, s2, idx1, num2, idx2, num3 }));
}
return num6;
}
else
{
num4++;
num5++;
}
}
sourceConsumed = len1 <= len2;
targetConsumed = len1 >= len2;
return (len1 != len2) ? ((len1 != num) ? 1 : (-1)) : 0;
}
// Token: 0x060007F5 RID: 2037 RVA: 0x0001AF18 File Offset: 0x00019118
private int CompareOrdinalIgnoreCase(string s1, int idx1, int len1, string s2, int idx2, int len2)
{
int num = ((len1 >= len2) ? len2 : len1);
int num2 = idx1 + num;
int num3 = idx2 + num;
if (idx1 < 0 || idx2 < 0 || num2 > s1.Length || num3 > s2.Length)
{
throw new SystemException(string.Format("CompareInfo Internal Error: Should not happen. {0} {1} {2} {3} {4} {5}", new object[] { idx1, idx2, len1, len2, s1.Length, s2.Length }));
}
TextInfo textInfo = SimpleCollator.invariant.textInfo;
int num4 = idx1;
int num5 = idx2;
while (num4 < num2 && num5 < num3)
{
if (textInfo.ToLower(s1[num4]) != textInfo.ToLower(s2[num5]))
{
return (int)(textInfo.ToLower(s1[num4]) - textInfo.ToLower(s2[num5]));
}
num4++;
num5++;
}
return (len1 != len2) ? ((len1 != num) ? 1 : (-1)) : 0;
}
// Token: 0x060007F6 RID: 2038 RVA: 0x0001B050 File Offset: 0x00019250
public unsafe int Compare(string s1, int idx1, int len1, string s2, int idx2, int len2, CompareOptions options)
{
if (idx1 == idx2 && len1 == len2 && object.ReferenceEquals(s1, s2))
{
return 0;
}
if (options == CompareOptions.Ordinal)
{
return this.CompareOrdinal(s1, idx1, len1, s2, idx2, len2);
}
if (options == CompareOptions.OrdinalIgnoreCase)
{
return this.CompareOrdinalIgnoreCase(s1, idx1, len1, s2, idx2, len2);
}
byte* ptr;
byte* ptr2;
checked
{
ptr = stackalloc byte[4 * 1];
ptr2 = stackalloc byte[4 * 1];
this.ClearBuffer(ptr, 4);
this.ClearBuffer(ptr2, 4);
}
SimpleCollator.Context context = new SimpleCollator.Context(options, null, null, ptr, ptr2, null, this.QuickCheckPossible(s1, idx1, idx1 + len1, s2, idx2, idx2 + len2));
bool flag;
bool flag2;
int num = this.CompareInternal(s1, idx1, len1, s2, idx2, len2, out flag, out flag2, true, false, ref context);
return (num != 0) ? ((num >= 0) ? 1 : (-1)) : 0;
}
// Token: 0x060007F7 RID: 2039 RVA: 0x0001B12C File Offset: 0x0001932C
private unsafe void ClearBuffer(byte* buffer, int size)
{
for (int i = 0; i < size; i++)
{
buffer[i] = 0;
}
}
// Token: 0x060007F8 RID: 2040 RVA: 0x0001B150 File Offset: 0x00019350
private bool QuickCheckPossible(string s1, int idx1, int end1, string s2, int idx2, int end2)
{
return false;
}
// Token: 0x060007F9 RID: 2041 RVA: 0x0001B154 File Offset: 0x00019354
private unsafe int CompareInternal(string s1, int idx1, int len1, string s2, int idx2, int len2, out bool targetConsumed, out bool sourceConsumed, bool skipHeadingExtenders, bool immediateBreakup, ref SimpleCollator.Context ctx)
{
CompareOptions option = ctx.Option;
int num = idx1;
int num2 = idx2;
int num3 = idx1 + len1;
int num4 = idx2 + len2;
targetConsumed = false;
sourceConsumed = false;
SimpleCollator.PreviousInfo previousInfo = new SimpleCollator.PreviousInfo(false);
if (option == CompareOptions.None && ctx.QuickCheckPossible)
{
return this.CompareQuick(s1, idx1, len1, s2, idx2, len2, out sourceConsumed, out targetConsumed, immediateBreakup);
}
int num5 = 0;
int num6 = 5;
int num7 = -1;
int num8 = -1;
int num9 = 0;
int num10 = 0;
if (skipHeadingExtenders)
{
while (idx1 < num3)
{
if (this.GetExtenderType((int)s1[idx1]) == SimpleCollator.ExtenderType.None)
{
break;
}
idx1++;
}
while (idx2 < num4)
{
if (this.GetExtenderType((int)s2[idx2]) == SimpleCollator.ExtenderType.None)
{
break;
}
idx2++;
}
}
SimpleCollator.ExtenderType extenderType = SimpleCollator.ExtenderType.None;
SimpleCollator.ExtenderType extenderType2 = SimpleCollator.ExtenderType.None;
int num11 = idx1;
int num12 = idx2;
bool flag = (option & CompareOptions.StringSort) != CompareOptions.None;
bool flag2 = (option & CompareOptions.IgnoreNonSpace) != CompareOptions.None;
SimpleCollator.Escape escape = default(SimpleCollator.Escape);
SimpleCollator.Escape escape2 = default(SimpleCollator.Escape);
for (;;)
{
while (idx1 < num3)
{
if (!SimpleCollator.IsIgnorable((int)s1[idx1], option))
{
break;
}
idx1++;
}
while (idx2 < num4)
{
if (!SimpleCollator.IsIgnorable((int)s2[idx2], option))
{
break;
}
idx2++;
}
if (idx1 >= num3)
{
if (escape.Source == null)
{
break;
}
s1 = escape.Source;
num = escape.Start;
idx1 = escape.Index;
num3 = escape.End;
num11 = escape.Optional;
escape.Source = null;
}
else if (idx2 >= num4)
{
if (escape2.Source == null)
{
break;
}
s2 = escape2.Source;
num2 = escape2.Start;
idx2 = escape2.Index;
num4 = escape2.End;
num12 = escape2.Optional;
escape2.Source = null;
}
else
{
if (num11 < idx1 && num12 < idx2)
{
while (idx1 < num3 && idx2 < num4 && s1[idx1] == s2[idx2])
{
idx1++;
idx2++;
}
if (idx1 == num3 || idx2 == num4)
{
continue;
}
int num13 = num11;
int num14 = num12;
num11 = idx1;
num12 = idx2;
idx1--;
idx2--;
while (idx1 > num13)
{
if (this.Category((int)s1[idx1]) != 1)
{
break;
}
idx1--;
}
while (idx2 > num14)
{
if (this.Category((int)s2[idx2]) != 1)
{
break;
}
idx2--;
}
while (idx1 > num13)
{
if (this.IsSafe((int)s1[idx1]))
{
break;
}
idx1--;
}
while (idx2 > num14)
{
if (this.IsSafe((int)s2[idx2]))
{
break;
}
idx2--;
}
}
int num15 = idx1;
int num16 = idx2;
byte* ptr = null;
byte* ptr2 = null;
int num17 = this.FilterOptions((int)s1[idx1], option);
int num18 = this.FilterOptions((int)s2[idx2], option);
bool flag3 = false;
bool flag4 = false;
extenderType = this.GetExtenderType(num17);
if (extenderType != SimpleCollator.ExtenderType.None)
{
if (ctx.PrevCode < 0)
{
if (ctx.PrevSortKey == null)
{
idx1++;
continue;
}
ptr = ctx.PrevSortKey;
}
else
{
num17 = this.FilterExtender(ctx.PrevCode, extenderType, option);
}
}
extenderType2 = this.GetExtenderType(num18);
if (extenderType2 != SimpleCollator.ExtenderType.None)
{
if (previousInfo.Code < 0)
{
if (previousInfo.SortKey == null)
{
idx2++;
continue;
}
ptr2 = previousInfo.SortKey;
}
else
{
num18 = this.FilterExtender(previousInfo.Code, extenderType2, option);
}
}
byte b = this.Category(num17);
byte b2 = this.Category(num18);
if (b == 6)
{
if (!flag && num6 == 5)
{
num7 = ((escape.Source == null) ? (num15 - num) : (escape.Index - escape.Start));
num9 = (int)this.Level1(num17) << (int)(8 + MSCompatUnicodeTable.Level3(num17));
}
ctx.PrevCode = num17;
idx1++;
}
if (b2 == 6)
{
if (!flag && num6 == 5)
{
num8 = ((escape2.Source == null) ? (num16 - num2) : (escape2.Index - escape2.Start));
num10 = (int)this.Level1(num18) << (int)(8 + MSCompatUnicodeTable.Level3(num18));
}
previousInfo.Code = num18;
idx2++;
}
if (b == 6 || b2 == 6)
{
if (num6 == 5)
{
if (num9 == num10)
{
num8 = (num7 = -1);
num10 = (num9 = 0);
}
else
{
num6 = 4;
}
}
}
else
{
Contraction contraction = null;
if (extenderType == SimpleCollator.ExtenderType.None)
{
contraction = this.GetContraction(s1, idx1, num3);
}
int num19 = 1;
if (ptr != null)
{
num19 = 1;
}
else if (contraction != null)
{
num19 = contraction.Source.Length;
if (contraction.SortKey != null)
{
ptr = ctx.Buffer1;
for (int i = 0; i < contraction.SortKey.Length; i++)
{
ptr[i] = contraction.SortKey[i];
}
ctx.PrevCode = -1;
ctx.PrevSortKey = ptr;
}
else if (escape.Source == null)
{
escape.Source = s1;
escape.Start = num;
escape.Index = num15 + contraction.Source.Length;
escape.End = num3;
escape.Optional = num11;
s1 = contraction.Replacement;
idx1 = 0;
num = 0;
num3 = s1.Length;
num11 = 0;
continue;
}
}
else
{
ptr = ctx.Buffer1;
*ptr = b;
ptr[1] = this.Level1(num17);
if (!flag2 && num6 > 1)
{
ptr[2] = this.Level2(num17, extenderType);
}
if (num6 > 2)
{
ptr[3] = MSCompatUnicodeTable.Level3(num17);
}
if (num6 > 3)
{
flag3 = MSCompatUnicodeTable.HasSpecialWeight((char)num17);
}
if (b > 1)
{
ctx.PrevCode = num17;
}
}
Contraction contraction2 = null;
if (extenderType2 == SimpleCollator.ExtenderType.None)
{
contraction2 = this.GetContraction(s2, idx2, num4);
}
if (ptr2 != null)
{
idx2++;
}
else if (contraction2 != null)
{
idx2 += contraction2.Source.Length;
if (contraction2.SortKey != null)
{
ptr2 = ctx.Buffer2;
for (int j = 0; j < contraction2.SortKey.Length; j++)
{
ptr2[j] = contraction2.SortKey[j];
}
previousInfo.Code = -1;
previousInfo.SortKey = ptr2;
}
else if (escape2.Source == null)
{
escape2.Source = s2;
escape2.Start = num2;
escape2.Index = num16 + contraction2.Source.Length;
escape2.End = num4;
escape2.Optional = num12;
s2 = contraction2.Replacement;
idx2 = 0;
num2 = 0;
num4 = s2.Length;
num12 = 0;
continue;
}
}
else
{
ptr2 = ctx.Buffer2;
*ptr2 = b2;
ptr2[1] = this.Level1(num18);
if (!flag2 && num6 > 1)
{
ptr2[2] = this.Level2(num18, extenderType2);
}
if (num6 > 2)
{
ptr2[3] = MSCompatUnicodeTable.Level3(num18);
}
if (num6 > 3)
{
flag4 = MSCompatUnicodeTable.HasSpecialWeight((char)num18);
}
if (b2 > 1)
{
previousInfo.Code = num18;
}
idx2++;
}
idx1 += num19;
if (!flag2)
{
while (idx1 < num3)
{
if (this.Category((int)s1[idx1]) != 1)
{
break;
}
if (ptr[2] == 0)
{
ptr[2] = 2;
}
ptr[2] = ptr[2] + this.Level2((int)s1[idx1], SimpleCollator.ExtenderType.None);
idx1++;
}
while (idx2 < num4)
{
if (this.Category((int)s2[idx2]) != 1)
{
break;
}
if (ptr2[2] == 0)
{
ptr2[2] = 2;
}
ptr2[2] = ptr2[2] + this.Level2((int)s2[idx2], SimpleCollator.ExtenderType.None);
idx2++;
}
}
int num20 = (int)(*ptr - *ptr2);
num20 = ((num20 == 0) ? ((int)(ptr[1] - ptr2[1])) : num20);
if (num20 != 0)
{
return num20;
}
if (num6 != 1)
{
if (!flag2)
{
num20 = (int)(ptr[2] - ptr2[2]);
if (num20 != 0)
{
num5 = num20;
if (immediateBreakup)
{
return -1;
}
num6 = ((!this.frenchSort) ? 1 : 2);
continue;
}
}
if (num6 != 2)
{
num20 = (int)(ptr[3] - ptr2[3]);
if (num20 != 0)
{
num5 = num20;
if (immediateBreakup)
{
return -1;
}
num6 = 2;
}
else if (num6 != 3)
{
if (flag3 != flag4)
{
if (immediateBreakup)
{
return -1;
}
num5 = ((!flag3) ? (-1) : 1);
num6 = 3;
}
else if (flag3)
{
num20 = this.CompareFlagPair(!MSCompatUnicodeTable.IsJapaneseSmallLetter((char)num17), !MSCompatUnicodeTable.IsJapaneseSmallLetter((char)num18));
num20 = ((num20 == 0) ? ((int)(SimpleCollator.ToDashTypeValue(extenderType, option) - SimpleCollator.ToDashTypeValue(extenderType2, option))) : num20);
num20 = ((num20 == 0) ? this.CompareFlagPair(MSCompatUnicodeTable.IsHiragana((char)num17), MSCompatUnicodeTable.IsHiragana((char)num18)) : num20);
num20 = ((num20 == 0) ? this.CompareFlagPair(!SimpleCollator.IsHalfKana((int)((ushort)num17), option), !SimpleCollator.IsHalfKana((int)((ushort)num18), option)) : num20);
if (num20 != 0)
{
if (immediateBreakup)
{
return -1;
}
num5 = num20;
num6 = 3;
}
}
}
}
}
}
}
}
if (!flag2 && num5 != 0 && num6 > 2)
{
while (idx1 < num3 && idx2 < num4)
{
if (!MSCompatUnicodeTable.IsIgnorableNonSpacing((int)s1[idx1]))
{
break;
}
if (!MSCompatUnicodeTable.IsIgnorableNonSpacing((int)s2[idx2]))
{
break;
}
num5 = (int)(this.Level2(this.FilterOptions((int)s1[idx1], option), extenderType) - this.Level2(this.FilterOptions((int)s2[idx2], option), extenderType2));
if (num5 != 0)
{
break;
}
idx1++;
idx2++;
extenderType = SimpleCollator.ExtenderType.None;
extenderType2 = SimpleCollator.ExtenderType.None;
}
}
if (num6 == 1 && num5 != 0)
{
while (idx1 < num3)
{
if (!MSCompatUnicodeTable.IsIgnorableNonSpacing((int)s1[idx1]))
{
break;
}
idx1++;
}
while (idx2 < num4)
{
if (!MSCompatUnicodeTable.IsIgnorableNonSpacing((int)s2[idx2]))
{
break;
}
idx2++;
}
}
if (num5 == 0)
{
if (num7 < 0 && num8 >= 0)
{
num5 = -1;
}
else if (num8 < 0 && num7 >= 0)
{
num5 = 1;
}
else
{
num5 = num7 - num8;
if (num5 == 0)
{
num5 = num9 - num10;
}
}
}
if (num5 == 0)
{
if (idx2 == num4)
{
targetConsumed = true;
}
if (idx1 == num3)
{
sourceConsumed = true;
}
}
return (idx1 == num3) ? ((idx2 != num4) ? (-1) : num5) : 1;
}
// Token: 0x060007FA RID: 2042 RVA: 0x0001BD38 File Offset: 0x00019F38
private int CompareFlagPair(bool b1, bool b2)
{
return (b1 != b2) ? ((!b1) ? (-1) : 1) : 0;
}
// Token: 0x060007FB RID: 2043 RVA: 0x0001BD54 File Offset: 0x00019F54
public bool IsPrefix(string src, string target, CompareOptions opt)
{
return this.IsPrefix(src, target, 0, src.Length, opt);
}
// Token: 0x060007FC RID: 2044 RVA: 0x0001BD74 File Offset: 0x00019F74
public unsafe bool IsPrefix(string s, string target, int start, int length, CompareOptions opt)
{
if (target.Length == 0)
{
return true;
}
byte* ptr;
byte* ptr2;
checked
{
ptr = stackalloc byte[4 * 1];
ptr2 = stackalloc byte[4 * 1];
this.ClearBuffer(ptr, 4);
this.ClearBuffer(ptr2, 4);
}
SimpleCollator.Context context = new SimpleCollator.Context(opt, null, null, ptr, ptr2, null, this.QuickCheckPossible(s, start, start + length, target, 0, target.Length));
return this.IsPrefix(s, target, start, length, true, ref context);
}
// Token: 0x060007FD RID: 2045 RVA: 0x0001BDE0 File Offset: 0x00019FE0
private bool IsPrefix(string s, string target, int start, int length, bool skipHeadingExtenders, ref SimpleCollator.Context ctx)
{
bool flag;
bool flag2;
this.CompareInternal(s, start, length, target, 0, target.Length, out flag, out flag2, skipHeadingExtenders, true, ref ctx);
return flag;
}
// Token: 0x060007FE RID: 2046 RVA: 0x0001BE0C File Offset: 0x0001A00C
public bool IsSuffix(string src, string target, CompareOptions opt)
{
return this.IsSuffix(src, target, src.Length - 1, src.Length, opt);
}
// Token: 0x060007FF RID: 2047 RVA: 0x0001BE30 File Offset: 0x0001A030
public bool IsSuffix(string s, string target, int start, int length, CompareOptions opt)
{
if (target.Length == 0)
{
return true;
}
int num = this.LastIndexOf(s, target, start, length, opt);
return num >= 0 && this.Compare(s, num, s.Length - num, target, 0, target.Length, opt) == 0;
}
// Token: 0x06000800 RID: 2048 RVA: 0x0001BE80 File Offset: 0x0001A080
public int IndexOf(string s, string target, CompareOptions opt)
{
return this.IndexOf(s, target, 0, s.Length, opt);
}
// Token: 0x06000801 RID: 2049 RVA: 0x0001BEA0 File Offset: 0x0001A0A0
private int QuickIndexOf(string s, string target, int start, int length, out bool testWasUnable)
{
int num = -1;
int num2 = -1;
testWasUnable = true;
if (target.Length == 0)
{
return 0;
}
if (target.Length > length)
{
return -1;
}
testWasUnable = false;
int num3 = start + length - target.Length + 1;
for (int i = start; i < num3; i++)
{
bool flag = false;
for (int j = 0; j < target.Length; j++)
{
if (num2 < j)
{
if (target[j] >= '\u0080')
{
testWasUnable = true;
return -1;
}
num2 = j;
}
if (num < i + j)
{
if (s[i + j] >= '\u0080')
{
testWasUnable = true;
return -1;
}
num = i + j;
}
if (s[i + j] != target[j])
{
flag = true;
break;
}
}
if (!flag)
{
return i;
}
}
return -1;
}
// Token: 0x06000802 RID: 2050 RVA: 0x0001BF90 File Offset: 0x0001A190
public unsafe int IndexOf(string s, string target, int start, int length, CompareOptions opt)
{
if (opt == CompareOptions.Ordinal)
{
return this.IndexOfOrdinal(s, target, start, length);
}
if (opt == CompareOptions.OrdinalIgnoreCase)
{
return this.IndexOfOrdinalIgnoreCase(s, target, start, length);
}
if (opt == CompareOptions.None)
{
bool flag;
int num = this.QuickIndexOf(s, target, start, length, out flag);
if (!flag)
{
return num;
}
}
checked
{
byte* ptr = stackalloc byte[16 * 1];
byte* ptr2 = stackalloc byte[16 * 1];
byte* ptr3 = stackalloc byte[4 * 1];
byte* ptr4 = stackalloc byte[4 * 1];
byte* ptr5 = stackalloc byte[4 * 1];
this.ClearBuffer(ptr, 16);
this.ClearBuffer(ptr2, 16);
this.ClearBuffer(ptr3, 4);
this.ClearBuffer(ptr4, 4);
this.ClearBuffer(ptr5, 4);
SimpleCollator.Context context = new SimpleCollator.Context(opt, ptr, ptr2, ptr4, ptr5, null, false);
return this.IndexOf(s, target, start, length, ptr3, ref context);
}
}
// Token: 0x06000803 RID: 2051 RVA: 0x0001C05C File Offset: 0x0001A25C
private int IndexOfOrdinal(string s, string target, int start, int length)
{
if (target.Length == 0)
{
return 0;
}
if (target.Length > length)
{
return -1;
}
int num = start + length - target.Length + 1;
for (int i = start; i < num; i++)
{
bool flag = false;
for (int j = 0; j < target.Length; j++)
{
if (s[i + j] != target[j])
{
flag = true;
break;
}
}
if (!flag)
{
return i;
}
}
return -1;
}
// Token: 0x06000804 RID: 2052 RVA: 0x0001C0E8 File Offset: 0x0001A2E8
private int IndexOfOrdinalIgnoreCase(string s, string target, int start, int length)
{
if (target.Length == 0)
{
return 0;
}
if (target.Length > length)
{
return -1;
}
int num = start + length - target.Length + 1;
for (int i = start; i < num; i++)
{
bool flag = false;
for (int j = 0; j < target.Length; j++)
{
if (this.textInfo.ToLower(s[i + j]) != this.textInfo.ToLower(target[j]))
{
flag = true;
break;
}
}
if (!flag)
{
return i;
}
}
return -1;
}
// Token: 0x06000805 RID: 2053 RVA: 0x0001C18C File Offset: 0x0001A38C
public int IndexOf(string s, char target, CompareOptions opt)
{
return this.IndexOf(s, target, 0, s.Length, opt);
}
// Token: 0x06000806 RID: 2054 RVA: 0x0001C1AC File Offset: 0x0001A3AC
public unsafe int IndexOf(string s, char target, int start, int length, CompareOptions opt)
{
if (opt == CompareOptions.Ordinal)
{
return this.IndexOfOrdinal(s, target, start, length);
}
if (opt == CompareOptions.OrdinalIgnoreCase)
{
return this.IndexOfOrdinalIgnoreCase(s, target, start, length);
}
byte* ptr3;
byte* ptr5;
SimpleCollator.Context context;
Contraction contraction;
checked
{
byte* ptr = stackalloc byte[16 * 1];
byte* ptr2 = stackalloc byte[16 * 1];
ptr3 = stackalloc byte[4 * 1];
byte* ptr4 = stackalloc byte[4 * 1];
ptr5 = stackalloc byte[4 * 1];
this.ClearBuffer(ptr, 16);
this.ClearBuffer(ptr2, 16);
this.ClearBuffer(ptr3, 4);
this.ClearBuffer(ptr4, 4);
this.ClearBuffer(ptr5, 4);
context = new SimpleCollator.Context(opt, ptr, ptr2, ptr4, ptr5, null, false);
contraction = this.GetContraction(target);
}
if (contraction == null)
{
int num = this.FilterOptions((int)target, opt);
*ptr3 = this.Category(num);
ptr3[1] = this.Level1(num);
if ((opt & CompareOptions.IgnoreNonSpace) == CompareOptions.None)
{
ptr3[2] = this.Level2(num, SimpleCollator.ExtenderType.None);
}
ptr3[3] = MSCompatUnicodeTable.Level3(num);
return this.IndexOfSortKey(s, start, length, ptr3, target, num, !MSCompatUnicodeTable.HasSpecialWeight((char)num), ref context);
}
if (contraction.Replacement != null)
{
return this.IndexOf(s, contraction.Replacement, start, length, ptr3, ref context);
}
for (int i = 0; i < contraction.SortKey.Length; i++)
{
ptr5[i] = contraction.SortKey[i];
}
return this.IndexOfSortKey(s, start, length, ptr5, '\0', -1, true, ref context);
}
// Token: 0x06000807 RID: 2055 RVA: 0x0001C314 File Offset: 0x0001A514
private int IndexOfOrdinal(string s, char target, int start, int length)
{
int num = start + length;
for (int i = start; i < num; i++)
{
if (s[i] == target)
{
return i;
}
}
return -1;
}
// Token: 0x06000808 RID: 2056 RVA: 0x0001C348 File Offset: 0x0001A548
private int IndexOfOrdinalIgnoreCase(string s, char target, int start, int length)
{
int num = start + length;
target = this.textInfo.ToLower(target);
for (int i = start; i < num; i++)
{
if (this.textInfo.ToLower(s[i]) == target)
{
return i;
}
}
return -1;
}
// Token: 0x06000809 RID: 2057 RVA: 0x0001C398 File Offset: 0x0001A598
private unsafe int IndexOfSortKey(string s, int start, int length, byte* sortkey, char target, int ti, bool noLv4, ref SimpleCollator.Context ctx)
{
int num = start + length;
int i = start;
while (i < num)
{
int num2 = i;
if (this.MatchesForward(s, ref i, num, ti, sortkey, noLv4, ref ctx))
{
return num2;
}
}
return -1;
}
// Token: 0x0600080A RID: 2058 RVA: 0x0001C3D4 File Offset: 0x0001A5D4
private unsafe int IndexOf(string s, string target, int start, int length, byte* targetSortKey, ref SimpleCollator.Context ctx)
{
CompareOptions option = ctx.Option;
int i;
for (i = 0; i < target.Length; i++)
{
if (!SimpleCollator.IsIgnorable((int)target[i], option))
{
break;
}
}
if (i == target.Length)
{
return start;
}
Contraction contraction = this.GetContraction(target, i, target.Length - i);
string text = ((contraction == null) ? null : contraction.Replacement);
byte* ptr = ((text != null) ? null : targetSortKey);
bool flag = true;
char c = '\0';
int num = -1;
if (contraction != null && ptr != null)
{
for (int j = 0; j < contraction.SortKey.Length; j++)
{
ptr[j] = contraction.SortKey[j];
}
}
else if (ptr != null)
{
c = target[i];
num = this.FilterOptions((int)target[i], option);
*ptr = this.Category(num);
ptr[1] = this.Level1(num);
if ((option & CompareOptions.IgnoreNonSpace) == CompareOptions.None)
{
ptr[2] = this.Level2(num, SimpleCollator.ExtenderType.None);
}
ptr[3] = MSCompatUnicodeTable.Level3(num);
flag = !MSCompatUnicodeTable.HasSpecialWeight((char)num);
}
if (ptr != null)
{
for (i++; i < target.Length; i++)
{
if (this.Category((int)target[i]) != 1)
{
break;
}
if (ptr[2] == 0)
{
ptr[2] = 2;
}
ptr[2] = ptr[2] + this.Level2((int)target[i], SimpleCollator.ExtenderType.None);
}
}
for (;;)
{
int num2;
if (text != null)
{
num2 = this.IndexOf(s, text, start, length, targetSortKey, ref ctx);
}
else
{
num2 = this.IndexOfSortKey(s, start, length, ptr, c, num, flag, ref ctx);
}
if (num2 < 0)
{
break;
}
length -= num2 - start;
start = num2;
if (this.IsPrefix(s, target, start, length, false, ref ctx))
{
return num2;
}
Contraction contraction2 = this.GetContraction(s, start, length);
if (contraction2 != null)
{
start += contraction2.Source.Length;
length -= contraction2.Source.Length;
}
else
{
start++;
length--;
}
if (length <= 0)
{
return -1;
}
}
return -1;
}
// Token: 0x0600080B RID: 2059 RVA: 0x0001C614 File Offset: 0x0001A814
public int LastIndexOf(string s, string target, CompareOptions opt)
{
return this.LastIndexOf(s, target, s.Length - 1, s.Length, opt);
}
// Token: 0x0600080C RID: 2060 RVA: 0x0001C638 File Offset: 0x0001A838
public unsafe int LastIndexOf(string s, string target, int start, int length, CompareOptions opt)
{
if (opt == CompareOptions.Ordinal)
{
return this.LastIndexOfOrdinal(s, target, start, length);
}
if (opt == CompareOptions.OrdinalIgnoreCase)
{
return this.LastIndexOfOrdinalIgnoreCase(s, target, start, length);
}
checked
{
byte* ptr = stackalloc byte[16 * 1];
byte* ptr2 = stackalloc byte[16 * 1];
byte* ptr3 = stackalloc byte[4 * 1];
byte* ptr4 = stackalloc byte[4 * 1];
byte* ptr5 = stackalloc byte[4 * 1];
this.ClearBuffer(ptr, 16);
this.ClearBuffer(ptr2, 16);
this.ClearBuffer(ptr3, 4);
this.ClearBuffer(ptr4, 4);
this.ClearBuffer(ptr5, 4);
SimpleCollator.Context context = new SimpleCollator.Context(opt, ptr, ptr2, ptr4, ptr5, null, false);
return this.LastIndexOf(s, target, start, length, ptr3, ref context);
}
}
// Token: 0x0600080D RID: 2061 RVA: 0x0001C6E0 File Offset: 0x0001A8E0
private int LastIndexOfOrdinal(string s, string target, int start, int length)
{
if (target.Length == 0)
{
return 0;
}
if (s.Length < target.Length || target.Length > length)
{
return -1;
}
int num = start - length + target.Length - 1;
char c = target[target.Length - 1];
int i = start;
while (i > num)
{
if (s[i] != c)
{
i--;
}
else
{
int num2 = i - target.Length + 1;
i--;
bool flag = false;
for (int j = target.Length - 2; j >= 0; j--)
{
if (s[num2 + j] != target[j])
{
flag = true;
break;
}
}
if (!flag)
{
return num2;
}
}
}
return -1;
}
// Token: 0x0600080E RID: 2062 RVA: 0x0001C7B8 File Offset: 0x0001A9B8
private int LastIndexOfOrdinalIgnoreCase(string s, string target, int start, int length)
{
if (target.Length == 0)
{
return 0;
}
if (s.Length < length || target.Length > length)
{
return -1;
}
int num = start - length + target.Length - 1;
char c = this.textInfo.ToLower(target[target.Length - 1]);
int i = start;
while (i > num)
{
if (this.textInfo.ToLower(s[i]) != c)
{
i--;
}
else
{
int num2 = i - target.Length + 1;
i--;
bool flag = false;
for (int j = target.Length - 2; j >= 0; j--)
{
if (this.textInfo.ToLower(s[num2 + j]) != this.textInfo.ToLower(target[j]))
{
flag = true;
break;
}
}
if (!flag)
{
return num2;
}
}
}
return -1;
}
// Token: 0x0600080F RID: 2063 RVA: 0x0001C8B8 File Offset: 0x0001AAB8
public int LastIndexOf(string s, char target, CompareOptions opt)
{
return this.LastIndexOf(s, target, s.Length - 1, s.Length, opt);
}
// Token: 0x06000810 RID: 2064 RVA: 0x0001C8DC File Offset: 0x0001AADC
public unsafe int LastIndexOf(string s, char target, int start, int length, CompareOptions opt)
{
if (opt == CompareOptions.Ordinal)
{
return this.LastIndexOfOrdinal(s, target, start, length);
}
if (opt == CompareOptions.OrdinalIgnoreCase)
{
return this.LastIndexOfOrdinalIgnoreCase(s, target, start, length);
}
byte* ptr3;
byte* ptr5;
SimpleCollator.Context context;
Contraction contraction;
checked
{
byte* ptr = stackalloc byte[16 * 1];
byte* ptr2 = stackalloc byte[16 * 1];
ptr3 = stackalloc byte[4 * 1];
byte* ptr4 = stackalloc byte[4 * 1];
ptr5 = stackalloc byte[4 * 1];
this.ClearBuffer(ptr, 16);
this.ClearBuffer(ptr2, 16);
this.ClearBuffer(ptr3, 4);
this.ClearBuffer(ptr4, 4);
this.ClearBuffer(ptr5, 4);
context = new SimpleCollator.Context(opt, ptr, ptr2, ptr4, ptr5, null, false);
contraction = this.GetContraction(target);
}
if (contraction == null)
{
int num = this.FilterOptions((int)target, opt);
*ptr3 = this.Category(num);
ptr3[1] = this.Level1(num);
if ((opt & CompareOptions.IgnoreNonSpace) == CompareOptions.None)
{
ptr3[2] = this.Level2(num, SimpleCollator.ExtenderType.None);
}
ptr3[3] = MSCompatUnicodeTable.Level3(num);
return this.LastIndexOfSortKey(s, start, start, length, ptr3, num, !MSCompatUnicodeTable.HasSpecialWeight((char)num), ref context);
}
if (contraction.Replacement != null)
{
return this.LastIndexOf(s, contraction.Replacement, start, length, ptr3, ref context);
}
for (int i = 0; i < contraction.SortKey.Length; i++)
{
ptr5[i] = contraction.SortKey[i];
}
return this.LastIndexOfSortKey(s, start, start, length, ptr5, -1, true, ref context);
}
// Token: 0x06000811 RID: 2065 RVA: 0x0001CA44 File Offset: 0x0001AC44
private int LastIndexOfOrdinal(string s, char target, int start, int length)
{
if (s.Length == 0)
{
return -1;
}
int num = start - length;
for (int i = start; i > num; i--)
{
if (s[i] == target)
{
return i;
}
}
return -1;
}
// Token: 0x06000812 RID: 2066 RVA: 0x0001CA88 File Offset: 0x0001AC88
private int LastIndexOfOrdinalIgnoreCase(string s, char target, int start, int length)
{
if (s.Length == 0)
{
return -1;
}
int num = start - length;
char c = this.textInfo.ToUpper(target);
for (int i = start; i > num; i--)
{
if (this.textInfo.ToUpper(s[i]) == c)
{
return i;
}
}
return -1;
}
// Token: 0x06000813 RID: 2067 RVA: 0x0001CAE4 File Offset: 0x0001ACE4
private unsafe int LastIndexOfSortKey(string s, int start, int orgStart, int length, byte* sortkey, int ti, bool noLv4, ref SimpleCollator.Context ctx)
{
int num = start - length;
int i = start;
while (i > num)
{
int num2 = i;
if (this.MatchesBackward(s, ref i, num, orgStart, ti, sortkey, noLv4, ref ctx))
{
return num2;
}
}
return -1;
}
// Token: 0x06000814 RID: 2068 RVA: 0x0001CB24 File Offset: 0x0001AD24
private unsafe int LastIndexOf(string s, string target, int start, int length, byte* targetSortKey, ref SimpleCollator.Context ctx)
{
CompareOptions option = ctx.Option;
int num = start;
int i;
for (i = 0; i < target.Length; i++)
{
if (!SimpleCollator.IsIgnorable((int)target[i], option))
{
break;
}
}
if (i == target.Length)
{
return start;
}
Contraction contraction = this.GetContraction(target, i, target.Length - i);
string text = ((contraction == null) ? null : contraction.Replacement);
byte* ptr = ((text != null) ? null : targetSortKey);
bool flag = true;
int num2 = -1;
if (contraction != null && ptr != null)
{
for (int j = 0; j < contraction.SortKey.Length; j++)
{
ptr[j] = contraction.SortKey[j];
}
}
else if (ptr != null)
{
num2 = this.FilterOptions((int)target[i], option);
*ptr = this.Category(num2);
ptr[1] = this.Level1(num2);
if ((option & CompareOptions.IgnoreNonSpace) == CompareOptions.None)
{
ptr[2] = this.Level2(num2, SimpleCollator.ExtenderType.None);
}
ptr[3] = MSCompatUnicodeTable.Level3(num2);
flag = !MSCompatUnicodeTable.HasSpecialWeight((char)num2);
}
if (ptr != null)
{
for (i++; i < target.Length; i++)
{
if (this.Category((int)target[i]) != 1)
{
break;
}
if (ptr[2] == 0)
{
ptr[2] = 2;
}
ptr[2] = ptr[2] + this.Level2((int)target[i], SimpleCollator.ExtenderType.None);
}
}
int k;
for (;;)
{
if (text != null)
{
k = this.LastIndexOf(s, text, start, length, targetSortKey, ref ctx);
}
else
{
k = this.LastIndexOfSortKey(s, start, num, length, ptr, num2, flag, ref ctx);
}
if (k < 0)
{
break;
}
length -= start - k;
start = k;
if (this.IsPrefix(s, target, k, num - k + 1, false, ref ctx))
{
goto Block_15;
}
Contraction contraction2 = this.GetContraction(s, k, num - k + 1);
if (contraction2 != null)
{
start -= contraction2.Source.Length;
length -= contraction2.Source.Length;
}
else
{
start--;
length--;
}
if (length <= 0)
{
return -1;
}
}
return -1;
Block_15:
while (k < num)
{
if (!SimpleCollator.IsIgnorable((int)s[k], option))
{
break;
}
k++;
}
return k;
}
// Token: 0x06000815 RID: 2069 RVA: 0x0001CD94 File Offset: 0x0001AF94
private unsafe bool MatchesForward(string s, ref int idx, int end, int ti, byte* sortkey, bool noLv4, ref SimpleCollator.Context ctx)
{
int num = (int)s[idx];
if (ctx.AlwaysMatchFlags != null && num < 128 && ((int)ctx.AlwaysMatchFlags[num / 8] & (1 << num % 8)) != 0)
{
return true;
}
if (ctx.NeverMatchFlags != null && num < 128 && ((int)ctx.NeverMatchFlags[num / 8] & (1 << num % 8)) != 0)
{
idx++;
return false;
}
SimpleCollator.ExtenderType extenderType = this.GetExtenderType((int)s[idx]);
Contraction contraction = null;
if (this.MatchesForwardCore(s, ref idx, end, ti, sortkey, noLv4, extenderType, ref contraction, ref ctx))
{
if (ctx.AlwaysMatchFlags != null && contraction == null && extenderType == SimpleCollator.ExtenderType.None && num < 128)
{
byte* ptr = ctx.AlwaysMatchFlags + num / 8;
*ptr |= (byte)(1 << num % 8);
}
return true;
}
if (ctx.NeverMatchFlags != null && contraction == null && extenderType == SimpleCollator.ExtenderType.None && num < 128)
{
byte* ptr2 = ctx.NeverMatchFlags + num / 8;
*ptr2 |= (byte)(1 << num % 8);
}
return false;
}
// Token: 0x06000816 RID: 2070 RVA: 0x0001CEBC File Offset: 0x0001B0BC
private unsafe bool MatchesForwardCore(string s, ref int idx, int end, int ti, byte* sortkey, bool noLv4, SimpleCollator.ExtenderType ext, ref Contraction ct, ref SimpleCollator.Context ctx)
{
CompareOptions option = ctx.Option;
byte* ptr = ctx.Buffer1;
bool flag = (option & CompareOptions.IgnoreNonSpace) != CompareOptions.None;
int num = -1;
if (ext == SimpleCollator.ExtenderType.None)
{
ct = this.GetContraction(s, idx, end);
}
else if (ctx.PrevCode < 0)
{
if (ctx.PrevSortKey == null)
{
idx++;
return false;
}
ptr = ctx.PrevSortKey;
}
else
{
num = this.FilterExtender(ctx.PrevCode, ext, option);
}
if (ct != null)
{
idx += ct.Source.Length;
if (!noLv4)
{
return false;
}
if (ct.SortKey == null)
{
int num2 = 0;
return this.MatchesForward(ct.Replacement, ref num2, ct.Replacement.Length, ti, sortkey, noLv4, ref ctx);
}
for (int i = 0; i < 4; i++)
{
ptr[i] = sortkey[i];
}
ctx.PrevCode = -1;
ctx.PrevSortKey = ptr;
}
else
{
if (num < 0)
{
num = this.FilterOptions((int)s[idx], option);
}
idx++;
*ptr = this.Category(num);
bool flag2 = false;
if (*sortkey == *ptr)
{
ptr[1] = this.Level1(num);
}
else
{
flag2 = true;
}
if (!flag && sortkey[1] == ptr[1])
{
ptr[2] = this.Level2(num, ext);
}
else if (!flag)
{
flag2 = true;
}
if (flag2)
{
while (idx < end)
{
if (this.Category((int)s[idx]) != 1)
{
break;
}
idx++;
}
return false;
}
ptr[3] = MSCompatUnicodeTable.Level3(num);
if (*ptr != 1)
{
ctx.PrevCode = num;
}
}
while (idx < end)
{
if (this.Category((int)s[idx]) != 1)
{
break;
}
if (!flag)
{
if (ptr[2] == 0)
{
ptr[2] = 2;
}
ptr[2] = ptr[2] + this.Level2((int)s[idx], SimpleCollator.ExtenderType.None);
}
idx++;
}
return this.MatchesPrimitive(option, ptr, num, ext, sortkey, ti, noLv4);
}
// Token: 0x06000817 RID: 2071 RVA: 0x0001D104 File Offset: 0x0001B304
private unsafe bool MatchesPrimitive(CompareOptions opt, byte* source, int si, SimpleCollator.ExtenderType ext, byte* target, int ti, bool noLv4)
{
bool flag = (opt & CompareOptions.IgnoreNonSpace) != CompareOptions.None;
return *source == *target && source[1] == target[1] && (flag || source[2] == target[2]) && source[3] == target[3] && ((noLv4 && (si < 0 || !MSCompatUnicodeTable.HasSpecialWeight((char)si))) || (!noLv4 && (flag || ext != SimpleCollator.ExtenderType.Conditional) && MSCompatUnicodeTable.IsJapaneseSmallLetter((char)si) == MSCompatUnicodeTable.IsJapaneseSmallLetter((char)ti) && SimpleCollator.ToDashTypeValue(ext, opt) == SimpleCollator.ToDashTypeValue(SimpleCollator.ExtenderType.None, opt) && !MSCompatUnicodeTable.IsHiragana((char)si) == !MSCompatUnicodeTable.IsHiragana((char)ti) && SimpleCollator.IsHalfKana((int)((ushort)si), opt) == SimpleCollator.IsHalfKana((int)((ushort)ti), opt)));
}
// Token: 0x06000818 RID: 2072 RVA: 0x0001D1E8 File Offset: 0x0001B3E8
private unsafe bool MatchesBackward(string s, ref int idx, int end, int orgStart, int ti, byte* sortkey, bool noLv4, ref SimpleCollator.Context ctx)
{
int num = (int)s[idx];
if (ctx.AlwaysMatchFlags != null && num < 128 && ((int)ctx.AlwaysMatchFlags[num / 8] & (1 << num % 8)) != 0)
{
return true;
}
if (ctx.NeverMatchFlags != null && num < 128 && ((int)ctx.NeverMatchFlags[num / 8] & (1 << num % 8)) != 0)
{
idx--;
return false;
}
SimpleCollator.ExtenderType extenderType = this.GetExtenderType((int)s[idx]);
Contraction contraction = null;
if (this.MatchesBackwardCore(s, ref idx, end, orgStart, ti, sortkey, noLv4, extenderType, ref contraction, ref ctx))
{
if (ctx.AlwaysMatchFlags != null && contraction == null && extenderType == SimpleCollator.ExtenderType.None && num < 128)
{
byte* ptr = ctx.AlwaysMatchFlags + num / 8;
*ptr |= (byte)(1 << num % 8);
}
return true;
}
if (ctx.NeverMatchFlags != null && contraction == null && extenderType == SimpleCollator.ExtenderType.None && num < 128)
{
byte* ptr2 = ctx.NeverMatchFlags + num / 8;
*ptr2 |= (byte)(1 << num % 8);
}
return false;
}
// Token: 0x06000819 RID: 2073 RVA: 0x0001D314 File Offset: 0x0001B514
private unsafe bool MatchesBackwardCore(string s, ref int idx, int end, int orgStart, int ti, byte* sortkey, bool noLv4, SimpleCollator.ExtenderType ext, ref Contraction ct, ref SimpleCollator.Context ctx)
{
CompareOptions option = ctx.Option;
byte* buffer = ctx.Buffer1;
bool flag = (option & CompareOptions.IgnoreNonSpace) != CompareOptions.None;
int num = idx;
int num2 = -1;
if (ext != SimpleCollator.ExtenderType.None)
{
byte b = 0;
for (int i = 0; i >= 0; i--)
{
if (!SimpleCollator.IsIgnorable((int)s[i], option))
{
int num3 = this.FilterOptions((int)s[i], option);
byte b2 = this.Category(num3);
if (b2 != 1)
{
num2 = this.FilterExtender(num3, ext, option);
*buffer = b2;
buffer[1] = this.Level1(num2);
if (!flag)
{
buffer[2] = this.Level2(num2, ext);
}
buffer[3] = MSCompatUnicodeTable.Level3(num2);
if (ext != SimpleCollator.ExtenderType.Conditional && b != 0)
{
buffer[2] = ((buffer[2] != 0) ? b : (b + 2));
}
idx--;
goto IL_101;
}
b = this.Level2(num3, SimpleCollator.ExtenderType.None);
}
}
return false;
}
IL_101:
if (ext == SimpleCollator.ExtenderType.None)
{
ct = this.GetTailContraction(s, idx, end);
}
if (ct != null)
{
idx -= ct.Source.Length;
if (!noLv4)
{
return false;
}
if (ct.SortKey == null)
{
int num4 = ct.Replacement.Length - 1;
return 0 <= this.LastIndexOfSortKey(ct.Replacement, num4, num4, ct.Replacement.Length, sortkey, ti, noLv4, ref ctx);
}
for (int j = 0; j < 4; j++)
{
buffer[j] = sortkey[j];
}
ctx.PrevCode = -1;
ctx.PrevSortKey = buffer;
}
else if (ext == SimpleCollator.ExtenderType.None)
{
if (num2 < 0)
{
num2 = this.FilterOptions((int)s[idx], option);
}
idx--;
bool flag2 = false;
*buffer = this.Category(num2);
if (*buffer == *sortkey)
{
buffer[1] = this.Level1(num2);
}
else
{
flag2 = true;
}
if (!flag && buffer[1] == sortkey[1])
{
buffer[2] = this.Level2(num2, ext);
}
else if (!flag)
{
flag2 = true;
}
if (flag2)
{
return false;
}
buffer[3] = MSCompatUnicodeTable.Level3(num2);
if (*buffer != 1)
{
ctx.PrevCode = num2;
}
}
if (ext == SimpleCollator.ExtenderType.None)
{
for (int k = num + 1; k < orgStart; k++)
{
if (this.Category((int)s[k]) != 1)
{
break;
}
if (!flag)
{
if (buffer[2] == 0)
{
buffer[2] = 2;
}
buffer[2] = buffer[2] + this.Level2((int)s[k], SimpleCollator.ExtenderType.None);
}
}
}
return this.MatchesPrimitive(option, buffer, num2, ext, sortkey, ti, noLv4);
}
// Token: 0x0400016B RID: 363
private const int UnsafeFlagLength = 96;
// Token: 0x0400016C RID: 364
private static bool QuickCheckDisabled = Environment.internalGetEnvironmentVariable("MONO_COLLATION_QUICK_CHECK_DISABLED") == "yes";
// Token: 0x0400016D RID: 365
private static SimpleCollator invariant = new SimpleCollator(CultureInfo.InvariantCulture);
// Token: 0x0400016E RID: 366
private readonly TextInfo textInfo;
// Token: 0x0400016F RID: 367
private readonly bool frenchSort;
// Token: 0x04000170 RID: 368
private unsafe readonly byte* cjkCatTable;
// Token: 0x04000171 RID: 369
private unsafe readonly byte* cjkLv1Table;
// Token: 0x04000172 RID: 370
private readonly CodePointIndexer cjkIndexer;
// Token: 0x04000173 RID: 371
private unsafe readonly byte* cjkLv2Table;
// Token: 0x04000174 RID: 372
private readonly CodePointIndexer cjkLv2Indexer;
// Token: 0x04000175 RID: 373
private readonly int lcid;
// Token: 0x04000176 RID: 374
private readonly Contraction[] contractions;
// Token: 0x04000177 RID: 375
private readonly Level2Map[] level2Maps;
// Token: 0x04000178 RID: 376
private readonly byte[] unsafeFlags;
// Token: 0x0200008B RID: 139
internal struct Context
{
// Token: 0x0600081A RID: 2074 RVA: 0x0001D600 File Offset: 0x0001B800
public unsafe Context(CompareOptions opt, byte* alwaysMatchFlags, byte* neverMatchFlags, byte* buffer1, byte* buffer2, byte* prev1, bool quickCheckPossible)
{
this.Option = opt;
this.AlwaysMatchFlags = alwaysMatchFlags;
this.NeverMatchFlags = neverMatchFlags;
this.Buffer1 = buffer1;
this.Buffer2 = buffer2;
this.PrevSortKey = prev1;
this.PrevCode = -1;
this.QuickCheckPossible = quickCheckPossible;
}
// Token: 0x0600081B RID: 2075 RVA: 0x0001D64C File Offset: 0x0001B84C
public void ClearPrevInfo()
{
this.PrevCode = -1;
this.PrevSortKey = null;
}
// Token: 0x04000179 RID: 377
public readonly CompareOptions Option;
// Token: 0x0400017A RID: 378
public unsafe readonly byte* NeverMatchFlags;
// Token: 0x0400017B RID: 379
public unsafe readonly byte* AlwaysMatchFlags;
// Token: 0x0400017C RID: 380
public unsafe byte* Buffer1;
// Token: 0x0400017D RID: 381
public unsafe byte* Buffer2;
// Token: 0x0400017E RID: 382
public int PrevCode;
// Token: 0x0400017F RID: 383
public unsafe byte* PrevSortKey;
// Token: 0x04000180 RID: 384
public readonly bool QuickCheckPossible;
}
// Token: 0x0200008C RID: 140
private struct PreviousInfo
{
// Token: 0x0600081C RID: 2076 RVA: 0x0001D660 File Offset: 0x0001B860
public PreviousInfo(bool dummy)
{
this.Code = -1;
this.SortKey = null;
}
// Token: 0x04000181 RID: 385
public int Code;
// Token: 0x04000182 RID: 386
public unsafe byte* SortKey;
}
// Token: 0x0200008D RID: 141
private struct Escape
{
// Token: 0x04000183 RID: 387
public string Source;
// Token: 0x04000184 RID: 388
public int Index;
// Token: 0x04000185 RID: 389
public int Start;
// Token: 0x04000186 RID: 390
public int End;
// Token: 0x04000187 RID: 391
public int Optional;
}
// Token: 0x0200008E RID: 142
private enum ExtenderType
{
// Token: 0x04000189 RID: 393
None,
// Token: 0x0400018A RID: 394
Simple,
// Token: 0x0400018B RID: 395
Voiced,
// Token: 0x0400018C RID: 396
Conditional,
// Token: 0x0400018D RID: 397
Buggy
}
}
}