Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit a959b76

Browse files
committed
Remove use of icu::Locale C++ type
Remove all the uses of the icu::Locale type in favor of just using a char* which is the raw locale id (which is exactly what all the ICU C apis use for a locale). The meat of this change si in locale.cpp to actually handle doing the conversion from UChar* to char*. The rest of the places are dealing with the fallout (GetLocale now has a different signiture and the .getName() dance is no longer needed as we have a raw locale name all the time now).
1 parent 787327a commit a959b76

File tree

5 files changed

+179
-128
lines changed

5 files changed

+179
-128
lines changed

src/corefx/System.Globalization.Native/calendarData.cpp

Lines changed: 34 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -209,12 +209,14 @@ Returns the list of CalendarIds that are available for the specified locale.
209209
*/
210210
extern "C" int32_t GetCalendars(const UChar* localeName, CalendarId* calendars, int32_t calendarsCapacity)
211211
{
212-
Locale locale = GetLocale(localeName);
213-
if (locale.isBogus())
212+
UErrorCode err = U_ZERO_ERROR;
213+
char locale[ULOC_FULLNAME_CAPACITY];
214+
GetLocale(localeName, locale, ULOC_FULLNAME_CAPACITY, false, &err);
215+
216+
if (U_FAILURE(err))
214217
return 0;
215218

216-
UErrorCode err = U_ZERO_ERROR;
217-
UEnumeration* pEnum = ucal_getKeywordValuesForLocale("calendar", locale.getName(), TRUE, &err);
219+
UEnumeration* pEnum = ucal_getKeywordValuesForLocale("calendar", locale, TRUE, &err);
218220
UEnumerationHolder enumHolder(pEnum, err);
219221

220222
if (U_FAILURE(err))
@@ -291,16 +293,19 @@ with the requested value.
291293
extern "C" CalendarDataResult GetCalendarInfo(
292294
const UChar* localeName, CalendarId calendarId, CalendarDataType dataType, UChar* result, int32_t resultCapacity)
293295
{
294-
Locale locale = GetLocale(localeName);
295-
if (locale.isBogus())
296+
UErrorCode err = U_ZERO_ERROR;
297+
char locale[ULOC_FULLNAME_CAPACITY];
298+
GetLocale(localeName, locale, ULOC_FULLNAME_CAPACITY, false, &err);
299+
300+
if (U_FAILURE(err))
296301
return UnknownError;
297302

298303
switch (dataType)
299304
{
300305
case NativeName:
301-
return GetNativeCalendarName(locale.getName(), calendarId, result, resultCapacity);
306+
return GetNativeCalendarName(locale, calendarId, result, resultCapacity);
302307
case MonthDay:
303-
return GetMonthDayPattern(locale.getName(), result, resultCapacity);
308+
return GetMonthDayPattern(locale, result, resultCapacity);
304309
default:
305310
assert(false);
306311
return UnknownError;
@@ -557,8 +562,11 @@ extern "C" int32_t EnumCalendarInfo(EnumCalendarInfoCallback callback,
557562
CalendarDataType dataType,
558563
const void* context)
559564
{
560-
Locale locale = GetLocale(localeName);
561-
if (locale.isBogus())
565+
UErrorCode err = U_ZERO_ERROR;
566+
char locale[ULOC_FULLNAME_CAPACITY];
567+
GetLocale(localeName, locale, ULOC_FULLNAME_CAPACITY, false, &err);
568+
569+
if (U_FAILURE(err))
562570
return false;
563571

564572
switch (dataType)
@@ -567,38 +575,37 @@ extern "C" int32_t EnumCalendarInfo(EnumCalendarInfoCallback callback,
567575
// ShortDates to map kShort and kMedium in ICU, but also adding the "yMd"
568576
// skeleton as well, as this
569577
// closely matches what is used on Windows
570-
return InvokeCallbackForDateTimePattern(
571-
locale.getName(), UDAT_YEAR_NUM_MONTH_DAY_UCHAR, callback, context) &&
572-
InvokeCallbackForDatePattern(locale.getName(), UDAT_SHORT, callback, context) &&
573-
InvokeCallbackForDatePattern(locale.getName(), UDAT_MEDIUM, callback, context);
578+
return InvokeCallbackForDateTimePattern(locale, UDAT_YEAR_NUM_MONTH_DAY_UCHAR, callback, context) &&
579+
InvokeCallbackForDatePattern(locale, UDAT_SHORT, callback, context) &&
580+
InvokeCallbackForDatePattern(locale, UDAT_MEDIUM, callback, context);
574581
case LongDates:
575582
// LongDates map to kFull and kLong in ICU.
576-
return InvokeCallbackForDatePattern(locale.getName(), UDAT_FULL, callback, context) &&
577-
InvokeCallbackForDatePattern(locale.getName(), UDAT_LONG, callback, context);
583+
return InvokeCallbackForDatePattern(locale, UDAT_FULL, callback, context) &&
584+
InvokeCallbackForDatePattern(locale, UDAT_LONG, callback, context);
578585
case YearMonths:
579-
return InvokeCallbackForDateTimePattern(locale.getName(), UDAT_YEAR_MONTH_UCHAR, callback, context);
586+
return InvokeCallbackForDateTimePattern(locale, UDAT_YEAR_MONTH_UCHAR, callback, context);
580587
case DayNames:
581-
return EnumSymbols(locale.getName(), calendarId, UDAT_STANDALONE_WEEKDAYS, 1, callback, context);
588+
return EnumSymbols(locale, calendarId, UDAT_STANDALONE_WEEKDAYS, 1, callback, context);
582589
case AbbrevDayNames:
583-
return EnumSymbols(locale.getName(), calendarId, UDAT_STANDALONE_SHORT_WEEKDAYS, 1, callback, context);
590+
return EnumSymbols(locale, calendarId, UDAT_STANDALONE_SHORT_WEEKDAYS, 1, callback, context);
584591
case MonthNames:
585-
return EnumSymbols(locale.getName(), calendarId, UDAT_STANDALONE_MONTHS, 0, callback, context);
592+
return EnumSymbols(locale, calendarId, UDAT_STANDALONE_MONTHS, 0, callback, context);
586593
case AbbrevMonthNames:
587-
return EnumSymbols(locale.getName(), calendarId, UDAT_STANDALONE_SHORT_MONTHS, 0, callback, context);
594+
return EnumSymbols(locale, calendarId, UDAT_STANDALONE_SHORT_MONTHS, 0, callback, context);
588595
case SuperShortDayNames:
589596
#ifdef HAVE_DTWIDTHTYPE_SHORT
590-
return EnumSymbols(locale.getName(), calendarId, UDAT_STANDALONE_SHORTER_WEEKDAYS, 1, callback, context);
597+
return EnumSymbols(locale, calendarId, UDAT_STANDALONE_SHORTER_WEEKDAYS, 1, callback, context);
591598
#else
592-
return EnumSymbols(locale.getName(), calendarId, UDAT_STANDALONE_NARROW_WEEKDAYS, 1, callback, context);
599+
return EnumSymbols(locale, calendarId, UDAT_STANDALONE_NARROW_WEEKDAYS, 1, callback, context);
593600
#endif
594601
case MonthGenitiveNames:
595-
return EnumSymbols(locale.getName(), calendarId, UDAT_MONTHS, 0, callback, context);
602+
return EnumSymbols(locale, calendarId, UDAT_MONTHS, 0, callback, context);
596603
case AbbrevMonthGenitiveNames:
597-
return EnumSymbols(locale.getName(), calendarId, UDAT_SHORT_MONTHS, 0, callback, context);
604+
return EnumSymbols(locale, calendarId, UDAT_SHORT_MONTHS, 0, callback, context);
598605
case EraNames:
599-
return EnumSymbols(locale.getName(), calendarId, UDAT_ERAS, 0, callback, context);
606+
return EnumSymbols(locale, calendarId, UDAT_ERAS, 0, callback, context);
600607
case AbbrevEraNames:
601-
return EnumAbbrevEraNames(locale.getName(), calendarId, callback, context);
608+
return EnumAbbrevEraNames(locale, calendarId, callback, context);
602609
default:
603610
assert(false);
604611
return false;

src/corefx/System.Globalization.Native/locale.cpp

Lines changed: 77 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -31,45 +31,76 @@ int32_t UErrorCodeToBool(UErrorCode status)
3131
return 0;
3232
}
3333

34-
Locale GetLocale(const UChar* localeName, bool canonize)
34+
int32_t GetLocale(
35+
const UChar* localeName, char* localeNameResult, int32_t localeNameResultLength, bool canonicalize, UErrorCode* err)
3536
{
36-
char localeNameTemp[ULOC_FULLNAME_CAPACITY];
37+
char localeNameTemp[ULOC_FULLNAME_CAPACITY] = {0};
38+
int32_t localeLength;
3739

38-
if (localeName != NULL)
40+
// Convert ourselves instead of doing u_UCharsToChars as that function considers '@' a variant and stops.
41+
for (int i = 0; i < ULOC_FULLNAME_CAPACITY - 1; i++)
3942
{
40-
// use UnicodeString.extract instead of u_UCharsToChars; u_UCharsToChars
41-
// considers '@' a variant and stops
42-
UnicodeString str(localeName, -1, ULOC_FULLNAME_CAPACITY);
43-
str.extract(0, str.length(), localeNameTemp);
43+
UChar c = localeName[i];
44+
45+
if (c > (UChar)0x7F)
46+
{
47+
*err = U_ILLEGAL_ARGUMENT_ERROR;
48+
return ULOC_FULLNAME_CAPACITY;
49+
}
50+
51+
localeNameTemp[i] = (char)c;
52+
53+
if (c == (UChar)0x0)
54+
{
55+
break;
56+
}
4457
}
4558

46-
Locale loc;
47-
if (canonize)
59+
if (canonicalize)
4860
{
49-
loc = Locale::createCanonical(localeName == NULL ? NULL : localeNameTemp);
61+
localeLength = uloc_canonicalize(localeNameTemp, localeNameResult, localeNameResultLength, err);
5062
}
5163
else
5264
{
53-
loc = Locale::createFromName(localeName == NULL ? NULL : localeNameTemp);
65+
localeLength = uloc_getName(localeNameTemp, localeNameResult, localeNameResultLength, err);
66+
}
67+
68+
if (U_SUCCESS(*err))
69+
{
70+
// Make sure the "language" part of the locale is reasonable (i.e. we can fetch it and it is within range).
71+
// This mimics how the C++ ICU API determines if a locale is "bogus" or not.
72+
73+
char language[ULOC_LANG_CAPACITY];
74+
uloc_getLanguage(localeNameTemp, language, ULOC_LANG_CAPACITY, err);
75+
76+
if (*err == U_STRING_NOT_TERMINATED_WARNING)
77+
{
78+
// ULOC_LANG_CAPACITY includes the null terminator, so if we couldn't extract the language with the null
79+
// terminator, the language must be invalid.
80+
81+
*err = U_ILLEGAL_ARGUMENT_ERROR;
82+
}
5483
}
5584

56-
return loc;
85+
return localeLength;
5786
}
5887

5988
UErrorCode u_charsToUChars_safe(const char* str, UChar* value, int32_t valueLength)
6089
{
6190
int len = strlen(str);
91+
6292
if (len >= valueLength)
6393
{
6494
return U_BUFFER_OVERFLOW_ERROR;
6595
}
96+
6697
u_charsToUChars(str, value, len + 1);
6798
return U_ZERO_ERROR;
6899
}
69100

70-
int FixupLocaleName(UChar* value, int32_t valueLength)
101+
int32_t FixupLocaleName(UChar* value, int32_t valueLength)
71102
{
72-
int i = 0;
103+
int32_t i = 0;
73104
for (; i < valueLength; i++)
74105
{
75106
if (value[i] == (UChar)'\0')
@@ -87,50 +118,55 @@ int FixupLocaleName(UChar* value, int32_t valueLength)
87118

88119
extern "C" int32_t GetLocaleName(const UChar* localeName, UChar* value, int32_t valueLength)
89120
{
90-
Locale locale = GetLocale(localeName, true);
91-
92-
if (locale.isBogus())
93-
{
94-
// localeName not properly formatted
95-
return UErrorCodeToBool(U_ILLEGAL_ARGUMENT_ERROR);
96-
}
121+
UErrorCode status = U_ZERO_ERROR;
97122

98-
// other validation done on managed side
123+
char localeNameBuffer[ULOC_FULLNAME_CAPACITY];
124+
GetLocale(localeName, localeNameBuffer, ULOC_FULLNAME_CAPACITY, true, &status);
99125

100-
UErrorCode status = u_charsToUChars_safe(locale.getName(), value, valueLength);
101126
if (U_SUCCESS(status))
102127
{
103-
FixupLocaleName(value, valueLength);
128+
status = u_charsToUChars_safe(localeNameBuffer, value, valueLength);
129+
130+
if (U_SUCCESS(status))
131+
{
132+
FixupLocaleName(value, valueLength);
133+
}
104134
}
105135

106136
return UErrorCodeToBool(status);
107137
}
108138

109139
extern "C" int32_t GetDefaultLocaleName(UChar* value, int32_t valueLength)
110140
{
111-
Locale locale = GetLocale(NULL);
112-
if (locale.isBogus())
113-
{
114-
// ICU should be able to get default locale
115-
return UErrorCodeToBool(U_INTERNAL_PROGRAM_ERROR);
116-
}
141+
char localeNameBuffer[ULOC_FULLNAME_CAPACITY];
142+
UErrorCode status = U_ZERO_ERROR;
143+
144+
const char* defaultLocale = uloc_getDefault();
145+
146+
uloc_getBaseName(defaultLocale, localeNameBuffer, ULOC_FULLNAME_CAPACITY, &status);
117147

118-
UErrorCode status = u_charsToUChars_safe(locale.getBaseName(), value, valueLength);
119148
if (U_SUCCESS(status))
120149
{
121-
int localeNameLen = FixupLocaleName(value, valueLength);
150+
status = u_charsToUChars_safe(localeNameBuffer, value, valueLength);
122151

123-
// if collation is present, return that to managed side
124-
char collationValueTemp[ULOC_KEYWORDS_CAPACITY];
125-
if (locale.getKeywordValue("collation", collationValueTemp, ULOC_KEYWORDS_CAPACITY, status) > 0)
152+
if (U_SUCCESS(status))
126153
{
127-
// copy the collation; managed uses a "_" to represent collation (not
128-
// "@collation=")
129-
status = u_charsToUChars_safe("_", &value[localeNameLen], valueLength - localeNameLen);
130-
if (U_SUCCESS(status))
154+
int localeNameLen = FixupLocaleName(value, valueLength);
155+
156+
char collationValueTemp[ULOC_KEYWORDS_CAPACITY];
157+
int32_t collationLen =
158+
uloc_getKeywordValue(defaultLocale, "collation", collationValueTemp, ULOC_KEYWORDS_CAPACITY, &status);
159+
160+
if (U_SUCCESS(status) && collationLen > 0)
131161
{
132-
status = u_charsToUChars_safe(
133-
collationValueTemp, &value[localeNameLen + 1], valueLength - localeNameLen - 1);
162+
// copy the collation; managed uses a "_" to represent collation (not
163+
// "@collation=")
164+
status = u_charsToUChars_safe("_", &value[localeNameLen], valueLength - localeNameLen);
165+
if (U_SUCCESS(status))
166+
{
167+
status = u_charsToUChars_safe(
168+
collationValueTemp, &value[localeNameLen + 1], valueLength - localeNameLen - 1);
169+
}
134170
}
135171
}
136172
}

src/corefx/System.Globalization.Native/locale.hpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,13 @@ int32_t UErrorCodeToBool(UErrorCode code);
2727
Function:
2828
GetLocale
2929
30-
Returns a locale given the locale name
30+
Converts a managed localeName into something ICU understands and can use as a localeName.
3131
*/
32-
Locale GetLocale(const UChar* localeName, bool canonize = false);
32+
int32_t GetLocale(const UChar* localeName,
33+
char* localeNameResult,
34+
int32_t localeNameResultLength,
35+
bool canonicalize,
36+
UErrorCode* err);
3337

3438
/*
3539
Function:

0 commit comments

Comments
 (0)