Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,28 @@ internal static partial class Interop
internal static unsafe partial class Kernel32
{
internal const uint LOCALE_ALLOW_NEUTRAL_NAMES = 0x08000000; // Flag to allow returning neutral names/lcids for name conversion
internal const uint LOCALE_ILANGUAGE = 0x00000001;
internal const uint LOCALE_SUPPLEMENTAL = 0x00000002;
internal const uint LOCALE_REPLACEMENT = 0x00000008;
internal const uint LOCALE_NEUTRALDATA = 0x00000010;
internal const uint LOCALE_SPECIFICDATA = 0x00000020;
internal const uint LOCALE_SISO3166CTRYNAME = 0x0000005A;
internal const uint LOCALE_SNAME = 0x0000005C;
internal const uint LOCALE_INEUTRAL = 0x00000071;
internal const uint LOCALE_SSHORTTIME = 0x00000079;
internal const uint LOCALE_STIMEFORMAT = 0x00001003;
internal const uint LOCALE_IFIRSTDAYOFWEEK = 0x0000100C;
internal const uint LOCALE_RETURN_NUMBER = 0x20000000;
internal const uint LOCALE_NOUSEROVERRIDE = 0x80000000;

internal const int COMPARE_STRING = 0x0001;

internal const uint TIME_NOSECONDS = 0x00000002;

internal const string LOCALE_NAME_USER_DEFAULT = null;
internal const string LOCALE_NAME_SYSTEM_DEFAULT = "!x-sys-default-locale";


[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
internal static extern unsafe int LCIDToLocaleName(int locale, char *pLocaleName, int cchName, uint dwFlags);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,7 @@
<Compile Include="$(MSBuildThisFileDirectory)System\Globalization\ChineseLunisolarCalendar.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Globalization\CompareInfo.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Globalization\CompareInfo.Invariant.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Globalization\CompareOptions.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Globalization\CultureNotFoundException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Globalization\CultureTypes.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Globalization\DateTimeFormat.cs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -455,13 +455,9 @@ private static unsafe string GetUserDefaultLocaleName()
{
Debug.Assert(!GlobalizationMode.Invariant);

const int LOCALE_NAME_MAX_LENGTH = 85;
const uint LOCALE_SNAME = 0x0000005c;
const string LOCALE_NAME_USER_DEFAULT = null;

int result;
char* localeName = stackalloc char[LOCALE_NAME_MAX_LENGTH];
result = CultureData.GetLocaleInfoEx(LOCALE_NAME_USER_DEFAULT, LOCALE_SNAME, localeName, LOCALE_NAME_MAX_LENGTH);
char* localeName = stackalloc char[Interop.Kernel32.LOCALE_NAME_MAX_LENGTH];
result = CultureData.GetLocaleInfoEx(Interop.Kernel32.LOCALE_NAME_USER_DEFAULT, Interop.Kernel32.LOCALE_SNAME, localeName, Interop.Kernel32.LOCALE_NAME_MAX_LENGTH);

return result <= 0 ? "" : new string(localeName, 0, result - 1); // exclude the null termination
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,20 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

////////////////////////////////////////////////////////////////////////////
//
//
// Purpose: This class implements a set of methods for retrieving
// character type information. Character type information is
// independent of culture and region.
//
//
////////////////////////////////////////////////////////////////////////////

using System.Buffers.Binary;
using System.Diagnostics;
using System.Text;
using Internal.Runtime.CompilerServices;

namespace System.Globalization
{
/// <summary>
/// This class implements a set of methods for retrieving character type
/// information. Character type information is independent of culture
/// and region.
/// </summary>
public static partial class CharUnicodeInfo
{
//--------------------------------------------------------------------//
// Internal Information //
//--------------------------------------------------------------------//

//
// Native methods to access the Unicode category data tables in charinfo.nlp.
//
internal const char HIGH_SURROGATE_START = '\ud800';
internal const char HIGH_SURROGATE_END = '\udbff';
internal const char LOW_SURROGATE_START = '\udc00';
Expand All @@ -40,19 +28,14 @@ public static partial class CharUnicodeInfo
// The starting codepoint for Unicode plane 1. Plane 1 contains 0x010000 ~ 0x01ffff.
internal const int UNICODE_PLANE01_START = 0x10000;


////////////////////////////////////////////////////////////////////////
//
// Actions:
// Convert the BMP character or surrogate pointed by index to a UTF32 value.
// This is similar to char.ConvertToUTF32, but the difference is that
// it does not throw exceptions when invalid surrogate characters are passed in.
//
// WARNING: since it doesn't throw an exception it CAN return a value
// in the surrogate range D800-DFFF, which are not legal unicode values.
//
////////////////////////////////////////////////////////////////////////

/// <summary>
/// Convert the BMP character or surrogate pointed by index to a UTF32 value.
/// This is similar to char.ConvertToUTF32, but the difference is that
/// it does not throw exceptions when invalid surrogate characters are passed in.
///
/// WARNING: since it doesn't throw an exception it CAN return a value
/// in the surrogate range D800-DFFF, which are not legal unicode values.
/// </summary>
internal static int InternalConvertToUtf32(string s, int index)
{
Debug.Assert(s != null, "s != null");
Expand All @@ -70,7 +53,7 @@ internal static int InternalConvertToUtf32(string s, int index)
}
}
}
return ((int)s[index]);
return (int)s[index];
}

internal static int InternalConvertToUtf32(StringBuilder s, int index)
Expand All @@ -88,35 +71,19 @@ internal static int InternalConvertToUtf32(StringBuilder s, int index)
if ((uint)temp2 <= HIGH_SURROGATE_RANGE)
{
// Convert the surrogate to UTF32 and get the result.
return ((temp1 * 0x400) + temp2 + UNICODE_PLANE01_START);
return (temp1 * 0x400) + temp2 + UNICODE_PLANE01_START;
}
}
}
return c;
}

