filesbox/app/filesbox_ios/FilesBox/Pods/Realm/Realm/RLMRealmConfiguration.mm
2023-09-21 10:53:23 +08:00

319 lines
9.5 KiB
Plaintext

////////////////////////////////////////////////////////////////////////////
//
// 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 "RLMRealmConfiguration_Private.h"
#import "RLMObjectSchema_Private.hpp"
#import "RLMRealm_Private.h"
#import "RLMSchema_Private.hpp"
#import "RLMUtil.hpp"
#import "schema.hpp"
#import "shared_realm.hpp"
#if REALM_ENABLE_SYNC
#import "sync/sync_config.hpp"
#else
@class RLMSyncConfiguration;
#endif
static NSString *const c_RLMRealmConfigurationProperties[] = {
@"fileURL",
@"inMemoryIdentifier",
@"encryptionKey",
@"readOnly",
@"schemaVersion",
@"migrationBlock",
@"deleteRealmIfMigrationNeeded",
@"shouldCompactOnLaunch",
@"dynamic",
@"customSchema",
};
static NSString *const c_defaultRealmFileName = @"default.realm";
RLMRealmConfiguration *s_defaultConfiguration;
NSString *RLMRealmPathForFileAndBundleIdentifier(NSString *fileName, NSString *bundleIdentifier) {
return [RLMDefaultDirectoryForBundleIdentifier(bundleIdentifier)
stringByAppendingPathComponent:fileName];
}
NSString *RLMRealmPathForFile(NSString *fileName) {
static NSString *directory = RLMDefaultDirectoryForBundleIdentifier(nil);
return [directory stringByAppendingPathComponent:fileName];
}
@implementation RLMRealmConfiguration {
realm::Realm::Config _config;
}
- (realm::Realm::Config&)config {
return _config;
}
+ (instancetype)defaultConfiguration {
return [[self rawDefaultConfiguration] copy];
}
+ (void)setDefaultConfiguration:(RLMRealmConfiguration *)configuration {
if (!configuration) {
@throw RLMException(@"Cannot set the default configuration to nil.");
}
@synchronized(c_defaultRealmFileName) {
s_defaultConfiguration = [configuration copy];
}
}
+ (RLMRealmConfiguration *)rawDefaultConfiguration {
RLMRealmConfiguration *configuration;
@synchronized(c_defaultRealmFileName) {
if (!s_defaultConfiguration) {
s_defaultConfiguration = [[RLMRealmConfiguration alloc] init];
}
configuration = s_defaultConfiguration;
}
return configuration;
}
+ (void)resetRealmConfigurationState {
@synchronized(c_defaultRealmFileName) {
s_defaultConfiguration = nil;
}
}
- (instancetype)init {
self = [super init];
if (self) {
static NSURL *defaultRealmURL = [NSURL fileURLWithPath:RLMRealmPathForFile(c_defaultRealmFileName)];
self.fileURL = defaultRealmURL;
self.schemaVersion = 0;
self.cache = YES;
// We have our own caching of RLMRealm instances, so the ObjectStore
// cache is at best pointless, and may result in broken behavior when
// a realm::Realm instance outlives the RLMRealm (due to collection
// notifiers being in the middle of running when the RLMRealm is
// dealloced) and then reused for a new RLMRealm
_config.cache = false;
}
return self;
}
- (instancetype)copyWithZone:(NSZone *)zone {
RLMRealmConfiguration *configuration = [[[self class] allocWithZone:zone] init];
configuration->_config = _config;
configuration->_cache = _cache;
configuration->_dynamic = _dynamic;
configuration->_migrationBlock = _migrationBlock;
configuration->_shouldCompactOnLaunch = _shouldCompactOnLaunch;
configuration->_customSchema = _customSchema;
return configuration;
}
- (NSString *)description {
NSMutableString *string = [NSMutableString stringWithFormat:@"%@ {\n", self.class];
for (NSString *key : c_RLMRealmConfigurationProperties) {
NSString *description = [[self valueForKey:key] description];
description = [description stringByReplacingOccurrencesOfString:@"\n" withString:@"\n\t"];
[string appendFormat:@"\t%@ = %@;\n", key, description];
}
return [string stringByAppendingString:@"}"];
}
static void RLMNSStringToStdString(std::string &out, NSString *in) {
out.resize([in maximumLengthOfBytesUsingEncoding:NSUTF8StringEncoding]);
if (out.empty()) {
return;
}
NSUInteger size = out.size();
[in getBytes:&out[0]
maxLength:size
usedLength:&size
encoding:NSUTF8StringEncoding
options:0 range:{0, in.length} remainingRange:nullptr];
out.resize(size);
}
- (NSURL *)fileURL {
if (_config.in_memory || _config.sync_config) {
return nil;
}
return [NSURL fileURLWithPath:@(_config.path.c_str())];
}
- (void)setFileURL:(NSURL *)fileURL {
NSString *path = fileURL.path;
if (path.length == 0) {
@throw RLMException(@"Realm path must not be empty");
}
_config.sync_config = nullptr;
RLMNSStringToStdString(_config.path, path);
_config.in_memory = false;
}
- (NSString *)inMemoryIdentifier {
if (!_config.in_memory) {
return nil;
}
return [@(_config.path.c_str()) lastPathComponent];
}
- (void)setInMemoryIdentifier:(NSString *)inMemoryIdentifier {
if (inMemoryIdentifier.length == 0) {
@throw RLMException(@"In-memory identifier must not be empty");
}
_config.sync_config = nullptr;
RLMNSStringToStdString(_config.path, [NSTemporaryDirectory() stringByAppendingPathComponent:inMemoryIdentifier]);
_config.in_memory = true;
}
- (NSData *)encryptionKey {
return _config.encryption_key.empty() ? nil : [NSData dataWithBytes:_config.encryption_key.data() length:_config.encryption_key.size()];
}
- (void)setEncryptionKey:(NSData * __nullable)encryptionKey {
if (NSData *key = RLMRealmValidatedEncryptionKey(encryptionKey)) {
auto bytes = static_cast<const char *>(key.bytes);
_config.encryption_key.assign(bytes, bytes + key.length);
#if REALM_ENABLE_SYNC
if (_config.sync_config) {
auto& sync_encryption_key = self.config.sync_config->realm_encryption_key;
sync_encryption_key = std::array<char, 64>();
std::copy_n(_config.encryption_key.begin(), 64, sync_encryption_key->begin());
}
#endif
}
else {
_config.encryption_key.clear();
#if REALM_ENABLE_SYNC
if (_config.sync_config)
_config.sync_config->realm_encryption_key = realm::util::none;
#endif
}
}
- (BOOL)readOnly {
return _config.immutable();
}
- (void)setReadOnly:(BOOL)readOnly {
if (readOnly) {
if (self.deleteRealmIfMigrationNeeded) {
@throw RLMException(@"Cannot set `readOnly` when `deleteRealmIfMigrationNeeded` is set.");
} else if (self.shouldCompactOnLaunch) {
@throw RLMException(@"Cannot set `readOnly` when `shouldCompactOnLaunch` is set.");
}
_config.schema_mode = realm::SchemaMode::Immutable;
}
else if (self.readOnly) {
_config.schema_mode = realm::SchemaMode::Automatic;
}
}
- (uint64_t)schemaVersion {
return _config.schema_version;
}
- (void)setSchemaVersion:(uint64_t)schemaVersion {
if (schemaVersion == RLMNotVersioned) {
@throw RLMException(@"Cannot set schema version to %llu (RLMNotVersioned)", RLMNotVersioned);
}
_config.schema_version = schemaVersion;
}
- (BOOL)deleteRealmIfMigrationNeeded {
return _config.schema_mode == realm::SchemaMode::ResetFile;
}
- (void)setDeleteRealmIfMigrationNeeded:(BOOL)deleteRealmIfMigrationNeeded {
if (deleteRealmIfMigrationNeeded) {
if (self.readOnly) {
@throw RLMException(@"Cannot set `deleteRealmIfMigrationNeeded` when `readOnly` is set.");
}
_config.schema_mode = realm::SchemaMode::ResetFile;
}
else if (self.deleteRealmIfMigrationNeeded) {
_config.schema_mode = realm::SchemaMode::Automatic;
}
}
- (NSArray *)objectClasses {
return [_customSchema.objectSchema valueForKeyPath:@"objectClass"];
}
- (void)setObjectClasses:(NSArray *)objectClasses {
self.customSchema = [RLMSchema schemaWithObjectClasses:objectClasses];
}
- (void)setDynamic:(bool)dynamic {
_dynamic = dynamic;
self.cache = !dynamic;
}
- (bool)disableFormatUpgrade {
return _config.disable_format_upgrade;
}
- (void)setDisableFormatUpgrade:(bool)disableFormatUpgrade {
_config.disable_format_upgrade = disableFormatUpgrade;
}
- (realm::SchemaMode)schemaMode {
return _config.schema_mode;
}
- (void)setSchemaMode:(realm::SchemaMode)mode {
_config.schema_mode = mode;
}
- (NSString *)pathOnDisk {
return @(_config.path.c_str());
}
- (void)setShouldCompactOnLaunch:(RLMShouldCompactOnLaunchBlock)shouldCompactOnLaunch {
if (shouldCompactOnLaunch) {
if (self.readOnly) {
@throw RLMException(@"Cannot set `shouldCompactOnLaunch` when `readOnly` is set.");
}
_config.should_compact_on_launch_function = [=](size_t totalBytes, size_t usedBytes) {
return shouldCompactOnLaunch(totalBytes, usedBytes);
};
}
else {
_config.should_compact_on_launch_function = nullptr;
}
_shouldCompactOnLaunch = shouldCompactOnLaunch;
}
- (void)setCustomSchemaWithoutCopying:(RLMSchema *)schema {
_customSchema = schema;
}
#if !REALM_ENABLE_SYNC
- (RLMSyncConfiguration *)syncConfiguration {
return nil;
}
#endif
@end