未验证 提交 20f4ff43 编写于 作者: A Alexander Köplinger 提交者: GitHub

Enable Automatic Reference Counting (ARC) for Objective-C code that needs it (#90379)

We noticed that ARC isn't enabled for System.Globalization.Native code but we aren't properly doing manual memory management by calling `release`.

Enable ARC for the System.Globalization.Native ObjC code so it is handled automatically by the compiler.
Disable it for System.Native code since that one is less complex and we can manually manage it.

We need to wrap all public entrypoints to the library in `@autoreleasepool` blocks so that the releasing of autoreleased objects occurs at the end of the block, rather than at some undetermined point in the future (and we don't even know if we have an autorelease pool in the thread).
上级 55828b9a
......@@ -83,7 +83,7 @@ if(HAVE_SYS_ICU)
set_source_files_properties(${icu_shim_sources} PROPERTIES COMPILE_DEFINITIONS OSX_ICU_LIBRARY_PATH="${OSX_ICU_LIBRARY_PATH}")
set_source_files_properties(${icu_shim_sources} PROPERTIES COMPILE_FLAGS "-I\"${ICU_INCLUDEDIR}\" -I\"${CLR_SRC_NATIVE_DIR}/libs/System.Globalization.Native/\" -I\"${CLR_SRC_NATIVE_DIR}/libs/Common/\" ${ICU_FLAGS}")
if(TARGET_DARWIN)
set_property(SOURCE ${icu_shim_darwin_sources} APPEND_STRING PROPERTY COMPILE_FLAGS "${CLR_CMAKE_COMMON_OBJC_FLAGS}")
set_property(SOURCE ${icu_shim_darwin_sources} APPEND_STRING PROPERTY COMPILE_FLAGS " -fobjc-arc ${CLR_CMAKE_COMMON_OBJC_FLAGS}")
endif()
if(TARGET_WIN32)
set_source_files_properties(${icu_shim_sources} PROPERTIES LANGUAGE CXX)
......
......@@ -93,8 +93,13 @@ else()
endif()
if (CLR_CMAKE_TARGET_APPLE)
set(NATIVEGLOBALIZATION_SOURCES ${NATIVEGLOBALIZATION_SOURCES} pal_locale.m pal_collation.m pal_casing.m pal_calendarData.m)
set_source_files_properties(pal_locale.m pal_collation.m pal_casing.m pal_calendarData.m PROPERTIES COMPILE_FLAGS "${CLR_CMAKE_COMMON_OBJC_FLAGS}")
set(NATIVEGLOBALIZATION_SOURCES_OBJC
pal_locale.m
pal_collation.m
pal_casing.m
pal_calendarData.m)
set_source_files_properties(${NATIVEGLOBALIZATION_SOURCES_OBJC} PROPERTIES COMPILE_FLAGS "-fobjc-arc ${CLR_CMAKE_COMMON_OBJC_FLAGS}")
set(NATIVEGLOBALIZATION_SOURCES ${NATIVEGLOBALIZATION_SOURCES} ${NATIVEGLOBALIZATION_SOURCES_OBJC})
endif()
# time zone names are filtered out of icu data for the browser and associated functionality is disabled
......
......@@ -6,6 +6,10 @@
#include "pal_calendarData.h"
#import <Foundation/Foundation.h>
#if !__has_feature(objc_arc)
#error This file relies on ARC for memory management, but ARC is not enabled.
#endif
#if defined(TARGET_MACCATALYST) || defined(TARGET_IOS) || defined(TARGET_TVOS)
/*
......@@ -55,83 +59,86 @@ with the requested value.
*/
const char* GlobalizationNative_GetCalendarInfoNative(const char* localeName, CalendarId calendarId, CalendarDataType dataType)
{
NSString *locName = [NSString stringWithFormat:@"%s", localeName];
NSLocale *currentLocale = [[NSLocale alloc] initWithLocaleIdentifier:locName];
if (dataType == CalendarData_MonthDay)
@autoreleasepool
{
NSString *formatString = [NSDateFormatter dateFormatFromTemplate:@"MMMMd" options:0 locale:currentLocale];
return formatString ? strdup([formatString UTF8String]) : NULL;
}
else if (dataType == CalendarData_YearMonths)
{
NSString *formatString = [NSDateFormatter dateFormatFromTemplate:@"MMMM yyyy" options:0 locale:currentLocale];
return formatString ? strdup([formatString UTF8String]) : NULL;
}
NSString *locName = [NSString stringWithFormat:@"%s", localeName];
NSLocale *currentLocale = [[NSLocale alloc] initWithLocaleIdentifier:locName];
NSString *calendarIdentifier = GetCalendarIdentifier(calendarId);
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:calendarIdentifier];
if (dataType == CalendarData_MonthDay)
{
NSString *formatString = [NSDateFormatter dateFormatFromTemplate:@"MMMMd" options:0 locale:currentLocale];
return formatString ? strdup([formatString UTF8String]) : NULL;
}
else if (dataType == CalendarData_YearMonths)
{
NSString *formatString = [NSDateFormatter dateFormatFromTemplate:@"MMMM yyyy" options:0 locale:currentLocale];
return formatString ? strdup([formatString UTF8String]) : NULL;
}
if (dataType == CalendarData_NativeName)
return calendar ? strdup([[calendar calendarIdentifier] UTF8String]) : NULL;
NSString *calendarIdentifier = GetCalendarIdentifier(calendarId);
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:calendarIdentifier];
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
dateFormat.locale = currentLocale;
dateFormat.calendar = calendar;
if (dataType == CalendarData_NativeName)
return calendar ? strdup([[calendar calendarIdentifier] UTF8String]) : NULL;
NSArray *result;
switch (dataType)
{
case CalendarData_ShortDates:
{
[dateFormat setDateStyle:NSDateFormatterShortStyle];
NSString *shortFormatString = [dateFormat dateFormat];
[dateFormat setDateStyle:NSDateFormatterMediumStyle];
NSString *mediumFormatString = [dateFormat dateFormat];
NSString *yearMonthDayFormat = [NSDateFormatter dateFormatFromTemplate:@"yMd" options:0 locale:currentLocale];
result = @[shortFormatString, mediumFormatString, yearMonthDayFormat];
break;
}
case CalendarData_LongDates:
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
dateFormat.locale = currentLocale;
dateFormat.calendar = calendar;
NSArray *result;
switch (dataType)
{
[dateFormat setDateStyle:NSDateFormatterLongStyle];
NSString *longFormatString = [dateFormat dateFormat];
[dateFormat setDateStyle:NSDateFormatterFullStyle];
NSString *fullFormatString = [dateFormat dateFormat];
result = @[longFormatString, fullFormatString];
break;
case CalendarData_ShortDates:
{
[dateFormat setDateStyle:NSDateFormatterShortStyle];
NSString *shortFormatString = [dateFormat dateFormat];
[dateFormat setDateStyle:NSDateFormatterMediumStyle];
NSString *mediumFormatString = [dateFormat dateFormat];
NSString *yearMonthDayFormat = [NSDateFormatter dateFormatFromTemplate:@"yMd" options:0 locale:currentLocale];
result = @[shortFormatString, mediumFormatString, yearMonthDayFormat];
break;
}
case CalendarData_LongDates:
{
[dateFormat setDateStyle:NSDateFormatterLongStyle];
NSString *longFormatString = [dateFormat dateFormat];
[dateFormat setDateStyle:NSDateFormatterFullStyle];
NSString *fullFormatString = [dateFormat dateFormat];
result = @[longFormatString, fullFormatString];
break;
}
case CalendarData_DayNames:
result = [dateFormat standaloneWeekdaySymbols];
break;
case CalendarData_AbbrevDayNames:
result = [dateFormat shortStandaloneWeekdaySymbols];
break;
case CalendarData_MonthNames:
result = [dateFormat standaloneMonthSymbols];
break;
case CalendarData_AbbrevMonthNames:
result = [dateFormat shortStandaloneMonthSymbols];
break;
case CalendarData_SuperShortDayNames:
result = [dateFormat veryShortStandaloneWeekdaySymbols];
break;
case CalendarData_MonthGenitiveNames:
result = [dateFormat monthSymbols];
break;
case CalendarData_AbbrevMonthGenitiveNames:
result = [dateFormat shortMonthSymbols];
break;
case CalendarData_EraNames:
case CalendarData_AbbrevEraNames:
result = [dateFormat eraSymbols];
break;
default:
assert(false);
return NULL;
}
case CalendarData_DayNames:
result = [dateFormat standaloneWeekdaySymbols];
break;
case CalendarData_AbbrevDayNames:
result = [dateFormat shortStandaloneWeekdaySymbols];
break;
case CalendarData_MonthNames:
result = [dateFormat standaloneMonthSymbols];
break;
case CalendarData_AbbrevMonthNames:
result = [dateFormat shortStandaloneMonthSymbols];
break;
case CalendarData_SuperShortDayNames:
result = [dateFormat veryShortStandaloneWeekdaySymbols];
break;
case CalendarData_MonthGenitiveNames:
result = [dateFormat monthSymbols];
break;
case CalendarData_AbbrevMonthGenitiveNames:
result = [dateFormat shortMonthSymbols];
break;
case CalendarData_EraNames:
case CalendarData_AbbrevEraNames:
result = [dateFormat eraSymbols];
break;
default:
assert(false);
return NULL;
}
NSString *arrayToString = [[result valueForKey:@"description"] componentsJoinedByString:@"||"];
return arrayToString ? strdup([arrayToString UTF8String]) : NULL;
NSString *arrayToString = [[result valueForKey:@"description"] componentsJoinedByString:@"||"];
return arrayToString ? strdup([arrayToString UTF8String]) : NULL;
}
}
#endif
......@@ -7,6 +7,10 @@
#import <Foundation/Foundation.h>
#if !__has_feature(objc_arc)
#error This file relies on ARC for memory management, but ARC is not enabled.
#endif
#if defined(TARGET_MACCATALYST) || defined(TARGET_IOS) || defined(TARGET_TVOS)
/**
......@@ -97,39 +101,42 @@ Returns 0 for success, non-zero on failure see ErrorCodes.
int32_t GlobalizationNative_ChangeCaseNative(const uint16_t* localeName, int32_t lNameLength,
const uint16_t* lpSrc, int32_t cwSrcLength, uint16_t* lpDst, int32_t cwDstLength, int32_t bToUpper)
{
NSLocale *currentLocale;
if(localeName == NULL || lNameLength == 0)
@autoreleasepool
{
currentLocale = [NSLocale systemLocale];
}
else
{
NSString *locName = [NSString stringWithCharacters: localeName length: lNameLength];
currentLocale = [NSLocale localeWithLocaleIdentifier:locName];
}
NSLocale *currentLocale;
if(localeName == NULL || lNameLength == 0)
{
currentLocale = [NSLocale systemLocale];
}
else
{
NSString *locName = [NSString stringWithCharacters: localeName length: lNameLength];
currentLocale = [NSLocale localeWithLocaleIdentifier:locName];
}
int32_t srcIdx = 0, dstIdx = 0, isError = 0;
uint16_t dstCodepoint;
while (srcIdx < cwSrcLength)
{
int32_t startIndex = srcIdx;
NEXTOFFSET(lpSrc, srcIdx, cwSrcLength);
int32_t srcLength = srcIdx - startIndex;
NSString *src = [NSString stringWithCharacters: lpSrc + startIndex length: srcLength];
NSString *dst = bToUpper ? [src uppercaseStringWithLocale:currentLocale] : [src lowercaseStringWithLocale:currentLocale];
int32_t index = 0;
// iterate over all code points of a surrogate pair character
while (index < srcLength)
int32_t srcIdx = 0, dstIdx = 0, isError = 0;
uint16_t dstCodepoint;
while (srcIdx < cwSrcLength)
{
// the dst.length > srcLength is to prevent code point expansions
dstCodepoint = dst.length > srcLength ? [src characterAtIndex: index] : [dst characterAtIndex: index];
Append(lpDst, dstIdx, cwDstLength, dstCodepoint, isError);
index++;
int32_t startIndex = srcIdx;
NEXTOFFSET(lpSrc, srcIdx, cwSrcLength);
int32_t srcLength = srcIdx - startIndex;
NSString *src = [NSString stringWithCharacters: lpSrc + startIndex length: srcLength];
NSString *dst = bToUpper ? [src uppercaseStringWithLocale:currentLocale] : [src lowercaseStringWithLocale:currentLocale];
int32_t index = 0;
// iterate over all code points of a surrogate pair character
while (index < srcLength)
{
// the dst.length > srcLength is to prevent code point expansions
dstCodepoint = dst.length > srcLength ? [src characterAtIndex: index] : [dst characterAtIndex: index];
Append(lpDst, dstIdx, cwDstLength, dstCodepoint, isError);
index++;
}
if (isError)
return isError;
}
if (isError)
return isError;
return Success;
}
return Success;
}
/*
......@@ -146,28 +153,31 @@ Returns 0 for success, non-zero on failure see ErrorCodes.
*/
int32_t GlobalizationNative_ChangeCaseInvariantNative(const uint16_t* lpSrc, int32_t cwSrcLength, uint16_t* lpDst, int32_t cwDstLength, int32_t bToUpper)
{
int32_t srcIdx = 0, dstIdx = 0, isError = 0;
uint16_t dstCodepoint;
while (srcIdx < cwSrcLength)
@autoreleasepool
{
int32_t startIndex = srcIdx;
NEXTOFFSET(lpSrc, srcIdx, cwSrcLength);
int32_t srcLength = srcIdx - startIndex;
NSString *src = [NSString stringWithCharacters: lpSrc + startIndex length: srcLength];
NSString *dst = bToUpper ? src.uppercaseString : src.lowercaseString;
int32_t index = 0;
// iterate over all code points of a surrogate pair character
while (index < srcLength)
int32_t srcIdx = 0, dstIdx = 0, isError = 0;
uint16_t dstCodepoint;
while (srcIdx < cwSrcLength)
{
// the dst.length > srcLength is to prevent code point expansions
dstCodepoint = dst.length > srcLength ? [src characterAtIndex: index] : [dst characterAtIndex: index];
Append(lpDst, dstIdx, cwDstLength, dstCodepoint, isError);
index++;
int32_t startIndex = srcIdx;
NEXTOFFSET(lpSrc, srcIdx, cwSrcLength);
int32_t srcLength = srcIdx - startIndex;
NSString *src = [NSString stringWithCharacters: lpSrc + startIndex length: srcLength];
NSString *dst = bToUpper ? src.uppercaseString : src.lowercaseString;
int32_t index = 0;
// iterate over all code points of a surrogate pair character
while (index < srcLength)
{
// the dst.length > srcLength is to prevent code point expansions
dstCodepoint = dst.length > srcLength ? [src characterAtIndex: index] : [dst characterAtIndex: index];
Append(lpDst, dstIdx, cwDstLength, dstCodepoint, isError);
index++;
}
if (isError)
return isError;
}
if (isError)
return isError;
return Success;
}
return Success;
}
#endif
......@@ -7,6 +7,10 @@
#import <Foundation/Foundation.h>
#if !__has_feature(objc_arc)
#error This file relies on ARC for memory management, but ARC is not enabled.
#endif
#if defined(TARGET_MACCATALYST) || defined(TARGET_IOS) || defined(TARGET_TVOS)
// Enum that corresponds to C# CompareOptions
......@@ -70,23 +74,26 @@ CompareString
int32_t GlobalizationNative_CompareStringNative(const uint16_t* localeName, int32_t lNameLength, const uint16_t* lpSource, int32_t cwSourceLength,
const uint16_t* lpTarget, int32_t cwTargetLength, int32_t comparisonOptions)
{
NSLocale *currentLocale = GetCurrentLocale(localeName, lNameLength);
NSString *sourceString = [NSString stringWithCharacters: lpSource length: cwSourceLength];
NSString *sourceStrPrecomposed = sourceString.precomposedStringWithCanonicalMapping;
NSString *targetString = [NSString stringWithCharacters: lpTarget length: cwTargetLength];
NSString *targetStrPrecomposed = targetString.precomposedStringWithCanonicalMapping;
NSRange comparisonRange = NSMakeRange(0, sourceStrPrecomposed.length);
NSStringCompareOptions options = ConvertFromCompareOptionsToNSStringCompareOptions(comparisonOptions);
// in case mapping is not found
if (options == 0)
return ERROR_COMPARISON_OPTIONS_NOT_FOUND;
return [sourceStrPrecomposed compare:targetStrPrecomposed
options:options
range:comparisonRange
locale:currentLocale];
@autoreleasepool
{
NSLocale *currentLocale = GetCurrentLocale(localeName, lNameLength);
NSString *sourceString = [NSString stringWithCharacters: lpSource length: cwSourceLength];
NSString *sourceStrPrecomposed = sourceString.precomposedStringWithCanonicalMapping;
NSString *targetString = [NSString stringWithCharacters: lpTarget length: cwTargetLength];
NSString *targetStrPrecomposed = targetString.precomposedStringWithCanonicalMapping;
NSRange comparisonRange = NSMakeRange(0, sourceStrPrecomposed.length);
NSStringCompareOptions options = ConvertFromCompareOptionsToNSStringCompareOptions(comparisonOptions);
// in case mapping is not found
if (options == 0)
return ERROR_COMPARISON_OPTIONS_NOT_FOUND;
return [sourceStrPrecomposed compare:targetStrPrecomposed
options:options
range:comparisonRange
locale:currentLocale];
}
}
static NSString* RemoveWeightlessCharacters(NSString* source)
......@@ -120,109 +127,112 @@ Find detailed explanation how this function works in https://github.com/dotnet/r
Range GlobalizationNative_IndexOfNative(const uint16_t* localeName, int32_t lNameLength, const uint16_t* lpTarget, int32_t cwTargetLength,
const uint16_t* lpSource, int32_t cwSourceLength, int32_t comparisonOptions, int32_t fromBeginning)
{
assert(cwTargetLength >= 0);
Range result = {ERROR_INDEX_NOT_FOUND, 0};
NSStringCompareOptions options = ConvertFromCompareOptionsToNSStringCompareOptions(comparisonOptions);
// in case mapping is not found
if (options == 0)
@autoreleasepool
{
result.location = ERROR_COMPARISON_OPTIONS_NOT_FOUND;
assert(cwTargetLength >= 0);
Range result = {ERROR_INDEX_NOT_FOUND, 0};
NSStringCompareOptions options = ConvertFromCompareOptionsToNSStringCompareOptions(comparisonOptions);
// in case mapping is not found
if (options == 0)
{
result.location = ERROR_COMPARISON_OPTIONS_NOT_FOUND;
return result;
}
NSString *searchString = [NSString stringWithCharacters: lpTarget length: cwTargetLength];
NSString *searchStrCleaned = RemoveWeightlessCharacters(searchString);
NSString *sourceString = [NSString stringWithCharacters: lpSource length: cwSourceLength];
NSString *sourceStrCleaned = RemoveWeightlessCharacters(sourceString);
if (sourceStrCleaned.length == 0 || searchStrCleaned.length == 0)
{
result.location = fromBeginning ? 0 : sourceString.length;
return result;
}
NSString *searchString = [NSString stringWithCharacters: lpTarget length: cwTargetLength];
NSString *searchStrCleaned = RemoveWeightlessCharacters(searchString);
NSString *sourceString = [NSString stringWithCharacters: lpSource length: cwSourceLength];
NSString *sourceStrCleaned = RemoveWeightlessCharacters(sourceString);
}
if (sourceStrCleaned.length == 0 || searchStrCleaned.length == 0)
{
result.location = fromBeginning ? 0 : sourceString.length;
return result;
}
NSLocale *currentLocale = GetCurrentLocale(localeName, lNameLength);
NSString *searchStrPrecomposed = searchStrCleaned.precomposedStringWithCanonicalMapping;
NSString *sourceStrPrecomposed = sourceStrCleaned.precomposedStringWithCanonicalMapping;
NSLocale *currentLocale = GetCurrentLocale(localeName, lNameLength);
NSString *searchStrPrecomposed = searchStrCleaned.precomposedStringWithCanonicalMapping;
NSString *sourceStrPrecomposed = sourceStrCleaned.precomposedStringWithCanonicalMapping;
// last index
if (!fromBeginning)
options |= NSBackwardsSearch;
// last index
if (!fromBeginning)
options |= NSBackwardsSearch;
// check if there is a possible match and return -1 if not
// doesn't matter which normalization form is used here
NSRange rangeOfReceiverToSearch = NSMakeRange(0, sourceStrPrecomposed.length);
NSRange containsRange = [sourceStrPrecomposed rangeOfString:searchStrPrecomposed
options:options
range:rangeOfReceiverToSearch
locale:currentLocale];
if (containsRange.location == NSNotFound)
return result;
// check if there is a possible match and return -1 if not
// doesn't matter which normalization form is used here
NSRange rangeOfReceiverToSearch = NSMakeRange(0, sourceStrPrecomposed.length);
NSRange containsRange = [sourceStrPrecomposed rangeOfString:searchStrPrecomposed
options:options
range:rangeOfReceiverToSearch
locale:currentLocale];
// in case search string is inside source string but we can't find the index return -3
result.location = ERROR_MIXED_COMPOSITION_NOT_FOUND;
// sourceString and searchString possibly have the same composition of characters
rangeOfReceiverToSearch = NSMakeRange(0, sourceStrCleaned.length);
NSRange nsRange = [sourceStrCleaned rangeOfString:searchStrCleaned
options:options
range:rangeOfReceiverToSearch
locale:currentLocale];
if (nsRange.location != NSNotFound)
{
result.location = nsRange.location;
result.length = nsRange.length;
// in case of CompareOptions.IgnoreCase if letters have different representations in source and search strings
// and case insensitive search appears more than one time in source string take last index for LastIndexOf and first index for IndexOf
// e.g. new CultureInfo().CompareInfo.LastIndexOf("Is \u0055\u0308 or \u0075\u0308 the same as \u00DC or \u00FC?", "U\u0308", 25,18, CompareOptions.IgnoreCase);
// should return 24 but here it will be 9
if (!(comparisonOptions & IgnoreCase))
if (containsRange.location == NSNotFound)
return result;
}
// check if sourceString has precomposed form of characters and searchString has decomposed form of characters
// convert searchString to a precomposed form
NSRange precomposedRange = [sourceStrCleaned rangeOfString:searchStrPrecomposed
options:options
range:rangeOfReceiverToSearch
locale:currentLocale];
if (precomposedRange.location != NSNotFound)
{
// in case of CompareOptions.IgnoreCase if letters have different representations in source and search strings
// and search appears more than one time in source string take last index for LastIndexOf and first index for IndexOf
// e.g. new CultureInfo().CompareInfo.LastIndexOf("Is \u0055\u0308 or \u0075\u0308 the same as \u00DC or \u00FC?", "U\u0308", 25,18, CompareOptions.IgnoreCase);
// this will return 24
if ((comparisonOptions & IgnoreCase) && IsIndexFound(fromBeginning, (int32_t)result.location, (int32_t)precomposedRange.location))
// in case search string is inside source string but we can't find the index return -3
result.location = ERROR_MIXED_COMPOSITION_NOT_FOUND;
// sourceString and searchString possibly have the same composition of characters
rangeOfReceiverToSearch = NSMakeRange(0, sourceStrCleaned.length);
NSRange nsRange = [sourceStrCleaned rangeOfString:searchStrCleaned
options:options
range:rangeOfReceiverToSearch
locale:currentLocale];
if (nsRange.location != NSNotFound)
{
result.location = nsRange.location;
result.length = nsRange.length;
// in case of CompareOptions.IgnoreCase if letters have different representations in source and search strings
// and case insensitive search appears more than one time in source string take last index for LastIndexOf and first index for IndexOf
// e.g. new CultureInfo().CompareInfo.LastIndexOf("Is \u0055\u0308 or \u0075\u0308 the same as \u00DC or \u00FC?", "U\u0308", 25,18, CompareOptions.IgnoreCase);
// should return 24 but here it will be 9
if (!(comparisonOptions & IgnoreCase))
return result;
}
// check if sourceString has precomposed form of characters and searchString has decomposed form of characters
// convert searchString to a precomposed form
NSRange precomposedRange = [sourceStrCleaned rangeOfString:searchStrPrecomposed
options:options
range:rangeOfReceiverToSearch
locale:currentLocale];
if (precomposedRange.location != NSNotFound)
{
// in case of CompareOptions.IgnoreCase if letters have different representations in source and search strings
// and search appears more than one time in source string take last index for LastIndexOf and first index for IndexOf
// e.g. new CultureInfo().CompareInfo.LastIndexOf("Is \u0055\u0308 or \u0075\u0308 the same as \u00DC or \u00FC?", "U\u0308", 25,18, CompareOptions.IgnoreCase);
// this will return 24
if ((comparisonOptions & IgnoreCase) && IsIndexFound(fromBeginning, (int32_t)result.location, (int32_t)precomposedRange.location))
return result;
result.location = precomposedRange.location;
result.length = precomposedRange.length;
if (!(comparisonOptions & IgnoreCase))
return result;
result.location = precomposedRange.location;
result.length = precomposedRange.length;
if (!(comparisonOptions & IgnoreCase))
return result;
}
// check if sourceString has decomposed form of characters and searchString has precomposed form of characters
// convert searchString to a decomposed form
NSString *searchStrDecomposed = searchStrCleaned.decomposedStringWithCanonicalMapping;
NSRange decomposedRange = [sourceStrCleaned rangeOfString:searchStrDecomposed
options:options
range:rangeOfReceiverToSearch
locale:currentLocale];
if (decomposedRange.location != NSNotFound)
{
if ((comparisonOptions & IgnoreCase) && IsIndexFound(fromBeginning, (int32_t)result.location, (int32_t)decomposedRange.location))
}
// check if sourceString has decomposed form of characters and searchString has precomposed form of characters
// convert searchString to a decomposed form
NSString *searchStrDecomposed = searchStrCleaned.decomposedStringWithCanonicalMapping;
NSRange decomposedRange = [sourceStrCleaned rangeOfString:searchStrDecomposed
options:options
range:rangeOfReceiverToSearch
locale:currentLocale];
if (decomposedRange.location != NSNotFound)
{
if ((comparisonOptions & IgnoreCase) && IsIndexFound(fromBeginning, (int32_t)result.location, (int32_t)decomposedRange.location))
return result;
result.location = decomposedRange.location;
result.length = decomposedRange.length;
return result;
}
result.location = decomposedRange.location;
result.length = decomposedRange.length;
return result;
}
return result;
}
/*
......@@ -231,25 +241,28 @@ Range GlobalizationNative_IndexOfNative(const uint16_t* localeName, int32_t lNam
int32_t GlobalizationNative_StartsWithNative(const uint16_t* localeName, int32_t lNameLength, const uint16_t* lpPrefix, int32_t cwPrefixLength,
const uint16_t* lpSource, int32_t cwSourceLength, int32_t comparisonOptions)
{
NSStringCompareOptions options = ConvertFromCompareOptionsToNSStringCompareOptions(comparisonOptions);
// in case mapping is not found
if (options == 0)
return ERROR_COMPARISON_OPTIONS_NOT_FOUND;
NSLocale *currentLocale = GetCurrentLocale(localeName, lNameLength);
NSString *prefixString = [NSString stringWithCharacters: lpPrefix length: cwPrefixLength];
NSString *prefixStrComposed = RemoveWeightlessCharacters(prefixString.precomposedStringWithCanonicalMapping);
NSString *sourceString = [NSString stringWithCharacters: lpSource length: cwSourceLength];
NSString *sourceStrComposed = RemoveWeightlessCharacters(sourceString.precomposedStringWithCanonicalMapping);
NSRange sourceRange = NSMakeRange(0, prefixStrComposed.length > sourceStrComposed.length ? sourceStrComposed.length : prefixStrComposed.length);
@autoreleasepool
{
NSStringCompareOptions options = ConvertFromCompareOptionsToNSStringCompareOptions(comparisonOptions);
int32_t result = [sourceStrComposed compare:prefixStrComposed
options:options
range:sourceRange
locale:currentLocale];
return result == NSOrderedSame ? 1 : 0;
// in case mapping is not found
if (options == 0)
return ERROR_COMPARISON_OPTIONS_NOT_FOUND;
NSLocale *currentLocale = GetCurrentLocale(localeName, lNameLength);
NSString *prefixString = [NSString stringWithCharacters: lpPrefix length: cwPrefixLength];
NSString *prefixStrComposed = RemoveWeightlessCharacters(prefixString.precomposedStringWithCanonicalMapping);
NSString *sourceString = [NSString stringWithCharacters: lpSource length: cwSourceLength];
NSString *sourceStrComposed = RemoveWeightlessCharacters(sourceString.precomposedStringWithCanonicalMapping);
NSRange sourceRange = NSMakeRange(0, prefixStrComposed.length > sourceStrComposed.length ? sourceStrComposed.length : prefixStrComposed.length);
int32_t result = [sourceStrComposed compare:prefixStrComposed
options:options
range:sourceRange
locale:currentLocale];
return result == NSOrderedSame ? 1 : 0;
}
}
/*
......@@ -258,25 +271,28 @@ int32_t GlobalizationNative_StartsWithNative(const uint16_t* localeName, int32_t
int32_t GlobalizationNative_EndsWithNative(const uint16_t* localeName, int32_t lNameLength, const uint16_t* lpSuffix, int32_t cwSuffixLength,
const uint16_t* lpSource, int32_t cwSourceLength, int32_t comparisonOptions)
{
NSStringCompareOptions options = ConvertFromCompareOptionsToNSStringCompareOptions(comparisonOptions);
// in case mapping is not found
if (options == 0)
return ERROR_COMPARISON_OPTIONS_NOT_FOUND;
NSLocale *currentLocale = GetCurrentLocale(localeName, lNameLength);
NSString *suffixString = [NSString stringWithCharacters: lpSuffix length: cwSuffixLength];
NSString *suffixStrComposed = RemoveWeightlessCharacters(suffixString.precomposedStringWithCanonicalMapping);
NSString *sourceString = [NSString stringWithCharacters: lpSource length: cwSourceLength];
NSString *sourceStrComposed = RemoveWeightlessCharacters(sourceString.precomposedStringWithCanonicalMapping);
int32_t startIndex = suffixStrComposed.length > sourceStrComposed.length ? 0 : sourceStrComposed.length - suffixStrComposed.length;
NSRange sourceRange = NSMakeRange(startIndex, sourceStrComposed.length - startIndex);
int32_t result = [sourceStrComposed compare:suffixStrComposed
options:options
range:sourceRange
locale:currentLocale];
return result == NSOrderedSame ? 1 : 0;
@autoreleasepool
{
NSStringCompareOptions options = ConvertFromCompareOptionsToNSStringCompareOptions(comparisonOptions);
// in case mapping is not found
if (options == 0)
return ERROR_COMPARISON_OPTIONS_NOT_FOUND;
NSLocale *currentLocale = GetCurrentLocale(localeName, lNameLength);
NSString *suffixString = [NSString stringWithCharacters: lpSuffix length: cwSuffixLength];
NSString *suffixStrComposed = RemoveWeightlessCharacters(suffixString.precomposedStringWithCanonicalMapping);
NSString *sourceString = [NSString stringWithCharacters: lpSource length: cwSourceLength];
NSString *sourceStrComposed = RemoveWeightlessCharacters(sourceString.precomposedStringWithCanonicalMapping);
int32_t startIndex = suffixStrComposed.length > sourceStrComposed.length ? 0 : sourceStrComposed.length - suffixStrComposed.length;
NSRange sourceRange = NSMakeRange(startIndex, sourceStrComposed.length - startIndex);
int32_t result = [sourceStrComposed compare:suffixStrComposed
options:options
range:sourceRange
locale:currentLocale];
return result == NSOrderedSame ? 1 : 0;
}
}
#endif
......@@ -67,56 +67,45 @@ else()
endif()
if (CLR_CMAKE_TARGET_APPLE)
list (APPEND NATIVE_SOURCES pal_autoreleasepool.m)
set_source_files_properties(pal_autoreleasepool.m PROPERTIES COMPILE_FLAGS "-fno-objc-arc ${CLR_CMAKE_COMMON_OBJC_FLAGS}")
else()
list (APPEND NATIVE_SOURCES pal_autoreleasepool.c)
endif()
if (CLR_CMAKE_TARGET_MACCATALYST OR CLR_CMAKE_TARGET_IOS OR CLR_CMAKE_TARGET_TVOS)
list (APPEND NATIVE_SOURCES pal_environment.m)
set_source_files_properties(pal_environment.m PROPERTIES COMPILE_FLAGS "${CLR_CMAKE_COMMON_OBJC_FLAGS}")
else()
list (APPEND NATIVE_SOURCES pal_environment.c)
endif()
if (CLR_CMAKE_TARGET_MACCATALYST OR CLR_CMAKE_TARGET_IOS OR CLR_CMAKE_TARGET_TVOS)
set(NATIVE_SOURCES ${NATIVE_SOURCES}
list (APPEND NATIVE_SOURCES_OBJC_NO_ARC
pal_autoreleasepool.m
pal_environment.m
pal_searchpath.m
pal_datetime.m)
set_source_files_properties(pal_datetime.m PROPERTIES COMPILE_FLAGS "${CLR_CMAKE_COMMON_OBJC_FLAGS}")
endif()
if (CLR_CMAKE_TARGET_MACCATALYST OR CLR_CMAKE_TARGET_IOS OR CLR_CMAKE_TARGET_TVOS)
set(NATIVE_SOURCES ${NATIVE_SOURCES}
pal_log.m
pal_searchpath.m)
set_source_files_properties(pal_log.m pal_searchpath.m PROPERTIES COMPILE_FLAGS "${CLR_CMAKE_COMMON_OBJC_FLAGS}")
elseif (CLR_CMAKE_TARGET_OSX)
list (APPEND NATIVE_SOURCES
pal_searchpath.m
pal_console.c
pal_log.c)
set_source_files_properties(pal_searchpath.m PROPERTIES COMPILE_FLAGS "${CLR_CMAKE_COMMON_OBJC_FLAGS}")
elseif (CLR_CMAKE_TARGET_WASI)
list (APPEND NATIVE_SOURCES
pal_searchpath.c
pal_console_wasi.c
pal_log.c)
else ()
if (CLR_CMAKE_TARGET_MACCATALYST OR CLR_CMAKE_TARGET_IOS OR CLR_CMAKE_TARGET_TVOS)
list (APPEND NATIVE_SOURCES_OBJC_NO_ARC pal_log.m)
if (CLR_CMAKE_TARGET_MACCATALYST)
list (APPEND NATIVE_SOURCES_OBJC_NO_ARC pal_iossupportversion.m)
else()
list (APPEND NATIVE_SOURCES pal_iossupportversion.c)
endif ()
elseif (CLR_CMAKE_TARGET_OSX)
list (APPEND NATIVE_SOURCES
pal_console.c
pal_log.c
pal_iossupportversion.c)
else()
message(FATAL_ERROR "Unsupported Apple platform")
endif ()
set_source_files_properties(${NATIVE_SOURCES_OBJC_NO_ARC} PROPERTIES COMPILE_FLAGS "-fno-objc-arc ${CLR_CMAKE_COMMON_OBJC_FLAGS}")
list (APPEND NATIVE_SOURCES ${NATIVE_SOURCES_OBJC_NO_ARC})
else()
list (APPEND NATIVE_SOURCES
pal_autoreleasepool.c
pal_environment.c
pal_searchpath.c
pal_console.c
pal_log.c)
endif ()
if (CLR_CMAKE_TARGET_MACCATALYST)
set(NATIVE_SOURCES ${NATIVE_SOURCES}
pal_iossupportversion.m)
set_source_files_properties(pal_iossupportversion.m PROPERTIES COMPILE_FLAGS "${CLR_CMAKE_COMMON_OBJC_FLAGS}")
else ()
list (APPEND NATIVE_SOURCES
pal_log.c
pal_iossupportversion.c)
endif ()
if (CLR_CMAKE_TARGET_WASI)
list (APPEND NATIVE_SOURCES pal_console_wasi.c)
else()
list (APPEND NATIVE_SOURCES pal_console.c)
endif()
endif()
if (NOT CLR_CMAKE_TARGET_BROWSER AND NOT CLR_CMAKE_TARGET_WASI)
list (APPEND NATIVE_SOURCES pal_networkchange.c)
......
......@@ -48,6 +48,7 @@ static const Entry s_sysNative[] =
DllImportEntry(SystemNative_GetSignalForBreak)
DllImportEntry(SystemNative_SetSignalForBreak)
DllImportEntry(SystemNative_GetSystemTimeAsTicks)
DllImportEntry(SystemNative_GetDefaultTimeZone)
DllImportEntry(SystemNative_GetTimeZoneData)
DllImportEntry(SystemNative_ConvertErrorPlatformToPal)
DllImportEntry(SystemNative_ConvertErrorPalToPlatform)
......
......@@ -5,6 +5,10 @@
#include <Foundation/Foundation.h>
#include <objc/runtime.h>
#if __has_feature(objc_arc)
#error This file uses manual memory management and must not use ARC, but ARC is enabled.
#endif
void EnsureNSThreadIsMultiThreaded(void)
{
if (![NSThread isMultiThreaded])
......
......@@ -61,6 +61,12 @@ char* SystemNative_GetDefaultTimeZone(void)
return NULL;
}
}
#elif !defined(__APPLE__)
char* SystemNative_GetDefaultTimeZone(void)
{
assert_err(false, "This function is not supported on this platform.", EINVAL);
return NULL;
}
#endif
const char* SystemNative_GetTimeZoneData(const char* name, int* length)
......
......@@ -8,8 +8,6 @@
PALEXPORT int64_t SystemNative_GetSystemTimeAsTicks(void);
#if defined(TARGET_ANDROID) || defined(__APPLE__)
PALEXPORT char* SystemNative_GetDefaultTimeZone(void);
#endif
PALEXPORT const char* SystemNative_GetTimeZoneData(const char* name, int* length);
......@@ -4,6 +4,10 @@
#include "pal_datetime.h"
#import <Foundation/Foundation.h>
#if __has_feature(objc_arc)
#error This file uses manual memory management and must not use ARC, but ARC is enabled.
#endif
char* SystemNative_GetDefaultTimeZone()
{
NSTimeZone *tz = [NSTimeZone localTimeZone];
......
......@@ -9,6 +9,10 @@
#include <objc/runtime.h>
#include <objc/message.h>
#if __has_feature(objc_arc)
#error This file uses manual memory management and must not use ARC, but ARC is enabled.
#endif
char* SystemNative_GetEnv(const char* variable)
{
return getenv(variable);
......
......@@ -5,14 +5,16 @@
#include "pal_autoreleasepool.h"
#import <Foundation/Foundation.h>
#if __has_feature(objc_arc)
#error This file uses manual memory management and must not use ARC, but ARC is enabled.
#endif
const char* SystemNative_iOSSupportVersion()
{
EnsureNSThreadIsMultiThreaded();
NSDictionary *plist = [[NSDictionary alloc] initWithContentsOfFile:@"/System/Library/CoreServices/SystemVersion.plist"];
NSString *iOSSupportVersion = (NSString *)[plist objectForKey:@"iOSSupportVersion"];
const char* version = strdup([iOSSupportVersion UTF8String]);
[plist release];
@autoreleasepool
{
NSDictionary *plist = [NSDictionary dictionaryWithContentsOfFile:@"/System/Library/CoreServices/SystemVersion.plist"];
NSString *iOSSupportVersion = (NSString *)[plist objectForKey:@"iOSSupportVersion"];
return strdup([iOSSupportVersion UTF8String]);
}
return version;
}
......@@ -4,6 +4,10 @@
#include "pal_log.h"
#import <Foundation/Foundation.h>
#if __has_feature(objc_arc)
#error This file uses manual memory management and must not use ARC, but ARC is enabled.
#endif
void SystemNative_Log (uint8_t* buffer, int32_t length)
{
NSString *msg = [[NSString alloc] initWithBytes: buffer length: length encoding: NSUTF16LittleEndianStringEncoding];
......
......@@ -4,6 +4,10 @@
#include "pal_searchpath.h"
#import <Foundation/Foundation.h>
#if __has_feature(objc_arc)
#error This file uses manual memory management and must not use ARC, but ARC is enabled.
#endif
const char* SystemNative_SearchPath(int32_t folderId)
{
NSSearchPathDirectory spd = (NSSearchPathDirectory) folderId;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册