////////////////////////////////////////////////////////////////////////
//
// Convert a character or a surrogate pair starting at index of string s
// to UTF32 value.
//
// Parameters:
// s The string
// index The starting index. It can point to a BMP character or
// a surrogate pair.
// len The length of the string.
// charLength [out] If the index points to a BMP char, charLength
// will be 1. If the index points to a surrogate pair,
// charLength will be 2.
//
// WARNING: since it doesn't throw an exception it CAN return a value
// in the surrogate range D800-DFFF, which are not legal unicode values.
//
// Returns:
// The UTF32 value
//
////////////////////////////////////////////////////////////////////////

/// <summary>
/// Convert a character or a surrogate pair starting at index of string s
/// to UTF32 value.
/// WARNING: since it doesn't throw an exception it CAN return a value
/// in the surrogate range D800-DFFF, which are not legal unicode values.
/// </summary>
internal static int InternalConvertToUtf32(string s, int index, out int charLength)
{
Debug.Assert(s != null, "s != null");
Expand All @@ -140,10 +107,11 @@ internal static int InternalConvertToUtf32(string s, int index, out int charLeng
return ((int)s[index]);
}

//
// This is called by the public char and string, index versions
//
// Note that for ch in the range D800-DFFF we just treat it as any other non-numeric character
/// <summary>
/// This is called by the public char and string, index versions
/// Note that for ch in the range D800-DFFF we just treat it as any
/// other non-numeric character
/// </summary>
internal static double InternalGetNumericValue(int ch)
{
Debug.Assert(ch >= 0 && ch <= 0x10ffff, "ch is not in valid Unicode range.");
Expand All @@ -159,7 +127,10 @@ internal static double InternalGetNumericValue(int ch)
ref var value = ref Unsafe.AsRef(in NumericValues[index * 8]);

if (BitConverter.IsLittleEndian)
{
return Unsafe.ReadUnaligned<double>(ref value);
}

return BitConverter.Int64BitsToDouble(BinaryPrimitives.ReverseEndianness(Unsafe.ReadUnaligned<long>(ref value)));
}
return -1;
Expand All @@ -182,28 +153,17 @@ internal static byte InternalGetDigitValues(int ch, int offset)
return 0xff;
}

////////////////////////////////////////////////////////////////////////
//
//Returns the numeric value associated with the character c. If the character is a fraction,
// the return value will not be an integer. If the character does not have a numeric value, the return value is -1.
//
//Returns:
// the numeric value for the specified Unicode character. If the character does not have a numeric value, the return value is -1.
//Arguments:
// ch a Unicode character
//Exceptions:
// ArgumentNullException
// ArgumentOutOfRangeException
//
////////////////////////////////////////////////////////////////////////


/// <summary>
/// Returns the numeric value associated with the character c.
/// If the character is a fraction, the return value will not be an
/// integer. If the character does not have a numeric value, the return
/// value is -1.
/// </summary>
public static double GetNumericValue(char ch)
{
return (InternalGetNumericValue(ch));
return InternalGetNumericValue(ch);
}


public static double GetNumericValue(string s, int index)
{
if (s == null)
Expand All @@ -214,7 +174,8 @@ public static double GetNumericValue(string s, int index)
{
throw new ArgumentOutOfRangeException(nameof(index), SR.ArgumentOutOfRange_Index);
}
return (InternalGetNumericValue(InternalConvertToUtf32(s, index)));

return InternalGetNumericValue(InternalConvertToUtf32(s, index));
}

public static int GetDecimalDigitValue(char ch)
Expand All @@ -228,7 +189,6 @@ public static int GetDecimalDigitValue(string s, int index)
{
throw new ArgumentNullException(nameof(s));
}

