6992685b86
Former-commit-id: 0a113cb3a6feb7873f632839b1307cc6033cd595
201 lines
5.1 KiB
C#
201 lines
5.1 KiB
C#
using System.Runtime.CompilerServices;
|
|
|
|
namespace System.Globalization
|
|
{
|
|
partial class TextInfo
|
|
{
|
|
unsafe static ushort *to_lower_data_low;
|
|
unsafe static ushort *to_lower_data_high;
|
|
unsafe static ushort *to_upper_data_low;
|
|
unsafe static ushort *to_upper_data_high;
|
|
|
|
[MethodImplAttribute(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]
|
|
unsafe static extern void GetDataTablePointersLite (out ushort *to_lower_data_low, out ushort *to_lower_data_high, out ushort *to_upper_data_low, out ushort *to_upper_data_high);
|
|
|
|
static readonly object cookie = new object ();
|
|
|
|
unsafe static void ReadDataTable ()
|
|
{
|
|
if (to_lower_data_low == null) {
|
|
lock (cookie) {
|
|
if (to_lower_data_low != null)
|
|
return;
|
|
|
|
GetDataTablePointersLite (out to_lower_data_low, out to_lower_data_high, out to_upper_data_low, out to_upper_data_high);
|
|
}
|
|
}
|
|
}
|
|
|
|
unsafe string ToUpperInternal (string str)
|
|
{
|
|
if (str.Length == 0)
|
|
return String.Empty;
|
|
|
|
string tmp = String.FastAllocateString (str.Length);
|
|
fixed (char* source = str, dest = tmp) {
|
|
|
|
char* destPtr = (char*)dest;
|
|
char* sourcePtr = (char*)source;
|
|
|
|
for (int n = 0; n < str.Length; n++) {
|
|
*destPtr = ToUpper (*sourcePtr);
|
|
sourcePtr++;
|
|
destPtr++;
|
|
}
|
|
}
|
|
return tmp;
|
|
}
|
|
|
|
unsafe string ToLowerInternal (string str)
|
|
{
|
|
if (str.Length == 0)
|
|
return String.Empty;
|
|
|
|
string tmp = String.FastAllocateString (str.Length);
|
|
fixed (char* source = str, dest = tmp) {
|
|
|
|
char* destPtr = (char*)dest;
|
|
char* sourcePtr = (char*)source;
|
|
|
|
for (int n = 0; n < str.Length; n++) {
|
|
*destPtr = ToLower (*sourcePtr);
|
|
sourcePtr++;
|
|
destPtr++;
|
|
}
|
|
}
|
|
return tmp;
|
|
}
|
|
|
|
char ToUpperInternal (char c)
|
|
{
|
|
switch (c) {
|
|
case '\u0069': // Latin lowercase i
|
|
if (!IsAsciiCasingSameAsInvariant)
|
|
return '\u0130'; // dotted capital I
|
|
break;
|
|
case '\u0131': // dotless i
|
|
return '\u0049'; // I
|
|
|
|
case '\u01c5': // see ToLower()
|
|
return '\u01c4';
|
|
case '\u01c8': // see ToLower()
|
|
return '\u01c7';
|
|
case '\u01cb': // see ToLower()
|
|
return '\u01ca';
|
|
case '\u01f2': // see ToLower()
|
|
return '\u01f1';
|
|
case '\u0390': // GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS
|
|
return '\u03aa'; // it is not in ICU
|
|
case '\u03b0': // GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS
|
|
return '\u03ab'; // it is not in ICU
|
|
case '\u03d0': // GREEK BETA
|
|
return '\u0392';
|
|
case '\u03d1': // GREEK THETA
|
|
return '\u0398';
|
|
case '\u03d5': // GREEK PHI
|
|
return '\u03a6';
|
|
case '\u03d6': // GREEK PI
|
|
return '\u03a0';
|
|
case '\u03f0': // GREEK KAPPA
|
|
return '\u039a';
|
|
case '\u03f1': // GREEK RHO
|
|
return '\u03a1';
|
|
// am not sure why miscellaneous GREEK symbols are
|
|
// not handled here.
|
|
}
|
|
|
|
return ToUpperInvariant (c);
|
|
}
|
|
|
|
char ToLowerInternal (char c)
|
|
{
|
|
switch (c) {
|
|
case '\u0049': // Latin uppercase I
|
|
if (!IsAsciiCasingSameAsInvariant)
|
|
return '\u0131'; // I becomes dotless i
|
|
break;
|
|
case '\u0130': // I-dotted
|
|
return '\u0069'; // i
|
|
|
|
case '\u01c5': // LATIN CAPITAL LETTER D WITH SMALL LETTER Z WITH CARON
|
|
return '\u01c6';
|
|
// \u01c7 -> \u01c9 (LJ) : invariant
|
|
case '\u01c8': // LATIN CAPITAL LETTER L WITH SMALL LETTER J
|
|
return '\u01c9';
|
|
// \u01ca -> \u01cc (NJ) : invariant
|
|
case '\u01cb': // LATIN CAPITAL LETTER N WITH SMALL LETTER J
|
|
return '\u01cc';
|
|
// WITH CARON : invariant
|
|
// WITH DIAERESIS AND * : invariant
|
|
|
|
case '\u01f2': // LATIN CAPITAL LETTER D WITH SMALL LETTER Z
|
|
return '\u01f3';
|
|
case '\u03d2': // ? it is not in ICU
|
|
return '\u03c5';
|
|
case '\u03d3': // ? it is not in ICU
|
|
return '\u03cd';
|
|
case '\u03d4': // ? it is not in ICU
|
|
return '\u03cb';
|
|
}
|
|
return ToLowerInvariant (c);
|
|
}
|
|
|
|
static char ToLowerInvariant (char c)
|
|
{
|
|
ReadDataTable ();
|
|
|
|
unsafe {
|
|
if (c <= ((char)0x24cf))
|
|
return (char) to_lower_data_low [c];
|
|
if (c >= ((char)0xff21))
|
|
return (char) to_lower_data_high[c - 0xff21];
|
|
}
|
|
return c;
|
|
}
|
|
|
|
static char ToUpperInvariant (char c)
|
|
{
|
|
ReadDataTable ();
|
|
|
|
unsafe {
|
|
if (c <= ((char)0x24e9))
|
|
return (char) to_upper_data_low [c];
|
|
if (c >= ((char)0xff21))
|
|
return (char) to_upper_data_high [c - 0xff21];
|
|
}
|
|
return c;
|
|
}
|
|
|
|
static unsafe int InternalCompareStringOrdinalIgnoreCase (String strA, int indexA, String strB, int indexB, int lenA, int lenB)
|
|
{
|
|
if (strA == null) {
|
|
return strB == null ? 0 : -1;
|
|
}
|
|
if (strB == null) {
|
|
return 1;
|
|
}
|
|
int lengthA = Math.Min (lenA, strA.Length - indexA);
|
|
int lengthB = Math.Min (lenB, strB.Length - indexB);
|
|
|
|
if (lengthA == lengthB && Object.ReferenceEquals (strA, strB))
|
|
return 0;
|
|
|
|
fixed (char* aptr = strA, bptr = strB) {
|
|
char* ap = aptr + indexA;
|
|
char* end = ap + Math.Min (lengthA, lengthB);
|
|
char* bp = bptr + indexB;
|
|
while (ap < end) {
|
|
if (*ap != *bp) {
|
|
char c1 = Char.ToUpperInvariant (*ap);
|
|
char c2 = Char.ToUpperInvariant (*bp);
|
|
if (c1 != c2)
|
|
return c1 - c2;
|
|
}
|
|
ap++;
|
|
bp++;
|
|
}
|
|
return lengthA - lengthB;
|
|
}
|
|
}
|
|
}
|
|
} |