| //===--- SwiftNativeNSXXXBase.mm.gyb - Cocoa classes with fast refcounts --===// |
| // |
| // This source file is part of the Swift.org open source project |
| // |
| // Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors |
| // Licensed under Apache License v2.0 with Runtime Library Exception |
| // |
| // See https://swift.org/LICENSE.txt for license information |
| // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // Classes derived from ObjC bases but that use native swift reference |
| // counting, layout, and allocation. |
| // |
| // These classes declare a native Swift object header and override the |
| // NSObject methods that do reference counting to use it accordingly. |
| // We can only do this trick with objc classes that are known not to |
| // use the storage where Swift places its native object header. This |
| // takes care of how the classes are handled from Objective-C code. |
| // _NSSwiftArrayBase, _NSSwiftDictionaryBase, _NSSwiftSetBase |
| // _NSSwiftSetBase, _NSSwiftStringBase |
| // |
| // To trick Swift into using its fast refcounting and allocation |
| // directly (rather than going through objc_msgSend to arrive at the |
| // implementations defined here), we define subclasses on the Swift |
| // side but hide the inheritance relationship from the Swift compiler |
| // and only establish it dynamically, in the '+ load' method of each |
| // class defined here. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "swift/Runtime/Config.h" |
| |
| #if SWIFT_OBJC_INTEROP |
| #import <Foundation/Foundation.h> |
| #import <CoreFoundation/CoreFoundation.h> |
| #include <objc/NSObject.h> |
| #include <objc/runtime.h> |
| #include <objc/objc.h> |
| #include "swift/Runtime/HeapObject.h" |
| #include "swift/Runtime/Metadata.h" |
| #include "swift/Runtime/ObjCBridge.h" |
| #include "llvm/ADT/DenseMap.h" |
| #include <stdio.h> |
| #include <stdlib.h> |
| |
| using namespace swift; |
| |
| % for Class in ('Array', 'Dictionary', 'Set', 'String', 'Enumerator', 'Data', 'CharacterSet', 'IndexSet'): |
| SWIFT_RUNTIME_STDLIB_INTERFACE |
| @interface _SwiftNativeNS${Class}Base : NS${Class} |
| { |
| SWIFT_HEAPOBJECT_NON_OBJC_MEMBERS; |
| } |
| @end |
| |
| |
| @implementation _SwiftNativeNS${Class}Base |
| |
| - (id)retain { |
| auto SELF = reinterpret_cast<HeapObject *>(self); |
| swift_retain(SELF); |
| return self; |
| } |
| - (oneway void)release { |
| auto SELF = reinterpret_cast<HeapObject *>(self); |
| swift_release(SELF); |
| } |
| - (id)autorelease { |
| return _objc_rootAutorelease(self); |
| } |
| |
| - (BOOL)_tryRetain { |
| auto SELF = reinterpret_cast<HeapObject *>(self); |
| return (bool)swift_tryRetain(SELF); |
| } |
| - (BOOL)_isDeallocating { |
| return swift_isDeallocating(reinterpret_cast<HeapObject *>(self)); |
| } |
| - (BOOL)allowsWeakReference { |
| return !swift_isDeallocating(reinterpret_cast<HeapObject *>(self)); |
| } |
| - (BOOL)retainWeakReference { |
| return swift_tryRetain(reinterpret_cast<HeapObject*>(self)) != nullptr; |
| } |
| |
| #pragma clang diagnostic push |
| #pragma clang diagnostic ignored "-Wobjc-missing-super-calls" |
| - (void)dealloc { |
| swift_rootObjCDealloc(reinterpret_cast<HeapObject *>(self)); |
| } |
| #pragma clang diagnostic pop |
| |
| @end |
| % end |
| |
| SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE |
| bool |
| swift_stdlib_NSObject_isEqual(NSObject *NS_RELEASES_ARGUMENT lhs, |
| NSObject *NS_RELEASES_ARGUMENT rhs) { |
| bool Result = (lhs == rhs) || [lhs isEqual:rhs]; |
| swift_unknownRelease(lhs); |
| swift_unknownRelease(rhs); |
| return Result; |
| } |
| |
| SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE |
| int32_t swift_stdlib_compareNSStringDeterministicUnicodeCollation( |
| NSString *NS_RELEASES_ARGUMENT lhs, NSString *NS_RELEASES_ARGUMENT rhs) { |
| // 'kCFCompareNonliteral' actually means "normalize to NFD". |
| int Result = CFStringCompare((__bridge CFStringRef)lhs, |
| (__bridge CFStringRef)rhs, kCFCompareNonliteral); |
| swift_unknownRelease(lhs); |
| swift_unknownRelease(rhs); |
| return Result; |
| } |
| |
| SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE |
| int32_t |
| swift_stdlib_compareNSStringDeterministicUnicodeCollationPtr(void *Lhs, |
| void *Rhs) { |
| NSString *lhs = (NSString *)Lhs; |
| NSString *rhs = (NSString *)Rhs; |
| |
| // 'kCFCompareNonliteral' actually means "normalize to NFD". |
| int Result = CFStringCompare((__bridge CFStringRef)lhs, |
| (__bridge CFStringRef)rhs, kCFCompareNonliteral); |
| return Result; |
| } |
| |
| SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE |
| size_t |
| swift_stdlib_NSStringHashValue(NSString *NS_RELEASES_ARGUMENT str, |
| bool isASCII) { |
| size_t Result = |
| isASCII ? str.hash : str.decomposedStringWithCanonicalMapping.hash; |
| |
| swift_unknownRelease(str); |
| return Result; |
| } |
| |
| SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE |
| size_t |
| swift_stdlib_NSStringHashValuePointer(void *opaque, bool isASCII) { |
| NSString *str = (NSString *)opaque; |
| return isASCII ? str.hash : str.decomposedStringWithCanonicalMapping.hash; |
| } |
| |
| |
| SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE |
| bool swift_stdlib_NSStringHasPrefixNFD(NSString *theString, |
| NSString *prefix) { |
| auto Length = CFStringGetLength((__bridge CFStringRef)theString); |
| int Result = CFStringFindWithOptions( |
| (__bridge CFStringRef)theString, (__bridge CFStringRef)prefix, |
| CFRangeMake(0, Length), kCFCompareAnchored | kCFCompareNonliteral, |
| nullptr); |
| swift_unknownRelease(theString); |
| swift_unknownRelease(prefix); |
| return Result; |
| } |
| |
| SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE |
| bool swift_stdlib_NSStringHasPrefixNFDPointer(void *theString, |
| void *prefix) { |
| auto Length = CFStringGetLength((__bridge CFStringRef)theString); |
| int Result = CFStringFindWithOptions( |
| (__bridge CFStringRef)theString, (__bridge CFStringRef)prefix, |
| CFRangeMake(0, Length), kCFCompareAnchored | kCFCompareNonliteral, |
| nullptr); |
| return Result; |
| } |
| |
| SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE |
| bool |
| swift_stdlib_NSStringHasSuffixNFD(NSString *NS_RELEASES_ARGUMENT theString, |
| NSString *NS_RELEASES_ARGUMENT suffix) { |
| auto Length = CFStringGetLength((__bridge CFStringRef)theString); |
| int Result = CFStringFindWithOptions( |
| (__bridge CFStringRef)theString, (__bridge CFStringRef)suffix, |
| CFRangeMake(0, Length), |
| kCFCompareAnchored | kCFCompareBackwards | kCFCompareNonliteral, nullptr); |
| swift_unknownRelease(theString); |
| swift_unknownRelease(suffix); |
| return Result; |
| } |
| |
| SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE |
| bool swift_stdlib_NSStringHasSuffixNFDPointer(void *theString, |
| void *suffix) { |
| auto Length = CFStringGetLength((__bridge CFStringRef)theString); |
| int Result = CFStringFindWithOptions( |
| (__bridge CFStringRef)theString, (__bridge CFStringRef)suffix, |
| CFRangeMake(0, Length), |
| kCFCompareAnchored | kCFCompareBackwards | kCFCompareNonliteral, nullptr); |
| return Result; |
| } |
| |
| SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE |
| NS_RETURNS_RETAINED NSString * |
| swift_stdlib_NSStringLowercaseString(NSString *NS_RELEASES_ARGUMENT str) { |
| NSString *Result = objc_retain(str.lowercaseString); |
| swift_unknownRelease(str); |
| return Result; |
| } |
| |
| SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE |
| NS_RETURNS_RETAINED NSString * |
| swift_stdlib_NSStringUppercaseString(NSString *NS_RELEASES_ARGUMENT str) { |
| NSString *Result = objc_retain(str.uppercaseString); |
| swift_unknownRelease(str); |
| return Result; |
| } |
| |
| SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE |
| void swift_stdlib_CFSetGetValues(NSSet *NS_RELEASES_ARGUMENT set, |
| const void **values) { |
| CFSetGetValues((__bridge CFSetRef)set, values); |
| swift_unknownRelease(set); |
| } |
| #endif |
| |
| // ${'Local Variables'}: |
| // eval: (read-only-mode 1) |
| // End: |