if (index < 0 || index >= s.Length)
{
throw new ArgumentOutOfRangeException(nameof(index), SR.ArgumentOutOfRange_Index);
Expand All @@ -248,7 +208,6 @@ public static int GetDigitValue(string s, int index)
{
throw new ArgumentNullException(nameof(s));
}

if (index < 0 || index >= s.Length)
{
throw new ArgumentOutOfRangeException(nameof(index), SR.ArgumentOutOfRange_Index);
Expand All @@ -259,40 +218,32 @@ public static int GetDigitValue(string s, int index)

public static UnicodeCategory GetUnicodeCategory(char ch)
{
return (GetUnicodeCategory((int)ch));
return GetUnicodeCategory((int)ch);
}

public static UnicodeCategory GetUnicodeCategory(string s, int index)
{
if (s == null)
{
throw new ArgumentNullException(nameof(s));
}
if (((uint)index) >= ((uint)s.Length))
{
throw new ArgumentOutOfRangeException(nameof(index));
}

return InternalGetUnicodeCategory(s, index);
}

public static UnicodeCategory GetUnicodeCategory(int codePoint)
{
return ((UnicodeCategory)InternalGetCategoryValue(codePoint, UNICODE_CATEGORY_OFFSET));
return (UnicodeCategory)InternalGetCategoryValue(codePoint, UNICODE_CATEGORY_OFFSET);
}


////////////////////////////////////////////////////////////////////////
//
//Action: Returns the Unicode Category property for the character c.
//Returns:
// an value in UnicodeCategory enum
//Arguments:
// ch a Unicode character
//Exceptions:
// None
//
//Note that this API will return values for D800-DF00 surrogate halves.
//
////////////////////////////////////////////////////////////////////////

/// <summary>
/// Returns the Unicode Category property for the character c.
/// Note that this API will return values for D800-DF00 surrogate halves.
/// </summary>
internal static byte InternalGetCategoryValue(int ch, int offset)
{
Debug.Assert(ch >= 0 && ch <= 0x10ffff, "ch is not in valid Unicode range.");
Expand All @@ -302,26 +253,18 @@ internal static byte InternalGetCategoryValue(int ch, int offset)
// Note that & has the lower precedence than addition, so don't forget the parathesis.
index = Unsafe.ReadUnaligned<ushort>(ref Unsafe.AsRef(in CategoryLevel2Index[(index << 6) + ((ch >> 3) & 0b111110)]));
if (!BitConverter.IsLittleEndian)
{
index = BinaryPrimitives.ReverseEndianness((ushort)index);
}

// Get the result from the 0 -3 bit of ch.
index = CategoryLevel3Index[(index << 4) + (ch & 0x000f)];
return CategoriesValue[index * 2 + offset];
}

////////////////////////////////////////////////////////////////////////
//
//Action: Returns the Unicode Category property for the character c.
//Returns:
// an value in UnicodeCategory enum
//Arguments:
// value a Unicode String
// index Index for the specified string.
//Exceptions:
// None
//
////////////////////////////////////////////////////////////////////////

/// <summary>
/// Returns the Unicode Category property for the character c.
/// </summary>
internal static UnicodeCategory InternalGetUnicodeCategory(string value, int index)
{
Debug.Assert(value != null, "value can not be null");
Expand All @@ -333,8 +276,9 @@ internal static UnicodeCategory InternalGetUnicodeCategory(string value, int ind
internal static BidiCategory GetBidiCategory(string s, int index)
{
if (s == null)
{
throw new ArgumentNullException(nameof(s));

}
if (((uint)index) >= ((uint)s.Length))
{
throw new ArgumentOutOfRangeException(nameof(index));
Expand All @@ -351,20 +295,17 @@ internal static BidiCategory GetBidiCategory(StringBuilder s, int index)
return ((BidiCategory) InternalGetCategoryValue(InternalConvertToUtf32(s, index), BIDI_CATEGORY_OFFSET));
}

////////////////////////////////////////////////////////////////////////
//
// Get the Unicode category of the character starting at index. If the character is in BMP, charLength will return 1.
// If the character is a valid surrogate pair, charLength will return 2.
//
////////////////////////////////////////////////////////////////////////

/// <summary>
/// Get the Unicode category of the character starting at index. If the character is in BMP, charLength will return 1.
/// If the character is a valid surrogate pair, charLength will return 2.
/// </summary>
internal static UnicodeCategory InternalGetUnicodeCategory(string str, int index, out int charLength)
{
Debug.Assert(str != null, "str can not be null");
Debug.Assert(str.Length > 0, "str.Length > 0"); ;
Debug.Assert(index >= 0 && index < str.Length, "index >= 0 && index < str.Length");

return (GetUnicodeCategory(InternalConvertToUtf32(str, index, out charLength)));
return GetUnicodeCategory(InternalConvertToUtf32(str, index, out charLength));
}

internal static bool IsCombiningCategory(UnicodeCategory uc)
Expand Down
Loading