123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303 |
- ////////////////////////////////////////////////////////////////////////////
- //
- // 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"
- #import "sync/sync_config.hpp"
- 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 (_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());
- }
- }
- else {
- _config.encryption_key.clear();
- if (_config.sync_config)
- _config.sync_config->realm_encryption_key = realm::util::none;
- }
- }
- - (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;
- }
- @end
|