An amazing project that generates micro reports from tournament results
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

163 lines
4.7 KiB

////////////////////////////////////////////////////////////////////////////
//
// Copyright 2015 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////
#import "RLMOptionalBase.h"
#import "RLMAccessor.hpp"
#import "RLMObject_Private.hpp"
#import "RLMProperty.h"
#import "RLMUtil.hpp"
#import "object.hpp"
namespace {
struct OptionalBase {
virtual id get() = 0;
virtual void set(id) = 0;
virtual ~OptionalBase() = default;
};
class UnmanagedOptional : public OptionalBase {
public:
id get() override {
return _value;
}
void set(__unsafe_unretained const id newValue) override {
@autoreleasepool {
RLMObjectBase *object = _parent;
[object willChangeValueForKey:_property];
_value = newValue;
[object didChangeValueForKey:_property];
}
}
void attach(__unsafe_unretained RLMObjectBase *const obj, NSString *property) {
if (!_property) {
_property = property;
_parent = obj;
}
}
private:
id _value;
NSString *_property;
__weak RLMObjectBase *_parent;
};
class ManagedOptional : public OptionalBase {
public:
ManagedOptional(RLMObjectBase *obj, RLMProperty *prop)
: _realm(obj->_realm)
, _object(obj->_realm->_realm, *obj->_info->objectSchema, obj->_row)
, _propertyName(prop.name.UTF8String)
, _ctx(obj->_realm, *obj->_info)
{
}
id get() override {
return _object.get_property_value<id>(_ctx, _propertyName);
}
void set(__unsafe_unretained id const value) override {
_object.set_property_value(_ctx, _propertyName, value ?: NSNull.null, false);
}
private:
// We have to hold onto a strong reference to the Realm as
// RLMAccessorContext holds a non-retaining one.
__unused RLMRealm *_realm;
realm::Object _object;
std::string _propertyName;
RLMAccessorContext _ctx;
};
} // anonymous namespace
@interface RLMOptionalBase () {
std::unique_ptr<OptionalBase> _impl;
}
@end
@implementation RLMOptionalBase
- (instancetype)init {
return self;
}
- (BOOL)isKindOfClass:(Class)aClass {
return [RLMGetOptional(self) isKindOfClass:aClass] || RLMIsKindOfClass(object_getClass(self), aClass);
}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel {
return [RLMGetOptional(self) methodSignatureForSelector:sel];
}
- (void)forwardInvocation:(NSInvocation *)invocation {
[invocation invokeWithTarget:RLMGetOptional(self)];
}
- (id)forwardingTargetForSelector:(__unused SEL)sel {
return RLMGetOptional(self);
}
- (BOOL)respondsToSelector:(SEL)aSelector {
return [RLMGetOptional(self) respondsToSelector:aSelector];
}
- (void)doesNotRecognizeSelector:(SEL)aSelector {
[RLMGetOptional(self) doesNotRecognizeSelector:aSelector];
}
id RLMGetOptional(__unsafe_unretained RLMOptionalBase *const self) {
try {
return self->_impl ? RLMCoerceToNil(self->_impl->get()) : nil;
}
catch (std::exception const& err) {
@throw RLMException(err);
}
}
void RLMSetOptional(__unsafe_unretained RLMOptionalBase *const self, __unsafe_unretained const id value) {
try {
if (!self->_impl && value) {
self->_impl.reset(new UnmanagedOptional);
}
if (self->_impl) {
self->_impl->set(value);
}
}
catch (std::exception const& err) {
@throw RLMException(err);
}
}
void RLMInitializeManagedOptional(__unsafe_unretained RLMOptionalBase *const self,
__unsafe_unretained RLMObjectBase *const parent,
__unsafe_unretained RLMProperty *const prop) {
REALM_ASSERT(parent->_realm);
self->_impl.reset(new ManagedOptional(parent, prop));
}
void RLMInitializeUnmanagedOptional(__unsafe_unretained RLMOptionalBase *const self,
__unsafe_unretained RLMObjectBase *const parent,
__unsafe_unretained RLMProperty *const prop) {
if (!self->_impl) {
self->_impl.reset(new UnmanagedOptional);
}
static_cast<UnmanagedOptional&>(*self->_impl).attach(parent, prop.name);
}
@end