Update release

This commit is contained in:
vczh
2025-07-18 18:40:47 -07:00
parent 901afd35ea
commit 019a7b10f4
18 changed files with 4288 additions and 4203 deletions
+199 -180
View File
@@ -625,6 +625,10 @@ namespace vl
{
using namespace collections;
/***********************************************************************
Locale Helper Functions
***********************************************************************/
SYSTEMTIME DateTimeToSystemTime(const DateTime& dateTime)
{
SYSTEMTIME systemTime;
@@ -691,115 +695,206 @@ namespace vl
}
/***********************************************************************
Locale
WindowsLocaleImpl
***********************************************************************/
Locale Locale::Invariant()
class WindowsLocaleImpl : public Object, public ILocaleImpl
{
return Locale(LOCALE_NAME_INVARIANT);
public:
Locale Invariant() const override
{
return Locale(LOCALE_NAME_INVARIANT);
}
Locale SystemDefault() const override
{
wchar_t buffer[LOCALE_NAME_MAX_LENGTH + 1] = { 0 };
GetSystemDefaultLocaleName(buffer, LOCALE_NAME_MAX_LENGTH);
return Locale(buffer);
}
Locale UserDefault() const override
{
wchar_t buffer[LOCALE_NAME_MAX_LENGTH + 1] = { 0 };
GetUserDefaultLocaleName(buffer, LOCALE_NAME_MAX_LENGTH);
return Locale(buffer);
}
void Enumerate(collections::List<Locale>& locales) const override
{
EnumSystemLocalesEx(&Locale_EnumLocalesProcEx, LOCALE_ALL, (LPARAM)&locales, NULL);
}
void GetShortDateFormats(const WString& localeName, collections::List<WString>& formats) const override
{
EnumDateFormatsExEx(&Locale_EnumDateFormatsProcExEx, localeName.Buffer(), DATE_SHORTDATE, (LPARAM)&formats);
}
void GetLongDateFormats(const WString& localeName, collections::List<WString>& formats) const override
{
EnumDateFormatsExEx(&Locale_EnumDateFormatsProcExEx, localeName.Buffer(), DATE_LONGDATE, (LPARAM)&formats);
}
void GetYearMonthDateFormats(const WString& localeName, collections::List<WString>& formats) const override
{
EnumDateFormatsExEx(&Locale_EnumDateFormatsProcExEx, localeName.Buffer(), DATE_YEARMONTH, (LPARAM)&formats);
}
void GetLongTimeFormats(const WString& localeName, collections::List<WString>& formats) const override
{
EnumTimeFormatsEx(&EnumTimeFormatsProcEx, localeName.Buffer(), 0, (LPARAM)&formats);
}
void GetShortTimeFormats(const WString& localeName, collections::List<WString>& formats) const override
{
EnumTimeFormatsEx(&EnumTimeFormatsProcEx, localeName.Buffer(), TIME_NOSECONDS, (LPARAM)&formats);
}
WString FormatDate(const WString& localeName, const WString& format, DateTime date) const override
{
SYSTEMTIME st = DateTimeToSystemTime(date);
int length = GetDateFormatEx(localeName.Buffer(), 0, &st, format.Buffer(), NULL, 0, NULL);
if (length == 0) return L"";
Array<wchar_t> buffer(length);
GetDateFormatEx(localeName.Buffer(), 0, &st, format.Buffer(), &buffer[0], (int)buffer.Count(), NULL);
return &buffer[0];
}
WString FormatTime(const WString& localeName, const WString& format, DateTime time) const override
{
SYSTEMTIME st = DateTimeToSystemTime(time);
int length = GetTimeFormatEx(localeName.Buffer(), 0, &st, format.Buffer(), NULL, 0);
if (length == 0) return L"";
Array<wchar_t> buffer(length);
GetTimeFormatEx(localeName.Buffer(), 0, &st, format.Buffer(), &buffer[0], (int)buffer.Count());
return &buffer[0];
}
WString FormatNumber(const WString& localeName, const WString& number) const override
{
int length = GetNumberFormatEx(localeName.Buffer(), 0, number.Buffer(), NULL, NULL, 0);
if (length == 0) return L"";
Array<wchar_t> buffer(length);
GetNumberFormatEx(localeName.Buffer(), 0, number.Buffer(), NULL, &buffer[0], (int)buffer.Count());
return &buffer[0];
}
WString FormatCurrency(const WString& localeName, const WString& currency) const override
{
int length = GetCurrencyFormatEx(localeName.Buffer(), 0, currency.Buffer(), NULL, NULL, 0);
if (length == 0) return L"";
Array<wchar_t> buffer(length);
GetCurrencyFormatEx(localeName.Buffer(), 0, currency.Buffer(), NULL, &buffer[0], (int)buffer.Count());
return &buffer[0];
}
WString GetShortDayOfWeekName(const WString& localeName, vint dayOfWeek) const override
{
return FormatDate(localeName, L"ddd", DateTime::FromDateTime(2000, 1, 2 + dayOfWeek));
}
WString GetLongDayOfWeekName(const WString& localeName, vint dayOfWeek) const override
{
return FormatDate(localeName, L"dddd", DateTime::FromDateTime(2000, 1, 2 + dayOfWeek));
}
WString GetShortMonthName(const WString& localeName, vint month) const override
{
return FormatDate(localeName, L"MMM", DateTime::FromDateTime(2000, month, 1));
}
WString GetLongMonthName(const WString& localeName, vint month) const override
{
return FormatDate(localeName, L"MMMM", DateTime::FromDateTime(2000, month, 1));
}
WString ToLower(const WString& localeName, const WString& str) const override
{
return Transform(localeName, str, LCMAP_LOWERCASE);
}
WString ToUpper(const WString& localeName, const WString& str) const override
{
return Transform(localeName, str, LCMAP_UPPERCASE);
}
WString ToLinguisticLower(const WString& localeName, const WString& str) const override
{
return Transform(localeName, str, LCMAP_LOWERCASE | LCMAP_LINGUISTIC_CASING);
}
WString ToLinguisticUpper(const WString& localeName, const WString& str) const override
{
return Transform(localeName, str, LCMAP_UPPERCASE | LCMAP_LINGUISTIC_CASING);
}
vint Compare(const WString& localeName, const WString& s1, const WString& s2, Locale::Normalization normalization) const override
{
switch (CompareStringEx(localeName.Buffer(), TranslateNormalization(normalization), s1.Buffer(), (int)s1.Length(), s2.Buffer(), (int)s2.Length(), NULL, NULL, NULL))
{
case CSTR_LESS_THAN: return -1;
case CSTR_GREATER_THAN: return 1;
default: return 0;
}
}
vint CompareOrdinal(const WString& s1, const WString& s2) const override
{
switch (CompareStringOrdinal(s1.Buffer(), (int)s1.Length(), s2.Buffer(), (int)s2.Length(), FALSE))
{
case CSTR_LESS_THAN: return -1;
case CSTR_GREATER_THAN: return 1;
default: return 0;
}
}
vint CompareOrdinalIgnoreCase(const WString& s1, const WString& s2) const override
{
switch (CompareStringOrdinal(s1.Buffer(), (int)s1.Length(), s2.Buffer(), (int)s2.Length(), TRUE))
{
case CSTR_LESS_THAN: return -1;
case CSTR_GREATER_THAN: return 1;
default: return 0;
}
}
collections::Pair<vint, vint> FindFirst(const WString& localeName, const WString& text, const WString& find, Locale::Normalization normalization) const override
{
int length = 0;
int result = FindNLSStringEx(localeName.Buffer(), FIND_FROMSTART | TranslateNormalization(normalization), text.Buffer(), (int)text.Length(), find.Buffer(), (int)find.Length(), &length, NULL, NULL, NULL);
return result == -1 ? collections::Pair<vint, vint>(-1, 0) : collections::Pair<vint, vint>(result, length);
}
collections::Pair<vint, vint> FindLast(const WString& localeName, const WString& text, const WString& find, Locale::Normalization normalization) const override
{
int length = 0;
int result = FindNLSStringEx(localeName.Buffer(), FIND_FROMEND | TranslateNormalization(normalization), text.Buffer(), (int)text.Length(), find.Buffer(), (int)find.Length(), &length, NULL, NULL, NULL);
return result == -1 ? collections::Pair<vint, vint>(-1, 0) : collections::Pair<vint, vint>(result, length);
}
bool StartsWith(const WString& localeName, const WString& text, const WString& find, Locale::Normalization normalization) const override
{
int result = FindNLSStringEx(localeName.Buffer(), FIND_STARTSWITH | TranslateNormalization(normalization), text.Buffer(), (int)text.Length(), find.Buffer(), (int)find.Length(), NULL, NULL, NULL, NULL);
return result != -1;
}
bool EndsWith(const WString& localeName, const WString& text, const WString& find, Locale::Normalization normalization) const override
{
int result = FindNLSStringEx(localeName.Buffer(), FIND_ENDSWITH | TranslateNormalization(normalization), text.Buffer(), (int)text.Length(), find.Buffer(), (int)find.Length(), NULL, NULL, NULL, NULL);
return result != -1;
}
};
WindowsLocaleImpl windowsLocaleImpl;
ILocaleImpl* GetOSLocaleImpl()
{
return &windowsLocaleImpl;
}
Locale Locale::SystemDefault()
{
wchar_t buffer[LOCALE_NAME_MAX_LENGTH + 1] = { 0 };
GetSystemDefaultLocaleName(buffer, LOCALE_NAME_MAX_LENGTH);
return Locale(buffer);
}
Locale Locale::UserDefault()
{
wchar_t buffer[LOCALE_NAME_MAX_LENGTH + 1] = { 0 };
GetUserDefaultLocaleName(buffer, LOCALE_NAME_MAX_LENGTH);
return Locale(buffer);
}
void Locale::Enumerate(collections::List<Locale>& locales)
{
EnumSystemLocalesEx(&Locale_EnumLocalesProcEx, LOCALE_ALL, (LPARAM)&locales, NULL);
}
void Locale::GetShortDateFormats(collections::List<WString>& formats)const
{
EnumDateFormatsExEx(&Locale_EnumDateFormatsProcExEx, localeName.Buffer(), DATE_SHORTDATE, (LPARAM)&formats);
}
void Locale::GetLongDateFormats(collections::List<WString>& formats)const
{
EnumDateFormatsExEx(&Locale_EnumDateFormatsProcExEx, localeName.Buffer(), DATE_LONGDATE, (LPARAM)&formats);
}
void Locale::GetYearMonthDateFormats(collections::List<WString>& formats)const
{
EnumDateFormatsExEx(&Locale_EnumDateFormatsProcExEx, localeName.Buffer(), DATE_YEARMONTH, (LPARAM)&formats);
}
void Locale::GetLongTimeFormats(collections::List<WString>& formats)const
{
EnumTimeFormatsEx(&EnumTimeFormatsProcEx, localeName.Buffer(), 0, (LPARAM)&formats);
}
void Locale::GetShortTimeFormats(collections::List<WString>& formats)const
{
EnumTimeFormatsEx(&EnumTimeFormatsProcEx, localeName.Buffer(), TIME_NOSECONDS, (LPARAM)&formats);
}
WString Locale::FormatDate(const WString& format, DateTime date)const
{
SYSTEMTIME st = DateTimeToSystemTime(date);
int length = GetDateFormatEx(localeName.Buffer(), 0, &st, format.Buffer(), NULL, 0, NULL);
if (length == 0) return L"";
Array<wchar_t> buffer(length);
GetDateFormatEx(localeName.Buffer(), 0, &st, format.Buffer(), &buffer[0], (int)buffer.Count(), NULL);
return &buffer[0];
}
WString Locale::FormatTime(const WString& format, DateTime time)const
{
SYSTEMTIME st = DateTimeToSystemTime(time);
int length = GetTimeFormatEx(localeName.Buffer(), 0, &st, format.Buffer(), NULL, 0);
if (length == 0) return L"";
Array<wchar_t> buffer(length);
GetTimeFormatEx(localeName.Buffer(), 0, &st, format.Buffer(), &buffer[0], (int)buffer.Count());
return &buffer[0];
}
WString Locale::FormatNumber(const WString& number)const
{
int length = GetNumberFormatEx(localeName.Buffer(), 0, number.Buffer(), NULL, NULL, 0);
if (length == 0) return L"";
Array<wchar_t> buffer(length);
GetNumberFormatEx(localeName.Buffer(), 0, number.Buffer(), NULL, &buffer[0], (int)buffer.Count());
return &buffer[0];
}
WString Locale::FormatCurrency(const WString& currency)const
{
int length = GetCurrencyFormatEx(localeName.Buffer(), 0, currency.Buffer(), NULL, NULL, 0);
if (length == 0) return L"";
Array<wchar_t> buffer(length);
GetCurrencyFormatEx(localeName.Buffer(), 0, currency.Buffer(), NULL, &buffer[0], (int)buffer.Count());
return &buffer[0];
}
WString Locale::GetShortDayOfWeekName(vint dayOfWeek)const
{
return FormatDate(L"ddd", DateTime::FromDateTime(2000, 1, 2 + dayOfWeek));
}
WString Locale::GetLongDayOfWeekName(vint dayOfWeek)const
{
return FormatDate(L"dddd", DateTime::FromDateTime(2000, 1, 2 + dayOfWeek));
}
WString Locale::GetShortMonthName(vint month)const
{
return FormatDate(L"MMM", DateTime::FromDateTime(2000, month, 1));
}
WString Locale::GetLongMonthName(vint month)const
{
return FormatDate(L"MMMM", DateTime::FromDateTime(2000, month, 1));
}
/***********************************************************************
Locale (Windows Specific)
***********************************************************************/
WString Locale::ToFullWidth(const WString& str)const
{
@@ -821,26 +916,6 @@ Locale
return Transform(localeName, str, LCMAP_KATAKANA);
}
WString Locale::ToLower(const WString& str)const
{
return Transform(localeName, str, LCMAP_LOWERCASE);
}
WString Locale::ToUpper(const WString& str)const
{
return Transform(localeName, str, LCMAP_UPPERCASE);
}
WString Locale::ToLinguisticLower(const WString& str)const
{
return Transform(localeName, str, LCMAP_LOWERCASE | LCMAP_LINGUISTIC_CASING);
}
WString Locale::ToLinguisticUpper(const WString& str)const
{
return Transform(localeName, str, LCMAP_UPPERCASE | LCMAP_LINGUISTIC_CASING);
}
WString Locale::ToSimplifiedChinese(const WString& str)const
{
return Transform(localeName, str, LCMAP_SIMPLIFIED_CHINESE);
@@ -855,62 +930,6 @@ Locale
{
return Transform(localeName, str, LCMAP_TITLECASE);
}
vint Locale::Compare(const WString& s1, const WString& s2, Normalization normalization)const
{
switch (CompareStringEx(localeName.Buffer(), TranslateNormalization(normalization), s1.Buffer(), (int)s1.Length(), s2.Buffer(), (int)s2.Length(), NULL, NULL, NULL))
{
case CSTR_LESS_THAN: return -1;
case CSTR_GREATER_THAN: return 1;
default: return 0;
}
}
vint Locale::CompareOrdinal(const WString& s1, const WString& s2)const
{
switch (CompareStringOrdinal(s1.Buffer(), (int)s1.Length(), s2.Buffer(), (int)s2.Length(), FALSE))
{
case CSTR_LESS_THAN: return -1;
case CSTR_GREATER_THAN: return 1;
default: return 0;
}
}
vint Locale::CompareOrdinalIgnoreCase(const WString& s1, const WString& s2)const
{
switch (CompareStringOrdinal(s1.Buffer(), (int)s1.Length(), s2.Buffer(), (int)s2.Length(), TRUE))
{
case CSTR_LESS_THAN: return -1;
case CSTR_GREATER_THAN: return 1;
default: return 0;
}
}
collections::Pair<vint, vint> Locale::FindFirst(const WString& text, const WString& find, Normalization normalization)const
{
int length = 0;
int result = FindNLSStringEx(localeName.Buffer(), FIND_FROMSTART | TranslateNormalization(normalization), text.Buffer(), (int)text.Length(), find.Buffer(), (int)find.Length(), &length, NULL, NULL, NULL);
return result == -1 ? Pair<vint, vint>(-1, 0) : Pair<vint, vint>(result, length);
}
collections::Pair<vint, vint> Locale::FindLast(const WString& text, const WString& find, Normalization normalization)const
{
int length = 0;
int result = FindNLSStringEx(localeName.Buffer(), FIND_FROMEND | TranslateNormalization(normalization), text.Buffer(), (int)text.Length(), find.Buffer(), (int)find.Length(), &length, NULL, NULL, NULL);
return result == -1 ? Pair<vint, vint>(-1, 0) : Pair<vint, vint>(result, length);
}
bool Locale::StartsWith(const WString& text, const WString& find, Normalization normalization)const
{
int result = FindNLSStringEx(localeName.Buffer(), FIND_STARTSWITH | TranslateNormalization(normalization), text.Buffer(), (int)text.Length(), find.Buffer(), (int)find.Length(), NULL, NULL, NULL, NULL);
return result != -1;
}
bool Locale::EndsWith(const WString& text, const WString& find, Normalization normalization)const
{
int result = FindNLSStringEx(localeName.Buffer(), FIND_ENDSWITH | TranslateNormalization(normalization), text.Buffer(), (int)text.Length(), find.Buffer(), (int)find.Length(), NULL, NULL, NULL, NULL);
return result != -1;
}
}