blob: 38cdbd9e96db4f4ccc40900a2904931aa5b7be18 [file] [log] [blame]
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
#import <Foundation/Foundation.h>
#import <CoreGraphics/CoreGraphics.h>
#include <swift/Runtime/Debug.h>
// This file assumes that `sizeof(NSInteger) == Swift.Int` and
// `sizeof(NSUInteger) == sizeof(Swift.UInt)`.
@interface _SwiftTypePreservingNSNumber : NSNumber
@end
// This enum has a matching counterpart in Foundation.swift, please
// update both copies when changing it.
enum _SwiftTypePreservingNSNumberTag {
SwiftInt = 1,
SwiftUInt = 2,
SwiftFloat = 3,
SwiftDouble = 4,
SwiftCGFloat = 5,
SwiftBool = 6
};
@implementation _SwiftTypePreservingNSNumber {
_SwiftTypePreservingNSNumberTag tag;
char storage[8];
}
- (id)init {
self = [super init];
if (self) {
self->tag = SwiftInt;
const int64_t value = 0;
memcpy(self->storage, &value, 8);
}
return self;
}
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wobjc-designated-initializers"
- (id)initWithCoder:(NSCoder *)coder {
swift::swift_reportError(
/* flags = */ 0,
"_SwiftTypePreservingNSNumber should not be archived.\n");
abort();
}
#pragma GCC diagnostic pop
- (id)copyWithZone:(NSZone *)zone {
return [self retain];
}
- (const char *)objCType {
// When changing this method, make sure to keep the `getValue:` method in
// sync (it should copy as many bytes as this property promises).
switch(tag) {
case SwiftInt:
return @encode(NSInteger);
case SwiftUInt:
return @encode(NSUInteger);
case SwiftFloat:
return @encode(float);
case SwiftDouble:
return @encode(double);
case SwiftCGFloat:
return @encode(CGFloat);
case SwiftBool:
return @encode(bool);
}
swift::swift_reportError(
/* flags = */ 0,
"_SwiftTypePreservingNSNumber.tag is corrupted.\n");
}
- (void)getValue:(void *)value {
// This method should copy as many bytes as the `objCType` property promises.
switch(tag) {
case SwiftInt:
memcpy(value, self->storage, sizeof(NSInteger));
return;
case SwiftUInt:
memcpy(value, self->storage, sizeof(NSUInteger));
return;
case SwiftFloat:
memcpy(value, self->storage, sizeof(float));
return;
case SwiftDouble:
memcpy(value, self->storage, sizeof(double));
return;
case SwiftCGFloat:
memcpy(value, self->storage, sizeof(CGFloat));
return;
case SwiftBool:
memcpy(value, self->storage, sizeof(bool));
return;
}
swift::swift_reportError(
/* flags = */ 0,
"_SwiftTypePreservingNSNumber.tag is corrupted.\n");
}
#define DEFINE_ACCESSOR(C_TYPE, METHOD_NAME) \
- (C_TYPE)METHOD_NAME { \
switch(tag) { \
case SwiftInt: { \
NSInteger result; \
memcpy(&result, self->storage, sizeof(result)); \
return result; \
} \
case SwiftUInt: { \
NSUInteger result; \
memcpy(&result, self->storage, sizeof(result)); \
return result; \
} \
case SwiftFloat: { \
float result; \
memcpy(&result, self->storage, sizeof(result)); \
return result; \
} \
case SwiftDouble: { \
double result; \
memcpy(&result, self->storage, sizeof(result)); \
return result; \
} \
case SwiftCGFloat: { \
CGFloat result; \
memcpy(&result, self->storage, sizeof(result)); \
return result; \
} \
case SwiftBool: { \
bool result; \
memcpy(&result, self->storage, sizeof(result)); \
return result; \
} \
} \
swift::swift_reportError( \
/* flags = */ 0, \
"_SwiftTypePreservingNSNumber.tag is corrupted.\n"); \
}
DEFINE_ACCESSOR(char, charValue)
DEFINE_ACCESSOR(int, intValue)
DEFINE_ACCESSOR(unsigned int, unsignedIntValue)
DEFINE_ACCESSOR(long long, longLongValue)
DEFINE_ACCESSOR(unsigned long long, unsignedLongLongValue)
DEFINE_ACCESSOR(float, floatValue)
DEFINE_ACCESSOR(double, doubleValue)
#undef DEFINE_ACCESSOR
- (Class)classForCoder {
return [NSNumber class];
}
#define DEFINE_INIT(C_TYPE, FUNCTION_NAME) \
SWIFT_CC(swift) extern "C" NS_RETURNS_RETAINED NSNumber * \
_swift_Foundation_TypePreservingNSNumberWith ## FUNCTION_NAME(C_TYPE value) { \
_SwiftTypePreservingNSNumber *result = \
[[_SwiftTypePreservingNSNumber alloc] init]; \
result->tag = Swift ## FUNCTION_NAME; \
memcpy(result->storage, &value, sizeof(value)); \
return result; \
}
DEFINE_INIT(NSInteger, Int)
DEFINE_INIT(NSUInteger, UInt)
DEFINE_INIT(float, Float)
DEFINE_INIT(double, Double)
DEFINE_INIT(CGFloat, CGFloat)
DEFINE_INIT(bool, Bool)
#undef DEFINE_INIT
SWIFT_CC(swift) extern "C" uint32_t
_swift_Foundation_TypePreservingNSNumberGetKind(
NSNumber *NS_RELEASES_ARGUMENT _Nonnull self_) {
uint32_t result = 0;
if ([self_ isKindOfClass: [_SwiftTypePreservingNSNumber class]]) {
result = ((_SwiftTypePreservingNSNumber *) self_)->tag;
}
[self_ release];
return result;
}
#define DEFINE_GETTER(C_TYPE, FUNCTION_NAME) \
SWIFT_CC(swift) extern "C" C_TYPE \
_swift_Foundation_TypePreservingNSNumberGetAs ## FUNCTION_NAME( \
_SwiftTypePreservingNSNumber *NS_RELEASES_ARGUMENT _Nonnull self_) { \
if (self_->tag != Swift ## FUNCTION_NAME) { \
swift::swift_reportError( \
/* flags = */ 0, "Incorrect tag.\n"); \
} \
C_TYPE result; \
memcpy(&result, self_->storage, sizeof(result)); \
[self_ release]; \
return result; \
}
DEFINE_GETTER(NSInteger, Int)
DEFINE_GETTER(NSUInteger, UInt)
DEFINE_GETTER(float, Float)
DEFINE_GETTER(double, Double)
DEFINE_GETTER(CGFloat, CGFloat)
DEFINE_GETTER(bool, Bool)
#undef DEFINE_GETTER
@end