@@ -7,21 +7,23 @@ namespace System.Globalization
7
7
{
8
8
internal sealed partial class CultureData
9
9
{
10
+ private const int LOC_FULLNAME_CAPACITY = 157 ; // max size of locale name
11
+
10
12
/// <summary>
11
13
/// This method uses the sRealName field (which is initialized by the constructor before this is called) to
12
14
/// initialize the rest of the state of CultureData based on the underlying OS globalization library.
13
15
/// </summary>
14
- private bool InitNativeCultureDataCore ( )
16
+ private bool InitAppleCultureDataCore ( )
15
17
{
16
18
Debug . Assert ( _sRealName != null ) ;
17
19
Debug . Assert ( ! GlobalizationMode . Invariant ) ;
18
20
string realNameBuffer = _sRealName ;
19
21
20
- _sWindowsName = GetLocaleNameNative ( realNameBuffer ) ;
22
+ _sWindowsName = _sName = _sRealName = GetLocaleNameNative ( realNameBuffer ) ;
21
23
return true ;
22
24
}
23
25
24
- internal static unsafe string GetLocaleNameNative ( string localeName )
26
+ internal static string GetLocaleNameNative ( string localeName )
25
27
{
26
28
return Interop . Globalization . GetLocaleNameNative ( localeName ) ;
27
29
}
@@ -36,11 +38,111 @@ private string GetLocaleInfoNative(LocaleStringData type)
36
38
37
39
// For LOCALE_SPARENT we need the option of using the "real" name (forcing neutral names) instead of the
38
40
// "windows" name, which can be specific for downlevel (< windows 7) os's.
39
- private static unsafe string GetLocaleInfoNative ( string localeName , LocaleStringData type )
41
+ private static string GetLocaleInfoNative ( string localeName , LocaleStringData type )
40
42
{
41
43
Debug . Assert ( localeName != null , "[CultureData.GetLocaleInfoNative] Expected localeName to be not be null" ) ;
42
44
43
45
return Interop . Globalization . GetLocaleInfoStringNative ( localeName , ( uint ) type ) ;
44
46
}
47
+
48
+ private int GetLocaleInfoNative ( LocaleNumberData type )
49
+ {
50
+ Debug . Assert ( _sWindowsName != null , "[CultureData.GetLocaleInfoNative(LocaleNumberData)] Expected _sWindowsName to be populated already" ) ;
51
+
52
+ // returning 0 will cause the first supported calendar to be returned, which is the preferred calendar
53
+ if ( type == LocaleNumberData . CalendarType )
54
+ return 0 ;
55
+
56
+ int value = Interop . Globalization . GetLocaleInfoIntNative ( _sWindowsName , ( uint ) type ) ;
57
+ const int DEFAULT_VALUE = 0 ;
58
+ if ( value < 0 )
59
+ {
60
+ Debug . Fail ( "[CultureData.GetLocaleInfoNative(LocaleNumberData)] failed" ) ;
61
+ return DEFAULT_VALUE ;
62
+ }
63
+
64
+ return value ;
65
+ }
66
+
67
+ private int [ ] GetLocaleInfoNative ( LocaleGroupingData type )
68
+ {
69
+ Debug . Assert ( _sWindowsName != null , "[CultureData.GetLocaleInfoNative(LocaleGroupingData)] Expected _sWindowsName to be populated already" ) ;
70
+
71
+ int primaryGroupingSize = Interop . Globalization . GetLocaleInfoPrimaryGroupingSizeNative ( _sWindowsName , ( uint ) type ) ;
72
+ int secondaryGroupingSize = Interop . Globalization . GetLocaleInfoSecondaryGroupingSizeNative ( _sWindowsName , ( uint ) type ) ;
73
+
74
+ if ( secondaryGroupingSize == 0 )
75
+ {
76
+ return new int [ ] { primaryGroupingSize } ;
77
+ }
78
+
79
+ return new int [ ] { primaryGroupingSize , secondaryGroupingSize } ;
80
+ }
81
+
82
+ private string GetTimeFormatStringNative ( ) => GetTimeFormatStringNative ( shortFormat : false ) ;
83
+
84
+ private string GetTimeFormatStringNative ( bool shortFormat )
85
+ {
86
+ Debug . Assert ( _sWindowsName != null , "[CultureData.GetTimeFormatStringNative(bool shortFormat)] Expected _sWindowsName to be populated already" ) ;
87
+
88
+ string result = Interop . Globalization . GetLocaleTimeFormatNative ( _sWindowsName , shortFormat ) ;
89
+
90
+ return ConvertNativeTimeFormatString ( result ) ;
91
+ }
92
+
93
+ private static string ConvertNativeTimeFormatString ( string nativeFormatString )
94
+ {
95
+ Span < char > result = stackalloc char [ LOC_FULLNAME_CAPACITY ] ;
96
+
97
+ bool amPmAdded = false ;
98
+ int resultPos = 0 ;
99
+
100
+ for ( int i = 0 ; i < nativeFormatString . Length ; i ++ )
101
+ {
102
+ switch ( nativeFormatString [ i ] )
103
+ {
104
+ case '\' ' :
105
+ result [ resultPos ++ ] = nativeFormatString [ i ++ ] ;
106
+ while ( i < nativeFormatString . Length )
107
+ {
108
+ char current = nativeFormatString [ i ] ;
109
+ result [ resultPos ++ ] = current ;
110
+ if ( current == '\' ' )
111
+ {
112
+ break ;
113
+ }
114
+ i ++ ;
115
+ }
116
+ break ;
117
+
118
+ case ':' :
119
+ case '.' :
120
+ case 'H' :
121
+ case 'h' :
122
+ case 'm' :
123
+ case 's' :
124
+ result [ resultPos ++ ] = nativeFormatString [ i ] ;
125
+ break ;
126
+
127
+ case ' ' :
128
+ case '\u00A0 ' :
129
+ // Convert nonbreaking spaces into regular spaces
130
+ result [ resultPos ++ ] = ' ' ;
131
+ break ;
132
+
133
+ case 'a' : // AM/PM
134
+ if ( ! amPmAdded )
135
+ {
136
+ amPmAdded = true ;
137
+ result [ resultPos ++ ] = 't' ;
138
+ result [ resultPos ++ ] = 't' ;
139
+ }
140
+ break ;
141
+
142
+ }
143
+ }
144
+
145
+ return result . Slice ( 0 , resultPos ) . ToString ( ) ;
146
+ }
45
147
}
46
148
}
0 commit comments